Water works!

This commit is contained in:
2025-09-15 01:51:38 +03:00
parent 4d0fb8f60f
commit 5c03f0cd2c
18 changed files with 2435 additions and 1501 deletions

View File

@@ -4,28 +4,31 @@
#include "GameData.h"
#include "CharacterModule.h"
#include "WaterModule.h"
#include "TerrainModule.h"
#include "Components.h"
namespace ECS
{
CharacterModule::CharacterModule(flecs::world &ecs)
{
ecs.module<CharacterModule>();
player = ecs.entity("player");
player.set<AnimationControl>({ AnimationControl::ANIM_NONE,
AnimationControl::ANIM_NONE, false,
false });
player.set<CharacterBase>(
{ "normal-male.glb", 0.0f, nullptr, nullptr, nullptr });
player.set<CharacterBody>(
{ nullptr, nullptr, nullptr, { 0, 0, 0 }, false, false });
player.add<Character>();
player.add<Player>();
ecs.component<Character>();
ecs.component<Player>();
ecs.component<CharacterBase>();
ecs.component<CharacterVelocity>();
ecs.component<CharacterBody>().on_add(
[](flecs::entity e, CharacterBody &body) {
e.set<CharacterVelocity>(
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
body.checkGround = false;
body.checkGroundResult = false;
body.mCollisionShape = nullptr;
body.mGhostObject = nullptr;
body.mController = nullptr;
});
ecs.system<EngineData, CharacterBase>("UpdateTimer")
.kind(flecs::OnUpdate)
.each([this](EngineData &eng, CharacterBase &ch) {
ch.mTimer += eng.delta;
if (eng.startupDelay >= 0.0f)
eng.startupDelay -= eng.delta;
});
ecs.system<Input, Camera>("HandleInput")
.kind(flecs::OnUpdate)
@@ -38,6 +41,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
uint32_t active = input.control;
float zaxis = input.motion.z;
zaxis *= 0.9f;
if (!camera.mCameraPivot || !camera.mCameraGoal)
return;
if (pressed & 1)
std::cout << "W pressed\n";
if (released & 1)
@@ -181,25 +186,15 @@ CharacterModule::CharacterModule(flecs::world &ecs)
return;
ch.mBoneMotion = ch.mRootBone->getPosition();
});
ecs.system<const EngineData, CharacterBase, CharacterBody,
AnimationControl>("HandleRootMotion")
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleGravity")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.each([this](flecs::entity e, const EngineData &eng,
CharacterBase &ch, CharacterBody &body,
AnimationControl &anim) {
float delta = e.world().delta_time();
if (!ch.mBodyNode)
return;
Ogre::Quaternion rot = ch.mBodyNode->getOrientation();
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
Ogre::Vector3 boneMotion = ch.mBoneMotion;
Ogre::Vector3 velocity = rot * boneMotion / delta;
OgreAssert(delta > 0.0f, "Zero delta");
int maxPen = 0;
Ogre::Vector3 colNormal;
bool is_on_floor = false;
bool penetration = false;
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
if (e.has<InWater>()) {
float volume = 2.0f * 0.5f * 0.5f;
float density = 900.0f;
@@ -216,33 +211,80 @@ CharacterModule::CharacterModule(flecs::world &ecs)
Ogre::Vector3 b = -gravity * density * volume *
multiplier * current_subm /
full_subm / mass;
body.gvelocity += (gravity + b) * delta;
body.gvelocity.y = Ogre::Math::Clamp(
body.gvelocity.y, -2.5f, 2.5f);
} else
body.gvelocity += gravity * delta;
gr.gvelocity += (gravity + b) * eng.delta;
gr.gvelocity.y = Ogre::Math::Clamp(
gr.gvelocity.y, -2.5f, 2.5f);
} else {
gr.gvelocity += gravity * eng.delta;
if (pos.y < -1.2) {
gr.gvelocity.y = 0.0f;
}
}
gr.gvelocity *= 0.99;
});
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleRootMotionVelocity")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &v) {
if (eng.delta < 0.0000001f)
return;
if (!ch.mBodyNode)
return;
Ogre::Quaternion rot = ch.mBodyNode->getOrientation();
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
Ogre::Vector3 boneMotion = ch.mBoneMotion;
v.velocity = rot * boneMotion / eng.delta;
if (eng.startupDelay < 0.0f)
v.velocity += v.gvelocity;
v.velocity.y = Ogre::Math::Clamp(v.velocity.y, -10.5f,
1000000.0f);
});
ecs.system<const EngineData, CharacterBase, CharacterBody,
AnimationControl, CharacterVelocity>("HandleRootMotion")
.kind(flecs::OnUpdate)
.each([this](flecs::entity e, const EngineData &eng,
CharacterBase &ch, CharacterBody &body,
AnimationControl &anim, CharacterVelocity &v) {
if (!ch.mBodyNode)
return;
if (eng.delta < 0.0000001f)
return;
OgreAssert(eng.delta > 0.0f, "Zero delta");
int maxPen = 0;
Ogre::Vector3 colNormal;
bool is_on_floor = false;
bool penetration = false;
if (eng.startupDelay < 0.0f) {
body.gvelocity *= 0.99;
velocity += body.gvelocity;
Ogre::Vector3 rotMotion = velocity * delta;
btVector3 currentPosition =
body.mGhostObject->getWorldTransform()
.getOrigin();
is_on_floor = body.mController->isOnFloor();
penetration = body.mController->isPenetrating();
if (is_on_floor)
body.gvelocity =
Ogre::Vector3(0.0f, 0.0f, 0.0f);
if (body.mController) {
Ogre::Vector3 rotMotion =
v.velocity * eng.delta;
btVector3 currentPosition =
body.mGhostObject
->getWorldTransform()
.getOrigin();
is_on_floor =
body.mController->isOnFloor();
penetration = body.mController
->isPenetrating();
if (is_on_floor)
v.gvelocity = Ogre::Vector3(
0.0f, 0.0f, 0.0f);
btTransform from(
Ogre::Bullet::convert(
ch.mBodyNode->getOrientation()),
Ogre::Bullet::convert(
ch.mBodyNode->getPosition()));
ch.mBodyNode->setPosition(
ch.mBodyNode->getPosition() +
rotMotion);
ch.mBoneMotion = Ogre::Vector3(0, 0, 0);
btTransform from(
Ogre::Bullet::convert(
ch.mBodyNode
->getOrientation()),
Ogre::Bullet::convert(
ch.mBodyNode
->getPosition()));
ch.mBodyNode->setPosition(
ch.mBodyNode->getPosition() +
rotMotion);
ch.mBoneMotion = Ogre::Vector3(0, 0, 0);
}
}
});
ecs.system<const Input, AnimationControl>("HandlePlayerAnimations")
@@ -289,6 +331,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
.each([](const EngineData &eng, CharacterBase &ch,
CharacterBody &body) {
if (!ch.mBodyNode) {
body.mController = nullptr;
ch.mBodyEnt = eng.mScnMgr->createEntity(
"normal-male.glb");
ch.mBodyNode = eng.mScnMgr->getRootSceneNode()
@@ -297,7 +340,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ch.mSkeleton = ch.mBodyEnt->getSkeleton();
body.mGhostObject =
new btPairCachingGhostObject();
body.mCollisionShape = new btCompoundShape;
body.mCollisionShape =
new btCompoundShape(false);
body.mGhostObject->setCollisionShape(
body.mCollisionShape);
{
@@ -333,16 +377,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
eng.mWorld->attachCollisionObject(
body.mGhostObject, ch.mBodyEnt, 1,
0x7FFFFFFF);
body.mController =
new Ogre::Bullet::KinematicMotionSimple(
body.mGhostObject,
ch.mBodyNode);
OgreAssert(body.mGhostObject,
"Need GhostObject");
OgreAssert(body.mController, "Need controller");
eng.mWorld->getBtWorld()->addAction(
body.mController);
OgreAssert(body.mCollisionShape,
"No collision shape");
OgreAssert(ch.mSkeleton->hasBone("Root"),
@@ -351,11 +387,31 @@ CharacterModule::CharacterModule(flecs::world &ecs)
OgreAssert(ch.mRootBone, "No root bone");
}
});
ecs.system<const EngineData, CharacterBase, CharacterBody>(
"UpdateCharacterPhysics")
.kind(flecs::OnUpdate)
.with<Character>()
.with<TerrainReady>()
.with<WaterReady>()
.each([](const EngineData &eng, CharacterBase &ch,
CharacterBody &body) {
if (ch.mBodyNode && !body.mController &&
eng.startupDelay < 0.0f) {
body.mController =
new Ogre::Bullet::KinematicMotionSimple(
body.mGhostObject,
ch.mBodyNode);
eng.mWorld->getBtWorld()->addAction(
body.mController);
OgreAssert(body.mController, "Need controller");
}
});
#define CAM_HEIGHT 1.6f // height of camera above character's center of mass
ecs.system<const EngineData, Camera, const CharacterBase>(
"UpdateCamera")
.kind(flecs::OnUpdate)
.with<Player>()
.with<GroundCheckReady>()
.each([](const EngineData &eng, Camera &camera,
const CharacterBase &ch) {
float delta = eng.delta;
@@ -475,8 +531,10 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ecs.system<const EngineData, CharacterBody>("CheckGround")
.kind(flecs::OnUpdate)
.with<Character>()
.with<Player>()
.without<GroundCheckReady>()
.each([](const EngineData &eng, CharacterBody &body) {
if (body.checkGround) {
if (body.mGhostObject) {
btVector3 from =
body.mGhostObject->getWorldTransform()
.getOrigin() +
@@ -488,7 +546,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
resultCallback);
body.checkGroundResult =
resultCallback.hasHit();
body.checkGround = false;
if (resultCallback.hasHit())
ECS::get().add<GroundCheckReady>();
}
});
ecs.system<const WaterBody, const CharacterBase, CharacterBody>(
@@ -498,8 +557,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
.without<InWater>()
.each([](flecs::entity e, const WaterBody &waterb,
const CharacterBase &ch, CharacterBody &body) {
if (waterb.mInWater.find(body.mGhostObject) !=
waterb.mInWater.end() &&
if (waterb.isInWater(body.mGhostObject) &&
ch.mBodyNode->_getDerivedPosition().y < -0.05f) {
e.add<InWater>();
std::cout << "Big Splash\n";
@@ -518,8 +576,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
.with<InWater>()
.each([](flecs::entity e, const WaterBody &waterb,
const CharacterBase &ch, CharacterBody &body) {
if (waterb.mInWater.find(body.mGhostObject) ==
waterb.mInWater.end() &&
if (waterb.isInWater(body.mGhostObject) &&
ch.mBodyNode->_getDerivedPosition().y > 0.05f)
e.remove<InWater>();
});
@@ -535,6 +592,16 @@ CharacterModule::CharacterModule(flecs::world &ecs)
<< "\n";
});
#endif
/* Create player */
player = ecs.entity("player");
player.set<AnimationControl>({ AnimationControl::ANIM_NONE,
AnimationControl::ANIM_NONE, false,
false });
player.set<CharacterBase>(
{ "normal-male.glb", 0.0f, nullptr, nullptr, nullptr });
player.set<CharacterBody>({ nullptr, nullptr, nullptr, false, false });
player.add<Character>();
player.add<Player>();
}
void CharacterModule::setAnimation(AnimationControl &anim)