/// <summary>
        /// Combine coplanar triangles from the faceted body if they share the edge. From this process, polygonal faces (with or without holes) will be created
        /// </summary>
        public void SimplifyAndMergeFaces(bool ignoreMerge = false)
        {
            int eulerBefore = ignoreMerge ? 0 : CalculateEulerCharacteristic();

            int noTriangle = (IsMesh) ? m_MeshGeom.NumTriangles : m_Geom.TriangleCount;
            IEqualityComparer <XYZ>       normalComparer     = new VectorCompare();
            Dictionary <XYZ, List <int> > faceSortedByNormal = new Dictionary <XYZ, List <int> >(normalComparer);

            for (int ef = 0; ef < noTriangle; ++ef)
            {
                IList <int> vertIndex = new List <int>();

                if (IsMesh)
                {
                    MeshTriangle f = m_MeshGeom.get_Triangle(ef);
                    vertIndex = new List <int>(3)
                    {
                        (int)f.get_Index(0), (int)f.get_Index(1), (int)f.get_Index(2)
                    };
                }
                else
                {
                    TriangleInShellComponent f = m_Geom.GetTriangle(ef);
                    vertIndex = new List <int>(3)
                    {
                        f.VertexIndex0, f.VertexIndex1, f.VertexIndex2
                    };
                }

                IndexFace intF = new IndexFace(vertIndex, ref m_MeshVertices);
                m_FacesCollDict.Add(faceIdxOffset++, intF);     // Keep faces in a dictionary and assigns ID
                List <int> fIDList;

                if (!faceSortedByNormal.TryGetValue(intF.Normal, out fIDList))
                {
                    fIDList = new List <int>(1)
                    {
                        ef
                    };
                    faceSortedByNormal.Add(intF.Normal, fIDList);
                }
                else if (!fIDList.Contains(ef))
                {
                    fIDList.Add(ef);
                }
            }

            foreach (KeyValuePair <XYZ, List <int> > fListDict in faceSortedByNormal)
            {
                List <int> mergedFaceList = null;
                if (fListDict.Value.Count > 1)
                {
                    if (!ignoreMerge)
                    {
                        TryMergeFaces(fListDict.Value, out mergedFaceList);
                    }
                    else
                    {
                        // keep original face list
                        mergedFaceList = fListDict.Value;
                    }
                    if (mergedFaceList != null && mergedFaceList.Count > 0)
                    {
                        // insert only new face indexes as the mergedlist from different vertices can be duplicated
                        foreach (int fIdx in mergedFaceList)
                        {
                            if (!m_MergedFaceSet.Contains(fIdx))
                            {
                                m_MergedFaceSet.Add(fIdx);
                            }
                        }
                    }
                }
                else if (!m_MergedFaceSet.Contains(fListDict.Value[0]))
                {
                    m_MergedFaceSet.Add(fListDict.Value[0]); // No pair face, add it into the mergedList
                }
            }

            int eulerAfter = ignoreMerge ? 0 : CalculateEulerCharacteristic();

            if (eulerBefore != eulerAfter)
            {
                throw new InvalidOperationException(); // Coplanar merge broke the mesh in some way, so we need to fall back to exporting a triangular mesh
            }
        }
Example #2
0
    private static void CutTriangle(Plane _plane,
                                    MeshTriangle _triangle,
                                    bool _triangleALeftSide,
                                    bool _triangleBLeftSide,
                                    bool _triangleCLeftSide,
                                    GeneratedMesh _leftSide,
                                    GeneratedMesh _rightSide,
                                    List <Vector3> _addedVertices)
    {
        List <bool> leftSide = new List <bool>();

        leftSide.Add(_triangleALeftSide);
        leftSide.Add(_triangleBLeftSide);
        leftSide.Add(_triangleCLeftSide);

        MeshTriangle leftMeshTriangle  = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex);
        MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex);

        bool left  = false;
        bool right = false;

        for (int i = 0; i < 3; ++i)
        {
            if (leftSide[i])
            {
                if (!left)
                {
                    left = true;

                    leftMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    leftMeshTriangle.Vertices[1] = leftMeshTriangle.Vertices[0];

                    leftMeshTriangle.UVs[0] = _triangle.UVs[i];
                    leftMeshTriangle.UVs[1] = leftMeshTriangle.UVs[0];

                    leftMeshTriangle.Normals[0] = _triangle.Normals[i];
                    leftMeshTriangle.Normals[1] = leftMeshTriangle.Normals[0];
                }
                else
                {
                    leftMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    leftMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    leftMeshTriangle.UVs[1]      = _triangle.UVs[i];
                }
            }
            else
            {
                if (!right)
                {
                    right = true;

                    rightMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    rightMeshTriangle.Vertices[1] = rightMeshTriangle.Vertices[0];

                    rightMeshTriangle.UVs[0] = _triangle.UVs[i];
                    rightMeshTriangle.UVs[1] = rightMeshTriangle.UVs[0];

                    rightMeshTriangle.Normals[0] = _triangle.Normals[i];
                    rightMeshTriangle.Normals[1] = rightMeshTriangle.Normals[0];
                }
                else
                {
                    rightMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    rightMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    rightMeshTriangle.UVs[1]      = _triangle.UVs[i];
                }
            }
        }

        float normalizedDistance;
        float distance;

        _plane.Raycast(new Ray(leftMeshTriangle.Vertices[0], (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).magnitude;
        Vector3 vertLeft = Vector3.Lerp(leftMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[0], normalizedDistance);

        _addedVertices.Add(vertLeft);

        Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Normals[0], rightMeshTriangle.Normals[0], normalizedDistance);
        Vector2 uvLeft     = Vector2.Lerp(leftMeshTriangle.UVs[0], rightMeshTriangle.UVs[0], normalizedDistance);

        _plane.Raycast(new Ray(leftMeshTriangle.Vertices[1], (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).magnitude;
        Vector3 vertRight = Vector3.Lerp(leftMeshTriangle.Vertices[1], rightMeshTriangle.Vertices[1], normalizedDistance);

        _addedVertices.Add(vertRight);

        Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Normals[1], rightMeshTriangle.Normals[1], normalizedDistance);
        Vector2 uvRight     = Vector2.Lerp(leftMeshTriangle.UVs[1], rightMeshTriangle.UVs[1], normalizedDistance);

        MeshTriangle currentTriangle;

        Vector3[] updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], vertLeft, vertRight };
        Vector3[] updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], normalLeft, normalRight };
        Vector2[] updatedUVs      = new Vector2[] { leftMeshTriangle.UVs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }

            _leftSide.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], leftMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], leftMeshTriangle.Normals[1], normalRight };
        updatedUVs      = new Vector2[] { leftMeshTriangle.UVs[0], leftMeshTriangle.UVs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }

            _leftSide.AddTriangle(currentTriangle);
        }


        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], vertLeft, vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], normalLeft, normalRight };
        updatedUVs      = new Vector2[] { rightMeshTriangle.UVs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }

            _rightSide.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], rightMeshTriangle.Normals[1], normalRight };
        updatedUVs      = new Vector2[] { rightMeshTriangle.UVs[0], rightMeshTriangle.UVs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }

            _rightSide.AddTriangle(currentTriangle);
        }
    }
Example #3
0
        public static void Execute1(
            ExternalCommandData commandData)
        {
            Transaction trans = null;

            UIDocument uidoc = commandData.Application
                               .ActiveUIDocument;

            Document doc = uidoc.Document;

            try
            {
                Selection choices = uidoc.Selection;

                Reference reference = choices.PickObject(
                    ObjectType.Face);

                Element el = doc.GetElement(
                    reference.ElementId);

                trans = new Transaction(doc, "Create elements");
                trans.Start();

                TessellatedShapeBuilder builder
                    = new TessellatedShapeBuilder();

                builder.OpenConnectedFaceSet(false);

                Face face = el.GetGeometryObjectFromReference(
                    reference) as Face;

                Mesh       mesh = face.Triangulate();
                List <XYZ> args = new List <XYZ>(3);

                XYZ offset = new XYZ();
                if (el.Location is LocationPoint)
                {
                    LocationPoint locationPoint = el.Location
                                                  as LocationPoint;
                    offset = locationPoint.Point;
                }

                for (int i = 0; i < mesh.NumTriangles; i++)
                {
                    MeshTriangle triangle = mesh.get_Triangle(
                        i);

                    XYZ p1 = triangle.get_Vertex(0);
                    XYZ p2 = triangle.get_Vertex(1);
                    XYZ p3 = triangle.get_Vertex(2);

                    p1 = p1.Add(offset);
                    p2 = p2.Add(offset);
                    p3 = p3.Add(offset);

                    args.Clear();
                    args.Add(p1);
                    args.Add(p2);
                    args.Add(p3);

                    TessellatedFace tesseFace
                        = new TessellatedFace(args,
                                              ElementId.InvalidElementId);

                    if (builder.DoesFaceHaveEnoughLoopsAndVertices(
                            tesseFace))
                    {
                        builder.AddFace(tesseFace);
                    }
                }

                builder.CloseConnectedFaceSet();

                //TessellatedShapeBuilderResult result
                //  = builder.Build(
                //    TessellatedShapeBuilderTarget.AnyGeometry,
                //    TessellatedShapeBuilderFallback.Mesh,
                //    ElementId.InvalidElementId ); // 2016

                builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;    // 2018
                builder.Fallback = TessellatedShapeBuilderFallback.Mesh;         // 2018

                builder.Build();                                                 // 2018

                TessellatedShapeBuilderResult result = builder.GetBuildResult(); // 2018

                ElementId categoryId = new ElementId(
                    BuiltInCategory.OST_GenericModel);

                //DirectShape ds = DirectShape.CreateElement(
                //  doc, categoryId,
                //  Assembly.GetExecutingAssembly().GetType()
                //  .GUID.ToString(), Guid.NewGuid().ToString() ); // 2016

                DirectShape ds = DirectShape.CreateElement(
                    doc, categoryId); // 2018

                ds.ApplicationId = Assembly.GetExecutingAssembly()
                                   .GetType().GUID.ToString();    // 2018

                ds.ApplicationDataId = Guid.NewGuid().ToString(); // 2018

                ds.SetShape(result.GetGeometricalObjects());

                ds.Name = "MyShape";

                trans.Commit();
            }
            catch (Exception ex)
            {
                if (trans != null)
                {
                    trans.RollBack();
                }

                Debug.Print(ex.Message);
            }
        }
Example #4
0
        CollectEvent(object sender, CollectorEventArgs e)
        {
            // cast the sender object to the SnoopCollector we are expecting
            Collector snoopCollector = sender as Collector;

            if (snoopCollector == null)
            {
                Debug.Assert(false);    // why did someone else send us the message?
                return;
            }

            // see if it is a type we are responsible for
            Location loc = e.ObjToSnoop as Location;

            if (loc != null)
            {
                Stream(snoopCollector.Data(), loc);
                return;
            }

            GeometryObject geomObj = e.ObjToSnoop as GeometryObject;

            if (geomObj != null)
            {
                Stream(snoopCollector.Data(), geomObj);
                return;
            }

            Options opts = e.ObjToSnoop as Options;

            if (opts != null)
            {
                Stream(snoopCollector.Data(), opts);
                return;
            }

            Transform trf = e.ObjToSnoop as Transform;

            if (trf != null)
            {
                Stream(snoopCollector.Data(), trf);
                return;
            }

            BoundingBoxXYZ bndBoxXyz = e.ObjToSnoop as BoundingBoxXYZ;

            if (bndBoxXyz != null)
            {
                Stream(snoopCollector.Data(), bndBoxXyz);
                return;
            }

            MeshTriangle meshTri = e.ObjToSnoop as MeshTriangle;

            if (meshTri != null)
            {
                Stream(snoopCollector.Data(), meshTri);
                return;
            }

            Reference reference = e.ObjToSnoop as Reference;

            if (reference != null)
            {
                Stream(snoopCollector.Data(), reference);
                return;
            }

            EdgeArray edgeArray = e.ObjToSnoop as EdgeArray;    // NOTE: this is needed because EdgeArrayArray will display enumerable Snoop items

            if (edgeArray != null)
            {
                Stream(snoopCollector.Data(), edgeArray);
                return;
            }

            CurveArray curveArray = e.ObjToSnoop as CurveArray;    // NOTE: this is needed because CurveArrayArray will display enumerable Snoop items

            if (curveArray != null)
            {
                Stream(snoopCollector.Data(), curveArray);
                return;
            }

            Plane plane = e.ObjToSnoop as Plane;

            if (plane != null)
            {
                Stream(snoopCollector.Data(), plane);
                return;
            }

            IntersectionResult intrResult = e.ObjToSnoop as IntersectionResult;

            if (intrResult != null)
            {
                Stream(snoopCollector.Data(), intrResult);
                return;
            }

            BoundingBoxUV bboxUV = e.ObjToSnoop as BoundingBoxUV;

            if (bboxUV != null)
            {
                Stream(snoopCollector.Data(), bboxUV);
                return;
            }

            SweepProfile sweepProf = e.ObjToSnoop as SweepProfile;

            if (sweepProf != null)
            {
                Stream(snoopCollector.Data(), sweepProf);
                return;
            }

            DimensionSegment dimSeg = e.ObjToSnoop as DimensionSegment;

            if (dimSeg != null)
            {
                Stream(snoopCollector.Data(), dimSeg);
                return;
            }

            UV uv = e.ObjToSnoop as UV;

            if (uv != null)
            {
                Stream(snoopCollector.Data(), uv);
                return;
            }
        }
Example #5
0
            // public Vector3 ClosestPoint (Vector3 point)
            // {
            // }

            public MeshTriangle[] Subdivide()
            {
                MeshTriangle[] output = new MeshTriangle[4];
                return(output);
            }
Example #6
0
 public static Triangle3D ToSAM(this MeshTriangle meshTriangle)
 {
     return(new Triangle3D(meshTriangle.get_Vertex(0).ToSAM(), meshTriangle.get_Vertex(1).ToSAM(), meshTriangle.get_Vertex(2).ToSAM()));
 }
Example #7
0
    private static void CutTriangle(Plane plane, MeshTriangle triangle, bool [] pointsOnLeftSide, GeneratedMesh leftMesh, GeneratedMesh rightMesh, List <Vector3> addedVertices)
    {
        MeshTriangle leftMeshTriangle  = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], triangle.SubmeshIndices);
        MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], triangle.SubmeshIndices);

        bool left  = false;
        bool right = false;

        for (int i = 0; i < 3; i++)
        {
            if (pointsOnLeftSide[i])
            {
                if (!left)
                {
                    left = true;

                    leftMeshTriangle.Vertices[0] = leftMeshTriangle.Vertices[1] = triangle.Vertices[i];
                    leftMeshTriangle.Uvs[0]      = leftMeshTriangle.Uvs[1] = triangle.Uvs[i];
                    leftMeshTriangle.Normals[0]  = leftMeshTriangle.Normals[1] = triangle.Normals[i];
                }
                else
                {
                    leftMeshTriangle.Vertices[1] = triangle.Vertices[i];
                    leftMeshTriangle.Uvs[1]      = triangle.Uvs[i];
                    leftMeshTriangle.Normals[1]  = triangle.Normals[i];
                }
            }
            else
            {
                if (!right)
                {
                    right = true;

                    rightMeshTriangle.Vertices[0] = rightMeshTriangle.Vertices[1] = triangle.Vertices[i];
                    rightMeshTriangle.Uvs[0]      = rightMeshTriangle.Uvs[1] = triangle.Uvs[i];
                    rightMeshTriangle.Normals[0]  = rightMeshTriangle.Normals[1] = triangle.Normals[i];
                }
                else
                {
                    rightMeshTriangle.Vertices[1] = triangle.Vertices[i];
                    rightMeshTriangle.Uvs[1]      = triangle.Uvs[i];
                    rightMeshTriangle.Normals[1]  = triangle.Normals[i];
                }
            }
        }


        // можно переписать черех цикл и сократить количество кода в 2 раза и вынести в новую функцию добавление новой вершины
        float normalizedDistance;
        float distance;

        plane.Raycast(new Ray(leftMeshTriangle.Vertices[0], (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0]).magnitude;
        Vector3 vertLeft = Vector3.Lerp(leftMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[0], normalizedDistance);

        addedVertices.Add(vertLeft);

        Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Normals[0], rightMeshTriangle.Normals[0], normalizedDistance);
        Vector3 uvLeft     = Vector3.Lerp(leftMeshTriangle.Uvs[0], rightMeshTriangle.Uvs[0], normalizedDistance);

        plane.Raycast(new Ray(leftMeshTriangle.Vertices[1], (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1]).magnitude;
        Vector3 vertRight = Vector3.Lerp(leftMeshTriangle.Vertices[1], rightMeshTriangle.Vertices[1], normalizedDistance);

        addedVertices.Add(vertRight);

        Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Normals[1], rightMeshTriangle.Normals[1], normalizedDistance);
        Vector3 uvRight     = Vector3.Lerp(leftMeshTriangle.Uvs[1], rightMeshTriangle.Uvs[1], normalizedDistance);

        // до сюда

        // можно сократить код в 4 раза и вынести в новую функцию
        Vector3[] updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], vertLeft, vertRight };
        Vector3[] updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], normalLeft, normalRight };
        Vector2[] updatedUvs      = new Vector2[] { leftMeshTriangle.Uvs[0], uvLeft, uvRight };

        MeshTriangle currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, triangle.SubmeshIndices);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            leftMesh.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], leftMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], leftMeshTriangle.Normals[1], normalRight };
        updatedUvs      = new Vector2[] { leftMeshTriangle.Uvs[0], leftMeshTriangle.Uvs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, triangle.SubmeshIndices);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            leftMesh.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], vertLeft, vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], normalLeft, normalRight };
        updatedUvs      = new Vector2[] { rightMeshTriangle.Uvs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, triangle.SubmeshIndices);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            rightMesh.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], rightMeshTriangle.Normals[1], normalRight };
        updatedUvs      = new Vector2[] { rightMeshTriangle.Uvs[0], rightMeshTriangle.Uvs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, triangle.SubmeshIndices);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            rightMesh.AddTriangle(currentTriangle);
        }
        // до сюда
    }
Example #8
0
 public bool AllCornersAreSimilar(MeshTriangle meshTriangle, float maxDistanceSqr)
 {
     return(point1.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr && point2.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr && point3.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr);
 }
Example #9
0
    public static GameObject Cut(GameObject _originalGameObject, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null, bool fill = true, bool _addRigigibody = false)
    {
        if (currentlyCutting)
        {
            return(null);
        }
        currentlyCutting = true;

        // set the cutter relative to victim

        Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction),
                                _originalGameObject.transform.InverseTransformPoint(_contactPoint));

        //get the victims mesh
        originalMesh = _originalGameObject.GetComponent <MeshFilter>() ? _originalGameObject.GetComponent <MeshFilter>().mesh : _originalGameObject.GetComponent <SkinnedMeshRenderer>().sharedMesh;

        //List for added vertices
        List <Vector3> addedVertices = new List <Vector3>();

        //Create two new meshes
        GeneratedMesh leftMesh  = new GeneratedMesh();
        GeneratedMesh rightMesh = new GeneratedMesh();

        int[] submeshIndices;
        int   triangleIndexA, triangleIndexB, triangleIndexC;

        for (int i = 0; i < originalMesh.subMeshCount; i++)
        {
            //Fetches the triangle list for the specified sub-mesh on the victim
            submeshIndices = originalMesh.GetTriangles(i);

            for (int j = 0; j < submeshIndices.Length; j += 3)
            {
                triangleIndexA = submeshIndices[j];
                triangleIndexB = submeshIndices[j + 1];
                triangleIndexC = submeshIndices[j + 2];

                MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i);

                // Get vertices sides
                bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]);
                bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]);
                bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]);

                if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide)// left side
                {
                    leftMesh.AddTriangle(currentTriangle);
                }
                else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide)// right side
                {
                    rightMesh.AddTriangle(currentTriangle);
                }
                else // Cut the triangle
                {
                    CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices);
                }
            }
        }

        // Get Materials to apply to the new objects
        Material[] mats;

        if (_originalGameObject.GetComponent <MeshRenderer>())
        {
            mats = _originalGameObject.GetComponent <MeshRenderer>().sharedMaterials;
        }
        else
        {
            mats = _originalGameObject.GetComponent <SkinnedMeshRenderer>().sharedMaterials;
        }

        // if there is a material to fill the cut add it to materials list
        if (_cutMaterial)
        {
            if (mats[mats.Length - 1].name != _cutMaterial.name)
            {
                Material[] newmats = new Material[mats.Length + 1];
                mats.CopyTo(newmats, 0);
                newmats[mats.Length] = _cutMaterial;
                mats = newmats;
            }
        }
        int submeshCount = mats.Length - 1;

        if (fill)
        {
            // fill the opennings
            FillCut(addedVertices, plane, leftMesh, rightMesh, submeshCount);
        }

        //// Left Mesh
        Mesh left_HalfMesh = leftMesh.GetMesh();

        left_HalfMesh.name = "Split Mesh Left";

        //// Right Mesh
        Mesh right_HalfMesh = rightMesh.GetMesh();

        right_HalfMesh.name = "Split Mesh Right";

        //// assign the game objects

        if (_originalGameObject.GetComponent <MeshFilter>())
        {
            _originalGameObject.GetComponent <MeshFilter>().mesh = left_HalfMesh;
        }
        else
        {
            _originalGameObject.GetComponent <SkinnedMeshRenderer>().sharedMesh = left_HalfMesh;
        }


        GameObject leftSideObj  = _originalGameObject;
        GameObject rightSideObj = null;

        if (_originalGameObject.GetComponent <MeshRenderer>())
        {
            rightSideObj = new GameObject("right side", typeof(MeshFilter), typeof(MeshRenderer));
            rightSideObj.transform.position = _originalGameObject.transform.position;
            rightSideObj.transform.rotation = _originalGameObject.transform.rotation;
            rightSideObj.GetComponent <MeshFilter>().mesh = right_HalfMesh;
        }
        else if (_originalGameObject.GetComponent <SkinnedMeshRenderer>())
        {
            rightSideObj = new GameObject("right side");
            SkinnedMeshRenderer skinMesh = rightSideObj.AddComponent <SkinnedMeshRenderer>();
            rightSideObj.transform.position = _originalGameObject.transform.position;
            rightSideObj.transform.rotation = _originalGameObject.transform.rotation;
            skinMesh.sharedMesh             = right_HalfMesh;
        }


        if (_originalGameObject.transform.parent != null)
        {
            rightSideObj.transform.parent = _originalGameObject.transform.parent;
        }

        rightSideObj.transform.localScale = _originalGameObject.transform.localScale;

        //Add rigibody to the new object
        if (_addRigigibody)
        {
            var rigibody = rightSideObj.AddComponent <Rigidbody>();
            rigibody = _originalGameObject.GetComponent <Rigidbody>();
        }

        // assign materials

        if (_originalGameObject.GetComponent <MeshRenderer>())
        {
            leftSideObj.GetComponent <MeshRenderer>().materials  = mats;
            rightSideObj.GetComponent <MeshRenderer>().materials = mats;
        }
        else if (_originalGameObject.GetComponent <SkinnedMeshRenderer>())
        {
            leftSideObj.GetComponent <SkinnedMeshRenderer>().materials  = mats;
            rightSideObj.GetComponent <SkinnedMeshRenderer>().materials = mats;
        }

        return(rightSideObj);
    }
        /// <summary>
        /// Get triangles in a solid with transform.
        /// </summary>
        /// <param name="solid">The solid contains triangulars</param>
        /// <param name="transform">The transformation.</param>
        private void GetTriangular(Document document, Solid solid, Transform transform)
        {
            // a solid has many faces
            FaceArray faces        = solid.Faces;
            bool      hasTransform = (null != transform);

            if (0 == faces.Size)
            {
                return;
            }

            foreach (Face face in faces)
            {
                if (face.Visibility != Visibility.Visible)
                {
                    continue;
                }
                Mesh mesh = face.Triangulate();
                if (null == mesh)
                {
                    continue;
                }

                m_TriangularNumber += mesh.NumTriangles;

                PlanarFace planarFace = face as PlanarFace;

                // write face to stl file
                // a face has a mesh, all meshes are made of triangles
                for (int ii = 0; ii < mesh.NumTriangles; ii++)
                {
                    MeshTriangle          triangular = mesh.get_Triangle(ii);
                    double[]              xyz        = new double[9];
                    Autodesk.Revit.DB.XYZ normal     = new Autodesk.Revit.DB.XYZ();
                    try
                    {
                        Autodesk.Revit.DB.XYZ[] triPnts = new Autodesk.Revit.DB.XYZ[3];
                        for (int n = 0; n < 3; ++n)
                        {
                            double x, y, z;
                            Autodesk.Revit.DB.XYZ point = triangular.get_Vertex(n);
                            if (hasTransform)
                            {
                                point = transform.OfPoint(point);
                            }
                            if (m_Settings.ExportSharedCoordinates)
                            {
                                ProjectPosition ps = document.ActiveProjectLocation.GetProjectPosition(point);
                                x = ps.EastWest;
                                y = ps.NorthSouth;
                                z = ps.Elevation;
                            }
                            else
                            {
                                x = point.X;
                                y = point.Y;
                                z = point.Z;
                            }
                            if (m_Settings.Units != DisplayUnitType.DUT_UNDEFINED)
                            {
                                xyz[3 * n]     = UnitUtils.ConvertFromInternalUnits(x, m_Settings.Units);
                                xyz[3 * n + 1] = UnitUtils.ConvertFromInternalUnits(y, m_Settings.Units);
                                xyz[3 * n + 2] = UnitUtils.ConvertFromInternalUnits(z, m_Settings.Units);
                            }
                            else
                            {
                                xyz[3 * n]     = x;
                                xyz[3 * n + 1] = y;
                                xyz[3 * n + 2] = z;
                            }

                            var mypoint = new XYZ(xyz[3 * n], xyz[3 * n + 1], xyz[3 * n + 2]);
                            triPnts[n] = mypoint;
                        }

                        Autodesk.Revit.DB.XYZ pnt1 = triPnts[1] - triPnts[0];
                        normal = pnt1.CrossProduct(triPnts[2] - triPnts[1]);
                    }
                    catch (Exception ex)
                    {
                        m_TriangularNumber--;
                        STLDialogManager.ShowDebug(ex.Message);
                        continue;
                    }

                    if (m_Writer is SaveDataAsBinary && m_Settings.ExportColor)
                    {
                        Material material = document.GetElement(face.MaterialElementId) as Material;
                        if (material != null)
                        {
                            ((SaveDataAsBinary)m_Writer).Color = material.Color;
                        }
                    }

                    m_Writer.WriteSection(normal, xyz);
                }
            }
        }
Example #11
0
    // Fill holl when cutting the triangle
    public static void Fill(List <Vector3> _vertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh, int submeshCount)
    {
        // center of the filling
        Vector3 centerPosition = Vector3.zero;

        for (int i = 0; i < _vertices.Count; i++)
        {
            centerPosition += _vertices[i];
        }
        centerPosition = centerPosition / _vertices.Count;

        Vector3 up = new Vector3()
        {
            x = _plane.normal.x,
            y = _plane.normal.y,
            z = _plane.normal.z
        };

        Vector3 left = Vector3.Cross(_plane.normal, _plane.normal);

        Vector3 displacement = Vector3.zero;
        Vector2 uv1          = Vector2.zero;
        Vector2 uv2          = Vector2.zero;

        // go through edges and eliminate by creating triangles with connected edges
        // each new triangle removes 2 edges but creates 1 new edge
        // keep the chain in order
        for (int i = 0; i < _vertices.Count; i++)
        {
            displacement = _vertices[i] - centerPosition;
            uv1          = new Vector2()
            {
                x = .5f + Vector3.Dot(displacement, left),
                y = .5f + Vector3.Dot(displacement, up)
            };

            displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition;
            uv2          = new Vector2()
            {
                x = .5f + Vector3.Dot(displacement, left),
                y = .5f + Vector3.Dot(displacement, up)
            };

            Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition };
            Vector3[] normals  = new Vector3[] { -_plane.normal, -_plane.normal, -_plane.normal };
            Vector2[] uvs      = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) };
            //Update current triangle
            MeshTriangle currentTriangle = new MeshTriangle(vertices, normals, uvs, submeshCount);

            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add to left side
            _leftMesh.AddTriangle(currentTriangle);

            normals         = new Vector3[] { _plane.normal, _plane.normal, _plane.normal };
            currentTriangle = new MeshTriangle(vertices, normals, uvs, submeshCount);

            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add to right side
            _rightMesh.AddTriangle(currentTriangle);
        }
    }
Example #12
0
    private static void CutTriangle(Plane _plane, MeshTriangle _triangle, bool _triangleALeftSide, bool _triangleBLeftSide, bool _triangleCLeftSide,
                                    GeneratedMesh _leftSide, GeneratedMesh _rightSide, List <Vector3> _addedVertices)
    {
        List <bool> leftSide = new List <bool>();

        leftSide.Add(_triangleALeftSide);
        leftSide.Add(_triangleBLeftSide);
        leftSide.Add(_triangleCLeftSide);


        MeshTriangle leftMeshTriangle  = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex);
        MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex);
        MeshTriangle meshTriangle      = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], _triangle.SubmeshIndex);

        bool left  = false;
        bool right = false;

        for (int i = 0; i < 3; i++)
        {
            if (leftSide[i])// left
            {
                if (!left)
                {
                    left = true;
                    leftMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    leftMeshTriangle.Vertices[1] = leftMeshTriangle.Vertices[0];

                    leftMeshTriangle.Uvs[0] = _triangle.Uvs[i];
                    leftMeshTriangle.Uvs[1] = leftMeshTriangle.Uvs[0];

                    leftMeshTriangle.Normals[0] = _triangle.Normals[i];
                    leftMeshTriangle.Normals[1] = leftMeshTriangle.Normals[0];
                }
                else
                {
                    leftMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    leftMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    leftMeshTriangle.Uvs[1]      = _triangle.Uvs[i];
                }
            }
            else  // right
            {
                if (!right)
                {
                    right = true;
                    rightMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    rightMeshTriangle.Vertices[1] = rightMeshTriangle.Vertices[0];

                    rightMeshTriangle.Uvs[0] = _triangle.Uvs[i];
                    rightMeshTriangle.Uvs[1] = rightMeshTriangle.Uvs[0];

                    rightMeshTriangle.Normals[0] = _triangle.Normals[i];
                    rightMeshTriangle.Normals[1] = rightMeshTriangle.Normals[0];
                }
                else
                {
                    rightMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    rightMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    rightMeshTriangle.Uvs[1]      = _triangle.Uvs[i];
                }
            }
        }

        // now to find the intersection points between the solo point and the others
        float   normalizeDistance;
        float   distance;
        Vector3 edgeVector = Vector3.zero; // edge lenght and direction

        edgeVector = rightMeshTriangle.Vertices[0] - leftMeshTriangle.Vertices[0];
        _plane.Raycast(new Ray(leftMeshTriangle.Vertices[0], edgeVector.normalized), out distance);

        normalizeDistance = distance / edgeVector.magnitude;
        Vector3 vertLeft   = Vector3.Lerp(leftMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[0], normalizeDistance);
        Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Normals[0], rightMeshTriangle.Normals[0], normalizeDistance);
        Vector2 uvLeft     = Vector2.Lerp(leftMeshTriangle.Uvs[0], rightMeshTriangle.Uvs[0], normalizeDistance);

        edgeVector = rightMeshTriangle.Vertices[1] - leftMeshTriangle.Vertices[1];
        _plane.Raycast(new Ray(leftMeshTriangle.Vertices[1], edgeVector.normalized), out distance);

        normalizeDistance = distance / edgeVector.magnitude;
        Vector3 vertRight   = Vector3.Lerp(leftMeshTriangle.Vertices[1], rightMeshTriangle.Vertices[1], normalizeDistance);
        Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Normals[1], rightMeshTriangle.Normals[1], normalizeDistance);
        Vector2 uvRight     = Vector2.Lerp(leftMeshTriangle.Uvs[1], rightMeshTriangle.Uvs[1], normalizeDistance);

        if (vertLeft != vertRight)
        {
            //tracking newly created points
            _addedVertices.Add(vertLeft);
            _addedVertices.Add(vertRight);
        }

        // make the new triangles
        MeshTriangle currentTriangle;

        Vector3[] updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], vertLeft, vertRight };
        Vector3[] updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], normalLeft, normalRight };
        Vector2[] updatedUvs      = new Vector2[] { leftMeshTriangle.Uvs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add it
            _leftSide.AddTriangle(currentTriangle);
        }


        updatedVertices = new Vector3[] { leftMeshTriangle.Vertices[0], leftMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { leftMeshTriangle.Normals[0], leftMeshTriangle.Normals[1], normalRight };
        updatedUvs      = new Vector2[] { leftMeshTriangle.Uvs[0], leftMeshTriangle.Uvs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add it
            _leftSide.AddTriangle(currentTriangle);
        }


        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], vertLeft, vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], normalLeft, normalRight };
        updatedUvs      = new Vector2[] { rightMeshTriangle.Uvs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add it
            _rightSide.AddTriangle(currentTriangle);
        }


        updatedVertices = new Vector3[] { rightMeshTriangle.Vertices[0], rightMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { rightMeshTriangle.Normals[0], rightMeshTriangle.Normals[1], normalRight };
        updatedUvs      = new Vector2[] { rightMeshTriangle.Uvs[0], rightMeshTriangle.Uvs[1], uvRight };


        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUvs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            // check if it is facing the right way
            FacingCheck(currentTriangle);
            // add it
            _rightSide.AddTriangle(currentTriangle);
        }
    }
Example #13
0
 void Awake()
 {
     I_MeshT = GetComponentInChildren <MeshTriangle>();
     I_Line  = GetComponentInChildren <LineRenderer>();
 }
Example #14
0
 /// <summary>
 /// Add the vertices of the given triangle to our
 /// vertex lookup dictionary and emit a triangle.
 /// </summary>
 void StoreTriangle(MeshTriangle triangle)
 {
     for (int i = 0; i < 3; ++i)
     {
         XYZ p = triangle.get_Vertex(i);
         PointInt q = new PointInt(p);
         _triangles.Add(_vertices.AddVertex(q));
     }
 }
Example #15
0
    public static void CutGameobject(GameObject originalGameObject, Vector3 contactPoint, Vector3 direction, bool addRigidbody = false)
    {
        if (currentlyCutting)
        {
            return;
        }

        currentlyCutting = true;

        originalMesh = originalGameObject.GetComponent <MeshFilter>().mesh;

        var plane = new Plane(originalGameObject.transform.InverseTransformDirection(direction), originalGameObject.transform.InverseTransformPoint(contactPoint));

        var addedVertices = new List <Vector3>();

        var leftMesh  = new GeneratedMesh();
        var rightMesh = new GeneratedMesh();

        int[] submeshIndices;
        int   triangleIndexA, triangleIndexB, triangleIndexC;

        for (int i = 0; i < originalMesh.subMeshCount; i++)
        {
            submeshIndices = originalMesh.GetTriangles(i);

            for (int j = 0; j < submeshIndices.Length; j += 3)
            {
                triangleIndexA = submeshIndices[j];
                triangleIndexB = submeshIndices[j + 1];
                triangleIndexC = submeshIndices[j + 2];

                MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i);

                bool[] pointsOnLeftSide = new bool [3];

                pointsOnLeftSide[0] = plane.GetSide(originalMesh.vertices[triangleIndexA]);
                pointsOnLeftSide[1] = plane.GetSide(originalMesh.vertices[triangleIndexB]);
                pointsOnLeftSide[2] = plane.GetSide(originalMesh.vertices[triangleIndexC]);

                if (pointsOnLeftSide[0] && pointsOnLeftSide[1] && pointsOnLeftSide[2])
                {
                    leftMesh.AddTriangle(currentTriangle);
                }
                else if (!pointsOnLeftSide[0] && !pointsOnLeftSide[1] && !pointsOnLeftSide[2])
                {
                    rightMesh.AddTriangle(currentTriangle);
                }
                else
                {
                    CutTriangle(plane, currentTriangle, pointsOnLeftSide, leftMesh, rightMesh, addedVertices);
                }
            }

            FillCut(addedVertices, plane, leftMesh, rightMesh);

            GenerateCutterGameobject(originalGameObject, leftMesh, addRigidbody, Vector3.up);
            GenerateCutterGameobject(originalGameObject, rightMesh, addRigidbody, Vector3.left);

            currentlyCutting = false;
        }
    }
        void SubDivideSoffits_CreateFireRatedLayers(Document doc)
        {
            try
            {
                #region Get Soffits
                List <Element> Soffits = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors).ToElements().Where(m => !(m is ElementType)).ToList();

                #endregion

                //Subdivide
                foreach (Element Soffit in Soffits.Where(m => m.Name.ToLower().Contains("eave")))
                {
                    #region Get Soffit Geometry
                    Options ops = new Options();
                    ops.DetailLevel = ViewDetailLevel.Fine;
                    ops.IncludeNonVisibleObjects = true;
                    GeometryElement Geo = Soffit.get_Geometry(ops);

                    #endregion

                    foreach (var item in Geo)
                    {
                        if (item is Solid)
                        {
                            #region Get one of the Main Faces, it doesn't really matter if it is top or bottom
                            Solid       GSol = item as Solid;
                            List <Face> Fs   = new List <Face>();
                            foreach (Face f in GSol.Faces)
                            {
                                Fs.Add(f);
                            }
                            Face F = Fs.Where(m => m.Area == Fs.Max(a => a.Area)).First();
                            #endregion

                            #region Triangulate the Face with max detail
                            Mesh M = F.Triangulate(1);
                            #endregion

                            #region Create Variables for: the curves that will define the new Soffits, List of Custom Triangle Class, List of Custom Pair of Triangle Class
                            List <List <Curve> > LLC       = new List <List <Curve> >();
                            List <Triangle>      Triangles = new List <Triangle>();
                            List <TrianglePair>  TPairs    = new List <TrianglePair>();

                            #endregion

                            #region Loop Through Triangles & Add Them to the list of My Triangle Class
                            for (int i = 0; i < M.NumTriangles; i++)
                            {
                                List <Curve> LC = new List <Curve>();

                                #region Make List of Curves From Triangle
                                MeshTriangle MT     = M.get_Triangle(i);
                                List <Curve> Curves = new List <Curve>();
                                Curve        C      = Line.CreateBound(MT.get_Vertex(0), MT.get_Vertex(1)) as Curve;
                                Curves.Add(C);
                                C = Line.CreateBound(MT.get_Vertex(1), MT.get_Vertex(2)) as Curve;
                                Curves.Add(C);
                                C = Line.CreateBound(MT.get_Vertex(2), MT.get_Vertex(0)) as Curve;
                                Curves.Add(C);
                                #endregion

                                Triangle T = new Triangle();
                                T.Sides = new List <Curve>();
                                T.Sides = Curves;

                                T.Vertices = new List <XYZ>();
                                T.Vertices.Add(MT.get_Vertex(0));
                                T.Vertices.Add(MT.get_Vertex(1));
                                T.Vertices.Add(MT.get_Vertex(2));
                                Triangles.Add(T);
                            }
                            #endregion

                            #region Loop Through Triangles And Create Trapezoid Pairs To Catch The Segments, Getting Rid of The Shared sides
                            bool GO = true;
                            do
                            {
                                Triangle TKeeper1 = new Triangle();
                                Triangle TKeeper2 = new Triangle();

                                foreach (Triangle T in Triangles)
                                {
                                    TKeeper1 = new Triangle();
                                    foreach (Triangle T2 in Triangles)
                                    {
                                        TKeeper2 = new Triangle();
                                        if (T != T2)
                                        {
                                            if (FindCurvesFacing(T, T2) != null)
                                            {
                                                if (FindCurvesFacing(T, T2)[0].Length == T.Sides.Min(c => c.Length) ||
                                                    FindCurvesFacing(T, T2)[1].Length == T2.Sides.Min(c => c.Length))
                                                {
                                                    continue;
                                                }
                                                Curve[] Cs = FindCurvesFacing(T, T2);
                                                T.Sides.Remove(Cs[0]);
                                                T2.Sides.Remove(Cs[1]);
                                                if (T.Sides.Count() == 2 && T2.Sides.Count() == 2)
                                                {
                                                    TKeeper1 = T;
                                                    TKeeper2 = T2;
                                                    goto ADDANDGOROUND;
                                                }
                                            }
                                        }
                                    }
                                }
                                GO = false;
ADDANDGOROUND:
                                if (GO)
                                {
                                    Triangles.Remove(TKeeper1);
                                    Triangles.Remove(TKeeper2);
                                    TrianglePair TP = new TrianglePair();
                                    TP.T1 = TKeeper1;
                                    TP.T2 = TKeeper2;
                                    TPairs.Add(TP);
                                }
                            } while(GO);

                            #endregion

                            #region Create Curve Loops From Triangle Pairs
                            foreach (TrianglePair TPair in TPairs)
                            {
                                List <Curve> Cs = new List <Curve>();

                                Cs.AddRange(TPair.T1.Sides);
                                Cs.AddRange(TPair.T2.Sides);

                                LLC.Add(Cs);
                            }
                            #endregion

                            double    Offset = Convert.ToDouble(Soffit.LookupParameter("Height Offset From Level").AsValueString());
                            FloorType FT     = (Soffit as Floor).FloorType;
                            Level     Lvl    = doc.GetElement((Soffit as Floor).LevelId) as Level;

                            #region Delete Old Soffit If All Went Well
                            using (Transaction T = new Transaction(doc, "Delete Soffit"))
                            {
                                T.Start();
                                doc.Delete(Soffit.Id);
                                T.Commit();
                            }
                            #endregion

                            #region Sort The Lists of Curves and Create The New Segments
                            foreach (List <Curve> LC in LLC)
                            {
                                List <Curve> LCSorted = new List <Curve>();
                                try
                                {
                                    LCSorted = SortCurvesContiguous(LC, false);
                                }

                                #region Exception Details if Curves Could not be sorted
                                catch (Exception EXC)
                                {
                                    string exmsge = EXC.Message;
                                }

                                #endregion

                                CurveArray CA = new CurveArray();
                                foreach (Curve C in LCSorted)
                                {
                                    CA.Append(C);
                                }

                                using (Transaction T = new Transaction(doc, "Make Segment"))
                                {
                                    T.Start();
                                    Floor newFloor = doc.Create.NewFloor(CA, FT, Lvl, false);
                                    newFloor.LookupParameter("Height Offset From Level").SetValueString(Offset.ToString());
                                    T.Commit();
                                }
                            }
                            #endregion
                        }
                    }
                }
                //refresh collection
                Soffits = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors).ToElements().Where(m => !(m is ElementType)).ToList();
                //test soffits for needing fire rating
                foreach (Element Soffit in Soffits.Where(m => m.Name.ToLower().Contains("eave")))
                {
                    #region Get Soffit Geometry
                    Options ops = new Options();
                    ops.DetailLevel = ViewDetailLevel.Fine;
                    ops.IncludeNonVisibleObjects = true;
                    GeometryElement Geo = Soffit.get_Geometry(ops);

                    #endregion

                    foreach (var item in Geo)
                    {
                        if (item is Solid)
                        {
                            #region Find boundary Void Element
                            List <Element> MaybeBoundary  = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors).ToElements().Where(m => !(m is ElementType)).ToList();
                            Element        BoundryElement = MaybeBoundary.Where(m => !(m is FloorType) && m.Name == "Boundary").First();

                            #endregion

                            #region Get Intersection of Boundary and eave
                            PolygonAnalyser   com    = new PolygonAnalyser();
                            List <CurveArray> CArray = com.Execute(BoundryElement as Floor, Soffit as Floor);

                            Level L = doc.GetElement(Soffit.LevelId) as Level;

                            #endregion

                            foreach (CurveArray CA in CArray)
                            {
                                #region Sort The Curves
                                IList <Curve> CAL = new List <Curve>();
                                foreach (Curve C in CA)
                                {
                                    CAL.Add(C);
                                }

                                List <Curve> Curves       = SortCurvesContiguous(CAL, false);
                                List <XYZ>   NewCurveEnds = new List <XYZ>();

                                #endregion

                                #region Close the loop if nesesary
                                CurveLoop CL = new CurveLoop();
                                foreach (Curve curv in Curves)
                                {
                                    CL.Append(curv);
                                }
                                if (CL.IsOpen())
                                {
                                    Curves.Add(Line.CreateBound(CL.First().GetEndPoint(0), CL.Last().GetEndPoint(1)) as Curve);
                                }
                                #endregion

                                #region Recreate a Curve Array
                                Curves = SortCurvesContiguous(Curves, false);

                                CurveArray CA2 = new CurveArray();

                                int i = 0;
                                foreach (Curve c in Curves)
                                {
                                    CA2.Insert(c, i);
                                    i += 1;
                                }

                                #endregion

                                #region Create The New Fire Rated Layer element
                                FloorType   ft = new FilteredElementCollector(doc).WhereElementIsElementType().OfCategory(BuiltInCategory.OST_Floors).ToElements().Where(m => m.Name == "Fire Rated Layer").First() as FloorType;
                                Transaction T  = new Transaction(doc, "Fire Rated Layer Creation");
                                try
                                {
                                    T.Start();
                                    Floor  F  = doc.Create.NewFloor(CA2, ft, L, false);
                                    string s  = Soffit.LookupParameter("Height Offset From Level").AsValueString();
                                    double si = Convert.ToDouble(s);
                                    si = si + (Convert.ToDouble(Soffit.LookupParameter("Thickness").AsValueString()));
                                    F.LookupParameter("Height Offset From Level").SetValueString(si.ToString());
                                    T.Commit();
                                }
                                catch (Exception EX)
                                {
                                    T.RollBack();
                                    string EXmsg = EX.Message;
                                }

                                #endregion
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string mesg = ex.Message;
            }
        }
Example #17
0
    public void BuildPlanet()
    {
        Vector3    planetPos = transform.position;
        Quaternion planetRot = transform.rotation;

        // Reset planet position to origin temporarily
        transform.position = Vector3.zero;
        transform.rotation = Quaternion.identity;

        if (vectors != null)
        {
            vectors.Clear();
        }
        else
        {
            vectors = new List <Vector3>();
        }

        if (indices != null)
        {
            indices.Clear();
        }
        else
        {
            indices = new List <int>();
        }

        if (detailLevel < 0)
        {
            detailLevel = 0;
        }

        //Mesh generation freezes up for detail levels greater than 4
        if (detailLevel > 5)
        {
            detailLevel = 5;
        }

        unitScale = detailLevel;

        Geometry.Icosahedron(vectors, indices);

        // Subdivide icosahedron
        for (int i = 0; i < detailLevel; i++)
        {
            Geometry.Subdivide(vectors, indices, true);
        }

        // Normalize vectors to "inflate" the icosahedron into a sphere.
        for (int i = 0; i < vectors.Count; i++)
        {
            // You can also multiply this by some amount to change the build size
            vectors[i] = Vector3.Normalize(vectors[i]);
        }

        Dictionary <Vector3, List <MeshTriangle> > trianglesByTileFaceVerts = new Dictionary <Vector3, List <MeshTriangle> >();

        // Map each vertex to its surrounding triangles
        for (int t = 0; t < indices.Count - 2; t += 3)
        {
            Vector3 v0 = vectors[indices[t]];
            Vector3 v1 = vectors[indices[t + 1]];
            Vector3 v2 = vectors[indices[t + 2]];

            if (!trianglesByTileFaceVerts.ContainsKey(v0))
            {
                trianglesByTileFaceVerts.Add(v0, new List <MeshTriangle>());
            }

            if (!trianglesByTileFaceVerts.ContainsKey(v1))
            {
                trianglesByTileFaceVerts.Add(v1, new List <MeshTriangle>());
            }

            if (!trianglesByTileFaceVerts.ContainsKey(v2))
            {
                trianglesByTileFaceVerts.Add(v2, new List <MeshTriangle>());
            }

            MeshTriangle mTri = new MeshTriangle(v0, v1, v2, t, t + 1, t + 2);

            trianglesByTileFaceVerts[v0].Add(mTri);
            trianglesByTileFaceVerts[v1].Add(mTri);
            trianglesByTileFaceVerts[v2].Add(mTri);
        }

        // If generating whole planet as a single mesh
        if (GenerateAsSingleMesh)
        {
            MeshFilter mf = GetComponent <MeshFilter>();
            if (mf == null)
            {
                mf = gameObject.AddComponent <MeshFilter>();
            }
            if (GetComponent <MeshRenderer>() == null)
            {
                MeshRenderer mRenderer = gameObject.AddComponent <MeshRenderer>();
                mRenderer.sharedMaterial = GroupMaterials[0];
            }

            List <Vector3> verts = new List <Vector3>();
            List <int>     tris  = new List <int>();
            List <Vector3> norms = new List <Vector3>();

            Transform helper = new GameObject("Helper Transform").transform;
            helper.parent = transform;

            foreach (var kvp in trianglesByTileFaceVerts)
            {
                GenerateTileSubMesh(kvp.Key, kvp.Value, ref verts, ref tris, ref norms, helper);
            }

            Mesh mesh = new Mesh();
            mesh.vertices  = verts.ToArray();
            mesh.triangles = tris.ToArray();
            mesh.normals   = norms.ToArray();
            mesh.RecalculateBounds();

            mf.sharedMesh = mesh;

            DestroyImmediate(helper.gameObject);

            transform.position = planetPos;
            transform.rotation = planetRot;

            return;
        }

        // Generate tile gameobjects
        Dictionary <Vector3, Tile> tilesByFaceVerts = new Dictionary <Vector3, Tile>();

        tiles = new List <Tile>();
        // Create the tile meshes : O(n)
        foreach (var kvp in trianglesByTileFaceVerts)
        {
            Tile t = CreateTile(kvp.Key, kvp.Value);

            tiles.Add(t);
            // Map face vertices to the generated tile for neighbor finding
            tilesByFaceVerts.Add(kvp.Key, t);
        }

        // Find neighbors : O(n)
        foreach (var kvp in tilesByFaceVerts)
        {
            List <Tile> neighbors = new List <Tile>();

            // Loop over all vertices in each adjacent triangle
            foreach (MeshTriangle tri in trianglesByTileFaceVerts[kvp.Key])
            {
                for (int i = 0; i < 3; i++)
                {
                    Vector3 nVert = tri.Vertices[i];
                    Tile    t;
                    // Look up the tile corresponding to the face vertex in the adjacent triangle
                    if (tilesByFaceVerts.TryGetValue(nVert, out t))
                    {
                        if (!neighbors.Contains(t) && t != kvp.Value)
                        {
                            neighbors.Add(tilesByFaceVerts[nVert]);
                        }
                    }
                }
            }

            kvp.Value.neighborTiles = neighbors;
        }

        TileCount      = tiles.Count;
        tilesGenerated = true;

        //Assign tiles to navManager
        navManager.setWorldTiles(tiles);

        // Restore position and rotation
        transform.position = planetPos;
        transform.rotation = planetRot;
    }
Example #18
0
 public bool HasSimilarCorner(MeshTriangle meshTriangle, float maxDistanceSqr)
 {
     return(point1.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr || point2.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr || point3.GetDistanceSqrToClosestPoint(meshTriangle.point1, meshTriangle.point2, meshTriangle.point3) <= maxDistanceSqr);
 }
Example #19
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument    uidoc = uiapp.ActiveUIDocument;
            Application   app   = uiapp.Application;
            Document      doc   = uidoc.Document;



            //WALLS FACES
            List <PlanarFace> wallFaces = new List <PlanarFace>();

            //WALLS
            Reference wallRef = uidoc.Selection.PickObject(ObjectType.Element, "Select a Wall");

            Element wall = doc.GetElement(wallRef);

            LocationCurve lc = wall.Location as LocationCurve;

            Line wallLine = lc.Curve as Line;

            XYZ perpDir = wallLine.Direction.CrossProduct(XYZ.BasisZ);

            Options opt = new Options();

            opt.ComputeReferences        = true;
            opt.IncludeNonVisibleObjects = false;
            opt.View = doc.ActiveView;

            GeometryElement geomElem = doc.GetElement(wallRef).get_Geometry(opt);

            foreach (GeometryObject geomObj in geomElem)
            {
                Solid geomSolid = geomObj as Solid;
                foreach (Face geomFace in geomSolid.Faces)
                {
                    XYZ faceNormal = geomFace.ComputeNormal(new UV(0.5, 0.5));

                    //select only the vertical faces
                    if (faceNormal.CrossProduct(perpDir).IsAlmostEqualTo(XYZ.Zero))
                    {
                        PlanarFace pf = geomFace as PlanarFace;
                        wallFaces.Add(pf);
                    }
                }
            }


            //GET MESH
            Reference meshRef = uidoc.Selection.PickObject(ObjectType.Element, "Select Mesh");
            Element   e       = doc.GetElement(meshRef);

            GeometryElement geomElemSurvey = e.get_Geometry(opt);

            Mesh geomMesh = null;

            foreach (GeometryObject geomObj in geomElemSurvey)
            {
                try
                {
                    GeometryInstance gi = geomObj as GeometryInstance;
                    foreach (GeometryObject element in gi.GetInstanceGeometry())
                    {
                        geomMesh = element as Mesh;
                    }
                }
                catch
                {
                    geomMesh = geomObj as Mesh;
                }
            }


            using (Transaction t = new Transaction(doc, "Find intersection"))
            {
                t.Start();

                List <XYZ> intPts = new List <XYZ>();

                for (int i = 0; i < geomMesh.NumTriangles; i++)
                {
                    MeshTriangle triangle = geomMesh.get_Triangle(i);
                    XYZ          vertex1  = triangle.get_Vertex(0);
                    XYZ          vertex2  = triangle.get_Vertex(1);
                    XYZ          vertex3  = triangle.get_Vertex(2);

                    Line[] edgeList = new Line[3];

                    try
                    {
                        Line[] edges = new Line[] { Line.CreateBound(vertex1, vertex2), Line.CreateBound(vertex1, vertex3), Line.CreateBound(vertex2, vertex3) };

                        for (int k = 0; k < edgeList.Length; k++)
                        {
                            edgeList[k] = edges[k];
                        }
                    }
                    catch { }


                    //		        Plane facePlane = Plane.CreateByThreePoints(vertex1, vertex2, vertex3);
                    //		        SketchPlane sp = SketchPlane.Create(doc, facePlane);
                    //		        doc.Create.NewModelCurve(edge12, sp);
                    //		        doc.Create.NewModelCurve(edge13, sp);
                    //		        doc.Create.NewModelCurve(edge23, sp);



                    foreach (PlanarFace pf in wallFaces)
                    {
                        XYZ[] pts = new XYZ[2];

                        int count = 0;

                        if (edgeList[0] != null)
                        {
                            foreach (Line edge in edgeList)
                            {
                                IntersectionResultArray intersections = null;
                                SetComparisonResult     scr           = pf.Intersect(edge, out intersections);



                                if (scr == SetComparisonResult.Overlap && intersections.Size == 1)
                                {
                                    for (int j = 0; j < intersections.Size; j++)
                                    {
                                        //TaskDialog.Show("r", intersections.get_Item(i));
                                    }

                                    //TaskDialog.Show("r", intersections.Size.ToString());

                                    IntersectionResult iResult = intersections.get_Item(0);
                                    intPts.Add(iResult.XYZPoint);
                                    pts[count] = iResult.XYZPoint;
                                    count      = 1;

                                    if (pts.Length == 2 && pts[1] != null)
                                    {
                                        //		                TaskDialog.Show("r", String.Format("{0}\n{1}",pts[0], pts[1]));
                                        try
                                        {
                                            Plane       wallPlane = Plane.CreateByNormalAndOrigin(pf.FaceNormal, pf.Origin);
                                            SketchPlane spWall    = SketchPlane.Create(doc, wallPlane);
                                            doc.Create.NewModelCurve(Line.CreateBound(pts[0], pts[1]), spWall);
                                        }
                                        catch { }
                                    }
                                }
                            }
                        }
                    }
                }

                t.Commit();
            }

            return(Result.Succeeded);
        }
        /// <summary>
        /// Combine coplanar triangles from the faceted body if they share the edge. From this process, polygonal faces (with or without holes) will be created
        /// </summary>
        public void SimplifyAndMergeFaces()
        {
            int noTriangle = (IsMesh)? _meshGeom.NumTriangles : _geom.TriangleCount;
            int noVertices = (IsMesh)? _meshGeom.Vertices.Count : _geom.VertexCount;
            IEqualityComparer <XYZ>       normalComparer     = new vectorCompare();
            Dictionary <XYZ, List <int> > faceSortedByNormal = new Dictionary <XYZ, List <int> >(normalComparer);

            for (int ef = 0; ef < noTriangle; ++ef)
            {
                IList <int> vertIndex = new List <int>();

                if (IsMesh)
                {
                    MeshTriangle f = _meshGeom.get_Triangle(ef);
                    vertIndex.Add((int)f.get_Index(0));
                    vertIndex.Add((int)f.get_Index(1));
                    vertIndex.Add((int)f.get_Index(2));
                }
                else
                {
                    TriangleInShellComponent f = _geom.GetTriangle(ef);
                    vertIndex.Add(f.VertexIndex0);
                    vertIndex.Add(f.VertexIndex1);
                    vertIndex.Add(f.VertexIndex2);
                }

                IndexFace intF = new IndexFace(vertIndex);
                facesColl.Add(ef, intF);     // Keep faces in a dictionary and assigns ID
                List <int> fIDList;

                if (!faceSortedByNormal.TryGetValue(intF.normal, out fIDList))
                {
                    fIDList = new List <int>();
                    fIDList.Add(ef);
                    faceSortedByNormal.Add(intF.normal, fIDList);
                }
                else
                {
                    if (!fIDList.Contains(ef))
                    {
                        fIDList.Add(ef);
                    }
                }
            }

            foreach (KeyValuePair <XYZ, List <int> > fListDict in faceSortedByNormal)
            {
                List <int> mergedFaceList = null;
                if (fListDict.Value.Count > 1)
                {
                    TryMergeFaces(fListDict.Value, out mergedFaceList);
                    if (mergedFaceList != null && mergedFaceList.Count > 0)
                    {
                        // insert only new face indexes as the mergedlist from different vertices can be duplicated
                        foreach (int fIdx in mergedFaceList)
                        {
                            if (!_mergedFaceList.Contains(fIdx))
                            {
                                _mergedFaceList.Add(fIdx);
                            }
                        }
                    }
                }
                else if (!_mergedFaceList.Contains(fListDict.Value[0]))
                {
                    _mergedFaceList.Add(fListDict.Value[0]); // No pair face, add it into the mergedList
                }
            }
        }
        public static string GetFacesAndEdges(Element e, bool startFromZero)
        {
            String xx = "";
            bool   RetainCurvedSurfaceFacets = true;

            // Get element geometry
            Options         opt      = new Options();
            GeometryElement geomElem = e.get_Geometry(opt);

            int[]         triangleIndices = new int[3];
            XYZ[]         triangleCorners = new XYZ[3];
            List <string> faceVertices    = new List <string>();
            List <string> faceNormals     = new List <string>();
            List <string> faceElements    = new List <string>();

            //// First we need to get transformation
            //LocationCurve lc = e.Location as LocationCurve;

            //// Get curve starting- and endpoint
            //XYZ startingPoint = lc.Curve.GetEndPoint(0);
            //XYZ endPoint = lc.Curve.GetEndPoint(1);

            foreach (GeometryObject geomObj in geomElem)
            {
                Solid geomSolid = geomObj as Solid;
                if (null != geomSolid)
                {
                    faceVertices.Clear();
                    faceNormals.Clear();
                    faceElements.Clear();

                    foreach (Face face in geomSolid.Faces)
                    {
                        // Triangulate face to get mesh
                        Mesh mesh = face.Triangulate();

                        int nTriangles = mesh.NumTriangles;

                        IList <XYZ> vertices = mesh.Vertices;

                        int nVertices = vertices.Count;

                        List <int> vertexCoordsMm = new List <int>(3 * nVertices);

                        // A vertex may be reused several times with
                        // different normals for different faces, so
                        // we cannot precalculate normals per vertex.
                        // List<double> normals = new List<double>( 3 * nVertices );

                        // Extract vertices
                        foreach (XYZ v in vertices)
                        {
                            vertexCoordsMm.Add(ConvertLengthToMM(v.X));
                            vertexCoordsMm.Add(ConvertLengthToMM(v.Y));
                            vertexCoordsMm.Add(ConvertLengthToMM(v.Z));
                        }

                        // Loop over triangles
                        for (int i = 0; i < nTriangles; ++i)
                        {
                            MeshTriangle triangle = mesh.get_Triangle(i);

                            for (int j = 0; j < 3; ++j)
                            {
                                int k = (int)triangle.get_Index(j);
                                triangleIndices[j] = k;
                                triangleCorners[j] = vertices[k];
                            }

                            // Calculate constant triangle facet normal.
                            XYZ v = triangleCorners[1]
                                    - triangleCorners[0];
                            XYZ w = triangleCorners[2]
                                    - triangleCorners[0];
                            XYZ triangleNormal = v
                                                 .CrossProduct(w)
                                                 .Normalize();

                            // List to store vertice indexes in the form: [v1//vn1 v2//vn2 v3//vn3]
                            List <string> vertIndexes = new List <string>();

                            for (int j = 0; j < 3; ++j)
                            {
                                int nFaceVertices = faceVertices.Count;

                                //if(nFaceVertices != faceNormals.Count)
                                //{
                                //    xx += "expected equal number of face vertex and normal coordinates\n";
                                //}

                                int i3 = triangleIndices[j] * 3;

                                // Rotate the X, Y and Z directions,
                                // since the Z direction points upward
                                // in Revit as opposed to sideways or
                                // outwards or forwards in WebGL.

                                string vStr = $"v {vertexCoordsMm[i3]} {vertexCoordsMm[i3 + 1]} {vertexCoordsMm[i3 + 2]}";

                                // get vertice index
                                int vidx = faceVertices.IndexOf(vStr);

                                // add if not exist
                                if (vidx == -1)
                                {
                                    faceVertices.Add(vStr);
                                    vidx = faceVertices.Count - 1;
                                }


                                string vnStr = "";
                                if (RetainCurvedSurfaceFacets)
                                {
                                    vnStr = $"vn {Math.Round(triangleNormal.X, 2)} {Math.Round(triangleNormal.Y, 2)} {Math.Round(triangleNormal.Z, 2)}";
                                }
                                else
                                {
                                    UV uv = face.Project(
                                        triangleCorners[j]).UVPoint;

                                    XYZ normal = face.ComputeNormal(uv);

                                    vnStr = $"vn {Math.Round(normal.X, 2)} {Math.Round(normal.Y, 2)} {Math.Round(normal.Z, 2)}";
                                }

                                // get face normal index
                                int vnidx = faceNormals.IndexOf(vnStr);

                                // add if not in list
                                if (vnidx == -1)
                                {
                                    faceNormals.Add(vnStr);
                                    vnidx = faceNormals.Count - 1;
                                }

                                // add indexes to list
                                vertIndexes.Add($"{vidx+1+objStartIndex}/{vnidx+1 + objStartNormal}");
                            }

                            // Store face elements
                            string fStr = $"f {vertIndexes[0]} {vertIndexes[1]} {vertIndexes[2]}";
                            faceElements.Add(fStr);
                        }
                    }

                    // Write to string
                    xx += String.Join("\n\t", faceVertices) + "\n\t";
                    xx += String.Join("\n\t", faceNormals) + "\n\t";
                    xx += String.Join("\n\t", faceElements) + "\n\t";
                    if (!startFromZero)
                    {
                        objStartIndex  += faceVertices.Count;
                        objStartNormal += faceNormals.Count;
                    }
                }

                Mesh     geomMesh  = geomObj as Mesh;
                Curve    geomCurve = geomObj as Curve;
                Point    geomPoint = geomObj as Point;
                PolyLine geomPoly  = geomObj as PolyLine;

                GeometryInstance geomInst = geomObj as GeometryInstance;
                if (null != geomInst)
                {
                    GeometryElement geomElement = geomInst.GetInstanceGeometry();
                    foreach (GeometryObject geomObj1 in geomElement)
                    {
                        Solid geomSolid1 = geomObj1 as Solid;
                        if (null != geomSolid1)
                        {
                            Console.Out.WriteLine("got element: " + geomSolid1.Faces);
                        }
                    }
                }
            }

            return(xx);
        }
Example #22
0
        int getGeometry(Element e)
        {
            bool RetainCurvedSurfaceFacets = true;

            Options         opt = new Options();
            GeometryElement geo = e.get_Geometry(opt);

            if (geo == null)
            {
                return(0);
            }

            List <int>    faceIndices  = new List <int>();
            List <double> faceVertices = new List <double>();
            List <double> faceNormals  = new List <double>();

            int[] triangleIndices = new int[3];
            XYZ[] triangleCorners = new XYZ[3];

            foreach (GeometryObject obj in geo)
            {
                Solid solid = obj as Solid;

                if (solid != null && 0 < solid.Faces.Size)
                {
                    faceIndices.Clear();
                    faceVertices.Clear();
                    faceNormals.Clear();

                    foreach (Face face in solid.Faces)
                    {
                        Mesh mesh = face.Triangulate();

                        int nTriangles = mesh.NumTriangles;

                        IList <XYZ> vertices = mesh.Vertices;

                        int nVertices = vertices.Count;

                        List <double> vertexCoordsMm = new List <double>(3 * nVertices);

                        // A vertex may be reused several times with
                        // different normals for different faces, so
                        // we cannot precalculate normals per vertex.
                        //List<double> normals = new List<double>( 3 * nVertices );

                        foreach (XYZ v in vertices)
                        {
                            // Translate the entire element geometry
                            // to the bounding box midpoint and scale
                            // to metric millimetres.

                            XYZ p = v;

                            vertexCoordsMm.Add(p.X * _footToMm);
                            vertexCoordsMm.Add(p.Y * _footToMm);
                            vertexCoordsMm.Add(p.Z * _footToMm);
                        }

                        for (int i = 0; i < nTriangles; ++i)
                        {
                            MeshTriangle triangle = mesh.get_Triangle(i);

                            for (int j = 0; j < 3; ++j)
                            {
                                int k = (int)triangle.get_Index(j);
                                triangleIndices[j] = k;
                                triangleCorners[j] = vertices[k];
                            }

                            // Calculate constant triangle facet normal.

                            XYZ v = triangleCorners[1]
                                    - triangleCorners[0];
                            XYZ w = triangleCorners[2]
                                    - triangleCorners[0];
                            XYZ triangleNormal = v
                                                 .CrossProduct(w)
                                                 .Normalize();

                            for (int j = 0; j < 3; ++j)
                            {
                                int nFaceVertices = faceVertices.Count;

                                //Debug.Assert(nFaceVertices.Equals(faceNormals.Count),
                                //  "expected equal number of face vertex and normal coordinates");

                                faceIndices.Add(nFaceVertices / 3);

                                int i3 = triangleIndices[j] * 3;

                                // Rotate the X, Y and Z directions,
                                // since the Z direction points upward
                                // in Revit as opposed to sideways or
                                // outwards or forwards in WebGL.

                                faceVertices.Add(vertexCoordsMm[i3 + 1]);
                                faceVertices.Add(vertexCoordsMm[i3 + 2]);
                                faceVertices.Add(vertexCoordsMm[i3]);

                                if (RetainCurvedSurfaceFacets)
                                {
                                    faceNormals.Add(triangleNormal.Y);
                                    faceNormals.Add(triangleNormal.Z);
                                    faceNormals.Add(triangleNormal.X);
                                }
                                else
                                {
                                    UV uv = face.Project(
                                        triangleCorners[j]).UVPoint;

                                    XYZ normal = face.ComputeNormal(uv);

                                    faceNormals.Add(normal.Y);
                                    faceNormals.Add(normal.Z);
                                    faceNormals.Add(normal.X);
                                }
                            }
                        }
                    }

                    // Scale the vertices to a [-1,1] cube
                    // centered around the origin. Translation
                    // to the origin was already performed above.

                    //double scale = 2.0 / FootToMm(MaxCoord(vsize));

                    //Debug.Print("position: [{0}],",
                    //  string.Join(", ",
                    //    faceVertices.ConvertAll<string>(
                    //      i => (i * scale).ToString("0.##"))));

                    //Debug.Print("normal: [{0}],",
                    //  string.Join(", ",
                    //    faceNormals.ConvertAll<string>(
                    //      f => f.ToString("0.##"))));

                    //Debug.Print("indices: [{0}],",
                    //  string.Join(", ",
                    //    faceIndices.ConvertAll<string>(
                    //      i => i.ToString())));
                }
            }

            return(faceIndices.Count);
        }
Example #23
0
    private static void SortVerticesFromIntersectedTriangle(MeshTriangle _triangle, List <bool> leftSide, MeshTriangle leftMeshTriangle, MeshTriangle rightMeshTriangle)
    {
        // These boolean values help us determine if either 1 or 2 verices of the intersecting triangle lie on a specific side
        bool oneVertexLeft  = false;
        bool oneVertexRight = false;

        // We sort the vertices of the triangle depending on which side of the plane it was on
        for (int i = 0; i < 3; i++)
        {
            if (leftSide[i])
            {
                // First time we have a vertex on the left side, we assume that that's the only vertex on that side
                if (!oneVertexLeft)
                {
                    oneVertexLeft = true;

                    leftMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    leftMeshTriangle.Vertices[1] = leftMeshTriangle.Vertices[0];

                    leftMeshTriangle.UVs[0] = _triangle.UVs[i];
                    leftMeshTriangle.UVs[1] = leftMeshTriangle.UVs[0];

                    leftMeshTriangle.Normals[0] = _triangle.Normals[i];
                    leftMeshTriangle.Normals[1] = leftMeshTriangle.Normals[0];
                }
                // If we encounter another vertex on the left side, simply overright what we had before
                else
                {
                    leftMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    leftMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    leftMeshTriangle.UVs[1]      = _triangle.UVs[i];
                }
            }
            else
            {
                if (!oneVertexRight)
                {
                    oneVertexRight = true;

                    rightMeshTriangle.Vertices[0] = _triangle.Vertices[i];
                    rightMeshTriangle.Vertices[1] = rightMeshTriangle.Vertices[0];

                    rightMeshTriangle.UVs[0] = _triangle.UVs[i];
                    rightMeshTriangle.UVs[1] = rightMeshTriangle.UVs[0];

                    rightMeshTriangle.Normals[0] = _triangle.Normals[i];
                    rightMeshTriangle.Normals[1] = rightMeshTriangle.Normals[0];
                }
                else
                {
                    rightMeshTriangle.Vertices[1] = _triangle.Vertices[i];
                    rightMeshTriangle.Normals[1]  = _triangle.Normals[i];
                    rightMeshTriangle.UVs[1]      = _triangle.UVs[i];
                }
            }
        }
    }
Example #24
0
    private static void CutTriangle(Plane _plane, MeshTriangle meshTri, bool tALS, bool TBLS, bool TCLS,
                                    GeneratedMesh lSide, GeneratedMesh rSide, List <Vector3> addedVert)
    {
        List <bool> leftSide = new List <bool>();

        leftSide.Add(tALS);
        leftSide.Add(TBLS);
        leftSide.Add(TCLS);

        MeshTriangle leftMeshTriangle  = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], meshTri.SMIndex);
        MeshTriangle rightMeshTriangle = new MeshTriangle(new Vector3[2], new Vector3[2], new Vector2[2], meshTri.SMIndex);

        bool left  = false;
        bool right = false;

        for (int i = 0; i < 3; i++)
        {
            if (leftSide[i])
            {
                if (!left)
                {
                    left = true;

                    leftMeshTriangle.Vert[0] = meshTri.Vert[i];
                    leftMeshTriangle.Vert[1] = leftMeshTriangle.Vert[0];

                    leftMeshTriangle.UV[0] = meshTri.UV[i];
                    leftMeshTriangle.UV[1] = leftMeshTriangle.UV[0];

                    leftMeshTriangle.Norm[0] = meshTri.Norm[i];
                    leftMeshTriangle.Norm[1] = leftMeshTriangle.Norm[0];
                }
                else
                {
                    leftMeshTriangle.Vert[1] = meshTri.Vert[i];
                    leftMeshTriangle.Norm[1] = meshTri.Vert[i];
                    leftMeshTriangle.UV[1]   = meshTri.Vert[i];
                }
            }
            else
            {
                if (!right)
                {
                    right = true;

                    rightMeshTriangle.Vert[0] = meshTri.Vert[i];
                    rightMeshTriangle.Vert[1] = rightMeshTriangle.Vert[0];

                    rightMeshTriangle.UV[0] = meshTri.UV[i];
                    rightMeshTriangle.UV[1] = rightMeshTriangle.UV[0];

                    rightMeshTriangle.Norm[0] = meshTri.Norm[i];
                    rightMeshTriangle.Norm[1] = rightMeshTriangle.Norm[0];
                }
                else
                {
                    rightMeshTriangle.Vert[1] = meshTri.Vert[i];
                    rightMeshTriangle.Norm[1] = meshTri.Vert[i];
                    rightMeshTriangle.UV[1]   = meshTri.Vert[i];
                }
            }
        }

        float normalizedDistance;
        float distance;

        _plane.Raycast(new Ray(leftMeshTriangle.Vert[0],
                               (rightMeshTriangle.Vert[0] - leftMeshTriangle.Vert[0]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vert[0] - leftMeshTriangle.Vert[0]).magnitude;
        Vector3 vertLeft = Vector3.Lerp(leftMeshTriangle.Vert[0], rightMeshTriangle.Vert[0], normalizedDistance);

        addedVert.Add(vertLeft);

        Vector3 normalLeft = Vector3.Lerp(leftMeshTriangle.Norm[0], rightMeshTriangle.Norm[0], normalizedDistance);
        Vector2 uvLeft     = Vector2.Lerp(leftMeshTriangle.UV[0], rightMeshTriangle.UV[0], normalizedDistance);

        _plane.Raycast(new Ray(leftMeshTriangle.Vert[1],
                               (rightMeshTriangle.Vert[1] - leftMeshTriangle.Vert[1]).normalized), out distance);

        normalizedDistance = distance / (rightMeshTriangle.Vert[1] - leftMeshTriangle.Vert[1]).magnitude;
        Vector3 vertRight = Vector3.Lerp(leftMeshTriangle.Vert[1], rightMeshTriangle.Vert[1], normalizedDistance);

        addedVert.Add(vertLeft);

        Vector3 normalRight = Vector3.Lerp(leftMeshTriangle.Norm[1], rightMeshTriangle.Norm[1], normalizedDistance);
        Vector2 uvRight     = Vector2.Lerp(leftMeshTriangle.UV[1], rightMeshTriangle.UV[1], normalizedDistance);

        MeshTriangle currentTriangle;

        Vector3[] updatedVert = new Vector3[] { leftMeshTriangle.Vert[0], vertLeft, vertRight };
        Vector3[] updatedNorm = new Vector3[] { leftMeshTriangle.Norm[0], normalLeft, normalRight };
        Vector2[] updatedUV   = new Vector2[] { leftMeshTriangle.UV[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex);

        if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            lSide.AddTriangle(currentTriangle);
        }

        updatedVert = new Vector3[] { leftMeshTriangle.Vert[0], leftMeshTriangle.Vert[1], vertRight };
        updatedNorm = new Vector3[] { leftMeshTriangle.Norm[0], leftMeshTriangle.Norm[1], normalRight };
        updatedUV   = new Vector2[] { leftMeshTriangle.UV[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex);

        if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            lSide.AddTriangle(currentTriangle);
        }

        updatedVert = new Vector3[] { rightMeshTriangle.Vert[0], vertLeft, vertRight };
        updatedNorm = new Vector3[] { rightMeshTriangle.Norm[0], normalLeft, normalRight };
        updatedUV   = new Vector2[] { rightMeshTriangle.UV[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex);

        if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            rSide.AddTriangle(currentTriangle);
        }

        updatedVert = new Vector3[] { rightMeshTriangle.Vert[0], rightMeshTriangle.Vert[1], vertRight };
        updatedNorm = new Vector3[] { rightMeshTriangle.Norm[0], rightMeshTriangle.Norm[1], normalRight };
        updatedUV   = new Vector2[] { rightMeshTriangle.UV[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVert, updatedNorm, updatedUV, meshTri.SMIndex);

        if (updatedVert[0] != updatedVert[1] && updatedVert[0] != updatedVert[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVert[1] - updatedVert[0], updatedVert[2] - updatedVert[0]), updatedVert[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            rSide.AddTriangle(currentTriangle);
        }
    }
Example #25
0
    public static void Cut(GameObject _originalGameObject, Vector3 _contactPoint, Vector3 _direction, Material _cutMaterial = null,
                           bool fill = true, bool _addRigidBody = false)
    {
        if (currentlyCutting)
        {
            return;
        }

        currentlyCutting = true;

        Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction),
                                _originalGameObject.transform.InverseTransformPoint(_contactPoint));

        originalGameObject = _originalGameObject;
        originalMesh       = _originalGameObject.GetComponent <MeshFilter>().mesh;
        List <Vector3> addedVertices = new List <Vector3>();

        GeneratedMesh leftMesh  = new GeneratedMesh();
        GeneratedMesh rightMesh = new GeneratedMesh();

        int[] submeshIndices;
        int   triangleIndexA, triangleIndexB, triangleIndexC;

        for (int i = 0; i < originalMesh.subMeshCount; i++)
        {
            submeshIndices = originalMesh.GetTriangles(i);

            for (int j = 0; j < submeshIndices.Length; j += 3)
            {
                triangleIndexA = submeshIndices[j];
                triangleIndexB = submeshIndices[j + 1];
                triangleIndexC = submeshIndices[j + 2];

                MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i);

                bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]);
                bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]);
                bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]);

                /*
                 *  Three different cases:
                 *  - The triangle is either above the plane
                 *  - The triangle is below the plane
                 *  - The place intersects the triangle
                 */
                if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide)
                {
                    leftMesh.AddTriangle(currentTriangle);
                }
                else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide)
                {
                    rightMesh.AddTriangle(currentTriangle);
                }
                else
                {
                    CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices);
                }
            }
        }

        // if either mesh has no vertices, return
        if (leftMesh.Vertices.Count == 0 || rightMesh.Vertices.Count == 0 || addedVertices.Count == 0)
        {
            currentlyCutting = false;
            return;
        }

        FillCut(addedVertices, plane, leftMesh, rightMesh);

        GenerateGameObject(leftMesh);
        GenerateGameObject(rightMesh);
        Object.Destroy(_originalGameObject);
        currentlyCutting = false;
    }
Example #26
0
        /// <summary>
        /// Function called before and after triangle merging.
        /// Before merging it calculates the Euler characteristic of the original mesh.
        /// After merging it calculates the Euler characteristic of the merged mesh.
        /// </summary>
        private int CalculateEulerCharacteristic()
        {
            int noVertices = 0;
            int noHoles    = 0; // Stays zero if mesh is triangular
            int noFaces;
            HashSet <IndexSegment> edges    = new HashSet <IndexSegment>(new SegmentComparer(true /*compareBothDirections*/));
            HashSet <int>          vertices = new HashSet <int>();

            if (m_MergedFaceSet.Count != 0)
            {
                // Merging already occurred, calculate new Euler characteristic
                noFaces = m_MergedFaceSet.Count;
                foreach (int mergedFace in m_MergedFaceSet)
                {
                    m_FacesCollDict[mergedFace].IndexOuterBoundary.ToList().ForEach(vt => vertices.Add(vt));
                    if (m_FacesCollDict[mergedFace].IndexedInnerBoundaries != null)
                    {
                        foreach (IList <int> innerB in m_FacesCollDict[mergedFace].IndexedInnerBoundaries)
                        {
                            innerB.ToList().ForEach(vt => vertices.Add(vt));
                        }
                    }

                    m_FacesCollDict[mergedFace].OuterAndInnerBoundaries.ToList().ForEach(vp => edges.Add(vp.Value));
                    if (m_FacesCollDict[mergedFace].IndexedInnerBoundaries != null)
                    {
                        noHoles += m_FacesCollDict[mergedFace].IndexedInnerBoundaries.Count;
                    }
                }
                noVertices = vertices.Count; // Vertices must be counted from the final merged faces as some of the inner vertices may disappear after stitching
            }
            else
            {
                if (IsMesh)
                {
                    noVertices = m_MeshGeom.Vertices.Count;
                    noFaces    = m_MeshGeom.NumTriangles;
                    for (int faceIdx = 0; faceIdx < noFaces; faceIdx++)
                    {
                        MeshTriangle tri = m_MeshGeom.get_Triangle(faceIdx);
                        edges.Add(new IndexSegment((int)tri.get_Index(0), (int)tri.get_Index(1)));
                        edges.Add(new IndexSegment((int)tri.get_Index(1), (int)tri.get_Index(2)));
                        edges.Add(new IndexSegment((int)tri.get_Index(2), (int)tri.get_Index(0)));
                    }
                }
                else
                {
                    noVertices = m_Geom.VertexCount;
                    noFaces    = m_Geom.TriangleCount;
                    for (int faceIdx = 0; faceIdx < noFaces; faceIdx++)
                    {
                        TriangleInShellComponent tri = m_Geom.GetTriangle(faceIdx);
                        edges.Add(new IndexSegment(tri.VertexIndex0, tri.VertexIndex1));
                        edges.Add(new IndexSegment(tri.VertexIndex1, tri.VertexIndex2));
                        edges.Add(new IndexSegment(tri.VertexIndex2, tri.VertexIndex0));
                    }
                }
            }

            // V - E + F - I
            return(noVertices - edges.Count + noFaces - noHoles);
        }
Example #27
0
    private static void MakeTriangles(Plane _plane, MeshTriangle _triangle, GeneratedMesh _currentSide, List <Vector3> _addedVertices, MeshTriangle currentMeshTriangle, MeshTriangle oppositeMeshTriangle, bool addVertices)
    {
        float normalizedDistance;
        float distance;

        // Get the distance from the vertex to the intersecting plane, in the direction of a vertex that we know exists on the other side of the intersection
        // From our original triangle
        _plane.Raycast(new Ray(currentMeshTriangle.Vertices[0], (oppositeMeshTriangle.Vertices[0] - currentMeshTriangle.Vertices[0]).normalized), out distance);
        normalizedDistance = distance / (oppositeMeshTriangle.Vertices[0] - currentMeshTriangle.Vertices[0]).magnitude;

        Vector3 vertLeft   = Vector3.Lerp(currentMeshTriangle.Vertices[0], oppositeMeshTriangle.Vertices[0], normalizedDistance);
        Vector3 normalLeft = Vector3.Lerp(currentMeshTriangle.Normals[0], oppositeMeshTriangle.Normals[0], normalizedDistance);
        Vector2 uvLeft     = Vector2.Lerp(currentMeshTriangle.UVs[0], oppositeMeshTriangle.UVs[0], normalizedDistance);

        _plane.Raycast(new Ray(currentMeshTriangle.Vertices[1], (oppositeMeshTriangle.Vertices[1] - currentMeshTriangle.Vertices[1]).normalized), out distance);

        normalizedDistance = distance / (oppositeMeshTriangle.Vertices[1] - currentMeshTriangle.Vertices[1]).magnitude;
        Vector3 vertRight = Vector3.Lerp(currentMeshTriangle.Vertices[1], oppositeMeshTriangle.Vertices[1], normalizedDistance);

        // Since we call this method twice, prevent adding new vertices twice
        if (addVertices)
        {
            _addedVertices.Add(vertLeft);
            _addedVertices.Add(vertRight);
        }
        Vector3 normalRight = Vector3.Lerp(currentMeshTriangle.Normals[1], oppositeMeshTriangle.Normals[1], normalizedDistance);
        Vector3 uvRight     = Vector2.Lerp(currentMeshTriangle.UVs[1], oppositeMeshTriangle.UVs[1], normalizedDistance);

        MeshTriangle currentTriangle;

        Vector3[] updatedVertices = new Vector3[] { currentMeshTriangle.Vertices[0], vertLeft, vertRight };
        Vector3[] updatedNormals  = new Vector3[] { currentMeshTriangle.Normals[0], normalLeft, normalRight };
        Vector2[] updatedUVs      = new Vector2[] { currentMeshTriangle.UVs[0], uvLeft, uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            _currentSide.AddTriangle(currentTriangle);
        }

        updatedVertices = new Vector3[] { currentMeshTriangle.Vertices[0], currentMeshTriangle.Vertices[1], vertRight };
        updatedNormals  = new Vector3[] { currentMeshTriangle.Normals[0], currentMeshTriangle.Normals[1], normalRight };
        updatedUVs      = new Vector2[] { currentMeshTriangle.UVs[0], currentMeshTriangle.UVs[1], uvRight };

        currentTriangle = new MeshTriangle(updatedVertices, updatedNormals, updatedUVs, _triangle.SubmeshIndex);

        if (updatedVertices[0] != updatedVertices[1] && updatedVertices[0] != updatedVertices[2])
        {
            if (Vector3.Dot(Vector3.Cross(updatedVertices[1] - updatedVertices[0], updatedVertices[2] - updatedVertices[0]), updatedNormals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            _currentSide.AddTriangle(currentTriangle);
        }
    }
Example #28
0
    public static void Cut(GameObject _originalGameObject,
                           Vector3 _contactPoint,
                           Vector3 _direction,
                           Material _cutMaterial = null,
                           bool _fill            = true,
                           bool _addRigidbody    = false)
    {
        if (currentlyCutting)
        {
            return;
        }

        currentlyCutting = true;

        Plane plane = new Plane(_originalGameObject.transform.InverseTransformDirection(-_direction),
                                _originalGameObject.transform.InverseTransformDirection(_contactPoint));

        originalMesh = _originalGameObject.GetComponent <MeshFilter>().mesh;
        List <Vector3> addedVertices = new List <Vector3>();

        GeneratedMesh leftMesh  = new GeneratedMesh();
        GeneratedMesh rightMesh = new GeneratedMesh();

        int[] submeshIndices;
        int   triangleIndexA, triangleIndexB, triangleIndexC;

        for (int i = 0; i < originalMesh.subMeshCount; ++i)
        {
            submeshIndices = originalMesh.GetTriangles(i);

            for (int j = 0; j < submeshIndices.Length; j += 3)
            {
                triangleIndexA = submeshIndices[j];
                triangleIndexB = submeshIndices[j + 1];
                triangleIndexC = submeshIndices[j + 2];

                MeshTriangle currentTriangle = GetTriangle(triangleIndexA, triangleIndexB, triangleIndexC, i);

                bool triangleALeftSide = plane.GetSide(originalMesh.vertices[triangleIndexA]);
                bool triangleBLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexB]);
                bool triangleCLeftSide = plane.GetSide(originalMesh.vertices[triangleIndexC]);

                if (triangleALeftSide && triangleBLeftSide && triangleCLeftSide)
                {
                    leftMesh.AddTriangle(currentTriangle);
                }
                else if (!triangleALeftSide && !triangleBLeftSide && !triangleCLeftSide)
                {
                    rightMesh.AddTriangle(currentTriangle);
                }
                else
                {
                    CutTriangle(plane, currentTriangle, triangleALeftSide, triangleBLeftSide, triangleCLeftSide, leftMesh, rightMesh, addedVertices);
                }
            }
        }

        if (_fill)
        {
            FillCut(addedVertices, plane, leftMesh, rightMesh);
        }

        originalMesh.Clear();

        originalMesh.vertices  = leftMesh.Vertices.ToArray();
        originalMesh.normals   = leftMesh.Normals.ToArray();
        originalMesh.uv        = leftMesh.UVs.ToArray();
        originalMesh.triangles = leftMesh.Indices(0);


        GameObject secondGameObject = GameObject.Instantiate(_originalGameObject);
        Mesh       secondMesh       = secondGameObject.GetComponent <MeshFilter>().mesh;

        secondMesh.vertices  = rightMesh.Vertices.ToArray();
        secondMesh.normals   = rightMesh.Normals.ToArray();
        secondMesh.uv        = rightMesh.UVs.ToArray();
        secondMesh.triangles = rightMesh.Indices(0);

        Component.Destroy(_originalGameObject.GetComponent <SphereCollider>());
        Component.Destroy(secondGameObject.GetComponent <SphereCollider>());

        _originalGameObject.AddComponent <MeshCollider>();
        secondGameObject.AddComponent <MeshCollider>();

        _originalGameObject.GetComponent <MeshCollider>().convex = true;
        secondGameObject.GetComponent <MeshCollider>().convex    = true;


        currentlyCutting = false;
    }
Example #29
0
    private static void Fill(List <Vector3> _vertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh)
    {
        Vector3 centerPosition = Vector3.zero;

        for (int i = 0; i < _vertices.Count; i++)
        {
            centerPosition += _vertices[i];
        }
        centerPosition = centerPosition / _vertices.Count;

        Vector3 up = new Vector3()
        {
            x = _plane.normal.x,
            y = _plane.normal.y,
            z = _plane.normal.z
        };

        Vector3 left         = Vector3.zero;
        Vector3 displacement = Vector3.zero;
        Vector2 uv1          = Vector2.zero;
        Vector2 uv2          = Vector2.zero;

        for (int i = 0; i < _vertices.Count; i++)
        {
            displacement = _vertices[i] - centerPosition;
            uv1          = new Vector2()
            {
                x = .5f + Vector3.Dot(displacement, left),
                y = .5f + Vector3.Dot(displacement, up)
            };

            displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition;
            uv2          = new Vector2()
            {
                x = .5f + Vector3.Dot(displacement, left),
                y = .5f + Vector3.Dot(displacement, up)
            };

            Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition };
            Vector3[] normals  = new Vector3[] { -_plane.normal, -_plane.normal, -_plane.normal };
            Vector2[] uvs      = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) };

            MeshTriangle currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1);

            // Make sure triangle is facing the right way
            if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }

            _leftMesh.AddTriangle(currentTriangle);

            normals         = new Vector3[] { _plane.normal, _plane.normal, _plane.normal };
            currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1);

            if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            _rightMesh.AddTriangle(currentTriangle);
        }
    }
Example #30
0
    public static void Fill(List <Vector3> _vertices, Plane _plane, GeneratedMesh _leftMesh, GeneratedMesh _rightMesh)
    {
        // Firstly we need the center we do this by adding up all the vertices and then calculating the average
        Vector3 centerPosition = Vector3.zero;

        for (int i = 0; i < _vertices.Count; ++i)
        {
            centerPosition += _vertices[i];
        }
        centerPosition = centerPosition / _vertices.Count;

        // We now need an Upward Axis we use the plane we cut the mesh with for that
        Vector3 up = new Vector3()
        {
            x = _plane.normal.x,
            y = _plane.normal.y,
            z = _plane.normal.z
        };

        Vector3 left = Vector3.Cross(_plane.normal, _plane.normal);

        Vector3 displacement = Vector3.zero;
        Vector2 uv1          = Vector2.zero;
        Vector2 uv2          = Vector2.zero;

        for (int i = 0; i < _vertices.Count; ++i)
        {
            displacement = _vertices[i] - centerPosition;
            uv1          = new Vector2()
            {
                x = 0.5f + Vector3.Dot(displacement, left),
                y = 0.5f + Vector3.Dot(displacement, up)
            };

            displacement = _vertices[(i + 1) % _vertices.Count] - centerPosition;
            uv2          = new Vector2()
            {
                x = 0.5f + Vector3.Dot(displacement, left),
                y = 0.5f + Vector3.Dot(displacement, up)
            };

            Vector3[] vertices = new Vector3[] { _vertices[i], _vertices[(i + 1) % _vertices.Count], centerPosition };
            Vector3[] normals  = new Vector3[] { -_plane.normal, -_plane.normal, -_plane.normal };
            Vector2[] uvs      = new Vector2[] { uv1, uv2, new Vector2(0.5f, 0.5f) };

            MeshTriangle currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1);

            if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            _leftMesh.AddTriangle(currentTriangle);

            normals         = new Vector3[] { _plane.normal, _plane.normal, _plane.normal };
            currentTriangle = new MeshTriangle(vertices, normals, uvs, originalMesh.subMeshCount + 1);

            if (Vector3.Dot(Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]), normals[0]) < 0)
            {
                FlipTriangle(currentTriangle);
            }
            _rightMesh.AddTriangle(currentTriangle);
        }
    }
Example #31
0
 private static void FlipTriangle(MeshTriangle triangle)
 {
     triangle.Vertices.Reverse();
     triangle.Normals.Reverse();
     triangle.UVs.Reverse();
 }
        private void Stream(ArrayList data, MeshTriangle meshTri)
        {
            data.Add(new Snoop.Data.ClassSeparator(typeof(MeshTriangle)));

            // TBD: not sure what get_index() is all about??

            data.Add(new Snoop.Data.Xyz("Vertex [0]", meshTri.get_Vertex(0)));
            data.Add(new Snoop.Data.Xyz("Vertex [1]", meshTri.get_Vertex(1)));
            data.Add(new Snoop.Data.Xyz("Vertex [2]", meshTri.get_Vertex(2)));
        }
        private static MeshTriangle[] ExtractSubmeshTriangles( SubMesh subMesh )
        {
            int[] vertIdx = new int[ 3 ];
            Vector3[] vertPos = new Vector3[ 3 ];
            VertexElement posElem = subMesh.vertexData.vertexDeclaration.FindElementBySemantic( VertexElementSemantic.Position );
            HardwareVertexBuffer posBuffer = posBuffer = subMesh.vertexData.vertexBufferBinding.GetBuffer( posElem.Source );
            IntPtr indexPtr = subMesh.indexData.indexBuffer.Lock( BufferLocking.ReadOnly );
            IntPtr posPtr = posBuffer.Lock( BufferLocking.ReadOnly );
            int posOffset = posElem.Offset / sizeof( float );
            int posStride = posBuffer.VertexSize / sizeof( float );
            int numFaces = subMesh.indexData.indexCount / 3;
            MeshTriangle[] triangles = new MeshTriangle[ numFaces ];
            unsafe
            {
                int* pIdxInt32 = null;
                short* pIdxShort = null;
                float* pVPos = (float*) posPtr.ToPointer();
                if( subMesh.indexData.indexBuffer.Type == IndexType.Size32 )
                    pIdxInt32 = (int*) indexPtr.ToPointer();
                else
                    pIdxShort = (short*) indexPtr.ToPointer();

                // loop through all faces to calculate the tangents
                for( int n = 0; n < numFaces; n++ )
                {
                    for( int i = 0; i < 3; i++ )
                    {
                        // get indices of vertices that form a polygon in the position buffer
                        if( subMesh.indexData.indexBuffer.Type == IndexType.Size32 )
                            vertIdx[ i ] = pIdxInt32[ 3 * n + i ];
                        else
                            vertIdx[ i ] = pIdxShort[ 3 * n + i ];
                        vertPos[ i ].x = pVPos[ vertIdx[ i ] * posStride + posOffset ];
                        vertPos[ i ].y = pVPos[ vertIdx[ i ] * posStride + posOffset + 1 ];
                        vertPos[ i ].z = pVPos[ vertIdx[ i ] * posStride + posOffset + 2 ];
                    }
                    triangles[ n ] = new MeshTriangle( vertPos[ 0 ], vertPos[ 1 ], vertPos[ 2 ] );
                }
            }
            posBuffer.Unlock();
            subMesh.indexData.indexBuffer.Unlock();
            if( DoLog )
            {
                int count = triangles.Length;
                Log( string.Format( " extracted {0} triangles", count ) );
                for( int i = 0; i < count; i++ )
                    Log( string.Format( "  {0}", triangles[ i ].ToString() ) );
            }
            return triangles;
        }