Better boat handling
This commit is contained in:
@@ -6,14 +6,17 @@
|
||||
#include <Jolt/Physics/Character/Character.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
|
||||
#include <Jolt/Physics/Body/BodyLock.h>
|
||||
#include <Jolt/Physics/Collision/ContactListener.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "WaterModule.h"
|
||||
#include "BoatModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "LuaData.h"
|
||||
#include "physics.h"
|
||||
#include "loader.h"
|
||||
#include "EventModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -28,10 +31,10 @@ struct WaterBody {
|
||||
struct TriggerBody {
|
||||
void *foo;
|
||||
};
|
||||
|
||||
PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<PhysicsModule>();
|
||||
ecs.import <EventModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <BoatModule>();
|
||||
flecs::entity PhysicsPreUpdate =
|
||||
@@ -54,6 +57,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
ecs.component<TriggerBody>();
|
||||
ecs.component<CharacterVelocity>();
|
||||
ecs.component<WaterBody>().add(flecs::Singleton);
|
||||
ecs.component<CachedMass>();
|
||||
ecs.system<const EngineData, const Camera>("physics_init")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.without<Physics>()
|
||||
@@ -184,6 +188,9 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
static_cast<JPH::Character *>(b.ch.get())
|
||||
->AddToPhysicsSystem(
|
||||
JPH::EActivation::Activate);
|
||||
e.set<JPH::BodyID>(
|
||||
static_cast<JPH::Character *>(b.ch.get())
|
||||
->GetBodyID());
|
||||
e.modified<CharacterBody>();
|
||||
});
|
||||
ecs.observer<const EngineData, const EventTrigger>(
|
||||
@@ -205,6 +212,83 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
// JoltPhysicsWrapper::getSingleton().setDebugDraw(true);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
id, JPH::EActivation::Activate);
|
||||
JoltPhysicsWrapper::getSingleton().addContactListener(
|
||||
id,
|
||||
[](const JoltPhysics::ContactListener::
|
||||
ContactReport &report) -> void {
|
||||
flecs::entity trigger_e =
|
||||
ECS::get()
|
||||
.query_builder<
|
||||
const JPH::
|
||||
BodyID>()
|
||||
.with<EventTrigger>()
|
||||
.build()
|
||||
.find([&](const JPH::BodyID
|
||||
&id) {
|
||||
return id == report.id1 ||
|
||||
id == report.id2;
|
||||
});
|
||||
flecs::entity parent_e =
|
||||
trigger_e.parent();
|
||||
const JPH::BodyID &trigger_body =
|
||||
trigger_e.get<JPH::BodyID>();
|
||||
const JPH::BodyID &other_body =
|
||||
(trigger_body == report.id1) ?
|
||||
report.id2 :
|
||||
report.id1;
|
||||
flecs::entity other_e =
|
||||
ECS::get()
|
||||
.query_builder<
|
||||
const JPH::
|
||||
BodyID>()
|
||||
.without<EventTrigger>()
|
||||
.build()
|
||||
.find([&](const JPH::BodyID
|
||||
&id) {
|
||||
return id ==
|
||||
other_body;
|
||||
});
|
||||
if (!trigger_e.is_valid() ||
|
||||
!other_e.is_valid())
|
||||
return;
|
||||
if (parent_e.is_valid() &&
|
||||
parent_e == other_e)
|
||||
return;
|
||||
OgreAssert(
|
||||
trigger_e.is_valid(),
|
||||
"trigger entity is not valid");
|
||||
OgreAssert(other_e.is_valid(),
|
||||
"other entity is not valid");
|
||||
const EventTrigger &trg =
|
||||
trigger_e.get<EventTrigger>();
|
||||
if (report.entered) {
|
||||
trigger_e.get_mut<EventData>()
|
||||
.add(trigger_e,
|
||||
trg.event +
|
||||
"_enter",
|
||||
trigger_e,
|
||||
other_e);
|
||||
other_e.add<InTrigger>(
|
||||
trigger_e);
|
||||
trigger_e.add<TriggeredBy>(
|
||||
other_e);
|
||||
} else {
|
||||
trigger_e.get_mut<EventData>()
|
||||
.add(trigger_e,
|
||||
trg.event +
|
||||
"_exit",
|
||||
trigger_e,
|
||||
other_e);
|
||||
#if 0
|
||||
/* do not delete triggers until exit from actuator */
|
||||
other_e.remove<InTrigger>(
|
||||
trigger_e);
|
||||
trigger_e.remove<TriggeredBy>(
|
||||
other_e);
|
||||
#endif
|
||||
}
|
||||
ECS::modified<LuaEvent>();
|
||||
});
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const EventTrigger, const JPH::BodyID>(
|
||||
@@ -260,6 +344,7 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
.with<WaterAlmostReady>()
|
||||
.each([this](const EngineData &eng, WaterBody &body) {
|
||||
const WaterSurface &water = ECS::get<WaterSurface>();
|
||||
body.inWater.clear();
|
||||
JoltPhysicsWrapper::getSingleton().broadphaseQuery(
|
||||
eng.delta,
|
||||
water.mWaterNode->_getDerivedPosition(),
|
||||
@@ -388,17 +473,18 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
JoltPhysicsWrapper::getSingleton().activate(id);
|
||||
});
|
||||
ecs.system<const EngineData, const BoatBase, const WaterBody,
|
||||
const JPH::BodyID>("update_water_boat_buoyancy")
|
||||
const JPH::BodyID, const CachedMass>(
|
||||
"update_water_boat_buoyancy")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<InWater>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat, const WaterBody &body,
|
||||
const JPH::BodyID &id) {
|
||||
const JPH::BodyID &id, const CachedMass &mass) {
|
||||
const WaterSurface &water = ECS::get<WaterSurface>();
|
||||
float b = 1.0f, drag = 0.5f, adrag = 0.5f;
|
||||
float level = 0.1f;
|
||||
float level = 0.25f;
|
||||
float my = JoltPhysicsWrapper::getSingleton()
|
||||
.getPosition(id)
|
||||
.y;
|
||||
@@ -411,8 +497,9 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
else if (my > level && myv > 0)
|
||||
b = 0.8f;
|
||||
#endif
|
||||
/* max = 2.7; min = 1.7 */
|
||||
if (my < level)
|
||||
b = 1.7f;
|
||||
b = 2.2f;
|
||||
else if (my > level)
|
||||
b = 0.9f;
|
||||
// std::cout << my << std::endl;
|
||||
@@ -420,6 +507,33 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
id, water.mWaterNode->_getDerivedPosition(),
|
||||
Ogre::Vector3::UNIT_Y, b, drag, adrag,
|
||||
Ogre::Vector3::ZERO, eng.delta);
|
||||
/* stabilisation */
|
||||
Ogre::Vector3 currentAngularVelocity =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.getAngularVelocity(id);
|
||||
Ogre::Quaternion rotation =
|
||||
JoltPhysicsWrapper::getSingleton().getRotation(
|
||||
id);
|
||||
Ogre::Vector3 rotComp =
|
||||
rotation.Inverse() * Ogre::Vector3::UNIT_Y;
|
||||
rotComp.y = 0;
|
||||
if (Ogre::Math::Abs(rotComp.x) > 0.1f ||
|
||||
Ogre::Math::Abs(rotComp.z) > 0.1f) {
|
||||
Ogre::Vector3 localAngularVelocity =
|
||||
rotation.Inverse() *
|
||||
currentAngularVelocity;
|
||||
Ogre::Vector3 localAngularVelocityChange(
|
||||
-localAngularVelocity.x, 0,
|
||||
-localAngularVelocity.z);
|
||||
localAngularVelocityChange -=
|
||||
rotComp * 20.0f * eng.delta;
|
||||
Ogre::Vector3 angularVelocityChange =
|
||||
rotation * localAngularVelocityChange;
|
||||
Ogre::Vector3 angularImpulse =
|
||||
mass.mass * angularVelocityChange;
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.addAngularImpulse(id, angularImpulse);
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, const WaterBody>(
|
||||
"update_water_character_buoyancy")
|
||||
@@ -480,15 +594,31 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
#endif
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, CharacterVelocity>(
|
||||
"HandleVelocity")
|
||||
ecs.system<const EngineData, const CharacterBody>("UpdatePhysics")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterUpdatePhysicsState>()
|
||||
.write<CharacterUpdatePhysicsState>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBody &body) {
|
||||
if (e.has<CharacterDisablePhysics>())
|
||||
PhysicsModule::controlPhysics(e, false);
|
||||
else
|
||||
PhysicsModule::controlPhysics(e, true);
|
||||
e.remove<CharacterUpdatePhysicsState>();
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBase, const CharacterBody,
|
||||
CharacterVelocity>("HandleVelocity")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.without<CharacterDisablePhysics>()
|
||||
.without<CharacterUpdatePhysicsState>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &chbase,
|
||||
const CharacterBody &body, CharacterVelocity &gr) {
|
||||
if (e.has<InWater>() &&
|
||||
chbase.mBodyNode->_getDerivedPosition().y > -0.5f)
|
||||
e.remove<InWater>();
|
||||
Ogre::Vector3 v = gr.velocity;
|
||||
v.y = 0.0f;
|
||||
JPH::Character *ch =
|
||||
@@ -513,6 +643,39 @@ PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
ch->SetLinearVelocity(JoltPhysics::convert(v));
|
||||
gr.velocity = Ogre::Vector3::ZERO;
|
||||
});
|
||||
ecs.system<const EngineData, CharacterBase, const CharacterBody,
|
||||
CharacterVelocity>("HandleVelocityNoPhysics")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<CharacterDisablePhysics>()
|
||||
.without<CharacterUpdatePhysicsState>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
CharacterBase &ch, const CharacterBody &body,
|
||||
CharacterVelocity &gr) {
|
||||
Ogre::Vector3 v = gr.velocity;
|
||||
// v.y = 0.0f;
|
||||
ch.mBodyNode->_setDerivedPosition(
|
||||
ch.mBodyNode->_getDerivedPosition() +
|
||||
v * eng.delta);
|
||||
gr.velocity = Ogre::Vector3::ZERO;
|
||||
if (e.has<JPH::BodyID>())
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.setPositionAndRotation(
|
||||
e.get<JPH::BodyID>(),
|
||||
ch.mBodyNode
|
||||
->_getDerivedPosition(),
|
||||
ch.mBodyNode
|
||||
->_getDerivedOrientation(),
|
||||
false);
|
||||
if (e.has<InWater>() &&
|
||||
ch.mBodyNode->_getDerivedPosition().y > -0.5f) {
|
||||
e.remove<InWater>();
|
||||
ch.is_submerged = false;
|
||||
}
|
||||
if (!e.has<InWater>() && ch.is_submerged)
|
||||
ch.is_submerged = false;
|
||||
});
|
||||
}
|
||||
flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
float *samples,
|
||||
@@ -528,8 +691,58 @@ flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
|
||||
return e;
|
||||
}
|
||||
void PhysicsModule::controlPhysics(flecs::entity e, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (e.has<CharacterBase>()) {
|
||||
e.remove<CharacterDisablePhysics>();
|
||||
OgreAssert(e.has<CharacterBody>(), "No body component");
|
||||
OgreAssert(e.has<JPH::BodyID>(),
|
||||
"No body id in entity");
|
||||
}
|
||||
if (!JoltPhysicsWrapper::getSingleton().isAdded(
|
||||
e.get<JPH::BodyID>())) {
|
||||
Ogre::Vector3 position =
|
||||
e.get<CharacterBase>()
|
||||
.mBodyNode->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
e.get<CharacterBase>()
|
||||
.mBodyNode->_getDerivedOrientation();
|
||||
if (position.y >= -0.5f)
|
||||
e.remove<InWater>();
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.setPositionAndRotation(e.get<JPH::BodyID>(),
|
||||
position, orientation,
|
||||
false);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
e.get<JPH::BodyID>(),
|
||||
JPH::EActivation::Activate);
|
||||
}
|
||||
} else {
|
||||
if (e.has<CharacterBase>()) {
|
||||
e.add<CharacterDisablePhysics>();
|
||||
if (!e.has<CharacterBody>())
|
||||
return;
|
||||
OgreAssert(e.has<CharacterBody>(), "No body component");
|
||||
OgreAssert(e.has<JPH::BodyID>(),
|
||||
"No body id in entity");
|
||||
}
|
||||
if (JoltPhysicsWrapper::getSingleton().isAdded(
|
||||
e.get<JPH::BodyID>()))
|
||||
JoltPhysicsWrapper::getSingleton().removeBody(
|
||||
e.get<JPH::BodyID>());
|
||||
Ogre::Vector3 position =
|
||||
e.get<CharacterBase>().mBodyNode->_getDerivedPosition();
|
||||
e.remove<InWater>();
|
||||
}
|
||||
}
|
||||
bool WaterBody::isInWater(const JPH::BodyID &id) const
|
||||
{
|
||||
flecs::entity e =
|
||||
ECS::get().query_builder<const JPH::BodyID>().build().find(
|
||||
[&](const JPH::BodyID &bodyid) {
|
||||
return bodyid == id;
|
||||
});
|
||||
return inWater.find(id) != inWater.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user