//[MethodImpl(MethodImplOptions.NoInlining)]
        void FindIntersectionVertices(ref BlobArray <float4> intersectingPlanes0,
                                      ref BlobArray <float4> intersectingPlanes1,
                                      ref BlobArray <PlanePair> usedPlanePairs1,
                                      ref BlobArray <int> intersectingPlaneIndices0,
                                      float4x4 nodeToTreeSpaceMatrix0,
                                      //ref HashedVertices              hashedVertices,
                                      NativeArray <PlaneVertexIndexPair> foundIndices0,
                                      ref int foundIndices0Length,
                                      NativeArray <PlaneVertexIndexPair> foundIndices1,
                                      ref int foundIndices1Length)
        {
            var foundVertices      = new NativeArray <float4>(usedPlanePairs1.Length * intersectingPlanes0.Length, Allocator.Temp);
            var foundEdges         = new NativeArray <IntersectionEdge>(usedPlanePairs1.Length * intersectingPlanes0.Length, Allocator.Temp);
            var foundIntersections = new NativeArray <IntersectionPlanes>(usedPlanePairs1.Length * intersectingPlanes0.Length, Allocator.Temp);
            var n = 0;

            for (int i = 0; i < usedPlanePairs1.Length; i++)
            {
                for (int j = 0; j < intersectingPlanes0.Length; j++)
                {
                    foundIntersections[n] = new IntersectionPlanes
                    {
                        plane0      = usedPlanePairs1[i].plane0,
                        plane1      = usedPlanePairs1[i].plane1,
                        plane2      = intersectingPlanes0[j],
                        planeIndex0 = usedPlanePairs1[i].planeIndex0,
                        planeIndex1 = usedPlanePairs1[i].planeIndex1,
                        planeIndex2 = intersectingPlaneIndices0[j]
                    };

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

                    var plane0 = usedPlanePairs1[i].plane0;
                    var plane1 = usedPlanePairs1[i].plane1;
                    var plane2 = intersectingPlanes0[j];

                    foundVertices[n] = new float4(PlaneExtensions.Intersection(plane2, plane0, plane1), 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)) <= kDistanceEpsilon &&
                    math.abs(math.dot(plane2, edgeVertex1)) <= kDistanceEpsilon)
                {
                    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(ref intersectingPlanes0, foundVertices[k]) ||
                    IsOutsidePlanes(ref intersectingPlanes1, 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;
                var vertexIndex     = hashedVertices.AddNoResize(treeSpaceVertex);

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

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

                foundIndices1[foundIndices1Length] = new PlaneVertexIndexPair {
                    planeIndex = planeIndex1, vertexIndex = vertexIndex
                };
                foundIndices1Length++;
            }
        }
        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 :;
                }
            }
        }
Ejemplo n.º 3
0
        public float3 GetVertexFromIntersectingPlanes(int vertexIndex)
        {
            sSnapPlaneIndices.Clear();
            // TODO: precalculate this somehow
            for (int e = 0; e < halfEdges.Length; e++)
            {
                if (halfEdges[e].vertexIndex != vertexIndex)
                {
                    continue;
                }

                sSnapPlaneIndices.Add(halfEdgePolygonIndices[e]);
            }

            if (sSnapPlaneIndices.Count < 3)
            {
                return(vertices[vertexIndex]);
            }

            sSnapPlanes.Clear();
            sSnapPlaneIndices.Sort();
            for (int i = 0; i < sSnapPlaneIndices.Count; i++)
            {
                sSnapPlanes.Add(planes[sSnapPlaneIndices[i]]);
            }

            // most common case
            if (sSnapPlanes.Count == 3)
            {
                var vertex = (float3)PlaneExtensions.Intersection(sSnapPlanes[0], sSnapPlanes[1], sSnapPlanes[2]);
                if (double.IsNaN(vertex.x) || double.IsInfinity(vertex.x) ||
                    double.IsNaN(vertex.y) || double.IsInfinity(vertex.y) ||
                    double.IsNaN(vertex.z) || double.IsInfinity(vertex.z))
                {
                    Debug.LogWarning("NaN");
                    return(vertices[vertexIndex]);
                }
                return(vertex);
            }

            double3 snappedVertex      = double3.zero;
            int     snappedVertexCount = 0;

            for (int a = 0; a < sSnapPlanes.Count - 2; a++)
            {
                for (int b = a + 1; b < sSnapPlanes.Count - 1; b++)
                {
                    for (int c = b + 1; c < sSnapPlanes.Count; c++)
                    {
                        // TODO: accumulate in a better way
                        var vertex = PlaneExtensions.Intersection(sSnapPlanes[a], sSnapPlanes[b], sSnapPlanes[c]);
                        if (double.IsNaN(vertex.x) || double.IsInfinity(vertex.x) ||
                            double.IsNaN(vertex.y) || double.IsInfinity(vertex.y) ||
                            double.IsNaN(vertex.z) || double.IsInfinity(vertex.z))
                        {
                            continue;
                        }

                        snappedVertex += vertex;
                        snappedVertexCount++;
                    }
                }
            }

            var finalVertex = (snappedVertex / snappedVertexCount);

            if (double.IsNaN(finalVertex.x) || double.IsInfinity(finalVertex.x) ||
                double.IsNaN(finalVertex.y) || double.IsInfinity(finalVertex.y) ||
                double.IsNaN(finalVertex.z) || double.IsInfinity(finalVertex.z))
            {
                Debug.LogWarning("NaN");
                return(vertices[vertexIndex]);
            }
            return((float3)finalVertex);
        }