Ejemplo n.º 1
0
        public void Init()
        {
            CompactHierarchyManager.Clear();
            BrushMeshFactory.CreateBox(Vector3.one, 0, out var brushMesh);
            var surfaceDefinition = new ChiselSurfaceDefinition();

            surfaceDefinition.EnsureSize(6);
            var brushMeshHash = BrushMeshManager.RegisterBrushMesh(brushMesh, surfaceDefinition);

            dummyBrushMeshInstance = new BrushMeshInstance {
                brushMeshHash = brushMeshHash
            };
        }
Ejemplo n.º 2
0
        // For each brush

        // 1D:
        // Find surfaces that intersect with ray
        // Find edges on that surface, if intersection is close enough to edge, find closest point on edge
        static void FindSnapPointsAlongRay(GameObject[] selection, Vector3 worldRayStart, Vector3 worldRayDirection, List <SurfaceSnap> allSurfaceSnapEvents, List <EdgeSnap> allEdgeSnapEvents, List <VertexSnap> allVertexSnapEvents)
        {
            if (selection == null || selection.Length == 0)
            {
                return;
            }

            if (allSurfaceSnapEvents == null &&
                allEdgeSnapEvents == null &&
                allVertexSnapEvents == null)
            {
                return;
            }

            s_FoundIntersections.Clear();
            if (ChiselSceneQuery.FindFirstWorldIntersection(s_FoundIntersections, worldRayStart - worldRayDirection, worldRayStart + worldRayDirection, filter: selection))
            {
                if (allSurfaceSnapEvents != null)
                {
                    for (int i = 0; i < s_FoundIntersections.Count; i++)
                    {
                        var intersection = s_FoundIntersections[i];
                        allSurfaceSnapEvents.Add(new SurfaceSnap
                        {
                            brush        = intersection.brushIntersection.brush,
                            surfaceIndex = intersection.brushIntersection.surfaceIndex,
                            intersection = intersection.worldPlaneIntersection,
                            normal       = intersection.worldPlane.normal,
                        });
                    }
                }
            }

            if (allEdgeSnapEvents == null && allVertexSnapEvents == null)
            {
                return;
            }

            foreach (var intersection in s_FoundIntersections)
            {
                var csgBrush      = intersection.brushIntersection.brush;
                var csgTree       = intersection.brushIntersection.tree;
                var brushMeshBlob = BrushMeshManager.GetBrushMeshBlob(csgBrush.BrushMesh);
                if (!brushMeshBlob.IsCreated)
                {
                    continue;
                }

                ref var brushMesh = ref brushMeshBlob.Value;
                ref var polygons  = ref brushMesh.polygons;
Ejemplo n.º 3
0
        static bool GetAllMaterials(CSGTreeBrush brush, CSGTreeBrush findBrush, List <ChiselBrushMaterial> brushMaterials)
        {
            if (findBrush != brush)
            {
                return(false);
            }

            var brushMeshBlob = BrushMeshManager.GetBrushMeshBlob(brush.BrushMesh.BrushMeshID);

            if (!brushMeshBlob.IsCreated)
            {
                return(true);
            }

            ref var brushMesh = ref brushMeshBlob.Value;
Ejemplo n.º 4
0
        static bool FindSurfaceReference(ChiselNode chiselNode, CSGTreeBrush brush, CSGTreeBrush findBrush, int surfaceID, out SurfaceReference surfaceReference)
        {
            surfaceReference = null;
            if (findBrush != brush)
            {
                return(false);
            }

            var brushMeshBlob = BrushMeshManager.GetBrushMeshBlob(findBrush.BrushMesh.BrushMeshID);

            if (!brushMeshBlob.IsCreated)
            {
                return(true);
            }

            ref var brushMesh = ref brushMeshBlob.Value;
Ejemplo n.º 5
0
        static bool GetAllSurfaces(ChiselNode chiselNode, CSGTreeBrush brush, CSGTreeBrush?findBrush, List <SurfaceReference> surfaces)
        {
            if (!brush.Valid)
            {
                return(false);
            }

            if (findBrush.HasValue && findBrush.Value != brush)
            {
                return(true);
            }

            var brushMeshBlob = BrushMeshManager.GetBrushMeshBlob(brush.BrushMesh.BrushMeshID);

            if (!brushMeshBlob.IsCreated)
            {
                return(true);
            }

            ref var brushMesh = ref brushMeshBlob.Value;
Ejemplo n.º 6
0
        static void FindClosestSnapPointsToPlane(GameObject[] selection, Vector3 startWorldPoint, Vector3 currentWorldPoint, Grid worldSlideGrid, float maxSnapDistance, List <SurfaceSnap> allSurfaceSnapEvents, List <EdgeSnap> allEdgeSnapEvents, List <VertexSnap> allVertexSnapEvents)
        {
            if (selection == null || selection.Length == 0)
            {
                return;
            }

            if (allSurfaceSnapEvents == null &&
                allEdgeSnapEvents == null &&
                allVertexSnapEvents == null)
            {
                return;
            }

            var worldSlidePlane = worldSlideGrid.PlaneXZ;

            var gridSnapping = Snapping.GridSnappingActive;

            if (gridSnapping)
            {
                var vectorX = worldSlideGrid.Right * maxSnapDistance;
                var vectorZ = worldSlideGrid.Forward * maxSnapDistance;

                var snappedWorldPoint = Snapping.SnapPoint(currentWorldPoint, worldSlideGrid);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorX, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorZ, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);

                snappedWorldPoint = Snapping.SnapPoint(startWorldPoint, worldSlideGrid);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorX, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
                FindSnapPointsAlongRay(selection, snappedWorldPoint, vectorZ, allSurfaceSnapEvents, allEdgeSnapEvents, allVertexSnapEvents);
            }


            worldSlidePlane = new Plane(worldSlidePlane.normal, currentWorldPoint);

            s_SelectedBrushes.Clear();
            foreach (var go in selection)
            {
                if (!go)
                {
                    continue;
                }

                var node = go.GetComponent <ChiselNode>();
                if (!node)
                {
                    continue;
                }

                s_SelectedNodes.Clear();
                node.CollectCSGTreeNodes(s_SelectedNodes);
                foreach (var child in s_SelectedNodes)
                {
                    if (!child.Valid || child.Type != CSGNodeType.Brush)
                    {
                        continue;
                    }
                    s_SelectedBrushes.Add((CSGTreeBrush)child);
                }
            }

            if (s_SelectedBrushes.Count == 0)
            {
                return;
            }

            var snapDistanceSqr = maxSnapDistance * maxSnapDistance;

            EdgeSnap[] foundEdges = new EdgeSnap[2];
            int        foundEdgeCount;

            foreach (var csgBrush in s_SelectedBrushes)
            {
                var csgTree   = csgBrush.Tree;
                var brushMesh = BrushMeshManager.GetBrushMesh(csgBrush.BrushMesh);
                var polygons  = brushMesh.polygons;
                var halfEdges = brushMesh.halfEdges;
                var vertices  = brushMesh.vertices;
                var planes    = brushMesh.planes;
                var halfEdgePolygonIndices = brushMesh.halfEdgePolygonIndices;

                // TODO: store this information with brush
                var model       = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(csgTree.UserID) as ChiselModel;
                var worldToNode = csgBrush.TreeToNodeSpaceMatrix * model.hierarchyItem.WorldToLocalMatrix;
                var nodeToWorld = model.hierarchyItem.LocalToWorldMatrix * csgBrush.NodeToTreeSpaceMatrix;

                var brushPoint = worldToNode.MultiplyPoint(currentWorldPoint);
                var brushPlane = worldToNode.TransformPlane(worldSlidePlane);

                if (allVertexSnapEvents != null)
                {
                    if (gridSnapping)
                    {
                        for (int i = 0; i < vertices.Length; i++)
                        {
                            var vertex = vertices[i];
                            var dist0  = brushPlane.GetDistanceToPoint(vertex);
                            if (math.abs(dist0) > snapDistanceSqr)
                            {
                                continue;
                            }
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                vertexIndex  = i,
                                intersection = nodeToWorld.MultiplyPoint(vertex)
                            });
                        }
                    }
                    else
                    {
                        for (int i = 0; i < vertices.Length; i++)
                        {
                            var vertex = vertices[i];
                            if (math.lengthsq(vertex - (float3)brushPoint) > snapDistanceSqr)
                            {
                                continue;
                            }
                            var dist0 = brushPlane.GetDistanceToPoint(vertex);
                            if (math.abs(dist0) > snapDistanceSqr)
                            {
                                continue;
                            }
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                vertexIndex  = i,
                                intersection = nodeToWorld.MultiplyPoint(vertex)
                            });
                        }
                    }
                }


                if (allSurfaceSnapEvents == null &&
                    allEdgeSnapEvents == null)
                {
                    continue;
                }


                for (int surfaceIndex = 0; surfaceIndex < polygons.Length; surfaceIndex++)
                {
                    var polygon   = polygons[surfaceIndex];
                    var firstEdge = polygon.firstEdge;
                    var lastEdge  = firstEdge + polygon.edgeCount;

                    // TODO: If point is ON plane, ignore. We don't want to "snap" to every point on that surface b/c then we won't be snapping at all

                    foundEdgeCount = 0;
                    for (int e0 = lastEdge - 1, e1 = firstEdge; e1 < lastEdge; e0 = e1, e1++)
                    {
                        var i0 = halfEdges[e0].vertexIndex;
                        var i1 = halfEdges[e1].vertexIndex;

                        var vertex0 = vertices[i0];
                        var vertex1 = vertices[i1];

                        var distance0 = brushPlane.GetDistanceToPoint(vertex0);
                        var distance1 = brushPlane.GetDistanceToPoint(vertex1);

                        // Edge is plane aligned
                        if (math.abs(distance0) < kPlaneDistanceEpsilon &&
                            math.abs(distance1) < kPlaneDistanceEpsilon)
                        {
                            if (i0 < i1 && // skip duplicate edges
                                allEdgeSnapEvents != null)
                            {
                                if (gridSnapping)
                                {
                                }
                                else
                                {
                                    if (ClosestPointToLine(brushPoint, vertex0, vertex1, out Vector3 newVertex))
                                    {
                                        allEdgeSnapEvents.Add(new EdgeSnap
                                        {
                                            brush         = csgBrush,
                                            surfaceIndex0 = surfaceIndex,
                                            surfaceIndex1 = halfEdgePolygonIndices[halfEdges[e1].twinIndex],
                                            vertexIndex0  = i0,
                                            vertexIndex1  = i1,
                                            intersection  = nodeToWorld.MultiplyPoint(newVertex),
                                            from          = nodeToWorld.MultiplyPoint(vertex0),
                                            to            = nodeToWorld.MultiplyPoint(vertex1)
                                        });
                                    }
                                }
                            }
                            continue;
                        }

                        {
                            if ((distance0 < -snapDistanceSqr && distance1 < -snapDistanceSqr) ||
                                (distance0 > snapDistanceSqr && distance1 > snapDistanceSqr))
                            {
                                continue;
                            }

                            // TODO: Find intersection between plane and edge
                            var vector = vertex0 - vertex1;
                            var length = distance0 - distance1;
                            var delta  = distance0 / length;

                            if (float.IsNaN(delta) || float.IsInfinity(delta))
                            {
                                continue;
                            }

                            var newVertex = (Vector3)(vertex0 - (vector * delta));
                            var distanceN = brushPlane.GetDistanceToPoint(newVertex);

                            if ((distanceN <= distance0 && distanceN <= distance1) ||
                                (distanceN >= distance0 && distanceN >= distance1))
                            {
                                continue;
                            }

                            if ((newVertex - brushPoint).sqrMagnitude > snapDistanceSqr)
                            {
                                continue;
                            }

                            foundEdges[foundEdgeCount] = new EdgeSnap
                            {
                                brush         = csgBrush,
                                surfaceIndex0 = surfaceIndex,
                                surfaceIndex1 = halfEdgePolygonIndices[halfEdges[e1].twinIndex],
                                vertexIndex0  = i0,
                                vertexIndex1  = i1,
                                intersection  = nodeToWorld.MultiplyPoint(newVertex),
                                from          = nodeToWorld.MultiplyPoint(vertex0),
                                to            = nodeToWorld.MultiplyPoint(vertex1)
                            };
                            if (i0 < i1 && // skip duplicate edges
                                allEdgeSnapEvents != null)
                            {
                                allEdgeSnapEvents.Add(foundEdges[foundEdgeCount]);
                            }

                            foundEdgeCount++;
                            if (foundEdgeCount == 2)
                            {
                                break;
                            }
                        }
                    }

                    if (allSurfaceSnapEvents != null && foundEdgeCount > 0 && !gridSnapping)
                    {
                        if (foundEdgeCount == 2)
                        {
                            var plane      = planes[surfaceIndex];
                            var unityPlane = new Plane(plane.xyz, plane.w);

                            var vertex0 = foundEdges[0].intersection;
                            var vertex1 = foundEdges[1].intersection;

                            if (ClosestPointToLine(currentWorldPoint, vertex0, vertex1, out Vector3 closestWorldPoint))
                            {
                                allSurfaceSnapEvents.Add(new SurfaceSnap
                                {
                                    brush        = csgBrush,
                                    surfaceIndex = surfaceIndex,
                                    intersection = closestWorldPoint,
                                    normal       = nodeToWorld.MultiplyVector(unityPlane.normal),
                                });
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
        // For each brush

        // 1D:
        // Find surfaces that intersect with ray
        // Find edges on that surface, if intersection is close enough to edge, find closest point on edge
        static void FindSnapPointsAlongRay(GameObject[] selection, Vector3 worldRayStart, Vector3 worldRayDirection, List <SurfaceSnap> allSurfaceSnapEvents, List <EdgeSnap> allEdgeSnapEvents, List <VertexSnap> allVertexSnapEvents)
        {
            if (selection == null || selection.Length == 0)
            {
                return;
            }

            if (allSurfaceSnapEvents == null &&
                allEdgeSnapEvents == null &&
                allVertexSnapEvents == null)
            {
                return;
            }

            s_FoundIntersections.Clear();
            if (ChiselSceneQuery.FindFirstWorldIntersection(s_FoundIntersections, worldRayStart - worldRayDirection, worldRayStart + worldRayDirection, filter: selection))
            {
                if (allSurfaceSnapEvents != null)
                {
                    for (int i = 0; i < s_FoundIntersections.Count; i++)
                    {
                        var intersection = s_FoundIntersections[i];
                        allSurfaceSnapEvents.Add(new SurfaceSnap
                        {
                            brush        = intersection.brushIntersection.brush,
                            surfaceIndex = intersection.brushIntersection.surfaceIndex,
                            intersection = intersection.worldPlaneIntersection,
                            normal       = intersection.worldPlane.normal,
                        });
                    }
                }
            }

            if (allEdgeSnapEvents == null && allVertexSnapEvents == null)
            {
                return;
            }

            foreach (var intersection in s_FoundIntersections)
            {
                var csgBrush  = intersection.brushIntersection.brush;
                var csgTree   = intersection.brushIntersection.tree;
                var brushMesh = BrushMeshManager.GetBrushMesh(csgBrush.BrushMesh);
                var polygons  = brushMesh.polygons;
                var halfEdges = brushMesh.halfEdges;
                var vertices  = brushMesh.vertices;
                var halfEdgePolygonIndices = brushMesh.halfEdgePolygonIndices;

                var model       = ChiselNodeHierarchyManager.FindChiselNodeByInstanceID(csgTree.UserID) as ChiselModel;
                var worldToNode = csgBrush.TreeToNodeSpaceMatrix * model.hierarchyItem.WorldToLocalMatrix;
                var nodeToWorld = model.hierarchyItem.LocalToWorldMatrix * csgBrush.NodeToTreeSpaceMatrix;

                var brushRayStart     = worldToNode.MultiplyPoint(worldRayStart);
                var brushRayDirection = worldToNode.MultiplyVector(worldRayDirection).normalized;

                var surfaceIndex = intersection.brushIntersection.surfaceIndex;

                var polygon   = polygons[surfaceIndex];
                var firstEdge = polygon.firstEdge;
                var lastEdge  = firstEdge + polygon.edgeCount;
                for (int e0 = lastEdge - 1, e1 = firstEdge; e1 < lastEdge; e0 = e1, e1++)
                {
                    var i0 = halfEdges[e0].vertexIndex;
                    var i1 = halfEdges[e1].vertexIndex;

                    var v0 = vertices[i0];
                    var v1 = vertices[i1];

                    var result = ClosestPointsBetweenTwoLines(brushRayStart, brushRayDirection, v0, v1, out Vector3 A, out Vector3 B);
                    if (result == ClosestLineResult.None)
                    {
                        continue;
                    }

                    if (result == ClosestLineResult.Aligned)
                    {
                        // TODO: draw edge as being intersecting if we're on the edge right now
                        continue;
                    }


                    var dist = (A - B).magnitude;
                    if (dist > kEdgeDistanceEpsilon)
                    {
                        continue;
                    }

                    if (allVertexSnapEvents != null)
                    {
                        var vertDist = ((Vector3)v0 - B).magnitude;
                        if (vertDist < kVertexDistanceEpsilon)
                        {
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                surfaceIndex = surfaceIndex,
                                vertexIndex  = i0,
                                intersection = nodeToWorld.MultiplyPoint(v0)
                            });
                        }
                        vertDist = ((Vector3)v1 - B).magnitude;
                        if (vertDist < kVertexDistanceEpsilon)
                        {
                            allVertexSnapEvents.Add(new VertexSnap
                            {
                                brush        = csgBrush,
                                surfaceIndex = surfaceIndex,
                                vertexIndex  = i1,
                                intersection = nodeToWorld.MultiplyPoint(v1)
                            });
                        }
                    }

                    if (allEdgeSnapEvents != null)
                    {
                        allEdgeSnapEvents.Add(new EdgeSnap
                        {
                            brush         = csgBrush,
                            surfaceIndex0 = surfaceIndex,
                            surfaceIndex1 = halfEdgePolygonIndices[halfEdges[e1].twinIndex],
                            vertexIndex0  = i0,
                            vertexIndex1  = i1,
                            intersection  = nodeToWorld.MultiplyPoint(B),
                            from          = nodeToWorld.MultiplyPoint(v0),
                            to            = nodeToWorld.MultiplyPoint(v1)
                        });
                    }
                }
            }
        }