AddLinkedSpan() public method

public AddLinkedSpan ( int index, uint bottom, uint top, int area, int voxelWalkableClimb ) : void
index int
bottom uint
top uint
area int
voxelWalkableClimb int
return void
Esempio n. 1
0
        public static void MergeVoxelAreaData(VoxelArea source, VoxelArea merge, int voxelWalkableClimb)
        {
            #if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
            LinkedVoxelSpan[] spans1 = source.linkedSpans;

            int wd = source.width*source.depth;

            for (int x=0;x<wd;x++) {

                int i = x;
                if (spans1[i].bottom == VoxelArea.InvalidSpanValue) continue;

                while (i != -1) {
                    merge.AddLinkedSpan(x,spans1[i].bottom,spans1[i].top,spans1[i].area,voxelWalkableClimb);
                    i = spans1[i].next;
                }
            }
            #else
            throw new System.NotImplementedException ("This method only works with !ASTAR_RECAST_CLASS_BASED_LINKED_LIST");
            #endif
        }
Esempio n. 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");
        }
Esempio n. 3
0
		public static void MergeVoxelAreaData (VoxelArea source, VoxelArea merge, int voxelWalkableClimb) {
#if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
			LinkedVoxelSpan[] spans1 = source.linkedSpans;
			
			int wd = source.width*source.depth;
			
			for (int x=0;x<wd;x++) {
				
				int i = x;
				if (spans1[i].bottom == VoxelArea.InvalidSpanValue) continue;
				
				while (i != -1) {
					merge.AddLinkedSpan(x,spans1[i].bottom,spans1[i].top,spans1[i].area,voxelWalkableClimb);
					i = spans1[i].next;
				}
			}
#else
			throw new System.NotImplementedException ("This method only works with !ASTAR_RECAST_CLASS_BASED_LINKED_LIST");
#endif
		}
Esempio n. 4
0
        public void VoxelizeInput(Pathfinding.Util.GraphTransform graphTransform, Bounds graphSpaceBounds)
        {
            AstarProfiler.StartProfile("Build Navigation Mesh");

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

            // Transform from voxel space to graph space.
            // then scale from voxel space (one unit equals one voxel)
            // Finally add min
            Matrix4x4 voxelMatrix = Matrix4x4.TRS(graphSpaceBounds.min, Quaternion.identity, Vector3.one) * Matrix4x4.Scale(new Vector3(cellSize, cellHeight, cellSize));

            transformVoxel2Graph = new Pathfinding.Util.GraphTransform(voxelMatrix);

            // Transform from voxel space to world space
            // add half a voxel to fix rounding
            transform = graphTransform * voxelMatrix * Matrix4x4.TRS(new Vector3(0.5f, 0, 0.5f), Quaternion.identity, Vector3.one);

            int maximumVoxelYCoord = (int)(graphSpaceBounds.size.y / cellHeight);

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

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

            // Cosine of the slope limit in voxel space (some tweaks are needed because the voxel space might be stretched out along the y axis)
            float slopeLimit = Mathf.Cos(Mathf.Atan(Mathf.Tan(maxSlope * Mathf.Deg2Rad) * (cellSize / cellHeight)));

            // Temporary arrays used for rasterization
            var clipperOrig = new VoxelPolygonClipper(3);
            var clipperX1   = new VoxelPolygonClipper(7);
            var clipperX2   = new VoxelPolygonClipper(7);
            var clipperZ1   = new VoxelPolygonClipper(7);
            var clipperZ2   = new VoxelPolygonClipper(7);

            if (inputMeshes == null)
            {
                throw new System.NullReferenceException("inputMeshes 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 < inputMeshes.Count; m++)
            {
                maxVerts = System.Math.Max(inputMeshes[m].vertices.Length, maxVerts);
            }

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

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

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

            // This loop is the hottest place in the whole rasterization process
            // it usually accounts for around 50% of the time
            for (int m = 0; m < inputMeshes.Count; m++)
            {
                RasterizationMesh mesh = inputMeshes[m];
                var meshMatrix         = mesh.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(meshMatrix);

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

                // Transform vertices first to world space and then to voxel space
                for (int i = 0; i < vs.Length; i++)
                {
                    verts[i] = transform.InverseTransform(meshMatrix.MultiplyPoint3x4(vs[i]));
                }

                int mesharea = mesh.area;

                for (int i = 0; i < trisLength; i += 3)
                {
                    Vector3 p1 = verts[tris[i]];
                    Vector3 p2 = verts[tris[i + 1]];
                    Vector3 p3 = verts[tris[i + 2]];

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

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

                    int maxX = (int)System.Math.Ceiling(Utility.Max(p1.x, p2.x, p3.x));
                    int 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);

                    // Check if the mesh is completely out of bounds
                    if (minX >= voxelArea.width || minZ >= voxelArea.depth || maxX <= 0 || maxZ <= 0)
                    {
                        continue;
                    }

                    Vector3 normal;

                    int area;

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

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

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

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

                    clipperOrig[0] = p1;
                    clipperOrig[1] = p2;
                    clipperOrig[2] = p3;
                    clipperOrig.n  = 3;

                    for (int x = minX; x <= maxX; x++)
                    {
                        clipperOrig.ClipPolygonAlongX(ref clipperX1, 1f, -x + 0.5f);

                        if (clipperX1.n < 3)
                        {
                            continue;
                        }

                        clipperX1.ClipPolygonAlongX(ref clipperX2, -1F, x + 0.5F);

                        if (clipperX2.n < 3)
                        {
                            continue;
                        }

                        float clampZ1 = clipperX2.z[0];
                        float clampZ2 = clipperX2.z[0];
                        for (int q = 1; q < clipperX2.n; q++)
                        {
                            float val = clipperX2.z[q];
                            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++)
                        {
                            clipperX2.ClipPolygonAlongZWithYZ(ref clipperZ1, 1F, -z + 0.5F);

                            if (clipperZ1.n < 3)
                            {
                                continue;
                            }

                            clipperZ1.ClipPolygonAlongZWithY(ref clipperZ2, -1F, z + 0.5F);
                            if (clipperZ2.n < 3)
                            {
                                continue;
                            }

                            float sMin = clipperZ2.y[0];
                            float sMax = clipperZ2.y[0];
                            for (int q = 1; q < clipperZ2.n; q++)
                            {
                                float val = clipperZ2.y[q];
                                sMin = System.Math.Min(sMin, val);
                                sMax = System.Math.Max(sMax, val);
                            }

                            int maxi = (int)System.Math.Ceiling(sMax);

                            // Skip span if below or above the bounding box
                            if (maxi >= 0 && sMin <= maximumVoxelYCoord)
                            {
                                // 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");
        }
Esempio n. 5
0
		public static void MergeVoxelAreaData (VoxelArea source, VoxelArea merge, int voxelWalkableClimb) {
			
			LinkedVoxelSpan[] spans1 = source.linkedSpans;
			
			int wd = source.width*source.depth;
			
			for (int x=0;x<wd;x++) {
				
				int i = x;
				if (spans1[i].bottom == VoxelArea.InvalidSpanValue) continue;
				
				while (i != -1) {
					merge.AddLinkedSpan(x,spans1[i].bottom,spans1[i].top,spans1[i].area,voxelWalkableClimb);
					i = spans1[i].next;
				}
			}
			
			/*for (int c=0;c<cells1.Length;c++) {
				
				int i1 = (int)cells1[c].index;
				int i2 = (int)cells2[c].index;
				int c1 = (int)i1 + (int)cells1[c].count;
				int c2 = (int)i2 + (int)cells2[c].count;
				
				CompactVoxelSpan last;
				int lastIndex;
				int lastAreaType;
				if (i1 < c1 && (i2 >= c2 || spans1[i1].y < spans2[i2].y)) {
					last = spans1[i1];
					lastAreaType = source.areaTypes[i1];
					lastIndex = i1;
					i1++;
					spanCount++;
				} else if (i2 < c2) {
					last = spans2[i2];
					lastAreaType = merge.areaTypes[i2];
					lastIndex = i2;
					i2++;
					spanCount++;
				} else {
					continue;
				}
				
				while (i1 < c1 || i2 < c2) {
					
					CompactVoxelSpan span;
					int areaType;
					int spanIndex;
					
					Debug.Log (i1 + " " + i2 + " " + c1 + " " + c2);
					if (i1 < c1 && (i2 >= c2 || spans1[i1].y < spans2[i2].y)) {
						span = spans1[i1];
						spanIndex = i1;
						areaType = source.areaTypes[i1];
						i1++;
					} else if (i2 < c2) {
						span = spans2[i2];
						areaType = merge.areaTypes[i2];
						spanIndex = i2;
						i2++;
					} else {
						throw new System.Exception ("This should not happen");
					}
					
					Debug.Log (span.y + " " + (last.y+last.h));
					if (span.y > last.y+last.h) {
						last = span;
						spanCount++;
						continue;
					} else {
						last.h = System.Math.Max(last.h,span.y+span.h - last.y);
					}
				}
			}
			
			CompactVoxelSpan[] spansResult = new CompactVoxelSpan[spanCount];
			
			Debug.Log (spans1.Length + " : " + spans2.Length + " -> " + spanCount);
			
			
					int area;
					//1 is flagMergeDistance, when a walkable flag is favored before an unwalkable one
					if (Mathfx.Abs ((int)(span.y+span.h) - (int)(last.y+span.h)) <= voxelWalkableClimb) {
						area = Mathfx.Max (lastAreaType,areaType);
					}
				}
							
					
			}*/
		}
Esempio n. 6
0
        public static void MergeVoxelAreaData(VoxelArea source, VoxelArea merge, int voxelWalkableClimb)
        {
            LinkedVoxelSpan[] spans1 = source.linkedSpans;

            int wd = source.width * source.depth;

            for (int x = 0; x < wd; x++)
            {
                int i = x;
                if (spans1[i].bottom == VoxelArea.InvalidSpanValue)
                {
                    continue;
                }

                while (i != -1)
                {
                    merge.AddLinkedSpan(x, spans1[i].bottom, spans1[i].top, spans1[i].area, voxelWalkableClimb);
                    i = spans1[i].next;
                }
            }

            /*for (int c=0;c<cells1.Length;c++) {
             *
             *      int i1 = (int)cells1[c].index;
             *      int i2 = (int)cells2[c].index;
             *      int c1 = (int)i1 + (int)cells1[c].count;
             *      int c2 = (int)i2 + (int)cells2[c].count;
             *
             *      CompactVoxelSpan last;
             *      int lastIndex;
             *      int lastAreaType;
             *      if (i1 < c1 && (i2 >= c2 || spans1[i1].y < spans2[i2].y)) {
             *              last = spans1[i1];
             *              lastAreaType = source.areaTypes[i1];
             *              lastIndex = i1;
             *              i1++;
             *              spanCount++;
             *      } else if (i2 < c2) {
             *              last = spans2[i2];
             *              lastAreaType = merge.areaTypes[i2];
             *              lastIndex = i2;
             *              i2++;
             *              spanCount++;
             *      } else {
             *              continue;
             *      }
             *
             *      while (i1 < c1 || i2 < c2) {
             *
             *              CompactVoxelSpan span;
             *              int areaType;
             *              int spanIndex;
             *
             *              Debug.Log (i1 + " " + i2 + " " + c1 + " " + c2);
             *              if (i1 < c1 && (i2 >= c2 || spans1[i1].y < spans2[i2].y)) {
             *                      span = spans1[i1];
             *                      spanIndex = i1;
             *                      areaType = source.areaTypes[i1];
             *                      i1++;
             *              } else if (i2 < c2) {
             *                      span = spans2[i2];
             *                      areaType = merge.areaTypes[i2];
             *                      spanIndex = i2;
             *                      i2++;
             *              } else {
             *                      throw new System.Exception ("This should not happen");
             *              }
             *
             *              Debug.Log (span.y + " " + (last.y+last.h));
             *              if (span.y > last.y+last.h) {
             *                      last = span;
             *                      spanCount++;
             *                      continue;
             *              } else {
             *                      last.h = System.Math.Max(last.h,span.y+span.h - last.y);
             *              }
             *      }
             * }
             *
             * CompactVoxelSpan[] spansResult = new CompactVoxelSpan[spanCount];
             *
             * Debug.Log (spans1.Length + " : " + spans2.Length + " -> " + spanCount);
             *
             *
             *              int area;
             *              //1 is flagMergeDistance, when a walkable flag is favored before an unwalkable one
             *              if (Mathfx.Abs ((int)(span.y+span.h) - (int)(last.y+span.h)) <= voxelWalkableClimb) {
             *                      area = Mathfx.Max (lastAreaType,areaType);
             *              }
             *      }
             *
             *
             * }*/
        }