Fixed water body presence physics

This commit is contained in:
2025-09-03 22:16:53 +03:00
parent aca04ff621
commit 1c56387c35
6 changed files with 249 additions and 18 deletions

View File

@@ -1,3 +1,4 @@
#include <iostream>
#include <Ogre.h>
#include <OgreColourValue.h>
#include <OgreShaderSubRenderState.h>
@@ -164,12 +165,23 @@ WaterModule::WaterModule(flecs::world &ecs)
texture_unit->setTextureFiltering(
Ogre::FT_MIP, Ogre::FO_LINEAR);
#if 0
bool success =
Ogre::RTShader::ShaderGenerator::getSingletonPtr()
->createShaderBasedTechnique(
*mat,
Ogre::MSN_DEFAULT,
Ogre::MSN_SHADERGEN);
OgreAssert(
success,
"createShaderBasedTechnique");
Ogre::RTShader::RenderState *renderState =
Ogre::RTShader::ShaderGenerator::
getSingletonPtr()
->createOrRetrieveRenderState(
Ogre::MSN_SHADERGEN)
.first;
->getRenderState(
Ogre::MSN_SHADERGEN,
*mat,
0);
Ogre::RTShader::SubRenderState *perPixelLightModel =
Ogre::RTShader::ShaderGenerator::getSingletonPtr()
->createSubRenderState(
@@ -283,26 +295,183 @@ WaterModule::WaterModule(flecs::world &ecs)
ecs.system<const EngineData, const WaterSurface, WaterBody>(
"UpdateWaterBody")
.kind(flecs::OnUpdate)
.each([](const EngineData &eng, const WaterSurface &water,
WaterBody &body) {
.each([this](const EngineData &eng, const WaterSurface &water,
WaterBody &body) {
int i;
if (!body.mWaterBody) {
body.mWaterBody = new btGhostObject;
btBoxShape *boxShape = new btBoxShape(
btVector3(1000, 1000, 1000));
btCompoundShape *shape = new btCompoundShape;
shape->addChildShape(
btTransform(btQuaternion(),
btVector3(0, -1000, 0)),
boxShape);
btBoxShape *boxShape1 = new btBoxShape(
btVector3(1000, 20, 1000));
btBoxShape *boxShape2 = new btBoxShape(
btVector3(1000, 100, 1000));
btBoxShape *boxShape3 = new btBoxShape(
btVector3(1000, 1000, 1000));
btTransform boxShapeXform1(btQuaternion(),
btVector3(0, -20.2f,
0));
btTransform boxShapeXform2(btQuaternion(),
btVector3(0, -120.2f,
0));
btTransform boxShapeXform3(
btQuaternion(),
btVector3(0, -1120.2f, 0));
shape->addChildShape(boxShapeXform1, boxShape1);
shape->addChildShape(boxShapeXform2, boxShape2);
shape->addChildShape(boxShapeXform3, boxShape3);
body.mWaterBody = new btPairCachingGhostObject;
body.mWaterBody->setCollisionShape(shape);
body.mWaterBody->setCollisionFlags(
body.mWaterBody->getCollisionFlags() |
btCollisionObject::CF_NO_CONTACT_RESPONSE |
btCollisionObject::CF_STATIC_OBJECT);
body.mWaterBody->setActivationState(
DISABLE_DEACTIVATION);
body.mWaterBody->getWorldTransform().setOrigin(
btVector3(0, 0, 0));
eng.mWorld->attachCollisionObject(
body.mWaterBody, water.mWaterEnt, 16,
0x7fffffff & ~2);
}
Ogre::Vector3 waterPos =
water.mWaterNode->_getDerivedPosition();
Ogre::Vector3 waterBodyPos = Ogre::Bullet::convert(
body.mWaterBody->getWorldTransform()
.getOrigin());
waterPos.y = 0;
waterBodyPos.y = 0;
Ogre::Vector3 d = waterPos - waterBodyPos;
d.y = 0;
std::cout << "aabb: "
<< Ogre::Bullet::convert(body.mShapeAabbMin)
<< " "
<< Ogre::Bullet::convert(body.mShapeAabbMax)
<< "\n";
// Ogre::Vector3 waterPosition = mCameraPos;
// mWaterNode->setPosition(waterPosition);
if (d.squaredLength() > 10.0f * 10.0f)
body.mWaterBody->getWorldTransform().setOrigin(
Ogre::Bullet::convert(waterBodyPos +
d));
std::cout
<< "node: " << water.mWaterNode->getPosition()
<< " body: "
<< Ogre::Bullet::convert(
body.mWaterBody->getWorldTransform()
.getOrigin())
<< "\n";
btCompoundShape *mshape =
static_cast<btCompoundShape *>(
body.mWaterBody->getCollisionShape());
body.mShapeAabbMin =
body.mWaterBody->getWorldTransform()
.getOrigin() +
btVector3(-1000, -1000, -1000);
body.mShapeAabbMax =
body.mWaterBody->getWorldTransform()
.getOrigin() +
btVector3(1000, -0.2, 1000);
#if 0
mshape->getChildShape(0)->getAabb(
body.mWaterBody->getWorldTransform() *
mshape->getChildTransform(0),
body.mShapeAabbMin, body.mShapeAabbMax);
#endif
btDispatcher *dispatch =
eng.mWorld->getBtWorld()->getDispatcher();
eng.mWorld->getBtWorld()->getBroadphase()->setAabb(
body.mWaterBody->getBroadphaseHandle(),
body.mShapeAabbMin, body.mShapeAabbMax,
eng.mWorld->getBtWorld()->getDispatcher());
dispatch->dispatchAllCollisionPairs(
body.mWaterBody->getOverlappingPairCache(),
eng.mWorld->getBtWorld()->getDispatchInfo(),
dispatch);
btBroadphasePairArray &collisionPairs =
body.mWaterBody->getOverlappingPairCache()
->getOverlappingPairArray();
std::set<btCollisionObject *> currentOverlaps;
std::set<btCollisionObject *>::iterator it;
const int numObjects = collisionPairs.size();
for (int i = 0; i < numObjects; i++) {
body.mManifoldArray.resize(0);
const btBroadphasePair &collisionPair =
collisionPairs[i];
if (collisionPair.m_algorithm)
collisionPair.m_algorithm
->getAllContactManifolds(
body.mManifoldArray);
for (int j = 0; j < body.mManifoldArray.size();
j++) {
btPersistentManifold *manifold =
body.mManifoldArray[j];
if (manifold->getNumContacts() == 0)
continue;
const btCollisionObject *obj =
(manifold->getBody0() ==
body.mWaterBody) ?
manifold->getBody1() :
manifold->getBody0();
btCollisionObject *nobj =
const_cast<btCollisionObject *>(
obj);
if (obj->getCollisionFlags() &
btCollisionObject::CF_STATIC_OBJECT)
continue;
bool ok = false;
Ogre::Vector3 contactPosA, contactPosB;
float minDist = 0.0f;
for (int p = 0;
p < manifold->getNumContacts();
p++) {
const btManifoldPoint &pt =
manifold->getContactPoint(
p);
float dist = pt.getDistance();
if (dist < minDist) {
minDist = dist;
std::cout
<< " distance: "
<< dist << "\n";
contactPosA = Ogre::Bullet::convert(
pt.getPositionWorldOnA());
contactPosB = Ogre::Bullet::convert(
pt.getPositionWorldOnB());
std::cout
<< "positionA: "
<< contactPosA
<< "\n";
std::cout
<< "positionB: "
<< contactPosA
<< "\n";
ok = true;
}
}
if (ok) {
currentOverlaps.insert(nobj);
if (body.mInWater.find(nobj) ==
body.mInWater.end()) {
/* new body */
body.mInWater.insert(
nobj);
/* calculate proj surface */
body.mSurface[nobj] =
100.0f;
}
}
}
}
for (it = body.mInWater.begin();
it != body.mInWater.end();) {
btCollisionObject *obj = *it;
if (currentOverlaps.find(obj) ==
currentOverlaps.end()) {
/* remove body */
it = body.mInWater.erase(it);
body.mSurface.erase(obj);
} else
it++;
}
});
}
void WaterSurface::RenderTextureListener::preRenderTargetUpdate(