Normalize() static private method

static private Normalize ( double &x, double &y ) : void
x double
y double
return void
示例#1
0
 // reset camera
 internal static void ResetCamera()
 {
     World.AbsoluteCameraPosition  = new Vector3(-5.0, 2.5, -25.0);
     World.AbsoluteCameraDirection = new Vector3(-World.AbsoluteCameraPosition.X, -World.AbsoluteCameraPosition.Y, -World.AbsoluteCameraPosition.Z);
     World.AbsoluteCameraSide      = new Vector3(-World.AbsoluteCameraPosition.Z, 0.0, World.AbsoluteCameraPosition.X);
     World.Normalize(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z);
     World.Normalize(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z);
     World.AbsoluteCameraUp             = Vector3.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide);
     World.VerticalViewingAngle         = 45.0 * 0.0174532925199433;
     World.HorizontalViewingAngle       = 2.0 * Math.Atan(Math.Tan(0.5 * World.VerticalViewingAngle) * World.AspectRatio);
     World.OriginalVerticalViewingAngle = World.VerticalViewingAngle;
 }
            internal void ApplyShear(double dx, double dy, double dz, double sx, double sy, double sz, double r)
            {
                for (int j = 0; j < Mesh.Vertices.Length; j++)
                {
                    double n = r * (dx * Mesh.Vertices[j].Coordinates.X + dy * Mesh.Vertices[j].Coordinates.Y + dz * Mesh.Vertices[j].Coordinates.Z);
                    Mesh.Vertices[j].Coordinates.X += sx * n;
                    Mesh.Vertices[j].Coordinates.Y += sy * n;
                    Mesh.Vertices[j].Coordinates.Z += sz * n;
                }

                // ReSharper disable NotAccessedVariable
                double ux, uy, uz;

                // ReSharper restore NotAccessedVariable
                World.Cross(sx, sy, sz, dx, dy, dz, out ux, out uy, out uz);
                for (int j = 0; j < Mesh.Faces.Length; j++)
                {
                    for (int k = 0; k < Mesh.Faces[j].Vertices.Length; k++)
                    {
                        if (Mesh.Faces[j].Vertices[k].Normal.X != 0.0f | Mesh.Faces[j].Vertices[k].Normal.Y != 0.0f | Mesh.Faces[j].Vertices[k].Normal.Z != 0.0f)
                        {
                            double nx = (double)Mesh.Faces[j].Vertices[k].Normal.X;
                            double ny = (double)Mesh.Faces[j].Vertices[k].Normal.Y;
                            double nz = (double)Mesh.Faces[j].Vertices[k].Normal.Z;
                            double n  = r * (sx * nx + sy * ny + sz * nz);
                            nx -= dx * n;
                            ny -= dy * n;
                            nz -= dz * n;
                            World.Normalize(ref nx, ref ny, ref nz);
                            Mesh.Faces[j].Vertices[k].Normal.X = (float)nx;
                            Mesh.Faces[j].Vertices[k].Normal.Y = (float)ny;
                            Mesh.Faces[j].Vertices[k].Normal.Z = (float)nz;
                        }
                    }
                }
            }
示例#3
0
        /// <summary>Loads a Loksim3D 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="LoadMode">The texture load mode.</param>
        /// <param name="Rotation">The rotation to be applied</param>
        /// <returns>The object loaded.</returns>
        internal static ObjectManager.StaticObject ReadObject(string FileName, ObjectManager.ObjectLoadMode LoadMode, Vector3 Rotation)
        {
            string      BaseDir    = System.IO.Path.GetDirectoryName(FileName);
            XmlDocument currentXML = new XmlDocument();

            //Initialise the object
            ObjectManager.StaticObject Object = new ObjectManager.StaticObject();
            Object.Mesh.Faces     = new World.MeshFace[] { };
            Object.Mesh.Materials = new World.MeshMaterial[] { };
            Object.Mesh.Vertices  = new World.Vertex[] { };
            MeshBuilder Builder = new MeshBuilder();

            Vector3[] Normals         = new Vector3[4];
            bool      PropertiesFound = false;

            World.Vertex[] tempVertices       = new World.Vertex[0];
            Vector3[]      tempNormals        = new Vector3[0];
            Color24        transparentColor   = new Color24();
            string         tday               = null;
            string         tnight             = null;
            string         transtex           = null;
            bool           TransparencyUsed   = false;
            bool           TransparentTypSet  = false;
            bool           FirstPxTransparent = false;
            Color24        FirstPxColor       = new Color24();
            bool           Face2              = false;
            int            TextureWidth       = 0;
            int            TextureHeight      = 0;

            if (File.Exists(FileName))
            {
                try
                {
                    currentXML.Load(FileName);
                }
                catch
                {
                    return(null);
                }
            }
            else
            {
                Interface.AddMessage(Interface.MessageType.Error, false, "Loksim3D object " + FileName + " does not exist.");
                return(null);
            }
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/OBJECT");
                //Check this file actually contains Loksim3D object nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode outerNode in DocumentNodes)
                    {
                        if (outerNode.ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode node in outerNode.ChildNodes)
                            {
                                //I think there should only be one properties node??
                                //Need better format documentation
                                if (node.Name == "Props" && PropertiesFound == false)
                                {
                                    if (node.Attributes != null)
                                    {
                                        //Our node has child nodes, therefore this properties node should be valid
                                        //Needs better validation
                                        PropertiesFound = true;
                                        foreach (XmlAttribute attribute in node.Attributes)
                                        {
                                            switch (attribute.Name)
                                            {
                                            //Sets the texture
                                            //Loksim3D objects only support daytime textures
                                            case "Texture":
                                                tday = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                if (!File.Exists(tday))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Warning, true, "Ls3d Texture file " + attribute.Value + " not found.");
                                                    break;
                                                }
                                                try
                                                {
                                                    using (Bitmap TextureInformation = new Bitmap(tday))
                                                    {
                                                        TextureWidth  = TextureInformation.Width;
                                                        TextureHeight = TextureInformation.Height;
                                                        Color color = TextureInformation.GetPixel(0, 0);
                                                        FirstPxColor = new Color24(color.R, color.G, color.B);
                                                    }
                                                }
                                                catch
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, true,
                                                                         "An error occured loading daytime texture " + tday +
                                                                         " in file " + FileName);
                                                    tday = null;
                                                }
                                                break;

                                            //Defines whether the texture uses transparency
                                            //May be omitted
                                            case "Transparent":
                                                if (TransparentTypSet)
                                                {
                                                    //Appears to be ignored with TransparentTyp set
                                                    continue;
                                                }
                                                if (attribute.Value == "TRUE")
                                                {
                                                    TransparencyUsed = true;
                                                    transparentColor = new Color24(0, 0, 0);
                                                }
                                                break;

                                            case "TransTexture":
                                                if (string.IsNullOrEmpty(attribute.Value))
                                                {
                                                    //Empty....
                                                    continue;
                                                }
                                                transtex = OpenBveApi.Path.Loksim3D.CombineFile(BaseDir, attribute.Value, Program.FileSystem.LoksimPackageInstallationDirectory);
                                                if (!File.Exists(transtex))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, true, "AlphaTexture " + transtex + " could not be found in file " + FileName);
                                                    transtex = null;
                                                }
                                                break;

                                            //Sets the transparency type
                                            case "TransparentTyp":
                                                TransparentTypSet = true;
                                                switch (attribute.Value)
                                                {
                                                case "0":
                                                    //Transparency is disabled
                                                    TransparencyUsed = false;
                                                    break;

                                                case "1":
                                                    //Transparency is solid black
                                                    TransparencyUsed   = true;
                                                    transparentColor   = new Color24(0, 0, 0);
                                                    FirstPxTransparent = false;
                                                    break;

                                                case "2":
                                                    //Transparency is the color at Pixel 1,1
                                                    TransparencyUsed   = true;
                                                    FirstPxTransparent = true;
                                                    break;

                                                case "3":
                                                case "4":
                                                    //This is used when transparency is used with an alpha bitmap
                                                    TransparencyUsed   = false;
                                                    FirstPxTransparent = false;
                                                    break;

                                                case "5":
                                                    //Use the alpha channel from the image, so we don't need to do anything fancy
                                                    //TODO: (Low priority) Check what happens in Loksim itself when an image uses the Alpha channel, but doesn't actually specify type 5
                                                    break;

                                                default:
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Unrecognised transparency type " + attribute.Value + " detected in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    break;
                                                }
                                                break;

                                            //Sets whether the rears of the faces are to be drawn
                                            case "Drawrueckseiten":
                                                if (attribute.Value == "TRUE" || string.IsNullOrEmpty(attribute.Value))
                                                {
                                                    Face2 = true;
                                                }
                                                else
                                                {
                                                    Face2 = false;
                                                }
                                                break;

                                                /*
                                                 * MISSING PROPERTIES:
                                                 * AutoRotate - Rotate with tracks?? LS3D presumably uses a 3D world system.
                                                 * Beleuchtet- Translates as illuminated. Presume something to do with lighting? - What emissive color?
                                                 * FileAuthor
                                                 * FileInfo
                                                 * FilePicture
                                                 */
                                            }
                                        }
                                    }
                                }
                                //The point command is eqivilant to a vertex
                                else if (node.Name == "Point" && node.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Vertex
                                            double vx = 0.0, vy = 0.0, vz = 0.0;
                                            //Normals
                                            double nx = 0.0, ny = 0.0, nz = 0.0;
                                            foreach (XmlAttribute attribute in childNode.Attributes)
                                            {
                                                switch (attribute.Name)
                                                {
                                                //Sets the vertex normals
                                                case "Normal":
                                                    string[] NormalPoints = attribute.Value.Split(';');
                                                    if (!double.TryParse(NormalPoints[0], out nx))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nX in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(NormalPoints[1], out ny))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nY in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(NormalPoints[2], out nz))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument nZ in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    break;

                                                //Sets the vertex 3D co-ordinates
                                                case "Vekt":
                                                    string[] VertexPoints = attribute.Value.Split(';');
                                                    if (!double.TryParse(VertexPoints[0], out vx))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument vX in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(VertexPoints[1], out vy))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument yY in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    if (!double.TryParse(VertexPoints[2], out vz))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Invalid argument vZ in " + attribute.Name + " in Loksim3D object file " + FileName);
                                                    }
                                                    break;
                                                }
                                            }
                                            World.Normalize(ref nx, ref ny, ref nz);
                                            //Resize temp arrays
                                            Array.Resize <World.Vertex>(ref tempVertices, tempVertices.Length + 1);
                                            Array.Resize <Vector3>(ref tempNormals, tempNormals.Length + 1);
                                            //Add vertex and normals to temp array
                                            tempVertices[tempVertices.Length - 1].Coordinates = new Vector3(vx, vy, vz);
                                            tempNormals[tempNormals.Length - 1] = new Vector3((float)nx, (float)ny, (float)nz);
                                            Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                            while (Builder.Vertices.Length >= Normals.Length)
                                            {
                                                Array.Resize <Vector3>(ref Normals, Normals.Length << 1);
                                            }
                                            Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = new Vector3(vx, vy, vz);
                                            Normals[Builder.Vertices.Length - 1] = new Vector3((float)nx, (float)ny, (float)nz);
                                        }
                                    }
                                }
                                //The Flaeche command creates a face
                                else if (node.Name == "Flaeche" && node.ChildNodes.OfType <XmlElement>().Any())
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Defines the verticies in this face
                                            //**NOTE**: A vertex may appear in multiple faces with different texture co-ordinates
                                            if (childNode.Attributes["Points"] != null)
                                            {
                                                string[] Verticies = childNode.Attributes["Points"].Value.Split(';');
                                                int      f         = Builder.Faces.Length;
                                                //Add 1 to the length of the face array
                                                Array.Resize <World.MeshFace>(ref Builder.Faces, f + 1);
                                                Builder.Faces[f] = new World.MeshFace();
                                                //Create the vertex array for the face
                                                Builder.Faces[f].Vertices = new World.MeshFaceVertex[Verticies.Length];
                                                while (Builder.Vertices.Length > Normals.Length)
                                                {
                                                    Array.Resize <Vector3>(ref Normals,
                                                                           Normals.Length << 1);
                                                }
                                                //Run through the vertices list and grab from the temp array

                                                int smallestX = TextureWidth;
                                                int smallestY = TextureHeight;
                                                for (int j = 0; j < Verticies.Length; j++)
                                                {
                                                    //This is the position of the vertex in the temp array
                                                    int currentVertex;
                                                    if (!int.TryParse(Verticies[j], out currentVertex))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, Verticies[j] + " does not parse to a valid Vertex in " + node.Name + " in Loksim3D object file " + FileName);
                                                        continue;
                                                    }
                                                    //Add one to the actual vertex array
                                                    Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                                    //Set coordinates
                                                    Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = tempVertices[currentVertex].Coordinates;
                                                    //Set the vertex index
                                                    Builder.Faces[f].Vertices[j].Index = (ushort)(Builder.Vertices.Length - 1);
                                                    //Set the normals
                                                    Builder.Faces[f].Vertices[j].Normal = tempNormals[currentVertex];
                                                    //Now deal with the texture
                                                    //Texture mapping points are in pixels X,Y and are relative to the face in question rather than the vertex
                                                    if (childNode.Attributes["Texture"] != null)
                                                    {
                                                        string[] TextureCoords = childNode.Attributes["Texture"].Value.Split(';');
                                                        Vector2  currentCoords;
                                                        float    OpenBVEWidth;
                                                        float    OpenBVEHeight;
                                                        string[] splitCoords = TextureCoords[j].Split(',');
                                                        if (!float.TryParse(splitCoords[0], out OpenBVEWidth))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Invalid texture width specified in " + node.Name + " in Loksim3D object file " + FileName);
                                                            continue;
                                                        }
                                                        if (!float.TryParse(splitCoords[1], out OpenBVEHeight))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Invalid texture height specified in " + node.Name + " in Loksim3D object file " + FileName);
                                                            continue;
                                                        }
                                                        if (OpenBVEWidth <= smallestX && OpenBVEHeight <= smallestY)
                                                        {
                                                            //Clamp texture width and height
                                                            smallestX = (int)OpenBVEWidth;
                                                            smallestY = (int)OpenBVEHeight;
                                                        }
                                                        if (TextureWidth != 0 && TextureHeight != 0)
                                                        {
                                                            //Calculate openBVE co-ords
                                                            currentCoords.X = (OpenBVEWidth / TextureWidth);
                                                            currentCoords.Y = (OpenBVEHeight / TextureHeight);
                                                        }
                                                        else
                                                        {
                                                            //Invalid, so just return zero
                                                            currentCoords.X = 0;
                                                            currentCoords.Y = 0;
                                                        }
                                                        Builder.Vertices[Builder.Vertices.Length - 1].TextureCoordinates = currentCoords;
                                                    }
                                                }
                                                if (Face2)
                                                {
                                                    //Add face2 flag if required
                                                    Builder.Faces[f].Flags = (byte)World.MeshFace.Face2Mask;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //Apply rotation

                /*
                 * NOTES:
                 * No rotation order is specified
                 * The rotation string in a .l3dgrp file is ordered Y, Z, X    ??? Can't find a good reason for this ???
                 * Rotations must still be performed in X,Y,Z order to produce correct results
                 */

                if (Rotation.Z != 0.0)
                {
                    //Convert to radians
                    Rotation.Z *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 1, 0, 0, Rotation.Z);
                }


                if (Rotation.X != 0.0)
                {
                    //This is actually the Y-Axis rotation
                    //Convert to radians
                    Rotation.X *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 1, 0, Rotation.X);
                }
                if (Rotation.Y != 0.0)
                {
                    //This is actually the X-Axis rotation
                    //Convert to radians
                    Rotation.Y *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 0, 1, Rotation.Y);
                }


                //These files appear to only have one texture defined
                //Therefore import later- May have to change
                if (File.Exists(tday))
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].DaytimeTexture      = tday;
                        Builder.Materials[j].NighttimeTexture    = tnight;
                        Builder.Materials[j].TransparencyTexture = transtex;
                    }
                }
                if (TransparencyUsed == true)
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].TransparentColor     = FirstPxTransparent ? FirstPxColor : transparentColor;
                        Builder.Materials[j].TransparentColorUsed = true;
                    }
                }
            }
            ApplyMeshBuilder(ref Object, Builder, LoadMode, false, false);
            Object.Mesh.CreateNormals();
            return(Object);
        }
示例#4
0
            /// <summary>Call this method to update a single track follower</summary>
            /// <param name="NewTrackPosition">The new track position of the follower</param>
            /// <param name="UpdateWorldCoordinates">Whether to update the world co-ordinates</param>
            /// <param name="AddTrackInaccurary">Whether to add track innacuracy</param>
            internal void Update(double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary)
            {
                if (CurrentTrack.Elements.Length == 0)
                {
                    return;
                }
                int i = LastTrackElement;

                while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition)
                {
                    double ta = TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                    double tb = -0.01;
                    CheckEvents(i, -1, ta, tb);
                    i--;
                }
                if (i >= 0)
                {
                    while (i < CurrentTrack.Elements.Length - 1)
                    {
                        if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition)
                        {
                            break;
                        }
                        double ta = TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                        double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01;
                        CheckEvents(i, 1, ta, tb);
                        i++;
                    }
                }
                else
                {
                    i = 0;
                }
                double da = TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                double db = NewTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;

                // track
                if (UpdateWorldCoordinates)
                {
                    if (db != 0.0)
                    {
                        if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                        {
                            // curve
                            double  r = CurrentTrack.Elements[i].CurveRadius;
                            double  p = CurrentTrack.Elements[i].WorldDirection.Y / Math.Sqrt(CurrentTrack.Elements[i].WorldDirection.X * CurrentTrack.Elements[i].WorldDirection.X + CurrentTrack.Elements[i].WorldDirection.Z * CurrentTrack.Elements[i].WorldDirection.Z);
                            double  s = db / Math.Sqrt(1.0 + p * p);
                            double  h = s * p;
                            double  b = s / Math.Abs(r);
                            double  f = 2.0 * r * r * (1.0 - Math.Cos(b));
                            double  c = (double)Math.Sign(db) * Math.Sqrt(f >= 0.0 ? f : 0.0);
                            double  a = 0.5 * (double)Math.Sign(r) * b;
                            Vector3 D = new Vector3(CurrentTrack.Elements[i].WorldDirection.X, 0.0, CurrentTrack.Elements[i].WorldDirection.Z);
                            World.Normalize(ref D.X, ref D.Y, ref D.Z);
                            double cosa = Math.Cos(a);
                            double sina = Math.Sin(a);
                            World.Rotate(ref D, 0.0, 1.0, 0.0, cosa, sina);
                            WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X;
                            WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h;
                            WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z;
                            World.Rotate(ref D, 0.0, 1.0, 0.0, cosa, sina);
                            WorldDirection.X = D.X;
                            WorldDirection.Y = p;
                            WorldDirection.Z = D.Z;
                            World.Normalize(ref WorldDirection.X, ref WorldDirection.Y, ref WorldDirection.Z);
                            double cos2a = Math.Cos(2.0 * a);
                            double sin2a = Math.Sin(2.0 * a);
                            WorldSide = CurrentTrack.Elements[i].WorldSide;
                            World.Rotate(ref WorldSide, 0.0, 1.0, 0.0, cos2a, sin2a);
                            World.Cross(WorldDirection, WorldSide, out WorldUp);
                        }
                        else
                        {
                            // straight
                            WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X;
                            WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y;
                            WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z;
                            WorldDirection  = CurrentTrack.Elements[i].WorldDirection;
                            WorldUp         = CurrentTrack.Elements[i].WorldUp;
                            WorldSide       = CurrentTrack.Elements[i].WorldSide;
                            CurveRadius     = 0.0;
                        }

                        // cant
                        if (i < CurrentTrack.Elements.Length - 1)
                        {
                            double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                            if (t < 0.0)
                            {
                                t = 0.0;
                            }
                            else if (t > 1.0)
                            {
                                t = 1.0;
                            }
                            double t2 = t * t;
                            double t3 = t2 * t;
                            CurveCant =
                                (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                                (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                                (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                                (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                            CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                        }
                        else
                        {
                            CurveCant = CurrentTrack.Elements[i].CurveCant;
                        }
                    }
                    else
                    {
                        WorldPosition  = CurrentTrack.Elements[i].WorldPosition;
                        WorldDirection = CurrentTrack.Elements[i].WorldDirection;
                        WorldUp        = CurrentTrack.Elements[i].WorldUp;
                        WorldSide      = CurrentTrack.Elements[i].WorldSide;
                        CurveRadius    = CurrentTrack.Elements[i].CurveRadius;
                        CurveCant      = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                else
                {
                    if (db != 0.0)
                    {
                        if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                        {
                            CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                        }
                        else
                        {
                            CurveRadius = 0.0;
                        }
                        if (i < CurrentTrack.Elements.Length - 1)
                        {
                            double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                            if (t < 0.0)
                            {
                                t = 0.0;
                            }
                            else if (t > 1.0)
                            {
                                t = 1.0;
                            }
                            double t2 = t * t;
                            double t3 = t2 * t;
                            CurveCant =
                                (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                                (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                                (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                                (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                        }
                        else
                        {
                            CurveCant = CurrentTrack.Elements[i].CurveCant;
                        }
                    }
                    else
                    {
                        CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                        CurveCant   = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier;
                //Pitch added for Plugin Data usage
                //Mutliply this by 1000 to get the original value
                Pitch = CurrentTrack.Elements[i].Pitch * 1000;
                // inaccuracy
                if (AddTrackInaccurary)
                {
                    double x, y, c;
                    if (i < CurrentTrack.Elements.Length - 1)
                    {
                        double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                        if (t < 0.0)
                        {
                            t = 0.0;
                        }
                        else if (t > 1.0)
                        {
                            t = 1.0;
                        }
                        double x1, y1, c1;
                        double x2, y2, c2;
                        GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x1, out y1, out c1);
                        GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i + 1].CsvRwAccuracyLevel, out x2, out y2, out c2);
                        x = (1.0 - t) * x1 + t * x2;
                        y = (1.0 - t) * y1 + t * y2;
                        c = (1.0 - t) * c1 + t * c2;
                    }
                    else
                    {
                        GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x, out y, out c);
                    }
                    WorldPosition.X    += x * WorldSide.X + y * WorldUp.X;
                    WorldPosition.Y    += x * WorldSide.Y + y * WorldUp.Y;
                    WorldPosition.Z    += x * WorldSide.Z + y * WorldUp.Z;
                    CurveCant          += c;
                    CantDueToInaccuracy = c;
                }
                else
                {
                    CantDueToInaccuracy = 0.0;
                }
                // events
                CheckEvents(i, Math.Sign(db - da), da, db);
                //Update the odometer
                if (TrackPosition != NewTrackPosition)
                {
                    //HACK: Reset the odometer if we've moved more than 10m this frame
                    if (Math.Abs(NewTrackPosition - TrackPosition) > 10)
                    {
                        Odometer = 0;
                    }
                    else
                    {
                        Odometer += NewTrackPosition - TrackPosition;
                    }
                }
                // finish
                TrackPosition    = NewTrackPosition;
                LastTrackElement = i;
            }
示例#5
0
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            Program.MouseMovement();
            double   timeElapsed = CPreciseTimer.GetElapsedTime();
            DateTime time        = DateTime.Now;

            Game.SecondsSinceMidnight = (double)(3600 * time.Hour + 60 * time.Minute + time.Second) + 0.001 * (double)time.Millisecond;
            ObjectManager.UpdateAnimatedWorldObjects(timeElapsed, false);
            if (Program.ReducedMode)
            {
                System.Threading.Thread.Sleep(125);
            }
            else
            {
                System.Threading.Thread.Sleep(1);
            }
            bool updatelight = false;
            bool keep        = false;

            // rotate x
            if (Program.RotateX == 0)
            {
                double d = (1.0 + Math.Abs(RotateXSpeed)) * timeElapsed;
                if (RotateXSpeed >= -d & RotateXSpeed <= d)
                {
                    RotateXSpeed = 0.0;
                }
                else
                {
                    RotateXSpeed -= (double)Math.Sign(RotateXSpeed) * d;
                }
            }
            else
            {
                double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateXSpeed * RotateXSpeed)) * timeElapsed;
                double m = 1.0;
                RotateXSpeed += (double)Program.RotateX * d;
                if (RotateXSpeed < -m)
                {
                    RotateXSpeed = -m;
                }
                else if (RotateXSpeed > m)
                {
                    RotateXSpeed = m;
                }
            }
            if (RotateXSpeed != 0.0)
            {
                double cosa = Math.Cos(RotateXSpeed * timeElapsed);
                double sina = Math.Sin(RotateXSpeed * timeElapsed);
                World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, 0.0, 1.0, 0.0, cosa, sina);
                World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, 0.0, 1.0, 0.0, cosa, sina);
                World.Rotate(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z, 0.0, 1.0, 0.0, cosa, sina);
                keep = true;
            }
            // rotate y
            if (Program.RotateY == 0)
            {
                double d = (1.0 + Math.Abs(RotateYSpeed)) * timeElapsed;
                if (RotateYSpeed >= -d & RotateYSpeed <= d)
                {
                    RotateYSpeed = 0.0;
                }
                else
                {
                    RotateYSpeed -= (double)Math.Sign(RotateYSpeed) * d;
                }
            }
            else
            {
                double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateYSpeed * RotateYSpeed)) * timeElapsed;
                double m = 1.0;
                RotateYSpeed += (double)Program.RotateY * d;
                if (RotateYSpeed < -m)
                {
                    RotateYSpeed = -m;
                }
                else if (RotateYSpeed > m)
                {
                    RotateYSpeed = m;
                }
            }
            if (RotateYSpeed != 0.0)
            {
                double cosa = Math.Cos(RotateYSpeed * timeElapsed);
                double sina = Math.Sin(RotateYSpeed * timeElapsed);
                World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                keep = true;
            }
            // move x
            if (Program.MoveX == 0)
            {
                double d = (2.5 + Math.Abs(MoveXSpeed)) * timeElapsed;
                if (MoveXSpeed >= -d & MoveXSpeed <= d)
                {
                    MoveXSpeed = 0.0;
                }
                else
                {
                    MoveXSpeed -= (double)Math.Sign(MoveXSpeed) * d;
                }
            }
            else
            {
                double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveXSpeed * MoveXSpeed)) * timeElapsed;
                double m = 25.0;
                MoveXSpeed += (double)Program.MoveX * d;
                if (MoveXSpeed < -m)
                {
                    MoveXSpeed = -m;
                }
                else if (MoveXSpeed > m)
                {
                    MoveXSpeed = m;
                }
            }
            if (MoveXSpeed != 0.0)
            {
                World.AbsoluteCameraPosition.X += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.X;
                World.AbsoluteCameraPosition.Y += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Y;
                World.AbsoluteCameraPosition.Z += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Z;
                keep = true;
            }
            // move y
            if (Program.MoveY == 0)
            {
                double d = (2.5 + Math.Abs(MoveYSpeed)) * timeElapsed;
                if (MoveYSpeed >= -d & MoveYSpeed <= d)
                {
                    MoveYSpeed = 0.0;
                }
                else
                {
                    MoveYSpeed -= (double)Math.Sign(MoveYSpeed) * d;
                }
            }
            else
            {
                double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveYSpeed * MoveYSpeed)) * timeElapsed;
                double m = 25.0;
                MoveYSpeed += (double)Program.MoveY * d;
                if (MoveYSpeed < -m)
                {
                    MoveYSpeed = -m;
                }
                else if (MoveYSpeed > m)
                {
                    MoveYSpeed = m;
                }
            }
            if (MoveYSpeed != 0.0)
            {
                World.AbsoluteCameraPosition.X += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.X;
                World.AbsoluteCameraPosition.Y += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Y;
                World.AbsoluteCameraPosition.Z += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Z;
                keep = true;
            }
            // move z
            if (Program.MoveZ == 0)
            {
                double d = (2.5 + Math.Abs(MoveZSpeed)) * timeElapsed;
                if (MoveZSpeed >= -d & MoveZSpeed <= d)
                {
                    MoveZSpeed = 0.0;
                }
                else
                {
                    MoveZSpeed -= (double)Math.Sign(MoveZSpeed) * d;
                }
            }
            else
            {
                double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveZSpeed * MoveZSpeed)) * timeElapsed;
                double m = 25.0;
                MoveZSpeed += (double)Program.MoveZ * d;
                if (MoveZSpeed < -m)
                {
                    MoveZSpeed = -m;
                }
                else if (MoveZSpeed > m)
                {
                    MoveZSpeed = m;
                }
            }
            if (MoveZSpeed != 0.0)
            {
                World.AbsoluteCameraPosition.X += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.X;
                World.AbsoluteCameraPosition.Y += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Y;
                World.AbsoluteCameraPosition.Z += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Z;
                keep = true;
            }
            // lighting
            if (Program.LightingRelative == -1)
            {
                Program.LightingRelative = (double)Program.LightingTarget;
                updatelight = true;
            }
            if (Program.LightingTarget == 0)
            {
                if (Program.LightingRelative != 0.0)
                {
                    Program.LightingRelative -= 0.5 * timeElapsed;
                    if (Program.LightingRelative < 0.0)
                    {
                        Program.LightingRelative = 0.0;
                    }
                    updatelight = true;
                    keep        = true;
                }
            }
            else
            {
                if (Program.LightingRelative != 1.0)
                {
                    Program.LightingRelative += 0.5 * timeElapsed;
                    if (Program.LightingRelative > 1.0)
                    {
                        Program.LightingRelative = 1.0;
                    }
                    updatelight = true;
                    keep        = true;
                }
            }
            // continue
            if (Program.ReducedMode)
            {
                ReducedModeEnteringTime = 3.0;
            }
            else
            {
                if (keep)
                {
                    ReducedModeEnteringTime = 3.0;
                }
                else if (ReducedModeEnteringTime <= 0)
                {
                    Program.ReducedMode        = true;
                    World.AbsoluteCameraSide.Y = 0.0;
                    World.Normalize(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z);
                    World.Normalize(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z);
                    World.AbsoluteCameraUp = Vector3.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide);
                }
                else
                {
                    ReducedModeEnteringTime -= timeElapsed;
                }
            }
            if (updatelight)
            {
                Renderer.OptionAmbientColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative * (2.0 - Program.LightingRelative));
                Renderer.OptionAmbientColor.G = (byte)Math.Round(32.0 + 128.0 * 0.5 * (Program.LightingRelative + Program.LightingRelative * (2.0 - Program.LightingRelative)));
                Renderer.OptionAmbientColor.B = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Renderer.OptionDiffuseColor.R = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Renderer.OptionDiffuseColor.G = (byte)Math.Round(32.0 + 128.0 * Program.LightingRelative);
                Renderer.OptionDiffuseColor.B = (byte)Math.Round(32.0 + 128.0 * Math.Sqrt(Program.LightingRelative));
                Renderer.InitializeLighting();
            }
            Renderer.RenderScene();
            SwapBuffers();
        }
示例#6
0
        internal static void UpdateTrackFollower(ref TrackFollower Follower, double NewTrackPosition, bool UpdateWorldCoordinates, bool AddTrackInaccurary)
        {
            if (CurrentTrack.Elements.Length == 0)
            {
                return;
            }
            int i = Follower.LastTrackElement;

            while (i >= 0 && NewTrackPosition < CurrentTrack.Elements[i].StartingTrackPosition)
            {
                double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                double tb = -0.01;
                CheckEvents(ref Follower, i, -1, ta, tb);
                i--;
            }
            if (i >= 0)
            {
                while (i < CurrentTrack.Elements.Length - 1)
                {
                    if (NewTrackPosition < CurrentTrack.Elements[i + 1].StartingTrackPosition)
                    {
                        break;
                    }
                    double ta = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
                    double tb = CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition + 0.01;
                    CheckEvents(ref Follower, i, 1, ta, tb);
                    i++;
                }
            }
            else
            {
                i = 0;
            }
            double da = Follower.TrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;
            double db = NewTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition;

            // track
            if (UpdateWorldCoordinates)
            {
                if (db != 0.0)
                {
                    if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                    {
                        // curve
                        double  r = CurrentTrack.Elements[i].CurveRadius;
                        double  p = CurrentTrack.Elements[i].WorldDirection.Y / Math.Sqrt(CurrentTrack.Elements[i].WorldDirection.X * CurrentTrack.Elements[i].WorldDirection.X + CurrentTrack.Elements[i].WorldDirection.Z * CurrentTrack.Elements[i].WorldDirection.Z);
                        double  s = db / Math.Sqrt(1.0 + p * p);
                        double  h = s * p;
                        double  b = s / Math.Abs(r);
                        double  f = 2.0 * r * r * (1.0 - Math.Cos(b));
                        double  c = (double)Math.Sign(db) * Math.Sqrt(f >= 0.0 ? f : 0.0);
                        double  a = 0.5 * (double)Math.Sign(r) * b;
                        Vector3 D = new Vector3(CurrentTrack.Elements[i].WorldDirection.X, 0.0, CurrentTrack.Elements[i].WorldDirection.Z);
                        World.Normalize(ref D.X, ref D.Y, ref D.Z);
                        double cosa = Math.Cos(a);
                        double sina = Math.Sin(a);
                        World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                        Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + c * D.X;
                        Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + h;
                        Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + c * D.Z;
                        World.Rotate(ref D.X, ref D.Y, ref D.Z, 0.0, 1.0, 0.0, cosa, sina);
                        Follower.WorldDirection.X = D.X;
                        Follower.WorldDirection.Y = p;
                        Follower.WorldDirection.Z = D.Z;
                        World.Normalize(ref Follower.WorldDirection.X, ref Follower.WorldDirection.Y, ref Follower.WorldDirection.Z);
                        double cos2a = Math.Cos(2.0 * a);
                        double sin2a = Math.Sin(2.0 * a);
                        Follower.WorldSide = CurrentTrack.Elements[i].WorldSide;
                        World.Rotate(ref Follower.WorldSide.X, ref Follower.WorldSide.Y, ref Follower.WorldSide.Z, 0.0, 1.0, 0.0, cos2a, sin2a);
                        Follower.WorldUp     = Vector3.Cross(Follower.WorldDirection, Follower.WorldSide);
                        Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    }
                    else
                    {
                        // straight
                        Follower.WorldPosition.X = CurrentTrack.Elements[i].WorldPosition.X + db * CurrentTrack.Elements[i].WorldDirection.X;
                        Follower.WorldPosition.Y = CurrentTrack.Elements[i].WorldPosition.Y + db * CurrentTrack.Elements[i].WorldDirection.Y;
                        Follower.WorldPosition.Z = CurrentTrack.Elements[i].WorldPosition.Z + db * CurrentTrack.Elements[i].WorldDirection.Z;
                        Follower.WorldDirection  = CurrentTrack.Elements[i].WorldDirection;
                        Follower.WorldUp         = CurrentTrack.Elements[i].WorldUp;
                        Follower.WorldSide       = CurrentTrack.Elements[i].WorldSide;
                        Follower.CurveRadius     = 0.0;
                    }
                    // cant
                    if (i < CurrentTrack.Elements.Length - 1)
                    {
                        double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                        if (t < 0.0)
                        {
                            t = 0.0;
                        }
                        else if (t > 1.0)
                        {
                            t = 1.0;
                        }
                        double t2 = t * t;
                        double t3 = t2 * t;
                        Follower.CurveCant =
                            (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                            (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                            (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                            (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                    }
                    else
                    {
                        Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                else
                {
                    Follower.WorldPosition  = CurrentTrack.Elements[i].WorldPosition;
                    Follower.WorldDirection = CurrentTrack.Elements[i].WorldDirection;
                    Follower.WorldUp        = CurrentTrack.Elements[i].WorldUp;
                    Follower.WorldSide      = CurrentTrack.Elements[i].WorldSide;
                    Follower.CurveRadius    = CurrentTrack.Elements[i].CurveRadius;
                    Follower.CurveCant      = CurrentTrack.Elements[i].CurveCant;
                }
            }
            else
            {
                if (db != 0.0)
                {
                    if (CurrentTrack.Elements[i].CurveRadius != 0.0)
                    {
                        Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    }
                    else
                    {
                        Follower.CurveRadius = 0.0;
                    }
                    if (i < CurrentTrack.Elements.Length - 1)
                    {
                        double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                        if (t < 0.0)
                        {
                            t = 0.0;
                        }
                        else if (t > 1.0)
                        {
                            t = 1.0;
                        }
                        double t2 = t * t;
                        double t3 = t2 * t;
                        Follower.CurveCant =
                            (2.0 * t3 - 3.0 * t2 + 1.0) * CurrentTrack.Elements[i].CurveCant +
                            (t3 - 2.0 * t2 + t) * CurrentTrack.Elements[i].CurveCantTangent +
                            (-2.0 * t3 + 3.0 * t2) * CurrentTrack.Elements[i + 1].CurveCant +
                            (t3 - t2) * CurrentTrack.Elements[i + 1].CurveCantTangent;
                    }
                    else
                    {
                        Follower.CurveCant = CurrentTrack.Elements[i].CurveCant;
                    }
                }
                else
                {
                    Follower.CurveRadius = CurrentTrack.Elements[i].CurveRadius;
                    Follower.CurveCant   = CurrentTrack.Elements[i].CurveCant;
                }
            }
            Follower.AdhesionMultiplier = CurrentTrack.Elements[i].AdhesionMultiplier;
            // inaccuracy
            if (AddTrackInaccurary)
            {
                double x, y, c;
                if (i < CurrentTrack.Elements.Length - 1)
                {
                    double t = db / (CurrentTrack.Elements[i + 1].StartingTrackPosition - CurrentTrack.Elements[i].StartingTrackPosition);
                    if (t < 0.0)
                    {
                        t = 0.0;
                    }
                    else if (t > 1.0)
                    {
                        t = 1.0;
                    }
                    double x1, y1, c1;
                    double x2, y2, c2;
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x1, out y1, out c1);
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i + 1].CsvRwAccuracyLevel, out x2, out y2, out c2);
                    x = (1.0 - t) * x1 + t * x2;
                    y = (1.0 - t) * y1 + t * y2;
                    c = (1.0 - t) * c1 + t * c2;
                }
                else
                {
                    GetInaccuracies(NewTrackPosition, CurrentTrack.Elements[i].CsvRwAccuracyLevel, out x, out y, out c);
                }
                Follower.WorldPosition.X    += x * Follower.WorldSide.X + y * Follower.WorldUp.X;
                Follower.WorldPosition.Y    += x * Follower.WorldSide.Y + y * Follower.WorldUp.Y;
                Follower.WorldPosition.Z    += x * Follower.WorldSide.Z + y * Follower.WorldUp.Z;
                Follower.CurveCant          += c;
                Follower.CantDueToInaccuracy = c;
            }
            else
            {
                Follower.CantDueToInaccuracy = 0.0;
            }
            // events
            CheckEvents(ref Follower, i, Math.Sign(db - da), da, db);
            // finish
            Follower.TrackPosition    = NewTrackPosition;
            Follower.LastTrackElement = i;
        }
示例#7
0
        internal static void Main(string[] args)
        {
            // platform and mono
            int p = (int)Environment.OSVersion.Platform;

            if (p == 4 | p == 128)
            {
                // general Unix
                CurrentPlatform = Platform.Linux;
            }
            else if (p == 6)
            {
                // Mac
                CurrentPlatform = Platform.Mac;
            }
            else
            {
                // non-Unix
                CurrentPlatform = Platform.Windows;
            }
            CurrentlyRunOnMono = Type.GetType("Mono.Runtime") != null;
            // file system
            FileSystem = FileSystem.FromCommandLineArgs(args);
            FileSystem.CreateFileSystem();
            SetPackageLookupDirectories();
            // command line arguments
            bool[] SkipArgs = new bool[args.Length];
            if (args.Length != 0)
            {
                string File = System.IO.Path.Combine(Application.StartupPath, "RouteViewer.exe");
                if (System.IO.File.Exists(File))
                {
                    int Skips = 0;
                    System.Text.StringBuilder NewArgs = new System.Text.StringBuilder();
                    for (int i = 0; i < args.Length; i++)
                    {
                        if (System.IO.File.Exists(args[i]))
                        {
                            if (System.IO.Path.GetExtension(args[i]).Equals(".csv", StringComparison.OrdinalIgnoreCase))
                            {
                                string Text = System.IO.File.ReadAllText(args[i], System.Text.Encoding.UTF8);
                                if (Text.Length != -1 && Text.IndexOf("CreateMeshBuilder", StringComparison.OrdinalIgnoreCase) == -1)
                                {
                                    if (NewArgs.Length != 0)
                                    {
                                        NewArgs.Append(" ");
                                    }
                                    NewArgs.Append("\"" + args[i] + "\"");
                                    SkipArgs[i] = true;
                                    Skips++;
                                }
                            }
                        }
                        else
                        {
                            SkipArgs[i] = true;
                            Skips++;
                        }
                    }
                    if (NewArgs.Length != 0)
                    {
                        System.Diagnostics.Process.Start(File, NewArgs.ToString());
                    }
                    if (Skips == args.Length)
                    {
                        return;
                    }
                }
            }
            // application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0)
            {
                MessageBox.Show("SDL failed to initialize the video subsystem.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return;
            }
            Interface.CurrentOptions.ObjectOptimizationBasicThreshold = 1000;
            Interface.CurrentOptions.ObjectOptimizationFullThreshold  = 250;
            // initialize sdl window
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DEPTH_SIZE, 16);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 8);
            SDL.SDL_ShowCursor(1);
            // initialize camera
            ResetCamera();
            // create window
            Renderer.ScreenWidth  = 960;
            Renderer.ScreenHeight = 600;
            // int Bits = 32;
            //Sdl.SDL_SetVideoMode(Renderer.ScreenWidth, Renderer.ScreenHeight, Bits, Sdl.SDL_OPENGL | Sdl.SDL_DOUBLEBUF);
            SDLWindow = SDL.SDL_CreateWindow(Application.ProductName,
                                             SDL.SDL_WINDOWPOS_UNDEFINED, SDL.SDL_WINDOWPOS_UNDEFINED,
                                             Renderer.ScreenWidth, Renderer.ScreenHeight,
                                             SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE);
            if (SDLWindow != IntPtr.Zero)
            {
                // create window
                string File = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder(), "icon.png");
                if (System.IO.File.Exists(File))
                {
                    // set up icon
                    iconBmp  = new Bitmap(File);                    // load file
                    iconData = iconBmp.LockBits(new Rectangle(0, 0, iconBmp.Width, iconBmp.Height),
                                                System.Drawing.Imaging.ImageLockMode.ReadOnly,
                                                System.Drawing.Imaging.PixelFormat.Format32bppArgb);            // lock data
                    iconSurface = SDL.SDL_CreateRGBSurfaceFrom(iconData.Scan0, iconBmp.Width, iconBmp.Height, 32, iconData.Stride,
                                                               0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); // upload to sdl
                    SDL.SDL_SetWindowIcon(SDLWindow, iconSurface);                                              // use icon
                    // free is on the end of the program

                    /*
                     * IntPtr bitmap = SDL.SDL_LoadBMP(File);
                     * if (bitmap != IntPtr.Zero) {
                     *      SDL.SDL_Surface Surface = (SDL.SDL_Surface)System.Runtime.InteropServices.Marshal.PtrToStructure(bitmap, typeof(SDL.SDL_Surface));
                     *      uint ColorKey = SDL.SDL_MapRGB(Surface.format, 0, 0, 255);
                     *      SDL.SDL_SetColorKey(bitmap, 1, ColorKey);
                     *      SDL.SDL_SetWindowIcon(SDLWindow,bitmap);
                     * }
                     */
                }
                GLContext = SDL.SDL_GL_CreateContext(SDLWindow);
                tkContext = new GraphicsContext(new ContextHandle(GLContext),
                                                SDL.SDL_GL_GetProcAddress,
                                                () => new ContextHandle(SDL.SDL_GL_GetCurrentContext()));
                // anisotropic filtering
                string[] extensions = GL.GetString(StringName.Extensions).Split(new [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                Interface.CurrentOptions.AnisotropicFilteringMaximum = 0;
                for (int i = 0; i < extensions.Length; i++)
                {
                    if (extensions[i] == "GL_EXT_texture_filter_anisotropic")
                    {
                        float n;
                        GL.GetFloat((GetPName)ExtTextureFilterAnisotropic.MaxTextureMaxAnisotropyExt, out n);
                        Interface.CurrentOptions.AnisotropicFilteringMaximum = (int)Math.Round((double)n);
                        break;
                    }
                }
                if (Interface.CurrentOptions.AnisotropicFilteringMaximum <= 0)
                {
                    Interface.CurrentOptions.AnisotropicFilteringMaximum = 0;
                    Interface.CurrentOptions.AnisotropicFilteringLevel   = 0;
                    Interface.CurrentOptions.Interpolation = TextureManager.InterpolationMode.AnisotropicFiltering;
                }
                else
                {
                    Interface.CurrentOptions.AnisotropicFilteringLevel = Interface.CurrentOptions.AnisotropicFilteringMaximum;
                    Interface.CurrentOptions.Interpolation             = TextureManager.InterpolationMode.TrilinearMipmapped;
                }
                // module initialization
                Renderer.Initialize();
                Renderer.InitializeLighting();
                SDL.SDL_GL_SwapWindow(SDLWindow);
                Fonts.Initialize();
                UpdateViewport();
                // command line arguments
                for (int i = 0; i < args.Length; i++)
                {
                    if (!SkipArgs[i] && System.IO.File.Exists(args[i]))
                    {
                        try {
                            ObjectManager.UnifiedObject o = ObjectManager.LoadObject(args[i], System.Text.Encoding.UTF8, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                            ObjectManager.CreateObject(o, new World.Vector3D(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), new World.Transformation(0.0, 0.0, 0.0), true, 0.0, 0.0, 25.0, 0.0);
                        } catch (Exception ex) {
                            Interface.AddMessage(Interface.MessageType.Critical, false, "Unhandled error (" + ex.Message + ") encountered while processing the file " + args[i] + ".");
                        }
                        Array.Resize <string>(ref Files, Files.Length + 1);
                        Files[Files.Length - 1] = args[i];
                    }
                }
                ObjectManager.InitializeVisibility();
                ObjectManager.FinishCreatingObjects();
                ObjectManager.UpdateVisibility(0.0, true);
                ObjectManager.UpdateAnimatedWorldObjects(0.01, true);
                UpdateCaption();
                Stopwatch timer = new Stopwatch();
                timer.Start();
                LastTicks = timer.ElapsedMilliseconds;
                // loop
                while (!Quit)
                {
                    long   ticks       = timer.ElapsedMilliseconds;
                    double timeElapsed = 0.001 * (double)(ticks - LastTicks);
                    if (timeElapsed < 0.0001)
                    {
                        timeElapsed = 0.0001;
                    }
                    LastTicks = ticks;
                    DateTime time = DateTime.Now;
                    Game.SecondsSinceMidnight = (double)(3600 * time.Hour + 60 * time.Minute + time.Second) + 0.001 * (double)time.Millisecond;
                    ObjectManager.UpdateAnimatedWorldObjects(timeElapsed, false);
                    ProcessEvents();
                    if (ReducedMode)
                    {
                        System.Threading.Thread.Sleep(125);
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(1);
                    }
                    bool updatelight = false;
                    bool keep        = false;
                    // rotate x
                    if (RotateX == 0)
                    {
                        double d = (1.0 + Math.Abs(RotateXSpeed)) * timeElapsed;
                        if (RotateXSpeed >= -d & RotateXSpeed <= d)
                        {
                            RotateXSpeed = 0.0;
                        }
                        else
                        {
                            RotateXSpeed -= (double)Math.Sign(RotateXSpeed) * d;
                        }
                    }
                    else
                    {
                        double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateXSpeed * RotateXSpeed)) * timeElapsed;
                        double m = 1.0;
                        RotateXSpeed += (double)RotateX * d;
                        if (RotateXSpeed < -m)
                        {
                            RotateXSpeed = -m;
                        }
                        else if (RotateXSpeed > m)
                        {
                            RotateXSpeed = m;
                        }
                    }
                    if (RotateXSpeed != 0.0)
                    {
                        double cosa = Math.Cos(RotateXSpeed * timeElapsed);
                        double sina = Math.Sin(RotateXSpeed * timeElapsed);
                        World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, 0.0, 1.0, 0.0, cosa, sina);
                        World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, 0.0, 1.0, 0.0, cosa, sina);
                        World.Rotate(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z, 0.0, 1.0, 0.0, cosa, sina);
                        keep = true;
                    }
                    // rotate y
                    if (RotateY == 0)
                    {
                        double d = (1.0 + Math.Abs(RotateYSpeed)) * timeElapsed;
                        if (RotateYSpeed >= -d & RotateYSpeed <= d)
                        {
                            RotateYSpeed = 0.0;
                        }
                        else
                        {
                            RotateYSpeed -= (double)Math.Sign(RotateYSpeed) * d;
                        }
                    }
                    else
                    {
                        double d = (1.0 + 1.0 - 1.0 / (1.0 + RotateYSpeed * RotateYSpeed)) * timeElapsed;
                        double m = 1.0;
                        RotateYSpeed += (double)RotateY * d;
                        if (RotateYSpeed < -m)
                        {
                            RotateYSpeed = -m;
                        }
                        else if (RotateYSpeed > m)
                        {
                            RotateYSpeed = m;
                        }
                    }
                    if (RotateYSpeed != 0.0)
                    {
                        double cosa = Math.Cos(RotateYSpeed * timeElapsed);
                        double sina = Math.Sin(RotateYSpeed * timeElapsed);
                        World.Rotate(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                        World.Rotate(ref World.AbsoluteCameraUp.X, ref World.AbsoluteCameraUp.Y, ref World.AbsoluteCameraUp.Z, World.AbsoluteCameraSide.X, World.AbsoluteCameraSide.Y, World.AbsoluteCameraSide.Z, cosa, sina);
                        keep = true;
                    }
                    // move x
                    if (MoveX == 0)
                    {
                        double d = (2.5 + Math.Abs(MoveXSpeed)) * timeElapsed;
                        if (MoveXSpeed >= -d & MoveXSpeed <= d)
                        {
                            MoveXSpeed = 0.0;
                        }
                        else
                        {
                            MoveXSpeed -= (double)Math.Sign(MoveXSpeed) * d;
                        }
                    }
                    else
                    {
                        double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveXSpeed * MoveXSpeed)) * timeElapsed;
                        double m = 25.0;
                        MoveXSpeed += (double)MoveX * d;
                        if (MoveXSpeed < -m)
                        {
                            MoveXSpeed = -m;
                        }
                        else if (MoveXSpeed > m)
                        {
                            MoveXSpeed = m;
                        }
                    }
                    if (MoveXSpeed != 0.0)
                    {
                        World.AbsoluteCameraPosition.X += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.X;
                        World.AbsoluteCameraPosition.Y += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Y;
                        World.AbsoluteCameraPosition.Z += MoveXSpeed * timeElapsed * World.AbsoluteCameraSide.Z;
                        keep = true;
                    }
                    // move y
                    if (MoveY == 0)
                    {
                        double d = (2.5 + Math.Abs(MoveYSpeed)) * timeElapsed;
                        if (MoveYSpeed >= -d & MoveYSpeed <= d)
                        {
                            MoveYSpeed = 0.0;
                        }
                        else
                        {
                            MoveYSpeed -= (double)Math.Sign(MoveYSpeed) * d;
                        }
                    }
                    else
                    {
                        double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveYSpeed * MoveYSpeed)) * timeElapsed;
                        double m = 25.0;
                        MoveYSpeed += (double)MoveY * d;
                        if (MoveYSpeed < -m)
                        {
                            MoveYSpeed = -m;
                        }
                        else if (MoveYSpeed > m)
                        {
                            MoveYSpeed = m;
                        }
                    }
                    if (MoveYSpeed != 0.0)
                    {
                        World.AbsoluteCameraPosition.X += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.X;
                        World.AbsoluteCameraPosition.Y += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Y;
                        World.AbsoluteCameraPosition.Z += MoveYSpeed * timeElapsed * World.AbsoluteCameraUp.Z;
                        keep = true;
                    }
                    // move z
                    if (MoveZ == 0)
                    {
                        double d = (2.5 + Math.Abs(MoveZSpeed)) * timeElapsed;
                        if (MoveZSpeed >= -d & MoveZSpeed <= d)
                        {
                            MoveZSpeed = 0.0;
                        }
                        else
                        {
                            MoveZSpeed -= (double)Math.Sign(MoveZSpeed) * d;
                        }
                    }
                    else
                    {
                        double d = (5.0 + 10.0 - 10.0 / (1.0 + MoveZSpeed * MoveZSpeed)) * timeElapsed;
                        double m = 25.0;
                        MoveZSpeed += (double)MoveZ * d;
                        if (MoveZSpeed < -m)
                        {
                            MoveZSpeed = -m;
                        }
                        else if (MoveZSpeed > m)
                        {
                            MoveZSpeed = m;
                        }
                    }
                    if (MoveZSpeed != 0.0)
                    {
                        World.AbsoluteCameraPosition.X += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.X;
                        World.AbsoluteCameraPosition.Y += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Y;
                        World.AbsoluteCameraPosition.Z += MoveZSpeed * timeElapsed * World.AbsoluteCameraDirection.Z;
                        keep = true;
                    }
                    // lighting
                    if (LightingRelative == -1)
                    {
                        LightingRelative = (double)LightingTarget;
                        updatelight      = true;
                    }
                    if (LightingTarget == 0)
                    {
                        if (LightingRelative != 0.0)
                        {
                            LightingRelative -= 0.5 * timeElapsed;
                            if (LightingRelative < 0.0)
                            {
                                LightingRelative = 0.0;
                            }
                            updatelight = true;
                            keep        = true;
                        }
                    }
                    else
                    {
                        if (LightingRelative != 1.0)
                        {
                            LightingRelative += 0.5 * timeElapsed;
                            if (LightingRelative > 1.0)
                            {
                                LightingRelative = 1.0;
                            }
                            updatelight = true;
                            keep        = true;
                        }
                    }
                    // continue
                    if (ReducedMode)
                    {
                        ReducedModeEnteringTime = (int)(ticks + 3000);
                    }
                    else
                    {
                        if (keep)
                        {
                            ReducedModeEnteringTime = (int)(ticks + 3000);
                        }
                        else if (ticks > ReducedModeEnteringTime)
                        {
                            ReducedMode = true;
                            World.AbsoluteCameraSide.Y = 0.0;
                            World.Normalize(ref World.AbsoluteCameraSide.X, ref World.AbsoluteCameraSide.Y, ref World.AbsoluteCameraSide.Z);
                            World.Normalize(ref World.AbsoluteCameraDirection.X, ref World.AbsoluteCameraDirection.Y, ref World.AbsoluteCameraDirection.Z);
                            World.AbsoluteCameraUp = World.Cross(World.AbsoluteCameraDirection, World.AbsoluteCameraSide);
                        }
                    }
                    if (updatelight)
                    {
                        Renderer.OptionAmbientColor.R = (byte)Math.Round(32.0 + 128.0 * LightingRelative * (2.0 - LightingRelative));
                        Renderer.OptionAmbientColor.G = (byte)Math.Round(32.0 + 128.0 * 0.5 * (LightingRelative + LightingRelative * (2.0 - LightingRelative)));
                        Renderer.OptionAmbientColor.B = (byte)Math.Round(32.0 + 128.0 * LightingRelative);
                        Renderer.OptionDiffuseColor.R = (byte)Math.Round(32.0 + 128.0 * LightingRelative);
                        Renderer.OptionDiffuseColor.G = (byte)Math.Round(32.0 + 128.0 * LightingRelative);
                        Renderer.OptionDiffuseColor.B = (byte)Math.Round(32.0 + 128.0 * Math.Sqrt(LightingRelative));
                        Renderer.InitializeLighting();
                    }
                    Renderer.RenderScene();
                    SDL.SDL_GL_SwapWindow(SDLWindow);
                }
                // quit
                TextureManager.UnuseAllTextures();
                if (iconSurface != IntPtr.Zero)
                {
                    SDL.SDL_FreeSurface(iconSurface);                     // free surface
                }
                if (iconBmp != null && iconData != null)
                {
                    iconBmp.UnlockBits(iconData);                     // free pixels
                    iconBmp.Dispose();
                }
                SDL.SDL_GL_DeleteContext(GLContext);
                SDL.SDL_DestroyWindow(SDLWindow);
                SDL.SDL_Quit();
            }
            else
            {
                MessageBox.Show("SDL failed to create the window.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }
示例#8
0
        // read object
        /// <summary>Loads a Loksim3D 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. If the file uses a byte order mark, the encoding indicated by the byte order mark is used and the Encoding parameter is ignored.</param>
        /// <param name="LoadMode">The texture load mode.</param>
        /// <param name="ForceTextureRepeatX">Whether to force TextureWrapMode.Repeat for the X-axis</param>
        /// /// <param name="ForceTextureRepeatY">Whether to force TextureWrapMode.Repeat for the Y-axis</param>
        /// <returns>The object loaded.</returns>
        internal static ObjectManager.StaticObject ReadObject(string FileName, System.Text.Encoding Encoding, ObjectManager.ObjectLoadMode LoadMode, bool ForceTextureRepeatX, bool ForceTextureRepeatY, double RotationX, double RotationY, double RotationZ)
        {
            XmlDocument currentXML = new XmlDocument();

            //May need to be changed to use de-DE
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            //Initialise the object
            ObjectManager.StaticObject Object = new ObjectManager.StaticObject();
            Object.Mesh.Faces     = new World.MeshFace[] { };
            Object.Mesh.Materials = new World.MeshMaterial[] { };
            Object.Mesh.Vertices  = new World.Vertex[] { };
            MeshBuilder Builder = new MeshBuilder();

            World.Vector3Df[] Normals = new World.Vector3Df[4];
            bool PropertiesFound      = false;

            World.Vertex[]    tempVertices     = new World.Vertex[0];
            World.Vector3Df[] tempNormals      = new World.Vector3Df[0];
            World.ColorRGB    transparentColor = new World.ColorRGB();
            string            tday             = null;
            string            tnight           = null;
            bool TransparencyUsed = false;
            bool Face2            = false;
            int  TextureWidth     = 0;
            int  TextureHeight    = 0;

            if (File.Exists(FileName))
            {
                currentXML.Load(FileName);
            }
            else
            {
                return(null);
            }
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/OBJECT");
                //Check this file actually contains Loksim3D object nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode outerNode in DocumentNodes)
                    {
                        if (outerNode.HasChildNodes)
                        {
                            foreach (XmlNode node in outerNode.ChildNodes)
                            {
                                //I think there should only be one properties node??
                                //Need better format documentation
                                if (node.Name == "Props" && PropertiesFound == false)
                                {
                                    if (node.Attributes != null)
                                    {
                                        //Our node has child nodes, therefore this properties node should be valid
                                        //Needs better validation
                                        PropertiesFound = true;
                                        foreach (XmlAttribute attribute in node.Attributes)
                                        {
                                            switch (attribute.Name)
                                            {
                                            //Sets the texture
                                            //Loksim3D objects only support daytime textures
                                            case "Texture":
                                                tday = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), attribute.Value);
                                                if (File.Exists(tday))
                                                {
                                                    try
                                                    {
                                                        using (Bitmap TextureInformation = new Bitmap(tday))
                                                        {
                                                            TextureWidth  = TextureInformation.Width;
                                                            TextureHeight = TextureInformation.Height;
                                                            Color color = TextureInformation.GetPixel(1, 1);
                                                            transparentColor = new World.ColorRGB((byte)color.R, (byte)color.G, (byte)color.B);
                                                        }
                                                    }
                                                    catch
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, true, "An error occured loading daytime texture " + tday + " in file " + FileName);
                                                        tday = null;
                                                    }
                                                }
                                                else
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, true, "DaytimeTexture " + tday + " could not be found in file " + FileName);
                                                }
                                                break;

                                            //Defines whether the texture uses transparency
                                            //May be omitted
                                            case "Transparent":
                                                if (attribute.Value == "TRUE")
                                                {
                                                    TransparencyUsed = true;
                                                }
                                                else
                                                {
                                                    TransparencyUsed = false;
                                                }
                                                break;

                                            //Sets the transparency type
                                            case "TransparentTyp":
                                                switch (attribute.Value)
                                                {
                                                case "0":
                                                    //Transparency is disabled
                                                    TransparencyUsed = false;
                                                    break;

                                                case "1":
                                                    //Transparency is solid black
                                                    TransparencyUsed = true;
                                                    transparentColor = new World.ColorRGB(0, 0, 0);
                                                    break;

                                                case "2":
                                                    //Transparency is the color at Pixel 1,1
                                                    TransparencyUsed = true;
                                                    break;

                                                case "3":
                                                    //This is used when transparency is used with an alpha bitmap
                                                    //Not currently supported
                                                    TransparencyUsed = false;
                                                    break;
                                                }
                                                break;

                                            //Sets whether the rears of the faces are to be drawn
                                            case "Drawrueckseiten":
                                                Face2 = true;
                                                break;

                                                /*
                                                 * MISSING PROPERTIES:
                                                 * AutoRotate - Rotate with tracks?? LS3D presumably uses a 3D world system.
                                                 * Beleuchtet- Translates as illuminated. Presume something to do with lighting? - What emissive color?
                                                 * FileAuthor
                                                 * FileInfo
                                                 * FilePicture
                                                 */
                                            }
                                        }
                                    }
                                }
                                //The point command is eqivilant to a vertex
                                else if (node.Name == "Point" && node.HasChildNodes)
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Vertex
                                            double vx = 0.0, vy = 0.0, vz = 0.0;
                                            //Normals
                                            double nx = 0.0, ny = 0.0, nz = 0.0;
                                            foreach (XmlAttribute attribute in childNode.Attributes)
                                            {
                                                switch (attribute.Name)
                                                {
                                                //Sets the vertex normals
                                                case "Normal":
                                                    string[] NormalPoints = attribute.Value.Split(';');
                                                    double.TryParse(NormalPoints[0], out nx);
                                                    double.TryParse(NormalPoints[1], out ny);
                                                    double.TryParse(NormalPoints[2], out nz);
                                                    break;

                                                //Sets the vertex 3D co-ordinates
                                                case "Vekt":
                                                    string[] VertexPoints = attribute.Value.Split(';');
                                                    double.TryParse(VertexPoints[0], out vx);
                                                    double.TryParse(VertexPoints[1], out vy);
                                                    double.TryParse(VertexPoints[2], out vz);
                                                    break;
                                                }
                                            }
                                            World.Normalize(ref nx, ref ny, ref nz);

                                            {
                                                //Resize temp arrays
                                                Array.Resize <World.Vertex>(ref tempVertices, tempVertices.Length + 1);
                                                Array.Resize <World.Vector3Df>(ref tempNormals, tempNormals.Length + 1);
                                                //Add vertex and normals to temp array
                                                tempVertices[tempVertices.Length - 1].Coordinates = new World.Vector3D(vx, vy, vz);
                                                tempNormals[tempNormals.Length - 1] = new World.Vector3Df((float)nx, (float)ny, (float)nz);
                                            }

                                            Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                            while (Builder.Vertices.Length >= Normals.Length)
                                            {
                                                Array.Resize <World.Vector3Df>(ref Normals, Normals.Length << 1);
                                            }
                                            Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = new World.Vector3D(vx, vy, vz);
                                            Normals[Builder.Vertices.Length - 1] = new World.Vector3Df((float)nx, (float)ny, (float)nz);
                                        }
                                    }
                                }
                                //The Flaeche command creates a face
                                else if (node.Name == "Flaeche" && node.HasChildNodes)
                                {
                                    foreach (XmlNode childNode in node.ChildNodes)
                                    {
                                        if (childNode.Name == "Props" && childNode.Attributes != null)
                                        {
                                            //Defines the verticies in this face
                                            //**NOTE**: A vertex may appear in multiple faces with different texture co-ordinates
                                            if (childNode.Attributes["Points"] != null)
                                            {
                                                string[] Verticies = childNode.Attributes["Points"].Value.Split(';');
                                                int      f         = Builder.Faces.Length;
                                                //Add 1 to the length of the face array
                                                Array.Resize <World.MeshFace>(ref Builder.Faces, f + 1);
                                                Builder.Faces[f] = new World.MeshFace();
                                                //Create the vertex array for the face
                                                Builder.Faces[f].Vertices = new World.MeshFaceVertex[Verticies.Length];
                                                while (Builder.Vertices.Length > Normals.Length)
                                                {
                                                    Array.Resize <World.Vector3Df>(ref Normals,
                                                                                   Normals.Length << 1);
                                                }
                                                //Run through the vertices list and grab from the temp array
                                                for (int j = 0; j < Verticies.Length; j++)
                                                {
                                                    //This is the position of the vertex in the temp array
                                                    int currentVertex;
                                                    int.TryParse(Verticies[j], out currentVertex);
                                                    //Add one to the actual vertex array
                                                    Array.Resize <World.Vertex>(ref Builder.Vertices, Builder.Vertices.Length + 1);
                                                    //Set coordinates
                                                    Builder.Vertices[Builder.Vertices.Length - 1].Coordinates = tempVertices[currentVertex].Coordinates;
                                                    //Set the vertex index
                                                    Builder.Faces[f].Vertices[j].Index = (ushort)(Builder.Vertices.Length - 1);
                                                    //Set the normals
                                                    Builder.Faces[f].Vertices[j].Normal = tempNormals[currentVertex];
                                                    //Now deal with the texture
                                                    //Texture mapping points are in pixels X,Y and are relative to the face in question rather than the vertex
                                                    if (childNode.Attributes["Texture"] != null)
                                                    {
                                                        string[]        TextureCoords = childNode.Attributes["Texture"].Value.Split(';');
                                                        World.Vector2Df currentCoords;
                                                        float           OpenBVEWidth;
                                                        float           OpenBVEHeight;
                                                        string[]        splitCoords = TextureCoords[j].Split(',');
                                                        float.TryParse(splitCoords[0], out OpenBVEWidth);
                                                        float.TryParse(splitCoords[1], out OpenBVEHeight);
                                                        if (TextureWidth != 0 && TextureHeight != 0)
                                                        {
                                                            currentCoords.X = (OpenBVEWidth / TextureWidth);
                                                            currentCoords.Y = (OpenBVEHeight / TextureHeight);
                                                        }
                                                        else
                                                        {
                                                            currentCoords.X = 0;
                                                            currentCoords.Y = 0;
                                                        }
                                                        Builder.Vertices[Builder.Vertices.Length - 1].TextureCoordinates = currentCoords;
                                                    }
                                                    if (Face2)
                                                    {
                                                        Builder.Faces[f].Flags = (byte)World.MeshFace.Face2Mask;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                //Apply rotation

                /*
                 * NOTES:
                 * No rotation order is specified
                 * The rotation string in a .l3dgrp file is ordered Y, X, Z    ??? Can't find a good reason for this ???
                 * Rotations must still be performed in X,Y,Z order to produce correct results
                 */

                if (RotationX != 0.0)
                {
                    //This is actually the Y-Axis rotation
                    //Convert to radians
                    RotationX *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 1, 0, RotationX);
                }
                if (RotationY != 0.0)
                {
                    //This is actually the X-Axis rotation
                    //Convert to radians
                    RotationY *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 1, 0, 0, RotationY);
                }
                if (RotationZ != 0.0)
                {
                    //Convert to radians
                    RotationZ *= 0.0174532925199433;
                    //Apply rotation
                    ApplyRotation(Builder, 0, 0, 1, RotationZ);
                }

                //These files appear to only have one texture defined
                //Therefore import later- May have to change
                if (File.Exists(tday))
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].DaytimeTexture   = tday;
                        Builder.Materials[j].NighttimeTexture = tnight;
                    }
                }
                if (TransparencyUsed == true)
                {
                    for (int j = 0; j < Builder.Materials.Length; j++)
                    {
                        Builder.Materials[j].TransparentColor     = transparentColor;
                        Builder.Materials[j].TransparentColorUsed = true;
                    }
                }
            }
            ApplyMeshBuilder(ref Object, Builder, LoadMode, ForceTextureRepeatX, ForceTextureRepeatY);
            World.CreateNormals(ref Object.Mesh);
            return(Object);
        }