Last active
July 12, 2019 00:36
-
-
Save jasonsturges/1f1c8df23aad35aa8236 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@MenuItem ("Terrain/Object to Terrain") | |
static function Object2Terrain () { | |
// See if a valid object is selected | |
var obj = Selection.activeObject as GameObject; | |
if (obj == null) { | |
EditorUtility.DisplayDialog("No object selected", "Please select an object.", "Cancel"); | |
return; | |
} | |
if (obj.GetComponent(MeshFilter) == null) { | |
EditorUtility.DisplayDialog("No mesh selected", "Please select an object with a mesh.", "Cancel"); | |
return; | |
} | |
else if ((obj.GetComponent(MeshFilter) as MeshFilter).sharedMesh == null) { | |
EditorUtility.DisplayDialog("No mesh selected", "Please select an object with a valid mesh.", "Cancel"); | |
return; | |
} | |
if (Terrain.activeTerrain == null) { | |
EditorUtility.DisplayDialog("No terrain found", "Please make sure a terrain exists.", "Cancel"); | |
return; | |
} | |
var terrain = Terrain.activeTerrain.terrainData; | |
// If there's no mesh collider, add one (and then remove it later when done) | |
var addedCollider = false; | |
var addedMesh = false; | |
var objCollider = obj.collider as MeshCollider; | |
if (objCollider == null) { | |
objCollider = obj.AddComponent(MeshCollider); | |
addedCollider = true; | |
} | |
else if (objCollider.sharedMesh == null) { | |
objCollider.sharedMesh = (obj.GetComponent(MeshFilter) as MeshFilter).sharedMesh; | |
addedMesh = true; | |
} | |
Undo.RegisterUndo (terrain, "Object to Terrain"); | |
var resolutionX = terrain.heightmapWidth; | |
var resolutionZ = terrain.heightmapHeight; | |
var heights = terrain.GetHeights(0, 0, resolutionX, resolutionZ); | |
// Use bounds a bit smaller than the actual object; otherwise raycasting tends to miss at the edges | |
var objectBounds = objCollider.bounds; | |
var leftEdge = objectBounds.center.x - objectBounds.extents.x + .01; | |
var bottomEdge = objectBounds.center.z - objectBounds.extents.z + .01; | |
var stepX = (objectBounds.size.x - .019) / resolutionX; | |
var stepZ = (objectBounds.size.z - .019) / resolutionZ; | |
// Set up raycast vars | |
var y = objectBounds.center.y + objectBounds.extents.y + .01; | |
var hit : RaycastHit; | |
var ray = new Ray(Vector3.zero, -Vector3.up); | |
var rayDistance = objectBounds.size.y + .02; | |
var heightFactor = 1.0 / rayDistance; | |
// Do raycasting samples over the object to see what terrain heights should be | |
var z = bottomEdge; | |
for (zCount = 0; zCount < resolutionZ; zCount++) { | |
var x = leftEdge; | |
for (xCount = 0; xCount < resolutionX; xCount++) { | |
ray.origin = Vector3(x, y, z); | |
if (objCollider.Raycast(ray, hit, rayDistance)) { | |
heights[zCount, xCount] = 1.0 - (y - hit.point.y)*heightFactor; | |
} | |
else { | |
heights[zCount, xCount] = 0.0; | |
} | |
x += stepX; | |
} | |
z += stepZ; | |
} | |
terrain.SetHeights(0, 0, heights); | |
if (addedMesh) { | |
objCollider.sharedMesh = null; | |
} | |
if (addedCollider) { | |
DestroyImmediate(objCollider); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment