Beispiel #1
0
        public static bool UseSuperElevationDyn(Viewer viewer, List <DynamicTrackViewer> dTrackList, DyntrackObj dTrackObj,
                                                WorldPosition worldMatrixInput)
        {
            bool withCurves = false;

            for (int iTkSection = 0; iTkSection < dTrackObj.trackSections.Count; iTkSection++)
            {
                float length = 0;

                length = dTrackObj.trackSections[iTkSection].param1; // meters if straight; radians if curved
                if (length == 0.0)
                {
                    continue;                // Consider zero-length subsections vacuous
                }
                // Create new DT object copy; has only one meaningful subsection
                DyntrackObj subsection = new DyntrackObj(dTrackObj, iTkSection);

                // Straight or curved subsection?
                if (subsection.trackSections[0].isCurved == 0) // Straight section
                {                                              // Heading stays the same; translation changes in the direction oriented
                }
                else // Curved section
                {   // Both heading and translation change
                    //if (Math.Abs(radius * length) < Program.Simulator.SuperElevationMinLen) return false;
                    withCurves = true;
                }
            }
            return(withCurves); //if no curve, will not draw using super elevation
        }
Beispiel #2
0
        /// <summary>
        /// Decompose and add a SuperElevation on top of MSTS track section
        /// </summary>
        /// <param name="viewer">Viewer reference.</param>
        /// <param name="dTrackList">DynamicTrackViewer list.</param>
        /// <param name="dTrackObj">Dynamic track section to decompose.</param>
        /// <param name="worldMatrixInput">Position matrix.</param>
        public static void DecomposeDynamicSuperElevation(Viewer viewer, List <DynamicTrackViewer> dTrackList, DyntrackObj dTrackObj,
                                                          WorldPosition worldMatrixInput)
        {
            // DYNAMIC TRACK
            // =============
            // Objectives:
            // 1-Decompose multi-subsection DT into individual sections.
            // 2-Create updated transformation objects (instances of WorldPosition) to reflect
            //   root of next subsection.
            // 3-Distribute elevation change for total section through subsections. (ABANDONED)
            // 4-For each meaningful subsection of dtrack, build a separate SuperElevationPrimitive.
            //
            // Method: Iterate through each subsection, updating WorldPosition for the root of
            // each subsection.  The rotation component changes only in heading.  The translation
            // component steps along the path to reflect the root of each subsection.

            // The following vectors represent local positioning relative to root of original (5-part) section:
            Vector3 localV = Vector3.Zero;                                   // Local position (in x-z plane)
            Vector3 localProjectedV;                                         // Local next position (in x-z plane)
            Vector3 displacement;                                            // Local displacement (from y=0 plane)
            Vector3 heading = Vector3.Forward;                               // Local heading (unit vector)

            WorldPosition worldMatrix = new WorldPosition(worldMatrixInput); // Make a copy so it will not be messed

            WorldPosition nextRoot      = new WorldPosition(worldMatrix);    // Will become initial root
            Vector3       sectionOrigin = worldMatrix.XNAMatrix.Translation; // Save root position

            worldMatrix.XNAMatrix.Translation = Vector3.Zero;                // worldMatrix now rotation-only

            // Iterate through all subsections
            int count = -1;

            for (int iTkSection = 0; iTkSection < dTrackObj.trackSections.Count; iTkSection++)
            {
                count++;
                float length = 0, radius = -1;

                length = dTrackObj.trackSections[iTkSection].param1; // meters if straight; radians if curved
                if (length == 0.0)
                {
                    continue;                // Consider zero-length subsections vacuous
                }
                // Create new DT object copy; has only one meaningful subsection
                DyntrackObj subsection = new DyntrackObj(dTrackObj, iTkSection);

                // Create a new WorldPosition for this subsection, initialized to nextRoot,
                // which is the WorldPosition for the end of the last subsection.
                // In other words, beginning of present subsection is end of previous subsection.
                WorldPosition root = new WorldPosition(nextRoot);

                // Now we need to compute the position of the end (nextRoot) of this subsection,
                // which will become root for the next subsection.

                // Clear nextRoot's translation vector so that nextRoot matrix contains rotation only
                nextRoot.XNAMatrix.Translation = Vector3.Zero;

                // Straight or curved subsection?
                if (subsection.trackSections[0].isCurved == 0) // Straight section
                {                                              // Heading stays the same; translation changes in the direction oriented
                    // Rotate Vector3.Forward to orient the displacement vector
                    localProjectedV = localV + length * heading;
                    displacement    = Traveller.MSTSInterpolateAlongStraight(localV, heading, length,
                                                                             worldMatrix.XNAMatrix, out localProjectedV);
                }
                else // Curved section
                {   // Both heading and translation change
                    // nextRoot is found by moving from Point-of-Curve (PC) to
                    // center (O)to Point-of-Tangent (PT).
                    radius = subsection.trackSections[0].param2;                                                                 // meters
                    Vector3 left = radius * Vector3.Cross(Vector3.Up, heading) * Math.Sign(-subsection.trackSections[0].param1); // Vector from PC to O
                    Matrix  rot  = Matrix.CreateRotationY(-length);                                                              // Heading change (rotation about O)
                    // Shared method returns displacement from present world position and, by reference,
                    // local position in x-z plane of end of this section
                    displacement = Traveller.MSTSInterpolateAlongCurve(localV, left, rot,
                                                                       worldMatrix.XNAMatrix, out localProjectedV);

                    heading            = Vector3.Transform(heading, rot); // Heading change
                    nextRoot.XNAMatrix = rot * nextRoot.XNAMatrix;        // Store heading change
                }

                // Update nextRoot with new translation component
                nextRoot.XNAMatrix.Translation = sectionOrigin + displacement;

                sv = ev = mv = 0f;
                //                if (section.SectionCurve != null) FindSectionValue(shape, root, nextRoot, viewer.Simulator, section, TileX, TileZ, dTrackObj.UID);

                //nextRoot.XNAMatrix.Translation += Vector3.Transform(trackLoc, worldMatrix.XNAMatrix);
                dTrackList.Add(new SuperElevationViewer(viewer, root, nextRoot, radius, length, sv, ev, mv, dir));

                localV = localProjectedV; // Next subsection
            }
        }