/* ========================================================================== * (C) 2006 Universitat Jaume I * ========================================================================== * PROYECT: GAME TOOLS * ==========================================================================*/ /** CONTENT: * * * @file main.cpp /** COMMENTS: * Model must be in "media/models" folder. * Lod file must be in "media/GT" folder. /*===========================================================================*/ #include "ExampleApplication.h" #include "GeoLodManager.h" #include "GeoMeshLoader.h" #include "audiere.h" // Distance values #define dist_min 2000 #define dist_max 4000 // Model name //#define model_name "dwarf2" //Global variables Geometry::LodManager* lodManager = NULL; Geometry::Mesh *the_lodstrips_mesh = NULL, *the_lodtree_mesh = NULL; Geometry::GeoMeshLoader *lodstrips_meshloader = NULL, *lodtree_meshloader = NULL; Ogre::SceneManager *sceneManager = NULL; Ogre::Entity *orig_lodstrips_entity = NULL, *orig_lodtree_entity = NULL; audiere::AudioDevicePtr device(audiere::OpenDevice()); audiere::OutputStreamPtr song(OpenSound(device,"../../musica.mp3",false)); MaterialPtr *mat; ColourValue color=ColourValue::Red; Camera* theCam; Entity* pPlaneEnt; char HelpString[]="(F1) Quit this Help\n" "This demo shows an example of the LODManager in action. Every model in the scene\n" "has its own LodStrips object associated that manages its level of detail.\n" "Since the scene is highly populated, changing the LOD of every object independently\n" "would make the performance to fall.\n" "The LodManager makes efficient LOD computations by reusing previously calculated LODs.\n" "The level of detail of the objects depends on the distance to the camera. When the\n" "camera goes away from them, the level of detail decreases, and when the camera gets\n" "closer to them increases to restore the original geometry of the model.\n" "(F4) LODManager ON\n" "(F3) LODManager OFF\n\n" "IMPORTANT: to notice performance improvements the user must move the camera, since the\n" "LOD in only re-calculated when the camera position changes."; char NoHelpString[]="\n\n\n\n\n\n\n\n\n\n\n\n\n(F1) Help\n"; OverlayElement* mLOD; OverlayElement* mInfo; OverlayElement* mInfo2; OverlayElement* mHelp; //Ogre::OverlayElement *mInfo, *mInfo2; // framerate test std::vector framerates; const unsigned int msDelay = 1000; class CustomIndexData : public Geometry::IndexData { private: Ogre::Mesh *targetMesh; Ogre::HardwareIndexBufferSharedPtr ibuf; unsigned long* pIdx; Ogre::HardwareIndexBufferSharedPtr *orig_indexbuff; public: CustomIndexData(Ogre::Mesh *ogremesh):Geometry::IndexData(){ targetMesh=ogremesh; pIdx=NULL; orig_indexbuff=new Ogre::HardwareIndexBufferSharedPtr[targetMesh->getNumSubMeshes()]; for (int i=0; igetNumSubMeshes(); i++) { Ogre::RenderOperation mRenderOp; targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOp,0); orig_indexbuff[i] = mRenderOp.indexData->indexBuffer; } } virtual ~CustomIndexData(void){ delete[] orig_indexbuff; } virtual void Begin(unsigned int submeshid, unsigned int indexcount){ Ogre::RenderOperation mRenderOp; targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0); // restore the original index data to modify it mRenderOp.indexData->indexBuffer = orig_indexbuff[submeshid]; ibuf = mRenderOp.indexData->indexBuffer; mRenderOp.indexData->indexCount = indexcount; pIdx = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); } virtual void SetIndex(unsigned int i, unsigned int index){ pIdx[i] = index; } virtual void End(){ ibuf->unlock(); } virtual void BorrowIndexData(const Geometry::IndexData *idata){ CustomIndexData *custom_data = (CustomIndexData*)idata; for (int i=0; igetNumSubMeshes(); i++) { Ogre::RenderOperation mRenderOp, mRenderOpParam; targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOp,0); custom_data->targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOpParam,0); mRenderOp.indexData->indexBuffer = mRenderOpParam.indexData->indexBuffer; mRenderOp.indexData->indexCount = mRenderOpParam.indexData->indexCount; } } }; void AddNewLodStripsObj(void) { const int troop_width = 30; static int iname = 0; int i = iname%troop_width; int j = iname/troop_width; char newObjName[16]=""; sprintf(newObjName,"model_%d",iname); char newMeshName[16]=""; sprintf(newMeshName,"mesh_%d",iname); iname++; Ogre::Mesh *ogreMesh = orig_lodstrips_entity->getMesh()->clone(newMeshName).getPointer(); Entity *entity = sceneManager->createEntity(newObjName,newMeshName); entity->setNormaliseNormals(true); Ogre::SceneNode * auxnode = sceneManager->getRootSceneNode()->createChildSceneNode(); auxnode->attachObject(entity); auxnode->rotate(Ogre::Vector3(0,1,0),Ogre::Degree(180.0f),Ogre::Node::TS_WORLD); auxnode->scale(30.0f,30.0f,30.0f); float randomsepx = (float)((rand()%18)-9); float randomsepy = (float)((rand()%12)-6); auxnode->translate(i*120.0f+randomsepx,0.0f,-j*120.0f-randomsepx); // auxnode->translate(0,0,-500.0f); Geometry::LodStripsLibrary *myStrips = new Geometry::LodStripsLibrary( lodstrips_meshloader->GetLodStripsData(), the_lodstrips_mesh, new CustomIndexData(ogreMesh)); entity->setMaterialName("LODStripsDemo/Ogro"); // add the object to the manager Ogre::Vector3 opos = auxnode->getPosition(); lodManager->AddLodObj("ogre",myStrips,Geometry::Vector3(opos.x,opos.y,opos.z)); } void AddNewLodTreeObj(void) { const int troop_width = 10; static int iname = 0; int i = iname%troop_width; int j = iname/troop_width; char newObjName[16]=""; sprintf(newObjName,"tree_%d",iname); char newMeshName[16]=""; sprintf(newMeshName,"tree_%d",iname); iname++; Ogre::Mesh *ogreMesh = orig_lodtree_entity->getMesh()->clone(newMeshName).getPointer(); Entity *entity = sceneManager->createEntity(newObjName,newMeshName); entity->setNormaliseNormals(true); Ogre::SceneNode * auxnode = sceneManager->getRootSceneNode()->createChildSceneNode(); auxnode->attachObject(entity); auxnode->scale(11.0f,11.0f,11.0f); auxnode->rotate(Ogre::Vector3(0,0,1),Ogre::Degree(rand()%360)); auxnode->rotate(Ogre::Vector3(1,0,0),Ogre::Radian(-3.14159f*0.5f),Ogre::Node::TS_WORLD); float randomsepx = (float)((rand()%18)-9); float randomsepy = (float)((rand()%12)-6); auxnode->translate(i*60.0f+randomsepx,-1.0f,-j*60.0f-randomsepx); auxnode->translate(300,0,-500.0f); Geometry::LodTreeLibrary *myTree = new Geometry::LodTreeLibrary( lodtree_meshloader->GetLodStripsData(), lodtree_meshloader->GetTreeSimpSeq(), the_lodtree_mesh, new CustomIndexData(ogreMesh)); // load the right material for each part of the tree for (int submesh=0; submesh < ogreMesh->getNumSubMeshes(); submesh++) { bool istrunk = myTree->GetLeavesSubMesh()!=submesh; if (istrunk) entity->getSubEntity(submesh)->setMaterialName("Examples/Populifolia/trunk"); else entity->getSubEntity(submesh)->setMaterialName("Examples/Populifolia/leaf"); } // add the object to the manager Ogre::Vector3 opos = auxnode->getPosition(); lodManager->AddLodObj("tree",myTree,Geometry::Vector3(opos.x,opos.y,opos.z)); } class LodManagerFrameListener : public ExampleFrameListener { int manage; public: LodManagerFrameListener(RenderWindow* win, Camera* cam) : ExampleFrameListener(win, cam, false, false) { manage=1; } bool frameStarted(const FrameEvent& evt) { Vector3 dist; int distance=0,inc2=0; // test static float timeLeft = 0; const RenderTarget::FrameStats& stats = mWindow->getStatistics(); static bool rec_stats = false; if (mInputDevice->isKeyDown(Ogre::KC_J)) rec_stats=true; if (rec_stats) { if (timeLeft <= 0.0f) { framerates.push_back(stats.lastFPS); timeLeft = msDelay; } timeLeft -= evt.timeSinceLastFrame * 1000.0f; } // Move upto 80 units/second Real MoveFactor = 180.0 * evt.timeSinceLastFrame; // Copy the current state of the input devices mInputDevice->capture(); // If this is the first frame, pick a speed if (evt.timeSinceLastFrame == 0) { mMoveScale = 1; mRotScale = 0.1; } // Otherwise scale movement units by time passed since last frame else { // Move about 100 units per second, mMoveScale = mMoveSpeed * evt.timeSinceLastFrame; // Take about 10 seconds for full rotation mRotScale = mRotateSpeed * evt.timeSinceLastFrame; } mRotX = 0; mRotY = 0; mTranslateVector = Vector3::ZERO; lodManager->UpdateLOD(stats.lastFPS,90); bool cam_moved=false; if (mInputDevice->isKeyDown(Ogre::KC_F3)) { lodManager->always_calculate_lod = true; cam_moved = true; } if (mInputDevice->isKeyDown(Ogre::KC_F4)) { lodManager->always_calculate_lod = false; cam_moved = true; } //if (mInputDevice->isKeyDown(Ogre::KC_F7)) //{ // lodManager->force_highest_lod = true; // cam_moved = true; //} //if (mInputDevice->isKeyDown(Ogre::KC_F8)) //{ // lodManager->force_highest_lod = false; // cam_moved = true; //} // Move the cam if(mInputDevice->isKeyDown(Ogre::KC_UP)) { mTranslateVector.z = -mMoveScale; cam_moved=true; } if(mInputDevice->isKeyDown(Ogre::KC_DOWN)) { mTranslateVector.z = mMoveScale; cam_moved=true; } // Instead of moving the ship left and right, rotate it using yaw() if(mInputDevice->isKeyDown(Ogre::KC_LEFT)) { mCamera->yaw(mRotScale); cam_moved=true; } if(mInputDevice->isKeyDown(Ogre::KC_RIGHT)) { mCamera->yaw(-mRotScale); cam_moved=true; } if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE)) { delete lodManager; delete [] mat; FILE *f=fopen("fps.txt","wt"); unsigned int ms = 0; for (std::vector::iterator it = framerates.begin(); it != framerates.end(); it++, ms++) fprintf(f,"%u %f\n",ms,*it); fclose(f); return false; } static bool newpush = true; if (!mInputDevice->isKeyDown(Ogre::KC_F1)) newpush = true; static bool showing_help = false; if (mInputDevice->isKeyDown(Ogre::KC_F1) && newpush) { newpush = false; if (showing_help = !showing_help) mHelp->setCaption(HelpString); else mHelp->setCaption(NoHelpString); } if( mInputDevice->getMouseButton( 1 ) ) { mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13; mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13; cam_moved=true; } else { mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13); mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13); } char cadena[256]; if ( lodManager->always_calculate_lod ) sprintf(cadena,"\n\nLOD Manager: OFF\nTriangle Count: %d\n",stats.triangleCount); else sprintf(cadena,"\n\nLOD Manager: ON\nTriangle Count: %d\n",stats.triangleCount); mInfo->setCaption(cadena); mWindow->getStatistics(); sprintf(cadena,"Current FPS: %f\n",stats.lastFPS); mInfo2->setCaption(cadena); mCamera->yaw(mRotX); mCamera->pitch(mRotY); mCamera->moveRelative(mTranslateVector); if (cam_moved) lodManager->UpdateCamera(Geometry::Vector3(mCamera->getPosition().x,mCamera->getPosition().y,mCamera->getPosition().z)); return true; } }; class LodManagerApplication : public ExampleApplication { public: LodManagerApplication() {} ~LodManagerApplication() {} protected: // Just override the mandatory create scene method void createScene(void) { mat = new MaterialPtr[1]; theCam = mCamera; theCam->setPosition(1900,200,800); // Set ambient light sceneManager = mSceneMgr; mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2)); //SHADOWS //mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE); //mSceneMgr->setShadowTextureSettings(2048,1); //mSceneMgr->setShadowFarDistance(2048); //mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5)); // Create a point light Light* l = mSceneMgr->createLight("MainLight"); l->setType(Light::LT_DIRECTIONAL); l->setDirection(-0.5,-1.0,-1.0); mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox"); // My node to which all objects will be attached SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); // Define a floor plane mesh Plane plane( Vector3::UNIT_Y, 0 ); MeshManager::getSingleton().createPlane("ground", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane, 40000,40000,6,6,true,1,200,200,Vector3::UNIT_Z); Entity* groundEntity = mSceneMgr->createEntity( "GroundEntity", "ground" ); mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(groundEntity); groundEntity->setMaterialName("SnowTerrain"); groundEntity->setCastShadows(false); lodManager = new Geometry::LodManager(dist_min,dist_max,Geometry::Vector3(theCam->getPosition().x,theCam->getPosition().y,theCam->getPosition().z),100); lodManager->UpdateCamera(Geometry::Vector3( theCam->getPosition().x, theCam->getPosition().y, theCam->getPosition().z )); // load the LodStrips info from the object ///////////////////////////////////////////////////////////////// lodstrips_meshloader=new Geometry::GeoMeshLoader; the_lodstrips_mesh = lodstrips_meshloader->load("../../../OgreStuff/media/GT/ogrolod.mesh"); if (!lodstrips_meshloader->GetLodStripsData()) OGRE_EXCEPT(1, "The loaded mesh does not contain any LOD info","LOD Demo"); orig_lodstrips_entity = mSceneMgr->createEntity("orig_lods", "../../../OgreStuff/media/GT/ogrolod.mesh"); // load the LodTree info from the object ////////////////////////////////////////////////////////////////// /* lodtree_meshloader=new Geometry::GeoMeshLoader; the_lodtree_mesh = lodtree_meshloader->load("../../../OgreStuff/media/GT/ML11.mesh"); if (!lodtree_meshloader->GetLodStripsData()) OGRE_EXCEPT(1, "The loaded mesh does not contain LODStrips info","LOD Demo"); if (!lodtree_meshloader->GetTreeSimpSeq()) OGRE_EXCEPT(1, "The loaded mesh does not contain LODTree info","LOD Demo"); orig_lodtree_entity = mSceneMgr->createEntity("orig_lodt", "../../../OgreStuff/media/GT/ML11.mesh");*/ // Add objects to the LodManager! /* for (int i=0; i<25; i++) AddNewLodTreeObj();*/ //audiere::AudioDevicePtr device(audiere::OpenDevice()); //audiere::OutputStreamPtr song(OpenSound(device,"../../musica.mp3",false)); song->setVolume(0.5f); song->setRepeat(true); song->play(); for (int i=0; i<1000; i++) AddNewLodStripsObj(); // show overlay Overlay* pOver = OverlayManager::getSingleton().getByName("Demo_LodStrips/Overlay"); mInfo = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_1"); mInfo2 = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_2"); mHelp = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Help"); mHelp->setCaption(NoHelpString); pOver->show(); // pOver->hide(); } void createFrameListener(void) { mFrameListener= new LodManagerFrameListener(mWindow, mCamera); mFrameListener->showDebugOverlay(false); mRoot->addFrameListener(mFrameListener); } }; #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #ifdef __cplusplus extern "C" { #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char **argv) #endif { // Create application object LodManagerApplication app; try { app.go(); } catch( Exception& e ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription(); #endif } return 0; } #ifdef __cplusplus } #endif