/** The result should be as follows: We have three times the same image, a billboard with a cube and the text in front. They are replicated three times, one centered in the screen without viewport, one in the upper left (qurter screen) and one on the right (half screen). The latter is stretched due to the changed aspect ratio. The two viewport scenes get the texture drawn over the center as well, using draw2dimage. This should mark the proper image position with the top left corner of the texture. Finally, each scene has a checkbox drawn at the left side, vertically centered. This will show whether GUI elements adhere to viewports as well. */ static bool viewPortText(E_DRIVER_TYPE driverType) { IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32); if (!device) return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs IVideoDriver* driver = device->getVideoDriver(); ISceneManager * smgr = device->getSceneManager(); IGUIEnvironment* env = smgr->getGUIEnvironment(); stabilizeScreenBackground(driver); env->addCheckBox(true, core::recti(10,60,28,82)); logTestString("Testing driver %ls\n", driver->getName()); IBillboardSceneNode * bnode = smgr->addBillboardSceneNode(0,dimension2d<f32>(32,32),core::vector3df(0,0,10)); bnode->setMaterialFlag(video::EMF_LIGHTING, false); bnode->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bnode->setMaterialTexture(0, driver->getTexture("../media/fire.bmp")); smgr->addTextSceneNode(device->getGUIEnvironment()->getBuiltInFont(), L"TEST", video::SColor(255,255,255,255), 0); smgr->addCubeSceneNode(); smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); env->drawAll(); driver->setViewPort(rect<s32>(0,0,160/2,120/2)); smgr->drawAll(); env->drawAll(); driver->draw2DImage(driver->getTexture("../media/fire.bmp"), core::vector2di(160/2,120/2)); driver->setViewPort(rect<s32>(160/2,0,160,120)); smgr->drawAll(); env->drawAll(); driver->draw2DImage(driver->getTexture("../media/fire.bmp"), core::vector2di(160/2,120/2)); driver->endScene(); bool result = takeScreenshotAndCompareAgainstReference(driver, "-viewPortText.png", 98.71f); device->closeDevice(); device->run(); device->drop(); return result; }
/* That's it. The Scene node is done. Now we simply have to start the engine, create the scene node and a camera, and look at the result. */ int main() { // ask user for driver video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; //FIXME: hardcoded driverChoiceConsole(); if (driverType == video::EDT_COUNT) return 1; // create device MyEventReceiver receiver; g_Device = createDevice(driverType, core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver); if (g_Device == 0) return 1; // could not create selected driver. // create engine and camera g_Device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo"); video::IVideoDriver* driver = g_Device->getVideoDriver(); scene::ISceneManager* smgr = g_Device->getSceneManager(); IGUIEnvironment* env = g_Device->getGUIEnvironment(); IGUISkin* skin = env->getSkin(); IGUIFont* font = env->getFont("media/fonthaettenschweiler.bmp"); if (font) skin->setFont(font); skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP); env->addStaticText(L"Movement speed:", rect<s32> (GUI_X, GUI_Y, GUI_X + 95, GUI_Y + 20), true); IGUIScrollBar* scrollbar = env->addScrollBar(true, rect<s32> (GUI_X + 100, GUI_Y, GUI_X + 100 + 200, GUI_Y + 20), 0, GUI_ID_SPEED_SCROLL); //scrollbar->drop(); //max speed -> 1000 * 1000 / 100000 = 10 km/frame //min speed -> 10 * 10 / 100000 = 1m / frame scrollbar->setMax(1000); scrollbar->setMin(10); scrollbar->setPos(255); // add a camera scene node scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); //scene::ICameraSceneNode* camera = addCameraSceneNodeFPS(smgr); g_CameraAnimator = JWSceneNodeAnimatorCameraFPS::injectOnFPSCamera(camera); g_CameraAnimator->setMoveSpeed(scrollbar->getPos() / 5000.0); g_CameraAnimator->setAnimationEventsReceiver(&receiver); env->addStaticText(L"Level:", rect<s32> (GUI_X, GUI_Y + 22, GUI_X + 95, GUI_Y + 22 + 20), true); scrollbar = env->addScrollBar(true, rect<s32> (GUI_X + 100, GUI_Y + 22, GUI_X + 100 + 200, GUI_Y + 22 + 20), 0, GUI_ID_LEVEL); #define START_LEVEL 14 scrollbar->setMax(14); scrollbar->setMin(0); scrollbar->setPos(START_LEVEL); g_LevelScroll = scrollbar; env->addStaticText(L"Wireframe:", rect<s32> (GUI_X, GUI_Y + 22 + 22, GUI_X + 95, GUI_Y + 22 + 22 + 20), true); env->addCheckBox(false, rect<s32> (GUI_X + 100, GUI_Y + 22 + 22, GUI_X + 100 + 200, GUI_Y + 22 + 22 + 20), 0, GUI_ID_WIREFRAME); env->addStaticText(L"Update mesh:", rect<s32> (GUI_X, GUI_Y + 22 + 22 + 22, GUI_X + 95, GUI_Y + 22 + 22 + 22 + 20), true); env->addCheckBox(true, rect<s32> (GUI_X + 100, GUI_Y + 22 + 22 + 22, GUI_X + 100 + 200, GUI_Y + 22 + 22 + 22 + 20), 0, GUI_ID_MESH_UPDATE); SKeyMap keyMap[] = { { EKA_MOVE_FORWARD, KEY_KEY_W }, { EKA_MOVE_BACKWARD, KEY_KEY_S }, { EKA_STRAFE_LEFT, KEY_KEY_A }, { EKA_STRAFE_RIGHT, KEY_KEY_D }, { EKA_JUMP_UP, KEY_SPACE }, { EKA_CROUCH, KEY_LSHIFT } }; g_CameraAnimator->setKeyMap(keyMap, 6); core::vector3df earthCenter(0, 0, 0); camera->setFarValue(500000.f); //500 000 km //camera->setUpVector(core::vector3df(0,0,1)); camera->setPosition(core::vector3df(100, 100, -EARTH_RADIUS - 200.)); camera->setTarget(earthCenter); //camera->setFarValue(20000.f); //camera->setPosition(core::vector3df(0,0,-200)); // Maya cameras reposition themselves relative to their target, so target the location // where the mesh scene node is placed. //camera->setTarget(core::vector3df(0, 0, 0)); //smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0)); /* Create our scene node. I don't check the result of calling new, as it should throw an exception rather than returning 0 on failure. Because the new node will create itself with a reference count of 1, and then will have another reference added by its parent scene node when it is added to the scene, I need to drop my reference to it. Best practice is to drop it only *after* I have finished using it, regardless of what the reference count of the object is after creation. */ g_EarthVisualization = new SphereVisualization(smgr->getRootSceneNode(), smgr, driver, 666, START_LEVEL, earthCenter, EARTH_RADIUS); g_EarthVisualization->setMaterialType(video::EMT_SOLID); //g_textre = driver->getTexture("media/earth.bmp"); //g_EarthVisualization->getMaterial().setTexture(0, g_textre); g_EarthVisualization->setViewerPoint(camera->getPosition()); /* To animate something in this boring scene consisting only of one tetraeder, and to show that you now can use your scene node like any other scene node in the engine, we add an animator to the scene node, which rotates the node a little bit. irr::scene::ISceneManager::createRotationAnimator() could return 0, so should be checked. */ scene::ISceneNodeAnimator *anim = 0; //smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f)); if (anim) { g_EarthVisualization->addAnimator(anim); /* I'm done referring to anim, so must irr::IReferenceCounted::drop() this reference now because it was produced by a createFoo() function. As I shouldn't refer to it again, ensure that I can't by setting to 0. */ anim->drop(); anim = 0; } /* I'm done with my CSampleSceneNode object, and so must drop my reference. This won't delete the object, yet, because it is still attached to the scene graph, which prevents the deletion until the graph is deleted or the custom scene node is removed from it. */ g_EarthVisualization->drop(); //myNode = 0; // As I shouldn't refer to it again, ensure that I can't scene::ISceneNode *bill = smgr->addBillboardSceneNode(0, core::dimension2d< f32>(600, 600), earthCenter, 113); //600x600 km billboard 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")); //bill->drop(); /* Now draw everything and finish. */ u32 frames = 0; while (g_Device->run()) { driver->beginScene(true, true, video::SColor(0, 100, 100, 100)); smgr->drawAll(); env->drawAll(); driver->endScene(); if (++frames == 100) { core::vector3df vpoint = g_EarthVisualization->getViewerPoint(); vpoint.normalize(); core::vector2d<f32> txCoord = g_EarthVisualization->getSphericalCoordinates(vpoint); core::stringw str = L"FPS: "; str += (s32) (driver->getFPS()); str += L" TCoord:("; str += txCoord.X; str += L", "; str += txCoord.Y; str += L") Tile: "; str.printBinary(g_EarthVisualization->getUTriangleUnderUs(), 32, L'0', L'1'); g_Device->setWindowCaption(str.c_str()); frames = 0; } } g_Device->drop(); return 0; }