123 lines
3.6 KiB
C++
123 lines
3.6 KiB
C++
#include <Ogre.h>
|
|
#include <OgreMeshLodGenerator.h>
|
|
#include <OgreCompositorManager.h>
|
|
#include <OgreMaterialManager.h>
|
|
#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 = 400;
|
|
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);
|
|
auto mat = Ogre::MaterialManager::getSingleton().getByName("Water");
|
|
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");
|
|
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);
|
|
}
|