예제 #1
0
        /// <summary>
        /// Encodes material options code from parameterized options.
        /// Material options encoding is documented in SharedShape.SubObject() (Shapes.cs)
        /// or SceneryMaterial.SetState() (Materials.cs).
        /// </summary>
        /// <param name="lod">LODItem instance.</param>
        /// <returns>Options code.</returns>
        public static SceneryMaterialOptions EncodeMaterialOptions(LODItem lod)
        {
            var options = SceneryMaterialOptions.None;

            if (TextureAddressingModeNames.ContainsKey(lod.TexAddrModeName))
            {
                options |= TextureAddressingModeNames[lod.TexAddrModeName];
            }
            else
            {
                Trace.TraceWarning("Skipped unknown texture addressing mode {1} in shape {0}", lod.Name, lod.TexAddrModeName);
            }

            if (lod.AlphaTestMode == 1)
            {
                options |= SceneryMaterialOptions.AlphaTest;
            }

            if (ShaderNames.ContainsKey(lod.ShaderName))
            {
                options |= ShaderNames[lod.ShaderName];
            }
            else
            {
                Trace.TraceWarning("Skipped unknown shader name {1} in shape {0}", lod.Name, lod.ShaderName);
            }

            if (LightingModelNames.ContainsKey(lod.LightModelName))
            {
                options |= LightingModelNames[lod.LightModelName];
            }
            else
            {
                Trace.TraceWarning("Skipped unknown lighting model index {1} in shape {0}", lod.Name, lod.LightModelName);
            }

            if ((lod.ESD_Alternative_Texture & (int)TextureFlags.Night) != 0)
            {
                options |= SceneryMaterialOptions.NightTexture;
            }

            return(options);
        } // end EncodeMaterialOptions
예제 #2
0
        /// <summary>
        /// Builds a SuperElevation LOD to SuperElevationProfile specifications as one vertex buffer and one index buffer.
        /// The order in which the buffers are built reflects the nesting in the TrProfile.  The nesting order is:
        /// (Polylines (Vertices)).  All vertices and indices are built contiguously for an LOD.
        /// </summary>
        /// <param name="viewer">Viewer.</param>
        /// <param name="worldPosition">WorldPosition.</param>
        /// <param name="iLOD">Index of LOD mesh to be generated from profile.</param>
        /// <param name="iLODItem">Index of LOD mesh to be generated from profile.</param>
        public new ShapePrimitive BuildPrimitive(Viewer viewer, WorldPosition worldPosition, int iLOD, int iLODItem)
        {
            // Call for track section to initialize itself
            if (DTrackData.IsCurved == 0)
            {
                LinearGen();
            }
            else
            {
                CircArcGen();
            }

            // Count vertices and indices
            LOD     lod     = (LOD)TrProfile.LODs[iLOD];
            LODItem lodItem = (LODItem)lod.LODItems[iLODItem];

            NumVertices = (int)(lodItem.NumVertices * (NumSections + 1));
            NumIndices  = (short)(lodItem.NumSegments * NumSections * 6);
            // (Cells x 2 triangles/cell x 3 indices/triangle)

            // Allocate memory for vertices and indices
            VertexList          = new VertexPositionNormalTexture[NumVertices]; // numVertices is now aggregate
            TriangleListIndices = new short[NumIndices];                        // as is NumIndices

            // Build the mesh for lod
            VertexIndex = 0;
            IndexIndex  = 0;
            whichCase   = 0; //0: no elevation (MaxElev=0), 1: start (startE = 0, Max!=end),
            //2: end (end=0, max!=start), 3: middle (start>0, end>0), 4: start and finish in one

            if (StartElev.AlmostEqual(0f, 0.001f) && MaxElev.AlmostEqual(0f, 0.001f) && EndElv.AlmostEqual(0f, 0.001f))
            {
                whichCase = 0;                                                                                                        //no elev
            }
            else if (StartElev.AlmostEqual(0f, 0.001f) && EndElv.AlmostEqual(0f, 0.001f))
            {
                whichCase = 4;                                                                          //finish/start in one
            }
            else if (StartElev.AlmostEqual(0f, 0.001f) && !EndElv.AlmostEqual(0f, 0.001f))
            {
                whichCase = 1;                                                                           //start
            }
            else if (EndElv.AlmostEqual(0f, 0.001f) && !StartElev.AlmostEqual(0f, 0.001f))
            {
                whichCase = 2;                                                                           //finish
            }
            else
            {
                whichCase = 3; //in middle
            }
            Matrix PreRotation = Matrix.Identity;

            elevated = MaxElev;
            if (whichCase == 3 || whichCase == 2)
            {
                PreRotation = Matrix.CreateRotationZ(-elevated * Math.Sign(DTrackData.param1));
            }
            //if section is in the middle of curve, will only rotate the first set of vertex, others will follow the same rotation
            prevRotation = 0f;

            Vector3 tmp;

            // Initial load of baseline cross section polylines for this LOD only:
            foreach (Polyline pl in lodItem.Polylines)
            {
                foreach (Vertex v in pl.Vertices)
                {
                    tmp = new Vector3(v.Position.X, v.Position.Y, v.Position.Z);

                    if (whichCase == 3 || whichCase == 2)
                    {
                        tmp          = Vector3.Transform(tmp, PreRotation);
                        prevRotation = MaxElev;
                    }
                    VertexList[VertexIndex].Position          = tmp;
                    VertexList[VertexIndex].Normal            = v.Normal;
                    VertexList[VertexIndex].TextureCoordinate = v.TexCoord;
                    VertexIndex++;
                }
            }
            // Initial load of base cross section complete

            // Now generate and load subsequent cross sections
            OldRadius = -center;
            uint stride = VertexIndex;

            offSet = 0;

            for (uint i = 0; i < NumSections; i++)
            {
                currentRotation = determineRotation(DTrackData.param1);
                elevated        = currentRotation - prevRotation;
                prevRotation    = currentRotation;
                if (DTrackData.param1 > 0)
                {
                    elevated *= -1;
                }

                foreach (Polyline pl in lodItem.Polylines)
                {
                    uint plv = 0; // Polyline vertex index
                    foreach (Vertex v in pl.Vertices)
                    {
                        if (DTrackData.IsCurved == 0)
                        {
                            LinearGen(stride, pl);                           // Generation call
                        }
                        else
                        {
                            CircArcGen(stride, pl);
                        }

                        if (plv > 0)
                        {
                            // Sense for triangles is clockwise
                            // First triangle:
                            TriangleListIndices[IndexIndex++] = (short)VertexIndex;
                            TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1 - stride);
                            TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1);
                            // Second triangle:
                            TriangleListIndices[IndexIndex++] = (short)VertexIndex;
                            TriangleListIndices[IndexIndex++] = (short)(VertexIndex - stride);
                            TriangleListIndices[IndexIndex++] = (short)(VertexIndex - 1 - stride);
                        }
                        VertexIndex++;
                        plv++;
                    }
                }
                OldRadius = radius; // Get ready for next segment
                offSet++;
            }

            // Create and populate a new ShapePrimitive
            var indexBuffer = new IndexBuffer(viewer.GraphicsDevice, typeof(short), NumIndices, BufferUsage.WriteOnly);

            indexBuffer.SetData(TriangleListIndices);
            return(new ShapePrimitive(lodItem.LODMaterial, new SharedShape.VertexBufferSet(VertexList, viewer.GraphicsDevice), indexBuffer, 0, NumVertices, NumIndices / 3, new[] { -1 }, 0));
        }
예제 #3
0
        /// <summary>
        /// WireProfile constructor (default - builds from self-contained data)
        /// </summary>
        public WireProfile(Viewer viewer) // Nasty: void return type is not allowed. (See MSDN for compiler error CS0542.)
            : base(viewer, 0)             //call the dummy base constructor so that no data is pre-populated
        {
            LODMethod = LODMethods.ComponentAdditive;
            LODWire     lod;     // Local LOD instance
            LODItemWire lodItem; // Local LODItem instance
            Polyline    pl;      // Local polyline instance
            Polyline    vertical;

            expectedSegmentLength = 40;    //segment of wire is expected to be 40 meters

            lod     = new LODWire(800.0f); // Create LOD for railsides with specified CutoffRadius
            lodItem = new LODItemWire("Wire");
            if (File.Exists(viewer.Simulator.RoutePath + "\\Textures\\overheadwire.ace"))
            {
                lodItem.TexName = "overheadwire.ace";
            }
            else if (File.Exists(viewer.Simulator.BasePath + "\\global\\textures\\overheadwire.ace"))
            {
                lodItem.TexName = "..\\..\\..\\global\\textures\\overheadwire.ace";
            }
            else
            {
                Trace.TraceInformation("Ignored missing overheadwire.ace, using default. You can copy the overheadwire.ace from OR\'s AddOns folder to {0}\\Textures", viewer.Simulator.RoutePath);
                lodItem.TexName = "..\\..\\..\\global\\textures\\dieselsmoke.ace";
            }
            lodItem.ShaderName              = "TexDiff";
            lodItem.LightModelName          = "DarkShade";
            lodItem.AlphaTestMode           = 0;
            lodItem.TexAddrModeName         = "Wrap";
            lodItem.ESD_Alternative_Texture = 0;
            lodItem.MipMapLevelOfDetailBias = 0;
            LODItem.LoadMaterial(viewer, lodItem);

            bool drawTriphaseWire = (viewer.Simulator.TRK.Tr_RouteFile.TriphaseEnabled == "Off" ? false :
                                     viewer.Simulator.TRK.Tr_RouteFile.TriphaseEnabled == "On");
            bool drawDoubleWire = (viewer.Simulator.TRK.Tr_RouteFile.DoubleWireEnabled == "Off" ? false :
                                   viewer.Simulator.TRK.Tr_RouteFile.DoubleWireEnabled == "On" || viewer.Settings.DoubleWire);
            float topHeight     = (float)viewer.Simulator.TRK.Tr_RouteFile.OverheadWireHeight;
            float topWireOffset = (viewer.Simulator.TRK.Tr_RouteFile.DoubleWireHeight > 0 ?
                                   viewer.Simulator.TRK.Tr_RouteFile.DoubleWireHeight : 1.0f);
            float dist = (viewer.Simulator.TRK.Tr_RouteFile.TriphaseWidth > 0 ?
                          viewer.Simulator.TRK.Tr_RouteFile.TriphaseWidth : 1.0f);

            if (drawTriphaseWire)
            {
                pl = SingleWireProfile("TopWireLeft", topHeight, -dist / 2);
                lodItem.Polylines.Add(pl);
                lodItem.Accum(pl.Vertices.Count);

                pl = SingleWireProfile("TopWireRight", topHeight, dist / 2);
                lodItem.Polylines.Add(pl);
                lodItem.Accum(pl.Vertices.Count);
            }
            else
            {
                pl = SingleWireProfile("TopWire", topHeight);
                lodItem.Polylines.Add(pl);
                lodItem.Accum(pl.Vertices.Count);
            }

            if (drawDoubleWire)
            {
                topHeight += topWireOffset;

                if (drawTriphaseWire)
                {
                    pl = SingleWireProfile("TopWire1Left", topHeight, -dist / 2);
                    lodItem.Polylines.Add(pl);
                    lodItem.Accum(pl.Vertices.Count);
                    pl = SingleWireProfile("TopWire1Right", topHeight, dist / 2);
                    lodItem.Polylines.Add(pl);
                    lodItem.Accum(pl.Vertices.Count);

                    vertical = VerticalWireProfile("TopWireVerticalLeft", topHeight, -dist / 2);
                    lodItem.VerticalPolylines = new ArrayList();
                    lodItem.VerticalPolylines.Add(vertical);
                    lodItem.VerticalAccumulate(vertical.Vertices.Count);
                    vertical = VerticalWireProfile("TopWireVerticalRight", topHeight, dist / 2);
                    lodItem.VerticalPolylines.Add(vertical);
                    lodItem.VerticalAccumulate(vertical.Vertices.Count);
                }
                else
                {
                    pl = SingleWireProfile("TopWire1", topHeight);
                    lodItem.Polylines.Add(pl);
                    lodItem.Accum(pl.Vertices.Count);

                    vertical = VerticalWireProfile("TopWireVertical", topHeight);
                    lodItem.VerticalPolylines = new ArrayList();
                    lodItem.VerticalPolylines.Add(vertical);
                    lodItem.VerticalAccumulate(vertical.Vertices.Count);
                }
            }

            lod.LODItems.Add(lodItem); // Append to LODItems array
            base.LODs.Add(lod);        // Append this lod to LODs array
        }
예제 #4
0
        /// <summary>
        /// WireProfile constructor (default - builds from self-contained data)
        /// </summary>
        public WireProfile(Viewer viewer) // Nasty: void return type is not allowed. (See MSDN for compiler error CS0542.)
            : base(viewer, 0)             //call the dummy base constructor so that no data is pre-populated
        {
            LODMethod = LODMethods.ComponentAdditive;
            LODWire     lod;     // Local LOD instance
            LODItemWire lodItem; // Local LODItem instance
            Polyline    pl;      // Local polyline instance
            Polyline    vertical;

            expectedSegmentLength = 40;    //segment of wire is expected to be 40 meters

            lod     = new LODWire(800.0f); // Create LOD for railsides with specified CutoffRadius
            lodItem = new LODItemWire("Wire");
            var normalvalue = 0.707f;

            if (File.Exists(viewer.Simulator.RoutePath + "\\Textures\\overheadwire.ace"))
            {
                lodItem.TexName = "overheadwire.ace";
            }
            else
            {
                Trace.TraceInformation("Ignored missing overheadwire.ace, using default. You can copy the overheadwire.ace from OR\'s AddOns folder to {0}\\Textures", viewer.Simulator.RoutePath);
                lodItem.TexName = "..\\..\\..\\global\\textures\\dieselsmoke.ace";
            }
            lodItem.ShaderName              = "TexDiff";
            lodItem.LightModelName          = "OptSpecular0";
            lodItem.AlphaTestMode           = 0;
            lodItem.TexAddrModeName         = "Wrap";
            lodItem.ESD_Alternative_Texture = 0;
            lodItem.MipMapLevelOfDetailBias = 0;
            LODItem.LoadMaterial(viewer, lodItem);

            float topHeight = (float)viewer.Simulator.TRK.Tr_RouteFile.OverheadWireHeight;

            float u1 = 0.25f, v1 = 0.25f;

            pl = new Polyline(this, "TopWire", 5);
            pl.DeltaTexCoord = new Vector2(0.00f, 0.00f);

            pl.Vertices.Add(new Vertex(-0.01f, topHeight + 0.02f, 0.0f, -normalvalue, normalvalue, 0f, u1, v1));
            pl.Vertices.Add(new Vertex(0.01f, topHeight + 0.02f, 0.0f, normalvalue, normalvalue, 0f, u1, v1));
            pl.Vertices.Add(new Vertex(0.01f, topHeight, 0.0f, normalvalue, -normalvalue, 0f, u1, v1));
            pl.Vertices.Add(new Vertex(-0.01f, topHeight, 0.0f, -normalvalue, -normalvalue, 0f, u1, v1));
            pl.Vertices.Add(new Vertex(-0.01f, topHeight + 0.02f, 0.0f, -normalvalue, normalvalue, 0f, u1, v1));
            lodItem.Polylines.Add(pl);
            lodItem.Accum(pl.Vertices.Count);

            if (viewer.Settings.DoubleWire)
            {
                pl = new Polyline(this, "TopWire1", 5);
                pl.DeltaTexCoord = new Vector2(0.00f, 0.00f);
                topHeight       += 1.0f;

                pl.Vertices.Add(new Vertex(-0.01f, topHeight + 0.02f, 0.0f, -normalvalue, normalvalue, 0f, u1, v1));
                pl.Vertices.Add(new Vertex(0.01f, topHeight + 0.02f, 0.0f, normalvalue, normalvalue, 0f, u1, v1));
                pl.Vertices.Add(new Vertex(0.01f, topHeight, 0.0f, normalvalue, -normalvalue, 0f, u1, v1));
                pl.Vertices.Add(new Vertex(-0.01f, topHeight, 0.0f, -normalvalue, -normalvalue, 0f, u1, v1));
                pl.Vertices.Add(new Vertex(-0.01f, topHeight + 0.02f, 0.0f, -normalvalue, normalvalue, 0f, u1, v1));
                lodItem.Polylines.Add(pl);
                lodItem.Accum(pl.Vertices.Count);

                vertical = new Polyline(this, "TopWireVertical", 5);
                vertical.DeltaTexCoord = new Vector2(0.00f, 0.00f);

                vertical.Vertices.Add(new Vertex(-0.008f, topHeight, 0.008f, -normalvalue, 0f, normalvalue, u1, v1));
                vertical.Vertices.Add(new Vertex(-.008f, topHeight, -.008f, normalvalue, 0f, normalvalue, u1, v1));
                vertical.Vertices.Add(new Vertex(.008f, topHeight, -.008f, normalvalue, 0f, -normalvalue, u1, v1));
                vertical.Vertices.Add(new Vertex(.008f, topHeight, .008f, -normalvalue, 0f, -normalvalue, u1, v1));
                vertical.Vertices.Add(new Vertex(-.008f, topHeight, .008f, -normalvalue, 0f, normalvalue, u1, v1));
                lodItem.VerticalPolylines = new ArrayList();
                lodItem.VerticalPolylines.Add(vertical);
                lodItem.VerticalAccumulate(vertical.Vertices.Count);
            }


            lod.LODItems.Add(lodItem); // Append to LODItems array
            base.LODs.Add(lod);        // Append this lod to LODs array
        }
예제 #5
0
        private void Update()
        {
            GetComponentsInChildren <LODItem>(items);

            var camera = Camera.main;

            counter += 1;
            var pingThisFrame = false;

            if (counter % 10 == 0)
            {
                counter = 0;
                if (drawDebug)
                {
                    pingThisFrame = true;
                }
            }

            var selector = GetComponent <PullTabSelector>();

            var     closestAngle = float.PositiveInfinity;
            LODItem closestItem  = null;

            foreach (var item in items)
            {
                var testAngle = Vector3.Angle(camera.transform.forward,
                                              item.transform.position - camera.transform.position);
                var testDist = Vector3.Distance(item.transform.position, camera.transform.position);


                if (pingThisFrame)
                {
                    DebugPing.Ping(item.transform.position, LeapColor.blue, 0.08f);

                    Debug.Log(testAngle);
                }

                if (testAngle < closestAngle &&
                    testAngle <= maxCameraLookAngle &&
                    testDist <= maxDetailDistance)
                {
                    closestAngle = testAngle;

                    if (selector != null && selector.listOpenCloseAmount < 0.10f)
                    {
                        var activeMarbleItem = selector.activeMarbleParent.GetComponentInChildren <LODItem>();
                        if (item == activeMarbleItem)
                        {
                            closestItem = item;
                        }
                    }
                    else
                    {
                        closestItem = item;
                    }

                    if (pingThisFrame)
                    {
                        DebugPing.Ping(item.transform.position, LeapColor.red, 0.09f);
                    }
                }
            }


            if (viewMode == ViewMode.Full)
            {
                foreach (var item in items)
                {
                    if (closestItem != null)
                    {
                        if (item.propertySwitch.GetIsOffOrTurningOff())
                        {
                            item.propertySwitch.On();
                        }
                    }
                    else
                    {
                        if (item.propertySwitch.GetIsOnOrTurningOn())
                        {
                            item.propertySwitch.Off();
                        }
                    }
                }
            }
            else if (viewMode == ViewMode.Fade)
            {
                foreach (var item in items)
                {
                    var detailActivation = 0f;
                    if (closestItem != null)
                    {
                        float dist;
                        switch (fadeDistanceMode)
                        {
                        case FadeDistanceMode.FastFalloff:
                            dist             = Mathf.Sqrt((item.transform.position - closestItem.transform.position).magnitude);
                            detailActivation = dist.Map(0f, Mathf.Sqrt(fadeRadius), 1f, 0f);
                            break;

                        case FadeDistanceMode.SlowFalloff:
                            dist             = (item.transform.position - closestItem.transform.position).sqrMagnitude;
                            detailActivation = dist.Map(0f, fadeRadius * fadeRadius, 1f, 0f);
                            break;

                        case FadeDistanceMode.Linear:
                        default:
                            dist             = (item.transform.position - closestItem.transform.position).magnitude;
                            detailActivation = dist.Map(0f, fadeRadius, 1f, 0f);
                            break;
                        }

                        if (detailActivation < cutoffActivationPercent)
                        {
                            detailActivation = 0f;
                        }
                    }

                    if (item.tweenSwitch != null)
                    {
                        item.tweenSwitch.SetTweenTarget(detailActivation);
                    }
                    else
                    {
                        Debug.LogError("Can't use Fade view mode for this item; it doesn't use a "
                                       + "TweenSwitch.", item);
                    }
                }
            }
            else if (viewMode == ViewMode.Single)
            {
                foreach (var item in items)
                {
                    if (item != closestItem && item.tweenSwitch != null &&
                        item.propertySwitch.GetIsOnOrTurningOn())
                    {
                        item.propertySwitch.Off();
                    }
                }
                // Older: one at a time;
                if (closestItem != null && closestItem.tweenSwitch != null &&
                    closestItem.propertySwitch.GetIsOffOrTurningOff())
                {
                    closestItem.propertySwitch.On();
                }
            }

            if (pingThisFrame && closestItem != null)
            {
                DebugPing.Ping(closestItem.transform.position, LeapColor.purple, 0.10f);
            }
        }