ModuleControl::ModuleControl(void) { pCamara = 0; pModule = 0; CamaraPos.X = 0.f; CamaraPos.Y = 0.f; CamaraPos.Z = 0.f; ModuleposRelateToCamaraVector.X = 0.f; ModuleposRelateToCamaraVector.Y = 0.f; ModuleposRelateToCamaraVector.Z = 0.f; CenterCursor.set(0.5f, 0.5f); IrrlichtDevice* device = MyIrrlichtEngine::GetEngine()->GetDevice(); CursorPos = device->getCursorControl()->getRelativePosition(); device->getCursorControl()->setPosition(CenterCursor); }
int main(int argc, const char **argv) { VariantMap settings; settings["appName"] = "Puzzle Moppet"; settings["windowTitle"] = "Puzzle Moppet Configuration"; settings["screenWidth"] = 250; settings["screenHeight"] = 330; #ifndef __APPLE__ // Software renderer doesn't seem to work on Mac... settings["softwareMode"] = true; #endif IEngine *engine = CreateEngine(argc, argv, &settings); IrrlichtDevice *device = engine->GetIrrlichtDevice(); // Filesystem... // Irrlicht needs this so it can load textures from same dir as font xml. engine->GetIrrlichtDevice()->getFileSystem()->addFileArchive("../projects/ConfigApp/"); // Show the cursor device->getCursorControl()->setVisible(true); // Pause World, not needed for GUI app. // (pausing World also disables mouse centring) engine->GetWorld()->Pause(); // Load GUI gui::IGUIEnvironment *guienv = device->getGUIEnvironment(); ASSERT( guienv->loadGUI("gui.xml") ); // Get pointers to important elements within the loaded GUI. // Ideally in the future we'll have a layout manager and won't need the GUI // defined in xml. FindGUIElementPointers(); // Default font guienv->getSkin()->setFont( guienv->getFont("lucida.xml") ); // Change background colour... engine->GetRenderSystem()->SetBackgroundCol(video::SColor(0, 200,200,200)); // Receive GUI events. // This prevents Litha Engine from receiving GUI events, but that doesn't matter. IEventReceiver *eventReceiver = new EventReceiver(engine); guienv->setUserEventReceiver(eventReceiver); // Init InitSettings(); InitGUI(); engine->Run(); engine->drop(); delete eventReceiver; return 0; }
int main( ) { // Boring stuff: set up the scene, object & camera as usual IrrlichtDevice* device = createDevice( DRIVER, dimension2d<s32>( 640, 480 ), 16, false, false, false, 0 ); IVideoDriver* driver = device->getVideoDriver( ); ISceneManager* smgr = device->getSceneManager( ); IGUIEnvironment* guienv = device->getGUIEnvironment( ); device->getFileSystem( )->changeWorkingDirectoryTo( MEDIA_DIRECTORY ); guienv->addStaticText( L"Lens Flare", rect<s32>( 10, 10, 260, 22 ), true ); IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( smgr->getMesh( "sydney.md2" ) ); node->setMaterialFlag( EMF_LIGHTING, false ); node->setMD2Animation( scene::EMAT_STAND ); node->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); IAnimatedMeshSceneNode* node2 = smgr->addAnimatedMeshSceneNode( smgr->getMesh( "sydney.md2" ) ); node2->setMaterialFlag( EMF_LIGHTING, false ); node2->setMD2Animation( scene::EMAT_STAND ); node2->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); node2->setPosition( vector3df( 20.0f, 0.0f, 0.0f ) ); ICameraSceneNode* cam = smgr->addCameraSceneNode( 0, vector3df( 40.0f, 30.0f, -40.0f ), vector3df( 0.0f, 5.0f, 0.0f ) ); ISceneNode* sun = smgr->addSphereSceneNode( 50.0f, 16 ); sun->setPosition( vector3df( 0.0f, 50.0f, 1000.0f ) ); sun->setMaterialFlag( EMF_LIGHTING, false ); sun->setMaterialTexture( 0, driver->getTexture("sun.png") ); // Interesting stuff // As before, we make a renderer IPostProc* ppRenderer = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor( 255u, 100u, 101u, 140u ) ); // Now make a flare effect: // (render from, output size, sun scene node) // can also use a vector instead of a scene node - when using a scene node the position will follow node automatically CLensFlarePostProc* ppFlare1 = new CLensFlarePostProc( ppRenderer, dimension2di( 1024, 512 ), driver->getTexture("flare.png"), sun, 50.0f ); CLensFlarePostProc* ppFlare2 = new CLensFlarePostProc( ppFlare1, dimension2di( 1024, 512 ), driver->getTexture("flare.png"), vector3df( -2000.0f, 50.0f, 1000.0f ) ); ppFlare2->setQuality( PPQ_CRUDE ); // Setting the quality to crude avoids pixel checking, which is slow (expecially when more than one lens flare), so if you use >1 flare, set most of them to crude. // These variables aren't important - they are just for showing the FPS wchar_t tmp[255]; u8 t = 0u; while( device->run( ) ) { cam->setPosition( vector3df( -(device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.2f, -70.0f ) ); driver->beginScene( false, driver->getDriverType( ) == video::EDT_DIRECT3D9 ); ppFlare2->render( NULL ); guienv->drawAll( ); driver->endScene( ); // Show the current FPS if( ++ t == 30u ) { t = 0u; swprintf(tmp, 255, L"%ls fps:%3d", driver->getName(), driver->getFPS() ); device->setWindowCaption( tmp ); } } delete ppFlare1; delete ppFlare2; delete ppRenderer; // Back to boring stuff device->drop(); return 0; }
/** This test verifies that setting the cursor visibility only generates a mouse message when it actually changes */ bool cursorSetVisible(void) { IrrlichtDevice * device = createDevice(video::EDT_SOFTWARE, dimension2d<u32>(1, 1)); TrapMouseMoves moveTrapper; device->setEventReceiver(&moveTrapper); device->run(); gui::ICursorControl * cursor = device->getCursorControl(); // Move the cursor inside the Irrlicht window so that we get messages for it. cursor->setPosition(0, 0); device->run(); // Receive any messages cursor->setVisible(false); // Should generate a mouse move device->run(); // Receive any messages cursor->setVisible(false); // Should not generate a mouse move device->run(); // Receive any messages cursor->setVisible(true); // Should generate a mouse move device->run(); // Receive any messages cursor->setVisible(true); // Should not generate a mouse move device->run(); // Receive any messages // We should get at most 3 messages: one for the setPosition(), and one for // each actual change of visibility. bool result = (moveTrapper.MouseMovesReceived <= 3); device->closeDevice(); device->run(); device->drop(); if(!result) { logTestString("ERROR: cursorSetVisible received %d events.\n", moveTrapper.MouseMovesReceived); assert_log(false); } return result; }
int main() { IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<u32>(1680, 1050), 16, true, false, false, 0); if (!device) return 1; device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); device->getCursorControl()->setVisible(false); IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); StandardObject::smgr = smgr; StandardObject::driver = driver; GameScreen::smgr = smgr; GameScreen::driver = driver; GameScreen::guienv = guienv; GameScreen gameScreen = GameScreen(); while(device->run()) { gameScreen.Update(); driver->beginScene(true, true, SColor(255,100,101,140)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); } device->drop(); return 0; }
/* Now for the real fun. We create an Irrlicht Device and start to setup the scene. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice* device = createDevice(driverType, core::dimension2d<u32>(640, 480)); if (device == 0) return 1; // could not create selected driver. /* Before we start with the interesting stuff, we do some simple things: Store pointers to the most important parts of the engine (video driver, scene manager, gui environment) to safe us from typing too much, add an irrlicht engine logo to the window and a user controlled first person shooter style camera. Also, we let the engine know that it should store all textures in 32 bit. This necessary because for parallax mapping, we need 32 bit textures. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // add irrlicht logo env->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), core::position2d<s32>(10,10)); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-200,200,-200)); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Because we want the whole scene to look a little bit scarier, we add some fog to it. This is done by a call to IVideoDriver::setFog(). There you can set various fog settings. In this example, we use pixel fog, because it will work well with the materials we'll use in this example. Please note that you will have to set the material flag EMF_FOG_ENABLE to 'true' in every scene node which should be affected by this fog. */ driver->setFog(video::SColor(0,138,125,81), video::EFT_FOG_LINEAR, 250, 1000, .003f, true, false); /* To be able to display something interesting, we load a mesh from a .3ds file which is a room I modeled with anim8or. It is the same room as from the specialFX example. Maybe you remember from that tutorial, I am no good modeler at all and so I totally messed up the texture mapping in this model, but we can simply repair it with the IMeshManipulator::makePlanarTextureMapping() method. */ scene::IAnimatedMesh* roomMesh = smgr->getMesh("../../media/room.3ds"); scene::ISceneNode* room = 0; scene::ISceneNode* earth = 0; if (roomMesh) { // The Room mesh doesn't have proper Texture Mapping on the // floor, so we can recreate them on runtime smgr->getMeshManipulator()->makePlanarTextureMapping( roomMesh->getMesh(0), 0.003f); /* Now for the first exciting thing: If we successfully loaded the mesh we need to apply textures to it. Because we want this room to be displayed with a very cool material, we have to do a little bit more than just set the textures. Instead of only loading a color map as usual, we also load a height map which is simply a grayscale texture. From this height map, we create a normal map which we will set as second texture of the room. If you already have a normal map, you could directly set it, but I simply didn't find a nice normal map for this texture. The normal map texture is being generated by the makeNormalMapTexture method of the VideoDriver. The second parameter specifies the height of the heightmap. If you set it to a bigger value, the map will look more rocky. */ video::ITexture* normalMap = driver->getTexture("../../media/rockwall_height.bmp"); if (normalMap) driver->makeNormalMapTexture(normalMap, 9.0f); /* // The Normal Map and the displacement map/height map in the alpha channel video::ITexture* normalMap = driver->getTexture("../../media/rockwall_NRM.tga"); */ /* But just setting color and normal map is not everything. The material we want to use needs some additional informations per vertex like tangents and binormals. Because we are too lazy to calculate that information now, we let Irrlicht do this for us. That's why we call IMeshManipulator::createMeshWithTangents(). It creates a mesh copy with tangents and binormals from another mesh. After we've done that, we simply create a standard mesh scene node with this mesh copy, set color and normal map and adjust some other material settings. Note that we set EMF_FOG_ENABLE to true to enable fog in the room. */ scene::IMesh* tangentMesh = smgr->getMeshManipulator()-> createMeshWithTangents(roomMesh->getMesh(0)); room = smgr->addMeshSceneNode(tangentMesh); room->setMaterialTexture(0, driver->getTexture("../../media/rockwall.jpg")); room->setMaterialTexture(1, normalMap); // Stones don't glitter.. room->getMaterial(0).SpecularColor.set(0,0,0,0); room->getMaterial(0).Shininess = 0.f; room->setMaterialFlag(video::EMF_FOG_ENABLE, true); room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); // adjust height for parallax effect room->getMaterial(0).MaterialTypeParam = 1.f / 64.f; // drop mesh because we created it with a create.. call. tangentMesh->drop(); } /* After we've created a room shaded by per pixel lighting, we add a sphere into it with the same material, but we'll make it transparent. In addition, because the sphere looks somehow like a familiar planet, we make it rotate. The procedure is similar as before. The difference is that we are loading the mesh from an .x file which already contains a color map so we do not need to load it manually. But the sphere is a little bit too small for our needs, so we scale it by the factor 50. */ // add earth sphere scene::IAnimatedMesh* earthMesh = smgr->getMesh("../../media/earth.x"); if (earthMesh) { //perform various task with the mesh manipulator scene::IMeshManipulator *manipulator = smgr->getMeshManipulator(); // create mesh copy with tangent informations from original earth.x mesh scene::IMesh* tangentSphereMesh = manipulator->createMeshWithTangents(earthMesh->getMesh(0)); // set the alpha value of all vertices to 200 manipulator->setVertexColorAlpha(tangentSphereMesh, 200); // scale the mesh by factor 50 core::matrix4 m; m.setScale ( core::vector3df(50,50,50) ); manipulator->transform( tangentSphereMesh, m ); earth = smgr->addMeshSceneNode(tangentSphereMesh); earth->setPosition(core::vector3df(-70,130,45)); // load heightmap, create normal map from it and set it video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg"); if (earthNormalMap) { driver->makeNormalMapTexture(earthNormalMap, 20.0f); earth->setMaterialTexture(1, earthNormalMap); earth->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); } // adjust material settings earth->setMaterialFlag(video::EMF_FOG_ENABLE, true); // add rotation animator scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0,0.1f,0)); earth->addAnimator(anim); anim->drop(); // drop mesh because we created it with a create.. call. tangentSphereMesh->drop(); } /* Per pixel lighted materials only look cool when there are moving lights. So we add some. And because moving lights alone are so boring, we add billboards to them, and a whole particle system to one of them. We start with the first light which is red and has only the billboard attached. */ // add light 1 (more green) scene::ILightSceneNode* light1 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); // add fly circle animator to light 1 scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator (core::vector3df(50,300,0),190.0f, -0.003f); light1->addAnimator(anim); anim->drop(); // attach billboard to the light scene::IBillboardSceneNode* bill = smgr->addBillboardSceneNode(light1, core::dimension2d<f32>(60, 60)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/particlegreen.jpg")); /* Now the same again, with the second light. The difference is that we add a particle system to it too. And because the light moves, the particles of the particlesystem will follow. If you want to know more about how particle systems are created in Irrlicht, take a look at the specialFx example. Maybe you will have noticed that we only add 2 lights, this has a simple reason: The low end version of this material was written in ps1.1 and vs1.1, which doesn't allow more lights. You could add a third light to the scene, but it won't be used to shade the walls. But of course, this will change in future versions of Irrlicht where higher versions of pixel/vertex shaders will be implemented too. */ // add light 2 (red) scene::ISceneNode* light2 = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); // add fly circle animator to light 2 anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0), 200.0f, 0.001f, core::vector3df(0.2f, 0.9f, 0.f)); light2->addAnimator(anim); anim->drop(); // attach billboard to light bill = smgr->addBillboardSceneNode(light2, core::dimension2d<f32>(120, 120)); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); // add particle system scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false, light2); // create and set emitter scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d<f32>(-3,0,-3,3,1,3), core::vector3df(0.0f,0.03f,0.0f), 80,100, video::SColor(10,255,255,255), video::SColor(10,255,255,255), 400,1100); em->setMinStartSize(core::dimension2d<f32>(30.0f, 40.0f)); em->setMaxStartSize(core::dimension2d<f32>(30.0f, 40.0f)); ps->setEmitter(em); em->drop(); // create and set affector scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); ps->addAffector(paf); paf->drop(); // adjust some material settings ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); MyEventReceiver receiver(room, earth, env, driver); device->setEventReceiver(&receiver); /* Finally, draw everything. That's it. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); env->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Per pixel lighting example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
int main(int argc, char *argv[]) { /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); // Set locale. This is for forcing '.' as the decimal point. std::locale::global(std::locale("C")); // This enables printing all characters in bitmap font setlocale(LC_CTYPE, "en_US"); /* Parse command line */ // List all allowed options core::map<std::string, ValueSpec> allowed_options; allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG)); allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, "Run server directly")); allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, "Load configuration from specified file")); allowed_options.insert("port", ValueSpec(VALUETYPE_STRING)); allowed_options.insert("address", ValueSpec(VALUETYPE_STRING)); allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG)); allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG)); allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG)); allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING)); #ifdef _WIN32 allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG)); #endif allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG)); allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG)); Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help")) { dstream<<"Allowed options:"<<std::endl; for(core::map<std::string, ValueSpec>::Iterator i = allowed_options.getIterator(); i.atEnd() == false; i++) { dstream<<" --"<<i.getNode()->getKey(); if(i.getNode()->getValue().type == VALUETYPE_FLAG) { } else { dstream<<" <value>"; } dstream<<std::endl; if(i.getNode()->getValue().help != NULL) { dstream<<" "<<i.getNode()->getValue().help <<std::endl; } } return cmd_args.getFlag("help") ? 0 : 1; } /* Low-level initialization */ bool disable_stderr = false; #ifdef _WIN32 if(cmd_args.getFlag("dstream-on-stderr") == false) disable_stderr = true; #endif if(cmd_args.getFlag("info-on-stderr")) log_add_output(&main_stderr_log_out, LMT_INFO); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); // Initialize porting::path_data and porting::path_userdata porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_userdata); init_gettext((porting::path_data+DIR_DELIM+".."+DIR_DELIM+"locale").c_str()); // Initialize debug streams #ifdef RUN_IN_PLACE std::string debugfile = DEBUGFILE; #else std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE; #endif debugstreams_init(disable_stderr, debugfile.c_str()); // Initialize debug stacks debug_stacks_init(); DSTACK(__FUNCTION_NAME); // Init material properties table //initializeMaterialProperties(); // Debug handler BEGIN_DEBUG_EXCEPTION_HANDLER // Print startup message actionstream<<PROJECT_NAME<< " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use std::string configpath = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } configpath = cmd_args.get("config"); } else { core::array<std::string> filenames; filenames.push_back(porting::path_userdata + DIR_DELIM + "minetest.conf"); #ifdef RUN_IN_PLACE filenames.push_back(porting::path_userdata + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { configpath = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(configpath == "") configpath = filenames[0]; } // Initialize random seed srand(time(0)); mysrand(time(0)); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } /*for(s16 y=-100; y<100; y++) for(s16 x=-100; x<100; x++) { std::cout<<noise2d_gradient((double)x/10,(double)y/10, 32415)<<std::endl; } return 0;*/ /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // Map directory std::string map_dir = porting::path_userdata+DIR_DELIM+"world"; if(cmd_args.exists("map-dir")) map_dir = cmd_args.get("map-dir"); else if(g_settings->exists("map-dir")) map_dir = g_settings->get("map-dir"); // Run dedicated server if asked to if(cmd_args.getFlag("server")) { DSTACK("Dedicated server branch"); // Create time getter g_timegetter = new SimpleTimeGetter(); // Create server Server server(map_dir.c_str(), configpath); server.start(port); // Run server dedicated_server_loop(server, kill); return 0; } /* More parameters */ // Address to connect to std::string address = ""; if(cmd_args.exists("address")) { address = cmd_args.get("address"); } else { address = g_settings->get("address"); } std::string playername = g_settings->get("name"); /* Device initialization */ // Resolution selection bool fullscreen = false; u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* Create device and exit if creation failed */ MyEventReceiver receiver; IrrlichtDevice *device; device = createDevice(driverType, core::dimension2d<u32>(screenW, screenH), 16, fullscreen, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); // Disable mipmaps (because some of them look ugly) driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Set the window caption device->setWindowCaption(L"Minetest [Main Menu]"); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) input = new RandomInputHandler(); else input = new RealInputHandler(device, &receiver); scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); /* GUI stuff */ /* If an error occurs, this is set to something and the menu-game loop is restarted. It is then displayed before the menu. */ std::wstring error_message = L""; // The password entered during the menu screen, std::string password; /* Menu-game loop */ while(device->run() && kill == false) { // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* We need some kind of a root node to be able to add custom gui elements directly on the screen. Otherwise they won't be automatically drawn. */ guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000)); /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // Cursor can be non-visible when coming from the game device->getCursorControl()->setVisible(true); // Some stuff are left to scene manager when coming from the game // (map at least?) smgr->clear(); // Reset or hide the debug gui texts /*guitext->setText(L"Minetest-c55"); guitext2->setVisible(false); guitext_info->setVisible(false); guitext_chat->setVisible(false);*/ // Initialize menu data MainMenuData menudata; menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); menudata.fancy_trees = g_settings->getBool("new_style_leaves"); menudata.smooth_lighting = g_settings->getBool("smooth_lighting"); menudata.clouds_3d = g_settings->getBool("enable_3d_clouds"); menudata.opaque_water = g_settings->getBool("opaque_water"); menudata.creative_mode = g_settings->getBool("creative_mode"); menudata.enable_damage = g_settings->getBool("enable_damage"); GUIMainMenu *menu = new GUIMainMenu(guienv, guiroot, -1, &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); if(error_message != L"") { errorstream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; GUIMessageMenu *menu2 = new GUIMessageMenu(guienv, guiroot, -1, &g_menumgr, error_message.c_str()); menu2->drop(); error_message = L""; } video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Created main menu"<<std::endl; while(device->run() && kill == false) { if(menu->getStatus() == true) break; //driver->beginScene(true, true, video::SColor(255,0,0,0)); driver->beginScene(true, true, video::SColor(255,128,128,128)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; infostream<<"Dropping main menu"<<std::endl; menu->drop(); // Delete map if requested if(menudata.delete_map) { bool r = fs::RecursiveDeleteContent(map_dir); if(r == false) error_message = L"Delete failed"; continue; } playername = wide_to_narrow(menudata.name); password = translatePassword(playername, menudata.password); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = wide_to_narrow(menudata.address); int newport = stoi(wide_to_narrow(menudata.port)); if(newport != 0) port = newport; g_settings->set("new_style_leaves", itos(menudata.fancy_trees)); g_settings->set("smooth_lighting", itos(menudata.smooth_lighting)); g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d)); g_settings->set("opaque_water", itos(menudata.opaque_water)); g_settings->set("creative_mode", itos(menudata.creative_mode)); g_settings->set("enable_damage", itos(menudata.enable_damage)); // NOTE: These are now checked server side; no need to do it // here, so let's not do it here. /*// Check for valid parameters, restart menu if invalid. if(playername == "") { error_message = L"Name required."; continue; } // Check that name has only valid chars if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false) { error_message = L"Characters allowed: " +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS); continue; }*/ // Save settings g_settings->set("name", playername); g_settings->set("address", address); g_settings->set("port", itos(port)); // Update configuration file if(configpath != "") g_settings->updateConfigFile(configpath.c_str()); // Continue to game break; } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; /* Run game */ the_game( kill, random_input, input, device, font, map_dir, playername, password, address, port, error_message, configpath ); } //try catch(con::PeerNotFoundException &e) { errorstream<<"Connection error (timed out?)"<<std::endl; error_message = L"Connection error (timed out?)"; } catch(SocketException &e) { errorstream<<"Socket error (port already in use?)"<<std::endl; error_message = L"Socket error (port already in use?)"; } catch(ModError &e) { errorstream<<e.what()<<std::endl; error_message = narrow_to_wide(e.what()) + L"\nCheck debug.txt for details."; } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception, what()=\""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif } // Menu-game loop delete input; /* In the end, delete the Irrlicht device. */ device->drop(); END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return 0; }
/* The event receiver for keeping the pressed keys is ready, the actual responses will be made inside the render loop, right before drawing the scene. So lets just create an irr::IrrlichtDevice and the scene node we want to move. We also create some other additional scene nodes, to show that there are also some different possibilities to move and animate scene nodes. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device MyEventReceiver receiver; IrrlichtDevice* device = createDevice(driverType, core::dimension2d<u32>(1280, 800), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); /* Create the node which will be moved with the WSAD keys. We create a sphere node, which is a built-in geometry primitive. We place the node at (0,0,30) and assign a texture to it to let it look a little bit more interesting. Because we have no dynamic lights in this scene we disable lighting for each model (otherwise the models would be black). */ scene::ISceneNode * node = smgr->addSphereSceneNode(EARTH_RADIUS, 36); if (node) { node->setPosition(core::vector3df(0,0,30)); #ifdef _MSC_VER node->setMaterialTexture(0, driver->getTexture("../../../src/vendor/irrlicht/media/wall.bmp")); #else node->setMaterialTexture(0, driver->getTexture("../../src/vendor/irrlicht/media/wall.bmp")); #endif node->setMaterialFlag(video::EMF_LIGHTING, false); } /* To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(0, 0, -EARTH_RADIUS * START_DISTANCE)); camera->setTarget(core::vector3df(0, 0, 0)); const f32 ONE_AU = 149597870.0f; #if(0) camera->setFarValue(ONE_AU); #else camera->setFarValue(2<<23); #endif device->getCursorControl()->setVisible(false); /* We have done everything, so lets draw it. We also write the current frames per second and the name of the driver to the caption of the window. */ int lastFPS = -1; // In order to do framerate independent movement, we have to know // how long it was since the last frame u32 then = device->getTimer()->getTime(); // This is the movemen speed in units per second. //#if(1) const f32 MOVEMENT_SPEED = .5f; //#else //const f32 MOVEMENT_SPEED = EARTH_RADIUS; //#endif Skybox skybox(smgr, driver); while(device->run()) { // Work out a frame delta time. const u32 now = device->getTimer()->getTime(); const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds then = now; /* Check if keys W, S, A or D are being held down, and move the sphere node around respectively. */ core::vector3df nodePosition = node->getPosition(); if(receiver.IsKeyDown(irr::KEY_KEY_W)) nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_S)) nodePosition.Y -= MOVEMENT_SPEED * frameDeltaTime; if(receiver.IsKeyDown(irr::KEY_KEY_A)) nodePosition.X -= MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_D)) nodePosition.X += MOVEMENT_SPEED * frameDeltaTime; node->setPosition(nodePosition); driver->beginScene(true, true, video::SColor(255,113,113,133)); smgr->drawAll(); // draw the 3d scene device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo) driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"Movement Example - Irrlicht Engine ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; }
/* The event receiver for keeping the pressed keys is ready, the actual responses will be made inside the render loop, right before drawing the scene. So lets just create an irr::IrrlichtDevice and the scene node we want to move. We also create some other additional scene nodes, to show that there are also some different possibilities to move and animate scene nodes. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device MyEventReceiver receiver; IrrlichtDevice* device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); const io::path mediaPath = getExampleMediaPath(); /* Create the node which will be moved with the WSAD keys. We create a sphere node, which is a built-in geometry primitive. We place the node at (0,0,30) and assign a texture to it to let it look a little bit more interesting. Because we have no dynamic lights in this scene we disable lighting for each model (otherwise the models would be black). */ scene::ISceneNode * node = smgr->addSphereSceneNode(); if (node) { node->setPosition(core::vector3df(0,0,30)); node->setMaterialTexture(0, driver->getTexture(mediaPath + "wall.bmp")); node->setMaterialFlag(video::EMF_LIGHTING, false); } /* Now we create another node, movable using a scene node animator. Scene node animators modify scene nodes and can be attached to any scene node like mesh scene nodes, billboards, lights and even camera scene nodes. Scene node animators are not only able to modify the position of a scene node, they can also animate the textures of an object for example. We create a cube scene node and attach a 'fly circle' scene node animator to it, letting this node fly around our sphere scene node. */ scene::ISceneNode* n = smgr->addCubeSceneNode(); if (n) { n->setMaterialTexture(0, driver->getTexture(mediaPath + "t351sml.jpg")); n->setMaterialFlag(video::EMF_LIGHTING, false); scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f); if (anim) { n->addAnimator(anim); anim->drop(); } } /* The last scene node we add to show possibilities of scene node animators is a b3d model, which uses a 'fly straight' animator to run between to points. */ scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "ninja.b3d")); if (anms) { scene::ISceneNodeAnimator* anim = smgr->createFlyStraightAnimator(core::vector3df(100,0,60), core::vector3df(-100,0,60), 3500, true); if (anim) { anms->addAnimator(anim); anim->drop(); } /* To make the model look right we disable lighting, set the frames between which the animation should loop, rotate the model around 180 degrees, and adjust the animation speed and the texture. To set the right animation (frames and speed), we would also be able to just call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation instead of "setFrameLoop" and "setAnimationSpeed", but this only works with MD2 animations, and so you know how to start other animations. But a good advice is to not use hardcoded frame-numbers... */ anms->setMaterialFlag(video::EMF_LIGHTING, false); anms->setFrameLoop(0, 13); anms->setAnimationSpeed(15); // anms->setMD2Animation(scene::EMAT_RUN); anms->setScale(core::vector3df(2.f,2.f,2.f)); anms->setRotation(core::vector3df(0,-90,0)); // anms->setMaterialTexture(0, driver->getTexture(mediaPath + "sydney.bmp")); } /* To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ smgr->addCameraSceneNodeFPS(); device->getCursorControl()->setVisible(false); /* Add a colorful irrlicht logo */ device->getGUIEnvironment()->addImage( driver->getTexture(mediaPath + "irrlichtlogoalpha2.tga"), core::position2d<s32>(10,20)); gui::IGUIStaticText* diagnostics = device->getGUIEnvironment()->addStaticText( L"", core::rect<s32>(10, 10, 400, 20)); diagnostics->setOverrideColor(video::SColor(255, 255, 255, 0)); /* We have done everything, so lets draw it. We also write the current frames per second and the name of the driver to the caption of the window. */ int lastFPS = -1; // In order to do framerate independent movement, we have to know // how long it was since the last frame u32 then = device->getTimer()->getTime(); // This is the movemen speed in units per second. const f32 MOVEMENT_SPEED = 5.f; while(device->run()) { // Work out a frame delta time. const u32 now = device->getTimer()->getTime(); const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds then = now; /* Check if keys W, S, A or D are being held down, and move the sphere node around respectively. */ core::vector3df nodePosition = node->getPosition(); if(receiver.IsKeyDown(irr::KEY_KEY_W)) nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_S)) nodePosition.Y -= MOVEMENT_SPEED * frameDeltaTime; if(receiver.IsKeyDown(irr::KEY_KEY_A)) nodePosition.X -= MOVEMENT_SPEED * frameDeltaTime; else if(receiver.IsKeyDown(irr::KEY_KEY_D)) nodePosition.X += MOVEMENT_SPEED * frameDeltaTime; node->setPosition(nodePosition); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,113,113,133)); smgr->drawAll(); // draw the 3d scene device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo) driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"Movement Example - Irrlicht Engine ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; device->setWindowCaption(tmp.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; }
int main() { video::E_DRIVER_TYPE driverType; printf("Please select the driver you want for this example:\n"\ " (a) OpenGL 1.5\n (b) Direct3D 9.0c\n (c) Direct3D 8.1\n"\ " (d) Burning's Software Renderer\n (e) Software Renderer\n"\ " (f) NullDevice\n (otherKey) exit\n\n"); char i; //scanf_s("%c",&i); i='a'; switch(i) { case 'a': driverType = video::EDT_OPENGL; break; case 'b': driverType = video::EDT_DIRECT3D9;break; case 'c': driverType = video::EDT_DIRECT3D8;break; case 'd': driverType = video::EDT_BURNINGSVIDEO;break; case 'e': driverType = video::EDT_SOFTWARE; break; case 'f': driverType = video::EDT_NULL; break; default: return 1; } Configuracoes * conf = new Configuracoes(); MarcadorPedra * marcador = new MarcadorPedra(Vetor(5,0,5)); bool dentro = marcador->pontoDentroMarcador(Vetor(4.9,-0.05,4.9)); tipos::configuracoes config = conf->carregarConfigucacoes(); IrrlichtDevice* device = createDevice(driverType,core::dimension2d<u32>(config.resolucao.x, config.resolucao.y), config.bitsCor, config.fullscreen); PerfilDao * dao = new PerfilDao(); //dao->criarPerfil(tipos::Save(tipos::Perfil(1,"eduardo","menino1",21,67,Sexo::MASCULINO),0)); if (device == 0) return 1; device->setWindowCaption(L"Turma da Escalada"); Globais::setIrrDevice(device); Label::setGui(device->getGUIEnvironment()); device->getCursorControl()->setVisible(false); //device->getCursorControl()->getPosition(); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); Mesh_Info info = Mesh_Info(); info.arquivo = "modelos/personagem/Bonecos definitivos 23-09-2013/menino1/textures/menino1.x"; FaseDAO * faseDAO = new FaseDAO(); tipos::Fase_Dados f = faseDAO->getFase("fases/parede.xml"); GerenciadorDeExibicao * gerenciador = GerenciadorDeExibicao::getGerenciador(); GerenciadorExibicao2::setSceneManager(smgr); tipos::Save s = Save(Perfil(1,"Eduardo","menino1",21,66,Sexo::MASCULINO),0); bool teste=false; if(!teste) { //gerenciador->novaJanelaParaExibicao(new IntroScene(smgr->getRootSceneNode(), smgr, 11)); gerenciador->novaJanelaParaExibicao(new JanelaPrincipal(smgr->getRootSceneNode(),smgr,11)); //gerenciador->novaJanelaParaExibicao(new JanelaNovoJogo(smgr->getRootSceneNode(),smgr,11)); //JanelaTesteKinect*jtk = new JanelaTesteKinect(); gerenciador->novaJanelaParaExibicao(jtk); device->setEventReceiver(jtk); //gerenciador->novaJanelaParaExibicao(new JanelaEscolhaPersonagem(s.perfil,smgr->getRootSceneNode(),smgr,13)); //gerenciador->novaJanelaParaExibicao(new JanelaConfiguracao(smgr->getRootSceneNode(),smgr,12)); //gerenciador->novaJanelaParaExibicao(new JanelaEscolhaPerfil(smgr->getRootSceneNode(),smgr,12)); //gerenciador->novaJanelaParaExibicao(new JanelaEscolhaFase(smgr->getRootSceneNode(),smgr,13,s)); Jogador * jogador = new Jogador(s); //gerenciador->novaJanelaParaExibicao(new JanelaLoja2(jogador,smgr->getRootSceneNode(),smgr,15)); JanelaJogo*janelaJogo=new JanelaJogo(smgr->getRootSceneNode(),smgr,14,f);gerenciador->novaJanelaParaExibicao(janelaJogo);device->setEventReceiver(janelaJogo); } Janela *atual=NULL; if(!teste) { atual = gerenciador->getProximaJanela(); atual->iniciar(); } int lastFPS =-1; Janela * janela=NULL; bool criou1=false; bool criou2=false; bool criou3=false; bool criou4=false; Cronometro cronometro; int aux=0; cronometro.iniciarContagem(); lastFPS =-1; while(device->run() && ! GerenciadorDeExibicao::getGerenciador()->sairDoJogo()) { if(!atual->emExecucao()) { //smgr->getRootSceneNode()->removeChild(atual); //smgr->getRootSceneNode()->removeAll(); atual = GerenciadorDeExibicao::getGerenciador()->getProximaJanela(); atual->iniciar(); //atual->iniciar(); //smgr->getRootSceneNode()->addChild(atual); } driver->beginScene(true, true, video::SColor(0,100,100,100)); smgr->drawAll(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Turma da Escalada"; str += driver->getName(); str += " FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } driver->endScene(); } //sensor->finalizar(); return 0; }
int main() { IrrlichtDevice* device = createDevice( video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false, false, false); if (device == 0) return 1; ISceneManager *smgr = device->getSceneManager(); IVideoDriver *driver= device->getVideoDriver(); IMesh* mesh = smgr->getMesh("media/cube.obj")->getMesh(0); mesh->getMeshBuffer(0)->getMaterial().setTexture(0, driver->getTexture("media/grass.png")); CBatchingMesh* BatchingMesh = new CBatchingMesh(); s32 x,y,z; // let's add a grassy floor, 20x20 for (x=-10; x<11; ++x) for (z=-10; z<11; ++z) if ( abs(x) > 5 || abs(z) > 5) BatchingMesh->addMesh(mesh, core::vector3df(x*2,-4,z*2)); mesh->getMeshBuffer(0)->getMaterial().setTexture(0, driver->getTexture("media/stone.png")); // add some walls for (y=-1; y<7; ++y) for (x=-5; x<6; ++x) for (z=-5; z<6; ++z) if (((abs(z) == 5 || abs(x) == 5) && (abs(x)>1 || y > 3 )) || y==6) BatchingMesh->addMesh(mesh, core::vector3df(x*2,y*2-2,z*2)); mesh->getMeshBuffer(0)->getMaterial().setTexture(0, driver->getTexture("media/tile.png")); // a nice tiled interior for (x=-5; x<6; ++x) for (z=-5; z<6; ++z) BatchingMesh->addMesh(mesh, core::vector3df(x*2,-4,z*2)); BatchingMesh->update(); BatchingMesh->setMaterialFlag(EMF_LIGHTING, false); ISceneNode *node = smgr->addMeshSceneNode(BatchingMesh); node->setScale(core::vector3df(10,10,10)); node->setDebugDataVisible(EDS_BBOX_BUFFERS); BatchingMesh->drop(); /* To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ smgr->addCameraSceneNodeFPS(0, 100.0f, 0.1f); device->getCursorControl()->setVisible(false); int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255,113,113,133)); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw tmp(L"CBatchingMesh ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; tmp += L", mesh count: "; tmp += BatchingMesh->getSourceBufferCount(); device->setWindowCaption(tmp.c_str()); lastFPS = fps; } device->sleep(5,0); } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; }
/* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int example_terrain() { // create device IrrlichtDevice *device = startup(); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); //set other font //env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect<s32>(5,250,235,320), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); if ( terrain ) { terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); //terrain->setDebugDataVisible ( true ); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* If you need access to the terrain data you can also do this directly via the following code fragment. */ scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); // Work on data or get the IndexBuffer with a similar call. buffer->drop(); // When done drop the buffer again. } /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event reciever from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver EventReceiver_terrain receiver( device, terrain, skybox, skydome); device->setEventReceiver(&receiver); return run ( device ); }
/* Ok, now the main-function: First, we initialize the device, get the SourceManager and VideoDriver, load an animated mesh from .md2 and a map from .pk3. Because that's old stuff, I won't explain every step. Just take care of the maps position. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; //Instance of the EventReceiver MyEventReceiver receiver; //Initialise the engine IrrlichtDevice *device = createDevice(driverType, dimension2du(ResX,ResY), 32, fullScreen, false, false, &receiver); if (!device) return 1; ISceneManager *smgr = device->getSceneManager(); IVideoDriver *driver = device->getVideoDriver(); //Load model IAnimatedMesh *model = smgr->getMesh("../../media/sydney.md2"); if (!model) return 1; IAnimatedMeshSceneNode *model_node = smgr->addAnimatedMeshSceneNode(model); //Load texture if (model_node) { ITexture *texture = driver->getTexture("../../media/sydney.bmp"); model_node->setMaterialTexture(0,texture); model_node->setMD2Animation(scene::EMAT_RUN); //Disable lighting (we've got no light) model_node->setMaterialFlag(EMF_LIGHTING,false); } //Load map device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); IAnimatedMesh *map = smgr->getMesh("20kdm2.bsp"); if (map) { ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0)); //Set position map_node->setPosition(vector3df(-850,-220,-850)); } /* Now we create our four cameras. One is looking at the model from the front, one from the top and one from the side. In addition there's a FPS-camera which can be controlled by the user. */ // Create 3 fixed and one user-controlled cameras //Front camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0)); //Top camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0)); //Left camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0)); //User-controlled camera[3] = smgr->addCameraSceneNodeFPS(); // don't start at sydney's position if (camera[3]) camera[3]->setPosition(core::vector3df(-50,0,-50)); /* Create a variable for counting the fps and hide the mouse: */ //Hide mouse device->getCursorControl()->setVisible(false); //We want to count the fps int lastFPS = -1; /* There wasn't much new stuff - till now! Only by defining four cameras, the game won't be splitscreen. To do this you need several steps: - Set the viewport to the whole screen - Begin a new scene (Clear screen) - The following 3 steps are repeated for every viewport in the splitscreen - Set the viewport to the area you wish - Activate the camera which should be "linked" with the viewport - Render all objects - If you have a GUI: - Set the viewport the whole screen - Display the GUI - End scene Sounds a little complicated, but you'll see it isn't: */ while(device->run()) { //Set the viewpoint to the whole screen and begin scene driver->setViewPort(rect<s32>(0,0,ResX,ResY)); driver->beginScene(true,true,SColor(255,100,100,100)); //If SplitScreen is used if (SplitScreen) { //Activate camera1 smgr->setActiveCamera(camera[0]); //Set viewpoint to the first quarter (left top) driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera2 smgr->setActiveCamera(camera[1]); //Set viewpoint to the second quarter (right top) driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera3 smgr->setActiveCamera(camera[2]); //Set viewpoint to the third quarter (left bottom) driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY)); //Draw scene smgr->drawAll(); //Set viewport the last quarter (right bottom) driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY)); } //Activate camera4 smgr->setActiveCamera(camera[3]); //Draw scene smgr->drawAll(); driver->endScene(); /* As you can probably see, the image is rendered for every viewport seperately. That means, that you'll loose much performance. Ok, if you're aksing "How do I have to set the viewport to get this or that screen?", don't panic. It's really easy: In the rect-function you define 4 coordinates: - X-coordinate of the corner left top - Y-coordinate of the corner left top - X-coordinate of the corner right bottom - Y-coordinate of the corner right bottom That means, if you want to split the screen into 2 viewports you would give the following coordinates: - 1st viewport: 0,0,ResX/2,ResY - 2nd viewport: ResX/2,0,ResX,ResY If you didn't fully understand, just play arround with the example to check out what happens. Now we just view the current fps and shut down the engine, when the user wants to: */ //Get and show fps if (driver->getFPS() != lastFPS) { lastFPS = driver->getFPS(); core::stringw tmp = L"Irrlicht SplitScreen-Example (FPS: "; tmp += lastFPS; tmp += ")"; device->setWindowCaption(tmp.c_str()); } } //Delete device device->drop(); return 0; }
int main( ) { // Boring stuff: set up the scene, object & camera as usual // To make things more interesting, we add many Sydneys and a textured floor this time IrrlichtDevice* device = createDevice( DRIVER, dimension2d<s32>( 640, 480 ), 16, false, false, false, 0 ); IVideoDriver* driver = device->getVideoDriver( ); ISceneManager* smgr = device->getSceneManager( ); IGUIEnvironment* guienv = device->getGUIEnvironment( ); device->getFileSystem( )->changeWorkingDirectoryTo( MEDIA_DIRECTORY ); guienv->addStaticText( L"Sandbox", rect<s32>( 10, 10, 260, 22 ), true ); IAnimatedMesh* mesh = smgr->getMesh("sydney.md2"); IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices( ); u32 matid; switch( driver->getDriverType( ) ) { case EDT_OPENGL: matid = gpu->addHighLevelShaderMaterial( GL_V_MAT, "main", EVST_VS_1_1, GL_PLAIN, "main", EPST_PS_1_1, new CTexturesShaderCallback( ), EMT_SOLID, 1 ); break; case EDT_DIRECT3D8: case EDT_DIRECT3D9: default: matid = gpu->addHighLevelShaderMaterial( DX_V_MAT, "main", EVST_VS_1_1, DX_PLAIN, "main", EPST_PS_2_0, new CTexturesShaderCallback( ), EMT_SOLID, 0 ); } for( u8 x = 0u; x != 2u; ++ x ) for( u8 i = 0u; i != 5u; ++ i ) { IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); node->setMaterialType( (E_MATERIAL_TYPE) matid ); node->setPosition( vector3df( -x * 20.0f, 0.0f, i * 40.0f ) ); } ISceneNode* nodeF = smgr->addTerrainSceneNode( "terrain-heightmap.bmp" ); nodeF->setMaterialFlag(EMF_LIGHTING, false); nodeF->setMaterialTexture( 0, driver->getTexture("terrain-heightmap.bmp") ); nodeF->setPosition( vector3df( -512.0f, -50.0f, -512.0f ) ); nodeF->setScale( vector3df( 4.0f, 0.2f, 4.0f ) ); nodeF->setMaterialType( (E_MATERIAL_TYPE) matid ); ICameraSceneNode* cam1 = smgr->addCameraSceneNode( 0, vector3df( 0.0f, 0.0f, -40.0f ), vector3df( 0.0f, 5.0f, 50.0f ) ); IPostProc* ppRenderer1 = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor( 255, 130u, 180u, 230u ) ); CWaterPostProc* ppWater = new CWaterPostProc( ppRenderer1, dimension2di( 1024, 512 ), -22.0f ); ppWater->setTimer( device->getTimer( ) ); wchar_t tmp[255]; u8 t = 0u; while( device->run( ) ) { // cam1->setPosition( vector3df( 40.0f, 60.0f - (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.1f, -40.0f ) ); cam1->setPosition( vector3df( (device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.1f, -40.0f ) ); // cam1->setTarget( vector3df( (device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.1f, 0.0f ) ); // cam1->setTarget( cam1->getPosition( ) + vector3df( 0.0f, 0.0f, 10.0f ) ); // cam1->setTarget( vector3df( -(device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.2f, 50.0f ) ); driver->beginScene( false, driver->getDriverType( ) == video::EDT_DIRECT3D9 ); ppWater->render( NULL ); guienv->drawAll( ); driver->endScene( ); if( ++ t == 30u ) { t = 0u; swprintf(tmp, 255, L"%ls fps:%3d", driver->getName(), driver->getFPS() ); device->setWindowCaption( tmp ); } } delete ppWater; delete ppRenderer1; // Back to boring stuff device->drop(); return 0; }
int main() { sockets_init(); atexit(sockets_cleanup); /* Run unit tests */ if(ENABLE_TESTS) run_tests(); //return 0; //DEBUG /* Initialization */ srand(time(0)); g_viewing_range_nodes_mutex.Init(); assert(g_viewing_range_nodes_mutex.IsInitialized()); MyEventReceiver receiver; // create device and exit if creation failed /* Host selection */ char connect_name[100]; std::cout<<std::endl<<std::endl; std::cout<<"Address to connect to [empty = host a game]: "; std::cin.getline(connect_name, 100); bool hosting = false; if(connect_name[0] == 0){ snprintf(connect_name, 100, "127.0.0.1"); hosting = true; } std::cout<<"-> "<<connect_name<<std::endl; std::cout<<"Port [empty=30000]: "; char templine[100]; std::cin.getline(templine, 100); unsigned short port; if(templine[0] == 0) port = 30000; else port = atoi(templine); /* Resolution selection */ u16 screenW = 800; u16 screenH = 600; /* u16 resolutions[][2] = { {640,480}, {800,600}, {1024,768}, {1280,1024} }; u16 res_count = sizeof(resolutions)/sizeof(resolutions[0]); std::cout<<"Select window resolution " <<"(type a number and press enter):"<<std::endl; for(u16 i=0; i<res_count; i++) { std::cout<<(i+1)<<": "<<resolutions[i][0]<<"x" <<resolutions[i][1]<<std::endl; } u16 r0; std::cin>>r0; if(r0 > res_count || r0 == 0) r0 = 0; u16 screenW = resolutions[r0-1][0]; u16 screenH = resolutions[r0-1][1]; */ // video::E_DRIVER_TYPE driverType; #ifdef _WIN32 //driverType = video::EDT_DIRECT3D9; // Doesn't seem to work driverType = video::EDT_OPENGL; #else driverType = video::EDT_OPENGL; #endif IrrlichtDevice *device; device = createDevice(driverType, core::dimension2d<u32>(screenW, screenH), 16, false, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. /* Run some speed tests */ //SpeedTests(device); /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); // These make the textures not to show at all //driver->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT); //driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_SPEED ); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); gui::IGUIFont* font = guienv->getFont("../data/fontlucida.png"); if(font) skin->setFont(font); //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); const wchar_t *text = L"Loading..."; core::vector2d<s32> center(screenW/2, screenH/2); core::dimension2d<u32> textd = font->getDimension(text); std::cout<<"Text w="<<textd.Width<<" h="<<textd.Height<<std::endl; // Have to add a bit to disable the text from word wrapping //core::vector2d<s32> textsize(textd.Width+4, textd.Height); core::vector2d<s32> textsize(300, textd.Height); core::rect<s32> textrect(center - textsize/2, center + textsize/2); gui::IGUIStaticText *gui_loadingtext = guienv->addStaticText( text, textrect, false, false); gui_loadingtext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); driver->beginScene(true, true, video::SColor(255,0,0,0)); guienv->drawAll(); driver->endScene(); video::SMaterial materials[MATERIALS_COUNT]; for(u16 i=0; i<MATERIALS_COUNT; i++) { materials[i].Lighting = false; materials[i].BackfaceCulling = false; const char *filename = g_material_filenames[i]; if(filename != NULL){ video::ITexture *t = driver->getTexture(filename); if(t == NULL){ std::cout<<"Texture could not be loaded: \"" <<filename<<"\""<<std::endl; return 1; } materials[i].setTexture(0, driver->getTexture(filename)); } //materials[i].setFlag(video::EMF_TEXTURE_WRAP, video::ETC_REPEAT); materials[i].setFlag(video::EMF_BILINEAR_FILTER, false); //materials[i].setFlag(video::EMF_ANISOTROPIC_FILTER, false); } // Make a scope here for the client so that it gets removed // before the irrlicht device { std::cout<<"Creating server and client"<<std::endl; Server *server = NULL; if(hosting){ server = new Server(); server->start(port); } Client client(smgr, materials); Address connect_address(0,0,0,0, port); try{ connect_address.Resolve(connect_name); } catch(ResolveError &e) { std::cout<<"Couldn't resolve address"<<std::endl; return 0; } client.connect(connect_address); Player *player = client.getLocalPlayer(); /* Create the camera node */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNode( 0, // Camera parent v3f(BS*100, BS*2, BS*100), // Look from v3f(BS*100+1, BS*2, BS*100), // Look to -1 // Camera ID ); if(camera == NULL) return 1; camera->setFOV(FOV_ANGLE); // Just so big a value that everything rendered is visible camera->setFarValue(BS*1000); f32 camera_yaw = 0; // "right/left" f32 camera_pitch = 0; // "up/down" // Random constants #define WALK_ACCELERATION (4.0 * BS) #define WALKSPEED_MAX (4.0 * BS) //#define WALKSPEED_MAX (20.0 * BS) f32 walk_acceleration = WALK_ACCELERATION; f32 walkspeed_max = WALKSPEED_MAX; /* The mouse cursor needs not be visible, so we hide it via the irr::IrrlichtDevice::ICursorControl. */ device->getCursorControl()->setVisible(false); gui_loadingtext->remove(); gui::IGUIStaticText *guitext = guienv->addStaticText( L"Minetest-c55", core::rect<s32>(5, 5, 5+300, 5+textsize.Y), false, false); /* Main loop */ bool first_loop_after_window_activation = true; s32 lastFPS = -1; // Time is in milliseconds u32 lasttime = device->getTimer()->getTime(); while(device->run()) { /* Time difference calculation */ u32 time = device->getTimer()->getTime(); f32 dtime; // in seconds if(time > lasttime) dtime = (time - lasttime) / 1000.0; else dtime = 0; lasttime = time; updateViewingRange(dtime); // Collected during the loop and displayed core::list< core::aabbox3d<f32> > hilightboxes; /* Special keys */ if(receiver.IsKeyDown(irr::KEY_ESCAPE)) { break; } /* Player speed control */ v3f move_direction = v3f(0,0,1); move_direction.rotateXZBy(camera_yaw); v3f speed = v3f(0,0,0); if(receiver.IsKeyDown(irr::KEY_KEY_W)) { speed += move_direction; } if(receiver.IsKeyDown(irr::KEY_KEY_S)) { speed -= move_direction; } if(receiver.IsKeyDown(irr::KEY_KEY_A)) { speed += move_direction.crossProduct(v3f(0,1,0)); } if(receiver.IsKeyDown(irr::KEY_KEY_D)) { speed += move_direction.crossProduct(v3f(0,-1,0)); } if(receiver.IsKeyDown(irr::KEY_SPACE)) { if(player->touching_ground){ //player_speed.Y = 30*BS; //player.speed.Y = 5*BS; player->speed.Y = 6.5*BS; } } // The speed of the player (Y is ignored) speed = speed.normalize() * walkspeed_max; f32 inc = walk_acceleration * BS * dtime; if(player->speed.X < speed.X - inc) player->speed.X += inc; else if(player->speed.X > speed.X + inc) player->speed.X -= inc; else if(player->speed.X < speed.X) player->speed.X = speed.X; else if(player->speed.X > speed.X) player->speed.X = speed.X; if(player->speed.Z < speed.Z - inc) player->speed.Z += inc; else if(player->speed.Z > speed.Z + inc) player->speed.Z -= inc; else if(player->speed.Z < speed.Z) player->speed.Z = speed.Z; else if(player->speed.Z > speed.Z) player->speed.Z = speed.Z; /* Process environment */ { //TimeTaker("client.step(dtime)", device); client.step(dtime); } if(server != NULL){ //TimeTaker("server->step(dtime)", device); server->step(dtime); } /* Mouse and camera control */ if(device->isWindowActive()) { if(first_loop_after_window_activation){ first_loop_after_window_activation = false; } else{ s32 dx = device->getCursorControl()->getPosition().X - 320; s32 dy = device->getCursorControl()->getPosition().Y - 240; camera_yaw -= dx*0.2; camera_pitch += dy*0.2; if(camera_pitch < -89.9) camera_pitch = -89.9; if(camera_pitch > 89.9) camera_pitch = 89.9; } device->getCursorControl()->setPosition(320, 240); } else{ first_loop_after_window_activation = true; } v3f camera_direction = v3f(0,0,1); camera_direction.rotateYZBy(camera_pitch); camera_direction.rotateXZBy(camera_yaw); v3f camera_position = player->getPosition() + v3f(0, BS+BS/2, 0); camera->setPosition(camera_position); camera->setTarget(camera_position + camera_direction); if(FIELD_OF_VIEW_TEST){ //client.m_env.getMap().updateCamera(v3f(0,0,0), v3f(0,0,1)); client.updateCamera(v3f(0,0,0), v3f(0,0,1)); } else{ //client.m_env.getMap().updateCamera(camera_position, camera_direction); client.updateCamera(camera_position, camera_direction); } /* Calculate what block is the crosshair pointing to */ //u32 t1 = device->getTimer()->getTime(); f32 d = 4; // max. distance core::line3d<f32> shootline(camera_position, camera_position + camera_direction * BS * (d+1)); bool nodefound = false; v3s16 nodepos; v3s16 neighbourpos; core::aabbox3d<f32> nodefacebox; f32 mindistance = BS * 1001; v3s16 pos_i = Map::floatToInt(player->getPosition()); s16 a = d; s16 ystart = pos_i.Y + 0 - (camera_direction.Y<0 ? a : 1); s16 zstart = pos_i.Z - (camera_direction.Z<0 ? a : 1); s16 xstart = pos_i.X - (camera_direction.X<0 ? a : 1); s16 yend = pos_i.Y + 1 + (camera_direction.Y>0 ? a : 1); s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1); s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1); for(s16 y = ystart; y <= yend; y++){ for(s16 z = zstart; z <= zend; z++){ for(s16 x = xstart; x <= xend; x++) { try{ //if(client.m_env.getMap().getNode(x,y,z).d == MATERIAL_AIR){ if(client.getNode(v3s16(x,y,z)).d == MATERIAL_AIR){ continue; } }catch(InvalidPositionException &e){ continue; } v3s16 np(x,y,z); v3f npf = Map::intToFloat(np); f32 d = 0.01; v3s16 directions[6] = { v3s16(0,0,1), // back v3s16(0,1,0), // top v3s16(1,0,0), // right v3s16(0,0,-1), v3s16(0,-1,0), v3s16(-1,0,0), }; for(u16 i=0; i<6; i++){ //{u16 i=3; v3f dir_f = v3f(directions[i].X, directions[i].Y, directions[i].Z); v3f centerpoint = npf + dir_f * BS/2; f32 distance = (centerpoint - camera_position).getLength(); if(distance < mindistance){ //std::cout<<"for centerpoint=("<<centerpoint.X<<","<<centerpoint.Y<<","<<centerpoint.Z<<"): distance < mindistance"<<std::endl; //std::cout<<"npf=("<<npf.X<<","<<npf.Y<<","<<npf.Z<<")"<<std::endl; core::CMatrix4<f32> m; m.buildRotateFromTo(v3f(0,0,1), dir_f); // This is the back face v3f corners[2] = { v3f(BS/2, BS/2, BS/2), v3f(-BS/2, -BS/2, BS/2+d) }; for(u16 j=0; j<2; j++){ m.rotateVect(corners[j]); corners[j] += npf; //std::cout<<"box corners["<<j<<"]: ("<<corners[j].X<<","<<corners[j].Y<<","<<corners[j].Z<<")"<<std::endl; } //core::aabbox3d<f32> facebox(corners[0],corners[1]); core::aabbox3d<f32> facebox(corners[0]); facebox.addInternalPoint(corners[1]); if(facebox.intersectsWithLine(shootline)){ nodefound = true; nodepos = np; neighbourpos = np + directions[i]; mindistance = distance; nodefacebox = facebox; } } } }}} if(nodefound){ //std::cout<<"nodefound == true"<<std::endl; //std::cout<<"nodepos=("<<nodepos.X<<","<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl; //std::cout<<"neighbourpos=("<<neighbourpos.X<<","<<neighbourpos.Y<<","<<neighbourpos.Z<<")"<<std::endl; static v3s16 nodepos_old(-1,-1,-1); if(nodepos != nodepos_old){ std::cout<<"Pointing at ("<<nodepos.X<<"," <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl; nodepos_old = nodepos; /*wchar_t positiontext[20]; swprintf(positiontext, 20, L"(%i,%i,%i)", nodepos.X, nodepos.Y, nodepos.Z); positiontextgui->setText(positiontext);*/ } hilightboxes.push_back(nodefacebox); if(receiver.leftclicked){ std::cout<<"Removing block (MapNode)"<<std::endl; u32 time1 = device->getTimer()->getRealTime(); //client.m_env.getMap().removeNodeAndUpdate(nodepos); client.removeNode(nodepos); u32 time2 = device->getTimer()->getRealTime(); u32 dtime = time2 - time1; std::cout<<"Took "<<dtime<<"ms"<<std::endl; } if(receiver.rightclicked){ std::cout<<"Placing block (MapNode)"<<std::endl; u32 time1 = device->getTimer()->getRealTime(); /*f32 light = client.m_env.getMap().getNode(neighbourpos).light; MapNode n; n.d = g_selected_material; client.m_env.getMap().setNode(neighbourpos, n); client.m_env.getMap().nodeAddedUpdate(neighbourpos, light);*/ MapNode n; n.d = g_selected_material; client.addNode(neighbourpos, n); u32 time2 = device->getTimer()->getRealTime(); u32 dtime = time2 - time1; std::cout<<"Took "<<dtime<<"ms"<<std::endl; } } else{ //std::cout<<"nodefound == false"<<std::endl; //positiontextgui->setText(L""); } receiver.leftclicked = false; receiver.rightclicked = false; /* Update gui stuff */ static u8 old_selected_material = MATERIAL_AIR; if(g_selected_material != old_selected_material) { old_selected_material = g_selected_material; wchar_t temptext[50]; swprintf(temptext, 50, L"Minetest-c55 (F: material=%i)", g_selected_material); guitext->setText(temptext); } /* Drawing begins */ /* Background color is choosen based on whether the player is much beyond the initial ground level */ /*video::SColor bgcolor; v3s16 p0 = Map::floatToInt(player->position); s16 gy = client.m_env.getMap().getGroundHeight(v2s16(p0.X, p0.Z)); if(p0.Y > gy - MAP_BLOCKSIZE) bgcolor = video::SColor(255,90,140,200); else bgcolor = video::SColor(255,0,0,0);*/ video::SColor bgcolor = video::SColor(255,90,140,200); driver->beginScene(true, true, bgcolor); //std::cout<<"smgr->drawAll()"<<std::endl; smgr->drawAll(); core::vector2d<s32> displaycenter(screenW/2,screenH/2); driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0), displaycenter + core::vector2d<s32>(10,0), video::SColor(255,255,255,255)); driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10), displaycenter + core::vector2d<s32>(0,10), video::SColor(255,255,255,255)); video::SMaterial m; m.Thickness = 10; m.Lighting = false; driver->setMaterial(m); for(core::list< core::aabbox3d<f32> >::Iterator i=hilightboxes.begin(); i != hilightboxes.end(); i++){ driver->draw3DBox(*i, video::SColor(255,0,0,0)); } guienv->drawAll(); driver->endScene(); /* Drawing ends */ u16 fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Minetest ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } /*} else device->yield();*/ } if(server != NULL) delete server; } // client is deleted at this point /* In the end, delete the Irrlicht device. */ device->drop(); return 0; }
int main( ) { // Boring stuff: set up the scene, object & camera as usual // To make things more interesting, we add many Sydneys and a textured floor this time IrrlichtDevice* device = createDevice( DRIVER, dimension2d<s32>( 640, 480 ), 16, false, false, false, 0 ); IVideoDriver* driver = device->getVideoDriver( ); ISceneManager* smgr = device->getSceneManager( ); IGUIEnvironment* guienv = device->getGUIEnvironment( ); device->getFileSystem( )->changeWorkingDirectoryTo( MEDIA_DIRECTORY ); guienv->addStaticText( L"Heat Haze (with Depth dependence)", rect<s32>( 10, 10, 260, 22 ), true ); IAnimatedMesh* mesh = smgr->getMesh("sydney.md2"); ISceneManager* smgr2 = smgr->createNewSceneManager( false ); ISceneNode* rootnode2 = smgr2->getRootSceneNode( ); IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices( ); u32 matid, matid2; switch( driver->getDriverType( ) ) { case EDT_OPENGL: matid = gpu->addHighLevelShaderMaterial( GL_V_MAT, "main", EVST_VS_1_1, GL_PLAIN, "main", EPST_PS_1_1, new CTexturesShaderCallback( ), EMT_SOLID, 1 ); matid2 = gpu->addHighLevelShaderMaterial( GL_V_MAT, "main", EVST_VS_1_1, GL_HEATSOURCE, "main", EPST_PS_1_1, new CTexturesShaderCallback( ), EMT_TRANSPARENT_ALPHA_CHANNEL, 1 ); break; case EDT_DIRECT3D8: case EDT_DIRECT3D9: default: matid = gpu->addHighLevelShaderMaterial( DX_V_MAT, "main", EVST_VS_1_1, DX_PLAIN, "main", EPST_PS_2_0, new CTexturesShaderCallback( ), EMT_SOLID, 0 ); matid2 = gpu->addHighLevelShaderMaterial( DX_V_MAT, "main", EVST_VS_1_1, DX_HEATSOURCE, "main", EPST_PS_2_0, new CTexturesShaderCallback( ), EMT_TRANSPARENT_ALPHA_CHANNEL, 0 ); } for( u8 x = 0u; x != 2u; ++ x ) for( u8 i = 0u; i != 5u; ++ i ) { IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); node->setMaterialType( (E_MATERIAL_TYPE) matid ); node->setPosition( vector3df( -x * 20.0f, 0.0f, i * 40.0f ) ); ISceneNode* node2 = smgr2->addBillboardSceneNode( rootnode2, dimension2df( 30.0f, 80.0f ), vector3df( -x * 20.0f, 30.0f, i * 40.0f ) ); node2->setMaterialFlag(EMF_LIGHTING, false); node2->setMaterialType( EMT_TRANSPARENT_ADD_COLOR ); node2->setMaterialTexture( 0, driver->getTexture("fireball.bmp") ); node2->setMaterialType( (E_MATERIAL_TYPE) matid2 ); } ISceneNode* nodeF = smgr->addMeshSceneNode( smgr->addHillPlaneMesh( "", dimension2df( 200.0f, 200.0f ), dimension2d<u32>( 10, 10 ), NULL, 0.0f, dimension2df( 0.0f, 0.0f ), dimension2df( 100.0f, 100.0f ) ) ); nodeF->setMaterialFlag(EMF_LIGHTING, false); nodeF->setMaterialTexture( 0, driver->getTexture("terrain-heightmap.bmp") ); nodeF->setPosition( vector3df( 0.0f, -22.0f, 0.0f ) ); nodeF->setMaterialType( (E_MATERIAL_TYPE) matid ); ICameraSceneNode* cam1 = smgr->addCameraSceneNode( 0, vector3df( 40.0f, 60.0f, -40.0f ), vector3df( 0.0f, 5.0f, 50.0f ) ); ICameraSceneNode* cam2 = smgr2->addCameraSceneNode( rootnode2, vector3df( 40.0f, 60.0f, -40.0f ), vector3df( 0.0f, 5.0f, 50.0f ) ); IPostProc* ppRenderer1 = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor( 255u, 100u, 101u, 140u ) ); IPostProc* ppRenderer2 = new CRendererPostProc( smgr2, dimension2di( 1024, 512 ), true, true, SColor( 255u, 0u, 0u, 0u ) ); CEffectPostProc* ppHaze = new CEffectPostProc( ppRenderer1, dimension2di( 1024, 512 ), PP_HAZEDEPTH ); ppHaze->setInput( 1, ppRenderer2 ); ppHaze->setTimer( device->getTimer( ) ); // These variables aren't important - they are just for showing the FPS wchar_t tmp[255]; u8 t = 0u; while( device->run( ) ) { cam1->setPosition( vector3df( 40.0f, 60.0f - (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.1f, -40.0f ) ); cam1->setTarget( vector3df( -(device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.2f, 50.0f ) ); cam2->setPosition( cam1->getPosition( ) ); cam2->setTarget( cam1->getTarget( ) ); cam2->setUpVector( cam1->getUpVector( ) ); driver->beginScene( false, driver->getDriverType( ) == video::EDT_DIRECT3D9 ); ppHaze->render( NULL ); guienv->drawAll( ); driver->endScene( ); // Show the current FPS if( ++ t == 30u ) { t = 0u; swprintf(tmp, 255, L"%ls fps:%3d", driver->getName(), driver->getFPS() ); device->setWindowCaption( tmp ); } } delete ppHaze; delete ppRenderer1; delete ppRenderer2; // Back to boring stuff device->drop(); return 0; }
int main( ) { // Boring stuff: set up the scene, object & camera as usual // To make things more interesting, we add many Sydneys and a textured floor this time IrrlichtDevice* device = createDevice( DRIVER, dimension2d<s32>( 640, 480 ), 16, false, false, false, 0 ); IVideoDriver* driver = device->getVideoDriver( ); ISceneManager* smgr = device->getSceneManager( ); IGUIEnvironment* guienv = device->getGUIEnvironment( ); device->getFileSystem( )->changeWorkingDirectoryTo( MEDIA_DIRECTORY ); guienv->addStaticText( L"Depth of Field", rect<s32>( 10, 10, 260, 22 ), true ); IAnimatedMesh* mesh = smgr->getMesh("sydney.md2"); // Create the required material. This is a simple shader which draws the texture with no lights. // Use GL_PLAIN1 / DX_PLANE1 or GL_PLAIN2 / DX_PLANE2 to support 1 or 2 basic point-lights u32 matid; IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices( ); switch( driver->getDriverType( ) ) { case EDT_OPENGL: matid = gpu->addHighLevelShaderMaterial( GL_V_MAT, "main", EVST_VS_1_1, GL_PLAIN, "main", EPST_PS_1_1, new CTexturesShaderCallback( ), EMT_SOLID, 1 ); break; case EDT_DIRECT3D8: case EDT_DIRECT3D9: default: matid = gpu->addHighLevelShaderMaterial( DX_V_MAT, "main", EVST_VS_1_1, DX_PLAIN, "main", EPST_PS_2_0, new CTexturesShaderCallback( ), EMT_SOLID, 0 ); } for( u8 x = 0u; x != 2u; ++ x ) for( u8 i = 0u; i != 5u; ++ i ) { IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); node->setMaterialFlag(EMF_LIGHTING, false); node->setMD2Animation(scene::EMAT_STAND); node->setMaterialTexture( 0, driver->getTexture("sydney.bmp") ); node->setMaterialType( (E_MATERIAL_TYPE) matid ); node->setPosition( vector3df( -x * 20.0f, 0.0f, i * 40.0f ) ); } ISceneNode* node2 = smgr->addMeshSceneNode( smgr->addHillPlaneMesh( "", dimension2df( 200.0f, 200.0f ), dimension2d<u32>( 10, 10 ), NULL, 0.0f, dimension2df( 0.0f, 0.0f ), dimension2df( 100.0f, 100.0f ) ) ); node2->setMaterialFlag(EMF_LIGHTING, false); node2->setMaterialTexture( 0, driver->getTexture("terrain-heightmap.bmp") ); node2->setMaterialType( (E_MATERIAL_TYPE) matid ); node2->setPosition( vector3df( 0.0f, -22.0f, 0.0f ) ); ICameraSceneNode* cam = smgr->addCameraSceneNode( 0, vector3df( 40.0f, 60.0f, -40.0f ), vector3df( 0.0f, 5.0f, 50.0f ) ); IPostProc* ppRenderer = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor( 255u, 100u, 101u, 140u ) ); CEffectPostProc* ppBlurDOF = new CEffectPostProc( ppRenderer, dimension2di( 1024, 512 ), PP_BLURDOF ); // We could set parameters on creation, but no need since we will animate it anyway. // Parameters are: near blur, near focus, far focus, far blur, blur level // You can also use PP_BLURDOFNEAR or PP_BLURDOFFAR to have only near or far blurring // These variables aren't important - they are just for showing the FPS wchar_t tmp[255]; u8 t = 0u; while( device->run( ) ) { // Change the camera angle cam->setTarget( vector3df( -(device->getCursorControl( )->getPosition( ).X - 320.0f) * 0.1f, (device->getCursorControl( )->getPosition( ).Y - 240.0f) * 0.2f, 0.0f ) ); // Animate the depth of field: f32 p = sinf( device->getTimer( )->getTime( ) * 0.0005f ) * 0.5f - 0.2f; ppBlurDOF->setParameters( p * 100.0f + 80.0f, p * 100.0f + 110.0f, p * 100.0f + 160.0f, p * 100.0f + 240.0f, 0.01f ); driver->beginScene( false, driver->getDriverType( ) == video::EDT_DIRECT3D9 ); ppBlurDOF->render( NULL ); guienv->drawAll( ); driver->endScene( ); // Show the current FPS if( ++ t == 30u ) { t = 0u; swprintf(tmp, 255, L"%ls fps:%3d", driver->getName(), driver->getFPS() ); device->setWindowCaption( tmp ); } } delete ppBlurDOF; delete ppRenderer; // Back to boring stuff device->drop(); return 0; }
void android_main(struct android_app* app) #endif { #ifdef _IRR_ANDROID_PLATFORM_ app_dummy(); const bool shadows = false; video::E_DRIVER_TYPE driverType=video::EDT_OGLES1; #else // ask if user would like shadows char i; printf("Please press 'y' if you want to use realtime shadows.\n"); // std::cin >> i; const bool shadows = true;//(i == 'y'); // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) { #ifdef _IRR_ANDROID_PLATFORM_ return; #else return 1; #endif } #endif /* Create device and exit if creation failed. We make the stencil flag optional to avoid slow screen modes for runs without shadows. */ #ifdef _IRR_ANDROID_PLATFORM_ struct ue::SIrrlichtCreationParameters p; p.DriverType = driverType; // The android app object is needed by the irrlicht device. p.PrivateData = app; p.WindowSize = core::dimension2d<u32>(1280,800); IrrlichtDevice *device = createDeviceEx(p); #else IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, shadows); #endif if (device == 0) { #ifdef _IRR_ANDROID_PLATFORM_ return; #else return 1; // could not create selected driver. #endif } video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); scene::ISceneNode* node = 0; /* For our environment, we load a .3ds file. It is a small room I modelled with Anim8or and exported into the 3ds format because the Irrlicht Engine does not support the .an8 format. I am a very bad 3d graphic artist, and so the texture mapping is not very nice in this model. Luckily I am a better programmer than artist, and so the Irrlicht Engine is able to create a cool texture mapping for me: Just use the mesh manipulator and create a planar texture mapping for the mesh. If you want to see the mapping I made with Anim8or, uncomment this line. I also did not figure out how to set the material right in Anim8or, it has a specular light color which I don't really like. I'll switch it off too with this code. */ #ifdef _IRR_ANDROID_PLATFORM_ scene::IAnimatedMesh* mesh = smgr->getMesh("media/room.3ds"); #else scene::IAnimatedMesh* mesh = smgr->getMesh("../media/room.3ds"); #endif if (mesh) { smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f); node = smgr->addAnimatedMeshSceneNode(mesh); if (node) { ((scene::IAnimatedMeshSceneNode*)node)->addShadowVolumeSceneNode(); #ifdef _IRR_ANDROID_PLATFORM_ node->setMaterialTexture(0, driver->getTexture("media/wall.jpg")); #else node->setMaterialTexture(0, driver->getTexture("../media/wall.jpg")); #endif node->getMaterial(0).SpecularColor.set(0,0,0,0); } } /* Now, for the first special effect: Animated water. It works like this: The WaterSurfaceSceneNode takes a mesh as input and makes it wave like a water surface. And if we let this scene node use a nice material like the EMT_REFLECTION_2_LAYER, it looks really cool. We are doing this with the next few lines of code. As input mesh, we create a hill plane mesh, without hills. But any other mesh could be used for this, you could even use the room.3ds (which would look really strange) if you want to. */ mesh = 0;//smgr->addHillPlaneMesh( "myHill", // core::dimension2d<f32>(20,20), // core::dimension2d<u32>(40,40), 0, 0, // core::dimension2d<f32>(0,0), // core::dimension2d<f32>(10,10)); if (mesh) { node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f); if (node) { node->setPosition(core::vector3df(0,7,0)); #ifdef _IRR_ANDROID_PLATFORM_ node->setMaterialTexture(0, driver->getTexture("media/stones.jpg")); node->setMaterialTexture(1, driver->getTexture("media/water.jpg")); #else node->setMaterialTexture(0, driver->getTexture("../media/stones.jpg")); node->setMaterialTexture(1, driver->getTexture("../media/water.jpg")); #endif node->setMaterialType(video::EMT_REFLECTION_2_LAYER); } } /* The second special effect is very basic, I bet you saw it already in some Irrlicht Engine demos: A transparent billboard combined with a dynamic light. We simply create a light scene node, let it fly around, and to make it look more cool, we attach a billboard scene node to it. */ // create light node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 800.0f); if (node) { scene::ISceneNodeAnimator* anim = 0; anim = smgr->createFlyCircleAnimator (core::vector3df(0,150,0),250.0f); node->addAnimator(anim); anim->drop(); } // attach billboard to light node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50)); if (node) { node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); #ifdef _IRR_ANDROID_PLATFORM_ node->setMaterialTexture(0, driver->getTexture("media/particlewhite.bmp")); #else node->setMaterialTexture(0, driver->getTexture("../media/particlewhite.bmp")); #endif } /* Next we add a volumetric light node, which adds a glowing fake area light to the scene. Like with the billboards and particle systems we also assign a texture for the desired effect, though this time we'll use a texture animator to create the illusion of a magical glowing area effect. */ scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1, 32, // Subdivisions on U axis 32, // Subdivisions on V axis video::SColor(0, 255, 255, 255), // foot color video::SColor(0, 0, 0, 0)); // tail color if (n) { n->setScale(core::vector3df(56.0f, 56.0f, 56.0f)); n->setPosition(core::vector3df(-120,50,40)); // load textures for animation core::array<video::ITexture*> textures; for (s32 g=7; g > 0; --g) { core::stringc tmp; #ifdef _IRR_ANDROID_PLATFORM_ tmp = "media/portal"; #else tmp = "../media/portal"; #endif tmp += g; tmp += ".bmp"; video::ITexture* t = driver->getTexture( tmp.c_str() ); textures.push_back(t); } // create texture animator scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(textures, 150); // add the animator n->addAnimator(glow); // drop the animator because it was created with a create() function glow->drop(); } /* The next special effect is a lot more interesting: A particle system. The particle system in the Irrlicht Engine is quite modular and extensible, but yet easy to use. There is a particle system scene node into which you can put a particle emitter, which makes particles come out of nothing. These emitters are quite flexible and usually have lots of parameters like direction, amount, and color of the particles they create. There are different emitters, for example a point emitter which lets particles pop out at a fixed point. If the particle emitters available in the engine are not enough for you, you can easily create your own ones, you'll simply have to create a class derived from the IParticleEmitter interface and attach it to the particle system using setEmitter(). In this example we create a box particle emitter, which creates particles randomly inside a box. The parameters define the box, direction of the particles, minimal and maximal new particles per second, color, and minimal and maximal lifetime of the particles. Because only with emitters particle system would be a little bit boring, there are particle affectors which modify particles while they fly around. Affectors can be added to a particle system for simulating additional effects like gravity or wind. The particle affector we use in this example is an affector which modifies the color of the particles: It lets them fade out. Like the particle emitters, additional particle affectors can also be implemented by you, simply derive a class from IParticleAffector and add it with addAffector(). After we set a nice material to the particle system, we have a cool looking camp fire. By adjusting material, texture, particle emitter, and affector parameters, it is also easily possible to create smoke, rain, explosions, snow, and so on. */ // create a particle system scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false); if (ps) { scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d<f32>(-7,0,-7,7,1,7), // emitter size core::vector3df(0.0f,0.06f,0.0f), // initial direction 80,100, // emit rate video::SColor(0,255,255,255), // darkest color video::SColor(0,255,255,255), // brightest color 800,2000,0, // min and max age, angle core::dimension2df(10.f,10.f), // min size core::dimension2df(20.f,20.f)); // max size ps->setEmitter(em); // this grabs the emitter em->drop(); // so we can drop it here without deleting it scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); ps->addAffector(paf); // same goes for the affector paf->drop(); ps->setPosition(core::vector3df(-70,60,40)); ps->setScale(core::vector3df(2,2,2)); ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); ps->setMaterialTexture(0, driver->getTexture("../media/fire.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); } /* As our last special effect, we want a dynamic shadow be casted from an animated character. For this we load a DirectX .x model and place it into our world. For creating the shadow, we simply need to call addShadowVolumeSceneNode(). The color of shadows is only adjustable globally for all shadows, by calling ISceneManager::setShadowColor(). Voila, here is our dynamic shadow. Because the character is a little bit too small for this scene, we make it bigger using setScale(). And because the character is lighted by a dynamic light, we need to normalize the normals to make the lighting on it correct. This is always necessary if the scale of a dynamic lighted model is not (1,1,1). Otherwise it would get too dark or too bright because the normals will be scaled too. */ // add animated character #ifdef _IRR_ANDROID_PLATFORM_ mesh = smgr->getMesh("media/dwarf.x"); #else mesh = smgr->getMesh("../media/metaioman.md2"); #endif scene::IAnimatedMeshSceneNode* anode = 0; anode = smgr->addAnimatedMeshSceneNode(mesh); anode->setPosition(core::vector3df(-50,20,-60)); anode->setAnimationSpeed(15); // add shadow anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(150,0,0,0)); // make the model a little bit bigger and normalize its normals // because of the scaling, for correct lighting anode->setScale(core::vector3df(2,2,2)); anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); /* Finally we simply have to draw everything, that's all. */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-50,50,-150)); camera->setFarValue(10000.0f); // this increase a shadow visible range. // disable mouse cursor device->getCursorControl()->setVisible(false); s32 lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); const s32 fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - SpecialFX example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); #ifdef _IRR_ANDROID_PLATFORM_ return; #else return 0; #endif }
/* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType=driverType; params.WindowSize=core::dimension2d<u32>(640, 480); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // add irrlicht logo env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"), core::position2d<s32>(10,10)); //set other font env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); // add some help text env->addStaticText( L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", core::rect<s32>(10,421,250,475), true, true, 0, -1, true); // add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it. To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times. */ // add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( "../../media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); /* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */ // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); /* To make the user be able to switch between normal and wireframe mode, we create an instance of the event receiver from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'. */ // create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( driver->getTexture("../../media/irrlicht2_up.jpg"), driver->getTexture("../../media/irrlicht2_dn.jpg"), driver->getTexture("../../media/irrlicht2_lf.jpg"), driver->getTexture("../../media/irrlicht2_rt.jpg"), driver->getTexture("../../media/irrlicht2_ft.jpg"), driver->getTexture("../../media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); // create event receiver MyEventReceiver receiver(terrain, skybox, skydome); device->setEventReceiver(&receiver); /* That's it, draw everything. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0 ); smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin str += " Height: "; str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z); device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); const io::path mediaPath = getExampleMediaPath(); device->getFileSystem()->addFileArchive(mediaPath + "map-20kdm2.pk3"); scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::IMeshSceneNode* q3node = 0; // The Quake mesh is pickable, but doesn't get highlighted. if (q3levelmesh) q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); /* So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here comes something different: We create a triangle selector. A triangle selector is a class which can fetch the triangles from scene nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an OctreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels. After we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not need to care for the selector, for example dropping it after we do not need it anymore. */ scene::ITriangleSelector* selector = 0; if (q3node) { q3node->setPosition(core::vector3df(-1350,-130,-1400)); selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); // We're not done with this selector yet, so don't drop it. } /* We add a first person shooter camera to the scene so that we can see and move in the quake 3 level like in tutorial 2. But this, time, we add a special animator to the camera: A Collision Response animator. This animator modifies the scene node to which it is attached to in order to prevent it moving through walls, and to add gravity to it. The only thing we have to tell the animator is how the world looks like, how big the scene node is, how much gravity to apply and so on. After the collision response animator is attached to the camera, we do not have to do anything more for collision detection, anything is done automatically. The rest of the collision detection code below is for picking. And please note another cool feature: The collision response animator can be attached also to all other scene nodes, not only to cameras. And it can be mixed with other scene node animators. In this way, collision detection and response in the Irrlicht engine is really easy. Now we'll take a closer look on the parameters of createCollisionResponseAnimator(). The first parameter is the TriangleSelector, which specifies how the world, against collision detection is done looks like. The second parameter is the scene node, which is the object, which is affected by collision detection, in our case it is the camera. The third defines how big the object is, it is the radius of an ellipsoid. Try it out and change the radius to smaller values, the camera will be able to move closer to walls after this. The next parameter is the direction and speed of gravity. We'll set it to (0, -10, 0), which approximates to realistic gravity, assuming that our units are metres. You could set it to (0,0,0) to disable gravity. And the last value is just a translation: Without this, the ellipsoid with which collision detection is done would be around the camera, and the camera would be in the middle of the ellipsoid. But as human beings, we are used to have our eyes on top of the body, with which we collide with our world, not in the middle of it. So we place the scene node 50 units over the center of the ellipsoid with this parameter. And that's it, collision detection works now. */ // Set a jump speed of 3 units per second, which gives a fairly realistic jump // when used with the gravity of (0, -10, 0) in the collision response animator. scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, .3f, ID_IsNotPickable, 0, 0, true, 3.f); camera->setPosition(core::vector3df(50,50,-60)); camera->setTarget(core::vector3df(-70,30,-60)); if (selector) { scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30,50,30), core::vector3df(0,-10,0), core::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->getCursorControl()->setVisible(false); // Add the billboard. scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); bill->setMaterialTexture(0, driver->getTexture(mediaPath + "particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d<f32>(20.0f, 20.0f)); bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it /* Add 3 animated hominids, which we can pick using a ray-triangle intersection. They all animate quite slowly, to make it easier to see that accurate triangle selection is being performed. */ scene::IAnimatedMeshSceneNode* node = 0; video::SMaterial material; // Add an MD2 node, which uses vertex-based animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "faerie.md2"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-15,-140)); // Put its feet on the floor. node->setScale(core::vector3df(1.6f)); // Make it appear realistically scaled node->setMD2Animation(scene::EMAT_POINT); node->setAnimationSpeed(20.f); material.setTexture(0, driver->getTexture(mediaPath + "faerie2.bmp")); material.Lighting = true; material.NormalizeNormals = true; node->getMaterial(0) = material; // 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->setTriangleSelector(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(mediaPath + "ninja.b3d"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setScale(core::vector3df(10)); node->setPosition(core::vector3df(-75,-66,-80)); node->setRotation(core::vector3df(0,90,0)); node->setAnimationSpeed(8.f); node->getMaterial(0).NormalizeNormals = true; node->getMaterial(0).Lighting = true; // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // This X files uses skeletal animation, but without skinning. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "dwarf.x"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70,-66,-30)); // Put its feet on the floor. node->setRotation(core::vector3df(0,-90,0)); // And turn it towards the camera. node->setAnimationSpeed(20.f); node->getMaterial(0).Lighting = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); // And this mdl file uses skinned skeletal animation. node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(mediaPath + "yodan.mdl"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-90,-25,20)); node->setScale(core::vector3df(0.8f)); node->getMaterial(0).Lighting = true; node->setAnimationSpeed(20.f); // Just do the same as we did above. selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); material.setTexture(0, 0); material.Lighting = false; // Add a light, so that the unselected nodes aren't completely dark. scene::ILightSceneNode * light = smgr->addLightSceneNode(0, core::vector3df(-60,100,400), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600.0f); light->setID(ID_IsNotPickable); // Make it an invalid target for selection. // Remember which scene node is highlighted scene::ISceneNode* highlightedSceneNode = 0; scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); int lastFPS = -1; // draw the selection triangle only as wireframe material.Wireframe=true; while(device->run()) if (device->isWindowActive()) { driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0)); smgr->drawAll(); // Unlight any currently highlighted scene node if (highlightedSceneNode) { highlightedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); highlightedSceneNode = 0; } // 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 // ISceneCollisionManager::getRayFromScreenCoordinates() core::line3d<f32> ray; ray.start = camera->getPosition(); ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f; // Tracks the current intersection point with the level or a mesh core::vector3df intersection; // Used to show with triangle has been hit core::triangle3df hitTriangle; // 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 scene::ISceneNode * selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, // This will be the position of the collision 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 0); // Check the entire scene (this is actually the implicit default) // If the ray hit anything, move the billboard to the collision position // and draw the triangle that was hit. if(selectedSceneNode) { bill->setPosition(intersection); // We need to reset the transform before doing our own rendering. driver->setTransform(video::ETS_WORLD, core::matrix4()); driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0,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->getID() & 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(video::EMF_LIGHTING, false); } } // We're all done drawing, so end the scene. driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Collision detection example - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
/* At first, we let the user select the driver type, then start up the engine, set a caption, and get a pointer to the video driver. */ int main() { // create device IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(512, 384)); if (device == 0) return 1; // could not create selected driver. device->setWindowCaption(L"Irrlicht Engine - 2D Graphics Demo"); video::IVideoDriver* driver = device->getVideoDriver(); /* All 2d graphics in this example are put together into one texture, 2ddemo.png. Because we want to draw colorkey based sprites, we need to load this texture and tell the engine, which part of it should be transparent based on a colorkey. In this example, we don't tell it the color directly, we just say "Hey Irrlicht Engine, you'll find the color I want at position (0,0) on the texture.". Instead, it would be also possible to call driver->makeColorKeyTexture(images, video::SColor(0,0,0,0)), to make e.g. all black pixels transparent. Please note that makeColorKeyTexture just creates an alpha channel based on the color. */ video::ITexture* images = driver->getTexture("../../lib/irr/media/2ddemo.png"); driver->makeColorKeyTexture(images, core::position2d<s32>(0,0)); /* To be able to draw some text with two different fonts, we first load them. Ok, we load just one. As the first font we just use the default font which is built into the engine. Also, we define two rectangles which specify the position of the images of the red imps (little flying creatures) in the texture. */ gui::IGUIFont* font = device->getGUIEnvironment()->getBuiltInFont(); gui::IGUIFont* font2 = device->getGUIEnvironment()->getFont("../../lib/irr/media/fonthaettenschweiler.bmp"); core::rect<s32> imp1(349,15,385,78); core::rect<s32> imp2(387,15,423,78); /* Prepare a nicely filtering 2d render mode for special cases. */ driver->getMaterial2D().TextureLayer[0].BilinearFilter=true; driver->getMaterial2D().AntiAliasing=video::EAAM_FULL_BASIC; /* Everything is prepared, now we can draw everything in the draw loop, between the begin scene and end scene calls. In this example, we are just doing 2d graphics, but it would be no problem to mix them with 3d graphics. Just try it out, and draw some 3d vertices or set up a scene with the scene manager and draw it. */ while(device->run() && driver) { if (device->isWindowActive()) { u32 time = device->getTimer()->getTime(); driver->beginScene(true, true, video::SColor(255,120,102,136)); /* First, we draw 3 sprites, using the alpha channel we created with makeColorKeyTexture. The last parameter specifies that the drawing method should use this alpha channel. The last-but-one parameter specifies a color, with which the sprite should be colored. (255,255,255,255) is full white, so the sprite will look like the original. The third sprite is drawn with the red channel modulated based on the time. */ // draw fire & dragons background world driver->draw2DImage(images, core::position2d<s32>(50,50), core::rect<s32>(0,0,342,224), 0, video::SColor(255,255,255,255), true); // draw flying imp driver->draw2DImage(images, core::position2d<s32>(164,125), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,255,255,255), true); // draw second flying imp with colorcylce driver->draw2DImage(images, core::position2d<s32>(270,105), (time/500 % 2) ? imp1 : imp2, 0, video::SColor(255,(time) % 255,255,255), true); /* Drawing text is really simple. The code should be self explanatory. */ // draw some text if (font) font->draw(L"This demo shows that Irrlicht is also capable of drawing 2D graphics.", core::rect<s32>(130,10,300,50), video::SColor(255,255,255,255)); // draw some other text if (font2) font2->draw(L"Also mixing with 3d graphics is possible.", core::rect<s32>(130,20,300,60), video::SColor(255,time % 255,time % 255,255)); /* Next, we draw the Irrlicht Engine logo (without using a color or an alpha channel). Since we slightly scale the image we use the prepared filter mode. */ driver->enableMaterial2D(); driver->draw2DImage(images, core::rect<s32>(10,10,108,48), core::rect<s32>(354,87,442,118)); driver->enableMaterial2D(false); /* Finally draw a half-transparent rect under the mouse cursor. */ core::position2d<s32> m = device->getCursorControl()->getPosition(); driver->draw2DRectangle(video::SColor(100,255,255,255), core::rect<s32>(m.X-20, m.Y-20, m.X+20, m.Y+20)); driver->endScene(); } } device->drop(); return 0; }
/* The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling. */ int main() { // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType= video::EDT_DIRECT3D9; params.WindowSize=core::dimension2d<u32>(1024, 768); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor. */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); IFileSystem* filesys = device->getFileSystem(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); SKeyMap keyMap[4]; keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP; keyMap[1].Action = EKA_MOVE_BACKWARD; keyMap[1].KeyCode = KEY_DOWN; keyMap[2].Action = EKA_STRAFE_LEFT; keyMap[2].KeyCode = KEY_LEFT; keyMap[3].Action = EKA_STRAFE_RIGHT; keyMap[3].KeyCode = KEY_RIGHT; // add camera camera = smgr->addCameraSceneNodeFPS(0,100.0f,0.5f, -1, keyMap, 4); camera->setPosition(core::vector3df(-168, 283, -168)); camera->setTarget(core::vector3df(60,137,83)); camera->setFarValue(42000.0f); // disable mouse cursor device->getCursorControl()->setVisible(false); // create event receiver MyEventReceiver receiver; device->setEventReceiver(&receiver); smgr->setAmbientLight(video::SColorf(0.1,0.1,0.1,1)); ITerrainSceneNode* floorNode = smgr->addTerrainSceneNode(0, 0, -1, vector3df(0, 0, 0), vector3df(0, 0, 0), vector3df(1, 1, 1), SColor(255, 255, 255, 255), 5, ETPS_17, 0, true); char floor[32 * 32] = {0}; IReadFile* floorfile = filesys->createMemoryReadFile(floor, sizeof(char) * 32 * 32, "m2"); floorNode->loadHeightMapRAW(floorfile); //floorNode->setMaterialFlag(EMF_LIGHTING, false); floorNode->setScale(vector3df(100, 1, 100)); floorNode->setPosition(vector3df(-800, 1, -800)); floorNode->getMaterial(0).EmissiveColor.set(255,10,10,10); //floorNode->setVisible(false); smgr->addSphereSceneNode(10); tool = smgr->addSphereSceneNode(TOOL_R); ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0,1,0)); tool->addAnimator(anim); tool->setPosition(vector3df(0, 120, 0)); tool->setMaterialFlag(EMF_WIREFRAME, true); node = smgr->addTerrainSceneNode(0, 0, -1, vector3df(0, 0, 0), vector3df(0, 0, 0), vector3df(1, 1, 1), SColor(255, 255, 255, 255), 0, ETPS_17, 0, true); for (int i = OFFSET; i < (MATERIAL_SIZE + OFFSET); ++i) { for (int j = OFFSET; j < (MATERIAL_SIZE + OFFSET); ++j) { material[i * REAL_SIZE + j] = 100; } } file = filesys->createMemoryReadFile(material, sizeof(float) * REAL_SIZE * REAL_SIZE, "m1"); node->loadHeightMapRAW(file, 32, false, true, REAL_SIZE); node->getMaterial(0).AmbientColor.set(255,0,0,255); //node->getMaterial(0).Shininess = 20.0f; //node->setMaterialFlag(EMF_LIGHTING, false); //node->setMaterialFlag(EMF_WIREFRAME, true); node->setMaterialFlag(EMF_BACK_FACE_CULLING, false); node->setPosition(vector3df(-OFFSET, 0, -OFFSET)); smgr->addLightSceneNode( 0, core::vector3df(100,300,100), video::SColorf(0.3f,0.3f,0.3f), 300); std::list<vector3df> pathList; pathList.push_back(vector3df(30, 100, 30)); pathList.push_back(vector3df(30, 100, 170)); pathList.push_back(vector3df(170, 100, 170)); pathList.push_back(vector3df(170, 100, 30)); pathList.push_back(vector3df(60, 100, 30)); pathList.push_back(vector3df(60, 100, 140)); pathList.push_back(vector3df(140, 100, 140)); pathList.push_back(vector3df(140, 100, 60)); std::list<vector3df>::iterator pathIter = pathList.begin(); int s = 0; int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { if (pathIter != pathList.end()) { vector3df endP = *pathIter; vector3df noewP = tool->getPosition(); vector3df vStep; if (noewP.X < endP.X) { vStep.X = STEP; } if (noewP.X > endP.X) { vStep.X = -STEP; } if (noewP.Y < endP.Y) { vStep.Y = STEP; } if (noewP.Y > endP.Y) { vStep.Y = -STEP; } if (noewP.Z < endP.Z) { vStep.Z = STEP; } if (noewP.Z > endP.Z) { vStep.Z = -STEP; } tool->setPosition(tool->getPosition() + vStep); Cut(); if (endP.getDistanceFrom(noewP) <= STEP) { ++pathIter; } } // IMesh* m = node->getMesh(); // IMeshBuffer* b = m->getMeshBuffer(0); // // u32 c1 = m->getMeshBufferCount(); // // u32 c2 = b->getVertexCount(); // // void* v = b->getVertices(); // // for (int i = 0; i < 30; ++i) // { // for (int j = 0; j < 30; ++j) // { // S3DVertex2TCoords* tmpv = (static_cast<S3DVertex2TCoords*>(v) + (i + s + 10) * 128 + (j + s + 10)); // // tmpv->Pos.Y = 1000; // } // } // // s = (s + 1) % 50 + 10; // // for (int i = 0; i < 30; ++i) // { // for (int j = 0; j < 30; ++j) // { // S3DVertex2TCoords* tmpv = (static_cast<S3DVertex2TCoords*>(v) + (i + s + 10) * 128 + (j + s + 10)); // // tmpv->Pos.Y = 800; // } // } // node->setPosition(node->getPosition()); driver->beginScene(true, true, 0 ); smgr->drawAll(); env->drawAll(); // for (int i = 0; i < 30; ++i) // { // for (int j = 0; j < 30; ++j) // { // material[(i + s + 10) * 128 + (j + s + 10)] = 1000; // } // } // // s = (s + 1) % 50 + 10; // // for (int i = 0; i < 30; ++i) // { // for (int j = 0; j < 30; ++j) // { // material[(i + s + 10) * 128 + (j + s + 10)] = 800; // } // } // // file->read(material, sizeof(float) * 128 * 128); // file->seek(0); // node->loadHeightMapRAW(file, 32, false, true, 128); // // node->setMaterialFlag(EMF_LIGHTING, false); // node->setMaterialFlag(EMF_WIREFRAME, true); // node->setMaterialFlag(EMF_BACK_FACE_CULLING, false); // node->setMaterialFlag(EMF_FRONT_FACE_CULLING, false); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return 0; }
int main() { // Event Receiver // ====================================================== MyEventReceiver receiver; // get Screen resolution // =============================================== //create a NULL device to detect screen resolution IrrlichtDevice *nulldevice = createDevice(video::EDT_NULL); core::dimension2d<u32> deskRes = nulldevice->getVideoModeList()->getDesktopResolution(); nulldevice->drop(); // Create device // ======================================================= IrrlichtDevice *device; //1366, 768 //1024, 600 int FullScreen = 1; if (FullScreen == 1) { device = createDevice(video::EDT_DIRECT3D9, deskRes, 32, true, false, true, &receiver); } else { device = createDevice(video::EDT_DIRECT3D9, core::dimension2d<u32>(800, 600), 32, false, false, true, &receiver); } // Get a pointers // ====================================================== video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); // Disable mip maps // ===================================================== //driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); // Image // ================================================================ video::ITexture* controlsPic = driver->getTexture("./media/Controls.png"); video::ITexture* irrlichtLogo = driver->getTexture("./media/irrlichtlogo2.png"); // Terrain // ============================================================== scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("./media/heightmap3.jpg", 0, -1, core::vector3df(0, 0, 0), core::vector3df(0, 0, 0), core::vector3df(1, 1, 1)); if (terrain) { terrain->setID(NotPickable); terrain->setScale(core::vector3df(1.0f, 0.5f, 1.0f)); //terrain->setPosition(core::vector3df(0, 0, 0)); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("./media/terrainTexture2.jpg")); } // Box // ================================================================== scene::ISceneNode* box = smgr->addCubeSceneNode(); box->setMaterialTexture(0, driver->getTexture("./media/redPixel.bmp")); box->setMaterialFlag(video::EMF_LIGHTING, false); box->setScale(core::vector3df(5, 5, 5)); box->setPosition(core::vector3df(-500, 1000, -500)); //box->setScale(core::vector3df(1, 2, 1)); // light // ================================================================ scene::ILightSceneNode* lightSun1 = smgr->addLightSceneNode(0, core::vector3df(812, terrain->getHeight(812, 812) + 812, 812), video::SColorf(1, 1, 0.94f, 1), 5000.0f); // ========================================================================= device->getCursorControl()->setVisible(false); // display frames per second // ============================================ int fps; int lastFPS = -1; gui::IGUIStaticText* guiText = guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!", core::rect<s32>(10, 200, 100, 222), true); core::stringw str; // Frame rate independence // ============================================== u32 then = device->getTimer()->getTime(); u32 now; f32 tempT; f32 deltaTime; ITimer* Timer = device->getTimer(); // Action // =============================================================== Action Act(&receiver, device, terrain, &deltaTime); while (device->run()) { if (device->isWindowActive()) { // Frame rate independence // ========================================== now = Timer->getTime(); tempT = (f32)(now - then); deltaTime = (f32)(((tempT) < 60) ? tempT : 60); then = now; // ===================================================================== Act.update(); // Draw Scene // ======================================================= driver->beginScene(true, true, video::SColor(255, 100, 101, 140)); smgr->drawAll(); guienv->drawAll(); driver->draw2DImage(controlsPic, core::rect<s32>(10, 10, 200, 200), core::rect<s32>(0, 0, 256, 256), 0, 0, true); driver->draw2DImage(irrlichtLogo, core::rect<s32>(1100, 10, 1250, 150), core::rect<s32>(0, 0, 128, 128), 0, 0, true); // Selection box (must be implemented elsewhere of course /*driver->draw2DRectangle(video::SColor(50, 3, 67, 67), core::rect<s32>(512, 512, 680, 680)); driver->draw2DLine(core::position2d<s32>(512, 512), core::position2d<s32>(512, 680), video::SColor(255, 11, 208, 194)); driver->draw2DLine(core::position2d<s32>(512, 680), core::position2d<s32>(680, 680), video::SColor(255, 11, 208, 194)); driver->draw2DLine(core::position2d<s32>(680, 680), core::position2d<s32>(680, 512), video::SColor(255, 11, 208, 194)); driver->draw2DLine(core::position2d<s32>(680, 512), core::position2d<s32>(512, 512), video::SColor(255, 11, 208, 194));*/ Act.DrawCursor(); driver->endScene(); // Type FPS //========================================================== fps = driver->getFPS(); if (lastFPS != fps) { str = L"["; str += driver->getName(); str += "] FPS:"; str += fps; guiText->setText(str.c_str()); lastFPS = fps; } } else device->yield(); } // Drop Device //=========================================================== device->drop(); return 0; }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed IrrlichtDevice *device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, false); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); /* Now, we load an animated mesh to be displayed. As in most examples, we'll take the fairy md2 model. The difference here: We set the shininess of the model to a value other than 0 which is the default value. This enables specular highlights on the model if dynamic lighting is on. The value influences the size of the highlights. */ // load and display animated fairy mesh scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../../media/faerie.md2")); if (fairy) { fairy->setMaterialTexture(0, driver->getTexture("../../media/faerie2.bmp")); // set diffuse texture fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights fairy->setPosition(core::vector3df(-10,0,-100)); fairy->setMD2Animation ( scene::EMAT_STAND ); } /* To make specular highlights appear on the model, we need a dynamic light in the scene. We add one directly in vicinity of the model. In addition, to make the model not that dark, we set the ambient light to gray. */ // add white light smgr->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f)); // set ambient light smgr->setAmbientLight(video::SColor(0,60,60,60)); /* The next is just some standard stuff: Add a test cube and let it rotate to make the scene more interesting. The user defined camera and cursor setup is made later on, right before the render loop. */ // create test cube scene::ISceneNode* test = smgr->addCubeSceneNode(60); // let the cube rotate and set some light settings scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator( core::vector3df(0.3f, 0.3f,0)); test->setPosition(core::vector3df(-100,0,-100)); test->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting test->addAnimator(anim); anim->drop(); // set window caption device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example"); /* To test out the render to texture feature, we need a render target texture. These are not like standard textures, but need to be created first. To create one, we call IVideoDriver::addRenderTargetTexture() and specify the size of the texture. Please don't use sizes bigger than the frame buffer for this, because the render target shares the zbuffer with the frame buffer. Because we want to render the scene not from the user camera into the texture, we add another fixed camera to the scene. But before we do all this, we check if the current running driver is able to render to textures. If it is not, we simply display a warning text. */ // create render target video::ITexture* rt = 0; scene::ICameraSceneNode* fixedCam = 0; if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) { rt = driver->addRenderTargetTexture(core::dimension2d<u32>(256,256), "RTT1"); test->setMaterialTexture(0, rt); // set material of cube to render target // add fixed camera fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), core::vector3df(-10,10,-100)); } else { // create problem text gui::IGUISkin* skin = env->getSkin(); gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); gui::IGUIStaticText* text = env->addStaticText( L"Your hardware or this renderer is not able to use the "\ L"render to texture feature. RTT Disabled.", core::rect<s32>(150,20,470,60)); text->setOverrideColor(video::SColor(100,255,255,255)); } // add fps camera scene::ICameraSceneNode* fpsCamera = smgr->addCameraSceneNodeFPS(); fpsCamera->setPosition(core::vector3df(-50,50,-150)); // disable mouse cursor device->getCursorControl()->setVisible(false); /* Nearly finished. Now we need to draw everything. Every frame, we draw the scene twice. Once from the fixed camera into the render target texture and once as usual. When rendering into the render target, we need to disable the visibility of the test cube, because it has the render target texture applied to it. That's it, wasn't too complicated I hope. :) */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0); if (rt) { // draw scene into render target // set render target texture driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255)); // make cube invisible and set fixed camera as active camera test->setVisible(false); smgr->setActiveCamera(fixedCam); // draw whole scene into render buffer smgr->drawAll(); // set back old render target // The buffer might have been distorted, so clear it driver->setRenderTarget(0, true, true, 0); // make the cube visible and set the user controlled camera as active one test->setVisible(true); smgr->setActiveCamera(fpsCamera); } // draw scene normally smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Irrlicht Engine - Render to Texture and Specular Highlights example"; str += " FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); // drop device return 0; }
int main(int argc, char *argv[]) { int retval = 0; /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); /* Parse command line */ // List all allowed options std::map<std::string, ValueSpec> allowed_options; allowed_options.insert(std::make_pair("help", ValueSpec(VALUETYPE_FLAG, _("Show allowed options")))); allowed_options.insert(std::make_pair("version", ValueSpec(VALUETYPE_FLAG, _("Show version information")))); allowed_options.insert(std::make_pair("config", ValueSpec(VALUETYPE_STRING, _("Load configuration from specified file")))); allowed_options.insert(std::make_pair("port", ValueSpec(VALUETYPE_STRING, _("Set network port (UDP)")))); allowed_options.insert(std::make_pair("disable-unittests", ValueSpec(VALUETYPE_FLAG, _("Disable unit tests")))); allowed_options.insert(std::make_pair("enable-unittests", ValueSpec(VALUETYPE_FLAG, _("Enable unit tests")))); allowed_options.insert(std::make_pair("map-dir", ValueSpec(VALUETYPE_STRING, _("Same as --world (deprecated)")))); allowed_options.insert(std::make_pair("world", ValueSpec(VALUETYPE_STRING, _("Set world path (implies local game) ('list' lists all)")))); allowed_options.insert(std::make_pair("worldname", ValueSpec(VALUETYPE_STRING, _("Set world by name (implies local game)")))); allowed_options.insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG, _("Print more information to console")))); allowed_options.insert(std::make_pair("verbose", ValueSpec(VALUETYPE_FLAG, _("Print even more information to console")))); allowed_options.insert(std::make_pair("trace", ValueSpec(VALUETYPE_FLAG, _("Print enormous amounts of information to log and console")))); allowed_options.insert(std::make_pair("logfile", ValueSpec(VALUETYPE_STRING, _("Set logfile path ('' = no logging)")))); allowed_options.insert(std::make_pair("gameid", ValueSpec(VALUETYPE_STRING, _("Set gameid (\"--gameid list\" prints available ones)")))); allowed_options.insert(std::make_pair("migrate", ValueSpec(VALUETYPE_STRING, _("Migrate from current map backend to another (Only works when using minetestserver or with --server)")))); #ifndef SERVER allowed_options.insert(std::make_pair("videomodes", ValueSpec(VALUETYPE_FLAG, _("Show available video modes")))); allowed_options.insert(std::make_pair("speedtests", ValueSpec(VALUETYPE_FLAG, _("Run speed tests")))); allowed_options.insert(std::make_pair("address", ValueSpec(VALUETYPE_STRING, _("Address to connect to. ('' = local game)")))); allowed_options.insert(std::make_pair("random-input", ValueSpec(VALUETYPE_FLAG, _("Enable random user input, for testing")))); allowed_options.insert(std::make_pair("server", ValueSpec(VALUETYPE_FLAG, _("Run dedicated server")))); allowed_options.insert(std::make_pair("name", ValueSpec(VALUETYPE_STRING, _("Set player name")))); allowed_options.insert(std::make_pair("password", ValueSpec(VALUETYPE_STRING, _("Set password")))); allowed_options.insert(std::make_pair("go", ValueSpec(VALUETYPE_FLAG, _("Disable main menu")))); #endif Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1")) { dstream<<_("Allowed options:")<<std::endl; for(std::map<std::string, ValueSpec>::iterator i = allowed_options.begin(); i != allowed_options.end(); ++i) { std::ostringstream os1(std::ios::binary); os1<<" --"<<i->first; if(i->second.type == VALUETYPE_FLAG) {} else os1<<_(" <value>"); dstream<<padStringRight(os1.str(), 24); if(i->second.help != NULL) dstream<<i->second.help; dstream<<std::endl; } return cmd_args.getFlag("help") ? 0 : 1; } if(cmd_args.getFlag("version")) { #ifdef SERVER dstream<<"minetestserver "<<minetest_version_hash<<std::endl; #else dstream<<"Minetest "<<minetest_version_hash<<std::endl; dstream<<"Using Irrlicht "<<IRRLICHT_SDK_VERSION<<std::endl; #endif dstream<<"Build info: "<<minetest_build_info<<std::endl; return 0; } /* Low-level initialization */ // If trace is enabled, enable logging of certain things if(cmd_args.getFlag("trace")){ dstream<<_("Enabling trace level debug output")<<std::endl; log_trace_level_enabled = true; dout_con_ptr = &verbosestream; // this is somewhat old crap socket_enable_debug_output = true; // socket doesn't use log.h } // In certain cases, output info level on stderr if(cmd_args.getFlag("info") || cmd_args.getFlag("verbose") || cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests")) log_add_output(&main_stderr_log_out, LMT_INFO); // In certain cases, output verbose level on stderr if(cmd_args.getFlag("verbose") || cmd_args.getFlag("trace")) log_add_output(&main_stderr_log_out, LMT_VERBOSE); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_user); infostream<<"path_share = "<<porting::path_share<<std::endl; infostream<<"path_user = "******"gameid") && cmd_args.get("gameid") == "list") { std::set<std::string> gameids = getAvailableGameIds(); for(std::set<std::string>::const_iterator i = gameids.begin(); i != gameids.end(); i++) dstream<<(*i)<<std::endl; return 0; } // List worlds if requested if(cmd_args.exists("world") && cmd_args.get("world") == "list"){ dstream<<_("Available worlds:")<<std::endl; std::vector<WorldSpec> worldspecs = getAvailableWorlds(); print_worldspecs(worldspecs, dstream); return 0; } // Print startup message infostream<<PROJECT_NAME<< " "<<_("with")<<" SER_FMT_VER_HIGHEST_READ="<<(int)SER_FMT_VER_HIGHEST_READ <<", "<<minetest_build_info <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use g_settings_path = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } g_settings_path = cmd_args.get("config"); } else { std::vector<std::string> filenames; filenames.push_back(porting::path_user + DIR_DELIM + "minetest.conf"); // Legacy configuration file location filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #if RUN_IN_PLACE // Try also from a lower level (to aid having the same configuration // for many RUN_IN_PLACE installs) filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { g_settings_path = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(g_settings_path == "") g_settings_path = filenames[0]; } // Initialize debug streams #define DEBUGFILE "debug.txt" #if RUN_IN_PLACE std::string logfile = DEBUGFILE; #else std::string logfile = porting::path_user+DIR_DELIM+DEBUGFILE; #endif if(cmd_args.exists("logfile")) logfile = cmd_args.get("logfile"); log_remove_output(&main_dstream_no_stderr_log_out); int loglevel = g_settings->getS32("debug_log_level"); if (loglevel == 0) //no logging logfile = ""; else if (loglevel > 0 && loglevel <= LMT_NUM_VALUES) log_add_output_maxlev(&main_dstream_no_stderr_log_out, (LogMessageLevel)(loglevel - 1)); if(logfile != "") debugstreams_init(false, logfile.c_str()); else debugstreams_init(false, NULL); infostream<<"logfile = "<<logfile<<std::endl; // Initialize random seed srand(time(0)); mysrand(time(0)); // Initialize HTTP fetcher httpfetch_init(g_settings->getS32("curl_parallel_limit")); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } #ifdef _MSC_VER init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"),argc,argv); #else init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language")); #endif /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) commanded_world = cmd_args.get("world"); else if(cmd_args.exists("map-dir")) commanded_world = cmd_args.get("map-dir"); else if(cmd_args.exists("nonopt0")) // First nameless argument commanded_world = cmd_args.get("nonopt0"); else if(g_settings->exists("map-dir")) commanded_world = g_settings->get("map-dir"); // World name std::string commanded_worldname = ""; if(cmd_args.exists("worldname")) commanded_worldname = cmd_args.get("worldname"); // Strip world.mt from commanded_world { std::string worldmt = "world.mt"; if(commanded_world.size() > worldmt.size() && commanded_world.substr(commanded_world.size()-worldmt.size()) == worldmt){ dstream<<_("Supplied world.mt file - stripping it off.")<<std::endl; commanded_world = commanded_world.substr( 0, commanded_world.size()-worldmt.size()); } } // If a world name was specified, convert it to a path if(commanded_worldname != ""){ // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); bool found = false; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ if(commanded_world != ""){ dstream<<_("--worldname takes precedence over previously " "selected world.")<<std::endl; } commanded_world = worldspecs[i].path; found = true; break; } } if(!found){ dstream<<_("World")<<" '"<<commanded_worldname<<_("' not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // Gamespec SubgameSpec commanded_gamespec; if(cmd_args.exists("gameid")){ std::string gameid = cmd_args.get("gameid"); commanded_gamespec = findSubgame(gameid); if(!commanded_gamespec.isValid()){ errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl; return 1; } } /* Run dedicated server if asked to or no other option */ #ifdef SERVER bool run_dedicated_server = true; #else bool run_dedicated_server = cmd_args.getFlag("server"); #endif g_settings->set("server_dedicated", run_dedicated_server ? "true" : "false"); if(run_dedicated_server) { DSTACK("Dedicated server branch"); // Create time getter if built with Irrlicht #ifndef SERVER g_timegetter = new SimpleTimeGetter(); #endif // World directory std::string world_path; verbosestream<<_("Determining world path")<<std::endl; bool is_legacy_world = false; // If a world was commanded, use it if(commanded_world != ""){ world_path = commanded_world; infostream<<"Using commanded world path ["<<world_path<<"]" <<std::endl; } // No world was specified; try to select it automatically else { // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world name was specified, select it if(commanded_worldname != ""){ world_path = ""; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ world_path = worldspecs[i].path; break; } } if(world_path == ""){ dstream<<_("World")<<" '"<<commanded_worldname<<"' "<<_("not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // If there is only a single world, use it if(worldspecs.size() == 1){ world_path = worldspecs[0].path; dstream<<_("Automatically selecting world at")<<" [" <<world_path<<"]"<<std::endl; // If there are multiple worlds, list them } else if(worldspecs.size() > 1){ dstream<<_("Multiple worlds are available.")<<std::endl; dstream<<_("Please select one using --worldname <name>" " or --world <path>")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; // If there are no worlds, automatically create a new one } else { // This is the ultimate default world path world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "world"; infostream<<"Creating default world at [" <<world_path<<"]"<<std::endl; } } if(world_path == ""){ errorstream<<"No world path specified or found."<<std::endl; return 1; } verbosestream<<_("Using world path")<<" ["<<world_path<<"]"<<std::endl; // We need a gamespec. SubgameSpec gamespec; verbosestream<<_("Determining gameid/gamespec")<<std::endl; // If world doesn't exist if(!getWorldExists(world_path)) { // Try to take gamespec from command line if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; infostream<<"Using commanded gameid ["<<gamespec.id<<"]"<<std::endl; } // Otherwise we will be using "minetest" else{ gamespec = findSubgame(g_settings->get("default_game")); infostream<<"Using default gameid ["<<gamespec.id<<"]"<<std::endl; } } // World exists else { std::string world_gameid = getWorldGameId(world_path, is_legacy_world); // If commanded to use a gameid, do so if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; if(commanded_gamespec.id != world_gameid){ errorstream<<"WARNING: Using commanded gameid [" <<gamespec.id<<"]"<<" instead of world gameid [" <<world_gameid<<"]"<<std::endl; } } else{ // If world contains an embedded game, use it; // Otherwise find world from local system. gamespec = findWorldSubgame(world_path); infostream<<"Using world gameid ["<<gamespec.id<<"]"<<std::endl; } } if(!gamespec.isValid()){ errorstream<<"Subgame ["<<gamespec.id<<"] could not be found." <<std::endl; return 1; } verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; // Bind address std::string bind_str = g_settings->get("bind_address"); Address bind_addr(0,0,0,0, port); if (g_settings->getBool("ipv6_server")) { bind_addr.setAddress((IPv6AddressBytes*) NULL); } try { bind_addr.Resolve(bind_str.c_str()); } catch (ResolveError &e) { infostream << "Resolving bind address \"" << bind_str << "\" failed: " << e.what() << " -- Listening on all addresses." << std::endl; } if(bind_addr.isIPv6() && !g_settings->getBool("enable_ipv6")) { errorstream << "Unable to listen on " << bind_addr.serializeString() << L" because IPv6 is disabled" << std::endl; return 1; } // Create server Server server(world_path, gamespec, false, bind_addr.isIPv6()); // Database migration if (cmd_args.exists("migrate")) { std::string migrate_to = cmd_args.get("migrate"); Settings world_mt; bool success = world_mt.readConfigFile((world_path + DIR_DELIM + "world.mt").c_str()); if (!success) { errorstream << "Cannot read world.mt" << std::endl; return 1; } if (!world_mt.exists("backend")) { errorstream << "Please specify your current backend in world.mt file:" << std::endl << " backend = {sqlite3|leveldb|redis|dummy}" << std::endl; return 1; } std::string backend = world_mt.get("backend"); Database *new_db; if (backend == migrate_to) { errorstream << "Cannot migrate: new backend is same as the old one" << std::endl; return 1; } if (migrate_to == "sqlite3") new_db = new Database_SQLite3(&(ServerMap&)server.getMap(), world_path); #if USE_LEVELDB else if (migrate_to == "leveldb") new_db = new Database_LevelDB(&(ServerMap&)server.getMap(), world_path); #endif #if USE_REDIS else if (migrate_to == "redis") new_db = new Database_Redis(&(ServerMap&)server.getMap(), world_path); #endif else { errorstream << "Migration to " << migrate_to << " is not supported" << std::endl; return 1; } std::list<v3s16> blocks; ServerMap &old_map = ((ServerMap&)server.getMap()); old_map.listAllLoadableBlocks(blocks); int count = 0; new_db->beginSave(); for (std::list<v3s16>::iterator i = blocks.begin(); i != blocks.end(); ++i) { MapBlock *block = old_map.loadBlock(*i); new_db->saveBlock(block); MapSector *sector = old_map.getSectorNoGenerate(v2s16(i->X, i->Z)); sector->deleteBlock(block); ++count; if (count % 500 == 0) actionstream << "Migrated " << count << " blocks " << (100.0 * count / blocks.size()) << "% completed" << std::endl; } new_db->endSave(); delete new_db; actionstream << "Successfully migrated " << count << " blocks" << std::endl; world_mt.set("backend", migrate_to); if(!world_mt.updateConfigFile((world_path + DIR_DELIM + "world.mt").c_str())) errorstream<<"Failed to update world.mt!"<<std::endl; else actionstream<<"world.mt updated"<<std::endl; return 0; } server.start(bind_addr); // Run server dedicated_server_loop(server, kill); return 0; } #ifndef SERVER // Exclude from dedicated server build /* More parameters */ std::string address = g_settings->get("address"); if(commanded_world != "") address = ""; else if(cmd_args.exists("address")) address = cmd_args.get("address"); std::string playername = g_settings->get("name"); if(cmd_args.exists("name")) playername = cmd_args.get("name"); bool skip_main_menu = cmd_args.getFlag("go"); /* Device initialization */ // Resolution selection bool fullscreen = g_settings->getBool("fullscreen"); u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // bpp, fsaa, vsync bool vsync = g_settings->getBool("vsync"); u16 bits = g_settings->getU16("fullscreen_bpp"); u16 fsaa = g_settings->getU16("fsaa"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; #ifdef _IRR_COMPILE_WITH_OGLES1_ else if(driverstring == "ogles1") driverType = video::EDT_OGLES1; #endif #ifdef _IRR_COMPILE_WITH_OGLES2_ else if(driverstring == "ogles2") driverType = video::EDT_OGLES2; #endif else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* List video modes if requested */ MyEventReceiver receiver; if(cmd_args.getFlag("videomodes")){ IrrlichtDevice *nulldevice; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = video::EDT_NULL; params.WindowSize = core::dimension2d<u32>(640, 480); params.Bits = 24; params.AntiAlias = fsaa; params.Fullscreen = false; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); nulldevice = createDeviceEx(params); if(nulldevice == 0) return 1; dstream<<_("Available video modes (WxHxD):")<<std::endl; video::IVideoModeList *videomode_list = nulldevice->getVideoModeList(); if(videomode_list == 0){ nulldevice->drop(); return 1; } s32 videomode_count = videomode_list->getVideoModeCount(); core::dimension2d<u32> videomode_res; s32 videomode_depth; for (s32 i = 0; i < videomode_count; ++i){ videomode_res = videomode_list->getVideoModeResolution(i); videomode_depth = videomode_list->getVideoModeDepth(i); dstream<<videomode_res.Width<<"x"<<videomode_res.Height <<"x"<<videomode_depth<<std::endl; } dstream<<_("Active video mode (WxHxD):")<<std::endl; videomode_res = videomode_list->getDesktopResolution(); videomode_depth = videomode_list->getDesktopDepth(); dstream<<videomode_res.Width<<"x"<<videomode_res.Height <<"x"<<videomode_depth<<std::endl; nulldevice->drop(); return 0; } /* Create device and exit if creation failed */ IrrlichtDevice *device; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(screenW, screenH); params.Bits = bits; params.AntiAlias = fsaa; params.Fullscreen = fullscreen; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; params.HighPrecisionFPU = g_settings->getBool("high_precision_fpu"); device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); device->drop(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) { input = new RandomInputHandler(); } else { input = new RealInputHandler(device, &receiver); } scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); std::string font_path = g_settings->get("font_path"); gui::IGUIFont *font; #if USE_FREETYPE bool use_freetype = g_settings->getBool("freetype"); if (use_freetype) { std::string fallback; if (is_yes(gettext("needs_fallback_font"))) fallback = "fallback_"; u16 font_size = g_settings->getU16(fallback + "font_size"); font_path = g_settings->get(fallback + "font_path"); u32 font_shadow = g_settings->getU16(fallback + "font_shadow"); u32 font_shadow_alpha = g_settings->getU16(fallback + "font_shadow_alpha"); font = gui::CGUITTFont::createTTFont(guienv, font_path.c_str(), font_size, true, true, font_shadow, font_shadow_alpha); } else { font = guienv->getFont(font_path.c_str()); } #else font = guienv->getFont(font_path.c_str()); #endif if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255,70,100,50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255,255,255,255)); #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 // Irrlicht 1.8 input colours skin->setColor(gui::EGDC_EDITABLE, video::SColor(255,128,128,128)); skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49)); #endif // Create the menu clouds if (!g_menucloudsmgr) g_menucloudsmgr = smgr->createNewSceneManager(); if (!g_menuclouds) g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(), g_menucloudsmgr, -1, rand(), 100); g_menuclouds->update(v2f(0, 0), video::SColor(255,200,200,255)); scene::ICameraSceneNode* camera; camera = g_menucloudsmgr->addCameraSceneNode(0, v3f(0,0,0), v3f(0, 60, 100)); camera->setFarValue(10000); /* GUI stuff */ ChatBackend chat_backend; /* If an error occurs, this is set to something and the menu-game loop is restarted. It is then displayed before the menu. */ std::wstring error_message = L""; // The password entered during the menu screen, std::string password; bool first_loop = true; /* Menu-game loop */ while(device->run() && kill == false) { // Set the window caption wchar_t* text = wgettext("Main Menu"); device->setWindowCaption((std::wstring(L"Minetest [")+text+L"]").c_str()); delete[] text; // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* We need some kind of a root node to be able to add custom gui elements directly on the screen. Otherwise they won't be automatically drawn. */ guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000)); SubgameSpec gamespec; WorldSpec worldspec; bool simple_singleplayer_mode = false; // These are set up based on the menu and other things std::string current_playername = "inv£lid"; std::string current_password = ""; std::string current_address = "does-not-exist"; int current_port = 0; /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // If skip_main_menu, only go through here once if(skip_main_menu && !first_loop){ kill = true; break; } first_loop = false; // Cursor can be non-visible when coming from the game device->getCursorControl()->setVisible(true); // Some stuff are left to scene manager when coming from the game // (map at least?) smgr->clear(); // Initialize menu data MainMenuData menudata; menudata.address = address; menudata.name = playername; menudata.port = itos(port); menudata.errormessage = wide_to_narrow(error_message); error_message = L""; if(cmd_args.exists("password")) menudata.password = cmd_args.get("password"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map")); menudata.enable_public = g_settings->getBool("server_announce"); std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world was commanded, append and select it if(commanded_world != ""){ std::string gameid = getWorldGameId(commanded_world, true); std::string name = _("[--world parameter]"); if(gameid == ""){ gameid = g_settings->get("default_game"); name += " [new]"; } //TODO find within worldspecs and set config } if(skip_main_menu == false) { video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Waiting for other menus"<<std::endl; while(device->run() && kill == false) { if(noMenuActive()) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Waited for other menus"<<std::endl; GUIEngine* temp = new GUIEngine(device, guiroot, &g_menumgr,smgr,&menudata,kill); delete temp; //once finished you'll never end up here smgr->clear(); } if(menudata.errormessage != ""){ error_message = narrow_to_wide(menudata.errormessage); continue; } //update worldspecs (necessary as new world may have been created) worldspecs = getAvailableWorlds(); if (menudata.name == "") menudata.name = std::string("Guest") + itos(myrand_range(1000,9999)); else playername = menudata.name; password = translatePassword(playername, narrow_to_wide(menudata.password)); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = menudata.address; int newport = stoi(menudata.port); if(newport != 0) port = newport; simple_singleplayer_mode = menudata.simple_singleplayer_mode; // Save settings g_settings->set("name", playername); if((menudata.selected_world >= 0) && (menudata.selected_world < (int)worldspecs.size())) g_settings->set("selected_world_path", worldspecs[menudata.selected_world].path); // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; current_playername = playername; current_password = password; current_address = address; current_port = port; // If using simple singleplayer mode, override if(simple_singleplayer_mode){ current_playername = "singleplayer"; current_password = ""; current_address = ""; current_port = myrand_range(49152, 65535); } else if (address != "") { ServerListSpec server; server["name"] = menudata.servername; server["address"] = menudata.address; server["port"] = menudata.port; server["description"] = menudata.serverdescription; ServerList::insert(server); } // Set world path to selected one if ((menudata.selected_world >= 0) && (menudata.selected_world < (int)worldspecs.size())) { worldspec = worldspecs[menudata.selected_world]; infostream<<"Selected world: "<<worldspec.name <<" ["<<worldspec.path<<"]"<<std::endl; } // If local game if(current_address == "") { if(menudata.selected_world == -1){ error_message = wgettext("No world selected and no address " "provided. Nothing to do."); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } // Load gamespec for required game gamespec = findWorldSubgame(worldspec.path); if(!gamespec.isValid() && !commanded_gamespec.isValid()){ error_message = wgettext("Could not find or load game \"") + narrow_to_wide(worldspec.gameid) + L"\""; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } if(commanded_gamespec.isValid() && commanded_gamespec.id != worldspec.gameid){ errorstream<<"WARNING: Overriding gamespec from \"" <<worldspec.gameid<<"\" to \"" <<commanded_gamespec.id<<"\""<<std::endl; gamespec = commanded_gamespec; } if(!gamespec.isValid()){ error_message = wgettext("Invalid gamespec."); error_message += L" (world_gameid=" +narrow_to_wide(worldspec.gameid)+L")"; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } } // Continue to game break; } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) { if(g_settings_path != "") { g_settings->updateConfigFile( g_settings_path.c_str()); } break; } /* Run game */ the_game( kill, random_input, input, device, font, worldspec.path, current_playername, current_password, current_address, current_port, error_message, chat_backend, gamespec, simple_singleplayer_mode ); smgr->clear(); } //try catch(con::PeerNotFoundException &e) { error_message = wgettext("Connection error (timed out?)"); errorstream<<wide_to_narrow(error_message)<<std::endl; } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception: \""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif // If no main menu, show error and exit if(skip_main_menu) { if(error_message != L""){ verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; retval = 1; } break; } } // Menu-game loop g_menuclouds->drop(); g_menucloudsmgr->drop(); delete input; /* In the end, delete the Irrlicht device. */ device->drop(); #if USE_FREETYPE if (use_freetype) font->drop(); #endif #endif // !SERVER // Update configuration file if(g_settings_path != "") g_settings->updateConfigFile(g_settings_path.c_str()); // Print modified quicktune values { bool header_printed = false; std::vector<std::string> names = getQuicktuneNames(); for(u32 i=0; i<names.size(); i++){ QuicktuneValue val = getQuicktuneValue(names[i]); if(!val.modified) continue; if(!header_printed){ dstream<<"Modified quicktune values:"<<std::endl; header_printed = true; } dstream<<names[i]<<" = "<<val.getString()<<std::endl; } } // Stop httpfetch thread (if started) httpfetch_cleanup(); END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return retval; }
int IRRCALLCONV main(int argc, char* argv[]) { /* Like in the HelloWorld example, we create an IrrlichtDevice with createDevice(). The difference now is that we ask the user to select which hardware accelerated driver to use. The Software device would be too slow to draw a huge Quake 3 map, but just for the fun of it, we make this decision possible too. */ // ask user for driver video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; // create device and exit if creation failed const core::dimension2du videoDim(800,600); IrrlichtDevice *device = createDevice(driverType, videoDim, 32, false ); if (device == 0) return 1; // could not create selected driver. const char* mapname=0; if (argc>2) mapname = argv[2]; else mapname = QUAKE3_MAP_NAME; /* Get a pointer to the video driver and the SceneManager so that we do not always have to write device->getVideoDriver() and device->getSceneManager(). */ video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* gui = device->getGUIEnvironment(); //! add our private media directory to the file system device->getFileSystem()->addFileArchive("../../media/"); /* To display the Quake 3 map, we first need to load it. Quake 3 maps are packed into .pk3 files, which are nothing other than .zip files. So we add the .pk3 file to our FileSystem. After it was added, we are able to read from the files in that archive as they would directly be stored on disk. */ if (argc>2) device->getFileSystem()->QUAKE3_STORAGE_FORMAT(argv[1]); else device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_1); #ifdef QUAKE3_STORAGE_2 device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_2); #endif // Quake3 Shader controls Z-Writing smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); /* Now we can load the mesh by calling getMesh(). We get a pointer returned to a IAnimatedMesh. As you know, Quake 3 maps are not really animated, they are only a huge chunk of static geometry with some materials attached. Hence the IAnimated mesh consists of only one frame, so we get the "first frame" of the "animation", which is our quake level and create an Octree scene node with it, using addOctreeSceneNode(). The Octree optimizes the scene a little bit, trying to draw only geometry which is currently visible. An alternative to the Octree would be a AnimatedMeshSceneNode, which would draw always the complete geometry of the mesh, without optimization. Try it out: Write addAnimatedMeshSceneNode instead of addOctreeSceneNode and compare the primitives drawed by the video driver. (There is a getPrimitiveCountDrawed() method in the IVideoDriver class). Note that this optimization with the Octree is only useful when drawing huge meshes consisting of lots of geometry. */ scene::IQ3LevelMesh* const mesh = (scene::IQ3LevelMesh*) smgr->getMesh(mapname); /* add the geometry mesh to the Scene ( polygon & patches ) The Geometry mesh is optimised for faster drawing */ scene::ISceneNode* node = 0; if (mesh) { scene::IMesh * const geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); node = smgr->addOctreeSceneNode(geometry, 0, -1, 4096); } // create an event receiver for making screenshots CScreenShotFactory screenshotFactory(device, mapname, node); device->setEventReceiver(&screenshotFactory); /* now construct SceneNodes for each Shader The Objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS and the Shader ID is stored in the MaterialParameters mostly dark looking skulls and moving lava.. or green flashing tubes? */ if ( mesh ) { // the additional mesh can be quite huge and is unoptimized const scene::IMesh * const additional_mesh = mesh->getMesh(quake3::E_Q3_MESH_ITEMS); #ifdef SHOW_SHADER_NAME gui::IGUIFont *font = device->getGUIEnvironment()->getFont("../../media/fontlucida.png"); u32 count = 0; #endif for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount(); ++i ) { const IMeshBuffer* meshBuffer = additional_mesh->getMeshBuffer(i); const video::SMaterial& material = meshBuffer->getMaterial(); // The ShaderIndex is stored in the material parameter const s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader const quake3::IShader *shader = mesh->getShader(shaderIndex); if (0 == shader) { continue; } // we can dump the shader to the console in its // original but already parsed layout in a pretty // printers way.. commented out, because the console // would be full... // quake3::dumpShader ( Shader ); node = smgr->addQuake3SceneNode(meshBuffer, shader); #ifdef SHOW_SHADER_NAME count += 1; core::stringw name( node->getName() ); node = smgr->addBillboardTextSceneNode( font, name.c_str(), node, core::dimension2d<f32>(80.0f, 8.0f), core::vector3df(0, 10, 0)); #endif } } /* Now we only need a Camera to look at the Quake 3 map. And we want to create a user controlled camera. There are some different cameras available in the Irrlicht engine. For example the Maya Camera which can be controlled compareable to the camera in Maya: Rotate with left mouse button pressed, Zoom with both buttons pressed, translate with right mouse button pressed. This could be created with addCameraSceneNodeMaya(). But for this example, we want to create a camera which behaves like the ones in first person shooter games (FPS). */ scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); /* so we need a good starting Position in the level. we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" we choose a random launch */ if ( mesh ) { quake3::tQ3EntityList &entityList = mesh->getEntityList(); quake3::IEntity search; search.name = "info_player_deathmatch"; s32 index = entityList.binary_search(search); if (index >= 0) { s32 notEndList; do { const quake3::SVarGroup *group = entityList[index].getGroup(1); u32 parsepos = 0; const core::vector3df pos = quake3::getAsVector3df(group->get("origin"), parsepos); parsepos = 0; const f32 angle = quake3::getAsFloat(group->get("angle"), parsepos); core::vector3df target(0.f, 0.f, 1.f); target.rotateXZBy(angle); camera->setPosition(pos); camera->setTarget(pos + target); ++index; /* notEndList = ( index < (s32) entityList.size () && entityList[index].name == search.name && (device->getTimer()->getRealTime() >> 3 ) & 1 ); */ notEndList = index == 2; } while ( notEndList ); } } /* The mouse cursor needs not to be visible, so we make it invisible. */ device->getCursorControl()->setVisible(false); // load the engine logo gui->addImage(driver->getTexture("irrlichtlogo2.png"), core::position2d<s32>(10, 10)); // show the driver logo const core::position2di pos(videoDim.Width - 128, videoDim.Height - 64); switch ( driverType ) { case video::EDT_BURNINGSVIDEO: gui->addImage(driver->getTexture("burninglogo.png"), pos); break; case video::EDT_OPENGL: gui->addImage(driver->getTexture("opengllogo.png"), pos); break; case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: gui->addImage(driver->getTexture("directxlogo.png"), pos); break; } /* We have done everything, so lets draw it. We also write the current frames per second and the drawn primitives to the caption of the window. The 'if (device->isWindowActive())' line is optional, but prevents the engine render to set the position of the mouse cursor after task switching when other program are active. */ int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255,20,20,40)); smgr->drawAll(); gui->drawAll(); driver->endScene(); int fps = driver->getFPS(); //if (lastFPS != fps) { io::IAttributes * const attr = smgr->getParameters(); core::stringw str = L"Q3 ["; str += driver->getName(); str += "] FPS:"; str += fps; str += " Cull:"; str += attr->getAttributeAsInt("calls"); str += "/"; str += attr->getAttributeAsInt("culled"); str += " Draw: "; str += attr->getAttributeAsInt("drawn_solid"); str += "/"; str += attr->getAttributeAsInt("drawn_transparent"); str += "/"; str += attr->getAttributeAsInt("drawn_transparent_effect"); device->setWindowCaption(str.c_str()); lastFPS = fps; } } /* In the end, delete the Irrlicht device. */ device->drop(); return 0; }
void ModuleControl::OnEvent( const SEvent& event ) { // 鼠标消息处理 if (event.EventType == EET_MOUSE_INPUT_EVENT) { // 滚轮处理 if (event.MouseInput.Wheel == -1) { vector3df vForward; GetForwardVector(vForward); ModuleposRelateToCamaraVector = ModuleposRelateToCamaraVector*2; setModuleposRelateToCamara(ModuleposRelateToCamaraVector); } if (event.MouseInput.Wheel == 1) { vector3df vForward; GetForwardVector(vForward); ModuleposRelateToCamaraVector = ModuleposRelateToCamaraVector/2; setModuleposRelateToCamara(ModuleposRelateToCamaraVector); } IrrlichtDevice* device = MyIrrlichtEngine::GetEngine()->GetDevice(); CursorPos = device->getCursorControl()->getRelativePosition(); if (CursorPos.equals(CenterCursor)) { return; } if (event.MouseInput.isLeftPressed()) { vector3df v = pModule->getPosition(); matrix4 vm = pCamara->getProjectionMatrix(); //pCamara->get //f32 data[4]; //data[0] = v.X; //data[1] = v.Y; //data[2] = v.Z; //data[3] = 1; //vm.multiplyWith1x4Matrix(data); //std::cout << "a" <<std::endl; } // 鼠标移动处理 f32 xdelta = (CursorPos.Y - CenterCursor.Y)*30; f32 ydelta = (CursorPos.X - CenterCursor.X)*30; if (m_vCamaraRotation.X >= 85.0 && xdelta > 0) { xdelta = 0; } if (m_vCamaraRotation.X <= -85.0 && xdelta < 0) { xdelta = 0; } m_vCamaraRotation += vector3df(xdelta, 0.0, 0.0); m_vCamaraRotation += vector3df(0.0, ydelta, 0.0); SetCamaraRotation(m_vCamaraRotation); device->getCursorControl()->setPosition(CenterCursor); } // 按键消息处理 if (event.EventType == EET_KEY_INPUT_EVENT) { if (event.KeyInput.Key == KEY_KEY_W ) { } if (event.KeyInput.Key == KEY_KEY_S ) { } if (event.KeyInput.Key == KEY_KEY_A ) { m_vModuleRotation += vector3df(0.f, 0.f, 1.f); pModule->setRotation(m_vModuleRotation); } if (event.KeyInput.Key == KEY_KEY_D ) { m_vModuleRotation += vector3df(0.f, 0.f, -1.f); pModule->setRotation(m_vModuleRotation); } if (event.KeyInput.Key == KEY_UP) { } if (event.KeyInput.Key == KEY_DOWN) { } if (event.KeyInput.Key == KEY_LEFT) { } if (event.KeyInput.Key == KEY_RIGHT) { } } }
int main(int argc, char *argv[]) { int retval = 0; /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); // Set locale. This is for forcing '.' as the decimal point. std::locale::global(std::locale("C")); // This enables printing all characters in bitmap font setlocale(LC_CTYPE, "en_US"); /* Parse command line */ // List all allowed options core::map<std::string, ValueSpec> allowed_options; allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG, _("Show allowed options"))); allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, _("Load configuration from specified file"))); allowed_options.insert("port", ValueSpec(VALUETYPE_STRING, _("Set network port (UDP)"))); allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG, _("Disable unit tests"))); allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG, _("Enable unit tests"))); allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING, _("Same as --world (deprecated)"))); allowed_options.insert("world", ValueSpec(VALUETYPE_STRING, _("Set world path (implies local game) ('list' lists all)"))); allowed_options.insert("worldname", ValueSpec(VALUETYPE_STRING, _("Set world by name (implies local game)"))); allowed_options.insert("info", ValueSpec(VALUETYPE_FLAG, _("Print more information to console"))); allowed_options.insert("verbose", ValueSpec(VALUETYPE_FLAG, _("Print even more information to console"))); allowed_options.insert("trace", ValueSpec(VALUETYPE_FLAG, _("Print enormous amounts of information to log and console"))); allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING, _("Set logfile path ('' = no logging)"))); allowed_options.insert("gameid", ValueSpec(VALUETYPE_STRING, _("Set gameid (\"--gameid list\" prints available ones)"))); #ifndef SERVER allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG, _("Run speed tests"))); allowed_options.insert("address", ValueSpec(VALUETYPE_STRING, _("Address to connect to. ('' = local game)"))); allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG, _("Enable random user input, for testing"))); allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, _("Run dedicated server"))); allowed_options.insert("name", ValueSpec(VALUETYPE_STRING, _("Set player name"))); allowed_options.insert("password", ValueSpec(VALUETYPE_STRING, _("Set password"))); allowed_options.insert("go", ValueSpec(VALUETYPE_FLAG, _("Disable main menu"))); #endif Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1")) { dstream<<_("Allowed options:")<<std::endl; for(core::map<std::string, ValueSpec>::Iterator i = allowed_options.getIterator(); i.atEnd() == false; i++) { std::ostringstream os1(std::ios::binary); os1<<" --"<<i.getNode()->getKey(); if(i.getNode()->getValue().type == VALUETYPE_FLAG) {} else os1<<_(" <value>"); dstream<<padStringRight(os1.str(), 24); if(i.getNode()->getValue().help != NULL) dstream<<i.getNode()->getValue().help; dstream<<std::endl; } return cmd_args.getFlag("help") ? 0 : 1; } /* Low-level initialization */ // If trace is enabled, enable logging of certain things if(cmd_args.getFlag("trace")){ dstream<<_("Enabling trace level debug output")<<std::endl; log_trace_level_enabled = true; dout_con_ptr = &verbosestream; // this is somewhat old crap socket_enable_debug_output = true; // socket doesn't use log.h } // In certain cases, output info level on stderr if(cmd_args.getFlag("info") || cmd_args.getFlag("verbose") || cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests")) log_add_output(&main_stderr_log_out, LMT_INFO); // In certain cases, output verbose level on stderr if(cmd_args.getFlag("verbose") || cmd_args.getFlag("trace")) log_add_output(&main_stderr_log_out, LMT_VERBOSE); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_user); init_gettext((porting::path_share+DIR_DELIM+".."+DIR_DELIM+"locale").c_str()); // Initialize debug streams #define DEBUGFILE "debug.txt" #if RUN_IN_PLACE std::string logfile = DEBUGFILE; #else std::string logfile = porting::path_user+DIR_DELIM+DEBUGFILE; #endif if(cmd_args.exists("logfile")) logfile = cmd_args.get("logfile"); if(logfile != "") debugstreams_init(false, logfile.c_str()); else debugstreams_init(false, NULL); infostream<<"logfile = "<<logfile<<std::endl; infostream<<"path_share = "<<porting::path_share<<std::endl; infostream<<"path_user = "******"gameid") && cmd_args.get("gameid") == "list") { std::set<std::string> gameids = getAvailableGameIds(); for(std::set<std::string>::const_iterator i = gameids.begin(); i != gameids.end(); i++) dstream<<(*i)<<std::endl; return 0; } // List worlds if requested if(cmd_args.exists("world") && cmd_args.get("world") == "list"){ dstream<<_("Available worlds:")<<std::endl; std::vector<WorldSpec> worldspecs = getAvailableWorlds(); print_worldspecs(worldspecs, dstream); return 0; } // Print startup message infostream<<PROJECT_NAME<< " "<<_("with")<<" SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use std::string configpath = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } configpath = cmd_args.get("config"); } else { core::array<std::string> filenames; filenames.push_back(porting::path_user + DIR_DELIM + "minetest.conf"); // Legacy configuration file location filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #if RUN_IN_PLACE // Try also from a lower level (to aid having the same configuration // for many RUN_IN_PLACE installs) filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { configpath = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(configpath == "") configpath = filenames[0]; } // Initialize random seed srand(time(0)); mysrand(time(0)); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) commanded_world = cmd_args.get("world"); else if(cmd_args.exists("map-dir")) commanded_world = cmd_args.get("map-dir"); else if(cmd_args.exists("nonopt0")) // First nameless argument commanded_world = cmd_args.get("nonopt0"); else if(g_settings->exists("map-dir")) commanded_world = g_settings->get("map-dir"); // World name std::string commanded_worldname = ""; if(cmd_args.exists("worldname")) commanded_worldname = cmd_args.get("worldname"); // Strip world.mt from commanded_world { std::string worldmt = "world.mt"; if(commanded_world.size() > worldmt.size() && commanded_world.substr(commanded_world.size()-worldmt.size()) == worldmt){ dstream<<_("Supplied world.mt file - stripping it off.")<<std::endl; commanded_world = commanded_world.substr( 0, commanded_world.size()-worldmt.size()); } } // If a world name was specified, convert it to a path if(commanded_worldname != ""){ // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); bool found = false; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ if(commanded_world != ""){ dstream<<_("--worldname takes precedence over previously " "selected world.")<<std::endl; } commanded_world = worldspecs[i].path; found = true; break; } } if(!found){ dstream<<_("World")<<" '"<<commanded_worldname<<_("' not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // Gamespec SubgameSpec commanded_gamespec; if(cmd_args.exists("gameid")){ std::string gameid = cmd_args.get("gameid"); commanded_gamespec = findSubgame(gameid); if(!commanded_gamespec.isValid()){ errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl; return 1; } } /* Run dedicated server if asked to or no other option */ #ifdef SERVER bool run_dedicated_server = true; #else bool run_dedicated_server = cmd_args.getFlag("server"); #endif if(run_dedicated_server) { DSTACK("Dedicated server branch"); // Create time getter if built with Irrlicht #ifndef SERVER g_timegetter = new SimpleTimeGetter(); #endif // World directory std::string world_path; verbosestream<<_("Determining world path")<<std::endl; bool is_legacy_world = false; // If a world was commanded, use it if(commanded_world != ""){ world_path = commanded_world; infostream<<"Using commanded world path ["<<world_path<<"]" <<std::endl; } // No world was specified; try to select it automatically else { // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world name was specified, select it if(commanded_worldname != ""){ world_path = ""; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ world_path = worldspecs[i].path; break; } } if(world_path == ""){ dstream<<_("World")<<" '"<<commanded_worldname<<"' "<<_("not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // If there is only a single world, use it if(worldspecs.size() == 1){ world_path = worldspecs[0].path; dstream<<_("Automatically selecting world at")<<" [" <<world_path<<"]"<<std::endl; // If there are multiple worlds, list them } else if(worldspecs.size() > 1){ dstream<<_("Multiple worlds are available.")<<std::endl; dstream<<_("Please select one using --worldname <name>" " or --world <path>")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; // If there are no worlds, automatically create a new one } else { // This is the ultimate default world path world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "world"; infostream<<"Creating default world at [" <<world_path<<"]"<<std::endl; } } if(world_path == ""){ errorstream<<"No world path specified or found."<<std::endl; return 1; } verbosestream<<_("Using world path")<<" ["<<world_path<<"]"<<std::endl; // We need a gamespec. SubgameSpec gamespec; verbosestream<<_("Determining gameid/gamespec")<<std::endl; // If world doesn't exist if(!getWorldExists(world_path)) { // Try to take gamespec from command line if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; infostream<<"Using commanded gameid ["<<gamespec.id<<"]"<<std::endl; } // Otherwise we will be using "minetest" else{ gamespec = findSubgame(g_settings->get("default_game")); infostream<<"Using default gameid ["<<gamespec.id<<"]"<<std::endl; } } // World exists else { std::string world_gameid = getWorldGameId(world_path, is_legacy_world); // If commanded to use a gameid, do so if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; if(commanded_gamespec.id != world_gameid){ errorstream<<"WARNING: Using commanded gameid [" <<gamespec.id<<"]"<<" instead of world gameid [" <<world_gameid<<"]"<<std::endl; } } else{ // If world contains an embedded game, use it; // Otherwise find world from local system. gamespec = findWorldSubgame(world_path); infostream<<"Using world gameid ["<<gamespec.id<<"]"<<std::endl; } } if(!gamespec.isValid()){ errorstream<<"Subgame ["<<gamespec.id<<"] could not be found." <<std::endl; return 1; } verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; // Create server Server server(world_path, configpath, gamespec, false); server.start(port); // Run server dedicated_server_loop(server, kill); return 0; } #ifndef SERVER // Exclude from dedicated server build /* More parameters */ std::string address = g_settings->get("address"); if(commanded_world != "") address = ""; else if(cmd_args.exists("address")) address = cmd_args.get("address"); std::string playername = g_settings->get("name"); if(cmd_args.exists("name")) playername = cmd_args.get("name"); bool skip_main_menu = cmd_args.getFlag("go"); /* Device initialization */ // Resolution selection bool fullscreen = g_settings->getBool("fullscreen"); u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // bpp, fsaa, vsync bool vsync = g_settings->getBool("vsync"); u16 bits = g_settings->getU16("fullscreen_bpp"); u16 fsaa = g_settings->getU16("fsaa"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* Create device and exit if creation failed */ MyEventReceiver receiver; IrrlichtDevice *device; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(screenW, screenH); params.Bits = bits; params.AntiAlias = fsaa; params.Fullscreen = fullscreen; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) input = new RandomInputHandler(); else input = new RealInputHandler(device, &receiver); scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255,70,100,50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255,255,255,255)); #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 // Irrlicht 1.8 input colours skin->setColor(gui::EGDC_EDITABLE, video::SColor(255,128,128,128)); skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49)); #endif /* GUI stuff */ ChatBackend chat_backend; /* If an error occurs, this is set to something and the menu-game loop is restarted. It is then displayed before the menu. */ std::wstring error_message = L""; // The password entered during the menu screen, std::string password; bool first_loop = true; /* Menu-game loop */ while(device->run() && kill == false) { // Set the window caption device->setWindowCaption((std::wstring(L"Minetest [")+wgettext("Main Menu")+L"]").c_str()); // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* We need some kind of a root node to be able to add custom gui elements directly on the screen. Otherwise they won't be automatically drawn. */ guiroot = guienv->addStaticText(L"", core::rect<s32>(0, 0, 10000, 10000)); SubgameSpec gamespec; WorldSpec worldspec; bool simple_singleplayer_mode = false; // These are set up based on the menu and other things std::string current_playername = "inv£lid"; std::string current_password = ""; std::string current_address = "does-not-exist"; int current_port = 0; /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // If skip_main_menu, only go through here once if(skip_main_menu && !first_loop){ kill = true; break; } first_loop = false; // Cursor can be non-visible when coming from the game device->getCursorControl()->setVisible(true); // Some stuff are left to scene manager when coming from the game // (map at least?) smgr->clear(); // Initialize menu data MainMenuData menudata; if(g_settings->exists("selected_mainmenu_tab")) menudata.selected_tab = g_settings->getS32("selected_mainmenu_tab"); menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); if(cmd_args.exists("password")) menudata.password = narrow_to_wide(cmd_args.get("password")); menudata.fancy_trees = g_settings->getBool("new_style_leaves"); menudata.smooth_lighting = g_settings->getBool("smooth_lighting"); menudata.clouds_3d = g_settings->getBool("enable_3d_clouds"); menudata.opaque_water = g_settings->getBool("opaque_water"); menudata.mip_map = g_settings->getBool("mip_map"); menudata.anisotropic_filter = g_settings->getBool("anisotropic_filter"); menudata.bilinear_filter = g_settings->getBool("bilinear_filter"); menudata.trilinear_filter = g_settings->getBool("trilinear_filter"); menudata.enable_shaders = g_settings->getS32("enable_shaders"); menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map); menudata.creative_mode = g_settings->getBool("creative_mode"); menudata.enable_damage = g_settings->getBool("enable_damage"); // Default to selecting nothing menudata.selected_world = -1; // Get world listing for the menu std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If there is only one world, select it if(worldspecs.size() == 1){ menudata.selected_world = 0; } // Otherwise try to select according to selected_world_path else if(g_settings->exists("selected_world_path")){ std::string trypath = g_settings->get("selected_world_path"); for(u32 i=0; i<worldspecs.size(); i++){ if(worldspecs[i].path == trypath){ menudata.selected_world = i; break; } } } // If a world was commanded, append and select it if(commanded_world != ""){ std::string gameid = getWorldGameId(commanded_world, true); std::string name = _("[--world parameter]"); if(gameid == ""){ gameid = g_settings->get("default_game"); name += " [new]"; } WorldSpec spec(commanded_world, name, gameid); worldspecs.push_back(spec); menudata.selected_world = worldspecs.size()-1; } // Copy worldspecs to menu menudata.worlds = worldspecs; if(skip_main_menu == false) { video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Waiting for other menus"<<std::endl; while(device->run() && kill == false) { if(noMenuActive()) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Waited for other menus"<<std::endl; GUIMainMenu *menu = new GUIMainMenu(guienv, guiroot, -1, &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); if(error_message != L"") { verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; GUIMessageMenu *menu2 = new GUIMessageMenu(guienv, guiroot, -1, &g_menumgr, error_message.c_str()); menu2->drop(); error_message = L""; } infostream<<"Created main menu"<<std::endl; while(device->run() && kill == false) { if(menu->getStatus() == true) break; //driver->beginScene(true, true, video::SColor(255,0,0,0)); driver->beginScene(true, true, video::SColor(255,128,128,128)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Dropping main menu"<<std::endl; menu->drop(); } playername = wide_to_narrow(menudata.name); password = translatePassword(playername, menudata.password); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = wide_to_narrow(menudata.address); int newport = stoi(wide_to_narrow(menudata.port)); if(newport != 0) port = newport; simple_singleplayer_mode = menudata.simple_singleplayer_mode; // Save settings g_settings->setS32("selected_mainmenu_tab", menudata.selected_tab); g_settings->set("new_style_leaves", itos(menudata.fancy_trees)); g_settings->set("smooth_lighting", itos(menudata.smooth_lighting)); g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d)); g_settings->set("opaque_water", itos(menudata.opaque_water)); g_settings->set("mip_map", itos(menudata.mip_map)); g_settings->set("anisotropic_filter", itos(menudata.anisotropic_filter)); g_settings->set("bilinear_filter", itos(menudata.bilinear_filter)); g_settings->set("trilinear_filter", itos(menudata.trilinear_filter)); g_settings->setS32("enable_shaders", menudata.enable_shaders); g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals)); g_settings->set("creative_mode", itos(menudata.creative_mode)); g_settings->set("enable_damage", itos(menudata.enable_damage)); g_settings->set("name", playername); g_settings->set("address", address); g_settings->set("port", itos(port)); if(menudata.selected_world != -1) g_settings->set("selected_world_path", worldspecs[menudata.selected_world].path); // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; current_playername = playername; current_password = password; current_address = address; current_port = port; // If using simple singleplayer mode, override if(simple_singleplayer_mode){ current_playername = "singleplayer"; current_password = ""; current_address = ""; current_port = 30011; } // Set world path to selected one if(menudata.selected_world != -1){ worldspec = worldspecs[menudata.selected_world]; infostream<<"Selected world: "<<worldspec.name <<" ["<<worldspec.path<<"]"<<std::endl; } // Only refresh if so requested if(menudata.only_refresh){ infostream<<"Refreshing menu"<<std::endl; continue; } // Create new world if requested if(menudata.create_world_name != L"") { std::string path = porting::path_user + DIR_DELIM "worlds" + DIR_DELIM + wide_to_narrow(menudata.create_world_name); // Create world if it doesn't exist if(!initializeWorld(path, menudata.create_world_gameid)){ error_message = wgettext("Failed to initialize world"); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } g_settings->set("selected_world_path", path); continue; } // If local game if(current_address == "") { if(menudata.selected_world == -1){ error_message = wgettext("No world selected and no address " "provided. Nothing to do."); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } // Load gamespec for required game gamespec = findWorldSubgame(worldspec.path); if(!gamespec.isValid() && !commanded_gamespec.isValid()){ error_message = wgettext("Could not find or load game \"") + narrow_to_wide(worldspec.gameid) + L"\""; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } if(commanded_gamespec.isValid() && commanded_gamespec.id != worldspec.gameid){ errorstream<<"WARNING: Overriding gamespec from \"" <<worldspec.gameid<<"\" to \"" <<commanded_gamespec.id<<"\""<<std::endl; gamespec = commanded_gamespec; } if(!gamespec.isValid()){ error_message = wgettext("Invalid gamespec."); error_message += L" (world_gameid=" +narrow_to_wide(worldspec.gameid)+L")"; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } } // Continue to game break; } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; /* Run game */ the_game( kill, random_input, input, device, font, worldspec.path, current_playername, current_password, current_address, current_port, error_message, configpath, chat_backend, gamespec, simple_singleplayer_mode ); } //try catch(con::PeerNotFoundException &e) { error_message = wgettext("Connection error (timed out?)"); errorstream<<wide_to_narrow(error_message)<<std::endl; } catch(ServerError &e) { error_message = narrow_to_wide(e.what()); errorstream<<wide_to_narrow(error_message)<<std::endl; } catch(ModError &e) { errorstream<<e.what()<<std::endl; error_message = narrow_to_wide(e.what()) + wgettext("\nCheck debug.txt for details."); } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception: \""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif // If no main menu, show error and exit if(skip_main_menu) { if(error_message != L""){ verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; retval = 1; } break; } } // Menu-game loop delete input; /* In the end, delete the Irrlicht device. */ device->drop(); #endif // !SERVER // Update configuration file if(configpath != "") g_settings->updateConfigFile(configpath.c_str()); // Print modified quicktune values { bool header_printed = false; std::vector<std::string> names = getQuicktuneNames(); for(u32 i=0; i<names.size(); i++){ QuicktuneValue val = getQuicktuneValue(names[i]); if(!val.modified) continue; if(!header_printed){ dstream<<"Modified quicktune values:"<<std::endl; header_printed = true; } dstream<<names[i]<<" = "<<val.getString()<<std::endl; } } END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return retval; }
int main() { // ask user for driver video::E_DRIVER_TYPE driverType = driverChoiceConsole(); if (driverType == video::EDT_COUNT) return 1; // create device with full flexibility over creation parameters // you can add more parameters if desired, check irr::SIrrlichtCreationParameters irr::SIrrlichtCreationParameters params; params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(1024, 768); IrrlichtDevice* device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); env->getSkin()->setFont(env->getFont("media/fontlucida.png")); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); // Add camera scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.05f); camera->setPosition(core::vector3df(820, 100, 850)); camera->setTarget(core::vector3df(1530, 708, 1296)); camera->setFarValue(42000.0f); // camera->setPosition(core::vector3df(50,50,-60)); // camera->setTarget(core::vector3df(-70,30,-60)); // disable mouse cursor device->getCursorControl()->setVisible(false); // Add terrain scene node scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("media/terrain-heightmap.bmp", 0, // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(7.f, 1.f, 7.f), // scale video::SColor(255, 255, 255, 255), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4 // smoothFactor ); terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 100.0f); // create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); // create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(selector, camera, core::vector3df(1, 1, 1), core::vector3df(0, 0, 0)); selector->drop(); camera->addAnimator(anim); anim->drop(); // sphere scene::IMeshSceneNode* sphere = smgr->addSphereSceneNode(25.f, 100); sphere->setPosition(core::vector3df(800, 100, 800)); sphere->setScale(core::vector3df(2, 2, 2)); // Create decal manager DecalManager* decalManager = new DecalManager(smgr); decalManager->setTerrain(terrain); decalManager->addMesh(sphere); MyEventReceiver* receiver = new MyEventReceiver(decalManager, terrain, sphere); device->setEventReceiver(receiver); irr::video::SColor backgroundColor(10, 255, 255, 255); irr::video::SColor textColor(255, 255, 255, 255); int lastFPS = -1; irr::core::vector3df position = irr::core::vector3df(800, 300, 800); irr::core::vector3df dimension = irr::core::vector3df(1, 1, 1); irr::core::vector3df normal = irr::core::vector3df(1, 1, 0); irr::f32 textureRotation = 0; irr::scene::ISceneNode* parent = 0; irr::f32 lifeTime = 110; irr::f32 distance = 110; // decalManager->addDecal("media/decal.png", collisionPoint, irr::core::vector3df(size, size, size), normal, rotation, parent, lifetime, distance); decalManager->addDecal("media/decal.png", position, dimension, normal, textureRotation, parent, lifeTime, distance); while (device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, 0); smgr->drawAll(); env->getVideoDriver()->draw2DRectangle(backgroundColor, irr::core::rect<s32>(0, 0, 280, 220)); irr::core::stringw str = "SIZE: "; str += (irr::u32) receiver->size; str += " [ S & D ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 10, 200, 20), textColor, false, true); str = "LIFETIME: "; str += (irr::u32) receiver->lifetime; str += " [ O & L ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 30, 200, 50), textColor, false, true); str = "DISTANCE: "; str += (irr::u32) receiver->distance; str += " [ I & K ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 60, 200, 80), textColor, false, true); str = "ROTATION: "; str += (irr::u32) receiver->rotation; str += " [ R or R Mouse Button ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 90, 200, 110), textColor, false, true); str = "COMBINE [C]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 120, 200, 140), textColor, false, true); str = "DECAL NORMAL: "; if (receiver->useCameraNormal) { str += "CAMERA DIRECTION"; } else { str += "HIT TRIANGLE"; } str += " [ N ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 150, 200, 170), textColor, false, true); str = "SPHERE AS PARENT: "; if (receiver->useParent) { str += "YES"; } else { str += "NO"; } str += " [ P ]"; env->getSkin()->getFont()->draw(str.c_str(), irr::core::rect<s32>(10, 180, 200, 200), textColor, false, true); irr::video::SColor color = irr::video::SColor(255, 255, 255, 255); u32 size = 15; irr::u32 cenW = (irr::u32) (driver->getScreenSize().Width * 0.5); irr::u32 cenH = (irr::u32) (driver->getScreenSize().Height * 0.5); //Draw crosshair driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH - size, cenW + 1, cenH - 4)); //above driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW + 4, cenH - 1, cenW + size, cenH + 1)); //right driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH + 4, cenW + 1, cenH + size)); //down driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - size, cenH - 1, cenW - 4, cenH + 1)); //left driver->draw2DRectangle(color, irr::core::rect<irr::s32>(cenW - 1, cenH - 1, cenW + 1, cenH + 1)); //center of screen env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"TANK@WAR DecalManager ["; str += driver->getName(); str += "] FPS:"; str += fps; str += " Nodes: "; str += smgr->getRootSceneNode()->getChildren().size(); str += " Primitives: "; str += driver->getPrimitiveCountDrawn(); device->setWindowCaption(str.c_str()); lastFPS = fps; } } } device->drop(); return 0; }
bool Tutorial12::Run() { IrrlichtDevice *device = createDevice(video::EDT_OPENGL, dimension2d<u32>(180,120), 16, false, false, false, 0); if(device==0) { return false; } video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); gui::IGUIEnvironment* env = device->getGUIEnvironment(); driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); env->addImage(driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlichtlogo2.png"), core::position2d<s32>(10,10)); env->getSkin()->setFont(env->getFont("../irrlicht/irrlicht-1.7.3/media/fontlucida.png")); scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f, 1.2f); camera->setPosition(core::vector3df(2700*2, 255*2, 2600*2)); camera->setTarget(core::vector3df(2397*2, 343*2, 2700*2)); camera->setFarValue(42000.0f); device->getCursorControl()->setVisible(false); scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("../irrlicht/irrlicht-1.7.3/media/terrain-heightmap.bmp", 0, // parent node // parent node -1, // node id core::vector3df(0.f, 0.f, 0.f), // position core::vector3df(0.f, 0.f, 0.f), // rotation core::vector3df(40.f, 4.4f, 40.f), // scale video::SColor ( 255, 255, 255, 255 ), // vertexColor 5, // maxLOD scene::ETPS_17, // patchSize 4); // smoothFactor terrain->setMaterialFlag(video::EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("../irrlicht/irrlicht-1.7.3/media/terrain-texture.jpg")); terrain->setMaterialTexture(1, driver->getTexture("../irrlicht/irrlicht-1.7.3/media/detailmap3.jpg")); terrain->setMaterialType(video::EMT_DETAIL_MAP); terrain->scaleTexture(1.0f, 20.0f); //collision scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain,0); terrain->setTriangleSelector(selector); scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); selector->drop(); camera->addAnimator(anim); anim->drop(); //add collision responder to camera, i.e. gravity! anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(10,20,10), core::vector3df(0,-5,0), core::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. //to access terrain data, do this! scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); terrain->getMeshBufferForLOD(*buffer, 0); video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); //work on data or get the IndexBuffer with a similar call buffer->drop(); //create skybox and skydome driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); scene::ISceneNode* skybox = smgr->addSkyBoxSceneNode( driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_up.jpg"), driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_dn.jpg"), driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_lf.jpg"), driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_rt.jpg"), driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_ft.jpg"), driver->getTexture("../irrlicht/irrlicht-1.7.3/media/irrlicht2_bk.jpg")); scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../irrlicht/irrlicht-1.7.3/media/skydome.jpg"),16,8,0.95f, 2.0f); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); //event receiver MyEventReceiver12 receiver(terrain, skybox, skydome); device->setEventReceiver(&receiver); int lastFPS = -1; while(device->run()) if (device->isWindowActive()) { driver->beginScene(true, true, 0 ); smgr->drawAll(); env->drawAll(); driver->endScene(); // display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin str += " Height: "; str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z); device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); return false; }