Exemple #1
0
        unsafe IOReadResult BuildMeshes_Simple(ReadOptions options, IMeshBuilder builder)
        {
            if (vPositions.Length == 0)
            {
                return(new IOReadResult(IOCode.GarbageDataError, "No vertices in file"));
            }
            if (vTriangles.Length == 0)
            {
                return(new IOReadResult(IOCode.GarbageDataError, "No triangles in file"));
            }

            // [TODO] support non-per-vertex normals/colors
            bool bHaveNormals = (vNormals.Length == vPositions.Length);
            bool bHaveColors  = (vColors.Length == vPositions.Length);
            bool bHaveUVs     = (vUVs.Length / 2 == vPositions.Length / 3);

            int nVertices = vPositions.Length / 3;

            int[] mapV = new int[nVertices];

            int meshID = builder.AppendNewMesh(bHaveNormals, bHaveColors, bHaveUVs, m_bOBJHasTriangleGroups);

            for (int k = 0; k < nVertices; ++k)
            {
                Index3i vk = new Index3i(k, k, k);
                mapV[k] = append_vertex(builder, vk, bHaveNormals, bHaveColors, bHaveUVs);
            }

            // [TODO] this doesn't handle missing vertices...
            for (int k = 0; k < vTriangles.Length; ++k)
            {
                append_triangle(builder, k, mapV);
            }

            if (UsedMaterials.Count == 1)           // [RMS] should not be in here otherwise
            {
                int         material_id = UsedMaterials.Keys.First();
                string      sMatName    = UsedMaterials[material_id];
                OBJMaterial useMat      = Materials[sMatName];
                int         matID       = builder.BuildMaterial(useMat);
                builder.AssignMaterial(matID, meshID);
            }

            return(new IOReadResult(IOCode.Ok, ""));
        }
Exemple #2
0
        public IOReadResult ReadMaterials(string sPath)
        {
            if (nWarningLevel >= 1)
            {
                emit_warning("[OBJReader] ReadMaterials " + sPath);
            }

            StreamReader reader;

            try {
                reader = new StreamReader(sPath);
                if (reader.EndOfStream)
                {
                    return(new IOReadResult(IOCode.FileAccessError, ""));
                }
            } catch {
                return(new IOReadResult(IOCode.FileAccessError, ""));
            }


            OBJMaterial curMaterial = null;

            while (reader.Peek() >= 0)
            {
                string   line   = reader.ReadLine();
                string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    continue;
                }

                if (tokens[0][0] == '#')
                {
                    continue;
                }
                else if (tokens[0] == "newmtl")
                {
                    curMaterial      = new OBJMaterial();
                    curMaterial.name = tokens[1];
                    curMaterial.id   = Materials.Count;

                    if (Materials.ContainsKey(curMaterial.name))
                    {
                        emit_warning("Material file " + sPath + " / material " + curMaterial.name + " : already exists in Material set. Replacing.");
                    }
                    if (nWarningLevel >= 1)
                    {
                        emit_warning("[OBJReader] parsing material " + curMaterial.name);
                    }

                    Materials[curMaterial.name] = curMaterial;
                }
                else if (tokens[0] == "Ka")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Ka = parse_mtl_color(tokens);
                    }
                }
                else if (tokens[0] == "Kd")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Kd = parse_mtl_color(tokens);
                    }
                }
                else if (tokens[0] == "Ks")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Ks = parse_mtl_color(tokens);
                    }
                }
                else if (tokens[0] == "Ke")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Ke = parse_mtl_color(tokens);
                    }
                }
                else if (tokens[0] == "Tf")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Tf = parse_mtl_color(tokens);
                    }
                }
                else if (tokens[0] == "illum")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.illum = int.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "d")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.d = Single.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "Tr")         // alternate to d/alpha, [Tr]ansparency is 1-d
                {
                    if (curMaterial != null)
                    {
                        curMaterial.d = 1.0f - Single.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "Ns")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Ns = Single.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "sharpness")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.sharpness = Single.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "Ni")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.Ni = Single.Parse(tokens[1]);
                    }
                }
                else if (tokens[0] == "map_Ka")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_Ka = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "map_Kd")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_Kd = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "map_Ks")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_Ks = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "map_Ke")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_Ke = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "map_d")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_d = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "map_Ns")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.map_Ns = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "bump" || tokens[0] == "map_bump")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.bump = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "disp")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.disp = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "decal")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.decal = parse_mtl_path(line, tokens);
                    }
                }
                else if (tokens[0] == "refl")
                {
                    if (curMaterial != null)
                    {
                        curMaterial.refl = parse_mtl_path(line, tokens);
                    }
                }
                else
                {
                    emit_warning("unknown material command " + tokens[0]);
                }
            }

            if (nWarningLevel >= 1)
            {
                emit_warning("[OBJReader] ReadMaterials completed");
            }

            return(new IOReadResult(IOCode.Ok, "ok"));
        }
Exemple #3
0
        private unsafe void append_face(string[] tokens, OBJMaterial activeMaterial, int nActiveGroup)
        {
            int nMode = 0;

            if (tokens[1].IndexOf("//") != -1)
            {
                nMode = 1;
            }
            else if (tokens[1].IndexOf('/') != -1)
            {
                nMode = 2;
            }

            Triangle t = new Triangle();

            t.clear();
            for (int ti = 0; ti < tokens.Length - 1; ++ti)
            {
                int j = (ti < 3) ? ti : 2;
                if (ti >= 3)
                {
                    t.move_vertex(2, 1);
                }

                // parse next vertex
                if (nMode == 0)
                {
                    // "f v1 v2 v3"
                    t.set_vertex(j, parse_v(tokens[ti + 1]));
                }
                else if (nMode == 1)
                {
                    // "f v1//vn1 v2//vn2 v3//vn3"
                    string[] parts = tokens[ti + 1].Split(this.splitDoubleSlash, StringSplitOptions.RemoveEmptyEntries);
                    t.set_vertex(j, parse_v(parts[0]), parse_n(parts[1]));
                }
                else if (nMode == 2)
                {
                    string[] parts = tokens[ti + 1].Split(this.splitSlash, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length == 2)
                    {
                        // "f v1/vt1 v2/vt2 v3/vt3"
                        t.set_vertex(j, parse_v(parts[0]), -1, parse_u(parts[1]));
                    }
                    else if (parts.Length == 3)
                    {
                        // "f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3"
                        t.set_vertex(j, parse_v(parts[0]), parse_n(parts[2]), parse_u(parts[1]));
                    }
                    else
                    {
                        emit_warning("parse_triangle unexpected face component " + tokens[j]);
                    }
                }


                // do append
                if (ti >= 2)
                {
                    if (activeMaterial != null)
                    {
                        t.nMaterialID = activeMaterial.id;
                        UsedMaterials[activeMaterial.id] = activeMaterial.name;
                    }
                    t.nGroupID = nActiveGroup;
                    vTriangles.Add(t);
                    if (t.is_complex())
                    {
                        HasComplexVertices = true;
                    }
                }
            }
        }
Exemple #4
0
        public IOReadResult ParseInput(TextReader reader, ReadOptions options)
        {
            vPositions = new DVector <double>();
            vNormals   = new DVector <float>();
            vUVs       = new DVector <float>();
            vColors    = new DVector <float>();
            vTriangles = new DVector <Triangle>();

            bool        bVerticesHaveColors = false;
            int         nMaxUVLength        = 0;
            OBJMaterial activeMaterial      = null;

            Dictionary <string, int> GroupNames = new Dictionary <string, int>();
            int nGroupCounter = 0;
            int nActiveGroup  = Triangle.InvalidGroupID;

            int nLines = 0;

            while (reader.Peek() >= 0)
            {
                string line = reader.ReadLine();
                nLines++;
                string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                if (tokens.Length == 0)
                {
                    continue;
                }

                // [RMS] this will hang VS on large models...
                //if (nWarningLevel >= 2)
                //    emit_warning("Parsing line " + line);
                try {
                    if (tokens[0][0] == 'v')
                    {
                        if (tokens[0].Length == 1)
                        {
                            if (tokens.Length == 7)
                            {
                                vPositions.Add(Double.Parse(tokens[1]));
                                vPositions.Add(Double.Parse(tokens[2]));
                                vPositions.Add(Double.Parse(tokens[3]));

                                vColors.Add(float.Parse(tokens[4]));
                                vColors.Add(float.Parse(tokens[5]));
                                vColors.Add(float.Parse(tokens[6]));
                                bVerticesHaveColors = true;
                            }
                            else if (tokens.Length >= 4)
                            {
                                vPositions.Add(Double.Parse(tokens[1]));
                                vPositions.Add(Double.Parse(tokens[2]));
                                vPositions.Add(Double.Parse(tokens[3]));
                            }
                            if (tokens.Length != 4 && tokens.Length != 7)
                            {
                                emit_warning("[OBJReader] vertex has unknown format: " + line);
                            }
                        }
                        else if (tokens[0][1] == 'n')
                        {
                            if (tokens.Length >= 4)
                            {
                                vNormals.Add(float.Parse(tokens[1]));
                                vNormals.Add(float.Parse(tokens[2]));
                                vNormals.Add(float.Parse(tokens[3]));
                            }
                            if (tokens.Length != 4)
                            {
                                emit_warning("[OBJReader] normal has more than 3 coordinates: " + line);
                            }
                        }
                        else if (tokens[0][1] == 't')
                        {
                            if (tokens.Length >= 3)
                            {
                                vUVs.Add(float.Parse(tokens[1]));
                                vUVs.Add(float.Parse(tokens[2]));
                                nMaxUVLength = Math.Max(nMaxUVLength, tokens.Length);
                            }
                            if (tokens.Length != 3)
                            {
                                emit_warning("[OBJReader] UV has unknown format: " + line);
                            }
                        }
                    }
                    else if (tokens[0][0] == 'f')
                    {
                        if (tokens.Length < 4)
                        {
                            emit_warning("[OBJReader] degenerate face specified : " + line);
                        }
                        else if (tokens.Length == 4)
                        {
                            Triangle tri = new Triangle();
                            parse_triangle(tokens, ref tri);

                            tri.nGroupID = nActiveGroup;

                            if (activeMaterial != null)
                            {
                                tri.nMaterialID = activeMaterial.id;
                                UsedMaterials[activeMaterial.id] = activeMaterial.name;
                            }

                            vTriangles.Add(tri);
                            if (tri.is_complex())
                            {
                                HasComplexVertices = true;
                            }
                        }
                        else
                        {
                            append_face(tokens, activeMaterial, nActiveGroup);
                        }
                    }
                    else if (tokens[0][0] == 'g')
                    {
                        string sGroupName = (tokens.Length == 2) ? tokens[1] : line.Substring(line.IndexOf(tokens[1]));
                        if (GroupNames.ContainsKey(sGroupName))
                        {
                            nActiveGroup = GroupNames[sGroupName];
                        }
                        else
                        {
                            nActiveGroup           = nGroupCounter;
                            GroupNames[sGroupName] = nGroupCounter++;
                        }
                    }
                    else if (tokens[0][0] == 'o')
                    {
                        // TODO multi-object support
                    }
                    else if (tokens[0] == "mtllib" && options.ReadMaterials)
                    {
                        if (MTLFileSearchPaths.Count == 0)
                        {
                            emit_warning("Materials requested but Material Search Paths not initialized!");
                        }
                        string sMTLPathString = (tokens.Length == 2) ? tokens[1] :
                                                line.Substring(line.IndexOf(tokens[1]));
                        string sFile = FindMTLFile(sMTLPathString);
                        if (sFile != null)
                        {
                            IOReadResult result = ReadMaterials(sFile);
                            if (result.code != IOCode.Ok)
                            {
                                emit_warning("error parsing " + sFile + " : " + result.message);
                            }
                        }
                        else
                        {
                            emit_warning("material file " + sMTLPathString + " could not be found in material search paths");
                        }
                    }
                    else if (tokens[0] == "usemtl" && options.ReadMaterials)
                    {
                        activeMaterial = find_material(tokens[1]);
                    }
                } catch (Exception e) {
                    emit_warning("error parsing line " + nLines.ToString() + ": " + line + ", exception " + e.Message);
                }
            }

            m_bOBJHasPerVertexColors = bVerticesHaveColors;
            m_bOBJHasTriangleGroups  = (nActiveGroup != Triangle.InvalidGroupID);
            m_nSetInvalidGroupsTo    = nGroupCounter++;
            m_nUVComponents          = nMaxUVLength;

            return(new IOReadResult(IOCode.Ok, ""));
        }
Exemple #5
0
        unsafe IOReadResult BuildMeshes_ByMaterial(ReadOptions options, IMeshBuilder builder)
        {
            if (vPositions.Length == 0)
            {
                return(new IOReadResult(IOCode.GarbageDataError, "No vertices in file"));
            }
            if (vTriangles.Length == 0)
            {
                return(new IOReadResult(IOCode.GarbageDataError, "No triangles in file"));
            }

            bool bHaveNormals = (vNormals.Length > 0);
            bool bHaveColors  = (vColors.Length > 0);
            bool bHaveUVs     = (vUVs.Length > 0);

            List <int> usedMaterialIDs = new List <int>(UsedMaterials.Keys);

            usedMaterialIDs.Add(Triangle.InvalidMaterialID);
            foreach (int material_id in usedMaterialIDs)
            {
                int matID = Triangle.InvalidMaterialID;
                if (material_id != Triangle.InvalidMaterialID)
                {
                    string      sMatName = UsedMaterials[material_id];
                    OBJMaterial useMat   = Materials[sMatName];
                    matID = builder.BuildMaterial(useMat);
                }
                bool bMatHaveUVs = (material_id == Triangle.InvalidMaterialID) ? false : bHaveUVs;

                // don't append mesh until we actually see triangles
                int meshID = -1;

                Dictionary <Index3i, int> mapV = new Dictionary <Index3i, int>();

                for (int k = 0; k < vTriangles.Length; ++k)
                {
                    Triangle t = vTriangles[k];
                    if (t.nMaterialID == material_id)
                    {
                        if (meshID == -1)
                        {
                            meshID = builder.AppendNewMesh(bHaveNormals, bHaveColors, bMatHaveUVs, false);
                        }

                        Triangle t2 = new Triangle();
                        for (int j = 0; j < 3; ++j)
                        {
                            Index3i vk = new Index3i(
                                t.vIndices[j] - 1, t.vNormals[j] - 1, t.vUVs[j] - 1);

                            int use_vtx = -1;
                            if (mapV.ContainsKey(vk) == false)
                            {
                                use_vtx  = append_vertex(builder, vk, bHaveNormals, bHaveColors, bMatHaveUVs);
                                mapV[vk] = use_vtx;
                            }
                            else
                            {
                                use_vtx = mapV[vk];
                            }

                            t2.vIndices[j] = use_vtx;
                        }
                        append_triangle(builder, t2);
                    }
                }

                if (matID != Triangle.InvalidMaterialID)
                {
                    builder.AssignMaterial(matID, meshID);
                }
            }

            return(new IOReadResult(IOCode.Ok, ""));
        }
Exemple #6
0
        // write .mtl file
        IOWriteResult write_materials(List <GenericMaterial> vMaterials, WriteOptions options)
        {
            StreamWriter w = new StreamWriter(options.MaterialFilePath);

            if (w.BaseStream == null)
            {
                return(new IOWriteResult(IOCode.FileAccessError, "Could not open file " + options.MaterialFilePath + " for writing"));
            }

            foreach (GenericMaterial gmat in vMaterials)
            {
                if (gmat is OBJMaterial == false)
                {
                    continue;
                }
                OBJMaterial mat = gmat as OBJMaterial;

                w.WriteLine("newmtl {0}", mat.name);
                if (mat.Ka != GenericMaterial.Invalid)
                {
                    w.WriteLine("Ka {0} {1} {2}", mat.Ka.x, mat.Ka.y, mat.Ka.z);
                }
                if (mat.Kd != GenericMaterial.Invalid)
                {
                    w.WriteLine("Kd {0} {1} {2}", mat.Kd.x, mat.Kd.y, mat.Kd.z);
                }
                if (mat.Ks != GenericMaterial.Invalid)
                {
                    w.WriteLine("Ks {0} {1} {2}", mat.Ks.x, mat.Ks.y, mat.Ks.z);
                }
                if (mat.Ke != GenericMaterial.Invalid)
                {
                    w.WriteLine("Ke {0} {1} {2}", mat.Ke.x, mat.Ke.y, mat.Ke.z);
                }
                if (mat.Tf != GenericMaterial.Invalid)
                {
                    w.WriteLine("Tf {0} {1} {2}", mat.Tf.x, mat.Tf.y, mat.Tf.z);
                }
                if (mat.d != Single.MinValue)
                {
                    w.WriteLine("d {0}", mat.d);
                }
                if (mat.Ns != Single.MinValue)
                {
                    w.WriteLine("Ns {0}", mat.Ns);
                }
                if (mat.Ni != Single.MinValue)
                {
                    w.WriteLine("Ni {0}", mat.Ni);
                }
                if (mat.sharpness != Single.MinValue)
                {
                    w.WriteLine("sharpness {0}", mat.sharpness);
                }
                if (mat.illum != -1)
                {
                    w.WriteLine("illum {0}", mat.illum);
                }

                if (mat.map_Ka != null && mat.map_Ka != "")
                {
                    w.WriteLine("map_Ka {0}", mat.map_Ka);
                }
                if (mat.map_Kd != null && mat.map_Kd != "")
                {
                    w.WriteLine("map_Kd {0}", mat.map_Kd);
                }
                if (mat.map_Ks != null && mat.map_Ks != "")
                {
                    w.WriteLine("map_Ks {0}", mat.map_Ks);
                }
                if (mat.map_Ke != null && mat.map_Ke != "")
                {
                    w.WriteLine("map_Ke {0}", mat.map_Ke);
                }
                if (mat.map_d != null && mat.map_d != "")
                {
                    w.WriteLine("map_d {0}", mat.map_d);
                }
                if (mat.map_Ns != null && mat.map_Ns != "")
                {
                    w.WriteLine("map_Ns {0}", mat.map_Ns);
                }

                if (mat.bump != null && mat.bump != "")
                {
                    w.WriteLine("bump {0}", mat.bump);
                }
                if (mat.disp != null && mat.disp != "")
                {
                    w.WriteLine("disp {0}", mat.disp);
                }
                if (mat.decal != null && mat.decal != "")
                {
                    w.WriteLine("decal {0}", mat.decal);
                }
                if (mat.refl != null && mat.refl != "")
                {
                    w.WriteLine("refl {0}", mat.refl);
                }
            }

            w.Close();

            return(IOWriteResult.Ok);
        }