Example #1
0
        // Create meshes for a given number of nodes and perform CSG on these.
        #region ProcessCSGNodes

        private static void ProcessNode(CSGNode node, CSGNode root)
        {
            if (node.cachedMesh == null)
            {
                if (node.NodeType != CSGNodeType.Brush)
                {
                    ProcessNode(node.Left, node);
                    ProcessNode(node.Right, node);
                    node.cachedMesh = CSGMesh.Combine(node.Translation, node.Left, node.Right);

                    node.Bounds.Clear();
                    node.Bounds.Add(node.Left.Bounds.Translated(Vector3.Subtract(node.Left.Translation, node.Translation)));
                    node.Bounds.Add(node.Right.Bounds.Translated(Vector3.Subtract(node.Right.Translation, node.Translation)));

                    UpdateMesh(node, root);
                }
                else
                {
                    node.cachedMesh = CSGMesh.CreateFromPlanes(node.Generator.GetPlanes(node.WorldTransformation));

                    node.Bounds.Set(node.cachedMesh.Bounds);
                }
            }
        }
Example #2
0
        // We cache our base meshes here
        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 (node.cachedMesh == null)
                {
                    // 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, root.Transformation.Transform);
                        var brushMeshes = ProcessCSGNodes(node, childNodes);
                        mesh = CSGMesh.Combine(node.Translation, brushMeshes);
                    }
                    else
                    {
                        mesh = CSGMesh.CreateFromPlanes(node.Generator.GetPlanes(node.WorldTransformation));
                    }

                    // Cache the mesh
                    node.cachedMesh = mesh;
                }
                else
                {
                    mesh = node.cachedMesh;
                }

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

            //ProcessNode(root, root);
            //Parallel.ForEach(nodes, ProcessNode);

            //CSGUtility.UpdateBounds(root);
            //UpdateMesh(root, root);

            //Parallel.ForEach(meshes, updateDelegate);

            //*/
            return(meshes);
        }