Obj string to valid mesh

Hi to all,

I make a mesh to obj function (Get an obj object from mesh) but now I was trying to re convert it to mesh but the problem is that the mesh created is not valid and the function ‘IsValidWithLog’ give me: “ON_Mesh.m_F[0] has degenerate double precision vertex locations.\n”

string[] objFile = Regex.Split(s, "\r\n|\r|\n");
            Mesh ms = new Mesh();
            System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
            foreach (string line in objFile)
            {

                string[] sLine = line.Split(' ');
                switch (sLine[0])
                {
                    case "v": //Vertices
                        ms.Vertices.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    case "vt": //TextureCoordinates
                        ms.TextureCoordinates.Add(float.Parse(sLine[1]), float.Parse(sLine[2]));
                        break;
                    case "vn": //Normals
                        ms.Normals.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    case "f": //Faces
                        if (sLine.Length == 4) //triangle
                        {
                            ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0]), int.Parse(sLine[2].Split('/')[0]), int.Parse(sLine[3].Split('/')[0]));
                        }
                        else //quadrat
                        {
                            ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0]), int.Parse(sLine[2].Split('/')[0]), int.Parse(sLine[3].Split('/')[0]), int.Parse(sLine[4].Split('/')[0]));
                        }
                        break;
                    case "#fn": //FaceNormals
                        ms.FaceNormals.AddFaceNormal(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    /*case "#tv": //TopologyVertices
                        ms.TopologyVertices. //.AddFaceNormal(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;*/
                }
            }
            var l = ms.IsValidWithLog(out string log);
            doc.Objects.AddMesh(ms);
            doc.Views.Redraw();

Thanks in advance

Hi @visiado.al.ordenador,

Can you provide a sample that allows us to repeat the problem?

– Dale

Hi @dale,

I use this:

v -2.452513 -1.350659 0
v -2.452513 -1.350659 2.847046
v 3.945347 -1.350659 0
v 3.945347 -1.350659 2.847046
v 3.945347 -1.350659 0
v 3.945347 -1.350659 2.847046
v 3.945347 2.559144 0
v 3.945347 2.559144 2.847046
v 3.945347 2.559144 0
v 3.945347 2.559144 2.847046
v -2.452513 2.559144 0
v -2.452513 2.559144 2.847046
v -2.452513 2.559144 0
v -2.452513 2.559144 2.847046
v -2.452513 -1.350659 0
v -2.452513 -1.350659 2.847046
v -2.452513 -1.350659 0
v 3.945347 -1.350659 0
v 3.945347 2.559144 0
v -2.452513 2.559144 0
v -2.452513 -1.350659 2.847046
v 3.945347 -1.350659 2.847046
v 3.945347 2.559144 2.847046
v -2.452513 2.559144 2.847046
vt 0 0
vt 0 0.633455
vt 0.3103448 0
vt 0.3103448 0.633455
vt 0.3103448 0
vt 0.3103448 0.633455
vt 0.5 0
vt 0.5 0.633455
vt 0.5 0
vt 0.5 0.633455
vt 0.8103448 0
vt 0.8103448 0.633455
vt 0.8103448 0
vt 0.8103448 0.633455
vt 1 0
vt 1 0.633455
vt 0 1
vt 0.3103448 1
vt 0.3103448 0.6334557
vt 0 0.6334557
vt 0.6896552 0.6334557
vt 1 0.6334557
vt 1 1
vt 0.6896552 1
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
f 1/1/1 3/3/3 4/4/4 2/2/2
f 5/5/5 7/7/7 8/8/8 6/6/6
f 9/9/9 11/11/11 12/12/12 10/10/10
f 13/13/13 15/15/15 16/16/16 14/14/14
f 18/18/18 17/17/17 20/20/20
f 20/20/20 19/19/19 18/18/18
f 22/22/22 24/24/24 21/21/21
f 24/24/24 22/22/22 23/23/23

I can open this in the menu but I can’t load this reading line by line
Thanks

Hi @visiado.al.ordenador,

I have no idea what I am supposed to do with this. If you want assistance, I’ll need source code to as sample that repeats your issue.

– Dale

hi @dale, I attached the sourcecode at my first post, but I’ll put more information. I have this function (that recive a string s that is in format obj and a RhinoDoc doc that I wand to create the 3d object form a string:
Sourcecode:

public static Result loadObj(string s, RhinoDoc doc)
{
string objFile = Regex.Split(s, “\r\n|\r|\n”);
Mesh ms = new Mesh();
System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
customCulture.NumberFormat.NumberDecimalSeparator = “.”;
System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
foreach (string line in objFile)
{

            string[] sLine = line.Split(' ');
            switch (sLine[0])
            {
                case "v": //Vertices
                    ms.Vertices.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                    break;
                case "vt": //TextureCoordinates
                    ms.TextureCoordinates.Add(float.Parse(sLine[1]), float.Parse(sLine[2]));
                    break;
                case "vn": //Normals
                    ms.Normals.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                    break;
                case "f": //Faces
                    if (sLine.Length == 4) //triangle
                    {
                        ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0]), int.Parse(sLine[2].Split('/')[0]), int.Parse(sLine[3].Split('/')[0]));
                    }
                    else //quadrat
                    {
                        ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0]), int.Parse(sLine[2].Split('/')[0]), int.Parse(sLine[3].Split('/')[0]), int.Parse(sLine[4].Split('/')[0]));
                    }
                    break;
            }
        }
        var l = ms.IsValidWithLog(out string log);
        doc.Objects.AddMesh(ms);
        doc.Views.Redraw();
        return Result.Success;
    }

And the obj that is in the string:

v -2.452513 -1.350659 0
v -2.452513 -1.350659 2.847046
v 3.945347 -1.350659 0
v 3.945347 -1.350659 2.847046
v 3.945347 -1.350659 0
v 3.945347 -1.350659 2.847046
v 3.945347 2.559144 0
v 3.945347 2.559144 2.847046
v 3.945347 2.559144 0
v 3.945347 2.559144 2.847046
v -2.452513 2.559144 0
v -2.452513 2.559144 2.847046
v -2.452513 2.559144 0
v -2.452513 2.559144 2.847046
v -2.452513 -1.350659 0
v -2.452513 -1.350659 2.847046
v -2.452513 -1.350659 0
v 3.945347 -1.350659 0
v 3.945347 2.559144 0
v -2.452513 2.559144 0
v -2.452513 -1.350659 2.847046
v 3.945347 -1.350659 2.847046
v 3.945347 2.559144 2.847046
v -2.452513 2.559144 2.847046
vt 0 0
vt 0 0.633455
vt 0.3103448 0
vt 0.3103448 0.633455
vt 0.3103448 0
vt 0.3103448 0.633455
vt 0.5 0
vt 0.5 0.633455
vt 0.5 0
vt 0.5 0.633455
vt 0.8103448 0
vt 0.8103448 0.633455
vt 0.8103448 0
vt 0.8103448 0.633455
vt 1 0
vt 1 0.633455
vt 0 1
vt 0.3103448 1
vt 0.3103448 0.6334557
vt 0 0.6334557
vt 0.6896552 0.6334557
vt 1 0.6334557
vt 1 1
vt 0.6896552 1
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
f 1/1/1 3/3/3 4/4/4 2/2/2
f 5/5/5 7/7/7 8/8/8 6/6/6
f 9/9/9 11/11/11 12/12/12 10/10/10
f 13/13/13 15/15/15 16/16/16 14/14/14
f 18/18/18 17/17/17 20/20/20
f 20/20/20 19/19/19 18/18/18
f 22/22/22 24/24/24 21/21/21
f 24/24/24 22/22/22 23/23/23

Visiado and @dale, The .OBJ file uses 1-based indexing. So you need to subtract 1 from the 3 or 4 face vertex indices. Here is the code with this fix. Try it now and see how it works.

string[] objFile = Regex.Split(s, "\r\n|\r|\n");
            Mesh ms = new Mesh();
            System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
            foreach (string line in objFile)
            {

                string[] sLine = line.Split(' ');
                switch (sLine[0])
                {
                    case "v": //Vertices
                        ms.Vertices.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    case "vt": //TextureCoordinates
                        ms.TextureCoordinates.Add(float.Parse(sLine[1]), float.Parse(sLine[2]));
                        break;
                    case "vn": //Normals
                        ms.Normals.Add(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    case "f": //Faces
                        if (sLine.Length == 4) //triangle
                        {
                            ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0])-1, int.Parse(sLine[2].Split('/')[0])-1, int.Parse(sLine[3].Split('/')[0])-1);
                        }
                        else //quadrat
                        {
                            ms.Faces.AddFace(int.Parse(sLine[1].Split('/')[0])-1, int.Parse(sLine[2].Split('/')[0])-1, int.Parse(sLine[3].Split('/')[0])-1, int.Parse(sLine[4].Split('/')[0])-1);
                        }
                        break;
                    case "#fn": //FaceNormals
                        ms.FaceNormals.AddFaceNormal(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;
                    /*case "#tv": //TopologyVertices
                        ms.TopologyVertices. //.AddFaceNormal(float.Parse(sLine[1]), float.Parse(sLine[2]), float.Parse(sLine[3]));
                        break;*/
                }
            }
            var l = ms.IsValidWithLog(out string log);
            doc.Objects.AddMesh(ms);
            doc.Views.Redraw();

Regards,
Terry.

1 Like