/* ========================================================================== * (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 "GeoLodStripsLibrary.h" #include "GeoMeshLoader.h" // Distance values #define dist_min 1200 #define dist_max 2000 // Model name #define model_name "dwarf2" //Global variables Entity* entity; Geometry::LodStripsLibrary* myStrips; Ogre::Mesh *ogreMesh=NULL; Geometry::GeoMeshLoader *meshloader=NULL; SceneNode* node; MaterialPtr *mat; ColourValue color=ColourValue::Red; Camera* theCam; Entity* pPlaneEnt; std::vector belowWaterEnts; std::vector aboveWaterEnts; Plane reflectionPlane; OverlayElement* mInfo; OverlayElement* mInfo2; class RefractionTextureListener : public RenderTargetListener { public: void preRenderTargetUpdate(const RenderTargetEvent& evt) { // Hide plane and objects above the water pPlaneEnt->setVisible(false); std::vector::iterator i, iend; iend = aboveWaterEnts.end(); for (i = aboveWaterEnts.begin(); i != iend; ++i) { (*i)->setVisible(false); } } void postRenderTargetUpdate(const RenderTargetEvent& evt) { // Show plane and objects above the water pPlaneEnt->setVisible(true); std::vector::iterator i, iend; iend = aboveWaterEnts.end(); for (i = aboveWaterEnts.begin(); i != iend; ++i) { (*i)->setVisible(true); } } }; class ReflectionTextureListener : public RenderTargetListener { public: void preRenderTargetUpdate(const RenderTargetEvent& evt) { // Hide plane and objects below the water pPlaneEnt->setVisible(false); std::vector::iterator i, iend; iend = belowWaterEnts.end(); for (i = belowWaterEnts.begin(); i != iend; ++i) { (*i)->setVisible(false); } theCam->enableReflection(reflectionPlane); } void postRenderTargetUpdate(const RenderTargetEvent& evt) { // Show plane and objects below the water pPlaneEnt->setVisible(true); std::vector::iterator i, iend; iend = belowWaterEnts.end(); for (i = belowWaterEnts.begin(); i != iend; ++i) { (*i)->setVisible(true); } theCam->disableReflection(); } }; void DumpDataToOgreBuffers(Ogre::Mesh *original_mesh, Geometry::LodStripsLibrary *lodStripsLib) { // Copy to Ogre buffers including the degenerated triangles Ogre::HardwareIndexBufferSharedPtr ibuf; Ogre::IndexData *indexes; Ogre::RenderOperation mRenderOp; for (int submesh=0; submesh < original_mesh->getNumSubMeshes(); submesh++) { int indices_to_render = lodStripsLib->GetValidIndexCount(submesh); int offset = lodStripsLib->GetValidOffset(submesh); original_mesh->getSubMesh(submesh)->_getRenderOperation(mRenderOp,0); ibuf = mRenderOp.indexData->indexBuffer; mRenderOp.indexData->indexStart = 0; mRenderOp.indexData->indexCount = indices_to_render; unsigned long* pIdx = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); for (int k=0; kdataRetrievalInterface->GetIndex(k+offset); ibuf->unlock(); } } class FresnelFrameListener : public ExampleFrameListener { int manage; public: FresnelFrameListener(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 = node->getPosition() - 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; static float lodfactorBefore = -1.0f; if (fabsf(lodfactorBefore-lodfactor)>0.05f || (lodfactorBefore>0.0f && lodfactor==0.0f) || (lodfactorBefore<1.0f && lodfactor==1.0f)) { myStrips->GoToLod(lodfactor); DumpDataToOgreBuffers(ogreMesh,myStrips); lodfactorBefore=lodfactor; } // Move the node if(mInputDevice->isKeyDown(Ogre::KC_UP)) mTranslateVector.z = -mMoveScale; if(mInputDevice->isKeyDown(Ogre::KC_DOWN)) mTranslateVector.z = mMoveScale; // Instead of moving the ship left and right, rotate it using yaw() if(mInputDevice->isKeyDown(Ogre::KC_LEFT)) mCamera->yaw(mRotScale); if(mInputDevice->isKeyDown(Ogre::KC_RIGHT)) mCamera->yaw(-mRotScale); // Move the node if(mInputDevice->isKeyDown(Ogre::KC_W)) node->translate(0,mMoveScale,0); if(mInputDevice->isKeyDown(Ogre::KC_S)) node->translate(0,-mMoveScale,0); if(mInputDevice->isKeyDown(Ogre::KC_Z)) node->scale(1.01,1.01,1.01); if(mInputDevice->isKeyDown(Ogre::KC_X)) node->scale(0.99,0.99,0.99); // Rotate if(mInputDevice->isKeyDown(Ogre::KC_A)) node->yaw(mRotScale); if(mInputDevice->isKeyDown(Ogre::KC_D)) node->yaw(-mRotScale); if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE)) { delete myStrips; delete [] mat; 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 FresnelApplication : public ExampleApplication { protected: RefractionTextureListener mRefractionListener; ReflectionTextureListener mReflectionListener; public: FresnelApplication() { } ~FresnelApplication() { } protected: // Just override the mandatory create scene method void createScene(void) { Entity* pEnt; mat = new MaterialPtr[1]; // Check prerequisites first const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM))) { OGRE_EXCEPT(1, "Your card does not support vertex and fragment programs, so cannot " "run this demo. Sorry!", "Fresnel::createScene"); } else { if (!GpuProgramManager::getSingleton().isSyntaxSupported("arbfp1") && !GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0") && !GpuProgramManager::getSingleton().isSyntaxSupported("ps_1_4") ) { OGRE_EXCEPT(1, "Your card does not support advanced fragment programs, " "so cannot run this demo. Sorry!", "Fresnel::createScene"); } } theCam = mCamera; theCam->setPosition(0,20,dist_min-600.0f); // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3)); // Create a point light Light* l = mSceneMgr->createLight("MainLight"); l->setType(Light::LT_DIRECTIONAL); l->setDirection(0.0,0.0,-1.0); RenderTexture* rttTex = mRoot->getRenderSystem()->createRenderTexture( "Refraction", 512, 512 ); { Viewport *v = rttTex->addViewport( mCamera ); MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction"); mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName("Refraction"); v->setOverlaysEnabled(false); rttTex->addListener(&mRefractionListener); } rttTex = mRoot->getRenderSystem()->createRenderTexture( "Reflection", 512, 512 ); { Viewport *v = rttTex->addViewport( mCamera ); MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction"); mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection"); v->setOverlaysEnabled(false); rttTex->addListener(&mReflectionListener); } // Define a floor plane mesh reflectionPlane.normal = Vector3::UNIT_Y; reflectionPlane.d = 0; MeshManager::getSingleton().createPlane("ReflectPlane", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, reflectionPlane, 9000,9000,10,10,true,1,5,5,Vector3::UNIT_Z); pPlaneEnt = mSceneMgr->createEntity( "plane", "ReflectPlane" ); pPlaneEnt->setMaterialName("Examples/FresnelReflectionRefraction"); mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt); mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox"); // My node to which all objects will be attached SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); // Now the below water ents pEnt = mSceneMgr->createEntity( "PoolFloor", "PoolFloor.mesh" ); myRootNode->attachObject(pEnt); belowWaterEnts.push_back(pEnt); myRootNode->scale(6.0,6.0,6.0); std::string model_file=model_name; model_file.append(".mesh"); //Models entity = mSceneMgr->createEntity(model_name, "../../../OgreStuff/media/GT/ogrolod.mesh"); ogreMesh = entity->getMesh().getPointer(); // load LOD info from the object meshloader=new Geometry::GeoMeshLoader; Geometry::Mesh *themesh = meshloader->load("../../../OgreStuff/media/GT/ogrolod.mesh"); node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); node->attachObject( entity ); std::string lod_file="../../media/GT/"; lod_file.append(model_name); lod_file.append(".lod"); if (!meshloader->GetLodStripsData()) OGRE_EXCEPT(1, "The loaded mesh does not contain any LOD info","LOD Demo"); myStrips = new Geometry::LodStripsLibrary(meshloader->GetLodStripsData(),themesh); entity->setNormaliseNormals(true); aboveWaterEnts.push_back(entity); entity->setMaterialName("LODStripsDemo/Ogro"); for (int i=-3; i<7; i++) // 7 for (int j=0; j<4; j++) // 4 { char newObjName[16]=""; sprintf(newObjName,"arbol_%d_%d",i,j); Ogre::SceneNode * auxnode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); Ogre::Entity *auxen = entity->clone(newObjName); auxnode->attachObject(auxen); 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*70.0f+randomsepx,-1.0f,-j*70.0f-randomsepx); auxen->setNormaliseNormals(true); } node->translate(0,0,-500.0f); // 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"); pOver->show(); } void createFrameListener(void) { mFrameListener= new FresnelFrameListener(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 FresnelApplication 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