void FindIntersectionVertices(ref NativeArray <float4> intersectingPlanes0,
                                      int intersectingPlanes0Length,
                                      int intersectingPlanesAndEdges0Length,
                                      ref NativeArray <float4> intersectingPlanes1,
                                      int intersectingPlanes1Length,
                                      int intersectingPlanesAndEdges1Length,
                                      ref NativeArray <PlanePair> usedPlanePairs1,
                                      int usedPlanePairs1Length,
                                      ref NativeArray <int> intersectingPlaneIndices0,
                                      int intersectingPlaneIndices0Length,
                                      float4x4 nodeToTreeSpaceMatrix0,
                                      ref HashedVertices hashedTreeSpaceVertices,
                                      ref HashedVertices snapHashedVertices,
                                      NativeArray <PlaneVertexIndexPair> foundIndices0,
                                      ref int foundIndices0Length,
                                      NativeArray <PlaneVertexIndexPair> foundIndices1,
                                      ref int foundIndices1Length)
        {
            int foundVerticesCount = usedPlanePairs1Length * intersectingPlanes0Length;

            NativeCollectionHelpers.EnsureMinimumSize(ref foundVertices, foundVerticesCount);
            NativeCollectionHelpers.EnsureMinimumSize(ref foundEdges, foundVerticesCount);
            NativeCollectionHelpers.EnsureMinimumSize(ref foundIntersections, foundVerticesCount);

            var n = 0;

            for (int i = 0; i < usedPlanePairs1Length; i++)
            {
                for (int j = 0; j < intersectingPlanes0Length; j++)
                {
                    var plane0 = usedPlanePairs1[i].plane0;
                    var plane1 = usedPlanePairs1[i].plane1;
                    var plane2 = intersectingPlanes0[j];

                    foundIntersections[n] = new IntersectionPlanes
                    {
                        //plane0    = plane0,
                        //plane1    = plane1,
                        plane2      = plane2,
                        planeIndex0 = usedPlanePairs1[i].planeIndex0,
                        planeIndex1 = usedPlanePairs1[i].planeIndex1,
                        planeIndex2 = intersectingPlaneIndices0[j]
                    };

                    foundEdges[n] = new IntersectionEdge
                    {
                        edgeVertex0 = usedPlanePairs1[i].edgeVertex0,
                        edgeVertex1 = usedPlanePairs1[i].edgeVertex1
                    };

                    if (math.abs(math.dot(plane2.xyz, plane0.xyz)) >= CSGConstants.kNormalDotAlignEpsilon ||
                        math.abs(math.dot(plane2.xyz, plane1.xyz)) >= CSGConstants.kNormalDotAlignEpsilon ||
                        math.abs(math.dot(plane0.xyz, plane1.xyz)) >= CSGConstants.kNormalDotAlignEpsilon)
                    {
                        continue;
                    }

                    var localVertex = PlaneExtensions.Intersection(plane2, plane0, plane1);
                    if (double.IsNaN(localVertex.x))
                    {
                        continue;
                    }

                    foundVertices[n] = new float4((float3)localVertex, 1);
                    n++;
                }
            }

            for (int k = n - 1; k >= 0; k--)
            {
                var edgeVertex0 = foundEdges[k].edgeVertex0;
                var edgeVertex1 = foundEdges[k].edgeVertex1;
                var plane2      = foundIntersections[k].plane2;

                if (math.abs(math.dot(plane2, edgeVertex0)) <= kFatPlaneWidthEpsilon &&
                    math.abs(math.dot(plane2, edgeVertex1)) <= kFatPlaneWidthEpsilon)
                {
                    if (k < n - 1)
                    {
                        foundIntersections[k] = foundIntersections[n - 1];
                        foundVertices[k]      = foundVertices[n - 1];
                    }
                    n--;
                }
            }

            // TODO: since we're using a pair in the outer loop, we could also determine which
            //       2 planes it intersects at both ends and just check those two planes ..

            // NOTE: for brush2, the intersection will always be only on two planes
            //       UNLESS it's a corner vertex along that edge (we can compare to the two vertices)
            //       in which case we could use a pre-calculated list of planes ..
            //       OR when the intersection is outside of the edge ..

            for (int k = n - 1; k >= 0; k--)
            {
                if (IsOutsidePlanes(intersectingPlanes0, intersectingPlanesAndEdges0Length, foundVertices[k]) ||
                    IsOutsidePlanes(intersectingPlanes1, intersectingPlanesAndEdges1Length, foundVertices[k]))
                {
                    if (k < n - 1)
                    {
                        foundIntersections[k] = foundIntersections[n - 1];
                        foundVertices[k]      = foundVertices[n - 1];
                    }
                    n--;
                }
            }

            for (int k = 0; k < n; k++)
            {
                var planeIndex0 = (ushort)foundIntersections[k].planeIndex0;
                var planeIndex1 = (ushort)foundIntersections[k].planeIndex1;
                var planeIndex2 = (ushort)foundIntersections[k].planeIndex2;

                var localVertex = foundVertices[k];

                // TODO: should be having a Loop for each plane that intersects this vertex, and add that vertex
                //       to ensure they are identical
                var treeSpaceVertex = math.mul(nodeToTreeSpaceMatrix0, localVertex).xyz;
                treeSpaceVertex = snapHashedVertices[snapHashedVertices.AddNoResize(treeSpaceVertex)];
                var treeSpaceVertexIndex = hashedTreeSpaceVertices.AddNoResize(treeSpaceVertex);

                {
                    // TODO: optimize
                    for (int f = 0; f < foundIndices0Length; f++)
                    {
                        if (foundIndices0[f].vertexIndex == treeSpaceVertexIndex &&
                            foundIndices0[f].planeIndex == planeIndex2)
                        {
                            goto skip0;
                        }
                    }

                    foundIndices0[foundIndices0Length] = new PlaneVertexIndexPair {
                        planeIndex = planeIndex2, vertexIndex = treeSpaceVertexIndex
                    };
                    foundIndices0Length++;
                    skip0 :;
                }

                {
                    // TODO: optimize
                    for (int f = 0; f < foundIndices1Length; f++)
                    {
                        if (foundIndices1[f].vertexIndex == treeSpaceVertexIndex &&
                            foundIndices1[f].planeIndex == planeIndex0)
                        {
                            goto skip1;
                        }
                    }

                    foundIndices1[foundIndices1Length] = new PlaneVertexIndexPair {
                        planeIndex = planeIndex0, vertexIndex = treeSpaceVertexIndex
                    };
                    foundIndices1Length++;
                    skip1 :;
                }

                {
                    // TODO: optimize
                    for (int f = 0; f < foundIndices1Length; f++)
                    {
                        if (foundIndices1[f].vertexIndex == treeSpaceVertexIndex &&
                            foundIndices1[f].planeIndex == planeIndex1)
                        {
                            goto skip2;
                        }
                    }

                    foundIndices1[foundIndices1Length] = new PlaneVertexIndexPair {
                        planeIndex = planeIndex1, vertexIndex = treeSpaceVertexIndex
                    };
                    foundIndices1Length++;
                    skip2 :;
                }
            }
        }
        public void Execute(int index)
        {
            var count = input.BeginForEachIndex(index);

            if (count == 0)
            {
                return;
            }

            var brushIndexOrder = input.Read <IndexOrder>();
            var brushNodeOrder  = brushIndexOrder.nodeOrder;
            var vertexCount     = input.Read <int>();

            NativeCollectionHelpers.EnsureCapacityAndClear(ref brushVertices, vertexCount);
            for (int v = 0; v < vertexCount; v++)
            {
                var vertex = input.Read <float3>();
                brushVertices.AddNoResize(vertex);
            }


            var surfaceOuterCount = input.Read <int>();

            NativeCollectionHelpers.EnsureSizeAndClear(ref surfaceLoopIndices, surfaceOuterCount);
            for (int o = 0; o < surfaceOuterCount; o++)
            {
                UnsafeList <int> inner = default;
                var surfaceInnerCount  = input.Read <int>();
                if (surfaceInnerCount > 0)
                {
                    inner = new UnsafeList <int>(surfaceInnerCount, Allocator.Temp);
                    //inner.ResizeUninitialized(surfaceInnerCount);
                    for (int i = 0; i < surfaceInnerCount; i++)
                    {
                        inner.AddNoResize(input.Read <int>());
                    }
                }
                surfaceLoopIndices[o] = inner;
            }

            var surfaceLoopCount = input.Read <int>();

            NativeCollectionHelpers.EnsureMinimumSizeAndClear(ref surfaceLoopAllInfos, surfaceLoopCount);
            NativeCollectionHelpers.EnsureSizeAndClear(ref surfaceLoopAllEdges, surfaceLoopCount);
            for (int l = 0; l < surfaceLoopCount; l++)
            {
                surfaceLoopAllInfos[l] = input.Read <SurfaceInfo>();
                var edgeCount = input.Read <int>();
                if (edgeCount > 0)
                {
                    var edgesInner = new UnsafeList <Edge>(edgeCount, Allocator.Temp);
                    //edgesInner.ResizeUninitialized(edgeCount);
                    for (int e = 0; e < edgeCount; e++)
                    {
                        edgesInner.AddNoResize(input.Read <Edge>());
                    }
                    surfaceLoopAllEdges[l] = edgesInner;
                }
            }
            input.EndForEachIndex();



            if (!basePolygonCache[brushNodeOrder].IsCreated)
            {
                return;
            }

            var maxLoops   = 0;
            var maxIndices = 0;

            for (int s = 0; s < surfaceLoopIndices.Length; s++)
            {
                if (!surfaceLoopIndices[s].IsCreated)
                {
                    continue;
                }
                var length = surfaceLoopIndices[s].Length;
                maxIndices += length;
                maxLoops    = math.max(maxLoops, length);
            }


            ref var baseSurfaces                = ref basePolygonCache[brushNodeOrder].Value.surfaces;
        //[MethodImpl(MethodImplOptions.NoInlining)]
        void FindInsideVertices([NoAlias] NativeArray <float3> usedVertices0,
                                int usedVertices0Length,
                                [NoAlias] NativeArray <ushort> vertexIntersectionPlanes,
                                int vertexIntersectionPlanesLength,
                                [NoAlias] NativeArray <int2> vertexIntersectionSegments,
                                int vertexIntersectionSegmentsLength,
                                [NoAlias] NativeArray <float4> intersectingPlanes1,
                                int intersectingPlanes1Length,
                                int intersectingPlanesAndEdges1Length,
                                float4x4 nodeToTreeSpaceMatrix1,
                                float4x4 vertexToLocal0,
                                [NoAlias] ref HashedVertices hashedTreeSpaceVertices,
                                [NoAlias] ref HashedVertices snapHashedVertices,
                                [NoAlias] NativeArray <PlaneVertexIndexPair> foundIndices0,
                                ref int foundIndices0Length)
        {
            NativeCollectionHelpers.EnsureMinimumSize(ref localVertices, usedVertices0Length);
            NativeCollectionHelpers.EnsureMinimumSize(ref usedVertexIndices, usedVertices0Length);

            for (int j = 0; j < usedVertices0Length; j++)
            {
                var brushVertex1 = new float4(usedVertices0[j], 1);
                localVertices[j]     = math.mul(vertexToLocal0, brushVertex1);
                usedVertexIndices[j] = (ushort)j;
            }

            var foundVertexCount = usedVertices0Length;

            for (int j = foundVertexCount - 1; j >= 0; j--)
            {
                if (IsOutsidePlanes(intersectingPlanes1, intersectingPlanesAndEdges1Length, localVertices[j]))
                {
                    if (j < foundVertexCount - 1)
                    {
                        localVertices[j]     = localVertices[foundVertexCount - 1];
                        usedVertexIndices[j] = usedVertexIndices[foundVertexCount - 1];
                    }
                    foundVertexCount--;
                }
            }

            for (int j = 0; j < foundVertexCount; j++)
            {
                var usedVertexIndex = usedVertexIndices[j];
                var segment         = vertexIntersectionSegments[usedVertexIndex];
                if (segment.y == 0)
                {
                    continue;
                }

                var treeSpaceVertex = math.mul(nodeToTreeSpaceMatrix1, localVertices[j]).xyz;
                treeSpaceVertex = snapHashedVertices[snapHashedVertices.AddNoResize(treeSpaceVertex)];
                var treeSpaceVertexIndex = hashedTreeSpaceVertices.AddNoResize(treeSpaceVertex);
                for (int i = segment.x; i < segment.x + segment.y; i++)
                {
                    var planeIndex = vertexIntersectionPlanes[i];

                    // TODO: optimize
                    for (int k = 0; k < foundIndices0Length; k++)
                    {
                        if (foundIndices0[k].planeIndex == planeIndex &&
                            foundIndices0[k].vertexIndex == treeSpaceVertexIndex)
                        {
                            goto skipMe;
                        }
                    }

                    foundIndices0[foundIndices0Length] = new PlaneVertexIndexPair {
                        planeIndex = (ushort)planeIndex, vertexIndex = (ushort)treeSpaceVertexIndex
                    };
                    foundIndices0Length++;
skipMe:
                    ;
                }
            }
        }
Beispiel #4
0
        public void Execute(int index)
        {
            //var brushNodeIndex = treeBrushNodeIndices[index];
            var count = input.BeginForEachIndex(index);

            if (count == 0)
            {
                return;
            }

            HashedVertices           brushVertices;
            NativeListArray <int>    surfaceLoopIndices;
            NativeList <SurfaceInfo> surfaceLoopAllInfos;
            NativeListArray <Edge>   surfaceLoopAllEdges;


            var brushNodeIndex = input.Read <int>();
            var vertexCount    = input.Read <int>();

            brushVertices = new HashedVertices(vertexCount, allocator);
            for (int v = 0; v < vertexCount; v++)
            {
                var vertex = input.Read <float3>();
                brushVertices.AddNoResize(vertex);
            }


            var surfaceOuterCount = input.Read <int>();

            surfaceLoopIndices = new NativeListArray <int>(surfaceOuterCount, allocator);
            surfaceLoopIndices.ResizeExact(surfaceOuterCount);
            for (int o = 0; o < surfaceOuterCount; o++)
            {
                var surfaceInnerCount = input.Read <int>();
                if (surfaceInnerCount > 0)
                {
                    var inner = surfaceLoopIndices.AllocateWithCapacityForIndex(o, surfaceInnerCount);
                    //inner.ResizeUninitialized(surfaceInnerCount);
                    for (int i = 0; i < surfaceInnerCount; i++)
                    {
                        inner.AddNoResize(input.Read <int>());
                    }
                }
            }

            var surfaceLoopCount = input.Read <int>();

            surfaceLoopAllInfos = new NativeList <SurfaceInfo>(surfaceLoopCount, allocator);
            surfaceLoopAllEdges = new NativeListArray <Edge>(surfaceLoopCount, allocator);

            surfaceLoopAllInfos.ResizeUninitialized(surfaceLoopCount);
            surfaceLoopAllEdges.ResizeExact(surfaceLoopCount);
            for (int l = 0; l < surfaceLoopCount; l++)
            {
                surfaceLoopAllInfos[l] = input.Read <SurfaceInfo>();
                var edgeCount = input.Read <int>();
                if (edgeCount > 0)
                {
                    var edgesInner = surfaceLoopAllEdges.AllocateWithCapacityForIndex(l, edgeCount);
                    //edgesInner.ResizeUninitialized(edgeCount);
                    for (int e = 0; e < edgeCount; e++)
                    {
                        edgesInner.AddNoResize(input.Read <Edge>());
                    }
                }
            }
            input.EndForEachIndex();



            var maxLoops   = 0;
            var maxIndices = 0;

            for (int s = 0; s < surfaceLoopIndices.Length; s++)
            {
                if (!surfaceLoopIndices.IsIndexCreated(s))
                {
                    continue;
                }
                var length = surfaceLoopIndices[s].Length;
                maxIndices += length;
                maxLoops    = math.max(maxLoops, length);
            }


            ref var baseSurfaces                = ref basePolygons[brushNodeIndex].Value.surfaces;