Beispiel #1
0
        public void BuildCompactField()
        {
            AstarProfiler.StartProfile("Build Compact Voxel Field");

            //Build compact representation
            int spanCount = voxelArea.GetSpanCount();

            voxelArea.compactSpanCount = spanCount;
            if (voxelArea.compactSpans == null || voxelArea.compactSpans.Length < spanCount)
            {
                voxelArea.compactSpans = new CompactVoxelSpan[spanCount];
                voxelArea.areaTypes    = new int[spanCount];
            }

            uint idx = 0;

            int w  = voxelArea.width;
            int d  = voxelArea.depth;
            int wd = w * d;

            if (this.voxelWalkableHeight >= 0xFFFF)
            {
                Debug.LogWarning("Too high walkable height to guarantee correctness. Increase voxel height or lower walkable height.");
            }

#if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
            LinkedVoxelSpan[] spans = voxelArea.linkedSpans;
#endif

            //Parallel.For (0, voxelArea.depth, delegate (int pz) {
            for (int z = 0, pz = 0; z < wd; z += w, pz++)
            {
                for (int x = 0; x < w; x++)
                {
#if !ASTAR_RECAST_CLASS_BASED_LINKED_LIST
                    int spanIndex = x + z;
                    if (spans[spanIndex].bottom == VoxelArea.InvalidSpanValue)
                    {
                        voxelArea.compactCells[x + z] = new CompactVoxelCell(0, 0);
                        continue;
                    }

                    uint index = idx;
                    uint count = 0;

                    //Vector3 p = new Vector3(x,0,pz)*cellSize+voxelOffset;

                    while (spanIndex != -1)
                    {
                        if (spans[spanIndex].area != UnwalkableArea)
                        {
                            int bottom = (int)spans[spanIndex].top;
                            int next   = spans[spanIndex].next;
                            int top    = next != -1 ? (int)spans[next].bottom : VoxelArea.MaxHeightInt;

                            voxelArea.compactSpans[idx] = new CompactVoxelSpan((ushort)(bottom > 0xFFFF ? 0xFFFF : bottom), (uint)(top - bottom > 0xFFFF ? 0xFFFF : top - bottom));
                            voxelArea.areaTypes[idx]    = spans[spanIndex].area;
                            idx++;
                            count++;
                        }
                        spanIndex = spans[spanIndex].next;
                    }

                    voxelArea.compactCells[x + z] = new CompactVoxelCell(index, count);
#else
                    VoxelSpan s = voxelArea.cells[x + z].firstSpan;

                    if (s == null)
                    {
                        voxelArea.compactCells[x + z] = new CompactVoxelCell(0, 0);
                        continue;
                    }

                    uint index = idx;
                    uint count = 0;

                    //Vector3 p = new Vector3(x,0,pz)*cellSize+voxelOffset;

                    while (s != null)
                    {
                        if (s.area != UnwalkableArea)
                        {
                            int bottom = (int)s.top;
                            int top    = s.next != null ? (int)s.next.bottom : VoxelArea.MaxHeightInt;

                            voxelArea.compactSpans[idx] = new CompactVoxelSpan((ushort)AstarMath.Clamp(bottom, 0, 0xffff), (uint)AstarMath.Clamp(top - bottom, 0, 0xffff));
                            voxelArea.areaTypes[idx]    = s.area;
                            idx++;
                            count++;
                        }
                        s = s.next;
                    }

                    voxelArea.compactCells[x + z] = new CompactVoxelCell(index, count);
#endif
                }
            }

            AstarProfiler.EndProfile("Build Compact Voxel Field");
        }
Beispiel #2
0
        public void VoxelizeInput()
        {
            AstarProfiler.StartProfile("Build Navigation Mesh");

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


            //Debug.DrawLine (forcedBounds.min,forcedBounds.max,Color.blue);

            Vector3 min = forcedBounds.min;

            voxelOffset = min;

            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)));

            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];

            Matrix4x4 voxelMatrix = 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;

                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]];

                    minX = (int)(Utility.Min(p1.x, p2.x, p3.x));
                    // (Mathf.Min (Mathf.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 = AstarMath.Clamp((int)System.Math.Round(clampZ1), 0, voxelArea.depth - 1);
                        int clampZ2I = AstarMath.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");
        }