Esempio n. 1
0
    private void CreateBrushFromActive(Brush.CSGMode csgMode)
    {
        if (brushes == null)
        {
            brushes = new List <Brush>();
        }
        GameObject instantiatedBrush = (GameObject)Instantiate(activeBrush.gameObject, activeBrush.transform.position, activeBrush.transform.rotation);

        instantiatedBrush.transform.parent = this.transform;
        instantiatedBrush.name             = "AppliedBrush";
        DestroyImmediate(instantiatedBrush.GetComponent <ActiveBrush>());

        Brush brush = instantiatedBrush.GetComponent <Brush>();

        brush.Mode = csgMode;
        brushes.Add(brush);

        Rebuild();
    }
Esempio n. 2
0
    public void Rebuild()
    {
        // If there's an existing MeshGroup object, get rid of it
        if (transform.FindChild("MeshGroup") != null)
        {
            DestroyImmediate(transform.FindChild("MeshGroup").gameObject);
        }

        if (brushes != null && brushes.Count > 0)
        {
            // Ensure any brush objects that have been deleted by the user are removed from the brush sequence
            for (int i = 0; i < brushes.Count; i++)
            {
                if (brushes[i] == null)
                {
                    brushes.RemoveAt(i);
                    i--;
                }
            }

            CSG current = null;
            // Iterate through each brush in sequence
            for (int i = 0; i < brushes.Count; i++)
            {
                Brush.CSGMode mode = brushes[i].Mode;

                // Generate the CSG geometry for the brush
                CSG brushGeometry = brushes[i].GenerateCSG();

                brushGeometry.SetShared(brushes[i].SharedBrushData);

                if (i == 0)
                {
                    // The first brush is always added to the space (rather than subtracted)
                    current = brushGeometry;
                }
                else
                {
                    // For every brush after the first one, carry out the correct operation
                    if (mode == Brush.CSGMode.Subtract)
                    {
                        current = current.Subtract(brushGeometry);
                    }
                    else if (mode == Brush.CSGMode.Union)
                    {
                        current = current.Union(brushGeometry);
                    }
                    else if (mode == Brush.CSGMode.Intersect)
                    {
                        current = current.Intersect(brushGeometry);
                    }
                }
            }
            // Now that the final CSG has been calculated, fetch the polygons (mixture of triangles and quads)
            Polygon[] polygons = current.Polygons;

            // Create polygon subsets for each material
            Dictionary <Material, List <Polygon> > polygonMaterialTable = new Dictionary <Material, List <Polygon> >();

            // Iterate through every polygon adding it to the appropiate material list
            foreach (Polygon polygon in current.Polygons)
            {
                Material material = ((SharedBrushData)polygon.Shared).Material;
                if (!polygonMaterialTable.ContainsKey(material))
                {
                    polygonMaterialTable.Add(material, new List <Polygon>());
                }

                polygonMaterialTable[material].Add(polygon);
            }

            // Create a grouping object which will act as a parent for all the per material meshes
            meshGroup = new GameObject("MeshGroup");
            meshGroup.transform.parent = this.transform;

            // Create a separate mesh for polygons of each material so that we batch by material
            foreach (KeyValuePair <Material, List <Polygon> > polygonMaterialGroup in polygonMaterialTable)
            {
                Mesh           mesh      = new Mesh();
                List <Vector3> vertices  = new List <Vector3>();
                List <Vector3> normals   = new List <Vector3>();
                List <Vector2> uvs       = new List <Vector2>();
                List <Color>   colors    = new List <Color>();
                List <int>     triangles = new List <int>();

                // Setup an indexer that tracks unique vertices, so that we reuse vertex data appropiately
                Indexer indexer = new Indexer();

                // Iterate through every polygon and triangulate
                foreach (Polygon polygon in polygonMaterialGroup.Value)
                {
                    List <int> indices = new List <int>();

                    for (int i = 0; i < polygon.Vertices.Length; i++)
                    {
                        // Each vertex must know about its shared data for geometry tinting
                        polygon.Vertices[i].Shared = polygon.Shared;
                        // If the vertex is already in the indexer, fetch the index otherwise add it and get the added index
                        int index = indexer.Add(polygon.Vertices[i]);
                        // Put each vertex index in an array for use in the triangle generation
                        indices.Add(index);
                    }

                    // Triangulate the n-sided polygon and allow vertex reuse by using indexed geometry
                    for (int i = 2; i < indices.Count; i++)
                    {
                        triangles.Add(indices[0]);
                        triangles.Add(indices[i - 1]);
                        triangles.Add(indices[i]);
                    }
                }

                // Create the relevant buffers from the vertex array
                for (int i = 0; i < indexer.Vertices.Count; i++)
                {
                    vertices.Add(indexer.Vertices[i].Position);
                    normals.Add(indexer.Vertices[i].Normal);
                    uvs.Add(indexer.Vertices[i].UV);
                    colors.Add(((SharedBrushData)indexer.Vertices[i].Shared).BrushTintColor);
                }

                // Set the mesh buffers
                mesh.vertices  = vertices.ToArray();
                mesh.normals   = normals.ToArray();
                mesh.colors    = colors.ToArray();
                mesh.uv        = uvs.ToArray();
                mesh.triangles = triangles.ToArray();

                // Optionally you can turn these on to ensure normals are correct and also generate tangents
                // mesh.RecalculateNormals();
                // GenerateTangents(mesh);

                GameObject materialMesh = new GameObject("MaterialMesh", typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));
                materialMesh.transform.parent = meshGroup.transform;

                // Set the mesh to be rendered
                materialMesh.GetComponent <MeshFilter>().mesh = mesh;
                // Set the collision mesh
                materialMesh.GetComponent <MeshCollider>().sharedMesh = mesh;

                materialMesh.renderer.material = polygonMaterialGroup.Key;
            }
        }
    }