Esempio n. 1
0
		/** Builds a polygon mesh from a contour set.
		 *
		 * \param cset contour set to build a mesh from.
		 * \param nvp Maximum allowed vertices per polygon. \warning Currently locked to 3.
		 * \param mesh Results will be written to this mesh.
		 */
		public void BuildPolyMesh (VoxelContourSet cset, int nvp, out VoxelMesh mesh) {
			
			AstarProfiler.StartProfile ("Build Poly Mesh");
			
			nvp = 3;
			
			int maxVertices = 0;
			int maxTris = 0;
			int maxVertsPerCont = 0;
			
			for (int i = 0; i < cset.conts.Count; i++) {
				
				// Skip null contours.
				if (cset.conts[i].nverts < 3) continue;
				
				maxVertices += cset.conts[i].nverts;
				maxTris += cset.conts[i].nverts - 2;
				maxVertsPerCont = AstarMath.Max (maxVertsPerCont, cset.conts[i].nverts);
			}
			
			if (maxVertices >= 65534)
			{
				Debug.LogWarning ("To many vertices for unity to render - Unity might screw up rendering, but hopefully the navmesh will work ok");
				//mesh = new VoxelMesh ();
				//yield break;
				//return;
			}
			
			/** \todo Could be cached to avoid allocations */
			Int3[] verts = new Int3[maxVertices];
			/** \todo Could be cached to avoid allocations */
			int[] polys = new int[maxTris*nvp];
			
			Memory.MemSet<int> (polys, 0xff, sizeof(int));
			
			int[] indices = new int[maxVertsPerCont];
			
			int[] tris = new int[maxVertsPerCont*3];
			
			int vertexIndex = 0;
			int polyIndex = 0;
			
			for (int i=0;i<cset.conts.Count;i++) {
				
				VoxelContour cont = cset.conts[i];
				
				//Skip null contours
				if (cont.nverts < 3) {
					continue;
				}
				
				for (int j=0; j < cont.nverts;j++) {
					indices[j] = j;
					cont.verts[j*4+2] /= voxelArea.width;
				}
				
				int ntris = Triangulate (cont.nverts, cont.verts, ref indices, ref tris);
				
				int startIndex = vertexIndex;
				for (int j=0;j<ntris*3; polyIndex++, j++) {
					//@Error sometimes
					polys[polyIndex] = tris[j]+startIndex;
				}
				
				for (int j=0;j<cont.nverts; vertexIndex++, j++) {
					verts[vertexIndex] = new Int3(cont.verts[j*4],cont.verts[j*4+1],cont.verts[j*4+2]);
				}
			}
			
			mesh = new VoxelMesh ();
			//yield break;
			Int3[] trimmedVerts = new Int3[vertexIndex];
			for (int i=0;i<vertexIndex;i++) {
				trimmedVerts[i] = verts[i];
			}
			
			int[] trimmedTris = new int[polyIndex];
			
			System.Buffer.BlockCopy (polys, 0, trimmedTris, 0, polyIndex*sizeof(int));
			
			mesh.verts = trimmedVerts;
			mesh.tris = trimmedTris;
			
			// Some debugging
			/*for (int i=0;i<mesh.tris.Length/3;i++) {
				
				int p = i*3;
				
				int p1 = mesh.tris[p];
				int p2 = mesh.tris[p+1];
				int p3 = mesh.tris[p+2];
				
				//Debug.DrawLine (ConvertPosCorrZ (mesh.verts[p1].x,mesh.verts[p1].y,mesh.verts[p1].z),ConvertPosCorrZ (mesh.verts[p2].x,mesh.verts[p2].y,mesh.verts[p2].z),Color.yellow);
				//Debug.DrawLine (ConvertPosCorrZ (mesh.verts[p1].x,mesh.verts[p1].y,mesh.verts[p1].z),ConvertPosCorrZ (mesh.verts[p3].x,mesh.verts[p3].y,mesh.verts[p3].z),Color.yellow);
				//Debug.DrawLine (ConvertPosCorrZ (mesh.verts[p3].x,mesh.verts[p3].y,mesh.verts[p3].z),ConvertPosCorrZ (mesh.verts[p2].x,mesh.verts[p2].y,mesh.verts[p2].z),Color.yellow);
	
				//Debug.DrawLine (ConvertPosCorrZ (verts[p1],0,verts[p1+2]),ConvertPosCorrZ (verts[p2],0,verts[p2+2]),Color.blue);
				//Debug.DrawLine (ConvertPosCorrZ (verts[p1],0,verts[p1+2]),ConvertPosCorrZ (verts[p3],0,verts[p3+2]),Color.blue);
				//Debug.DrawLine (ConvertPosCorrZ (verts[p2],0,verts[p2+2]),ConvertPosCorrZ (verts[p3],0,verts[p3+2]),Color.blue);
	
			}*/
			
			AstarProfiler.EndProfile ("Build Poly Mesh");
			
		}
Esempio n. 2
0
		/** Create a tile at tile index \a x , \a z from the mesh.
		 * \warning This implementation is not thread safe. It uses cached variables to improve performance
		 */
		NavmeshTile CreateTile (Voxelize vox, VoxelMesh mesh, int x, int z) {

			if (mesh.tris == null) throw new System.ArgumentNullException ("mesh.tris");
			if (mesh.verts == null) throw new System.ArgumentNullException ("mesh.verts");

			//Create a new navmesh tile and assign its settings
			var tile = new NavmeshTile();

			tile.x = x;
			tile.z = z;
			tile.w = 1;
			tile.d = 1;
			tile.tris = mesh.tris;
			tile.verts = mesh.verts;
			tile.bbTree = new BBTree();

			if (tile.tris.Length % 3 != 0) throw new System.ArgumentException ("Indices array's length must be a multiple of 3 (mesh.tris)");

			if (tile.verts.Length >= VertexIndexMask) throw new System.ArgumentException ("Too many vertices per tile (more than "+VertexIndexMask+")." +
				"\nTry enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector");

			//Dictionary<Int3, int> firstVerts = new Dictionary<Int3, int> ();
			Dictionary<Int3, int> firstVerts = cachedInt3_int_dict;
			firstVerts.Clear();

			var compressedPointers = new int[tile.verts.Length];

			int count = 0;
			for (int i=0;i<tile.verts.Length;i++) {
				if (!firstVerts.ContainsKey(tile.verts[i])) {
					firstVerts.Add (tile.verts[i], count);
					compressedPointers[i] = count;
					tile.verts[count] = tile.verts[i];
					count++;
				} else {
					// There are some cases, rare but still there, that vertices are identical
					compressedPointers[i] = firstVerts[tile.verts[i]];
				}
			}

			for (int i=0;i<tile.tris.Length;i++) {
				tile.tris[i] = compressedPointers[tile.tris[i]];
			}

			var compressed = new Int3[count];
			for (int i=0;i<count;i++) compressed[i] = tile.verts[i];

			tile.verts = compressed;

			var nodes = new TriangleMeshNode[tile.tris.Length/3];
			tile.nodes = nodes;

			//Here we are faking a new graph
			//The tile is not added to any graphs yet, but to get the position querys from the nodes
			//to work correctly (not throw exceptions because the tile is not calculated) we fake a new graph
			//and direct the position queries directly to the tile
			int graphIndex = AstarPath.active.astarData.graphs.Length;

			TriangleMeshNode.SetNavmeshHolder (graphIndex, tile);

			//This index will be ORed to the triangle indices
			int tileIndex = x + z*tileXCount;
			tileIndex <<= TileIndexOffset;

			//Create nodes and assign triangle indices
			for (int i=0;i<nodes.Length;i++) {
				var node = new TriangleMeshNode(active);
				nodes[i] = node;
				node.GraphIndex = (uint)graphIndex;
				node.v0 = tile.tris[i*3+0] | tileIndex;
				node.v1 = tile.tris[i*3+1] | tileIndex;
				node.v2 = tile.tris[i*3+2] | tileIndex;

				//Degenerate triangles might occur, but they will not cause any large troubles anymore
				//if (Polygon.IsColinear (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
				//	Debug.Log ("COLINEAR!!!!!!");
				//}

				//Make sure the triangle is clockwise
				if (!Polygon.IsClockwise (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}

				node.Walkable = true;
				node.Penalty = initialPenalty;
				node.UpdatePositionFromVertices();
			}

			tile.bbTree.RebuildFrom(nodes);
			CreateNodeConnections (tile.nodes);

			//Remove the fake graph
			TriangleMeshNode.SetNavmeshHolder (graphIndex, null);

			return tile;
		}