コード例 #1
0
ファイル: WorldR.cs プロジェクト: AlteredCarrot71/OpenBVExp
 internal void Flip()
 {
     if ((this.Flags & FaceTypeMask) == FaceTypeQuadStrip)
     {
         for (int i = 0; i < this.Vertices.Length; i += 2)
         {
             MeshFaceVertex x = this.Vertices[i];
             this.Vertices[i]     = this.Vertices[i + 1];
             this.Vertices[i + 1] = x;
         }
     }
     else
     {
         int n = this.Vertices.Length;
         for (int i = 0; i < (n >> 1); i++)
         {
             MeshFaceVertex x = this.Vertices[i];
             this.Vertices[i]         = this.Vertices[n - i - 1];
             this.Vertices[n - i - 1] = x;
         }
     }
 }
コード例 #2
0
        /// <summary>Loads a Wavefront object from a file.</summary>
        /// <param name="FileName">The text file to load the animated object from. Must be an absolute file name.</param>
        /// <param name="Encoding">The encoding the file is saved in.</param>
        /// <returns>The object loaded.</returns>
        internal static StaticObject ReadObject(string FileName, System.Text.Encoding Encoding)
        {
            StaticObject Object = new StaticObject(Plugin.currentHost);

            MeshBuilder Builder = new MeshBuilder();

            /*
             * Temporary arrays
             */
            List <Vector3> tempVertices = new List <Vector3>();
            List <Vector3> tempNormals  = new List <Vector3>();
            List <Vector2> tempCoords   = new List <Vector2>();

            Material[] TempMaterials = new Material[0];
            //Stores the current material
            int currentMaterial = -1;

            //Read the contents of the file
            string[] Lines = File.ReadAllLines(FileName, Encoding);

            //Preprocess
            for (int i = 0; i < Lines.Length; i++)
            {
                // Strip hash comments
                int c = Lines[i].IndexOf("#", StringComparison.Ordinal);
                if (c >= 0)
                {
                    Lines[i] = Lines[i].Substring(0, c);
                }
                // collect arguments
                List <string> Arguments = new List <string>(Lines[i].Split(new char[] { ' ', '\t' }, StringSplitOptions.None));
                for (int j = Arguments.Count - 1; j >= 0; j--)
                {
                    Arguments[j] = Arguments[j].Trim(new char[] { });
                    if (Arguments[j] == string.Empty)
                    {
                        Arguments.RemoveAt(j);
                    }
                }
                if (Arguments.Count == 0)
                {
                    continue;
                }
                switch (Arguments[0].ToLowerInvariant())
                {
                case "v":
                    //Vertex
                    Vector3 vertex = new Vector3();
                    if (!double.TryParse(Arguments[1], out vertex.X))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out vertex.Y))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex at Line " + i);
                    }
                    if (!double.TryParse(Arguments[3], out vertex.Z))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex at Line " + i);
                    }
                    tempVertices.Add(vertex);
                    break;

                case "vt":
                    //Vertex texture co-ords
                    Vector2 coords = new Vector2();
                    if (!double.TryParse(Arguments[1], out coords.X))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-ordinates at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out coords.Y))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Texture Co-Ordinates at Line " + i);
                    }
                    tempCoords.Add(coords);
                    break;

                case "vn":
                    Vector3 normal = new Vector3();
                    if (!double.TryParse(Arguments[1], out normal.X))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid X co-ordinate in Vertex Normal at Line " + i);
                    }
                    if (!double.TryParse(Arguments[2], out normal.Y))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Y co-ordinate in Vertex Normal at Line " + i);
                    }
                    if (!double.TryParse(Arguments[3], out normal.Z))
                    {
                        Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Z co-ordinate in Vertex Normal at Line " + i);
                    }
                    tempNormals.Add(normal);
                    //Vertex normals
                    break;

                case "vp":
                    //Parameter space verticies, not supported
                    throw new NotSupportedException("Parameter space verticies are not supported by this parser");

                case "f":
                    //Creates a new face

                    //Create the temp list to hook out the vertices
                    List <VertexTemplate> vertices = new List <VertexTemplate>();
                    List <Vector3>        normals  = new List <Vector3>();
                    for (int f = 1; f < Arguments.Count; f++)
                    {
                        Vertex   newVertex     = new Vertex();
                        string[] faceArguments = Arguments[f].Split(new char[] { '/' }, StringSplitOptions.None);
                        int      idx;
                        if (!int.TryParse(faceArguments[0], out idx))
                        {
                            Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Vertex index in Face " + f + " at Line " + i);
                            continue;
                        }

                        int currentVertex = tempVertices.Count;
                        if (idx != Math.Abs(idx))
                        {
                            //Offset, so we seem to need to add one....
                            currentVertex++;
                            currentVertex += idx;
                        }
                        else
                        {
                            currentVertex = idx;
                        }
                        if (currentVertex > tempVertices.Count)
                        {
                            Plugin.currentHost.AddMessage(MessageType.Warning, false, "Vertex index " + idx + " was greater than the available number of vertices in Face " + f + " at Line " + i);
                            continue;
                        }
                        newVertex.Coordinates = tempVertices[currentVertex - 1];
                        if (faceArguments.Length <= 1)
                        {
                            normals.Add(new Vector3());
                        }
                        else
                        {
                            if (!int.TryParse(faceArguments[1], out idx))
                            {
                                if (!string.IsNullOrEmpty(faceArguments[1]))
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Texture Co-ordinate index in Face " + f + " at Line " + i);
                                }
                                newVertex.TextureCoordinates = new Vector2();
                            }
                            else
                            {
                                int currentCoord = tempCoords.Count;
                                if (idx != Math.Abs(idx))
                                {
                                    //Offset, so we seem to need to add one....
                                    currentCoord++;
                                    currentCoord += idx;
                                }
                                else
                                {
                                    currentCoord = idx;
                                }
                                if (currentCoord > tempCoords.Count)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Texture Co-ordinate index " + currentCoord + " was greater than the available number of texture co-ordinates in Face " + f + " at Line " + i);
                                }
                                else
                                {
                                    newVertex.TextureCoordinates = tempCoords[currentCoord - 1];
                                }
                            }
                        }
                        if (faceArguments.Length <= 2)
                        {
                            normals.Add(new Vector3());
                        }
                        else
                        {
                            if (!int.TryParse(faceArguments[2], out idx))
                            {
                                if (!string.IsNullOrEmpty(faceArguments[2]))
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid Vertex Normal index in Face " + f + " at Line " + i);
                                }
                                normals.Add(new Vector3());
                            }
                            else
                            {
                                int currentNormal = tempNormals.Count;
                                if (idx != Math.Abs(idx))
                                {
                                    //Offset, so we seem to need to add one....
                                    currentNormal++;
                                    currentNormal += idx;
                                }
                                else
                                {
                                    currentNormal = idx;
                                }
                                if (currentNormal > tempNormals.Count)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Vertex Normal index " + currentNormal + " was greater than the available number of normals in Face " + f + " at Line " + i);
                                    normals.Add(new Vector3());
                                }
                                else
                                {
                                    normals.Add(tempNormals[currentNormal - 1]);
                                }
                            }
                        }
                        vertices.Add(newVertex);
                    }
                    MeshFaceVertex[] Vertices = new MeshFaceVertex[vertices.Count];
                    for (int k = 0; k < vertices.Count; k++)
                    {
                        Builder.Vertices.Add(vertices[k]);
                        Vertices[k].Index  = (ushort)(Builder.Vertices.Count - 1);
                        Vertices[k].Normal = normals[k];
                    }
                    Builder.Faces.Add(currentMaterial == -1 ? new MeshFace(Vertices, 0) : new MeshFace(Vertices, (ushort)currentMaterial));
                    break;

                case "g":
                    //Starts a new face group and (normally) applies a new texture
                    ApplyMeshBuilder(ref Object, Builder);
                    Builder = new MeshBuilder();
                    break;

                case "s":
                    /*
                     * Changes the smoothing group applied to these vertexes:
                     * 0- Disabled (Overriden by Vertex normals)
                     * Otherwise appears to be a bitmask (32 available groups)
                     * whereby faces within the same groups have their normals averaged
                     * to appear smooth joins
                     *
                     * Not really supported at the minute, probably requires the engine
                     * twiddling to deliberately support specifiying the shading type for a face
                     *
                     */
                    break;

                case "mtllib":
                    //Loads the library of materials used by this file
                    string MaterialsPath = OpenBveApi.Path.CombineFile(Path.GetDirectoryName(FileName), Arguments[1]);
                    if (File.Exists(MaterialsPath))
                    {
                        LoadMaterials(MaterialsPath, ref TempMaterials);
                    }
                    break;

                case "usemtl":
                    for (int m = 0; m < TempMaterials.Length; m++)
                    {
                        if (TempMaterials[m].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant())
                        {
                            bool mf = false;
                            for (int k = 0; k < Builder.Materials.Length; k++)
                            {
                                if (Builder.Materials[k].Key != null && Builder.Materials[k].Key.ToLowerInvariant() == Arguments[1].ToLowerInvariant())
                                {
                                    mf = true;
                                    currentMaterial = k;
                                    break;
                                }
                            }
                            if (!mf)
                            {
                                Array.Resize(ref Builder.Materials, Builder.Materials.Length + 1);
                                Builder.Materials[Builder.Materials.Length - 1] = TempMaterials[m];
                                currentMaterial = Builder.Materials.Length - 1;
                            }
                            break;
                        }
                        if (m == TempMaterials.Length)
                        {
                            Plugin.currentHost.AddMessage(MessageType.Error, true, "Material " + Arguments[1] + " was not found.");
                            currentMaterial = -1;
                        }
                    }
                    break;

                default:
                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Unrecognised command " + Arguments[0]);
                    break;
                }
            }
            ApplyMeshBuilder(ref Object, Builder);
            Object.Mesh.CreateNormals();
            return(Object);
        }