示例#1
0
        public void TessellatorProducesCorrectVertexNormals()
        {
            Name = nameof(TessellatorProducesCorrectVertexNormals);
            var shape = new Polygon((4.96243, 50.58403), (5.78472, 50.58403), (5.78472, 65.83403), (-7.05727, 65.83403), (-7.05727, 50.57403), (4.96243, 50.57403));

            var geoElem = new GeometricElement(representation: new Extrude(shape, 1, Vector3.ZAxis, false));

            Model.AddElement(geoElem);
            var solid  = geoElem.GetFinalCsgFromSolids();
            var mgb    = new MockGraphicsBuffer();
            var arrows = new ModelArrows();

            Tessellation.Tessellate(new Csg.Solid[] { solid }.Select(s => new CsgTessellationTargetProvider(solid)), mgb);
            for (int i = 0; i < mgb.Indices.Count; i += 3)
            {
                var a     = mgb.Indices[i];
                var b     = mgb.Indices[i + 1];
                var c     = mgb.Indices[i + 2];
                var verts = new[] { mgb.Vertices[a], mgb.Vertices[b], mgb.Vertices[c] };
                verts.ToList().ForEach((v) =>
                {
                    arrows.Vectors.Add((v.position, v.normal, 0.2, Colors.Blue));
                });
                var triangle = new Polygon(verts.Select(v => v.position).ToList());
                var normal   = verts[0].normal;
                Assert.True(triangle.Normal().Dot(normal.Unitized()) > 0, "The vertex normals are pointing in the opposite direction as their triangles' winding should suggest");
                Model.AddElement(triangle.TransformedPolygon(new Transform(normal * 0.2)));
            }
            Model.AddElement(arrows);
        }
        public List <Segment> Tessellate()
        {
            List <Segment> segments = new List <Segment>();
            PartDoc        swPart   = (PartDoc)swModel;

            System.Object vBodies;
            System.Array  aBodies;

            /* Acquiring solid's bodies */
            vBodies = swPart.GetBodies2((int)swBodyType_e.swAllBodies, false);
            aBodies = (System.Array)vBodies;

            int iNumBodies      = aBodies.Length;
            int iNumSolidBodies = 0;
            int iNumSheetBodies = 0;

            Body2 swBody;

            for (int b = 0; b < iNumBodies; b++)
            {
                swBody = (Body2)aBodies.GetValue(b);

                int nBodyType = swBody.GetType();

                if (nBodyType == (int)swBodyType_e.swSheetBody)
                {
                    iNumSheetBodies++;
                }

                if (nBodyType == (int)swBodyType_e.swSolidBody)
                {
                    iNumSolidBodies++;

                    Face2        swFace         = null;
                    Tessellation swTessellation = null;

                    bool bResult = false;
                    swTessellation = (Tessellation)swBody.GetTessellation(null);

                    swTessellation.NeedFaceFacetMap = true;
                    swTessellation.NeedVertexParams = true;
                    swTessellation.NeedVertexNormal = true;
                    swTessellation.ImprovedQuality  = true;

                    /* Proper Tesselation */
                    swTessellation.MatchType = (int)swTesselationMatchType_e.swTesselationMatchFacetTopology;
                    bResult = swTessellation.Tessellate();

                    int[]    aFacetIds;
                    int      iNumFacetIds;
                    int[]    aFinIds;
                    int[]    aVertexIds;
                    double[] aVertexCoords1;
                    double[] aVertexCoords2;

                    swFace = (Face2)swBody.GetFirstFace();

                    /* Getting all solid's triangles */
                    while (swFace != null)
                    {
                        aFacetIds = (int[])swTessellation.GetFaceFacets(swFace);

                        iNumFacetIds = aFacetIds.Length;

                        for (int iFacetIdIdx = 0; iFacetIdIdx < iNumFacetIds; iFacetIdIdx++)
                        {
                            aFinIds = (int[])swTessellation.GetFacetFins(aFacetIds[iFacetIdIdx]);

                            for (int iFinIdx = 0; iFinIdx < 3; iFinIdx++)
                            {
                                aVertexIds = (int[])swTessellation.GetFinVertices(aFinIds[iFinIdx]);

                                aVertexCoords1 = (double[])swTessellation.GetVertexPoint(aVertexIds[0]);
                                aVertexCoords2 = (double[])swTessellation.GetVertexPoint(aVertexIds[1]);

                                /* Creating segments */
                                segments.Add(new Segment(aVertexCoords1, aVertexCoords2));
                            }
                        }

                        swFace = (Face2)swFace.GetNextFace();
                    }
                }
            }

            return(segments);
        }
示例#3
0
        /// Convert a SolidWorks component to Wavefront OBJ mesh
        ///
        public static void Convert(Component2 swComp, ref string asciitext, bool saveUV, ref UserProgressBar swProgress)
        {
            StringBuilder textbuilder = new StringBuilder();
            Body2         swBody      = default(Body2);

            object[] vBodies      = null;
            object[] vBodiesSolid = null;
            object[] vBodiesSheet = null;
            object   vBodyInfo;

            int[]     BodiesInfo = null;
            int       j          = 0;
            ModelDoc2 swModel;


            swModel = (ModelDoc2)swComp.GetModelDoc();

            vBodiesSolid = (object[])swComp.GetBodies3((int)swBodyType_e.swSolidBody, out vBodyInfo);
            vBodiesSheet = (object[])swComp.GetBodies3((int)swBodyType_e.swSheetBody, out vBodyInfo);
            BodiesInfo   = (int[])vBodyInfo;

            if (vBodiesSolid != null && vBodiesSheet == null)
            {
                vBodies = vBodiesSolid;
            }

            if (vBodiesSolid == null && vBodiesSheet != null)
            {
                vBodies = vBodiesSheet;
            }

            if (vBodiesSolid != null && vBodiesSheet != null)
            {
                vBodies = vBodiesSheet.Concat(vBodiesSolid).ToArray();
            }

            // vBodies = (object[])swComp.GetBodies3((int)swBodyType_e.swSolidBody, out vBodyInfo);


            if (vBodies != null)
            {
                int iNumBodies           = vBodies.Length;
                int iNumSolidBodies      = 0;
                int iNumSheetBodies      = 0;
                int iNumTesselatedBodies = 0;


                if (iNumBodies > 0)
                {
                    asciitext += "# Wavefront .OBJ file for tesselated shape: " + swComp.Name2 + " path: " + swModel.GetPathName() + "\n\n";
                }

                int group_vstride = 0;
                int group_nstride = 0;

                // Loop through bodies
                for (j = 0; j <= vBodies.Length - 1; j++)
                {
                    swBody = (Body2)vBodies[j];

                    int nBodyType = (int)swBody.GetType();

                    if (nBodyType == (int)swBodyType_e.swSheetBody)
                    {
                        iNumSheetBodies++;
                    }

                    if (nBodyType == (int)swBodyType_e.swSolidBody)
                    {
                        iNumSolidBodies++;
                    }

                    if ((nBodyType == (int)swBodyType_e.swSheetBody ||
                         nBodyType == (int)swBodyType_e.swSolidBody) &&
                        !swBody.Name.StartsWith("COLL.") &&
                        swBody.Visible)
                    {
                        iNumTesselatedBodies++;

                        CultureInfo bz = new CultureInfo("en-BZ");

                        //asciitext += "g body_" + iNumTesselatedBodies + "\n";
                        textbuilder.Append("g body_" + iNumTesselatedBodies + "\n");

                        Face2        swFace         = null;
                        Tessellation swTessellation = null;

                        bool bResult = false;

                        // Pass in null so the whole body will be tessellated
                        swTessellation = (Tessellation)swBody.GetTessellation(null);

                        // Set up the Tessellation object
                        swTessellation.NeedFaceFacetMap = true;
                        swTessellation.NeedVertexParams = true;
                        swTessellation.NeedVertexNormal = true;
                        swTessellation.ImprovedQuality  = true;

                        // How to handle matches across common edges
                        swTessellation.MatchType = (int)swTesselationMatchType_e.swTesselationMatchFacetTopology;

                        // Do it
                        if (swProgress != null)
                        {
                            swProgress.UpdateTitle("Exporting (tesselate process) ...");
                        }
                        bResult = swTessellation.Tessellate();

                        // Get the number of vertices and facets
                        //System.Windows.Forms.MessageBox.Show("Body n." + j + " vert.num=" + swTessellation.GetVertexCount());
                        //Debug.Print("Number of vertices: " + swTessellation.GetVertexCount());
                        //Debug.Print("Number of facets: " + swTessellation.GetFacetCount());

                        // Now get the facet data per face
                        int[]    aFacetIds;
                        int      iNumFacetIds;
                        int[]    aFinIds;
                        int[]    aVertexIds;
                        double[] aNormal;
                        double[] aVertexCoords1;
                        double[] aVertexCoords2;
                        double[] aVertexParams;

                        int numv = swTessellation.GetVertexCount();

                        // Write all vertexes
                        string mline;

                        for (int iv = 0; iv < numv; iv++)
                        {
                            if ((swProgress != null) && (iv % 200 == 0))
                            {
                                swProgress.UpdateTitle("Exporting (write " + iv + "-th vertex in .obj) ...");
                            }
                            aVertexCoords1 = (double[])swTessellation.GetVertexPoint(iv);
                            mline          = "v " + (aVertexCoords1[0] * ChScale.L).ToString("f6", bz)
                                             + " " + (aVertexCoords1[1] * ChScale.L).ToString("f6", bz)
                                             + " " + (aVertexCoords1[2] * ChScale.L).ToString("f6", bz)
                                             + "\n";
                            textbuilder.Append(mline);
                        }

                        // Write all normals
                        for (int iv = 0; iv < numv; iv++)
                        {
                            if ((swProgress != null) && (iv % 200 == 0))
                            {
                                swProgress.UpdateTitle("Exporting (write " + iv + "-th normal in .obj) ...");
                            }
                            aNormal = (double[])swTessellation.GetVertexNormal(iv);
                            mline   = "vn " + aNormal[0].ToString("f3", bz)
                                      + " " + aNormal[1].ToString("f3", bz)
                                      + " " + aNormal[2].ToString("f3", bz)
                                      + "\n";
                            textbuilder.Append(mline);
                        }
                        if (nBodyType == (int)swBodyType_e.swSheetBody)  // for sheets, save two-sided triangles
                        {
                            for (int iv = 0; iv < numv; iv++)
                            {
                                if ((swProgress != null) && (iv % 200 == 0))
                                {
                                    swProgress.UpdateTitle("Exporting (write " + iv + "-th normal in .obj) ...");
                                }
                                aNormal = (double[])swTessellation.GetVertexNormal(iv);
                                mline   = "vn " + (-aNormal[0]).ToString("f3", bz)
                                          + " " + (-aNormal[1]).ToString("f3", bz)
                                          + " " + (-aNormal[2]).ToString("f3", bz)
                                          + "\n";
                                textbuilder.Append(mline);
                            }
                        }

                        // Write all UV (also with '0' as third value, for compatibility with some OBJ reader)
                        if (saveUV)
                        {
                            for (int iv = 0; iv < numv; iv++)
                            {
                                if ((swProgress != null) && (iv % 200 == 0))
                                {
                                    swProgress.UpdateTitle("Exporting (write " + iv + "-th UV in .obj) ...");
                                }
                                aVertexParams = (double[])swTessellation.GetVertexParams(iv);
                                mline         = "vt " + aVertexParams[0].ToString("f4", bz)
                                                + " " + aVertexParams[1].ToString("f4", bz)
                                                + " " + "0"
                                                + "\n";
                                textbuilder.Append(mline);
                            }
                        }


                        // Loop over faces
                        swFace = (Face2)swBody.GetFirstFace();
                        while (swFace != null)
                        {
                            aFacetIds = (int[])swTessellation.GetFaceFacets(swFace);

                            iNumFacetIds = aFacetIds.Length;

                            for (int iFacetIdIdx = 0; iFacetIdIdx < iNumFacetIds; iFacetIdIdx++)
                            {
                                if ((swProgress != null) && (iFacetIdIdx % 100 == 0))
                                {
                                    swProgress.UpdateTitle("Exporting (write " + iFacetIdIdx + "-th face in .obj) ...");
                                }

                                mline = "f";

                                aFinIds = (int[])swTessellation.GetFacetFins(aFacetIds[iFacetIdIdx]);

                                // There should always be three fins per facet
                                for (int iFinIdx = 0; iFinIdx < 3; iFinIdx++)
                                {
                                    aVertexIds = (int[])swTessellation.GetFinVertices(aFinIds[iFinIdx]);

                                    // Three fins per face, two vertexes each fin,
                                    // only the 1st vertex of two is needed (because of sharing)
                                    if (saveUV)
                                    {
                                        mline += " " + (aVertexIds[0] + group_vstride + 1) + "/"
                                                 + (aVertexIds[0] + group_vstride + 1) + "/"
                                                 + (aVertexIds[0] + group_nstride + 1);
                                    }
                                    else
                                    {
                                        mline += " " + (aVertexIds[0] + group_vstride + 1) + "//"
                                                 + (aVertexIds[0] + group_nstride + 1);
                                    }
                                }

                                mline += "\n";
                                textbuilder.Append(mline);
                            }
                            swFace = (Face2)swFace.GetNextFace();
                        }

                        swFace = (Face2)swBody.GetFirstFace();
                        if (nBodyType == (int)swBodyType_e.swSheetBody)  // for sheets, save two-sided triangles
                        {
                            while (swFace != null)
                            {
                                aFacetIds = (int[])swTessellation.GetFaceFacets(swFace);

                                iNumFacetIds = aFacetIds.Length;

                                for (int iFacetIdIdx = 0; iFacetIdIdx < iNumFacetIds; iFacetIdIdx++)
                                {
                                    if ((swProgress != null) && (iFacetIdIdx % 100 == 0))
                                    {
                                        swProgress.UpdateTitle("Exporting (write " + iFacetIdIdx + "-th face in .obj) ...");
                                    }

                                    mline = "f";

                                    aFinIds = (int[])swTessellation.GetFacetFins(aFacetIds[iFacetIdIdx]);

                                    for (int iFinIdx = 2; iFinIdx >= 0; iFinIdx--)
                                    {
                                        aVertexIds = (int[])swTessellation.GetFinVertices(aFinIds[iFinIdx]);

                                        if (saveUV)
                                        {
                                            mline += " " + (aVertexIds[0] + group_vstride + 1) + "/"
                                                     + (aVertexIds[0] + group_vstride + 1) + "/"
                                                     + (aVertexIds[0] + swTessellation.GetVertexCount() + group_nstride + 1);
                                        }
                                        else
                                        {
                                            mline += " " + (aVertexIds[0] + group_vstride + 1) + "//"
                                                     + (aVertexIds[0] + swTessellation.GetVertexCount() + group_nstride + 1);
                                        }
                                    }

                                    mline += "\n";
                                    textbuilder.Append(mline);
                                }
                                swFace = (Face2)swFace.GetNextFace();
                            }
                        }

                        group_vstride += swTessellation.GetVertexCount();
                        group_nstride += swTessellation.GetVertexCount();

                        if (nBodyType == (int)swBodyType_e.swSheetBody)  // for sheets: two-sided triangles
                        {
                            group_nstride += swTessellation.GetVertexCount();
                        }
                    }
                } // end loop on bodies
            }     // not null body

            asciitext += textbuilder.ToString();
        }
示例#4
0
        private Model.BodyglTFModel GetglTFBodyModel(Body2 swBody)
        {
            BodyglTFModel BodyModel = new BodyglTFModel();

            if (swBody == null)
            {
                return(null);
            }
            try
            {
                var BodyMaterial = (double[])swBody.MaterialPropertyValues2;
                if (BodyMaterial != null)
                {
                    BodyModel.BodyMaterialValue = BodyMaterial;
                }

                #region 网格化
                Tessellation swTessellation = swBody.GetTessellation(null);
                if (swTessellation != null)
                {
                    swTessellation.NeedFaceFacetMap = true;
                    swTessellation.NeedVertexParams = true;
                    swTessellation.NeedVertexNormal = true;
                    swTessellation.ImprovedQuality  = true;
                    // How to handle matches across common edges
                    swTessellation.MatchType = (int)swTesselationMatchType_e.swTesselationMatchFacetTopology;
                    // Do it
                    bool bResult = swTessellation.Tessellate();
                }
                else
                {
                    return(null);
                }
                #endregion
                Face2 swFace = (Face2)swBody.GetFirstFace();

                while (swFace != null)
                {
                    Model.FaceglTFModel FaceModel = new FaceglTFModel();
                    var FaceMaterial = swFace.MaterialPropertyValues;
                    if (FaceMaterial != null)
                    {
                        FaceModel.FaceMaterialValue = FaceMaterial;
                    }
                    #region 面的三角化
                    int[] aFacetIds    = (int[])swTessellation.GetFaceFacets(swFace);
                    int   iNumFacetIds = aFacetIds.Length;
                    for (int iFacetIdIdx = 0; iFacetIdIdx < iNumFacetIds; iFacetIdIdx++)
                    {
                        int[] aFinIds = (int[])swTessellation.GetFacetFins(aFacetIds[iFacetIdIdx]);
                        // There should always be three fins per facet
                        FaceVertexModel model  = new FaceVertexModel();
                        List <double[]> points = new List <double[]>();
                        for (int iFinIdx = 0; iFinIdx < 3; iFinIdx++)
                        {
                            int[] aVertexIds = (int[])swTessellation.GetFinVertices(aFinIds[iFinIdx]);
                            // Should always be two vertices per fin
                            double[] aVertexCoords1 = (double[])swTessellation.GetVertexPoint(aVertexIds[0]);
                            double[] aVertexCoords2 = (double[])swTessellation.GetVertexPoint(aVertexIds[1]);
                            var      v1             = new VERTEX(Convert.ToSingle(aVertexCoords1[0]),
                                                                 Convert.ToSingle(aVertexCoords1[1]),
                                                                 Convert.ToSingle(aVertexCoords1[2]));
                            var v2 = new VERTEX(Convert.ToSingle(aVertexCoords2[0]),
                                                Convert.ToSingle(aVertexCoords2[1]),
                                                Convert.ToSingle(aVertexCoords2[2]));
                            bool isContain = false;
                            foreach (var item in points)
                            {
                                if ((Math.Abs(item[0] - aVertexCoords1[0]) + Math.Abs(item[1] - aVertexCoords1[1]) + Math.Abs(item[2] - aVertexCoords1[2])) < 0.00001)
                                {
                                    isContain = true;
                                }
                            }
                            if (!isContain)
                            {
                                points.Add(aVertexCoords1);
                            }

                            isContain = false;
                            foreach (var item in points)
                            {
                                if ((Math.Abs(item[0] - aVertexCoords2[0]) + Math.Abs(item[1] - aVertexCoords2[1]) + Math.Abs(item[2] - aVertexCoords2[2])) < 0.00001)
                                {
                                    isContain = true;
                                }
                            }
                            if (!isContain)
                            {
                                points.Add(aVertexCoords2);
                            }
                            // Create a line
                            //swModel.CreateLine2(aVertexCoords1[0], aVertexCoords1[1], aVertexCoords1[2], aVertexCoords2[0], aVertexCoords2[1], aVertexCoords2[2]);
                        }
                        if (points.Count == 3)
                        {
                            model.a = new VERTEX(Convert.ToSingle(points[0][0]),
                                                 Convert.ToSingle(points[0][1]),
                                                 Convert.ToSingle(points[0][2]));
                            model.b = new VERTEX(Convert.ToSingle(points[1][0]),
                                                 Convert.ToSingle(points[1][1]),
                                                 Convert.ToSingle(points[1][2]));
                            model.c = new VERTEX(Convert.ToSingle(points[2][0]),
                                                 Convert.ToSingle(points[2][1]),
                                                 Convert.ToSingle(points[2][2]));
                            FaceModel.FaceTri.Add(model);
                        }
                    }
                    if (FaceModel.FaceTri.Count > 0)
                    {
                        BodyModel.FaceList.Add(FaceModel);
                    }
                    swFace = (Face2)swFace.GetNextFace();
                    #endregion
                }
            }
            catch (Exception ex)
            {
            }
            return(BodyModel);
        }