#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() : FrameListener() , mWaterNode(nullptr) , mScnMgr(nullptr) , mCameraNode(nullptr) , mWaterPlane(Ogre::Vector3::UNIT_Y, 0) { } Water::~Water() { if (mWaterNode) mScnMgr->destroySceneNode(mWaterNode); } void Water::createWater(Ogre::Camera *camera) { int i; float w = 1000; mCamera = camera; mScnMgr = camera->getSceneManager(); mCameraNode = camera->getParentSceneNode(); Ogre::Viewport *viewport = camera->getViewport(); mCameraPosition = mCameraNode->getPosition(); auto compositor = Ogre::CompositorManager::getSingleton().addCompositor( viewport, "Fresnel"); Ogre::CompositorManager::getSingleton().setCompositorEnabled( viewport, "Fresnel", true); // toggle reflection in camera compositor->getRenderTarget("reflection")->addListener(this); 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, -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"); Ogre::Entity *water = mScnMgr->createEntity("WaterR", "water"); water->setVisibilityFlags(WATER_MASK); water->setCastShadows(true); auto mat = Ogre::MaterialManager::getSingleton().getByName("Water"); mat->setReceiveShadows(false); mat->getTechnique(0) ->getPass(0) ->getTextureUnitState(0) ->setProjectiveTexturing(true, mCamera); water->setMaterial(mat); Ogre::SceneNode *node0 = mWaterNode->createChildSceneNode("WaterR"); node0->attachObject(water); 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->setMaterialName("Water"); 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); } } void Water::updateWater(float delta) { if (mCameraPosition.squaredDistance(mCameraNode->getPosition()) > 100.0f) { mCameraPosition = mCameraNode->getPosition(); Ogre::Vector3 waterPosition = mCameraPosition; waterPosition.y = 0; mWaterNode->setPosition(waterPosition); } } 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) { mCamera->enableReflection(mWaterPlane); } void Water::postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) { mCamera->disableReflection(); } void Water::add_submerged_entity(Ogre::Entity *ent) { ent->setVisibilityFlags(SUBMERGED_MASK); } void Water::add_surface_entity(Ogre::Entity *ent) { ent->setVisibilityFlags(SURFACE_MASK); }