// Copyright (C) 2002-2005 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // please note: This program is just a program to test out the features // of the irrlicht.net port. If you are looking for examples using Irrlicht.NET // please take a look into the examples.net directory. using System; using Irrlicht; using Irrlicht.Video; using Irrlicht.Core; using Irrlicht.Scene; using Irrlicht.GUI; enum TestScenarios { NONE = 0, TERRAIN_TEST, INDOOR_TEST, WINDOWS_FORMS_TEST, SHADER_TEST }; /// /// Example application using Irrlicht.NET /// class ExampleApp : IEventReceiver, IShaderConstantSetCallBack { /// /// The main entry point for the application. /// [STAThread] static void Main(string[] args) { ExampleApp ea = new ExampleApp(); ea.displayMainMenu(); switch(ea.ClickedButton) { case TestScenarios.TERRAIN_TEST: ea.runTerrainTest(); break; case TestScenarios.INDOOR_TEST: ea.runIndoorTest(); break; case TestScenarios.WINDOWS_FORMS_TEST: ea.runIrrlichtInWindowsFormTest(); break; case TestScenarios.SHADER_TEST: ea.runShaderTest(); break; } } /// /// Receives events (like input from mouse and keyboard) from the Irrlicht Engine /// public bool OnEvent(Event e) { if (e.Type == EventType.GUIEvent) { // a user interface event if ( e.GUIEventType == GUIEvent.LISTBOX_CHANGED || e.GUIEventType == GUIEvent.LISTBOX_SELECTED_AGAIN ) { int selected = ((IGUIListBox)e.GUIEventCaller).Selected; SelectedDriverType = (DriverType)(selected+1); } else if (e.GUIEventType == GUIEvent.BUTTON_CLICKED) ClickedButton = (TestScenarios)e.GUIEventCaller.ID; } else if (e.Type == EventType.KeyInput) { // a key has been pressed if (!e.KeyPressedDown && e.Key == KeyCode.KEY_KEY_S && Shadow != null) { // toggle shadow visibility Shadow.Visible = !Shadow.Visible; return true; } } return false; } public void displayMainMenu() { device = new IrrlichtDevice(DriverType.SOFTWARE, new Dimension2D(512, 384), 16, false, false, false); // set event receiver device.EventReceiver = this; // set text device.WindowCaption = "Irrlicht .NET test demos - main menu"; // load font IGUIFont font = device.GUIEnvironment.GetFont("../../media/fonthaettenschweiler.bmp"); if (font != null) device.GUIEnvironment.Skin.Font = font; // add images device.GUIEnvironment.AddImage( device.VideoDriver.GetTexture("../../media/dotnetback.jpg"), new Position2D(0,0), false, null, -1, ""); // add list box Rect pos = new Rect(150,60,350,135); IGUIListBox box = device.GUIEnvironment.AddListBox( pos, null, -1, true ); box.AddItem("Irrlicht Software Renderer 1.0"); box.AddItem("Apfelbaum Software Renderer 1.0"); box.AddItem("Direct3D 8.1"); box.AddItem("Direct3D 9.0c"); box.AddItem("OpenGL 1.5"); box.Selected = ((int)SelectedDriverType)-1; // add terrain button pos.LowerRightCorner.Y += 50; pos.UpperLeftCorner.Y += 100; device.GUIEnvironment.AddButton( pos, null, (int)TestScenarios.TERRAIN_TEST, "Start Terrain Test" ); // add indoor button pos.LowerRightCorner.Y += 30; pos.UpperLeftCorner.Y += 30; device.GUIEnvironment.AddButton( pos, null, (int)TestScenarios.INDOOR_TEST, "Start Indoor Test" ); // add windows forms button pos.LowerRightCorner.Y += 30; pos.UpperLeftCorner.Y += 30; device.GUIEnvironment.AddButton( pos, null, (int)TestScenarios.WINDOWS_FORMS_TEST, "Start Windows.Forms Test" ); // add shader test button pos.LowerRightCorner.Y += 30; pos.UpperLeftCorner.Y += 30; device.GUIEnvironment.AddButton( pos, null, (int)TestScenarios.SHADER_TEST, "Start Shader Test" ); // add copyright stuff IGUIStaticText text = device.GUIEnvironment.AddStaticText( "Background 3D scene created by Alvaro F. Celis, rendered using Irrlicht", new Rect(2,368,500,384), false, false, null, -1); text.OverrideColor = new Color(100,150,150,150); // draw everything while(device.Run() && ClickedButton == TestScenarios.NONE) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); device.VideoDriver.EndScene(); } device.CloseDevice(); return; } public void runTerrainTest() { device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, false, false); device.EventReceiver = this; device.ResizeAble = true; device.WindowCaption = "Irrlicht.NET terrain test"; // create a camera ICameraSceneNode cam = device.SceneManager.AddCameraSceneNodeFPS(null, 100, 1200, -1); cam.Position = new Vector3D(1900*2, 255*2, 3700*2); cam.Target = new Vector3D(2397*2, 343*2, 2700*2); cam.FarValue = 12000.0f; // create the terrain ITerrainSceneNode terrain = device.SceneManager.AddTerrainSceneNode( "../../media/terrain-heightmap.bmp", null, -1, new Vector3D(), new Vector3D(40, 4.4f, 40), new Color(255,255,255,255)); terrain.SetMaterialFlag(MaterialFlag.LIGHTING, false); terrain.SetMaterialType(MaterialType.DETAIL_MAP); terrain.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/terrain-texture.jpg")); terrain.SetMaterialTexture(1, device.VideoDriver.GetTexture("../../media/detailmap3.jpg")); terrain.ScaleTexture( 1.0f, 20.0f ); // create terrain triangle selector for collision ITriangleSelector selector = device.SceneManager.CreateTerrainTriangleSelector( terrain, 0 ); // create collision animator and add it to the camera ISceneNodeAnimator collAnim = device.SceneManager.CreateCollisionResponseAnimator( selector, cam, new Vector3D(30,50,30), // size of ellipsoid around camera new Vector3D(0, 0, 0), // gravity new Vector3D(0, 50, 0), // translation 0.0005f); // sliding value cam.AddAnimator(collAnim); // add sky box device.SceneManager.AddSkyBoxSceneNode( device.VideoDriver.GetTexture("../../media/irrlicht2_up.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_dn.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_lf.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_rt.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_ft.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_bk.jpg"), null, -1); // make cursor invisible device.CursorControl.Visible = false; // draw everything device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run()) { if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); device.VideoDriver.EndScene(); } } } public void runIndoorTest() { device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, true, false); device.EventReceiver = this; device.ResizeAble = true; device.WindowCaption = "Irrlicht.NET indoor test"; // load some textures and meshes ITexture texSydney = device.VideoDriver.GetTexture(@"..\..\media\sydney.bmp"); ITexture texWall = device.VideoDriver.GetTexture(@"..\..\media\wall.jpg"); ITexture texLogo = device.VideoDriver.GetTexture(@"..\..\media\irrlichtlogoaligned.jpg"); Irrlicht.Scene.IAnimatedMesh mesh = device.SceneManager.GetMesh(@"..\..\media\sydney.md2"); if (mesh == null) { System.Windows.Forms.MessageBox.Show( @"Could not load mesh ..\..\media\sydney.md2, exiting.", "Problem starting program"); return; } // add a cube to the scene ISceneNode node = device.SceneManager.AddCubeSceneNode(15, null, -1, new Vector3D(30,-15,0)); node.SetMaterialTexture(0, texWall); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); // add an animator to the cube to make it rotate ISceneNodeAnimator anim = device.SceneManager.CreateRotationAnimator(new Vector3D(0.2f, 0.2f, 0)); node.AddAnimator(anim); // add animated mesh IAnimatedMeshSceneNode anode = device.SceneManager.AddAnimatedMeshSceneNode(mesh, null, -1); anode.SetMaterialTexture(0, texSydney); anode.SetMaterialFlag(MaterialFlag.LIGHTING, false); anode.Scale = new Vector3D(2,2,2); anode.Position = new Vector3D(0, -20, 0); // add a shadow Shadow = anode.AddShadowVolumeSceneNode(); if (Shadow != null) Shadow.Visible = false; // where no light there no shadow device.SceneManager.AddLightSceneNode(null, new Vector3D(20,100,-50), new Colorf(255,0,0), 200, -1); // add quake 3 level device.FileSystem.AddZipFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh q3levelmesh = device.SceneManager.GetMesh("20kdm2.bsp"); ISceneNode q3node = device.SceneManager.AddOctTreeSceneNode(q3levelmesh, null, -1); q3node.Position = new Vector3D(-1370,-130,-1400); // create octtree triangle selector for q3 mesh ITriangleSelector selector = device.SceneManager.CreateOctTreeTriangleSelector( q3levelmesh.GetMesh(0), q3node, 128); // add billboard IBillboardSceneNode bill = device.SceneManager.AddBillboardSceneNode(null, new Dimension2Df(20,20), new Vector3D(0,0,0), -1); bill.SetMaterialType(MaterialType.TRANSPARENT_ADD_COLOR); bill.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/particle.bmp")); bill.SetMaterialFlag(MaterialFlag.LIGHTING, false); bill.SetMaterialFlag(MaterialFlag.ZBUFFER, false); // create camera ICameraSceneNode cam = device.SceneManager.AddCameraSceneNodeFPS(null, 100, 300, -1); cam.Position = new Vector3D(20,300,-50); // make cursor invisible device.CursorControl.Visible = false; // create collision animator and add it to the camera ISceneNodeAnimator collAnim = device.SceneManager.CreateCollisionResponseAnimator( selector, cam, new Vector3D(30,50,30), // size of ellipsoid around camera new Vector3D(0, -3, 0), // gravity new Vector3D(0, 50, 0), // translation 0.0005f); // sliding value cam.AddAnimator(collAnim); // load some font and set it into the skin IGUIFont font = device.GUIEnvironment.GetFont("../../media/fonthaettenschweiler.bmp"); device.GUIEnvironment.Skin.Font = font; // add some gui stuff device.GUIEnvironment.AddMessageBox("Hello World", "I'm a Irrlicht.NET MessageBox. Please press SPACE to close me.", true, MessageBoxFlag.OK | MessageBoxFlag.CANCEL, null, -1); // start drawing loop int fps = 0; device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run()) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); // draw scene device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); // do some collision testing Line3D line = new Line3D(); line.start = cam.Position; line.end = ((cam.Target - line.start).Normalize() * 1000.0f ) + line.start; Vector3D intersection = new Vector3D(); Triangle3D tri = new Triangle3D(); if (device.SceneManager.SceneCollisionManager.GetCollisionPoint( line, selector, out intersection, out tri)) { bill.Position = intersection; Material mat = new Material(); mat.Lighting = false; device.VideoDriver.SetTransform(TransformationState.WORLD, new Matrix4()); device.VideoDriver.SetMaterial(mat); device.VideoDriver.Draw3DTriangle(tri, new Color(0,255,0,0)); } // draw 2d logo device.VideoDriver.Draw2DImage( texLogo, new Position2D(10,10), new Rect(0,0,88,31), new Rect(new Position2D(0,0),device.VideoDriver.ScreenSize), new Color(0xffffff), false); // draw some text font.Draw("Press 'S' to toggle the visibility of the realtime shadow.", new Position2D(120,20), new Color(100,150,200,200)); device.VideoDriver.EndScene(); if (fps != device.VideoDriver.FPS) { fps = device.VideoDriver.FPS; device.WindowCaption = "Irrlicht.NET test (primitives:" + device.VideoDriver.PrimitiveCountDrawn + ") fps:" + fps; } } } void runIrrlichtInWindowsFormTest() { // testing irrlicht running embedded in a windows form System.Windows.Forms.Form f = new System.Windows.Forms.Form(); f.Text = "Irrlicht running embedded in Windows.Form"; device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, false, false, true, f.Handle); f.Show(); // set up a simple scene ICameraSceneNode cam = device.SceneManager.AddCameraSceneNode( null, new Vector3D(), new Vector3D(), -1); ISceneNodeAnimator anim = device.SceneManager.CreateFlyCircleAnimator( new Vector3D(0,10,0), 30.0f, 0.003f); cam.AddAnimator(anim); ISceneNode cube = device.SceneManager.AddCubeSceneNode(25, null, -1, new Vector3D()); cube.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/rockwall.bmp")); cube.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); // draw everything device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run() && f.Visible) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); device.VideoDriver.EndScene(); } } public void runShaderTest() { // testing irrlicht with shaders device = new IrrlichtDevice(SelectedDriverType, new Dimension2D(800,600), 16, false, true, false); device.EventReceiver = this; device.ResizeAble = true; device.WindowCaption = "Irrlicht.NET shader test"; String vsFileName = ""; String psFileName = ""; UseHighLevelShaders = false; switch(SelectedDriverType) { case DriverType.DIRECT3D8: psFileName = "../../media/d3d8.psh"; vsFileName = "../../media/d3d8.vsh"; break; case DriverType.DIRECT3D9: if (UseHighLevelShaders) { psFileName = "../../media/d3d9.hlsl"; vsFileName = psFileName; // both shaders are in the same file } else { psFileName = "../../media/d3d9.psh"; vsFileName = "../../media/d3d9.vsh"; } break; case DriverType.OPENGL: if (UseHighLevelShaders) { psFileName = "../../media/opengl.frag"; vsFileName = "../../media/opengl.vert"; } else { psFileName = "../../media/opengl.psh"; vsFileName = "../../media/opengl.vsh"; } break; } // create materials int newMaterialType1 = 0; int newMaterialType2 = 0; if ( device.VideoDriver.GPUProgrammingServices != null ) { IShaderConstantSetCallBack callBack = this; if (UseHighLevelShaders) { newMaterialType1 = device.VideoDriver.GPUProgrammingServices.AddHighLevelShaderMaterialFromFiles( vsFileName, "vertexMain", VertexShaderType.VST_VS_1_1, psFileName, "pixelMain", PixelShaderType.PST_PS_1_1, callBack, MaterialType.SOLID); newMaterialType2 = device.VideoDriver.GPUProgrammingServices.AddHighLevelShaderMaterialFromFiles( vsFileName, "vertexMain", VertexShaderType.VST_VS_1_1, psFileName, "pixelMain", PixelShaderType.PST_PS_1_1, callBack, MaterialType.TRANSPARENT_ADD_COLOR); } else { newMaterialType1 = device.VideoDriver.GPUProgrammingServices.AddShaderMaterialFromFiles( vsFileName, psFileName, callBack, MaterialType.SOLID ); newMaterialType2 = device.VideoDriver.GPUProgrammingServices.AddShaderMaterialFromFiles( vsFileName, psFileName, callBack, MaterialType.TRANSPARENT_ADD_COLOR ); } } // create test scene node 1, with the new created material type 1 ISceneNode node = device.SceneManager.AddCubeSceneNode(50, null, -1, new Vector3D(0,0,0)); node.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/wall.bmp")); node.SetMaterialType((MaterialType)newMaterialType1); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); //device.SceneManager.AddTextSceneNode( device.GUIEnvironment.BuiltInFont, // "PS & VS & EMT_SOLID", new Color(255,255,255,255), node, new Vector3D(0,0,0), -1); ISceneNodeAnimator anim = device.SceneManager.CreateRotationAnimator( new Vector3D(0,0.3f,0) ); node.AddAnimator(anim); // create test scene node 1, with the new created material type 1 node = device.SceneManager.AddCubeSceneNode(50, null, -1, new Vector3D(0,-10,50)); node.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/wall.bmp")); node.SetMaterialType((MaterialType)newMaterialType2); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); //device.SceneManager.AddTextSceneNode( device.GUIEnvironment.BuiltInFont, // "PS & VS & EMT_TRANSPARENT", new Color(255,255,255,255), node, new Vector3D(0,0,0), -1); anim = device.SceneManager.CreateRotationAnimator( new Vector3D(0,0.3f,0) ); node.AddAnimator(anim); //Then we add a third cube without a shader on it, to be able to compare the //cubes. node = device.SceneManager.AddCubeSceneNode(50, null, -1, new Vector3D(0,50,25)); node.SetMaterialTexture(0, device.VideoDriver.GetTexture("../../media/wall.bmp")); node.SetMaterialFlag(Irrlicht.Video.MaterialFlag.LIGHTING, false); //device.SceneManager.AddTextSceneNode( device.GUIEnvironment.BuiltInFont, // "NO SHADER", new Color(255,255,255,255), node, new Vector3D(0,0,0), -1); // And last, we add a skybox and a user controlled camera to the scene. device.SceneManager.AddSkyBoxSceneNode( device.VideoDriver.GetTexture("../../media/irrlicht2_up.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_dn.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_lf.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_rt.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_ft.jpg"), device.VideoDriver.GetTexture("../../media/irrlicht2_bk.jpg"), null, -1 ); ICameraSceneNode cam = device.SceneManager.AddCameraSceneNodeFPS(); cam.Target = new Vector3D(0,0,0); cam.Position = new Vector3D(-100,50,100); device.CursorControl.Visible = false; device.Run(); // fix for a temporary bug where quit messages are not be removed in the queue while(device.Run()) if (device.WindowActive) { device.VideoDriver.BeginScene(true, true, new Color(255,0,0,50)); device.SceneManager.DrawAll(); device.GUIEnvironment.DrawAll(); device.VideoDriver.EndScene(); } } public void OnSetConstants( IMaterialRendererServices services ) { Matrix4 invWorld = services.VideoDriver.GetTransform(TransformationState.WORLD); invWorld.MakeInverse(); if (UseHighLevelShaders) services.SetVertexShaderConstant("mInvWorld", invWorld.GetFloats(), 16); else services.SetVertexShaderConstant(invWorld.GetFloats(), 0, 4); // set clip matrix Matrix4 worldViewProj; worldViewProj = services.VideoDriver.GetTransform(TransformationState.PROJECTION); worldViewProj *= services.VideoDriver.GetTransform(TransformationState.VIEW); worldViewProj *= services.VideoDriver.GetTransform(TransformationState.WORLD); if (UseHighLevelShaders) services.SetVertexShaderConstant("mWorldViewProj", worldViewProj.GetFloats(), 16); else services.SetVertexShaderConstant(worldViewProj.GetFloats(), 4, 4); // set camera position Vector3D campos = device.SceneManager.ActiveCamera.Position; float[] pos = new float[4]; pos[0] = campos.X; pos[1] = campos.Y; pos[2] = campos.Z; pos[3] = 0; if (UseHighLevelShaders) services.SetVertexShaderConstant("mLightPos", pos, 3); else services.SetVertexShaderConstant(pos, 8, 1); // set light color pos[0] = 0; pos[1] = 1; pos[2] = 1; pos[3] = 0; if (UseHighLevelShaders) services.SetVertexShaderConstant("mLightColor", pos, 4); else services.SetVertexShaderConstant(pos, 9, 1); // set transposed world matrix Matrix4 world = services.VideoDriver.GetTransform(TransformationState.WORLD); world = world.GetTransposed(); if (UseHighLevelShaders) services.SetVertexShaderConstant("mTransWorld", world.GetFloats(), 16); else services.SetVertexShaderConstant(world.GetFloats(), 10, 4); } private DriverType SelectedDriverType = DriverType.DIRECT3D8; private TestScenarios ClickedButton = TestScenarios.NONE; private ISceneNode Shadow; private bool UseHighLevelShaders = false; private IrrlichtDevice device; }