コード例 #1
0
		public List<ExtraMesh> GetSceneMeshes (Bounds bounds) {
			
			if ( (tagMask != null && tagMask.Count > 0) || mask != 0 ) {
				MeshFilter[] filters = GameObject.FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
				
				List<MeshFilter> filteredFilters = new List<MeshFilter> (filters.Length/3);
				
				for (int i=0;i<filters.Length;i++) {
					MeshFilter filter = filters[i];
					if (filter.renderer != null && filter.sharedMesh != null && filter.renderer.enabled && (((1 << filter.gameObject.layer) & mask) == (1 << filter.gameObject.layer) || tagMask.Contains (filter.tag))) {
						if (filter.GetComponent<RecastMeshObj>() == null) {
							filteredFilters.Add (filter);
						}
					}
				}
			
				List<ExtraMesh> meshes = new List<ExtraMesh>();
				Dictionary<Mesh, Vector3[]> cachedVertices = new Dictionary<Mesh, Vector3[]>();
				Dictionary<Mesh, int[]> cachedTris = new Dictionary<Mesh, int[]>();
				
	#if UNITY_4
				bool containedStatic = false;
	#else
				HashSet<Mesh> staticMeshes = new HashSet<Mesh>();
	#endif
				
				foreach (MeshFilter filter in filteredFilters) {
					
					//Workaround for statically batched meshes
					if (filter.renderer.isPartOfStaticBatch) {
	#if UNITY_4
						containedStatic = true;
	#else
						Mesh mesh = filter.sharedMesh;
						if (!staticMeshes.Contains (mesh)) {
							staticMeshes.Add (mesh);
							ExtraMesh smesh = new ExtraMesh();
							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;
							}
							
							//This is not the real bounds, it will be expanded later as more renderers are found
							smesh.bounds = filter.renderer.bounds;
							smesh.matrix = Matrix4x4.identity;
							meshes.Add (smesh);
						} else {
							ExtraMesh smesh;
							for (int i=0;i<meshes.Count;i++) {
								if (meshes[i].original == mesh) { smesh = meshes[i]; break; }
							}
							smesh.bounds.Encapsulate (filter.renderer.bounds);
						}
	#endif
					} else {
						//Only include it if it intersects with the graph
						if (filter.renderer.bounds.Intersects (bounds)) {
							Mesh mesh = filter.sharedMesh;
							ExtraMesh smesh = new ExtraMesh();
							smesh.matrix = filter.renderer.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 = filter.renderer.bounds;
							
							meshes.Add (smesh);
						}
					}
					
	#if UNITY_4
					if (containedStatic)
						Debug.LogWarning ("Some meshes were statically batched. These meshes can not be used for navmesh calculation" +
							" due to technical constraints.");
	#endif
				}
				
	#if ASTARDEBUG
				int y = 0;
				foreach (SceneMesh smesh in meshes) {
					y++;
					Vector3[] vecs = smesh.mesh.vertices;
					int[] tris = smesh.mesh.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
				
				return meshes;
			} else {
				return new System.Collections.Generic.List<Pathfinding.Voxels.ExtraMesh>();
			}
		}
コード例 #2
0
        public void VoxelizeInput()
        {
            AstarProfiler.StartProfile("Build Navigation Mesh");

            AstarProfiler.StartProfile("Voxelizing - Step 1");

            Vector3 min = forcedBounds.min;

            voxelOffset = min;

            // Scale factor from world space to voxel space
            float ics = 1F / cellSize;
            float ich = 1F / cellHeight;

            AstarProfiler.EndProfile("Voxelizing - Step 1");

            AstarProfiler.StartProfile("Voxelizing - Step 2 - Init");

            float slopeLimit = Mathf.Cos(Mathf.Atan(Mathf.Tan(maxSlope * Mathf.Deg2Rad) * (ich * cellSize)));

            // Temporary arrays used for rasterization
            float[] vTris    = new float[3 * 3];
            float[] vOut     = new float[7 * 3];
            float[] vRow     = new float[7 * 3];
            float[] vCellOut = new float[7 * 3];
            float[] vCell    = new float[7 * 3];

            if (inputExtraMeshes == null)
            {
                throw new System.NullReferenceException("inputExtraMeshes not set");
            }

            //Find the largest lengths of vertex arrays and check for meshes which can be skipped
            int maxVerts = 0;

            for (int m = 0; m < inputExtraMeshes.Count; m++)
            {
                if (!inputExtraMeshes[m].bounds.Intersects(forcedBounds))
                {
                    continue;
                }
                maxVerts = System.Math.Max(inputExtraMeshes[m].vertices.Length, maxVerts);
            }

            //Create buffer, here vertices will be stored multiplied with the local-to-voxel-space matrix
            Vector3[] verts = new Vector3[maxVerts];

            // First subtract min, then scale to voxel space (one unit equals one voxel along the x and z axes)
            // then subtract half a voxel to fix rounding
            Matrix4x4 voxelMatrix = Matrix4x4.TRS(-new Vector3(0.5f, 0, 0.5f), Quaternion.identity, Vector3.one) * Matrix4x4.Scale(new Vector3(ics, ich, ics)) * Matrix4x4.TRS(-min, Quaternion.identity, Vector3.one);

            AstarProfiler.EndProfile("Voxelizing - Step 2 - Init");
            AstarProfiler.StartProfile("Voxelizing - Step 2");

            for (int m = 0; m < inputExtraMeshes.Count; m++)
            {
                ExtraMesh mesh = inputExtraMeshes[m];

                if (!mesh.bounds.Intersects(forcedBounds))
                {
                    continue;
                }

                Matrix4x4 matrix = mesh.matrix;
                matrix = voxelMatrix * matrix;

                // Flip the orientation of all faces if the mesh is scaled in such a way
                // that the face orientations would change
                // This happens for example if a mesh has a negative scale along an odd number of axes
                // e.g it happens for the scale (-1, 1, 1) but not for (-1, -1, 1) or (1,1,1)
                var flipOrientation = VectorMath.ReversesFaceOrientations(matrix);

                Vector3[] vs         = mesh.vertices;
                int[]     tris       = mesh.triangles;
                int       trisLength = tris.Length;

                for (int i = 0; i < vs.Length; i++)
                {
                    verts[i] = matrix.MultiplyPoint3x4(vs[i]);
                }

                //AstarProfiler.StartFastProfile(0);

                int mesharea = mesh.area;

                for (int i = 0; i < trisLength; i += 3)
                {
                    Vector3 p1;
                    Vector3 p2;
                    Vector3 p3;

                    int minX;
                    int minZ;
                    int maxX;
                    int maxZ;

                    p1 = verts[tris[i]];
                    p2 = verts[tris[i + 1]];
                    p3 = verts[tris[i + 2]];

                    if (flipOrientation)
                    {
                        var tmp = p1;
                        p1 = p3;
                        p3 = tmp;
                    }

                    minX = (int)(Utility.Min(p1.x, p2.x, p3.x));
                    minZ = (int)(Utility.Min(p1.z, p2.z, p3.z));

                    maxX = (int)System.Math.Ceiling(Utility.Max(p1.x, p2.x, p3.x));
                    maxZ = (int)System.Math.Ceiling(Utility.Max(p1.z, p2.z, p3.z));

                    minX = Mathf.Clamp(minX, 0, voxelArea.width - 1);
                    maxX = Mathf.Clamp(maxX, 0, voxelArea.width - 1);
                    minZ = Mathf.Clamp(minZ, 0, voxelArea.depth - 1);
                    maxZ = Mathf.Clamp(maxZ, 0, voxelArea.depth - 1);



                    if (minX >= voxelArea.width || minZ >= voxelArea.depth || maxX <= 0 || maxZ <= 0)
                    {
                        continue;
                    }

                    // Debug code
                    //Debug.DrawLine (p1*cellSize+min+Vector3.up*0.2F,p2*cellSize+voxelOffset+Vector3.up*0.1F,Color.red);
                    //Debug.DrawLine (p1*cellSize+min,p2*cellSize+voxelOffset,Color.red, 1);
                    //Debug.DrawLine (p2*cellSize+min,p3*cellSize+voxelOffset,Color.red, 1);
                    //Debug.DrawLine (p3*cellSize+min,p1*cellSize+voxelOffset,Color.red, 1);

                    Vector3 normal;

                    int area;

                    //AstarProfiler.StartProfile ("Rasterize...");

                    normal = Vector3.Cross(p2 - p1, p3 - p1);

                    float dot = Vector3.Dot(normal.normalized, Vector3.up);

                    if (dot < slopeLimit)
                    {
                        area = UnwalkableArea;
                    }
                    else
                    {
                        area = 1 + mesharea;
                    }

                    Utility.CopyVector(vTris, 0, p1);
                    Utility.CopyVector(vTris, 3, p2);
                    Utility.CopyVector(vTris, 6, p3);

                    for (int x = minX; x <= maxX; x++)
                    {
                        int nrow = Utility.ClipPolygon(vTris, 3, vOut, 1F, -x + 0.5F, 0);

                        if (nrow < 3)
                        {
                            continue;
                        }

                        nrow = Utility.ClipPolygon(vOut, nrow, vRow, -1F, x + 0.5F, 0);

                        if (nrow < 3)
                        {
                            continue;
                        }

                        float clampZ1 = vRow[2];
                        float clampZ2 = vRow[2];
                        for (int q = 1; q < nrow; q++)
                        {
                            float val = vRow[q * 3 + 2];
                            clampZ1 = System.Math.Min(clampZ1, val);
                            clampZ2 = System.Math.Max(clampZ2, val);
                        }

                        int clampZ1I = Mathf.Clamp((int)System.Math.Round(clampZ1), 0, voxelArea.depth - 1);
                        int clampZ2I = Mathf.Clamp((int)System.Math.Round(clampZ2), 0, voxelArea.depth - 1);


                        for (int z = clampZ1I; z <= clampZ2I; z++)
                        {
                            //AstarProfiler.StartFastProfile(1);
                            int ncell = Utility.ClipPolygon(vRow, nrow, vCellOut, 1F, -z + 0.5F, 2);

                            if (ncell < 3)
                            {
                                //AstarProfiler.EndFastProfile(1);
                                continue;
                            }

                            ncell = Utility.ClipPolygonY(vCellOut, ncell, vCell, -1F, z + 0.5F, 2);

                            if (ncell < 3)
                            {
                                //AstarProfiler.EndFastProfile(1);
                                continue;
                            }

                            //AstarProfiler.EndFastProfile(1);
                            //AstarProfiler.StartFastProfile(2);
                            float sMin = vCell[1];
                            float sMax = vCell[1];
                            for (int q = 1; q < ncell; q++)
                            {
                                float val = vCell[q * 3 + 1];
                                sMin = System.Math.Min(sMin, val);
                                sMax = System.Math.Max(sMax, val);
                            }

                            //AstarProfiler.EndFastProfile(2);
                            int maxi = (int)System.Math.Ceiling(sMax);

                            // Skip span if below the bounding box
                            if (maxi >= 0)
                            {
                                // Make sure mini >= 0
                                int mini = System.Math.Max(0, (int)sMin);

                                // Make sure the span is at least 1 voxel high
                                maxi = System.Math.Max(mini + 1, maxi);

                                voxelArea.AddLinkedSpan(z * voxelArea.width + x, (uint)mini, (uint)maxi, area, voxelWalkableClimb);
                            }
                        }
                    }
                }
                //AstarProfiler.EndFastProfile(0);
                //AstarProfiler.EndProfile ("Rasterize...");
            }
            AstarProfiler.EndProfile("Voxelizing - Step 2");
        }
コード例 #3
0
		/** 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.
		  * */
		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;
				
				if ( collider.sharedMesh != null ) {
					ExtraMesh m = new ExtraMesh(collider.sharedMesh.vertices, collider.sharedMesh.triangles, collider.bounds, localToWorldMatrix);
					return m;
				}
			}
			
			return new ExtraMesh();
		}
コード例 #4
0
		/** Find all relevant RecastMeshObj components and add ExtraMeshes for them */
		public void GetRecastMeshObjs (Bounds bounds, List<ExtraMesh> buffer) {
			List<RecastMeshObj> buffer2 = Util.ListPool<RecastMeshObj>.Claim ();
			
			RecastMeshObj.GetAllInBounds (buffer2, bounds);
			
			Dictionary<Mesh, Vector3[]> cachedVertices = new Dictionary<Mesh, Vector3[]>();
			Dictionary<Mesh, int[]> cachedTris = new Dictionary<Mesh, int[]>();
			
			for (int i=0;i<buffer2.Count;i++) {
				MeshFilter filter = buffer2[i].GetMeshFilter();
				
				if (filter != null) {
					Mesh mesh = filter.sharedMesh;
					
					ExtraMesh smesh = new ExtraMesh();
					smesh.matrix = filter.renderer.localToWorldMatrix;
					smesh.original = filter;
					smesh.area = buffer2[i].area;
					
					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 = filter.renderer.bounds;
					
					buffer.Add (smesh);
				} else {
					Collider coll = buffer2[i].GetCollider();
					if (coll == null) {
						Debug.LogError ("RecastMeshObject ("+buffer2[i].gameObject.name +") didn't have a collider or MeshFilter attached");
						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);
		}
コード例 #5
0
		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);
					}
				}
			}
		}
コード例 #6
0
ファイル: RecastGenerator.cs プロジェクト: mBeierl/GGJ16
		static 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 (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)
						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
			}
		}
コード例 #7
0
ファイル: RecastGenerator.cs プロジェクト: mBeierl/GGJ16
		/** 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;

					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) {
						Debug.LogError ("RecastMeshObject ("+buffer2[i].gameObject.name +") didn't have a collider or MeshFilter+Renderer attached");
						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);
		}
コード例 #8
0
ファイル: RecastGraph.cs プロジェクト: GameDiffs/TheForest
 private ExtraMesh RasterizeCollider(Collider col, Matrix4x4 localToWorldMatrix)
 {
     if (col is BoxCollider)
     {
         BoxCollider boxCollider = col as BoxCollider;
         Matrix4x4 matrix4x = Matrix4x4.TRS(boxCollider.center, Quaternion.identity, boxCollider.size * 0.5f);
         matrix4x = localToWorldMatrix * matrix4x;
         Bounds bounds = boxCollider.bounds;
         ExtraMesh result = new ExtraMesh(this.BoxColliderVerts, this.BoxColliderTris, bounds, matrix4x);
         return result;
     }
     if (col is SphereCollider || col is CapsuleCollider)
     {
         SphereCollider sphereCollider = col as SphereCollider;
         CapsuleCollider capsuleCollider = col as CapsuleCollider;
         float num = (!(sphereCollider != null)) ? capsuleCollider.radius : sphereCollider.radius;
         float num2 = (!(sphereCollider != null)) ? (capsuleCollider.height * 0.5f / num - 1f) : 0f;
         Matrix4x4 matrix4x2 = Matrix4x4.TRS((!(sphereCollider != null)) ? capsuleCollider.center : sphereCollider.center, Quaternion.identity, Vector3.one * num);
         matrix4x2 = localToWorldMatrix * matrix4x2;
         int num3 = Mathf.Max(4, Mathf.RoundToInt(this.colliderRasterizeDetail * Mathf.Sqrt(matrix4x2.MultiplyVector(Vector3.one).magnitude)));
         if (num3 > 100)
         {
             UnityEngine.Debug.LogWarning("Very large detail for some collider meshes. Consider decreasing Collider Rasterize Detail (RecastGraph)");
         }
         int num4 = num3;
         RecastGraph.CapsuleCache capsuleCache = null;
         for (int i = 0; i < this.capsuleCache.Count; i++)
         {
             RecastGraph.CapsuleCache capsuleCache2 = this.capsuleCache[i];
             if (capsuleCache2.rows == num3 && Mathf.Approximately(capsuleCache2.height, num2))
             {
                 capsuleCache = capsuleCache2;
             }
         }
         Vector3[] array;
         if (capsuleCache == null)
         {
             array = new Vector3[num3 * num4 + 2];
             List<int> list = new List<int>();
             array[array.Length - 1] = Vector3.up;
             for (int j = 0; j < num3; j++)
             {
                 for (int k = 0; k < num4; k++)
                 {
                     array[k + j * num4] = new Vector3(Mathf.Cos((float)k * 3.14159274f * 2f / (float)num4) * Mathf.Sin((float)j * 3.14159274f / (float)(num3 - 1)), Mathf.Cos((float)j * 3.14159274f / (float)(num3 - 1)) + ((j >= num3 / 2) ? (-num2) : num2), Mathf.Sin((float)k * 3.14159274f * 2f / (float)num4) * Mathf.Sin((float)j * 3.14159274f / (float)(num3 - 1)));
                 }
             }
             array[array.Length - 2] = Vector3.down;
             int l = 0;
             int num5 = num4 - 1;
             while (l < num4)
             {
                 list.Add(array.Length - 1);
                 list.Add(0 * num4 + num5);
                 list.Add(0 * num4 + l);
                 num5 = l++;
             }
             for (int m = 1; m < num3; m++)
             {
                 int n = 0;
                 int num6 = num4 - 1;
                 while (n < num4)
                 {
                     list.Add(m * num4 + n);
                     list.Add(m * num4 + num6);
                     list.Add((m - 1) * num4 + n);
                     list.Add((m - 1) * num4 + num6);
                     list.Add((m - 1) * num4 + n);
                     list.Add(m * num4 + num6);
                     num6 = n++;
                 }
             }
             int num7 = 0;
             int num8 = num4 - 1;
             while (num7 < num4)
             {
                 list.Add(array.Length - 2);
                 list.Add((num3 - 1) * num4 + num8);
                 list.Add((num3 - 1) * num4 + num7);
                 num8 = num7++;
             }
             capsuleCache = new RecastGraph.CapsuleCache();
             capsuleCache.rows = num3;
             capsuleCache.height = num2;
             capsuleCache.verts = array;
             capsuleCache.tris = list.ToArray();
             this.capsuleCache.Add(capsuleCache);
         }
         array = capsuleCache.verts;
         int[] tris = capsuleCache.tris;
         Bounds bounds2 = col.bounds;
         ExtraMesh result2 = new ExtraMesh(array, tris, bounds2, matrix4x2);
         return result2;
     }
     if (col is MeshCollider)
     {
         MeshCollider meshCollider = col as MeshCollider;
         if (meshCollider.sharedMesh != null)
         {
             ExtraMesh result3 = new ExtraMesh(meshCollider.sharedMesh.vertices, meshCollider.sharedMesh.triangles, meshCollider.bounds, localToWorldMatrix);
             return result3;
         }
     }
     return default(ExtraMesh);
 }
コード例 #9
0
ファイル: RecastGraph.cs プロジェクト: GameDiffs/TheForest
 private void CollectTreeMeshes(Terrain terrain, List<ExtraMesh> extraMeshes)
 {
     TerrainData terrainData = terrain.terrainData;
     for (int i = 0; i < terrainData.treeInstances.Length; i++)
     {
         TreeInstance treeInstance = terrainData.treeInstances[i];
         TreePrototype treePrototype = terrainData.treePrototypes[treeInstance.prototypeIndex];
         if (!(treePrototype.prefab == null))
         {
             Collider component = treePrototype.prefab.GetComponent<Collider>();
             if (component == null)
             {
                 Bounds b = new Bounds(terrain.transform.position + Vector3.Scale(treeInstance.position, terrainData.size), new Vector3(treeInstance.widthScale, treeInstance.heightScale, treeInstance.widthScale));
                 Matrix4x4 matrix = Matrix4x4.TRS(terrain.transform.position + Vector3.Scale(treeInstance.position, terrainData.size), Quaternion.identity, new Vector3(treeInstance.widthScale, treeInstance.heightScale, treeInstance.widthScale) * 0.5f);
                 ExtraMesh item = new ExtraMesh(this.BoxColliderVerts, this.BoxColliderTris, b, matrix);
                 extraMeshes.Add(item);
             }
             else
             {
                 Vector3 pos = terrain.transform.position + Vector3.Scale(treeInstance.position, terrainData.size);
                 Vector3 s = new Vector3(treeInstance.widthScale, treeInstance.heightScale, treeInstance.widthScale);
                 ExtraMesh item2 = this.RasterizeCollider(component, Matrix4x4.TRS(pos, Quaternion.identity, s));
                 if (item2.vertices != null)
                 {
                     item2.RecalculateBounds();
                     extraMeshes.Add(item2);
                 }
             }
         }
     }
 }