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 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(VideoDriver driver) { driver.SetTransform(TransformationState.World, Matrix.Identity); // set material Material m = Material.IdentityNoLighting; m.Wireframe = true; m.BackfaceCulling = false; m.Type = MaterialType.TransparentVertexAlpha; m.ZWrite = false; // draw back lines m.ZBuffer = ComparisonFunc.Greater; driver.SetMaterial(m); driver.DrawVertexPrimitiveList(vertBack, indBoth, PrimitiveType.Lines); // draw front lines m.ZBuffer = ComparisonFunc.LessEqual; driver.SetMaterial(m); driver.DrawVertexPrimitiveList(vertFront, indBoth, PrimitiveType.Lines); // draw front points m.Thickness = 10; driver.SetMaterial(m); driver.DrawVertexPrimitiveList(vertFront, indBoth, PrimitiveType.Points); }
void CSampleSceneNode_OnRender() { ushort[] indices = new ushort[] { 0, 2, 3, 2, 1, 3, 1, 0, 3, 2, 0, 1 }; VideoDriver driver = SceneManager.VideoDriver; driver.SetMaterial(material); driver.SetTransform(TransformationState.World, AbsoluteTransformation); driver.DrawVertexPrimitiveList(vertices, indices); }
public void DrawShadowVolume(VideoDriver driver, bool isDebug = false) { lock (visibleShadowVerticesBufferLocker) { if (visibleShadowVerticesBuffer == null || visibleShadowVerticesBuffer.Count == 0) { return; } driver.SetTransform(TransformationState.World, Matrix.Identity); if (isDebug) { Material material = new Material(); material.Lighting = false; material.Type = MaterialType.TransparentVertexAlpha; driver.SetMaterial(material); for (int i = 0; i < visibleShadowVerticesBuffer.Count; i += 3) { driver.Draw3DTriangle( visibleShadowVerticesBuffer[i], visibleShadowVerticesBuffer[i + 1], visibleShadowVerticesBuffer[i + 2], new Color(0x80000000)); } material.Wireframe = true; material.BackfaceCulling = false; material.ZBuffer = ComparisonFunc.Always; driver.SetMaterial(material); for (int i = 0; i < visibleShadowVerticesBuffer.Count; i += 3) { driver.Draw3DTriangle( visibleShadowVerticesBuffer[i], visibleShadowVerticesBuffer[i + 1], visibleShadowVerticesBuffer[i + 2], new Color(0x80ff0000)); } } else { driver.DrawStencilShadowVolume(visibleShadowVerticesBuffer); driver.DrawStencilShadow(false, shadowColor); } } }
public void DrawShadowVolume(VideoDriver driver, bool isDebug = false) { lock (visibleShadowVerticesBufferLocker) { if (visibleShadowVerticesBuffer == null || visibleShadowVerticesBuffer.Count == 0) return; driver.SetTransform(TransformationState.World, Matrix.Identity); if (isDebug) { Material material = new Material(); material.Lighting = false; material.Type = MaterialType.TransparentVertexAlpha; driver.SetMaterial(material); for (int i = 0; i < visibleShadowVerticesBuffer.Count; i += 3) driver.Draw3DTriangle( visibleShadowVerticesBuffer[i], visibleShadowVerticesBuffer[i + 1], visibleShadowVerticesBuffer[i + 2], new Color(0x80000000)); material.Wireframe = true; material.BackfaceCulling = false; material.ZBuffer = ComparisonFunc.Always; driver.SetMaterial(material); for (int i = 0; i < visibleShadowVerticesBuffer.Count; i += 3) driver.Draw3DTriangle( visibleShadowVerticesBuffer[i], visibleShadowVerticesBuffer[i + 1], visibleShadowVerticesBuffer[i + 2], new Color(0x80ff0000)); } else { driver.DrawStencilShadowVolume(visibleShadowVerticesBuffer); driver.DrawStencilShadow(false, shadowColor); } } }
private void backgroundRendering_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; //DeviceSettings settings = e.Argument as DeviceSettings; // create irrlicht device using provided settings if (panelRenderWindow.IsDisposed) { throw new Exception("Form closed!"); } DeviceSettings s = new DeviceSettings( IntPtr.Zero, DriverType.Direct3D9, 0, //antialias new Color(100, 101, 140), false); if (panelRenderWindow.InvokeRequired) { panelRenderWindow.Invoke(new MethodInvoker(delegate { s.WindowID = panelRenderWindow.Handle; })); } dev = IrrlichtDevice.CreateDevice(s); if (dev == null) { throw new NullReferenceException("Could not create device for engine!"); } dev.OnEvent += new IrrlichtDevice.EventHandler(this.device_OnEvent); dev.Logger.LogLevel = LogLevel.Warning; drv = dev.VideoDriver; smgr = dev.SceneManager; gui = dev.GUIEnvironment; _ = smgr.FileSystem.AddFileArchive(activeMod.FileDirectory); smgr.Attributes.AddValue("TW_TW3_LOAD_SKEL", true); smgr.Attributes.AddValue("TW_TW3_LOAD_BEST_LOD_ONLY", true); // added by vl if (meshFile != null && meshFile.Length > 0) { mesh = smgr.GetMesh(meshFile); } if (mesh == null) { throw new Exception("Failed to load mesh."); } mesh.Grab(); smgr.MeshManipulator.RecalculateNormals(mesh); meshLoaded = true; float scaleMul = 1.0f; node = smgr.AddAnimatedMeshSceneNode(mesh); helper = smgr.GetMeshLoader(smgr.MeshLoaderCount - 1).getMeshLoaderHelper(); // hacked to gat witcher3 loader if (node != null && meshLoaded) { node.Scale = new Vector3Df(3.0f); node.SetMaterialFlag(MaterialFlag.Lighting, false); scaleMul = node.BoundingBox.Radius / 4; if (!string.IsNullOrEmpty(rigFile)) { meshToAnimate = helper.loadRig(rigFile, mesh); if (meshToAnimate == null) { throw new Exception("Failed to load rig."); } else { meshToAnimate.Grab(); rigLoaded = true; Logger.LogString("Rig loaded!", Logtype.Success); node.Mesh = meshToAnimate; } } if (!string.IsNullOrEmpty(animFile) && rigLoaded) { animList = helper.loadAnimation(animFile, meshToAnimate); if (animList.Count > 0) { animLoaded = true; Logger.LogString($"{animList.Count} animations loaded! Select animation to play", Logtype.Success); } else { Logger.LogString("No animations loaded!", Logtype.Important); } } setMaterialsSettings(node); } var camera = smgr.AddCameraSceneNode(null, new Vector3Df(node.BoundingBox.Radius * 8, node.BoundingBox.Radius, 0), new Vector3Df(0, node.BoundingBox.Radius, 0)); camera.NearValue = 0.001f; camera.FOV = 45.0f * 3.14f / 180.0f; var animText = activeAnim; var mAnimText = gui.AddStaticText(animText, new Recti(0, this.ClientSize.Height - 80, 100, this.ClientSize.Height - 70)); var mPositionText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 70, 100, this.ClientSize.Height - 60)); var mRotationText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 60, 100, this.ClientSize.Height - 50)); var fpsText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 50, 100, this.ClientSize.Height - 40)); var infoText = gui.AddStaticText("[Space] - Reset\n[LMouse] - Rotate\n[MMouse] - Move\n[Wheel] - Zoom", new Recti(0, this.ClientSize.Height - 40, 100, this.ClientSize.Height)); mAnimText.OverrideColor = mPositionText.OverrideColor = mRotationText.OverrideColor = fpsText.OverrideColor = infoText.OverrideColor = new Color(255, 255, 255); mAnimText.BackgroundColor = mPositionText.BackgroundColor = mRotationText.BackgroundColor = fpsText.BackgroundColor = infoText.BackgroundColor = new Color(0, 0, 0); viewPort = drv.ViewPort; var lineMat = new Material { Lighting = false }; while (dev.Run()) { drv.ViewPort = viewPort; drv.BeginScene(ClearBufferFlag.Depth | ClearBufferFlag.Color, s.BackColor); node.Position = modelPosition; node.Rotation = modelAngle; //update info box mPositionText.Text = $"X: {modelPosition.X.ToString("F2")} Y: {modelPosition.Y.ToString("F2")} Z: {modelPosition.Z.ToString("F2")}"; mRotationText.Text = $"Yaw: {modelAngle.Y.ToString("F2")} Roll: {modelAngle.Z.ToString("F2")}"; fpsText.Text = $"FPS: {drv.FPS}"; smgr.DrawAll(); gui.DrawAll(); // draw xyz axis right bottom drv.ViewPort = new Recti(this.ClientSize.Width - 100, this.ClientSize.Height - 80, this.ClientSize.Width, this.ClientSize.Height); drv.SetMaterial(lineMat); var matrix = new Matrix(new Vector3Df(0, 0, 0), modelAngle); drv.SetTransform(TransformationState.World, matrix); matrix = matrix.BuildProjectionMatrixOrthoLH(100, 80, camera.NearValue, camera.FarValue); drv.SetTransform(TransformationState.Projection, matrix); matrix = matrix.BuildCameraLookAtMatrixLH(new Vector3Df(50, 0, 0), new Vector3Df(0, 0, 0), new Vector3Df(0, 1f, 0)); drv.SetTransform(TransformationState.View, matrix); drv.Draw3DLine(0, 0, 0, 30f, 0, 0, Color.SolidGreen); drv.Draw3DLine(0, 0, 0, 0, 30f, 0, Color.SolidBlue); drv.Draw3DLine(0, 0, 0, 0, 0, 30f, Color.SolidRed); drv.EndScene(); // if we requested to stop, we close the device if (worker.CancellationPending) { dev.Close(); } } // drop device dev.Drop(); }
static void Main() { DriverType?driverType = AskForDriver(); if (!driverType.HasValue) { return; } IrrlichtDevice device = IrrlichtDevice.CreateDevice(driverType.Value, new Dimension2Di(640, 480)); if (device == null) { return; } VideoDriver driver = device.VideoDriver; SceneManager smgr = device.SceneManager; device.FileSystem.AddFileArchive("../../media/map-20kdm2.pk3"); AnimatedMesh q3levelmesh = smgr.GetMesh("20kdm2.bsp"); MeshSceneNode q3node = null; // The Quake mesh is pickable, but doesn't get highlighted. if (q3levelmesh != null) { q3node = smgr.AddOctreeSceneNode(q3levelmesh.GetMesh(0), null, IDFlag_IsPickable); } TriangleSelector selector = null; if (q3node != null) { q3node.Position = new Vector3Df(-1350, -130, -1400); selector = smgr.CreateOctreeTriangleSelector(q3node.Mesh, q3node, 128); q3node.TriangleSelector = selector; // We're not done with this selector yet, so don't drop it. } // Set a jump speed of 3 units per second, which gives a fairly realistic jump // when used with the gravity of (0, -1000, 0) in the collision response animator. CameraSceneNode camera = smgr.AddCameraSceneNodeFPS(null, 100.0f, 0.3f, ID_IsNotPickable, null, true, 3.0f); camera.Position = new Vector3Df(50, 50, -60); camera.Target = new Vector3Df(-70, 30, -60); if (selector != null) { SceneNodeAnimator anim = smgr.CreateCollisionResponseAnimator( selector, camera, new Vector3Df(30, 50, 30), new Vector3Df(0, -1000, 0), new Vector3Df(0, 30, 0)); selector.Drop(); // As soon as we're done with the selector, drop it. camera.AddAnimator(anim); anim.Drop(); // And likewise, drop the animator when we're done referring to it. } // Now I create three animated characters which we can pick, a dynamic light for // lighting them, and a billboard for drawing where we found an intersection. // First, let's get rid of the mouse cursor. We'll use a billboard to show what we're looking at. device.CursorControl.Visible = false; // Add the billboard. BillboardSceneNode bill = smgr.AddBillboardSceneNode(); bill.SetMaterialType(MaterialType.TransparentAddColor); bill.SetMaterialTexture(0, driver.GetTexture("../../media/particle.bmp")); bill.SetMaterialFlag(MaterialFlag.Lighting, false); bill.SetMaterialFlag(MaterialFlag.ZBuffer, false); bill.SetSize(20, 20, 20); bill.ID = ID_IsNotPickable; // This ensures that we don't accidentally ray-pick it AnimatedMeshSceneNode node = null; // Add an MD2 node, which uses vertex-based animation. node = smgr.AddAnimatedMeshSceneNode(smgr.GetMesh("../../media/faerie.md2"), null, IDFlag_IsPickable | IDFlag_IsHighlightable); node.Position = new Vector3Df(-90, -15, -140); // Put its feet on the floor. node.Scale = new Vector3Df(1.6f); // Make it appear realistically scaled node.SetMD2Animation(AnimationTypeMD2.Point); node.AnimationSpeed = 20.0f; node.GetMaterial(0).SetTexture(0, driver.GetTexture("../../media/faerie2.bmp")); node.GetMaterial(0).Lighting = true; node.GetMaterial(0).NormalizeNormals = true; // Now create a triangle selector for it. The selector will know that it // is associated with an animated node, and will update itself as necessary. selector = smgr.CreateTriangleSelector(node); node.TriangleSelector = selector; selector.Drop(); // We're done with this selector, so drop it now. // And this B3D file uses skinned skeletal animation. node = smgr.AddAnimatedMeshSceneNode(smgr.GetMesh("../../media/ninja.b3d"), null, IDFlag_IsPickable | IDFlag_IsHighlightable); node.Scale = new Vector3Df(10); node.Position = new Vector3Df(-75, -66, -80); node.Rotation = new Vector3Df(0, 90, 0); node.AnimationSpeed = 8.0f; node.GetMaterial(0).NormalizeNormals = true; // Just do the same as we did above. selector = smgr.CreateTriangleSelector(node); node.TriangleSelector = selector; selector.Drop(); // This X files uses skeletal animation, but without skinning. node = smgr.AddAnimatedMeshSceneNode(smgr.GetMesh("../../media/dwarf.x"), null, IDFlag_IsPickable | IDFlag_IsHighlightable); node.Position = new Vector3Df(-70, -66, -30); // Put its feet on the floor. node.Rotation = new Vector3Df(0, -90, 0); // And turn it towards the camera. node.AnimationSpeed = 20.0f; selector = smgr.CreateTriangleSelector(node); node.TriangleSelector = selector; selector.Drop(); // And this mdl file uses skinned skeletal animation. node = smgr.AddAnimatedMeshSceneNode(smgr.GetMesh("../../media/yodan.mdl"), null, IDFlag_IsPickable | IDFlag_IsHighlightable); node.Position = new Vector3Df(-90, -25, 20); node.Scale = new Vector3Df(0.8f); node.GetMaterial(0).Lighting = true; node.AnimationSpeed = 20.0f; // Just do the same as we did above. selector = smgr.CreateTriangleSelector(node); node.TriangleSelector = selector; selector.Drop(); // Add a light, so that the unselected nodes aren't completely dark. LightSceneNode light = smgr.AddLightSceneNode(null, new Vector3Df(-60, 100, 400), new Colorf(1.0f, 1.0f, 1.0f), 600.0f); light.ID = ID_IsNotPickable; // Make it an invalid target for selection. // Remember which scene node is highlighted SceneNode highlightedSceneNode = null; SceneCollisionManager collMan = smgr.SceneCollisionManager; int lastFPS = -1; // draw the selection triangle only as wireframe Material material = new Material(); material.Lighting = false; material.Wireframe = true; while (device.Run()) { if (device.WindowActive) { driver.BeginScene(ClearBufferFlag.All, new Color(0)); smgr.DrawAll(); // Unlight any currently highlighted scene node if (highlightedSceneNode != null) { highlightedSceneNode.SetMaterialFlag(MaterialFlag.Lighting, true); highlightedSceneNode = null; } // All intersections in this example are done with a ray cast out from the camera to // a distance of 1000. You can easily modify this to check (e.g.) a bullet // trajectory or a sword's position, or create a ray from a mouse click position using // collMan.GetRayFromScreenCoordinates() Line3Df ray = new Line3Df(); ray.Start = camera.Position; ray.End = ray.Start + (camera.Target - ray.Start).Normalize() * 1000.0f; // This call is all you need to perform ray/triangle collision on every scene node // that has a triangle selector, including the Quake level mesh. It finds the nearest // collision point/triangle, and returns the scene node containing that point. // Irrlicht provides other types of selection, including ray/triangle selector, // ray/box and ellipse/triangle selector, plus associated helpers. // See the methods of ISceneCollisionManager SceneNode selectedSceneNode = collMan.GetSceneNodeAndCollisionPointFromRay( ray, out Vector3Df intersection, // This will be the position of the collision out Triangle3Df hitTriangle, // This will be the triangle hit in the collision IDFlag_IsPickable); // This ensures that only nodes that we have set up to be pickable are considered // If the ray hit anything, move the billboard to the collision position // and draw the triangle that was hit. if (selectedSceneNode != null) { bill.Position = intersection; // We need to reset the transform before doing our own rendering. driver.SetTransform(TransformationState.World, Matrix.Identity); driver.SetMaterial(material); driver.Draw3DTriangle(hitTriangle, new Color(255, 0, 0)); // We can check the flags for the scene node that was hit to see if it should be // highlighted. The animated nodes can be highlighted, but not the Quake level mesh if ((selectedSceneNode.ID & IDFlag_IsHighlightable) == IDFlag_IsHighlightable) { highlightedSceneNode = selectedSceneNode; // Highlighting in this case means turning lighting OFF for this node, // which means that it will be drawn with full brightness. highlightedSceneNode.SetMaterialFlag(MaterialFlag.Lighting, false); } } // We're all done drawing, so end the scene. driver.EndScene(); int fps = driver.FPS; if (lastFPS != fps) { device.SetWindowCaption(String.Format( "Collision detection example - Irrlicht Engine [{0}] fps: {1}", driver.Name, fps)); lastFPS = fps; } } } device.Drop(); }
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()); } } }
/// <summary> /// The irrlicht thread for rendering. /// </summary> private void StartIrr() { try { IrrlichtCreationParameters irrparam = new IrrlichtCreationParameters(); if (irrlichtPanel.IsDisposed) { throw new Exception("Form closed!"); } if (irrlichtPanel.InvokeRequired) { irrlichtPanel.Invoke(new MethodInvoker(delegate { irrparam.WindowID = irrlichtPanel.Handle; })); } irrparam.DriverType = DriverType.Direct3D9; irrparam.BitsPerPixel = 16; device = IrrlichtDevice.CreateDevice(irrparam); if (device == null) { throw new NullReferenceException("Could not create device for engine!"); } driver = device.VideoDriver; smgr = device.SceneManager; gui = device.GUIEnvironment; var animText = ""; if (Animations.AnimationNames.Count > 0) { animText = "Animation: " + Animations.AnimationNames[selectedAnimIdx].Key; } var mAnimText = gui.AddStaticText(animText, new Recti(0, this.ClientSize.Height - 80, 100, this.ClientSize.Height - 70)); var mPositionText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 70, 100, this.ClientSize.Height - 60)); var mRotationText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 60, 100, this.ClientSize.Height - 50)); var fpsText = gui.AddStaticText("", new Recti(0, this.ClientSize.Height - 50, 100, this.ClientSize.Height - 40)); var infoText = gui.AddStaticText("[Space] - Reset\n[LMouse] - Rotate\n[MMouse] - Move\n[Wheel] - Zoom", new Recti(0, this.ClientSize.Height - 40, 100, this.ClientSize.Height)); mAnimText.OverrideColor = mPositionText.OverrideColor = mRotationText.OverrideColor = fpsText.OverrideColor = infoText.OverrideColor = new Color(255, 255, 255); mAnimText.BackgroundColor = mPositionText.BackgroundColor = mRotationText.BackgroundColor = fpsText.BackgroundColor = infoText.BackgroundColor = new Color(0, 0, 0); SkinnedMesh skinnedMesh = smgr.CreateSkinnedMesh(); foreach (var meshBuffer in cdata.staticMesh.MeshBuffers) { skinnedMesh.AddMeshBuffer(meshBuffer); } smgr.MeshManipulator.RecalculateNormals(skinnedMesh); if (RigFile != null) { rig.Apply(skinnedMesh); if (AnimFile != null) { anims.Apply(skinnedMesh); } } skinnedMesh.SetDirty(HardwareBufferType.VertexAndIndex); skinnedMesh.FinalizeMeshPopulation(); AnimatedMeshSceneNode node = smgr.AddAnimatedMeshSceneNode(skinnedMesh); if (node == null) { throw new Exception("Could not load file!"); } node.Scale = new Vector3Df(3.0f); node.SetMaterialFlag(MaterialFlag.Lighting, false); SetMaterials(driver, node); CameraSceneNode camera = smgr.AddCameraSceneNode(null, new Vector3Df(node.BoundingBox.Radius * 8, node.BoundingBox.Radius, 0), new Vector3Df(0, node.BoundingBox.Radius, 0)); camera.NearValue = 0.001f; camera.FOV = 45 * CommonData.PI_OVER_180; scaleMul = node.BoundingBox.Radius / 4; var viewPort = driver.ViewPort; var lineMat = new Material(); lineMat.Lighting = false; while (device.Run()) { driver.ViewPort = viewPort; driver.BeginScene(ClearBufferFlag.All, new Color(100, 101, 140)); node.Position = modelPosition; node.Rotation = modelAngle; node.DebugDataVisible = DebugSceneType.Skeleton | DebugSceneType.BBox; mPositionText.Text = $"X: {modelPosition.X.ToString("F2")} Y: {modelPosition.Y.ToString("F2")} Z: {modelPosition.Z.ToString("F2")}"; mRotationText.Text = $"Yaw: {modelAngle.Y.ToString("F2")} Roll: {modelAngle.Z.ToString("F2")}"; fpsText.Text = $"FPS: {driver.FPS}"; smgr.DrawAll(); gui.DrawAll(); driver.ViewPort = new Recti(this.ClientSize.Width - 100, this.ClientSize.Height - 80, this.ClientSize.Width, this.ClientSize.Height); //driver.ClearBuffers(ClearBufferFlag.None); driver.SetMaterial(lineMat); var matrix = new Matrix(new Vector3Df(0, 0, 0), modelAngle); driver.SetTransform(TransformationState.World, matrix); matrix = matrix.BuildProjectionMatrixOrthoLH(100, 80, camera.NearValue, camera.FarValue); driver.SetTransform(TransformationState.Projection, matrix); matrix = matrix.BuildCameraLookAtMatrixLH(new Vector3Df(50, 0, 0), new Vector3Df(0, 0, 0), new Vector3Df(0, 1f, 0)); driver.SetTransform(TransformationState.View, matrix); driver.Draw3DLine(0, 0, 0, 30f, 0, 0, Color.OpaqueGreen); driver.Draw3DLine(0, 0, 0, 0, 30f, 0, Color.OpaqueBlue); driver.Draw3DLine(0, 0, 0, 0, 0, 30f, Color.OpaqueRed); driver.EndScene(); } device.Drop(); } catch (ThreadAbortException) { } catch (NullReferenceException) { } catch (Exception ex) { if (!this.IsDisposed) { MessageBox.Show(ex.Message); //this.Invoke(new MethodInvoker(delegate { this.Close(); })); } } }
/// <summary> /// The irrlicht thread for rendering. /// </summary> private void StartIrr() { #if DEBUG try #endif { float DEGREES_TO_RADIANS = (float)(Math.PI / 180.0); //Setup IrrlichtCreationParameters irrparam = new IrrlichtCreationParameters(); if (irrlichtPanel.IsDisposed) { throw new Exception("Form closed!"); } if (irrlichtPanel.InvokeRequired) { irrlichtPanel.Invoke(new MethodInvoker(delegate { irrparam.WindowID = irrlichtPanel.Handle; })); } irrparam.DriverType = DriverType.Direct3D9; irrparam.BitsPerPixel = 32; irrparam.AntiAliasing = 1; device = IrrlichtDevice.CreateDevice(irrparam); if (device == null) { throw new NullReferenceException("Could not create device for engine!"); } driver = device.VideoDriver; smgr = SceneManagerWolvenKit.Create(device); gui = device.GUIEnvironment; smgr.Attributes.SetValue("TW_TW3_TEX_PATH", depot); driver.SetTextureCreationFlag(TextureCreationFlag.Always32Bit, true); lightNode = smgr.AddLightSceneNode(null, new Vector3Df(0, 0, 0), new Colorf(1.0f, 1.0f, 1.0f), 200000.0f); smgr.AmbientLight = new Colorf(1.0f, 1.0f, 1.0f); worldNode = smgr.AddEmptySceneNode(); //NOTE: Witcher assets use Z up but Irrlicht uses Y up so rotate the model worldNode.Rotation = new Vector3Df(-90, 0, 0); //NOTE: We also need to flip the x-coordinate with this rotation worldNode.Scale = new Vector3Df(-1.0f, 1.0f, 1.0f); worldNode.Visible = true; var dome = smgr.AddSkyDomeSceneNode(driver.GetTexture("Terrain\\skydome.jpg"), 16, 8, 0.95f, 2.0f); dome.Visible = true; fpsText = gui.AddStaticText("FPS: 0", new Recti(2, 10, 200, 30), false, false, null, 1, false); fpsText.OverrideColor = IrrlichtLime.Video.Color.SolidRed; fpsText.OverrideFont = gui.GetFont("#DefaultWKFont"); vertexCountText = gui.AddStaticText("Vertices: " + totalVertexCount.ToString(), new Recti(2, 32, 300, 52), false, false, null, 1, false); vertexCountText.OverrideColor = IrrlichtLime.Video.Color.SolidRed; vertexCountText.OverrideFont = gui.GetFont("#DefaultWKFont"); meshCountText = gui.AddStaticText("Meshes: " + totalMeshCount.ToString(), new Recti(2, 54, 300, 74), false, false, null, 1, false); meshCountText.OverrideColor = IrrlichtLime.Video.Color.SolidRed; meshCountText.OverrideFont = gui.GetFont("#DefaultWKFont"); var camera = smgr.AddCameraSceneNodeWolvenKit(); camera.FarValue = 10000.0f; //distanceBar.Invoke((MethodInvoker)delegate //{ // camera.FarValue = (float)Math.Pow(10.0, (double)distanceBar.Value); //}); viewPort = driver.ViewPort; var lineMat = new IrrlichtLime.Video.Material { Lighting = false }; var WMatrix = new Matrix(new Vector3Df(0, 0, 0), smgr.ActiveCamera.ModelRotation); var PMatrix = new Matrix(); PMatrix = PMatrix.BuildProjectionMatrixOrthoLH(100, 80, 0.001f, 10000.0f); var VMatrix = new Matrix(); VMatrix = VMatrix.BuildCameraLookAtMatrixLH(new Vector3Df(50, 0, 0), new Vector3Df(0, 0, 0), new Vector3Df(0, 1f, 0)); int gizmoX = (int)(irrlichtPanel.Width * 0.92f); int gizmoY = (int)(irrlichtPanel.Height * 0.92f); var gizmoViewPort = new Recti(gizmoX, gizmoY, irrlichtPanel.Width, irrlichtPanel.Height); while (device.Run()) { if (this.Visible) { ProcessCommand(); driver.BeginScene(ClearBufferFlag.All); int val = driver.FPS; fpsText.Text = "FPS: " + val.ToString(); smgr.DrawAll(); gui.DrawAll(); // draw xyz axis right bottom driver.ViewPort = gizmoViewPort; driver.SetMaterial(lineMat); WMatrix.SetRotationRadians(smgr.ActiveCamera.ModelRotation * DEGREES_TO_RADIANS); driver.SetTransform(TransformationState.World, WMatrix); driver.SetTransform(TransformationState.Projection, PMatrix); driver.SetTransform(TransformationState.View, VMatrix); driver.Draw3DLine(0, 0, 0, 30f, 0, 0, IrrlichtLime.Video.Color.SolidGreen); driver.Draw3DLine(0, 0, 0, 0, 30f, 0, IrrlichtLime.Video.Color.SolidBlue); driver.Draw3DLine(0, 0, 0, 0, 0, 30f, IrrlichtLime.Video.Color.SolidRed); driver.ViewPort = viewPort; driver.EndScene(); } else { device.Yield(); } } } #if DEBUG catch (ThreadAbortException) { } catch (NullReferenceException) { } catch (Exception ex) { if (!this.IsDisposed) { MessageBox.Show(ex.Message); //this.Invoke(new MethodInvoker(delegate { this.Close(); })); } } #endif }