public override void LoadWorldGeometry(string fileName) { var serializer = new XmlSerializer(typeof(TerrainOptions)); this.options = (TerrainOptions)serializer.Deserialize(ResourceGroupManager.Instance.OpenResource(fileName)); this.scale = new Vector3(this.options.scalex, this.options.scaley, this.options.scalez); this.tileSize = this.options.size; // load the heightmap { Image image = Image.FromStream(ResourceGroupManager.Instance.OpenResource(this.options.Terrain), this.options.Terrain.Split('.')[1]); worldSize = this.options.worldSize = image.Width; var dest = new Real[(int)worldSize * (int)worldSize]; byte[] src = image.Data; Real invScale; //if ( image.Format != PixelFormat.L8 && image.Format != PixelFormat.L16 ) // throw new AxiomException( "Heightmap is not a grey scale image!" ); bool is16bit = (image.Format == PixelFormat.L16); // Determine mapping from fixed to floating ulong rowSize; if (is16bit) { invScale = 1.0f / 65535.0f; rowSize = (ulong)worldSize * 2; } else { invScale = 1.0f; // / 255.0f; rowSize = (ulong)worldSize; } // Read the data int srcIndex = 0; int dstIndex = 0; for (ulong j = 0; j < (ulong)worldSize; ++j) { for (ulong i = 0; i < (ulong)worldSize; ++i) { if (is16bit) { #if AXIOM_BIG_ENDIAN ushort val = (ushort)(src[srcIndex++] << 8); val += src[srcIndex++]; #else ushort val = src[srcIndex++]; val += (ushort)(src[srcIndex++] << 8); #endif dest[dstIndex++] = new Real(val) * invScale; } else { dest[dstIndex++] = new Real(src[srcIndex++]); // *invScale; #if (XBOX || XBOX360) srcIndex += 3; #endif } } } // get the data from the heightmap this.options.data = dest; } float maxx = this.options.scalex * this.options.worldSize; float maxy = 255 * this.options.scaley; float maxz = this.options.scalez * this.options.worldSize; Resize(new AxisAlignedBox(Vector3.Zero, new Vector3(maxx, maxy, maxz))); this.terrainMaterial = (Material) (MaterialManager.Instance.CreateOrRetrieve( !String.IsNullOrEmpty(this.options.MaterialName) ? this.options.MaterialName : "Terrain", ResourceGroupManager.Instance.WorldResourceGroupName).First); if (this.options.WorldTexture != "") { this.terrainMaterial.GetTechnique(0).GetPass(0).CreateTextureUnitState(this.options.WorldTexture, 0); } if (this.options.DetailTexture != "") { this.terrainMaterial.GetTechnique(0).GetPass(0).CreateTextureUnitState(this.options.DetailTexture, 1); } this.terrainMaterial.Lighting = this.options.isLit; this.terrainMaterial.Load(); this.terrainRoot = (SceneNode)RootSceneNode.CreateChild("TerrainRoot"); this.numTiles = (this.options.worldSize - 1) / (this.options.size - 1); this.tiles = new TerrainRenderable[this.numTiles, this.numTiles]; int p = 0, q = 0; for (int j = 0; j < this.options.worldSize - 1; j += (this.options.size - 1)) { p = 0; for (int i = 0; i < this.options.worldSize - 1; i += (this.options.size - 1)) { this.options.startx = i; this.options.startz = j; string name = string.Format("Tile[{0},{1}]", p, q); var node = (SceneNode)this.terrainRoot.CreateChild(name); var tile = new TerrainRenderable(); tile.Name = name; tile.RenderQueueGroup = WorldGeometryRenderQueueId; tile.SetMaterial(this.terrainMaterial); tile.Init(this.options); this.tiles[p, q] = tile; node.AttachObject(tile); p++; } q++; } int size1 = this.tiles.GetLength(0); int size2 = this.tiles.GetLength(1); for (int j = 0; j < size1; j++) { for (int i = 0; i < size2; i++) { if (j != size1 - 1) { this.tiles[i, j].SetNeighbor(Neighbor.South, this.tiles[i, j + 1]); this.tiles[i, j + 1].SetNeighbor(Neighbor.North, this.tiles[i, j]); } if (i != size2 - 1) { this.tiles[i, j].SetNeighbor(Neighbor.East, this.tiles[i + 1, j]); this.tiles[i + 1, j].SetNeighbor(Neighbor.West, this.tiles[i, j]); } } } if (this.options.isLit) { for (int j = 0; j < size1; j++) { for (int i = 0; i < size2; i++) { this.tiles[i, j].CalculateNormals(); } } } }
public override void LoadWorldGeometry(string fileName) { TerrainOptions options = new TerrainOptions(); DataSet optionData = new DataSet(); optionData.ReadXml(fileName); DataTable table = optionData.Tables[0]; DataRow row = table.Rows[0]; string terrainFileName = ""; string detailTexture = ""; string worldTexture = ""; if (table.Columns["Terrain"] != null) { terrainFileName = (string)row["Terrain"]; } if (table.Columns["DetailTexture"] != null) { detailTexture = (string)row["DetailTexture"]; } if (table.Columns["WorldTexture"] != null) { worldTexture = (string)row["WorldTexture"]; } if (table.Columns["MaxMipMapLevel"] != null) { options.maxMipmap = Convert.ToInt32(row["MaxMipMapLevel"]); } if (table.Columns["DetailTile"] != null) { options.detailTile = Convert.ToInt32(row["DetailTile"]); } if (table.Columns["MaxPixelError"] != null) { options.maxPixelError = Convert.ToInt32(row["MaxPixelError"]); } if (table.Columns["TileSize"] != null) { options.size = Convert.ToInt32(row["TileSize"]); } if (table.Columns["ScaleX"] != null) { options.scalex = StringConverter.ParseFloat((string)row["ScaleX"]); } if (table.Columns["ScaleY"] != null) { options.scaley = StringConverter.ParseFloat((string)row["ScaleY"]); } if (table.Columns["ScaleZ"] != null) { options.scalez = StringConverter.ParseFloat((string)row["ScaleZ"]); } if (table.Columns["VertexNormals"] != null) { options.isLit = ((string)row["VertexNormals"]) == "yes" ? true : false; } scale = new Vector3(options.scalex, options.scaley, options.scalez); tileSize = options.size; // load the heightmap Image image = Image.FromFile(terrainFileName); // TODO: Check terrain size for 2^n + 1 // get the data from the heightmap options.data = image.Data; options.worldSize = image.Width; float maxx = options.scalex * options.worldSize; float maxy = 255 * options.scaley; float maxz = options.scalez * options.worldSize; Resize(new AxisAlignedBox(Vector3.Zero, new Vector3(maxx, maxy, maxz))); terrainMaterial = CreateMaterial("Terrain"); if (worldTexture != "") { terrainMaterial.GetTechnique(0).GetPass(0).CreateTextureUnitState(worldTexture, 0); } if (detailTexture != "") { terrainMaterial.GetTechnique(0).GetPass(0).CreateTextureUnitState(detailTexture, 1); } terrainMaterial.Lighting = options.isLit; terrainMaterial.Load(); terrainRoot = (SceneNode)RootSceneNode.CreateChild("TerrainRoot"); numTiles = (options.worldSize - 1) / (options.size - 1); tiles = new TerrainRenderable[numTiles, numTiles]; int p = 0, q = 0; for (int j = 0; j < options.worldSize - 1; j += (options.size - 1)) { p = 0; for (int i = 0; i < options.worldSize - 1; i += (options.size - 1)) { options.startx = i; options.startz = j; string name = string.Format("Tile[{0},{1}]", p, q); SceneNode node = (SceneNode)terrainRoot.CreateChild(name); TerrainRenderable tile = new TerrainRenderable(); tile.Name = name; tile.SetMaterial(terrainMaterial); tile.Init(options); tiles[p, q] = tile; node.AttachObject(tile); p++; } q++; } int size1 = tiles.GetLength(0); int size2 = tiles.GetLength(1); for (int j = 0; j < size1; j++) { for (int i = 0; i < size2; i++) { if (j != size1 - 1) { ((TerrainRenderable)tiles[i, j]).SetNeighbor(Neighbor.South, (TerrainRenderable)tiles[i, j + 1]); ((TerrainRenderable)tiles[i, j + 1]).SetNeighbor(Neighbor.North, (TerrainRenderable)tiles[i, j]); } if (i != size2 - 1) { ((TerrainRenderable)tiles[i, j]).SetNeighbor(Neighbor.East, (TerrainRenderable)tiles[i + 1, j]); ((TerrainRenderable)tiles[i + 1, j]).SetNeighbor(Neighbor.West, (TerrainRenderable)tiles[i, j]); } } } #if NOT_USED if (false) // && options.isLit) //TODO: Fix { for (int j = 0; j < size1; j++) { for (int i = 0; i < size2; i++) { ((TerrainRenderable)tiles[i, j]).CalculateNormals(); } } } #endif this.terrainOptions = options; //we need these later for GetHeightAt, so make them a member variable }