public override void Render() { if (has_vertices()) { //draw triangles Material.AmbientColor = new Color(255, 40, 40, 40); Material.DiffuseColor = new Color(255, 100, 255, 0); Material.SpecularColor = new Color(255, 255, 255, 255); Material.EmissiveColor = new Color(255, 0, 0, 0); Material.Wireframe = false; Material.Lighting = true; Material.BackfaceCulling = false; Material.NormalizeNormals = false; _driver.SetMaterial(Material); _driver.SetTransform(TransformationState.World, AbsoluteTransformation); _driver.DrawMeshBuffer(get_mesh_buffer()); //draw lines Material.Wireframe = true; Material.Lighting = false; Material.BackfaceCulling = false; Material.NormalizeNormals = false; _driver.SetMaterial(Material); _driver.DrawMeshBuffer(get_mesh_buffer()); } }
public void Draw(bool debugDrawGenerator = false) { VideoDriver driver = device.VideoDriver; // draw driver.SetMaterial(cubeMaterial); foreach (GridLayer l in layers) { if (!l.MeshIsReady) { continue; } driver.SetTransform(TransformationState.World, l.Transform); foreach (MeshBuffer mb in l.Mesh.MeshBuffers) { driver.DrawMeshBuffer(mb); } } // draw debug info if (debugDrawGenerator) { foreach (GridLayer l in layers) { if (!l.MeshIsReady) { continue; } if (l.Generation == gridGeneration - 1) { driver.SetMaterial(Material.IdentityRedWireframe); driver.SetTransform(TransformationState.World, l.Transform); Color c = Color.SolidRed; float x1 = -(CubeSize * GridDim) / 2; float z1 = -(CubeSize * GridDim) / 2; float x2 = x1 + (GridDim - 1) * CubeSize; float z2 = z1 + (GridDim - 1) * CubeSize; driver.Draw3DLine(new Line3Df(x1, 0, z1, x2, 0, z1), c); driver.Draw3DLine(new Line3Df(x1, 0, z1, x1, 0, z2), c); driver.Draw3DLine(new Line3Df(x2, 0, z1, x2, 0, z2), c); driver.Draw3DLine(new Line3Df(x1, 0, z2, x2, 0, z2), c); foreach (MeshBuffer mb in l.Mesh.MeshBuffers) { driver.DrawMeshBuffer(mb); } break; } } } }
public void Draw(uint time, Vector3Df cameraPosition) { if (time > nextUpdateAt) { // animation transformation.Rotation = rotationVector * time; // recalculate current LOD currentLOD = meshLODs.Count - 1; float distanceSQ = (transformation.Translation - cameraPosition).LengthSQ; for (int i = 0; i < lodDistanceSQ.Length - 1; i++) { if (distanceSQ < lodDistanceSQ[i]) { currentLOD = i; break; } } // next line assigns new time for LOD to be recalculated in future, // we do not use same value for all LODs here, because we don't want all the LODItems // to be recalculated in the same time (same frame). So we assign a value // which higher when current LOD is higher - which also means that for now we are // a distant object and it is less possible that we will need to change LOD at all; // but close objects (with small LOD value, like 0, 1 or 2) we need to pick quite short time. // This is OK if it will be really short, because these objects are too close and indeed may // change their LOD value very soon, however, we also understand, that in general all the objects // takes very large area, so in general we will have something like less than 2% with LOD level 0, 1 or 2, // all other will get higher LOD, and about more than 50% will have maximum LOD value -- they take more time to recalc // their LOD than to draw them, so we need to calc their LOD less frequent. // p.s.: we also use the fact, that we do not give user ability to reach oposite side of our world in 1 frame, // the speed at which user moves is slow in general. nextUpdateAt = time + updateIntervals[currentLOD]; } // drawing // we do no set material here, because we draw all LODItems with the same material, we set material in main rendering loop driver.SetTransform(TransformationState.World, transformation); // this is also very time consuming operation; we can optimize it // to make something like 100 calls (instead of 5000 - the number of LODItems) - we need to group LODItems all this we increase FPS up on // 10%, BUT it that case we will not be able to move independent LODItems, becase they will not need (and will not have) own transformation // matrix (only LODGroup will has it). So grouping is really greate for some completly static objects like trees, shrubs, stones, etc. // we draw single 16-bit meshbuffer driver.DrawMeshBuffer(meshLODs[currentLOD].GetMeshBuffer(0)); if (LabelPositions != null && currentLOD <= 4) { Vector2Di p = device.SceneManager.SceneCollisionManager.GetScreenCoordinatesFrom3DPosition(transformation.Translation); // now we filter here results which will not be visible; we know that: // - GetScreenCoordinatesFrom3DPosition() returns {-10000,-10000} for behind camera 3d positions // - we do not need to draw out small text if its out of the screen // p.s.: without this filtering we will have about 200-300 labels to draw (instead of about 10-20 which are trully visible) if (p.X > -200 && p.X < screenSize.Width + 200 && p.Y > -100 && p.Y < screenSize.Height + 100) { int t = meshLODs[currentLOD].GetMeshBuffer(0).IndexCount / 3; int d = (int)(transformation.Translation - cameraPosition).Length; LabelPositions.Add(p); LabelTexts.Add( "LOD: " + currentLOD.ToString() + "\nTrinagles: " + t.ToString() + "\nDistance: " + d.ToString()); } } }