/// <summary> /// Initializes mesh with new value. /// Unless the heightmap is small, it won't all fit into a single MeshBuffer. /// This function chops it into pieces and generates a buffer from each one. /// </summary> public void Init(VideoDriver driver, HeightMap map, float s, ColorFunc cf) { width = map.Width; height = map.Height; scale = s; if (Mesh.MeshBufferCount > 0) Mesh.RemoveMeshBuffer(0, Mesh.MeshBufferCount); int sw = 0xffff / (height + 1); // maximum vertices per meshbuffer for (int y0 = 0; y0 < height; y0 += sw) { int y1 = y0 + sw; if (y1 >= height) y1 = height - 1; // the last one might be narrower addStrip(map, cf, y0, y1); } Mesh.RecalculateBoundingBox(); }
/// <summary> /// Generates a MeshBuffer which represents all the vertices and indices for values of y /// between y0 and y1, and add it to the mesh. /// </summary> void addStrip(HeightMap map, ColorFunc cf, int y0, int y1) { Vertex3D[] vertices = new Vertex3D[(y1 - y0 + 1) * width]; ushort[] indices = new ushort[(y1 - y0) * (width - 1) * 6]; // "6" is a number of indices in 2 triangles (which forms a quad) // calculate vertices int i = 0; for (int y = y0; y <= y1; ++y) { for (int x = 0; x < width; ++x) { float z = map.GetHeight(x, y); float xf = (float)x / (float)width; float yf = (float)y / (float)height; vertices[i++] = new Vertex3D( new Vector3Df(x, scale * z, y), // position map.GetNormal(x, y, scale), // normal calculate(cf, xf, yf, z), // color new Vector2Df(xf, yf) // tcoords ); } } // calculate indices i = 0; for (int y = y0; y < y1; ++y) { for (int x = 0; x < width - 1; ++x) { int n = (y - y0) * width + x; indices[i++] = (ushort)n; indices[i++] = (ushort)(n + width); indices[i++] = (ushort)(n + width + 1); indices[i++] = (ushort)(n + width + 1); indices[i++] = (ushort)(n + 1); indices[i++] = (ushort)n; } } // append calculated verices and indices to mesh buffer MeshBuffer buf = MeshBuffer.Create(VertexType.Standard, IndexType._16Bit); // create new buffer Mesh.AddMeshBuffer(buf); buf.Append(vertices, indices); buf.RecalculateBoundingBox(); buf.Drop(); }
static void Main(string[] args) { DriverType driverType; if (!AskUserForDriver(out driverType)) return; IrrlichtDevice device = IrrlichtDevice.CreateDevice(driverType, new Dimension2Di(800, 600)); if (device == null) return; device.OnEvent += new IrrlichtDevice.EventHandler(device_OnEvent); device.SetWindowCaption("Mesh handling - Irrlicht Lime"); VideoDriver driver = device.VideoDriver; SceneManager scene = device.SceneManager; // Generate starting height map and mesh HeightMap map = new HeightMap(255, 255); map.Generate(HeightMap.HeightFunc.EggBox); HeightMesh mesh = new HeightMesh(); mesh.Init(driver, map, 50.0f, HeightMesh.ColorFunc.GreyscaleBasedOnTheHeight); // Add the mesh to the scene graph MeshSceneNode meshnode = scene.AddMeshSceneNode(mesh.Mesh); meshnode.SetMaterialFlag(MaterialFlag.BackFaceCulling, false); // Add light (just for nice effects) LightSceneNode lightnode = scene.AddLightSceneNode(null, new Vector3Df(0, 100, 0), new Colorf(1, 1, 1), 500.0f); SceneNodeAnimator anim = scene.CreateFlyCircleAnimator(new Vector3Df(0, 150, 0), 250.0f); lightnode.AddAnimator(anim); anim.Drop(); // Add camera CameraSceneNode camera = scene.AddCameraSceneNodeFPS(); camera.Position = new Vector3Df(-20.0f, 100.0f, -20.0f); camera.Target = new Vector3Df(200.0f, -100.0f, 200.0f); camera.FarValue = 20000.0f; // Main loop while (device.Run()) { if (!device.WindowActive) { device.Sleep(100); continue; } if (IsKeyDown(KeyCode.KeyW)) { meshnode.SetMaterialFlag(MaterialFlag.Wireframe, !meshnode.GetMaterial(0).Wireframe); } else if (IsKeyDown(KeyCode.Key1)) { map.Generate(HeightMap.HeightFunc.EggBox); mesh.Init(driver, map, 50.0f, HeightMesh.ColorFunc.GreyscaleBasedOnTheHeight); } else if (IsKeyDown(KeyCode.Key2)) { map.Generate(HeightMap.HeightFunc.MoreSine); mesh.Init(driver, map, 50.0f, HeightMesh.ColorFunc.CoordinateInterpolation); } else if (IsKeyDown(KeyCode.Key3)) { map.Generate(HeightMap.HeightFunc.JustExp); mesh.Init(driver, map, 50.0f, HeightMesh.ColorFunc.CoordinateInterpolation); } driver.BeginScene(); scene.DrawAll(); driver.EndScene(); } // Clean up mesh.Drop(); device.Drop(); }