Example #1
0
    private GameObject Boolean(BoolOp operation)
    {
        Reset(main_object, operating_object);
        current_operation = TransfOp.Spectate;
        UpdateTransformationButtons();

        Mesh m;

        if (CSG_operation_history.Count == 0)
        {
            StoreCurrentState("start", main_object);
        }

        switch (operation)
        {
        case BoolOp.Union:
            StoreCurrentState("transformation", main_object);
            StoreCurrentState("union", operating_object);
            m = CSG.Union(main_object, operating_object);
            break;

        case BoolOp.Subtract:
            StoreCurrentState("transformation", main_object);
            StoreCurrentState("subtract", operating_object);
            m = CSG.Subtract(main_object, operating_object);
            break;

        case BoolOp.Intersect:
        default:
            StoreCurrentState("transformation", main_object);
            StoreCurrentState("intersect", operating_object);
            m = CSG.Intersect(main_object, operating_object);
            break;
        }

        composite      = new GameObject();
        composite.name = "Constructed CSG";
        composite.AddComponent <MeshFilter>().sharedMesh       = m;
        composite.AddComponent <MeshRenderer>().sharedMaterial = materials[material_ID];

        // Generate new mesh
        Mesh mesh = ConstructMesh(composite);

        // Generate new meshcollider
        composite.AddComponent <MeshCollider>();
        composite.GetComponent <MeshCollider>().sharedMesh = mesh;

        // Change tag
        composite.tag = "csg";

        Destroy(main_object);
        Destroy(operating_object);

        main_object      = null;
        operating_object = null;


        // Switch new composited object to main object
        return(composite);
    }
Example #2
0
    void Boolean(BoolOp operation)
    {
        Mesh m = new Mesh();

        switch (operation)
        {
        case BoolOp.Union:
            m = CSG.Union(first, second);
            break;

        case BoolOp.Subtract:
            m = CSG.Subtract(first, second);
            break;

        case BoolOp.Intersect:
            m = CSG.Intersect(first, second);
            break;
        }

        composite = new GameObject();
        composite.AddComponent <MeshFilter>().mesh       = m;
        composite.AddComponent <MeshRenderer>().material = first.GetComponent <MeshRenderer>().material;

        GenerateBarycentric(composite);
    }
Example #3
0
    // Use this for initialization
    void Start()
    {
        /*
         *      // Create new GameObject
         *      GameObject newObject = new GameObject();
         *      newObject.transform.localScale*=2f;
         *      MeshFilter meshFilter = newObject.AddComponent<MeshFilter>();
         *      MeshRenderer meshRenderer = newObject.AddComponent<MeshRenderer>();
         *      meshRenderer.materials = new Material[2]{meshColliderA.transform.GetComponent<Renderer>().materials[0],meshColliderB.transform.GetComponent<Renderer>().materials[0]};
         *
         *      // Assign booleanMesh
         *      BooleanMesh booleanMesh = new BooleanMesh(meshColliderA,meshColliderB);
         *      //meshFilter.mesh = booleanMesh.Difference();
         *      //meshFilter.mesh = booleanMesh.Union();
         *      meshFilter.mesh = booleanMesh.Intersection();
         */

        GameObject newObject = new GameObject();

        var meshFilter   = newObject.AddComponent <MeshFilter>();
        var meshRenderer = newObject.AddComponent <MeshRenderer>();

        meshRenderer.materials = new Material[2] {
            meshColliderA.transform.GetComponent <Renderer>().materials[0], meshColliderB.transform.GetComponent <Renderer>().materials[0]
        };

        meshFilter.mesh = CSG.Intersect(meshColliderA, meshColliderB);
    }
        public void T06_IntersectingARayWithACSGObjectMiss()
        {
            CSG c = new CSG(CSG.Operation.Union, new Sphere(), new Cube());
            Ray r = new Ray(new Point(0, 2, -5), new Vector(0, 0, 1));
            List <Intersection> xs = c.Intersect(r);

            Assert.IsEmpty(xs);
        }
Example #5
0
        public void TestCsgRayMisses()
        {
            var c  = new CSG(CsgOperation.Union, new Sphere(), new Cube());
            var r  = new Ray(new Point(0, 2, -5), Vector.VectorZ);
            var xs = c.Intersect(r);

            Assert.AreEqual(xs.Count, 0);
        }
Example #6
0
    public static GameObject GetIntersection(GameObject obj, GameObject hemisphere, Material truncatedMaterial, bool disableHemispheres)
    {
        GameObject cube = hemisphere.transform.Find("GuideCube").gameObject;
        Vector3    size = cube.transform.lossyScale;

        size.x -= 0.01F;
        size.y -= 0.01F;
        size.z -= 0.01F;
        //check if there is indeed area that is overlapping between the two objects
        Collider[] hitColliders = Physics.OverlapBox(cube.transform.position, size / 2, cube.transform.rotation);
        bool       isColliding  = false;

        foreach (Collider col in hitColliders)
        {
            if (col.gameObject == obj)
            {
                isColliding = true;
            }
        }
        if (!isColliding)
        {
            hemisphere.gameObject.SetActive(false);
            obj.gameObject.SetActive(false);
            return(null);
        }
        Vector3 position;

        position = obj.transform.position;
        obj.transform.position        = new Vector3(0, 0, 0);
        hemisphere.transform.position = obj.transform.position;
        Mesh n = CSG.Intersect(cube, obj);

        n.name = "Truncated Sphere";
        GameObject final = new GameObject("Final");

        final.AddComponent <MeshFilter>().sharedMesh       = n;
        final.AddComponent <MeshRenderer>().sharedMaterial = truncatedMaterial;
        final.AddComponent <MeshCollider>();
        final.GetComponent <MeshCollider>().sharedMesh = n;
        obj.transform.position        = position;
        hemisphere.transform.position = position;
        final.transform.position      = position;
        final.layer = LayerMask.NameToLayer("final");
        final.tag   = "Final";
        //GameObject VectorLineObj = DrawHemisphereLines(final, "final");
        //VectorLineObj.transform.parent = final.transform;
        //VectorLineObj.name = "HemiLine";

        if (disableHemispheres)
        {
            obj.GetComponent <MeshRenderer>().enabled        = false;
            hemisphere.GetComponent <MeshRenderer>().enabled = false;
        }

        return(final);
    }
Example #7
0
        public GameObject Intersect(GameObject s0, GameObject s1)
        {
            Mesh       m         = CSG.Intersect(s0, s1);
            GameObject composite = new GameObject();

            composite.transform.parent = mainObj.transform;
            composite.AddComponent <MeshFilter>().sharedMesh       = m;
            composite.AddComponent <MeshRenderer>().sharedMaterial = s0.GetComponent <MeshRenderer>().sharedMaterial;
            return(composite);
        }
Example #8
0
        public void TestCsgBBIntersectHit()
        {
            var left  = new TestShape();
            var right = new TestShape();
            var shape = new CSG(CsgOperation.Difference, left, right);
            var r     = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1));
            var xs    = shape.Intersect(r);

            Assert.IsNotNull(left.SavedRay);
            Assert.IsNotNull(right.SavedRay);
        }
Example #9
0
    // Use this for initialization
    void Start()
    {
        // Initialize two new meshes in the scene
        GameObject numbers = GameObject.Find("twoNum");
        GameObject ring    = GameObject.Find("ring");
        // Perform boolean operation
        Mesh m = CSG.Intersect(ring, numbers);

        // Create a gameObject to render the result
        composite = new GameObject();
        composite.AddComponent <MeshFilter>().mesh             = m;
        composite.AddComponent <MeshRenderer>().sharedMaterial = ring.GetComponent <MeshRenderer>().sharedMaterial;
    }
Example #10
0
    public static void CreateHemisphereMesh()
    {
        GameObject Sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        GameObject Cube   = GameObject.CreatePrimitive(PrimitiveType.Cube);

        Cube.transform.localScale = new Vector3(2, 2, 2);
        Sphere.transform.position = new Vector3(0, 0, 0);
        Cube.transform.position   = new Vector3(1, 0, 0);

        GameObject.Destroy(Sphere);
        GameObject.Destroy(Cube);
        Mesh m = CSG.Intersect(Sphere, Cube);

        m.name         = "Hemisphere Mesh";
        hemisphereMesh = m;
    }
Example #11
0
        public void TestCsgRayHits()
        {
            var s1 = new Sphere();
            var s2 = new Sphere();

            s2.Transform = Matrix.Translation(0, 0, 0.5);
            var c  = new CSG(CsgOperation.Union, s1, s2);
            var r  = new Ray(new Point(0, 0, -5), Vector.VectorZ);
            var xs = c.Intersect(r);

            Assert.AreEqual(xs.Count, 2);
            Assert.AreEqual(xs[0].t, 4, epsilon);
            Assert.AreEqual(xs[0].Object, s1);
            Assert.AreEqual(xs[1].t, 6.5, epsilon);
            Assert.AreEqual(xs[1].Object, s2);
        }
        public void T07_IntersectingARayWithACSGObjectHit()
        {
            Sphere s1 = new Sphere();
            Sphere s2 = new Sphere();

            s2.SetMatrix(Mat4.TranslateMatrix(0, 0, 0.5));
            CSG c = new CSG(CSG.Operation.Union, s1, s2);
            Ray r = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1));
            List <Intersection> xs = c.Intersect(r);

            Assert.AreEqual(2, xs.Count);
            Assert.IsTrue(Utility.FE(4, xs[0].t));
            Assert.AreEqual(s1, xs[0].rayObject);
            Assert.IsTrue(Utility.FE(6.5, xs[1].t));
            Assert.AreEqual(s2, xs[1].rayObject);
        }
        static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs)
        {
            if (lhs == null || rhs == null)
            {
                return(new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects"));
            }

            string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect");

            ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs };

            UndoUtility.RecordSelection(sel, op_string);

            UnityEngine.ProBuilder.Csg.Model result;

            switch (operation)
            {
            case BooleanOperation.Union:
                result = CSG.Union(lhs.gameObject, rhs.gameObject);
                break;

            case BooleanOperation.Subtract:
                result = CSG.Subtract(lhs.gameObject, rhs.gameObject);
                break;

            default:
                result = CSG.Intersect(lhs.gameObject, rhs.gameObject);
                break;
            }

            var            materials = result.materials.ToArray();
            ProBuilderMesh pb        = ProBuilderMesh.Create();

            pb.GetComponent <MeshFilter>().sharedMesh        = (Mesh)result;
            pb.GetComponent <MeshRenderer>().sharedMaterials = materials;
            MeshImporter importer = new MeshImporter(pb.gameObject);

            importer.Import(new MeshImportSettings()
            {
                quads = true, smoothing = true, smoothingAngle = 1f
            });
            pb.Rebuild();
            pb.CenterPivot(null);
            Selection.objects = new Object[] { pb.gameObject };

            return(new ActionResult(ActionResult.Status.Success, op_string));
        }
Example #14
0
        static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs)
        {
            if (lhs == null || rhs == null)
            {
                return(new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects"));
            }

            string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect");

            ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs };

            UndoUtility.RecordSelection(sel, op_string);

            Mesh c;

            switch (operation)
            {
            case BooleanOperation.Union:
                c = CSG.Union(lhs.gameObject, rhs.gameObject);
                break;

            case BooleanOperation.Subtract:
                c = CSG.Subtract(lhs.gameObject, rhs.gameObject);
                break;

            default:
                c = CSG.Intersect(lhs.gameObject, rhs.gameObject);
                break;
            }

            GameObject go = new GameObject();

            go.AddComponent <MeshRenderer>().sharedMaterial = EditorMaterialUtility.GetUserMaterial();
            go.AddComponent <MeshFilter>().sharedMesh       = c;

            ProBuilderMesh pb = InternalMeshUtility.CreateMeshWithTransform(go.transform, false);

            DestroyImmediate(go);

            Selection.objects = new Object[] { pb.gameObject };

            return(new ActionResult(ActionResult.Status.Success, op_string));
        }
Example #15
0
    void Boolean(BoolOp operation)
    {
        Mesh m;

        /**
         * All boolean operations accept two gameobjects and return a new mesh.
         * Order matters - left, right vs. right, left will yield different
         * results in some cases.
         */
        switch (operation)
        {
        case BoolOp.Union:
            m = CSG.Union(left, right);
            break;

        case BoolOp.SubtractLR:
            m = CSG.Subtract(left, right);
            break;

        case BoolOp.SubtractRL:
            m = CSG.Subtract(right, left);
            break;

        case BoolOp.Intersect:
        default:
            m = CSG.Intersect(right, left);
            break;
        }

        composite = new GameObject();
        composite.AddComponent <MeshFilter>().sharedMesh       = m;
        composite.AddComponent <MeshRenderer>().sharedMaterial = left.GetComponent <MeshRenderer>().sharedMaterial;

        GenerateBarycentric(composite);

        GameObject.Destroy(left);
        GameObject.Destroy(right);
    }
Example #16
0
 public void BooleanOp_WithReallySmallEpsilon_DoesNotCrash([ValueSource(nameof(BooleanOps))] CSG.BooleanOp op)
 {
     CSG.epsilon = 0.00000001f;
     Assert.DoesNotThrow(() => { CSG.Intersect(m_InputA, m_InputA); });
 }
Example #17
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;
            }
        }
    }