/// <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 }
/// <summary> /// Builds a Wire LOD to WireProfile 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="lodIndex">Index of LOD mesh to be generated from profile.</param> /// <param name="lodItemIndex">Index of LOD mesh to be generated from profile.</param> public ShapePrimitive BuildPrimitive(Viewer viewer, int lodIndex, int lodItemIndex) { // Call for track section to initialize itself if (DTrackData.IsCurved == 0) { LinearGen(); } else { CircArcGen(); } // Count vertices and indices LODWire lod = (LODWire)TrProfile.LODs[lodIndex]; LODItemWire lodItem = (LODItemWire)lod.LODItems[lodItemIndex]; NumVertices = (int)(lodItem.NumVertices * (NumSections + 1) + 2 * lodItem.VerticalNumVertices * NumSections); NumIndices = (short)(lodItem.NumSegments * NumSections * 6 + lodItem.VerticalNumSegments * 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; // Initial load of baseline cross section polylines for this LOD only: foreach (Polyline pl in lodItem.Polylines) { foreach (Vertex v in pl.Vertices) { VertexList[VertexIndex].Position = v.Position; 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; for (uint i = 0; i < NumSections; i++) { 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 } if (lodItem.VerticalPolylines != null && lodItem.VerticalPolylines.Count > 0) { // Now generate and load subsequent cross sections OldRadius = -center; float coveredLength = SegmentLength; for (uint i = 0; i < NumSections; i++) { stride = 0; radius = Vector3.Transform(OldRadius, sectionRotation); Vector3 p; // Initial load of baseline cross section polylines for this LOD only: if (i == 0) { foreach (Polyline pl in lodItem.VerticalPolylines) { foreach (Vertex v in pl.Vertices) { VertexList[VertexIndex].Position = v.Position; VertexList[VertexIndex].Normal = v.Normal; VertexList[VertexIndex].TextureCoordinate = v.TexCoord; VertexIndex++; stride++; } } } else { foreach (Polyline pl in lodItem.VerticalPolylines) { foreach (Vertex v in pl.Vertices) { if (DTrackData.IsCurved != 0) { OldV = v.Position - center - OldRadius; // Rotate the point about local origin and reposition it (including elevation change) p = DDY + center + radius + v.Position;// +Vector3.Transform(OldV, sectionRotation); VertexList[VertexIndex].Position = new Vector3(p.X, p.Y, p.Z); } else { VertexList[VertexIndex].Position = v.Position + new Vector3(0, 0, -coveredLength); } VertexList[VertexIndex].Normal = v.Normal; VertexList[VertexIndex].TextureCoordinate = v.TexCoord; VertexIndex++; stride++; } } } foreach (Polyline pl in lodItem.VerticalPolylines) { uint plv = 0; // Polyline vertex index foreach (Vertex v in pl.Vertices) { LinearVerticalGen(stride, pl); // Generation call 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++; } } if (i != 0) { OldRadius = radius; // Get ready for next segment coveredLength += SegmentLength; } } } // 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)); }
/// <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 }