Page 2 of 2 FirstFirst 12
Results 11 to 14 of 14

Thread: World file format

  1. #11
    Join Date
    Feb 2013
    known universe


    Quote Originally Posted by eolesen View Post
    Well, QD is a quaternion value and I wish it were easy to explain. It defines the 3D vector that the shape takes starting at the XYZ position value. The math to explain the values isn't simple by any means... that's why there are calculators to derive it from two sets of known XYZ coordinates.

    0 0 0 1 is due North. That's the only value that is easy to explain....

    I'll explain the rest later...
    As Dr. Daniel Jackson explains it:

    Cheers, Gerry
    It's my railroad and I'll do what I want! Historically accurate attitude of US Railroad Barons.
    Forever, ridin' drag in railroad knowledge.

  2. #12


    These are my definitions, not necessarily those of Kuju or other route developers... feel free to correct me if you know otherwise.

    World File Object Types:

    • Static -- the majority of scenery objects... things that don't move, and don't need any logic behind them to be displayed aside perhaps from animation
    • TrackObj -- track and roads... requires a corresponding entry in the TDB/RDB to allow movement, and also a definition in the TSection.dat file
    • Forest -- Dynamically renders objects at runtime using parameters stored in the W file object; Forests.dat file is used by TSRE and MSTSRE to create the object only; changes made to the DAT file only take effect for future object placements at time of placement.
    • Gantry -- Dynamically *placed* object using MSTS Route Editor functionality to follow a track vector. Declared as a Gantry so that it can be removed via the MSTS-RE.
    • Signal -- interactive that requires a corresponding entry in the SigScr and SigCfg for the filename, and also a corresponding entry in the TDB (related by TrItemID)
    • Speedpost -- interactive that requires a corresponding entry in the TDB (related by TrItemID); Speedpost.dat is used to create the object only, changes made to the DAT file only take effect on future object placements at time of placement.
    • LevelCr -- Scenery object which animates when activity on a specific TrItemID occurs, mostly used for grade crossing warning bells/gates, but also used for drawbridges and other animations
    • Transfer -- texture applied using parameters stored in the W file object, not commonly used
    • CollideObject -- Object which can cause a train to stop if the bounding box of the object overlaps with the bounding box of a wagon or engine. Used sometimes for low bridges, most commonly used with end of track buffers or wheelstops.
    • CarSpawner -- interactive that dynamically generates moving objects along a road path
    • Siding -- interactive used in activity files and ORTS timetables to indicate an intermediate stopping point
    • Platform -- interactive used in activity files and ORTS timetables to indicate an intermediate stopping point for passengers
    • Crossover -- identifies two overlapping pieces of track by relating the respective track vectors so that signaling can show a blocked path when movement is occurring on one or both vectors.
    • Hazard -- interactive that can move into the way of a train, not commonly used and sometimes also spelled Hazzard...
    • Pickup -- used in activity files to represent a load that would be picked up e.g. coal, lumber, etc. and increase the weight of a wagon
    • ViewDbSphere -- Microsoft concept that created object groupings so overlapping W file objects would render more or less as they were traveled. Doesn't appear supported in TSRE and not a mandatory definition. Creates a unique VDbID

    World File Object Parameters:

    • UiD -- Unique integer value within a specific W file, presumably used in MSTS to load objects into memory but also used in the TDB to identify a specific track object. Duplicate UID's for static objects doesn't appear to blow things up, but duplicate UID's within a W file for interactives will wreak havoc...
    • CollideFlags -- bitmask used to define what happens when different objects interact
    • Filename -- shapefile name to be rendered, defaults to route's SHAPES folder for all objects except TrObjects, which default to Global\Shapes. Both can be overridden by using a relative path name.
    • Position -- X Y Z coordinates of an object... Y is meters above sea level, X is meters east-west from center of tile, Z is meters north-south from center of tile. Max 1028 min -1028 for X and Z, no practical max/min for Y
    • QDirection -- Quaternion value (four params) defining the W X Y Z rotation of an object. Objects flat on the earth will have 0 values in positions 1 and 3. Anything else represents a rotation.
    • StaticFlags -- bitmask used to define behaviors at runtime such as what type of shadow is cast, if it's a terrain object, or if it's animated. Animated = 80000, TerrainObj = 40000, shadows none 0/round 2000/rect 4000/treeline 8000/Dynamic 10000
    • StaticDetailLevel --- integer value (min 0 max 10) used to optionally determine loading of objects at time of render. Both MSTS and ORTS support reducing tile density by filtering out objects with a SDL above the value selected in the filter. Also used by CatMaster and WorldFileHacker for other purposes.

      Track Object Specifics:
      • SectionIdx -- index of track/road object in TSection.dat (which further defines vector direction and length, compound vectors used by curved sections, and junctions used by switch/points)
      • Elevation -- meters above the terrain, seems to only be used by camera at runtime

      Transfer Object Specifics:
      • Width -- width to render transfer texture (will stretch/compress texture resolution)
      • Height -- height to render transfer texture (will stretch/compress texture resolution)

      Forest Object Specifics:
      • TreeTexture --- used by forest objects to define the texture used to dynamically create cruciforms for rendering.
      • TreeSize -- Height and width of default TreeTexture in meters
      • ScaleRange -- Scaling factor for randomness of tree sizes rendered at runtime
      • Area -- Size of box to be populated with cruciforms, value defined at time of placement in sim
      • Population -- density of cruciforms to be created, value created by editor after placement

    • VDbId -- not clear, but appears to be a hash used in the MSTS game engine to aid at rendering time. Not mandatory, no longer used in ORTS as far as I know or created by TSRE.

    That's what I have in my own code for WFH, and there might be a few objects or parameters that I've overlooked, but WFH accepts those as-is and doesn't do any processing of objects that it doesn't specifically recognize.
    Last edited by eolesen; 01-13-2021 at 08:44 AM.

  3. #13


    Here is an example of QD... it's not a clean math formula, you need to do tangent, cosine, sine, etc...


    Here's the formula that Tangent uses for calculating flat rotation (no elevation change) between two objects... there's a way to calculate the slope and slopedeg values based on the PosY values, but I don't have that handy nor do I try to use it...

                    float dx = 2048 * (EndObject.TileX - StartObject.TileX) + EndObject.PosX - StartObject.PosX;
                    float dy = EndObject.PosY - StartObject.PosY;
                    float dz = 2048 * (EndObject.TileZ - StartObject.TileZ) + EndObject.PosZ - StartObject.PosZ;
                    double heading;
                    if (Math.Abs(dx) > 0)
                        if (dx > 0) { heading = 90 - 180 / Math.PI * Math.Atan(dz / dx); }
                        else { heading = -90 - 180 / Math.PI * Math.Atan(dz / dx); }
                    else { heading = -90 + Math.Sign(dz) * 90; }
                    double distance = Math.Sqrt((dx * dx) + (dy * dy) + (dz * dz));
                    double slope;
                    if (Math.Abs(dy / distance) < 0.99999)
                    { slope = Math.Atan(dy / Math.Sqrt(dx * dx + dz * dz)); }
                       else { slope = Math.Sign(dy / distance) * 1000; }
                    double slopedeg = 0;
                    if (Math.Abs(dy / distance) < 0.99999)
                    { slope = 180 / Math.PI * Math.Atan(dy / Math.Sqrt(dx * dx + dz * dz)); }
                      else { slope = Math.Sign(dy / distance) * 90; }
                    double headingcos = Math.Cos(-0.5 * heading * Math.PI / 180);
                    double headingsin = Math.Sin(-0.5 * heading * Math.PI / 180);
                    double slopecos = 1;
                    double slopesin = 0;
                    double slopedegcos = 1;
                    double slopedegsin = 0;
                    double QD1 = (headingcos * slopecos * slopedegsin) + (headingsin * slopesin * slopedegcos);
                    double QD2 = (headingsin * slopecos * slopedegcos) - (headingcos * slopesin * slopedegsin);
                    double QD3 = (headingcos * slopesin * slopedegcos) + (headingsin * slopecos * slopedegsin);
                    double QD4 = (headingcos * slopecos * slopedegcos) + (headingsin * slopesin * slopedegsin);

  4. #14
    Join Date
    Oct 2008
    Lubec ME USA


    Great. Thanks for the info.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts