public ForestViewer(Viewer viewer, ForestObj forest, WorldPosition position) { Viewer = viewer; Position = position; MaximumCenterlineOffset = Viewer.Simulator.TRK.Tr_RouteFile.ForestClearDistance; Material = viewer.MaterialManager.Load("Forest", Helpers.GetForestTextureFile(viewer.Simulator, forest.TreeTexture)); Primitive = new ForestPrimitive(Viewer, forest, position, MaximumCenterlineOffset); }
public ForestPrimitive(Viewer viewer, ForestObj forest, WorldPosition position, float maximumCenterlineOffset, bool checkRoadsToo) { Viewer = viewer; MaximumCenterlineOffset = maximumCenterlineOffset; CheckRoadsToo = checkRoadsToo; var trees = CalculateTrees(viewer.Tiles, forest, position, out ObjectRadius); if (trees.Count > 0) { VertexBuffer = new VertexBuffer(viewer.GraphicsDevice, typeof(VertexPositionNormalTexture), trees.Count, BufferUsage.WriteOnly); VertexBuffer.SetData(trees.ToArray()); } PrimitiveCount = trees.Count / 3; }
public ForestPrimitive(Viewer viewer, ForestObj forest, WorldPosition position, float maximumCenterlineOffset) { Viewer = viewer; MaximumCenterlineOffset = maximumCenterlineOffset; var trees = CalculateTrees(viewer.Tiles, forest, position, out ObjectRadius); VertexDeclaration = new VertexDeclaration(viewer.GraphicsDevice, VertexPositionNormalTexture.VertexElements); if (trees.Count > 0) { VertexStride = VertexDeclaration.GetVertexStrideSize(0); VertexBuffer = new VertexBuffer(viewer.GraphicsDevice, typeof(VertexPositionNormalTexture), trees.Count, BufferUsage.WriteOnly); VertexBuffer.SetData(trees.ToArray()); } PrimitiveCount = trees.Count / 3; }
private List <VertexPositionNormalTexture> CalculateTrees(TileManager tiles, ForestObj forest, WorldPosition position, out float objectRadius) { // To get consistent tree placement between sessions, derive the seed from the location. var random = new Random((int)(1000.0 * (position.Location.X + position.Location.Z + position.Location.Y))); List <TrVectorSection> sections = new List <TrVectorSection>(); objectRadius = (float)Math.Sqrt(forest.forestArea.X * forest.forestArea.X + forest.forestArea.Z * forest.forestArea.Z) / 2; if (MaximumCenterlineOffset > 0) { Matrix InvForestXNAMatrix = Matrix.Invert(position.XNAMatrix); var addList = FindTracksAndRoadsClose(position.TileX, position.TileZ); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); // Check for cross-tile forests List <Vector3> forestVertices = new List <Vector3>(); var forestVertex = new Vector3(-forest.forestArea.X / 2, 0, -forest.forestArea.Z / 2); Vector3.Transform(ref forestVertex, ref position.XNAMatrix, out forestVertex); forestVertices.Add(forestVertex); forestVertex = new Vector3(forest.forestArea.X / 2, 0, -forest.forestArea.Z / 2); Vector3.Transform(ref forestVertex, ref position.XNAMatrix, out forestVertex); forestVertices.Add(forestVertex); forestVertex = new Vector3(-forest.forestArea.X / 2, 0, forest.forestArea.Z / 2); Vector3.Transform(ref forestVertex, ref position.XNAMatrix, out forestVertex); forestVertices.Add(forestVertex); forestVertex = new Vector3(forest.forestArea.X / 2, 0, forest.forestArea.Z / 2); Vector3.Transform(ref forestVertex, ref position.XNAMatrix, out forestVertex); forestVertices.Add(forestVertex); bool[] considerTile = new bool [4] { false, false, false, false }; foreach (var fVertex in forestVertices) { if (fVertex.X > 1024) { considerTile[0] = true; } if (fVertex.X < -1024) { considerTile[1] = true; } if (fVertex.Z > 1024) { considerTile[3] = true; } if (fVertex.Z < -1024) { considerTile[2] = true; } } // add sections in nearby tiles for cross-tile forests if (considerTile[0]) { addList = FindTracksAndRoadsClose(position.TileX + 1, position.TileZ); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[1]) { addList = FindTracksAndRoadsClose(position.TileX - 1, position.TileZ); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[2]) { addList = FindTracksAndRoadsClose(position.TileX, position.TileZ + 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[3]) { addList = FindTracksAndRoadsClose(position.TileX, position.TileZ - 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[0] && considerTile[2]) { addList = FindTracksAndRoadsClose(position.TileX + 1, position.TileZ + 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[0] && considerTile[3]) { addList = FindTracksAndRoadsClose(position.TileX + 1, position.TileZ - 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[1] && considerTile[2]) { addList = FindTracksAndRoadsClose(position.TileX - 1, position.TileZ + 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } if (considerTile[1] && considerTile[3]) { addList = FindTracksAndRoadsClose(position.TileX - 1, position.TileZ - 1); FindTracksAndRoadsMoreClose(ref sections, addList, forest, position, InvForestXNAMatrix); } } var trees = new List <VertexPositionNormalTexture>(forest.Population * 6); for (var i = 0; i < forest.Population; i++) { var xnaTreePosition = new Vector3((0.5f - (float)random.NextDouble()) * forest.forestArea.X, 0, (0.5f - (float)random.NextDouble()) * forest.forestArea.Z); Vector3.Transform(ref xnaTreePosition, ref position.XNAMatrix, out xnaTreePosition); bool onTrack = false; var scale = MathHelper.Lerp(forest.scaleRange.Minimum, forest.scaleRange.Maximum, (float)random.NextDouble()); var treeSize = new Vector3(forest.treeSize.Width * scale, forest.treeSize.Height * scale, 1); var heightComputed = false; if (MaximumCenterlineOffset > 0 && sections != null && sections.Count > 0) { foreach (var section in sections) { onTrack = InitTrackSection(section, xnaTreePosition, position.TileX, position.TileZ, treeSize.X / 2); if (onTrack) { try { var trackShape = Viewer.Simulator.TSectionDat.TrackShapes.Get((uint)section.ShapeIndex); if (trackShape != null && trackShape.TunnelShape) { xnaTreePosition.Y = tiles.LoadAndGetElevation(position.TileX, position.TileZ, xnaTreePosition.X, -xnaTreePosition.Z, false); heightComputed = true; if (xnaTreePosition.Y > section.Y + 10) { onTrack = false; continue; } } } catch { } break; } } } if (!onTrack) { if (!heightComputed) { xnaTreePosition.Y = tiles.LoadAndGetElevation(position.TileX, position.TileZ, xnaTreePosition.X, -xnaTreePosition.Z, false); } xnaTreePosition -= position.XNAMatrix.Translation; trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(1, 1))); trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(0, 0))); trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(1, 0))); trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(1, 1))); trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(0, 1))); trees.Add(new VertexPositionNormalTexture(xnaTreePosition, treeSize, new Vector2(0, 0))); } } return(trees); }
// don't consider track sections outside the forest boundaries public void FindTracksAndRoadsMoreClose(ref List <TrVectorSection> sections, List <TrVectorSection> allSections, ForestObj forest, WorldPosition position, Matrix invForestXNAMatrix) { if (allSections != null && allSections.Count > 0) { var toAddX = MaximumCenterlineOffset + forest.forestArea.X / 2 + forest.scaleRange.Maximum * forest.treeSize.Width; var toAddZ = MaximumCenterlineOffset + forest.forestArea.Z / 2 + forest.scaleRange.Maximum * forest.treeSize.Width; foreach (TrVectorSection section in allSections) { Vector3 sectPosition; Vector3 sectPosToForest; sectPosition.X = section.X; sectPosition.Z = section.Z; sectPosition.Y = section.Y; sectPosition.X += (section.TileX - position.TileX) * 2048; sectPosition.Z += (section.TileZ - position.TileZ) * 2048; sectPosition.Z = -sectPosition.Z; sectPosToForest = Vector3.Transform(sectPosition, invForestXNAMatrix); sectPosToForest.Z = -sectPosToForest.Z; trackSection = Viewer.Simulator.TSectionDat.TrackSections.Get(section.SectionIndex); if (trackSection == null) { continue; } var trackSectionLength = GetLength(trackSection); if (Math.Abs(sectPosToForest.X) > trackSectionLength + toAddX) { continue; } if (Math.Abs(sectPosToForest.Z) > trackSectionLength + toAddZ) { continue; } sections.Add(section); } } return; }