Пример #1
0
 public PlaneIntersection(CSGTreeBrushIntersection brushIntersection, CSGNode node, CSGModel model)
 {
     this.point = brushIntersection.surfaceIntersection.worldIntersection;
     this.plane = brushIntersection.surfaceIntersection.worldPlane;
     this.node  = node;
     this.model = model;
 }
Пример #2
0
    // Recursively remove all polygons in `polygons` that are inside this BSP
    // tree.
    public List <CSGPolygon> clipPolygons(List <CSGPolygon> polygons)
    {
        if (!validPlane)
        {
            return(new List <CSGPolygon>(polygons));
        }

        List <CSGPolygon> front = new List <CSGPolygon>();
        List <CSGPolygon> back  = new List <CSGPolygon>();

        for (int i = 0; i < polygons.Count; i++)
        {
            plane.splitPolygon(polygons[i], front, back, front, back);
        }

        if (this.front != null)
        {
            front = this.front.clipPolygons(front);
        }

        if (this.back != null)
        {
            back = this.back.clipPolygons(back);
        }
        else
        {
            back = new List <CSGPolygon>();
        }

        front.AddRange(back);

        return(front);
    }
Пример #3
0
        public static bool IsPartOfDefaultModel(UnityEngine.Object[] targetObjects)
        {
            if (targetObjects == null)
            {
                return(false);
            }

            for (int i = 0; i < targetObjects.Length; i++)
            {
                CSGNode node = targetObjects[i] as CSGNode;
                if (Equals(node, null))
                {
                    var gameObject = targetObjects[i] as GameObject;
                    if (gameObject)
                    {
                        node = gameObject.GetComponent <CSGNode>();
                    }
                }
                if (node)
                {
                    if (CSGGeneratedComponentManager.IsDefaultModel(node.hierarchyItem.Model))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        public static CSGNode GetTopMostGroupForNode(CSGNode node)
        {
            if (!node)
            {
                return(null);
            }

            var topSelected = node;
            var parent      = node.transform.parent;

            while (parent)
            {
                var model = parent.GetComponent <CSGModel>();
                if (model)
                {
                    break;
                }

                var parentOp = parent.GetComponent <CSGOperation>();
                if (parentOp &&
                    parentOp.HandleAsOne &&
                    !parentOp.PassThrough)
                {
                    topSelected = parentOp;
                }

                parent = parent.transform.parent;
            }
            return(topSelected);
        }
Пример #5
0
        public override CSGNode ToCSGNode(CSGNode parent, HashSet <CSGNode> animateNodes, bool ignoreAnimate)
        {
            var branch = new CSGNode(this.ID, Operator);

            branch.Parent           = parent;
            branch.LocalTranslation = this.Translation;
            if (parent != null)
            {
                branch.Translation = Vector3.Add(parent.Translation, branch.LocalTranslation);
            }
            else
            {
                branch.Translation = branch.LocalTranslation;
            }

            branch.Left  = Left.ToCSGNode(branch, animateNodes, Animate || ignoreAnimate);
            branch.Right = Right.ToCSGNode(branch, animateNodes, Animate || ignoreAnimate);

            if (Animate && !ignoreAnimate)
            {
                animateNodes.Add(branch);
            }

            return(branch);
        }
        private static CSGOperation GetGroupOperationForNode(CSGNode node)
        {
            if (!node)
            {
                return(null);
            }

            var parent = node.transform.parent;

            while (parent)
            {
                var model = parent.GetComponent <CSGModel>();
                if (model)
                {
                    return(null);
                }

                var parentOp = parent.GetComponent <CSGOperation>();
                if (parentOp &&
                    //!parentOp.PassThrough &&
                    parentOp.HandleAsOne)
                {
                    return(parentOp);
                }

                parent = parent.transform.parent;
            }
            return(null);
        }
 public SurfaceReference(CSGNode node, CSGBrushMeshAsset brushMeshAsset, int subNodeIndex, int subMeshIndex, int surfaceIndex, int surfaceID)
 {
     this.node           = node;
     this.brushMeshAsset = brushMeshAsset;
     this.subNodeIndex   = subNodeIndex;
     this.subMeshIndex   = subMeshIndex;
     this.surfaceIndex   = surfaceIndex;
     this.surfaceID      = surfaceID;
 }
Пример #8
0
 public static void UpdateChildTransformations(CSGNode node)
 {
     if (node.NodeType == CSGNodeType.Brush)
     {
         return;
     }
     UpdateChildTransformations(node.Left, node.Translation);
     UpdateChildTransformations(node.Right, node.Translation);
 }
        public static IChiselNodeDetails GetNodeDetails(CSGNode node)
        {
            IChiselNodeDetails someInterface;

            if (nodeDetailsLookup.TryGetValue(node.GetType(), out someInterface))
            {
                return(someInterface);
            }
            return(null);
        }
        public static GUIContent GetHierarchyIcon(CSGNode node)
        {
            IChiselNodeDetails someInterface;

            if (nodeDetailsLookup.TryGetValue(node.GetType(), out someInterface))
            {
                return(someInterface.GetHierarchyIconForGenericNode(node));
            }
            return(null);
        }
Пример #11
0
 public static void UpdateChildTransformations(CSGNode node, Vector3 parentTranslation)
 {
     node.Translation = Vector3.Add(parentTranslation, node.LocalTranslation);
     if (node.NodeType == CSGNodeType.Brush)
     {
         return;
     }
     UpdateChildTransformations(node.Left, node.Translation);
     UpdateChildTransformations(node.Right, node.Translation);
 }
Пример #12
0
        public static IRaycastGeometry <float3> Pipe(float radius = 1, float thickness = 0, string plane = "xy", float3?lowerBound = null, float3?upperBound = null)
        {
            if (thickness == 0)
            {
                return(Cylinder(radius, plane));
            }
            var cylinder1 = new CSGNode(Cylinder(radius, plane, lowerBound, upperBound));
            var cylinder2 = new CSGNode(Cylinder(radius + thickness, plane, lowerBound, upperBound));

            return(cylinder1 | cylinder2);
        }
Пример #13
0
        public static void UpdateBounds(CSGNode node)
        {
            if (node.NodeType != CSGNodeType.Brush)
            {
                var leftNode  = node.Left;
                var rightNode = node.Right;
                UpdateBounds(leftNode);
                UpdateBounds(rightNode);

                node.Bounds.Clear();
                node.Bounds.Add(leftNode.Bounds.Translated(Vector3.Subtract(leftNode.Translation, node.Translation)));
                node.Bounds.Add(rightNode.Bounds.Translated(Vector3.Subtract(rightNode.Translation, node.Translation)));
            }
        }
Пример #14
0
    // Remove all polygons in this BSP tree that are inside the other BSP tree
    // `bsp`.
    public void clipTo(CSGNode bsp)
    {
        this.polygons = bsp.clipPolygons(this.polygons);

        if (this.front != null)
        {
            this.front.clipTo(bsp);
        }

        if (this.back != null)
        {
            this.back.clipTo(bsp);
        }
    }
Пример #15
0
    // Return a new CSG solid representing space both this solid and in the
    // solid `csg`. Neither this solid nor the solid `csg` are modified.
    //
    //     A.intersect(B)
    //
    //     +-------+
    //     |       |
    //     |   A   |
    //     |    +--+----+   =   +--+
    //     +----+--+    |       +--+
    //          |   B   |
    //          |       |
    //          +-------+
    //
    public CSG intersect(CSG csg)
    {
        CSGNode a = new CSGNode(this.clone().polygons);
        CSGNode b = new CSGNode(csg.clone().polygons);

        a.invert();
        b.clipTo(a);
        b.invert();
        a.clipTo(b);
        b.clipTo(a);
        a.addPolygons(b.allPolygons());
        a.invert();
        return(CSG.fromPolygons(a.allPolygons()));
    }
        internal static void OnHierarchyWindowItemGUI(CSGNode node, Rect selectionRect)
        {
            // TODO: implement material drag & drop support on hierarchy items

            if (Event.current.type != EventType.Repaint)
            {
                return;
            }

            var icon = ChiselNodeDetailsManager.GetHierarchyIcon(node);

            if (icon != null)
            {
                RenderIcon(selectionRect, icon);
            }
        }
        internal static void Unregister(CSGNode node)
        {
            if (!registeredNodeLookup.Remove(node))
            {
                return;
            }

            var model = node as CSGModel;

            if (!ReferenceEquals(model, null))
            {
                componentGenerator.Unregister(model);
                sharedUnityMeshes.Unregister(model);
                registeredModels.Remove(model);
            }
        }
Пример #18
0
        public static IEnumerable <CSGNode> FindChildNodes(CSGNode node)
        {
            yield return(node);

            if (node.NodeType != CSGNodeType.Brush)
            {
                foreach (var child in FindChildNodes(node.Left))
                {
                    yield return(child);
                }
                foreach (var child in FindChildNodes(node.Right))
                {
                    yield return(child);
                }
            }
        }
Пример #19
0
    // Return a new CSG solid representing space in either this solid or in the
    // solid `csg`. Neither this solid nor the solid `csg` are modified.
    //
    //     A.union(B)
    //
    //     +-------+            +-------+
    //     |       |            |       |
    //     |   A   |            |       |
    //     |    +--+----+   =   |       +----+
    //     +----+--+    |       +----+       |
    //          |   B   |            |       |
    //          |       |            |       |
    //          +-------+            +-------+
    //
    public CSG union(CSG csg)
    {
        CSGNode a = new CSGNode(this.clone().polygons);
        CSGNode b = new CSGNode(csg.clone().polygons);

        a.clipTo(b);
        b.clipTo(a);
        b.invert();
        b.clipTo(a);
        b.invert();

        List <CSGPolygon> result = a.allPolygons();

        result.AddRange(b.allPolygons());

        return(CSG.fromPolygons(result));
    }
Пример #20
0
 public static IEnumerable <CSGNode> FindChildBrushes(CSGNode node)
 {
     if (node.NodeType != CSGNodeType.Brush)
     {
         foreach (var brush in FindChildBrushes(node.Left))
         {
             yield return(brush);
         }
         foreach (var brush in FindChildBrushes(node.Right))
         {
             yield return(brush);
         }
         yield break;
     }
     else
     {
         yield return(node);
     }
 }
Пример #21
0
    // Build a BSP tree out of `polygons`. When called on an existing tree, the
    // new polygons are filtered down to the bottom of the tree and become new
    // nodes there. Each set of polygons is partitioned using the first polygon
    // (no heuristic is used to pick a good split).
    public void addPolygons(List <CSGPolygon> polygons)
    {
        if (polygons.Count == 0)
        {
            return;
        }

        if (!validPlane)
        {
            this.plane = polygons[0].plane;
            validPlane = true;
        }

        List <CSGPolygon> front = new List <CSGPolygon>();
        List <CSGPolygon> back  = new List <CSGPolygon>();

        for (int i = 0; i < polygons.Count; i++)
        {
            this.plane.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
        }

        if (front.Count > 0)
        {
            if (this.front == null)
            {
                this.front = new CSGNode();
            }

            this.front.addPolygons(front);
        }

        if (back.Count > 0)
        {
            if (this.back == null)
            {
                this.back = new CSGNode();
            }

            this.back.addPolygons(back);
        }
    }
Пример #22
0
        public override CSGNode ToCSGNode(CSGNode parent, HashSet <CSGNode> animateNodes, bool ignoreAnimate)
        {
            var leaf = new CSGNode(this.ID, Planes);

            leaf.Parent           = parent;
            leaf.LocalTranslation = this.Translation;
            if (parent != null)
            {
                leaf.Translation = Vector3.Add(parent.Translation, leaf.LocalTranslation);
            }
            else
            {
                leaf.Translation = leaf.LocalTranslation;
            }

            if (Animate && !ignoreAnimate)
            {
                animateNodes.Add(leaf);
            }

            return(leaf);
        }
Пример #23
0
    public CSGNode clone()
    {
        CSGNode node = new CSGNode();

        node.plane      = plane;
        node.validPlane = validPlane;

        if (front != null)
        {
            node.front = front.clone();
        }

        if (back != null)
        {
            node.back = back.clone();
        }

        for (int i = 0; i < polygons.Count; i++)
        {
            node.polygons.Add(polygons[i].clone());
        }

        return(node);
    }
Пример #24
0
    // Convert solid space to empty space and empty space to solid space.
    public void invert()
    {
        for (int i = 0; i < polygons.Count; i++)
        {
            polygons[i].flip();
        }

        plane.flip();

        if (front != null)
        {
            front.invert();
        }

        if (back != null)
        {
            back.invert();
        }

        CSGNode temp = front;

        front = back;
        back  = temp;
    }
Пример #25
0
 GUIContent IChiselNodeDetails.GetHierarchyIconForGenericNode(CSGNode node)
 {
     return(GetHierarchyIcon((T)node));
 }
Пример #26
0
        internal static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGModel model, out CSGNode node, out CSGTreeBrushIntersection intersection)
        {
TryNextSelection:
            intersection = new CSGTreeBrushIntersection {
                surfaceID = -1, brushUserID = -1
            };

            model = null;
            node  = null;
            Material sharedMaterial;
            var      gameObject = PickModel(camera, pickposition, layers, ref ignore, ref filter, out model, out sharedMaterial);

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (model)
            {
                int filterLayerParameter0 = (sharedMaterial) ? sharedMaterial.GetInstanceID() : 0;
                {
                    var worldRay       = camera.ScreenPointToRay(pickposition);
                    var worldRayStart  = worldRay.origin;
                    var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
                    var worldRayEnd    = worldRayStart + worldRayVector;

                    CSGTreeBrushIntersection tempIntersection;
                    if (CSGSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out tempIntersection))
                    {
                        var clickedBrush = tempIntersection.brush;
                        node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(clickedBrush.UserID);
                        if (node)
                        {
                            if (ignore != null &&
                                ignore.Contains(node.gameObject))
                            {
                                node = null;
                                return(null);
                            }
                            intersection = tempIntersection;
                            return(node.gameObject);
                        }
                        else
                        {
                            node = null;
                        }
                    }
                }

                if (ignore == null)
                {
                    return(null);
                }

                ArrayUtility.Add(ref ignore, gameObject);
                goto TryNextSelection;
            }

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (ignore != null &&
                ignore.Contains(gameObject))
            {
                return(null);
            }

            return(gameObject);
        }
        // Logical OR set operation on polygons
        //
        // Table showing final output from combination of categorization of left and right node
        //
        //                  | right node
        //                  | inside    aligned     r-aligned   outside
        // -----------------+------------------------------------------
        // left  inside     | I         I           I           I
        // node  aligned    | I         A           I           A
        //       r-aligned  | I         I           R           R
        //       outside    | I         A           R           O
        //
        // I = inside   A = aligned
        // O = outside  R = reverse aligned
        //
        #region LogicalOr
        static void LogicalOr(CSGNode processedNode,
                              CSGMesh processedMesh,

                              CSGNode categorizationNode,

                              List <Polygon> inputPolygons,

                              List <Polygon> inside,
                              List <Polygon> aligned,
                              List <Polygon> revAligned,
                              List <Polygon> outside,

                              bool inverseLeft,
                              bool inverseRight)
        {
            var leftNode        = categorizationNode.Left;
            var rightNode       = categorizationNode.Right;
            var defaultCapacity = inputPolygons.Count / 2;

            // ... Allocations are ridiculously cheap in .NET, there is a garbage collection penalty however.
            // CSG can be performed without temporary buffers and recursion by using flags,
            // which would increase performance and scalability (garbage collection interfers with parallelization).
            // It makes the code a lot harder to read however.
            var leftAligned    = new List <Polygon>(defaultCapacity);
            var leftRevAligned = new List <Polygon>(defaultCapacity);
            var leftOutside    = new List <Polygon>(defaultCapacity);

            //var leftInside	= new List<Polygon>(defaultCapacity); // everything that's inside the left node
            // is always part of the inside category

            // First categorize polygons in left path ...
            if (inverseLeft)
            {
                Categorize(processedNode, processedMesh, leftNode,
                           inputPolygons,
                           leftOutside, leftRevAligned, leftAligned, inside);
            }
            else
            {
                Categorize(processedNode, processedMesh, leftNode,
                           inputPolygons,
                           inside, leftAligned, leftRevAligned, leftOutside);
            }

            // ... Then categorize the polygons in the right path
            // Note that no single polygon will go into more than one of the Categorize methods below
            if (inverseRight)
            {
                if (leftAligned.Count > 0)
                {
                    if (inside == aligned)
                    {
                        inside.AddRange(leftAligned);
                    }
                    else
                    {
                        Categorize(processedNode, processedMesh, rightNode,
                                   leftAligned,
                                   aligned, inside, aligned, inside);
                    }
                }

                if (leftRevAligned.Count > 0)
                {
                    if (inside == revAligned)
                    {
                        inside.AddRange(leftRevAligned);
                    }
                    else
                    {
                        Categorize(processedNode, processedMesh, rightNode,
                                   leftRevAligned,
                                   revAligned, revAligned, inside, inside);
                    }
                }

                if (leftOutside.Count > 0)
                {
                    Categorize(processedNode, processedMesh, rightNode,
                               leftOutside,
                               outside, revAligned, aligned, inside);
                }
            }
            else
            {
                if (leftAligned.Count > 0)
                {
                    if (inside == aligned)
                    {
                        inside.AddRange(leftAligned);
                    }
                    else
                    {
                        Categorize(processedNode, processedMesh, rightNode,
                                   leftAligned,
                                   inside, aligned, inside, aligned);
                    }
                }

                if (leftRevAligned.Count > 0)
                {
                    if (inside == revAligned)
                    {
                        inside.AddRange(leftRevAligned);
                    }
                    else
                    {
                        Categorize(processedNode, processedMesh, rightNode,
                                   leftRevAligned,
                                   inside, inside, revAligned, revAligned);
                    }
                }

                if (leftOutside.Count > 0)
                {
                    Categorize(processedNode, processedMesh, rightNode,
                               leftOutside,
                               inside, aligned, revAligned, outside);
                }
            }
        }
Пример #28
0
 public SelectedNode(CSGNode node, Transform transform)
 {
     this.node = node; this.transform = transform;
 }
        public static ConcurrentDictionary <CSGNode, CSGMesh> ProcessCSGNodes(CSGNode root, IEnumerable <CSGNode> nodes)
        {
            var meshes    = new ConcurrentDictionary <CSGNode, CSGMesh>();
            var buildMesh =
                (Action <CSGNode>)
                delegate(CSGNode node)
            {
                CSGMesh mesh;
                if (!cachedBaseMeshes.TryGetValue(node, out mesh))
                {
                    // If the node we're performing csg on is a brush, we simply create the geometry from the planes
                    // If the node is a more complicated node, we perform csg on it's child nodes and combine the
                    // meshes that are created.
                    // Note that right now we cache brushes per node, but we can improve on this by caching on
                    // node type instead. Since lots of nodes will have the same geometry in real life and only
                    // need to be created once. It won't help much in runtime performance considering they're
                    // cached anyway, but it'll save on memory usage.
                    if (node.NodeType != CSGNodeType.Brush)
                    {
                        var childNodes  = CSGUtility.FindChildBrushes(node);
                        var brushMeshes = ProcessCSGNodes(node, childNodes);
                        mesh = CSGMesh.Combine(node.Translation, brushMeshes);
                    }
                    else
                    {
                        mesh = CSGMesh.CreateFromPlanes(node.Planes);
                    }

                    // Cache the mesh
                    cachedBaseMeshes[node] = mesh;
                }

                // Clone the cached mesh so we can perform CSG on it.
                var clonedMesh = mesh.Clone();
                node.Bounds.Set(clonedMesh.Bounds);
                meshes[node] = clonedMesh;
            };

            var updateDelegate =
                (Action <KeyValuePair <CSGNode, CSGMesh> >)
                delegate(KeyValuePair <CSGNode, CSGMesh> item)
            {
                var processedNode = item.Key;
                var processedMesh = item.Value;

                var inputPolygons    = processedMesh.Polygons;
                var insidePolygons   = new List <Polygon>(inputPolygons.Count);
                var outsidePolygons  = new List <Polygon>(inputPolygons.Count);
                var alignedPolygons  = new List <Polygon>(inputPolygons.Count);
                var reversedPolygons = new List <Polygon>(inputPolygons.Count);

                CSGCategorization.Categorize(processedNode,
                                             processedMesh,

                                             root,

                                             inputPolygons,                                                             // these are the polygons that are categorized

                                             insidePolygons,
                                             alignedPolygons,
                                             reversedPolygons,
                                             outsidePolygons
                                             );

                // Flag all non aligned polygons as being invisible, and store their categorizations
                // so we can use it if we instance this mesh.
                foreach (var polygon in insidePolygons)
                {
                    polygon.Category = PolygonCategory.Inside;
                    polygon.Visible  = false;
                }

                foreach (var polygon in outsidePolygons)
                {
                    polygon.Category = PolygonCategory.Outside;
                    polygon.Visible  = false;
                }

                foreach (var polygon in alignedPolygons)
                {
                    polygon.Category = PolygonCategory.Aligned;
                }

                foreach (var polygon in reversedPolygons)
                {
                    polygon.Category = PolygonCategory.ReverseAligned;
                }
            };


            //
            // Here we run build the meshes and perform csg on them either in serial or parallel
            //

            /*
             * foreach (var node in nodes)
             *      buildMesh(node);
             * CSGUtility.UpdateBounds(root);
             * foreach (var item in meshes)
             *      updateDelegate(item);
             * /*/

            Parallel.ForEach(nodes, buildMesh);

            CSGUtility.UpdateBounds(root);

            Parallel.ForEach(meshes, updateDelegate);

            //*/
            return(meshes);
        }
Пример #30
0
 public abstract CSGNode ToCSGNode(CSGNode parent, HashSet <CSGNode> animateNodes, bool ignoreAnimate);