public TerrainPrimitive(Viewer viewer, TileManager tileManager, Tile tile, int x, int z) { Viewer = viewer; TileX = tile.TileX; TileZ = tile.TileZ; Size = tile.Size; PatchX = x; PatchZ = z; PatchSize = tile.Size * 2048 / tile.PatchCount; TileManager = tileManager; Tile = tile; Patch = Tile.GetPatch(x, z); var cx = Patch.CenterX - 1024; var cz = Patch.CenterZ - 1024 + 2048 * tile.Size; PatchLocation = new Vector3(cx, Tile.Floor, cz); PatchVertexBuffer = GetVertexBuffer(out AverageElevation); PatchIndexBuffer = GetIndexBuffer(out PatchPrimitiveCount); var terrainMaterial = tile.Size > 2 ? "TerrainSharedDistantMountain" : PatchIndexBuffer == null ? "TerrainShared" : "Terrain"; var ts = Tile.Shaders[Patch.ShaderIndex].terrain_texslots; var uv = Tile.Shaders[Patch.ShaderIndex].terrain_uvcalcs; if (ts.Length > 1) { PatchMaterial = viewer.MaterialManager.Load(terrainMaterial, Helpers.GetTerrainTextureFile(viewer.Simulator, ts[0].Filename) + "\0" + Helpers.GetTerrainTextureFile(viewer.Simulator, ts[1].Filename) + (uv[1].D != 0 && uv[1].D != 32 ? "\0" + uv[1].D.ToString(): "")); } else { PatchMaterial = viewer.MaterialManager.Load(terrainMaterial, Helpers.GetTerrainTextureFile(viewer.Simulator, ts[0].Filename) + "\0" + Helpers.GetTerrainTextureFile(viewer.Simulator, "microtex.ace")); } if (SharedPatchIndexBuffer == null) { SetupSharedData(Viewer.GraphicsDevice); } Tile = null; Patch = null; VertexBufferBindings = new[] { new VertexBufferBinding(PatchVertexBuffer), new VertexBufferBinding(GetDummyVertexBuffer(viewer.GraphicsDevice)) }; }
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); }