Ejemplo n.º 1
0
        /// <summary>
        /// This method is used to load information stored in .mtl files referenced by the .obj file.
        /// </summary>
        /// <param name="d3ddevice"></param>
        /// <param name="file"></param>

        private void parseOBJ(string basePath, string filename)
        {
            MaterialInfoWithFaces currentMaterial = null;

            StreamReader sr = SSAssetManager.OpenStreamReader(Path.Combine(basePath, filename));

            //Read the first line of text
            string line = sr.ReadLine();

            //Continue to read until you reach end of file
            while (line != null)
            {
                // handle line continuation with "\"
                if (line.Length > 0)
                {
                    while (line[line.Length - 1] == '\\')
                    {
                        line = line.Substring(0, line.Length - 1); // remove line extender..
                        var nextline = sr.ReadLine();
                        if (nextline != null && nextline.Length != 0)
                        {
                            line = line + nextline; // merge with next line
                        }
                        else
                        {
                            break; // be sure to avoid infinite loop...
                        }
                    }
                }

                // split the line into tokens, separated by space
                string[] tokens = line.Split(" ".ToArray(), 2);
                if (tokens.Length < 2)
                {
                    goto next_line;
                }

                string firstToken  = tokens[0];
                string lineContent = tokens[1];

                switch (firstToken)
                {
                /* unsupported features - fatal */
                case "cstype":        // curved surface type (bmatrix, bezier, bspline, cardinal, taylor)
                case "deg":           // curve attr: degree
                case "step":          // curve attr: step size
                case "bmat":          // curve attr: basis matrix
                case "surf":          // surface
                case "parm":          // curve body: paramater value
                case "trim":          // curve body: outer trimming loop
                case "hole":          // curve body: inner trimming loop
                case "scrv":          // curve body: special curve
                case "sp":            // curve body: special point
                case "end":           // curve body: end
                case "con":           // connection between free form surfaces
                case "vp":            // paramater space vertex (for free form surfaces)

                case "bevel":         // bevel interpolation
                case "c_interp":      // color interpolation
                case "d_interp":      // dissolve interpolation
                case "lod":           // level of detail
                case "ctech":         // Curve approximation technique
                case "stech":         // Surface approximation technique
                case "mg":            // merging group (for free form surfaces)

                    throw new WavefrontObjParseException("WavefrontObjLoader.cs: fatal error, token not supported :  " + firstToken);

                /* unsupported features - warning */
                case "o":             // object name
                case "g":             // group name
                case "s":             // smoothing group
                case "shadow_obj":    // shadow casting
                case "trace_obj":     // ray tracing
                    Console.WriteLine("WavefrontObjLoader.cs: warning - unsupported wavefront token : " + firstToken);
                    break;

                /* supported features */
                case "#":       // Nothing to read, these are comments.
                    break;

                case "v":       // Vertex position
                    positions.Add(WavefrontParser.readVector4(lineContent, null));
                    break;

                case "vn":      // vertex normal direction vector
                    normals.Add(WavefrontParser.readVector3(lineContent, null));
                    break;

                case "vt":      // Vertex texcoordinate
                    texCoords.Add(WavefrontParser.readVector2(lineContent, null));
                    break;

                case "f":       // Face
                    string[] values    = WavefrontParser.FilteredSplit(lineContent, null);
                    int      numPoints = values.Length;

                    Face face = new Face();
                    face.v_idx   = new Int16[numPoints];
                    face.n_idx   = new Int16[numPoints];
                    face.tex_idx = new Int16[numPoints];      // todo: how do outside clients know if there were texcoords or not?!?!

                    for (int i = 0; i < numPoints; i++)
                    {
                        // format is "loc_index[/tex_index[/normal_index]]"  e.g. 3 ; 3/2 ; 3/2/5
                        // but middle part can me empty, e.g. 3//5
                        string[] indexes = values[i].Split('/');

                        int iPosition = (int.Parse(indexes[0]) - 1);      // adjust 1-based index
                        if (iPosition < 0)
                        {
                            iPosition += positions.Count + 1;
                        }                                                            // adjust negative indicies
                        face.v_idx[i] = (Int16)iPosition;
                        numIndices++;

                        // initialize other indicies to not provided, in case they are missing
                        face.n_idx[i]   = -1;
                        face.tex_idx[i] = -1;

                        if (indexes.Length > 1)
                        {
                            string tex_index = indexes[1];
                            if (tex_index != "")
                            {
                                int iTexCoord = int.Parse(tex_index) - 1;     // adjust 1-based index
                                if (iTexCoord < 0)
                                {
                                    iTexCoord += texCoords.Count + 1;
                                }                                                             // adjust negative indicies

                                face.tex_idx[i] = (Int16)iTexCoord;
                            }

                            if (indexes.Length > 2)
                            {
                                hasNormals = true;
                                int iNormal = int.Parse(indexes[2]) - 1;     // adjust 1 based index
                                if (iNormal < 0)
                                {
                                    iNormal += normals.Count + 1;
                                }                                                      // adjust negative indicies

                                face.n_idx[i] = (Int16)iNormal;
                            }
                        }
                    }
                    if (currentMaterial == null)
                    {
                        // no material in file, so create one
                        currentMaterial = createImplicitMaterial();
                    }
                    currentMaterial.faces.Add(face);
                    currentMaterial.nbrIndices += face.v_idx.Length;
                    numFaces++;
                    break;

                case "mtllib":      // load named material file
                    string mtlFile = lineContent;
                    {
                        var mtls = SSWavefrontMTLInfo.ReadMTLs(Path.Combine(basePath, mtlFile));
                        foreach (var mtl in mtls)
                        {
                            materials.Add(new MaterialInfoWithFaces(mtl));
                        }
                    }
                    break;

                case "usemtl":      // use named material (from material file previously loaded)
                    bool found = false;

                    string matName = lineContent;

                    for (int i = 0; i < materials.Count; i++)
                    {
                        if (matName.Equals(materials[i].mtl.name))
                        {
                            found           = true;
                            currentMaterial = materials[i];
                        }
                    }

                    if (!found)
                    {
                        throw new WavefrontObjParseException("Materials are already loaded so we should have it!");
                    }
                    break;
                }

next_line:
                //Read the next line
                line = sr.ReadLine();
            }

            //close the file
            sr.Close();


            // debug print loaded stats
            Console.WriteLine("WavefrontObjLoader.cs: file processed...");
            Console.WriteLine("   vertex positions: {0}", positions.Count);
            Console.WriteLine("   vertex   normals: {0}", normals.Count);
            Console.WriteLine("   vertex texCoords: {0}", texCoords.Count);
            foreach (var mtl in materials)
            {
                Console.WriteLine(
                    "           Material:      faces: {1}  indicies: {2}  ({0})", mtl.mtl.name, mtl.faces.Count, mtl.nbrIndices);
                Console.WriteLine(
                    "                       diff Tex: {0}", mtl.mtl.diffuseTextureResourceName);
            }
            Console.WriteLine("WavefrontObjLoader.cs: end.");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This method is used to load information stored in .mtl files referenced by the .obj file.
        /// </summary>
        /// <param name="d3ddevice"></param>
        /// <param name="file"></param>

        private void parseOBJ(SSAssetManager.Context ctx, string filename)
        {
            MaterialInfoWithFaces currentMaterial = null;

            StreamReader sr = ctx.OpenText(filename);

            //Read the first line of text
            string line = sr.ReadLine();

            //Continue to read until you reach end of file
            while (line != null)
            {
                string[] tokens = line.Split(" ".ToArray(), 2);
                if (tokens.Length < 2)
                {
                    goto next_line;
                }

                string firstToken  = tokens[0];
                string lineContent = tokens[1];

                switch (firstToken)
                {
                case "#":       // Nothing to read, these are comments.
                    break;

                case "v":       // Vertex position
                    positions.Add(WavefrontParser.readVector4(lineContent, null));
                    break;

                case "vn":      // vertex normal direction vector
                    normals.Add(WavefrontParser.readVector3(lineContent, null));
                    break;

                case "vt":      // Vertex texcoordinate
                    texCoords.Add(WavefrontParser.readVector2(lineContent, null));
                    break;

                case "f":       // Face
                    string[] values    = WavefrontParser.FilteredSplit(lineContent, null);
                    int      numPoints = values.Length;

                    Face face = new Face();
                    face.v_idx   = new Int16[numPoints];
                    face.n_idx   = new Int16[numPoints];
                    face.tex_idx = new Int16[numPoints];      // todo: how do outside clients know if there were texcoords or not?!?!

                    for (int i = 0; i < numPoints; i++)
                    {
                        // format is "loc_index[/tex_index[/normal_index]]"  e.g. 3 ; 3/2 ; 3/2/5
                        // but middle part can me empty, e.g. 3//5
                        string[] indexes = values[i].Split('/');

                        int iPosition = (int.Parse(indexes[0]) - 1);      // adjust 1-based index
                        if (iPosition < 0)
                        {
                            iPosition += positions.Count + 1;
                        }                                                            // adjust negative indicies
                        face.v_idx[i] = (Int16)iPosition;
                        numIndices++;

                        // initialize other indicies to not provided, in case they are missing
                        face.n_idx[i]   = -1;
                        face.tex_idx[i] = -1;

                        if (indexes.Length > 1)
                        {
                            string tex_index = indexes[1];
                            if (tex_index != "")
                            {
                                int iTexCoord = int.Parse(tex_index) - 1;     // adjust 1-based index
                                if (iTexCoord < 0)
                                {
                                    iTexCoord += texCoords.Count + 1;
                                }                                                             // adjust negative indicies

                                face.tex_idx[i] = (Int16)iTexCoord;
                            }

                            if (indexes.Length > 2)
                            {
                                hasNormals = true;
                                int iNormal = int.Parse(indexes[2]) - 1;     // adjust 1 based index
                                if (iNormal < 0)
                                {
                                    iNormal += normals.Count + 1;
                                }                                                      // adjust negative indicies

                                face.n_idx[i] = (Int16)iNormal;
                            }
                        }
                    }
                    if (currentMaterial == null)
                    {
                        // no material in file, so create one
                        currentMaterial = createImplicitMaterial();
                    }
                    currentMaterial.faces.Add(face);
                    currentMaterial.nbrIndices += face.v_idx.Length;
                    numFaces++;
                    break;

                case "mtllib":      // load named material file
                    string mtlFile = lineContent;
                    {
                        var mtls = SSWavefrontMTLInfo.ReadMTLs(ctx, mtlFile);
                        foreach (var mtl in mtls)
                        {
                            materials.Add(new MaterialInfoWithFaces(mtl));
                        }
                    }
                    break;

                case "usemtl":      // use named material (from material file previously loaded)
                    bool found = false;

                    string matName = lineContent;

                    for (int i = 0; i < materials.Count; i++)
                    {
                        if (matName.Equals(materials[i].mtl.name))
                        {
                            found           = true;
                            currentMaterial = materials[i];
                        }
                    }

                    if (!found)
                    {
                        throw new WavefrontObjParseException("Materials are already loaded so we should have it!");
                    }
                    break;
                }

next_line:
                //Read the next line
                line = sr.ReadLine();
            }

            //close the file
            sr.Close();
        }