public ExtraMesh Copy() { ExtraMesh extraMesh = new ExtraMesh(open, index, baseMaterial, overlayMaterial, physicMaterial, startWidth, endWidth, flipped, yOffset); extraMesh.left = left; return(extraMesh); }
public RoundaboutExtraMesh(ExtraMesh extraMesh, int listIndex, float startOffset, float endOffset, float yOffset) { this.extraMesh = extraMesh; this.listIndex = listIndex; this.startOffset = startOffset; this.endOffset = endOffset; this.yOffset = yOffset; }
private static void GetSceneMeshes(Bounds bounds, LayerMask layerMask, List <ExtraMesh> meshes) { var filters = GameObject.FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[]; var filteredFilters = new List <MeshFilter>(filters.Length / 3); for (int i = 0; i < filters.Length; i++) { MeshFilter filter = filters[i]; Renderer rend = filter.GetComponent <Renderer>(); if (rend != null && filter.sharedMesh != null && rend.enabled && (((1 << filter.gameObject.layer) & layerMask) != 0)) { filteredFilters.Add(filter); } } var cachedVertices = new Dictionary <Mesh, Vector3[]>(); var cachedTris = new Dictionary <Mesh, int[]>(); for (int i = 0; i < filteredFilters.Count; i++) { MeshFilter filter = filteredFilters[i]; // Note, guaranteed to have a renderer Renderer rend = filter.GetComponent <Renderer>(); //Workaround for statically batched meshes if (!rend.isPartOfStaticBatch) { //Only include it if it intersects with the graph if (rend.bounds.Intersects(bounds)) { Mesh mesh = filter.sharedMesh; var smesh = new ExtraMesh(); smesh.matrix = rend.localToWorldMatrix; smesh.original = filter; if (cachedVertices.ContainsKey(mesh)) { smesh.vertices = cachedVertices[mesh]; smesh.triangles = cachedTris[mesh]; } else { smesh.vertices = mesh.vertices; smesh.triangles = mesh.triangles; cachedVertices[mesh] = smesh.vertices; cachedTris[mesh] = smesh.triangles; } smesh.bounds = rend.bounds; meshes.Add(smesh); } } } }
private void GenerateMesh(Vector3[] points, Vector3[] nextSegmentPoints, Vector3 previousPoint, Vector3[] previousVertices, float heightOffset, Transform segment, Transform previousSegment, Transform mesh, string name, Material baseMaterial, Material overlayMaterial, PhysicMaterial physicMaterial, float startXOffset = 0, float endXOffset = 0, float yOffset = 0, float leftYOffset = 0, ExtraMesh extraMesh = null) { if (name != "Road" && extraMesh.startWidth == 0 && extraMesh.endWidth == 0 && extraMesh.yOffset == 0) { mesh.GetComponent <MeshFilter>().sharedMesh = null; mesh.GetComponent <MeshCollider>().sharedMesh = null; return; } List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); int verticeIndex = 0; float totalDistance = 0; float currentDistance = 0; for (int i = 1; i < points.Length; i++) { totalDistance += Vector3.Distance(points[i - 1], points[i]); } for (int i = 0; i < points.Length; i++) { Vector3 left = Misc.CalculateLeft(points, nextSegmentPoints, previousPoint, i); float correctedHeightOffset = heightOffset; if (i > 0) { currentDistance += Vector3.Distance(points[i - 1], points[i]); } float roadWidth = Mathf.Lerp(startRoadWidth, endRoadWidth, currentDistance / totalDistance); if (i == 0 && previousSegment != null) { roadWidth = previousSegment.GetComponent <RoadSegment>().endRoadWidth; } if (i == 0 && previousPoint != Misc.MaxVector3) { correctedHeightOffset = previousPoint.y - points[i].y; } else if (i == points.Length - 1 && nextSegmentPoints != null && nextSegmentPoints.Length == 1) { correctedHeightOffset = nextSegmentPoints[0].y - points[i].y; } if (name == "Road") { vertices.Add((points[i] + left * roadWidth) - segment.position); vertices[verticeIndex] = new Vector3(vertices[verticeIndex].x, correctedHeightOffset + points[i].y - segment.position.y, vertices[verticeIndex].z); vertices.Add((points[i] - left * roadWidth) - segment.position); vertices[verticeIndex + 1] = new Vector3(vertices[verticeIndex + 1].x, correctedHeightOffset + points[i].y - segment.position.y, vertices[verticeIndex + 1].z); } else { float modifiedXOffset = Mathf.Lerp(startXOffset, endXOffset, currentDistance / totalDistance) + roadWidth; float width = Mathf.Lerp(extraMesh.startWidth, extraMesh.endWidth, currentDistance / totalDistance); if (extraMesh.left == false) { vertices.Add((points[i] + left * -modifiedXOffset) - segment.position); vertices[verticeIndex] = new Vector3(vertices[verticeIndex].x, correctedHeightOffset + leftYOffset + points[i].y - segment.position.y - heightOffset, vertices[verticeIndex].z); vertices.Add((points[i] + left * (-modifiedXOffset - width)) - segment.position); vertices[verticeIndex + 1] = new Vector3(vertices[verticeIndex + 1].x, correctedHeightOffset + yOffset + points[i].y - segment.position.y - heightOffset, vertices[verticeIndex + 1].z); } else { vertices.Add((points[i] + left * (modifiedXOffset + width)) - segment.position); vertices[verticeIndex] = new Vector3(vertices[verticeIndex].x, correctedHeightOffset + yOffset + points[i].y - segment.position.y - heightOffset, vertices[verticeIndex].z); vertices.Add((points[i] + left * modifiedXOffset) - segment.position); vertices[verticeIndex + 1] = new Vector3(vertices[verticeIndex + 1].x, correctedHeightOffset + leftYOffset + points[i].y - segment.position.y - heightOffset, vertices[verticeIndex + 1].z); } } if (i < points.Length - 1) { triangles.Add(verticeIndex); triangles.Add(verticeIndex + 2); triangles.Add(verticeIndex + 1); triangles.Add(verticeIndex + 1); triangles.Add(verticeIndex + 2); triangles.Add(verticeIndex + 3); } verticeIndex += 2; } TerrainDeformation(vertices, points, heightOffset, segment); // First if (previousVertices != null) { if (vertices.Count > 4 && previousVertices.Length > 3 && name == "Road") { vertices = fixVertices(0, vertices, (vertices[2] - vertices[4]).normalized); vertices = fixVertices(1, vertices, (vertices[3] - vertices[5]).normalized); } } Mesh generatedMesh = new Mesh(); generatedMesh.vertices = vertices.ToArray(); generatedMesh.triangles = triangles.ToArray(); if (name == "Road") { generatedMesh = GenerateUvs(generatedMesh, flipped); } else { if ((extraMesh.left == true && extraMesh.flipped == false) || (extraMesh.left == false && extraMesh.flipped == true)) { generatedMesh = GenerateUvs(generatedMesh, false); } else { generatedMesh = GenerateUvs(generatedMesh, true); } } generatedMesh.RecalculateNormals(); mesh.GetComponent <MeshFilter>().sharedMesh = generatedMesh; mesh.GetComponent <MeshCollider>().sharedMaterial = physicMaterial; if (segment.parent.parent.GetComponent <RoadCreator>().generateCollider == true) { mesh.GetComponent <MeshCollider>().sharedMesh = generatedMesh; } else { mesh.GetComponent <MeshCollider>().sharedMesh = null; } if (overlayMaterial == null) { mesh.GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial }; } else { mesh.GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial, overlayMaterial }; } }
void GetSceneMeshes(Bounds bounds, List <string> tagMask, LayerMask layerMask, List <ExtraMesh> meshes) { if ((tagMask != null && tagMask.Count > 0) || layerMask != 0) { var filters = GameObject.FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[]; var filteredFilters = new List <MeshFilter>(filters.Length / 3); for (int i = 0; i < filters.Length; i++) { MeshFilter filter = filters[i]; Renderer rend = filter.GetComponent <Renderer>(); if (rend != null && filter.sharedMesh != null && rend.enabled && (((1 << filter.gameObject.layer) & layerMask) != 0 || tagMask.Contains(filter.tag))) { if (filter.GetComponent <RecastMeshObj>() == null) { filteredFilters.Add(filter); } } } var cachedVertices = new Dictionary <Mesh, Vector3[]>(); var cachedTris = new Dictionary <Mesh, int[]>(); bool containedStatic = false; for (int i = 0; i < filteredFilters.Count; i++) { MeshFilter filter = filteredFilters[i]; // Note, guaranteed to have a renderer Renderer rend = filter.GetComponent <Renderer>(); //Workaround for statically batched meshes if (rend.isPartOfStaticBatch) { containedStatic = true; } else { //Only include it if it intersects with the graph if (rend.bounds.Intersects(bounds)) { Mesh mesh = filter.sharedMesh; var smesh = new ExtraMesh(); smesh.matrix = rend.localToWorldMatrix; smesh.original = filter; #if BNICKSON_UPDATED if (IsGameObjectInLayerMask(filter.gameObject, excludeMask)) { // UnwalkableArea = 0 = NoNavMeshOnObject + 1 const int NoNavMeshOnObject = -1; smesh.area = NoNavMeshOnObject; } #endif if (cachedVertices.ContainsKey(mesh)) { smesh.vertices = cachedVertices[mesh]; smesh.triangles = cachedTris[mesh]; } else { smesh.vertices = mesh.vertices; smesh.triangles = mesh.triangles; cachedVertices[mesh] = smesh.vertices; cachedTris[mesh] = smesh.triangles; } smesh.bounds = rend.bounds; meshes.Add(smesh); } } if (containedStatic) { EB.Debug.LogWarning("Some meshes were statically batched. These meshes can not be used for navmesh calculation" + " due to technical constraints.\nDuring runtime scripts cannot access the data of meshes which have been statically batched.\n" + "One way to solve this problem is to use cached startup (Save & Load tab in the inspector) to only calculate the graph when the game is not playing."); } } #if ASTARDEBUG int y = 0; foreach (ExtraMesh smesh in meshes) { y++; Vector3[] vecs = smesh.vertices; int[] tris = smesh.triangles; for (int i = 0; i < tris.Length; i += 3) { Vector3 p1 = smesh.matrix.MultiplyPoint3x4(vecs[tris[i + 0]]); Vector3 p2 = smesh.matrix.MultiplyPoint3x4(vecs[tris[i + 1]]); Vector3 p3 = smesh.matrix.MultiplyPoint3x4(vecs[tris[i + 2]]); Debug.DrawLine(p1, p2, Color.red, 1); Debug.DrawLine(p2, p3, Color.red, 1); Debug.DrawLine(p3, p1, Color.red, 1); } } #endif } }
/** Find all relevant RecastMeshObj components and create ExtraMeshes for them */ public void GetRecastMeshObjs(Bounds bounds, List <ExtraMesh> buffer) { List <RecastMeshObj> buffer2 = Util.ListPool <RecastMeshObj> .Claim(); // Get all recast mesh objects inside the bounds RecastMeshObj.GetAllInBounds(buffer2, bounds); var cachedVertices = new Dictionary <Mesh, Vector3[]>(); var cachedTris = new Dictionary <Mesh, int[]>(); // Create an ExtraMesh object // for each RecastMeshObj for (int i = 0; i < buffer2.Count; i++) { MeshFilter filter = buffer2[i].GetMeshFilter(); Renderer rend = filter != null?filter.GetComponent <Renderer>() : null; if (filter != null && rend != null) { Mesh mesh = filter.sharedMesh; #if BNICKSON_UPDATED // extra information about which game object is causing the problem if (null == mesh) { EB.Debug.LogError("RecastGenerator.GetRecastMeshObjs(): {0} has a RecastMeshObj, but does not have a MeshFilter", filter.name); } #endif var smesh = new ExtraMesh(); smesh.matrix = rend.localToWorldMatrix; smesh.original = filter; smesh.area = buffer2[i].area; // Don't read the vertices and triangles from the // mesh if we have seen the same mesh previously if (cachedVertices.ContainsKey(mesh)) { smesh.vertices = cachedVertices[mesh]; smesh.triangles = cachedTris[mesh]; } else { smesh.vertices = mesh.vertices; smesh.triangles = mesh.triangles; cachedVertices[mesh] = smesh.vertices; cachedTris[mesh] = smesh.triangles; } smesh.bounds = rend.bounds; buffer.Add(smesh); } else { Collider coll = buffer2[i].GetCollider(); if (coll == null) { EB.Debug.LogError("RecastMeshObject ({0}) didn't have a collider or MeshFilter+Renderer attached", buffer2[i].gameObject.name); continue; } ExtraMesh smesh = RasterizeCollider(coll); smesh.area = buffer2[i].area; //Make sure a valid ExtraMesh was returned if (smesh.vertices != null) { buffer.Add(smesh); } } } //Clear cache to avoid memory leak capsuleCache.Clear(); Util.ListPool <RecastMeshObj> .Release(buffer2); }
/** Rasterizes a collider to a mesh assuming it's vertices should be multiplied with the matrix. * Note that the bounds of the returned ExtraMesh is based on collider.bounds. So you might want to * call myExtraMesh.RecalculateBounds on the returned mesh to recalculate it if the collider.bounds would * not give the correct value. * */ public ExtraMesh RasterizeCollider (Collider col, Matrix4x4 localToWorldMatrix) { if (col is BoxCollider) { BoxCollider collider = col as BoxCollider; Matrix4x4 matrix = Matrix4x4.TRS (collider.center, Quaternion.identity, collider.size*0.5f); matrix = localToWorldMatrix * matrix; Bounds b = collider.bounds; ExtraMesh m = new ExtraMesh(BoxColliderVerts,BoxColliderTris, b, matrix); #if ASTARDEBUG Vector3[] verts = BoxColliderVerts; int[] tris = BoxColliderTris; for (int i=0;i<tris.Length;i+=3) { Debug.DrawLine (matrix.MultiplyPoint3x4(verts[tris[i]]),matrix.MultiplyPoint3x4(verts[tris[i+1]]), Color.yellow); Debug.DrawLine (matrix.MultiplyPoint3x4(verts[tris[i+2]]),matrix.MultiplyPoint3x4(verts[tris[i+1]]), Color.yellow); Debug.DrawLine (matrix.MultiplyPoint3x4(verts[tris[i]]),matrix.MultiplyPoint3x4(verts[tris[i+2]]), Color.yellow); //Normal debug /*Vector3 va = matrix.MultiplyPoint3x4(verts[tris[i]]); Vector3 vb = matrix.MultiplyPoint3x4(verts[tris[i+1]]); Vector3 vc = matrix.MultiplyPoint3x4(verts[tris[i+2]]); Debug.DrawRay ((va+vb+vc)/3, Vector3.Cross(vb-va,vc-va).normalized,Color.blue);*/ } #endif return m; } else if (col is SphereCollider || col is CapsuleCollider) { SphereCollider scollider = col as SphereCollider; CapsuleCollider ccollider = col as CapsuleCollider; float radius = (scollider != null ? scollider.radius : ccollider.radius); float height = scollider != null ? 0 : (ccollider.height*0.5f/radius) - 1; Matrix4x4 matrix = Matrix4x4.TRS (scollider != null ? scollider.center : ccollider.center, Quaternion.identity, Vector3.one*radius); matrix = localToWorldMatrix * matrix; //Calculate the number of rows to use //grows as sqrt(x) to the radius of the sphere/capsule which I have found works quite good int rows = Mathf.Max (4,Mathf.RoundToInt(colliderRasterizeDetail*Mathf.Sqrt(matrix.MultiplyVector(Vector3.one).magnitude))); if (rows > 100) { Debug.LogWarning ("Very large detail for some collider meshes. Consider decreasing Collider Rasterize Detail (RecastGraph)"); } int cols = rows; Vector3[] verts; int[] trisArr; //Check if we have already calculated a similar capsule CapsuleCache cached = null; for (int i=0;i<capsuleCache.Count;i++) { CapsuleCache c = capsuleCache[i]; if (c.rows == rows && Mathf.Approximately (c.height, height)) { cached = c; } } if (cached == null) { //Generate a sphere/capsule mesh verts = new Vector3[(rows)*cols + 2]; List<int> tris = new List<int>(); verts[verts.Length-1] = Vector3.up; for (int r=0;r<rows;r++) { for (int c=0;c<cols;c++) { verts[c + r*cols] = new Vector3 (Mathf.Cos (c*Mathf.PI*2/cols)*Mathf.Sin ((r*Mathf.PI/(rows-1))), Mathf.Cos ((r*Mathf.PI/(rows-1))) + (r < rows/2 ? height : -height) , Mathf.Sin (c*Mathf.PI*2/cols)*Mathf.Sin ((r*Mathf.PI/(rows-1)))); } } verts[verts.Length-2] = Vector3.down; for (int i=0, j = cols-1;i<cols; j = i++) { tris.Add (verts.Length-1); tris.Add (0*cols + j); tris.Add (0*cols + i); } for (int r=1;r<rows;r++) { for (int i=0, j = cols-1;i<cols; j = i++) { tris.Add (r*cols + i); tris.Add (r*cols + j); tris.Add ((r-1)*cols + i); tris.Add ((r-1)*cols + j); tris.Add ((r-1)*cols + i); tris.Add (r*cols + j); } } for (int i=0, j = cols-1;i<cols; j = i++) { tris.Add (verts.Length-2); tris.Add ((rows-1)*cols + j); tris.Add ((rows-1)*cols + i); } //Add calculated mesh to the cache cached = new CapsuleCache (); cached.rows = rows; cached.height = height; cached.verts = verts; cached.tris = tris.ToArray(); capsuleCache.Add (cached); } //Read from cache verts = cached.verts; trisArr = cached.tris; Bounds b = col.bounds; ExtraMesh m = new ExtraMesh(verts,trisArr, b, matrix); #if ASTARDEBUG for (int i=0;i<trisArr.Length;i+=3) { Debug.DrawLine (matrix.MultiplyPoint3x4(verts[trisArr[i]]),matrix.MultiplyPoint3x4(verts[trisArr[i+1]]), Color.yellow); Debug.DrawLine (matrix.MultiplyPoint3x4(verts[trisArr[i+2]]),matrix.MultiplyPoint3x4(verts[trisArr[i+1]]), Color.yellow); Debug.DrawLine (matrix.MultiplyPoint3x4(verts[trisArr[i]]),matrix.MultiplyPoint3x4(verts[trisArr[i+2]]), Color.yellow); //Normal debug /*Vector3 va = matrix.MultiplyPoint3x4(verts[trisArr[i]]); Vector3 vb = matrix.MultiplyPoint3x4(verts[trisArr[i+1]]); Vector3 vc = matrix.MultiplyPoint3x4(verts[trisArr[i+2]]); Debug.DrawRay ((va+vb+vc)/3, Vector3.Cross(vb-va,vc-va).normalized,Color.blue);*/ } #endif return m; } else if (col is MeshCollider) { MeshCollider collider = col as MeshCollider; ExtraMesh m = new ExtraMesh(collider.sharedMesh.vertices, collider.sharedMesh.triangles, collider.bounds, localToWorldMatrix); return m; } return new ExtraMesh(); }
public bool CollectMeshes (out MeshFilter[] filters, out ExtraMesh[] extraMeshes) { List<MeshFilter> filteredFilters; if (rasterizeMeshes) { filteredFilters = GetSceneMeshes (); } else { filteredFilters = new List<MeshFilter>(); } List<ExtraMesh> extraMeshesList = new List<ExtraMesh> (); Terrain[] terrains = MonoBehaviour.FindObjectsOfType(typeof(Terrain)) as Terrain[]; if (rasterizeTerrain && terrains.Length > 0) { for (int j=0;j<terrains.Length;j++) { TerrainData terrainData = terrains[j].terrainData; if (terrainData == null) continue; Vector3 offset = terrains[j].GetPosition (); Vector3 center = offset + terrainData.size * 0.5F; Bounds b = new Bounds (center, terrainData.size); //Only include terrains which intersects the graph if (!b.Intersects (this.forcedBounds)) continue; float[,] heights = terrainData.GetHeights (0,0,terrainData.heightmapWidth,terrainData.heightmapHeight); terrainSampleSize = terrainSampleSize < 1 ? 1 : terrainSampleSize;//Clamp to at least 1 int hWidth = terrainData.heightmapWidth / terrainSampleSize; int hHeight = terrainData.heightmapHeight / terrainSampleSize; Vector3[] terrainVertices = new Vector3[hWidth*hHeight]; Vector3 hSampleSize = terrainData.heightmapScale; float heightScale = terrainData.size.y; for (int z = 0, nz = 0;nz < hHeight;z+= terrainSampleSize, nz++) { for (int x = 0, nx = 0; nx < hWidth;x+= terrainSampleSize, nx++) { terrainVertices[nz*hWidth + nx] = new Vector3 (z * hSampleSize.z,heights[x,z]*heightScale, x * hSampleSize.x) + offset; } } int[] tris = new int[(hWidth-1)*(hHeight-1)*2*3]; int c = 0; for (int z = 0;z < hHeight-1;z++) { for (int x = 0; x < hWidth-1;x++) { tris[c] = z*hWidth + x; tris[c+1] = z*hWidth + x+1; tris[c+2] = (z+1)*hWidth + x+1; c += 3; tris[c] = z*hWidth + x; tris[c+1] = (z+1)*hWidth + x+1; tris[c+2] = (z+1)*hWidth + x; c += 3; } } #if ASTARDEBUG for (int i=0;i<tris.Length;i+=3) { Debug.DrawLine (terrainVertices[tris[i]],terrainVertices[tris[i+1]],Color.red); Debug.DrawLine (terrainVertices[tris[i+1]],terrainVertices[tris[i+2]],Color.red); Debug.DrawLine (terrainVertices[tris[i+2]],terrainVertices[tris[i]],Color.red); } #endif extraMeshesList.Add (new ExtraMesh (terrainVertices,tris,b)); if (rasterizeTrees) { //Rasterize all tree colliders on this terrain object CollectTreeMeshes (extraMeshesList, terrains[j]); } } } if (rasterizeColliders) { Collider[] colls = MonoBehaviour.FindObjectsOfType (typeof(Collider)) as Collider[]; foreach (Collider col in colls) { if (((1 << col.gameObject.layer) & mask) == (1 << col.gameObject.layer) && col.enabled) { ExtraMesh emesh = RasterizeCollider (col); //Make sure a valid ExtraMesh was returned if (emesh.vertices != null) extraMeshesList.Add (emesh); } } //Clear cache to avoid memory leak capsuleCache.Clear(); } if (filteredFilters.Count == 0 && extraMeshesList.Count == 0) { Debug.LogWarning ("No MeshFilters where found contained in the layers specified by the 'mask' variable"); filters = null; extraMeshes = null; return false; } filters = filteredFilters.ToArray (); extraMeshes = extraMeshesList.ToArray (); return true; }
public void CollectTreeMeshes (List<ExtraMesh> extraMeshes, Terrain terrain) { TerrainData data = terrain.terrainData; for (int i=0;i<data.treeInstances.Length;i++) { TreeInstance instance = data.treeInstances[i]; TreePrototype prot = data.treePrototypes[instance.prototypeIndex]; if (prot.prefab.collider == null) { Bounds b = new Bounds(terrain.transform.position + Vector3.Scale(instance.position,data.size), new Vector3(instance.widthScale,instance.heightScale,instance.widthScale)); Matrix4x4 matrix = Matrix4x4.TRS (terrain.transform.position + Vector3.Scale(instance.position,data.size), Quaternion.identity, new Vector3(instance.widthScale,instance.heightScale,instance.widthScale)*0.5f); ExtraMesh m = new ExtraMesh(BoxColliderVerts,BoxColliderTris, b, matrix); #if ASTARDEBUG Debug.DrawRay (instance.position, Vector3.up, Color.red,1); #endif extraMeshes.Add (m); } else { //The prefab has a collider, use that instead Vector3 pos = terrain.transform.position + Vector3.Scale(instance.position,data.size); Vector3 scale = new Vector3(instance.widthScale,instance.heightScale,instance.widthScale); //Generate a mesh from the collider ExtraMesh m = RasterizeCollider (prot.prefab.collider,Matrix4x4.TRS (pos,Quaternion.identity,scale)); //Make sure a valid mesh was generated if (m.vertices != null) { #if ASTARDEBUG Debug.DrawRay (pos, Vector3.up, Color.yellow,1); #endif //The bounds are incorrectly based on collider.bounds m.RecalculateBounds (); extraMeshes.Add (m); } } } }
public bool CollectMeshes(out MeshFilter[] filters, out ExtraMesh[] extraMeshes) { List<MeshFilter> filteredFilters = GetSceneMeshes (); List<ExtraMesh> extraMeshesList = new List<ExtraMesh> (); if (includeTerrain && Terrain.activeTerrain != null && Terrain.activeTerrain.terrainData != null) { TerrainData terrainData = Terrain.activeTerrain.terrainData; float[,] heights = terrainData.GetHeights (0,0,terrainData.heightmapWidth,terrainData.heightmapHeight); terrainSampleSize = terrainSampleSize < 1 ? 1 : terrainSampleSize;//Clamp to at least 1 int hWidth = terrainData.heightmapWidth / terrainSampleSize; int hHeight = terrainData.heightmapHeight / terrainSampleSize; Vector3[] terrainVertices = new Vector3[hWidth*hHeight]; Vector3 hSampleSize = terrainData.heightmapScale; Vector3 offset = Terrain.activeTerrain.GetPosition (); float heightScale = terrainData.size.y; for (int z = 0, nz = 0;nz < hHeight;z+= terrainSampleSize, nz++) { for (int x = 0, nx = 0; nx < hWidth;x+= terrainSampleSize, nx++) { terrainVertices[nz*hWidth + nx] = new Vector3 (z * hSampleSize.z,heights[x,z]*heightScale, x * hSampleSize.x) + offset; } } int[] tris = new int[(hWidth-1)*(hHeight-1)*2*3]; int c = 0; for (int z = 0;z < hHeight-1;z++) { for (int x = 0; x < hWidth-1;x++) { tris[c] = z*hWidth + x; tris[c+1] = z*hWidth + x+1; tris[c+2] = (z+1)*hWidth + x+1; c += 3; tris[c] = z*hWidth + x; tris[c+1] = (z+1)*hWidth + x+1; tris[c+2] = (z+1)*hWidth + x; c += 3; } } for (int i=0;i<tris.Length;i+=3) { Debug.DrawLine (terrainVertices[tris[i]],terrainVertices[tris[i+1]],Color.red); Debug.DrawLine (terrainVertices[tris[i+1]],terrainVertices[tris[i+2]],Color.red); Debug.DrawLine (terrainVertices[tris[i+2]],terrainVertices[tris[i]],Color.red); } Vector3 center = offset + terrainData.size * 0.5F; Bounds b = new Bounds (center, terrainData.size); extraMeshesList.Add (new ExtraMesh (terrainVertices,tris,b)); /*terrainMesh.vertices = terrainVertices; terrainMesh.triangles = tris; terrainMesh.RecalculateBounds (); terrainFilter.mesh = terrainMesh; filteredFilters.Add (terrainFilter); }*/ } if (filteredFilters.Count == 0 && extraMeshesList.Count == 0) { Debug.LogWarning ("No MeshFilters where found contained in the layers specified by the 'mask' variable"); filters = null; extraMeshes = null; return false; } filters = filteredFilters.ToArray (); extraMeshes = extraMeshesList.ToArray (); return true; }