Fixed water body presence physics
This commit is contained in:
2
Game.cpp
2
Game.cpp
@@ -620,6 +620,8 @@ public:
|
||||
void updateWorld(float delta)
|
||||
{
|
||||
mDynWorld->getBtWorld()->stepSimulation(delta, 4);
|
||||
mDbgDraw->update();
|
||||
|
||||
ECS::update(delta);
|
||||
}
|
||||
void updateWater(float delta)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <OgreBullet.h>
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "WaterModule.h"
|
||||
#include "Components.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -191,7 +192,19 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
bool is_on_floor = false;
|
||||
bool penetration = false;
|
||||
Ogre::Vector3 gravity(0, -9.8, 0);
|
||||
body.gvelocity += gravity * delta;
|
||||
if (e.has<InWater>()) {
|
||||
float full_subm = 2.0f;
|
||||
float current_subm = -Ogre::Math::Clamp(
|
||||
pos.y, -full_subm, 0.0f);
|
||||
float b = 9.0 * current_subm / full_subm;
|
||||
body.gvelocity +=
|
||||
(gravity + Ogre::Vector3(0, b, 0)) *
|
||||
delta;
|
||||
body.gvelocity.y = Ogre::Math::Clamp(
|
||||
body.gvelocity.y, -1.0f, 1.0f);
|
||||
std::cout << "InWater!!!!!!!\n";
|
||||
} else
|
||||
body.gvelocity += gravity * delta;
|
||||
velocity += body.gvelocity;
|
||||
Ogre::Vector3 rotMotion = velocity * delta;
|
||||
btVector3 currentPosition =
|
||||
@@ -293,9 +306,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
inertia);
|
||||
}
|
||||
body.mGhostObject->setCollisionFlags(
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT |
|
||||
btCollisionObject::
|
||||
CF_NO_CONTACT_RESPONSE);
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT /*|
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE */);
|
||||
body.mGhostObject->setActivationState(
|
||||
DISABLE_DEACTIVATION);
|
||||
eng.mWorld->attachCollisionObject(
|
||||
@@ -459,6 +471,48 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
body.checkGround = false;
|
||||
}
|
||||
});
|
||||
ecs.system<const WaterBody, const CharacterBase, CharacterBody>(
|
||||
"CharacterWater1")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<Character>()
|
||||
.without<InWater>()
|
||||
.each([](flecs::entity e, const WaterBody &waterb,
|
||||
const CharacterBase &ch, CharacterBody &body) {
|
||||
if (waterb.mInWater.find(body.mGhostObject) !=
|
||||
waterb.mInWater.end() &&
|
||||
ch.mBodyNode->_getDerivedPosition().y < -0.05f) {
|
||||
e.add<InWater>();
|
||||
std::cout << "Big Splash\n";
|
||||
}
|
||||
#if 0
|
||||
if (waterb.mInWater.find(body.mGhostObject) ==
|
||||
waterb.mInWater.end())
|
||||
e.add<InWater>();
|
||||
std::cout << waterb.mInWater.size() << " InWater\n";
|
||||
#endif
|
||||
});
|
||||
ecs.system<const WaterBody, const CharacterBase, CharacterBody>(
|
||||
"CharacterWater2")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<Character>()
|
||||
.with<InWater>()
|
||||
.each([](flecs::entity e, const WaterBody &waterb,
|
||||
const CharacterBase &ch, CharacterBody &body) {
|
||||
if (waterb.mInWater.find(body.mGhostObject) ==
|
||||
waterb.mInWater.end() &&
|
||||
ch.mBodyNode->_getDerivedPosition().y > 0.05f)
|
||||
e.remove<InWater>();
|
||||
});
|
||||
ecs.system<const EngineData, CharacterBase, CharacterBody>(
|
||||
"DisplayPlayerPos")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<Character>()
|
||||
.with<Player>()
|
||||
.each([](const EngineData &eng, CharacterBase &ch,
|
||||
CharacterBody &body) {
|
||||
std::cout << "player: " << ch.mBodyNode->getPosition()
|
||||
<< "\n";
|
||||
});
|
||||
}
|
||||
|
||||
void CharacterModule::setAnimation(AnimationControl &anim)
|
||||
|
||||
@@ -46,5 +46,6 @@ struct Camera {
|
||||
Ogre::SceneNode *mCameraGoal;
|
||||
Ogre::Real mPivotPitch;
|
||||
};
|
||||
struct InWater {};
|
||||
}
|
||||
#endif
|
||||
@@ -15,6 +15,7 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
ecs.component<GameData>().add(flecs::Singleton);
|
||||
ecs.component<Input>().add(flecs::Singleton);
|
||||
ecs.component<Camera>().add(flecs::Singleton);
|
||||
ecs.component<InWater>();
|
||||
ecs.set<EngineData>({ scnMgr, world, 0.0f });
|
||||
ecs.set<Camera>({ cameraNode, camera, false });
|
||||
ecs.add<GameData>();
|
||||
@@ -24,8 +25,8 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
.each([](EngineData &eng) {
|
||||
eng.delta = ECS::get().delta_time();
|
||||
});
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <WaterModule>();
|
||||
ecs.import <CharacterModule>();
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -25,7 +25,11 @@ struct WaterSurface {
|
||||
Ogre::Viewport *mViewports[2];
|
||||
};
|
||||
struct WaterBody {
|
||||
btGhostObject *mWaterBody;
|
||||
btPairCachingGhostObject *mWaterBody;
|
||||
std::set<btCollisionObject *> mInWater;
|
||||
std::unordered_map<btCollisionObject *, float> mSurface;
|
||||
btManifoldArray mManifoldArray;
|
||||
btVector3 mShapeAabbMin, mShapeAabbMax;
|
||||
};
|
||||
struct WaterModule {
|
||||
WaterModule(flecs::world &ecs);
|
||||
|
||||
Reference in New Issue
Block a user