static Terrain() { // Create the array of render batches for (int i = 0; i < NUMTEXTURES; i++) { batch[i] = new RenderBatch(20); } // Load the height map using (Bitmap bmp = (Bitmap)Bitmap.FromFile(FileResource.Fsp("terrain", "terrainheight.bmp"))) { // compute scale gridWidth = bmp.Width-1; // the grid of tiles will be 1 smaller than gridHeight = bmp.Height-1; // the grid of heights (last height = RH side of last tile) tileWidth = (float)Map.MapWidth / gridWidth; tileHeight = (float)Map.MapHeight / gridHeight; // Create the blank tiles tile = new Terrain[gridWidth,gridHeight]; // get heightmap into an array, for faster access // (Note: bitmap's origin is at TOP-left, so flip Y. Tile grid's origin is bottom-left) height = new float[bmp.Width,bmp.Height]; for (int y = 0; y<bmp.Height; y++) { for (int x=0; x<bmp.Width; x++) { height[x,y] = (float)bmp.GetPixel(x, bmp.Height-1-y).R * MAXHEIGHT / 256; } } } // dispose of the bitmap // Create the tiles and define their extents and heights for (int y = 0; y<gridHeight; y++) { for (int x=0; x<gridWidth; x++) { tile[x,y] = new Terrain(x,y,tileWidth,tileHeight,ref height); } } // Now that the triangles exist, define the vertex normals, by averaging the // surface normals of surrounding triangles for (int y = 1; y<gridHeight-1; y++) { for (int x=1; x<gridWidth-1; x++) { SetVertexNormal(tile,x,y); } } /// TODO: Load the texture map here & set the tiles' texture #s using (Bitmap bmp = (Bitmap)Bitmap.FromFile(FileResource.Fsp("terrain", "terraintex.bmp"))) { for (int y = 0; y<gridHeight; y++) { for (int x=0; x<gridWidth; x++) { tile[x,y].texture = (int)((float)bmp.GetPixel(x,bmp.Height-1-y).R / 256.0f * NUMTEXTURES); } } } // Define a material for lighting the textures // (May want different materials for each texture later?) material.Ambient = Color.FromArgb(64,64,64); material.Diffuse = Color.FromArgb(255, 255, 255); material.Specular = Color.FromArgb(90, 90, 90); }
/// <summary> /// Set the vertex normals for the triangles in this tile. /// Each vertex normal is the average of the face normals for surrounding triangles /// (some of which are in different tiles) /// </summary> /// <param name="tile">the array of tiles</param> /// <param name="x">our location in the array</param> /// <param name="y"></param> public static void SetVertexNormal(Terrain[,] tile, int x, int y) { // NW vertex tile[x,y].mesh[0].Normal = Vector3.Normalize( tile[x-1,y+1].faceNormal[1] + tile[x,y+1].faceNormal[0] + tile[x,y+1].faceNormal[1] + tile[x,y].faceNormal[0] + tile[x-1,y].faceNormal[1] + tile[x-1,y].faceNormal[0] ); // NE vertex tile[x,y].mesh[1].Normal = Vector3.Normalize( tile[x,y+1].faceNormal[1] + tile[x+1,y+1].faceNormal[0] + tile[x+1,y+1].faceNormal[1] + tile[x+1,y].faceNormal[0] + tile[x,y].faceNormal[1] + tile[x,y].faceNormal[0] ); // SW vertex tile[x,y].mesh[2].Normal = Vector3.Normalize( tile[x-1,y].faceNormal[1] + tile[x,y].faceNormal[0] + tile[x,y].faceNormal[1] + tile[x,y-1].faceNormal[0] + tile[x-1,y-1].faceNormal[1] + tile[x-1,y-1].faceNormal[0] ); // SE vertex tile[x,y].mesh[3].Normal = Vector3.Normalize( tile[x,y].faceNormal[1] + tile[x+1,y].faceNormal[0] + tile[x+1,y].faceNormal[1] + tile[x+1,y-1].faceNormal[0] + tile[x,y-1].faceNormal[1] + tile[x,y-1].faceNormal[0] ); // Add tangent and binormal vectors calculated from vertex normals for (int i = 0; i < 4; i++) { ThreeDee.TangentFromNormal(tile[x, y].mesh[i].Normal, out tile[x, y].mesh[i].Tangent, out tile[x, y].mesh[i].Binormal); } }