Files
ogre-prototype/water/water.cpp
2025-06-26 04:51:35 +03:00

126 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 = 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);
}