/// <summary> /// Build up renderable geometry from input height neighborhood and material map. /// </summary> /// <param name="neighbors"></param> /// <param name="colorMap"></param> /// <returns></returns> public bool MakeGeometry(VirtualMap.HeightMapNeighbors heightNeighbors, VirtualMap.ColorMapNeighbors colorNeighbors) { MakeMinLut(heightNeighbors); bool notEmpty = MakeRenderables(heightNeighbors, colorNeighbors); CheckIndices(heightNeighbors[(int)VirtualMap.HeightMapNeighbors.Dir.Center].Size); return(notEmpty); }
/// <summary> /// Build up renderable geometry for each possible material. Discard empties. /// </summary> /// <param name="neighbors"></param> /// <param name="colorMap"></param> /// <returns></returns> private bool MakeRenderables( VirtualMap.HeightMapNeighbors heightNeighbors, VirtualMap.ColorMapNeighbors colorNeighbors) { var heightMap = heightNeighbors[VirtualMap.HeightMapNeighbors.Dir.Center]; VirtualMap.ColorMap colorMap = colorNeighbors[VirtualMap.ColorMapNeighbors.Dir.Center]; Renderable.PrepareToBuild(heightMap.Size, Min, minLut); //Dispose(); //renderableDict.Clear(); // Reset number of local vertices in each Renderable // since we're about to remake the list. ResetAllVertexCounts(); Vector2 cubeSize = new Vector2( heightMap.Scale.X / (float)heightMap.Size.X, heightMap.Scale.Y / (float)heightMap.Size.Y); Vector2 halfSize = cubeSize * 0.5f; Point vert = new Point(0, 0); for (vert.X = 0; vert.X < heightMap.Size.X; vert.X += 1) { for (vert.Y = 0; vert.Y < heightMap.Size.Y; vert.Y += 1) { float h = heightMap.GetHeightUnsafe(vert.X, vert.Y); if (h != 0) { ushort color = colorMap[vert.X, vert.Y]; //Debug.Assert(TerrainMaterial.IsValid(color, false, true)); if (TerrainMaterial.IsValid(color, false, true)) { Vector3 pos = new Vector3( (float)vert.X * cubeSize.X + halfSize.X, (float)vert.Y * cubeSize.Y + halfSize.Y, h); Renderable r = GetOrMakeRenderable(colorMap[vert.X, vert.Y]); r.AddVertices(pos, halfSize, vert, heightNeighbors, colorNeighbors); } } } } return(FinishGeometry(cubeSize, halfSize)); }
/// <summary> /// Generate the minumum lookup table from the height neighborhood. /// </summary> /// <param name="neighbors"></param> private void MakeMinLut(VirtualMap.HeightMapNeighbors neighbors) { HeightMap heightMap = neighbors[VirtualMap.HeightMapNeighbors.Dir.Center]; if ((minLut == null) || (minLutSize.X != heightMap.Size.X + 1) || (minLutSize.Y != heightMap.Size.Y + 1)) { minLutSize = new Point(heightMap.Size.X + 1, heightMap.Size.Y + 1); minLut = new Vector2[minLutSize.X, minLutSize.Y]; } float absMax = heightMap.Scale.Z; float absMin = 0.0f; for (int j = 0; j < minLutSize.Y; ++j) { for (int i = 0; i < minLutSize.X; ++i) { minLut[i, j].X = absMax; minLut[i, j].Y = absMin; } } Debug.Assert(heightMap.Size.X == heightMap.Size.Y); int lastPix = heightMap.Size.X - 1; int lastLut = lastPix + 1; /// Prime the sides from the neighbors. HeightMap north = neighbors[VirtualMap.HeightMapNeighbors.Dir.North]; if (north != null) { for (int i = 0; i <= lastPix; ++i) { float height = north.GetHeight(i, 0); minLut[i, lastLut].X = Math.Min(minLut[i, lastLut].X, height); minLut[i + 1, lastLut].X = Math.Min(minLut[i + 1, lastLut].X, height); minLut[i, lastLut].Y = Math.Max(minLut[i, lastLut].Y, height); minLut[i + 1, lastLut].Y = Math.Max(minLut[i + 1, lastLut].Y, height); } } else { for (int i = 0; i < minLutSize.X; ++i) { minLut[i, lastLut].X = absMin; minLut[i, lastLut].Y = absMin; } } HeightMap east = neighbors[VirtualMap.HeightMapNeighbors.Dir.East]; if (east != null) { for (int j = 0; j <= lastPix; ++j) { float height = east.GetHeight(0, j); minLut[lastLut, j].X = Math.Min(minLut[lastLut, j].X, height); minLut[lastLut, j + 1].X = Math.Min(minLut[lastLut, j + 1].X, height); minLut[lastLut, j].Y = Math.Max(minLut[lastLut, j].Y, height); minLut[lastLut, j + 1].Y = Math.Max(minLut[lastLut, j + 1].Y, height); } } else { for (int j = 0; j < minLutSize.Y; ++j) { minLut[lastLut, j].X = absMin; minLut[lastLut, j].Y = absMin; } } HeightMap south = neighbors[VirtualMap.HeightMapNeighbors.Dir.South]; if (south != null) { for (int i = 0; i <= lastPix; ++i) { float height = south.GetHeight(i, lastPix); minLut[i, 0].X = Math.Min(minLut[i, 0].X, height); minLut[i + 1, 0].X = Math.Min(minLut[i + 1, 0].X, height); minLut[i, 0].Y = Math.Max(minLut[i, 0].Y, height); minLut[i + 1, 0].Y = Math.Max(minLut[i + 1, 0].Y, height); } } else { for (int i = 0; i < minLutSize.X; ++i) { minLut[i, 0].X = absMin; minLut[i, 0].Y = absMin; } } HeightMap west = neighbors[VirtualMap.HeightMapNeighbors.Dir.West]; if (west != null) { for (int j = 0; j <= lastPix; ++j) { float height = west.GetHeight(lastPix, j); minLut[0, j].X = Math.Min(minLut[0, j].X, height); minLut[0, j + 1].X = Math.Min(minLut[0, j + 1].X, height); minLut[0, j].Y = Math.Max(minLut[0, j].Y, height); minLut[0, j + 1].Y = Math.Max(minLut[0, j + 1].Y, height); } } else { for (int j = 0; j < minLutSize.Y; ++j) { minLut[0, j].X = absMin; minLut[0, j].Y = absMin; } } for (int i = 0; i < heightMap.Size.X; ++i) { for (int j = 0; j < heightMap.Size.Y; ++j) { float height = heightMap.GetHeight(i, j); minLut[i, j].X = Math.Min(minLut[i, j].X, height); minLut[i + 1, j].X = Math.Min(minLut[i + 1, j].X, height); minLut[i, j + 1].X = Math.Min(minLut[i, j + 1].X, height); minLut[i + 1, j + 1].X = Math.Min(minLut[i + 1, j + 1].X, height); minLut[i, j].Y = Math.Max(minLut[i, j].Y, height); minLut[i + 1, j].Y = Math.Max(minLut[i + 1, j].Y, height); minLut[i, j + 1].Y = Math.Max(minLut[i, j + 1].Y, height); minLut[i + 1, j + 1].Y = Math.Max(minLut[i + 1, j + 1].Y, height); } } }