/* ========================================================================== * (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 "GeoLodTreeLibrary.h" #include "GeoMeshLoader.h" // Distance values #define dist_min 300 #define dist_max 900 // Model name #define model_name "arbol" //Global variables Entity* entity; Geometry::LodTreeLibrary* myTrees; Ogre::Mesh *ogreMesh=NULL; Geometry::GeoMeshLoader *meshloader=NULL; bool force_maxLODfactor = false; Ogre::Vector3 forest_center; ColourValue color=ColourValue::Red; Camera* theCam; Entity* pPlaneEnt; OverlayElement* mInfo; OverlayElement* mInfo2; OverlayElement* mHelp; char HelpString[]="(F1) Help\n" "This demo shows an example of the LodTree model in action. The trees in the scene\n" "are associated to a LodTree object that manage their level of detail of both the\n" "trunk and the leaves. The level of detail of the objects depend on the distance to\n" "the camera. When the camera goes away from them, the level of detail decreases, and\n" "when the camera gets closer to them the level of detail increases to restore the\n" "original geometry of the model.\n" "The current level of detail can be seen in real-time in the top-left corner of the screen.\n" "The level of detail begins to decrease at a certain distance of the forest, and stops\n" "decreasing when the objects reach the their minimum LOD. This 'lodding' distance is\n" "customizable from the source code of the demo."; char NoHelpString[]="(F1) Help\n"; class LodTreeFrameListener : public ExampleFrameListener { int manage; public: LodTreeFrameListener(RenderWindow* win, Camera* cam) : ExampleFrameListener(win, cam, false, false) { manage=1; } bool frameStarted(const FrameEvent& evt) { Vector3 dist; int distance=0,inc2=0,d; unsigned int nlod,diflods; // 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; //LOD selection int difdist = dist_max - dist_min; int i=0; dist = forest_center - mCamera->getPosition(); distance =dist.length(); float lodfactor = (float)(distance - dist_min) / (float)(dist_max - dist_min); lodfactor = 1.0f - lodfactor; if (lodfactor<0.0f) lodfactor=0.0f; if (lodfactor>1.0f) lodfactor=1.0f; if (force_maxLODfactor) lodfactor=1.0f; static float lodfactorBefore = -1.0f; if (fabsf(lodfactorBefore-lodfactor)>0.1f) { myTrees->GoToLod(lodfactor); // DumpDataToOgreBuffers(ogreMesh,myTrees); lodfactorBefore=lodfactor; } // Move the cam if(mInputDevice->isKeyDown(Ogre::KC_UP) || mInputDevice->isKeyDown(Ogre::KC_W) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD5)) mTranslateVector.z = -mMoveScale; if(mInputDevice->isKeyDown(Ogre::KC_DOWN) || mInputDevice->isKeyDown(Ogre::KC_S) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD2)) mTranslateVector.z = mMoveScale; if (mInputDevice->isKeyDown(Ogre::KC_A) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD1)) mTranslateVector.x = -mMoveScale; if (mInputDevice->isKeyDown(Ogre::KC_D) || mInputDevice->isKeyDown(Ogre::KC_NUMPAD3)) mTranslateVector.x = mMoveScale; // Instead of moving the ship left and right, rotate it using yaw() if(mInputDevice->isKeyDown(Ogre::KC_LEFT)) mCamera->yaw(mRotScale); force_maxLODfactor=mInputDevice->isKeyDown(Ogre::KC_F2); if(mInputDevice->isKeyDown(Ogre::KC_RIGHT)) mCamera->yaw(-mRotScale); 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->isKeyDown(Ogre::KC_ESCAPE)) { //delete myTrees; return false; } if( mInputDevice->getMouseButton( 1 ) ) { mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13; mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13; } else { mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13); mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13); } char cadena[256]; sprintf(cadena,"Distance: %d",distance); mInfo->setCaption(cadena); sprintf(cadena,"LOD factor: %f",lodfactor); mInfo2->setCaption(cadena); mCamera->yaw(mRotX); mCamera->pitch(mRotY); mCamera->moveRelative(mTranslateVector); return true; } }; class CustomIndexData : public Geometry::IndexData { private: Ogre::Mesh *targetMesh; Ogre::HardwareIndexBufferSharedPtr ibuf; Ogre::RenderOperation mRenderOp; unsigned long* pIdx; public: CustomIndexData(Ogre::Mesh *ogremesh):Geometry::IndexData(){ targetMesh=ogremesh; pIdx=NULL; } virtual ~CustomIndexData(void){} virtual void Begin(unsigned int submeshid, unsigned int indexcount){ targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0); 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; //lodStripsLib->dataRetrievalInterface->GetIndex(k+offset); } virtual void End(){ ibuf->unlock(); } virtual void BorrowIndexData(const Geometry::IndexData *){} }; class LodTreeApplication : public ExampleApplication { protected: public: LodTreeApplication(){} ~LodTreeApplication(){} protected: // Just override the mandatory create scene method void createScene(void) { // mat = new MaterialPtr[1]; theCam = mCamera; theCam->setPosition(0,20,dist_min-40); // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.4, 0.4, 0.4)); theCam->setNearClipDistance(0.1f); // Create a directional light Light* l = mSceneMgr->createLight("MainLight"); l->setType(Light::LT_DIRECTIONAL); l->setDirection(0.0,-1.0,0.0); // Define a floor plane mesh Plane plane( Vector3::UNIT_Y, 0 ); MeshManager::getSingleton().createPlane("ground", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane, 1500,1500,20,20,true,1,5,5,Vector3::UNIT_Z); Entity* suelo = mSceneMgr->createEntity( "GroundEntity", "ground" ); mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(suelo); suelo->setMaterialName("Examples/GrassFloor"); suelo->setCastShadows(false); mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox"); // My node to which all objects will be attached SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); std::string model_file=model_name; model_file.append(".mesh"); //Models entity = mSceneMgr->createEntity(model_name, "../../../OgreStuff/media/GT/ML11.mesh"); ogreMesh = entity->getMesh().getPointer(); // load LOD info from the object meshloader=new Geometry::GeoMeshLoader; Geometry::Mesh *themesh = meshloader->load("../../../OgreStuff/media/GT/ML11.mesh"); if (!meshloader->GetLodStripsData()) OGRE_EXCEPT(1, "The loaded mesh does not contain LOD info for the trunk","LOD Demo"); if (!meshloader->GetTreeSimpSeq()) OGRE_EXCEPT(1, "The loaded mesh does not contain LOD info for the foliage","LOD Demo"); myTrees = new Geometry::LodTreeLibrary( meshloader->GetLodStripsData(), meshloader->GetTreeSimpSeq(), themesh, new CustomIndexData(ogreMesh)); entity->setNormaliseNormals(true); for (int submesh=0; submesh < ogreMesh->getNumSubMeshes(); submesh++) { bool istrunk = myTrees->GetLeavesSubMesh()!=submesh; if (istrunk) entity->getSubEntity(submesh)->setMaterialName("Examples/ML11/trunk"); else entity->getSubEntity(submesh)->setMaterialName("Examples/ML11/leaf"); } forest_center=Ogre::Vector3(150.0f,0.0f,0.0f); for (int i=1; i<5; i++) // 20 for (int j=1; j<5; j++) // 20 { char newTreeName[16]=""; sprintf(newTreeName,"arbol_%d_%d",i,j); Ogre::SceneNode * auxnode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); Ogre::Entity *auxent = entity->clone(newTreeName); auxnode->attachObject( auxent ); auxnode->scale(4.0f,4.0f,4.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()%38)-19); float randomsepy = (float)((rand()%32)-12); auxnode->translate(i*80.0f+randomsepx,0.0f,-j*80.0f-randomsepx); auxent->setNormaliseNormals(true); } if (!meshloader->GetLodStripsData() || !meshloader->GetTreeSimpSeq()) OGRE_EXCEPT(1, "The loaded mesh does not contain any LOD info","LOD Demo"); // 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(); } void createFrameListener(void) { mFrameListener= new LodTreeFrameListener(mWindow, mCamera); mFrameListener->showDebugOverlay(true); 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 LodTreeApplication 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