Exemplo n.º 1
0
        public static Mesh BuildMesh(List <CSGNode> nodes)
        {
            Mesh mesh = new Mesh();

            CSGTree tree = new CSGTree();

            tree.RootNode = CreateTree(nodes);

            var updateNodes    = CSGUtility.FindChildBrushes(tree);
            var modifiedMeshes = CSGCategorization.ProcessCSGNodes(tree.RootNode, updateNodes);

            Dictionary <CSGNode, CSGMesh> validMeshes = new Dictionary <CSGNode, CSGMesh>();

            foreach (var item in modifiedMeshes)
            {
                validMeshes[item.Key] = item.Value;
            }

            Vector4[] vertices    = new Vector4[65535];
            int[]     polyIndices = new int[65535 * 4];
            int[]     lineIndices = new int[65535 * 3];

            Dictionary <Vector4, int> vertexLookup = new Dictionary <Vector4, int>();

            int[] vertexIndexLookup = new int[65535];

            int vertexCount;
            int polyIndexCount;
            int lineIndexCount;

            CreateListsFromMeshes(vertexLookup, vertexIndexLookup, validMeshes, vertices, out vertexCount, polyIndices, out polyIndexCount, lineIndices, out lineIndexCount);

            Vector4[] verts    = new Vector4[vertexCount];
            int[]     indicies = new int[polyIndexCount];
            Array.Copy(vertices, verts, verts.Length);
            Array.Copy(polyIndices, indicies, indicies.Length);

            mesh.Vertices = verts;
            mesh.Indicies = indicies;

            return(mesh);
        }
Exemplo n.º 2
0
        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);
        }