/* ========================================================================== * (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 "OgreLodStripsLibrary.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 = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, // type of index indices_to_render, // number of indexes Ogre::HardwareBuffer::HBU_DISCARDABLE , // usage false); // no shadow buffer mRenderOp.indexData->indexBuffer = ibuf; mRenderOp.indexData->indexStart = 0;//offset; 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; /* if (lodfactor >= 0.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; if (lodfactor < 0.333f) { color.r=0.0; color.g=(lodfactor)*3.0f;//nlod*1.0/(diflods/3); color.b=(0.3f-lodfactor)*3.0f;//(nlod*1.0/(diflods/3)); } else { if (lodfactor<0.666f) { color.r=(lodfactor-0.333f)*3.0f;//(nlod-diflods/3)*1.0/(diflods/3); color.g=1.0; color.b=0.0; } else { color.r=1.0; color.g=(0.3f-lodfactor)*3.0f;//(nlod-(2*diflods/3))*1.0/(diflods/3); color.b=0.0; } } mat[0]->setDiffuse(color); } /* else { if ((distance > dist_max)) { color.r=0.0; color.g=0.0; color.b=1.0; mat[0]->setDiffuse(color); } else { if ((distance < dist_min)) { color.r=1.0; color.g=0.0; color.b=0.0; mat[0]->setDiffuse(color); } } } */ // 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/bunnylod.mesh"); ogreMesh = entity->getMesh().getPointer(); // load LOD info from the object meshloader=new Geometry::GeoMeshLoader; Geometry::Mesh *themesh = meshloader->load("../../../OgreStuff/media/GT/bunnylod.mesh"); node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); node->attachObject( entity ); std::string lod_file="../../media/GT/"; lod_file.append(model_name); lod_file.append(".lod"); // myStrips = new LodStripsLibrary(lod_file,entity->getMesh().getPointer()); 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); // Colour-coded material mat[0] = MaterialManager::getSingleton().create("test_mat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mat[0]->setCullingMode(CULL_ANTICLOCKWISE); mat[0]->setAmbient(ColourValue(0.3f,0.3f,0.3f)); mat[0]->setDiffuse(color); mat[0]->setLightingEnabled(true); entity->setMaterialName("test_mat"); for (int i=-3; i<2; i++) // 20 for (int j=0; j<5; j++) // 20 { char newObjName[16]=""; sprintf(newObjName,"arbol_%d_%d",i,j); Ogre::SceneNode * auxnode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); auxnode->attachObject( entity->clone(newObjName) ); auxnode->scale(0.8f,0.8f,0.8f); float randomsepx = (float)((rand()%18)-9); float randomsepy = (float)((rand()%12)-6); auxnode->translate(i*100.0f+randomsepx,40.0f,-j*100.0f-randomsepx); } 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