Exemplo n.º 1
0
        /// <summary>
        /// Processes a line from an OBJ file.
        /// </summary>
        /// <param name="line">A line from an OBJ file.</param>
        /// <param name="state">An object that manages state between calls.</param>
        private void ProcessObjLine(string line, ObjFileProcessorState state)
        {
            // Trim out comments (allow comments trailing on a line)
            int commentStart = line.IndexOf('#');

            if (commentStart != -1)
            {
                line = line.Substring(0, commentStart);
            }

            // Tokenize line
            string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);

            // Process line based on the keyword used
            if (tokens.Length > 0)
            {
                int?     v;
                float    x, y, z;
                Vertex[] faceVertices;
                int?[]   vt, vn;

                switch (tokens[0])
                {
                case "v":       // Vertex
                    if (tokens.Length != 4)
                    {
                        throw new IOException("Vertices in the OBJ file must have 3 coordinates.");
                    }

                    x = Single.Parse(tokens[1], CultureInfo.InvariantCulture);
                    y = Single.Parse(tokens[2], CultureInfo.InvariantCulture);
                    z = Single.Parse(tokens[3], CultureInfo.InvariantCulture);

                    Vertices.Add(new VertexTraits(x, y, z));
                    break;

                case "vt":       // Vertex texture
                    if (tokens.Length != 3 && tokens.Length != 4)
                    {
                        throw new IOException("Texture coordinates in the OBJ file must have 2 or 3 coordinates.");
                    }

                    x = Single.Parse(tokens[1], CultureInfo.InvariantCulture);
                    y = Single.Parse(tokens[2], CultureInfo.InvariantCulture);

                    state.VertexTextureCoords.Add(new Point(x, y));
                    break;

                case "vn":       // Vertex normal
                    if (tokens.Length != 4)
                    {
                        throw new IOException("Vertex normals in the OBJ file must have 3 coordinates.");
                    }

                    x = Single.Parse(tokens[1], CultureInfo.InvariantCulture);
                    y = Single.Parse(tokens[2], CultureInfo.InvariantCulture);
                    z = Single.Parse(tokens[3], CultureInfo.InvariantCulture);

                    state.VertexNormals.Add(new Vector3D(x, y, z));
                    break;

                case "f":       // Face
                    faceVertices = new Vertex[tokens.Length - 1];
                    vt           = new int?[tokens.Length - 1];
                    vn           = new int?[tokens.Length - 1];

                    // Parse vertex/texture coordinate/normal indices
                    for (int i = 0; i < faceVertices.Length; ++i)
                    {
                        string[] vertexTokens = tokens[i + 1].Split("/".ToCharArray());

                        v = Int32.Parse(vertexTokens[0]);

                        if (vertexTokens.Length > 1 && vertexTokens[1].Length > 0)
                        {
                            vt[i] = Int32.Parse(vertexTokens[1]);
                        }
                        else
                        {
                            Traits.HasTextureCoordinates = false;
                        }

                        if (vertexTokens.Length > 2 && vertexTokens[2].Length > 0)
                        {
                            vn[i] = Int32.Parse(vertexTokens[2]);
                        }
                        else
                        {
                            Traits.HasFaceVertexNormals = false;
                        }

                        faceVertices[i] = Vertices[v.Value - 1];
                    }

                    Face[] addedFaces = Faces.AddTriangles(faceVertices);

                    // Set texture coordinates and normals if any are given
                    for (int i = 0; i < faceVertices.Length; ++i)
                    {
                        Halfedge faceVertex;
                        if (vt[i].HasValue || vn[i].HasValue)
                        {
                            foreach (Face f in addedFaces)
                            {
                                faceVertex = f.FindHalfedgeTo(faceVertices[i]);
                                if (faceVertex != null)     // Make sure vertex belongs to face if triangularization is on
                                {
                                    if (vt[i].HasValue)
                                    {
                                        faceVertex.Traits.TextureCoordinate = state.VertexTextureCoords[vt[i].Value - 1];
                                    }
                                    if (vn[i].HasValue)
                                    {
                                        faceVertex.Traits.Normal = state.VertexNormals[vn[i].Value - 1];
                                    }
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }