Ejemplo n.º 1
0
        void InitCSGTree()
        {
            csgTree = CSGUtility.LoadTree("import.xml", out instanceNodes);
            if (csgTree == null)
            {
                MessageBox.Show("Failed to load file");
                return;
            }

            instanceNodeTranslations = new List <Vector3>();
            if (instanceNodes != null &&
                instanceNodes.Count > 0)
            {
                foreach (var node in instanceNodes)
                {
                    instanceNodeTranslations.Add(node.LocalTranslation);
                }

                subInstanceBrushes = new HashSet <CSGNode>();
                foreach (var node in instanceNodes)
                {
                    foreach (var brush in CSGUtility.FindChildBrushes(node))
                    {
                        subInstanceBrushes.Add(brush);
                    }
                }

                allBrushes = (from node in
                              CSGUtility.FindChildBrushes(csgTree)
                              where !subInstanceBrushes.Contains(node)
                              select node).ToList();
            }
            else
            {
                allBrushes = CSGUtility.FindChildBrushes(csgTree).ToList();
            }

            var updateNodes = new List <CSGNode>();

            updateNodes.AddRange(allBrushes);
            updateNodes.AddRange(instanceNodes);

            UpdateMeshes(csgTree, updateNodes);
        }
        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);
        }