Esempio 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);
        }
Esempio n. 2
0
        void AnimateInstanceNodes(double time)
        {
            if (instanceNodes == null ||
                instanceNodes.Count == 0)
            {
                return;
            }

            var revolutionsPerSecond = 0.75f;
            var t       = ((time * revolutionsPerSecond) * Math.PI);
            var radiusX = 15.0f;
            var radiusY = 15.0f;

            var translation = new Vector3((float)(Math.Cos(t) * radiusX), (float)(Math.Sin(t) * radiusY), 0);

            var foundNodes = new HashSet <CSGNode>();

            for (int i = 0; i < instanceNodes.Count; ++i)
            {
                var node       = instanceNodes[i];
                var nodeBounds = node.Bounds;
                var nodeTrans  = node.Translation;
                for (int j = 0; j < allBrushes.Count; ++j)
                {
                    var otherBrush = allBrushes[j];
                    if (foundNodes.Contains(otherBrush))
                    {
                        continue;
                    }

                    var otherBrushBounds = otherBrush.Bounds;
                    var otherBrushTrans  = otherBrush.Translation;
                    var relativeTrans    = Vector3.Subtract(nodeTrans, otherBrushTrans);
                    if (!AABB.IsOutside(nodeBounds, relativeTrans, otherBrushBounds))
                    {
                        foundNodes.Add(otherBrush);
                    }
                }
            }

            for (int i = 0; i < instanceNodes.Count; ++i)
            {
                var node = instanceNodes[i];
                node.LocalTranslation = Vector3.Add(instanceNodeTranslations[i], translation);
                if (node.Parent != null)
                {
                    node.Translation = node.LocalTranslation + node.Parent.Translation;
                }
                else
                {
                    node.Translation = node.LocalTranslation;
                }
                CSGUtility.UpdateChildTransformations(node);
                foundNodes.Add(node);
            }

            for (int i = 0; i < instanceNodes.Count; ++i)
            {
                var node       = instanceNodes[i];
                var nodeBounds = node.Bounds;
                var nodeTrans  = node.Translation;
                for (int j = 0; j < allBrushes.Count; ++j)
                {
                    var otherBrush = allBrushes[j];
                    if (foundNodes.Contains(otherBrush))
                    {
                        continue;
                    }

                    var otherBrushBounds = otherBrush.Bounds;
                    var otherBrushTrans  = otherBrush.Translation;
                    var relativeTrans    = Vector3.Subtract(nodeTrans, otherBrushTrans);
                    if (!AABB.IsOutside(node.Bounds, relativeTrans, otherBrush.Bounds))
                    {
                        foundNodes.Add(otherBrush);
                    }
                }
            }

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