#include #include #include #include #include #include "water.h" static const uint32_t SUBMERGED_MASK = 0x0F0; static const uint32_t SURFACE_MASK = 0x00F; static const uint32_t WATER_MASK = 0xF00; Water::Water() : RenderTargetListener() , mWaterNode(nullptr) , mScnMgr(nullptr) , mWindow(nullptr) , mCameraNode(nullptr) , mWaterPlane(Ogre::Vector3::UNIT_Y, 0) , mReflectionPlane(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */) , mReflectionClipPlaneAbove(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */ - 2.0f) , mReflectionClipPlaneBelow(Ogre::Vector3(0.0, -1.0, 0.0), -(0.0f /* water height */ + 2.0)) , mRefractionClipPlaneAbove(Ogre::Vector3(0.0, -1.0, 0.0), -(0.0f /* water height */ + 2.0)) , mRefractionClipPlaneBelow(Ogre::Vector3(0.0, 1.0, 0.0), 0.0f /* water height */ - 2.0) , mAbove(true) { } Water::~Water() { if (mWaterNode) mScnMgr->destroySceneNode(mWaterNode); if(mReflectionTexture) mReflectionTexture->removeAllListeners(); #if 0 if(mRefractionTexture) mRefractionTexture->removeAllListeners(); #endif } void Water::create_cameras() { mReflectionTexture->addListener(this); mReflectionCamera = mScnMgr->createCamera("ReflectionCamera"); mCamera->getParentSceneNode()->attachObject(mReflectionCamera); mReflectionCamera->setAspectRatio(mCamera->getAspectRatio()); mReflectionCamera->setNearClipDistance(mCamera->getNearClipDistance()); mReflectionCamera->setFarClipDistance(mCamera->getFarClipDistance()); mReflectionCamera->enableCustomNearClipPlane(mReflectionClipPlaneAbove); mReflectionCamera->enableReflection(mReflectionPlane); Ogre::Viewport * reflectionViewport = mReflectionTexture->addViewport(mReflectionCamera, 0, 0, 0, 0.5f, 1.0f); reflectionViewport->setClearEveryFrame(true); reflectionViewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 1.0, 1.0)); reflectionViewport->setOverlaysEnabled(false); reflectionViewport->setSkiesEnabled(true); reflectionViewport->setAutoUpdated(false); mViewports.push_back(reflectionViewport); // mRefractionTexture->addListener(this); #if 1 mRefractionCamera = mScnMgr->createCamera("RefractionCamera"); mCamera->getParentSceneNode()->attachObject(mRefractionCamera); mRefractionCamera->setAspectRatio(mCamera->getAspectRatio()); mRefractionCamera->setNearClipDistance(mCamera->getNearClipDistance()); mRefractionCamera->setFarClipDistance(mCamera->getFarClipDistance()); mRefractionCamera->enableCustomNearClipPlane(mRefractionClipPlaneAbove); Ogre::Viewport * refractionViewport = mReflectionTexture->addViewport(mRefractionCamera, 1, 0.5, 0, 0.5f, 1.0f); refractionViewport->setClearEveryFrame(true); refractionViewport->setBackgroundColour(Ogre::ColourValue(0.0, 0.5, 1.0, 1.0)); refractionViewport->setOverlaysEnabled(false); refractionViewport->setSkiesEnabled(false); refractionViewport->setAutoUpdated(false); mViewports.push_back(refractionViewport); #endif } void Water::create_textures() { Ogre::TexturePtr reflectionTexture = Ogre::TextureManager::getSingleton().createManual( "ReflectionRefractionTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET); mReflectionTexture = reflectionTexture->getBuffer()->getRenderTarget(); mReflectionTexture->setAutoUpdated(false); #if 0 Ogre::TexturePtr refractionTexture = Ogre::TextureManager::getSingleton().createManual( "RefractionTexture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET); mRefractionTexture = refractionTexture->getBuffer()->getRenderTarget(); #endif } void Water::init() { int i; float w = 1000.0f; // mWindow->addListener(this); create_cameras(); Ogre::MeshPtr water_plane = Ogre::MeshManager::getSingleton().createPlane( "water", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, w, w, 100, 100, true, 1, 100, 100, Ogre::Vector3::UNIT_Z); if (!Ogre::MeshLodGenerator::getSingletonPtr()) new Ogre::MeshLodGenerator(); Ogre::LodConfig lod_config(water_plane); lod_config.createGeneratedLodLevel(w, 0.5f); lod_config.createGeneratedLodLevel(w * 2.0, 0.25f); Ogre::MeshLodGenerator::getSingleton().generateLodLevels(lod_config); Ogre::Vector3 positions[] = { { 0, 0, 0 }, { 0, 0, -1 }, { 0, 0, 1 }, { -1, 0, 0 }, { 1, 0, 0 }, { -1, 0, -1 }, { -1, 0, 1 }, { 1, 0, -1 }, { 1, 0, 1 } }; mWaterNode = mScnMgr->getRootSceneNode()->createChildSceneNode("Water"); auto mat = Ogre::MaterialManager::getSingleton().getByName("Water/Above"); mat->load(); mat->setReceiveShadows(false); #if 0 mat->getTechnique(0) ->getPass(0) ->getTextureUnitState(0) ->setProjectiveTexturing(true, mCamera); #endif auto mat2 = Ogre::MaterialManager::getSingleton().getByName("Water/Below"); mat2->load(); mat2->setReceiveShadows(false); #if 0 mat2->getTechnique(0) ->getPass(0) ->getTextureUnitState(0) ->setProjectiveTexturing(true, mCamera); #endif for (i = 0; i < (int)sizeof(positions) / (int)sizeof(positions[0]); i++) { Ogre::Entity *water_lod1 = mScnMgr->createEntity( "Water" + Ogre::StringConverter::toString(i), "water"); water_lod1->setVisibilityFlags(WATER_MASK); water_lod1->setCastShadows(true); water_lod1->setMaterialName("Water/Above"); water_lod1->setMaterial(mat); Ogre::SceneNode *node_w = mWaterNode->createChildSceneNode( "Water" + Ogre::StringConverter::toString(i), positions[i] * w, Ogre::Quaternion::IDENTITY); node_w->attachObject(water_lod1); water_lod1->setVisibilityFlags(WATER_MASK); mWaterMeshes.push_back(water_lod1); } /* Ogre::Root::getSingleton().addFrameListener(this); */ } void Water::createWater(Ogre::RenderWindow * window, Ogre::Camera *camera) { int i; mCamera = camera; mScnMgr = camera->getSceneManager(); mCameraNode = camera->getParentSceneNode(); Ogre::Viewport *viewport = camera->getViewport(); mWindow = window; mCameraPosition = mCameraNode->getPosition(); create_textures(); } void Water::updateWater(float delta) { int i; if (mCameraPosition.squaredDistance(mCameraNode->getPosition()) > 200.0f * 200.0f) { mCameraPosition = mCameraNode->getPosition(); Ogre::Vector3 waterPosition = mCameraPosition; waterPosition.y = 0; mWaterNode->setPosition(waterPosition); } if (mAbove) { if (mCameraNode->getPosition().y < 0) { mAbove = false; for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setMaterialName("Water/Below"); } } else { if (mCameraNode->getPosition().y > 0) { mAbove = true; for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setMaterialName("Water/Above"); } } for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setVisible(false); for (i = 0; i < mViewports.size(); i++) mViewports[i]->update(); // mReflectionTexture->update(); for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setVisible(true); } /* bool Water::frameEnded(const Ogre::FrameEvent &evt) { updateWater(evt.timeSinceLastFrame); return true; } bool Water::frameRenderingQueued(const Ogre::FrameEvent &evt) { return FrameListener::frameRenderingQueued(evt); } */ void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { int i; if (evt.source == mReflectionTexture /*|| evt.source == mRefractionTexture */) { for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setVisible(false); if (evt.source == mReflectionTexture) mInRefTexUpdate = true; } else { for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setVisible(true); mInRefTexUpdate = false; } } void Water::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { int i; for (i = 0; i < mWaterMeshes.size(); i++) mWaterMeshes[i]->setVisible(true); mInRefTexUpdate = false; } void Water::add_submerged_entity(Ogre::Entity *ent) { ent->setVisibilityFlags(SUBMERGED_MASK); } void Water::add_surface_entity(Ogre::Entity *ent) { ent->setVisibilityFlags(SURFACE_MASK); } void Water::dump_textures() { mReflectionTexture->writeContentsToFile("Reflection.png"); // mRefractionTexture->writeContentsToFile("Refraction.png"); }