Ejemplo n.º 1
0
 public NavMesh(TerrainTile tile, NavMeshPolygon[] polys, Vector3[] vertices, int[] indices)
 {
     Tile = tile;
     Polygons = polys;
     Vertices = vertices;
     Indices = indices;
 }
Ejemplo n.º 2
0
		/// <summary>
		/// Put it all together
		/// </summary>
		private unsafe void SmashMesh(
			int userId,
			int vertComponentCount,
			int polyCount,
			IntPtr vertComponentsPtr,

			int totalPolyIndexCount,				// count of all vertex indices in all polys
			IntPtr pIndexCountsPtr,
			IntPtr pIndicesPtr,
			IntPtr pNeighborsPtr,
			IntPtr pFlagsPtr,
			IntPtr polyAreasAndTypesPtr
			)
		{
			//var coords = GetTileCoords(userId);
			//var tile = Terrain.GetTile(coords);

			//if (tile == null)
			//{
			//    throw new Exception("Invalid tile: " + id);
			//}

			// read native data
			var vertComponents = (float*)vertComponentsPtr;
			var pIndexCounts = (byte*)pIndexCountsPtr;
			var pIndices = (uint*)pIndicesPtr;
			var pNeighbors = (uint*)pNeighborsPtr;
			var pFlags = (ushort*)pFlagsPtr;
			var polyAreasAndTypes = (byte*)polyAreasAndTypesPtr;


			// create vertices array
			var indices = new int[totalPolyIndexCount];
			var vertCount = vertComponentCount / 3;

			List<Vector3> vertexList;
			using (LargeObjectPools.Vector3ListPool.Borrow(out vertexList))
			{
				var min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
				var max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

				for (int i = 0, v = 0; i < vertCount; i++, v += 3)
				{
					var vert = new Vector3(vertComponents[v], vertComponents[v + 1], vertComponents[v + 2]);
					RecastUtil.TransformRecastCoordsToWoWCoords(ref vert);
					vertexList.Add(vert);

					// expand bounding box
					min.X = Math.Min(min.X, vert.X);
					min.Y = Math.Min(min.Y, vert.Y);
					min.Z = Math.Min(min.Z, vert.Z);

					max.X = Math.Max(max.X, vert.X);
					max.Y = Math.Max(max.Y, vert.Y);
					max.Z = Math.Max(max.Z, vert.Z);
				}

				Min = min;
				Max = max;

				var vertices = EliminateDoubleVertices(vertexList, pIndices, totalPolyIndexCount);

				// polygon first pass -> Create polygons
				var polys = new NavMeshPolygon[polyCount];
				var polyEdgeIndex = 0;
				var p = 0;
				for (var i = 0; i < polyCount; i++)
				{
					var polyIndexCount = pIndexCounts[i];
					var poly = polys[i] = new NavMeshPolygon();
					poly.Indices = new int[polyIndexCount];
					poly.Neighbors = new int[polyIndexCount];

					Debug.Assert(3 == polyIndexCount);

					for (var j = 0; j < polyIndexCount; j++)
					{
						var idx = (int)pIndices[polyEdgeIndex + j];
						indices[p++] = idx;
						poly.Indices[j] = idx;
						poly.Neighbors[j] = -1;

						Debug.Assert(poly.Indices[j] >= 0 && poly.Indices[j] < vertCount);
					}

					// switch first and third index because our collision test needs the triangles to go in the other direction
					var tmp = poly.Indices[0];
					indices[p - 3] = poly.Indices[0] = poly.Indices[2];
					indices[p - 1] = poly.Indices[2] = tmp;

					polyEdgeIndex += polyIndexCount;
				}

				// polygon second pass -> Initialize neighbors
				polyEdgeIndex = 0;

				var undecidedNeighborRelations = new List<Tuple<int, int>>();
				for (var i = 0; i < polyCount; i++)
				{
					var poly = polys[i];
					var polyIndexCount = pIndexCounts[i];
					var a = poly.Indices[0];
					var b = poly.Indices[1];
					var c = poly.Indices[2];

					for (var j = 0; j < polyIndexCount; j++)
					{
						var neighbor = (int)pNeighbors[polyEdgeIndex + j];
						if (neighbor == -1) continue;

						var neighborPoly = polys[neighbor];

						// sort the neighbor poly into the array of neighbors, correctly
						var a2 = neighborPoly.Indices[0];
						var b2 = neighborPoly.Indices[1];
						var c2 = neighborPoly.Indices[2];


						var nCount = 0;
						var mask = 0;
						if (a == a2 || a == b2 || a == c2)
						{
							// some vertex matches the first vertex of the triangle
							nCount++;
							mask |= TerrainUtil.TrianglePointA;
						}
						if (b == a2 || b == b2 || b == c2)
						{
							// some vertex matches the second vertex of the triangle
							nCount++;
							mask |= TerrainUtil.TrianglePointB;
						}
						if (c == a2 || c == b2 || c == c2)
						{
							// some vertex matches the third vertex of the triangle
							nCount++;
							mask |= TerrainUtil.TrianglePointC;
						}


						//var va = vertices[a];
						//var vb = vertices[b];
						//var vc = vertices[c];
						//var ua = vertices[a2];
						//var ub = vertices[b2];
						//var uc = vertices[c2];

						//var vs = new List<Vector3>() { va, vb, vc };
						//var us = new List<Vector3>() { ua, ub, uc };
						//var mc = 0;
						//for (var ii = 0; ii < vs.Count; ii++)
						//{
						//    var vv = vs[ii];
						//    for (var jj = 0; jj < us.Count; jj++)
						//    {
						//        var uu = us[jj];
						//        if (vv.Equals(uu))
						//        {
						//            mc++;
						//            break;
						//        }
						//    }
						//}
						//Debug.Assert(mc == 2);
						//Debug.Assert(nCount == 2);

						if (nCount < 2)
						{
							undecidedNeighborRelations.Add(Tuple.Create(i, neighbor));
						}

						var edge = TerrainUtil.GetEdge(mask);
						if (edge != -1)
						{
							poly.Neighbors[edge] = neighbor;
						}
					}

					polyEdgeIndex += polyIndexCount;
				}

				// these relations are incorrect for some reason
				// the actual neighbor that is to replace the undecided neighbor is also in this set, though
				for (var i = 0; i < undecidedNeighborRelations.Count; i++)
				{
					var rel = undecidedNeighborRelations[i];

					var poly = polys[rel.Item1];
					var tri = poly.GetTriangle(vertices);

					for (var j = 0; j < undecidedNeighborRelations.Count; j++)
					{
						if (i == j) continue;

						var index2 = undecidedNeighborRelations[j].Item1;
						var poly2 = polys[index2];
						var tri2 = poly2.GetTriangle(vertices);

						var sharedMask = tri.GetSharedEdgeMask(tri2);
						var edge = TerrainUtil.GetEdge(sharedMask);
						if (edge != -1)
						{
							// the two share an edge
							poly.Neighbors[edge] = index2;
							break;
						}
					}
				}

				// make sure, the neighbor relation is symmetric
				for (var i = 0; i < polys.Length; i++)
				{
					var poly = polys[i];
					for (int j = 0; j < poly.Neighbors.Length; j++)
					{
						var neighbor = poly.Neighbors[j];
						if (neighbor == -1) continue;

						var neighborPoly = polys[neighbor];
						var found = false;
						for (var k = 0; k < neighborPoly.Neighbors.Length; k++)
						{
							var neighneigh = neighborPoly.Neighbors[k];
							if (neighneigh == i)
							{
								found = true;
								break;
							}
						}

						if (!found)
						{
							// neighbor of poly does not have poly as neighor
							// find the edge and insert the neighbor
							var tri = poly.GetTriangle(vertices);
							var tri2 = neighborPoly.GetTriangle(vertices);
							var sharedMask = tri2.GetSharedEdgeMask(tri);
							var edge = TerrainUtil.GetEdge(sharedMask);
							Debug.Assert(neighborPoly.Neighbors[edge] == -1);

							neighborPoly.Neighbors[edge] = i;
							break;
						}
					}
				}

				// create new NavMesh object
				Tile.NavMesh = new NavMesh(Tile, polys, vertices, indices);
			}
		}
Ejemplo n.º 3
0
        /// <summary>
        /// Put it all together
        /// </summary>
        private unsafe void SmashMesh(
            int userId,
            int vertComponentCount,
            int polyCount,
            IntPtr vertComponentsPtr,

            int totalPolyIndexCount,                                            // count of all vertex indices in all polys
            IntPtr pIndexCountsPtr,
            IntPtr pIndicesPtr,
            IntPtr pNeighborsPtr,
            IntPtr pFlagsPtr,
            IntPtr polyAreasAndTypesPtr
            )
        {
            //var coords = GetTileCoords(userId);
            //var tile = Terrain.GetTile(coords);

            //if (tile == null)
            //{
            //    throw new Exception("Invalid tile: " + id);
            //}

            // read native data
            var vertComponents    = (float *)vertComponentsPtr;
            var pIndexCounts      = (byte *)pIndexCountsPtr;
            var pIndices          = (uint *)pIndicesPtr;
            var pNeighbors        = (uint *)pNeighborsPtr;
            var pFlags            = (ushort *)pFlagsPtr;
            var polyAreasAndTypes = (byte *)polyAreasAndTypesPtr;


            // create vertices array
            var indices   = new int[totalPolyIndexCount];
            var vertCount = vertComponentCount / 3;

            List <Vector3> vertexList;

            using (LargeObjectPools.Vector3ListPool.Borrow(out vertexList))
            {
                var min = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue);
                var max = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue);

                for (int i = 0, v = 0; i < vertCount; i++, v += 3)
                {
                    var vert = new Vector3(vertComponents[v], vertComponents[v + 1], vertComponents[v + 2]);
                    RecastUtil.TransformRecastCoordsToWoWCoords(ref vert);
                    vertexList.Add(vert);

                    // expand bounding box
                    min.X = Math.Min(min.X, vert.X);
                    min.Y = Math.Min(min.Y, vert.Y);
                    min.Z = Math.Min(min.Z, vert.Z);

                    max.X = Math.Max(max.X, vert.X);
                    max.Y = Math.Max(max.Y, vert.Y);
                    max.Z = Math.Max(max.Z, vert.Z);
                }

                Min = min;
                Max = max;

                var vertices = EliminateDoubleVertices(vertexList, pIndices, totalPolyIndexCount);

                // polygon first pass -> Create polygons
                var polys         = new NavMeshPolygon[polyCount];
                var polyEdgeIndex = 0;
                var p             = 0;
                for (var i = 0; i < polyCount; i++)
                {
                    var polyIndexCount = pIndexCounts[i];
                    var poly           = polys[i] = new NavMeshPolygon();
                    poly.Indices   = new int[polyIndexCount];
                    poly.Neighbors = new int[polyIndexCount];

                    Debug.Assert(3 == polyIndexCount);

                    for (var j = 0; j < polyIndexCount; j++)
                    {
                        var idx = (int)pIndices[polyEdgeIndex + j];
                        indices[p++]      = idx;
                        poly.Indices[j]   = idx;
                        poly.Neighbors[j] = -1;

                        Debug.Assert(poly.Indices[j] >= 0 && poly.Indices[j] < vertCount);
                    }

                    // switch first and third index because our collision test needs the triangles to go in the other direction
                    var tmp = poly.Indices[0];
                    indices[p - 3] = poly.Indices[0] = poly.Indices[2];
                    indices[p - 1] = poly.Indices[2] = tmp;

                    polyEdgeIndex += polyIndexCount;
                }

                // polygon second pass -> Initialize neighbors
                polyEdgeIndex = 0;

                var undecidedNeighborRelations = new List <Tuple <int, int> >();
                for (var i = 0; i < polyCount; i++)
                {
                    var poly           = polys[i];
                    var polyIndexCount = pIndexCounts[i];
                    var a = poly.Indices[0];
                    var b = poly.Indices[1];
                    var c = poly.Indices[2];

                    for (var j = 0; j < polyIndexCount; j++)
                    {
                        var neighbor = (int)pNeighbors[polyEdgeIndex + j];
                        if (neighbor == -1)
                        {
                            continue;
                        }

                        var neighborPoly = polys[neighbor];

                        // sort the neighbor poly into the array of neighbors, correctly
                        var a2 = neighborPoly.Indices[0];
                        var b2 = neighborPoly.Indices[1];
                        var c2 = neighborPoly.Indices[2];


                        var nCount = 0;
                        var mask   = 0;
                        if (a == a2 || a == b2 || a == c2)
                        {
                            // some vertex matches the first vertex of the triangle
                            nCount++;
                            mask |= TerrainUtil.TrianglePointA;
                        }
                        if (b == a2 || b == b2 || b == c2)
                        {
                            // some vertex matches the second vertex of the triangle
                            nCount++;
                            mask |= TerrainUtil.TrianglePointB;
                        }
                        if (c == a2 || c == b2 || c == c2)
                        {
                            // some vertex matches the third vertex of the triangle
                            nCount++;
                            mask |= TerrainUtil.TrianglePointC;
                        }


                        //var va = vertices[a];
                        //var vb = vertices[b];
                        //var vc = vertices[c];
                        //var ua = vertices[a2];
                        //var ub = vertices[b2];
                        //var uc = vertices[c2];

                        //var vs = new List<Vector3>() { va, vb, vc };
                        //var us = new List<Vector3>() { ua, ub, uc };
                        //var mc = 0;
                        //for (var ii = 0; ii < vs.Count; ii++)
                        //{
                        //    var vv = vs[ii];
                        //    for (var jj = 0; jj < us.Count; jj++)
                        //    {
                        //        var uu = us[jj];
                        //        if (vv.Equals(uu))
                        //        {
                        //            mc++;
                        //            break;
                        //        }
                        //    }
                        //}
                        //Debug.Assert(mc == 2);
                        //Debug.Assert(nCount == 2);

                        if (nCount < 2)
                        {
                            undecidedNeighborRelations.Add(Tuple.Create(i, neighbor));
                        }

                        var edge = TerrainUtil.GetEdge(mask);
                        if (edge != -1)
                        {
                            poly.Neighbors[edge] = neighbor;
                        }
                    }

                    polyEdgeIndex += polyIndexCount;
                }

                // these relations are incorrect for some reason
                // the actual neighbor that is to replace the undecided neighbor is also in this set, though
                for (var i = 0; i < undecidedNeighborRelations.Count; i++)
                {
                    var rel = undecidedNeighborRelations[i];

                    var poly = polys[rel.Item1];
                    var tri  = poly.GetTriangle(vertices);

                    for (var j = 0; j < undecidedNeighborRelations.Count; j++)
                    {
                        if (i == j)
                        {
                            continue;
                        }

                        var index2 = undecidedNeighborRelations[j].Item1;
                        var poly2  = polys[index2];
                        var tri2   = poly2.GetTriangle(vertices);

                        var sharedMask = tri.GetSharedEdgeMask(tri2);
                        var edge       = TerrainUtil.GetEdge(sharedMask);
                        if (edge != -1)
                        {
                            // the two share an edge
                            poly.Neighbors[edge] = index2;
                            break;
                        }
                    }
                }

                // make sure, the neighbor relation is symmetric
                for (var i = 0; i < polys.Length; i++)
                {
                    var poly = polys[i];
                    for (int j = 0; j < poly.Neighbors.Length; j++)
                    {
                        var neighbor = poly.Neighbors[j];
                        if (neighbor == -1)
                        {
                            continue;
                        }

                        var neighborPoly = polys[neighbor];
                        var found        = false;
                        for (var k = 0; k < neighborPoly.Neighbors.Length; k++)
                        {
                            var neighneigh = neighborPoly.Neighbors[k];
                            if (neighneigh == i)
                            {
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            // neighbor of poly does not have poly as neighor
                            // find the edge and insert the neighbor
                            var tri        = poly.GetTriangle(vertices);
                            var tri2       = neighborPoly.GetTriangle(vertices);
                            var sharedMask = tri2.GetSharedEdgeMask(tri);
                            var edge       = TerrainUtil.GetEdge(sharedMask);
                            Debug.Assert(neighborPoly.Neighbors[edge] == -1);

                            neighborPoly.Neighbors[edge] = i;
                            break;
                        }
                    }
                }

                // create new NavMesh object
                Tile.NavMesh = new NavMesh(Tile, polys, vertices, indices);
            }
        }