converted to Jolt physics
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
project(characters)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain CONFIG)
|
||||
# add_library(controller STATIC controller.cpp)
|
||||
# target_link_libraries(controller PUBLIC OgreMain OgreBites PRIVATE GameData)
|
||||
# target_include_directories(controller PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -1,369 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "character.h"
|
||||
|
||||
#define RUN_SPEED 17 // character running speed in units per second
|
||||
#define TURN_SPEED 500.0f // character turning in degrees per second
|
||||
#define ANIM_FADE_SPEED \
|
||||
7.5f // animation crossfade speed in % of full weight per second
|
||||
|
||||
Character::Character(Ogre::SceneManager *scnMgr, const Ogre::String &model,
|
||||
Ogre::Bullet::DynamicsWorld *world)
|
||||
: mModelName(model)
|
||||
, mScnMgr(scnMgr)
|
||||
, mPivotPitch(0)
|
||||
, mVerticalVelocity(0)
|
||||
, mAnimID(ANIM_NONE)
|
||||
, mRunning(false)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
, mWorld(world)
|
||||
, mGoalDirection(0, 0, 0)
|
||||
, mUpdate(false)
|
||||
{
|
||||
setupBody();
|
||||
setupAnimations();
|
||||
}
|
||||
|
||||
Character::~Character()
|
||||
{
|
||||
}
|
||||
|
||||
bool Character::frameStarted(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Character::frameRenderingQueued(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
if (mUpdate) {
|
||||
updateBody(evt.timeSinceLastFrame);
|
||||
updateAnimations(evt.timeSinceLastFrame);
|
||||
if (evt.timeSinceLastFrame > 0)
|
||||
updateRootMotion(evt.timeSinceLastFrame);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Character::frameEnded(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Character::setupBody()
|
||||
{
|
||||
mBodyEnt = mScnMgr->createEntity(mModelName);
|
||||
mBodyNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
mBodyNode->attachObject(mBodyEnt);
|
||||
mSkeleton = mBodyEnt->getSkeleton();
|
||||
// mRigidBody = world->addCharacter(mBodyEnt, 0);
|
||||
// mCollisionShape = static_cast<btCompoundShape *>(mRigidBody->getCollisionShape());
|
||||
mGhostObject = new btPairCachingGhostObject();
|
||||
mCollisionShape = new btCompoundShape;
|
||||
mGhostObject->setCollisionShape(mCollisionShape);
|
||||
|
||||
{
|
||||
btVector3 inertia(0, 0, 0);
|
||||
// mCollisionShape = new btCompoundShape();
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
btCapsuleShape *shape =
|
||||
new btCapsuleShape(radius, 2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(mCollisionShape)
|
||||
->addChildShape(transform, shape);
|
||||
btScalar masses[1] = { 0 };
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(mCollisionShape)
|
||||
->calculatePrincipalAxisTransform(masses, principal,
|
||||
inertia);
|
||||
}
|
||||
mGhostObject->setCollisionFlags(
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT /* |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE */);
|
||||
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
|
||||
Ogre::Bullet::KinematicMotionSimple *controller =
|
||||
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,
|
||||
mBodyNode);
|
||||
mWorld->attachCollisionObject(mGhostObject, mBodyEnt,
|
||||
btBroadphaseProxy::AllFilter,
|
||||
btBroadphaseProxy::AllFilter);
|
||||
mWorld->getBtWorld()->addAction(controller);
|
||||
|
||||
assert(mCollisionShape);
|
||||
#if 0
|
||||
if (mRigidBody->getMass() == 0) {
|
||||
#if 0
|
||||
mRigidBody->setCollisionFlags(mRigidBody->getCollisionFlags()
|
||||
| btCollisionObject::CF_KINEMATIC_OBJECT
|
||||
| btCollisionObject::CF_NO_CONTACT_RESPONSE
|
||||
);
|
||||
#endif
|
||||
#if 0
|
||||
mGhostObject->setWorldTransform(mRigidBody->getWorldTransform());
|
||||
WorldData::get_singleton()->getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
mRigidBody->setActivationState(DISABLE_DEACTIVATION);
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
Ogre::Entity *e2 = mScnMgr->createEntity("normal-male.glb");
|
||||
Ogre::SceneNode *e2node = mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
e2node->attachObject(e2);
|
||||
mGhostObject = WorldData::get_singleton()->addGhostObject(e2, mCollisionShape);
|
||||
mController = new btKinematicCharacterController(mGhostObject, mCollisionShape, 0.5f);
|
||||
WorldData::get_singleton()->getBtWorld()->addAction(mController);
|
||||
}
|
||||
#endif
|
||||
assert(mSkeleton->hasBone("Root"));
|
||||
mRootBone = mSkeleton->getBone("Root");
|
||||
assert(mRootBone);
|
||||
}
|
||||
void Character::setupAnimations()
|
||||
{
|
||||
int i, j;
|
||||
mSkeleton->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);
|
||||
Ogre::String animNames[NUM_ANIMS] = { "idle", "walking", "running" };
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
|
||||
mAnims[i]->setLoop(true);
|
||||
mAnims[i]->setEnabled(true);
|
||||
mAnims[i]->setWeight(0);
|
||||
mFadingIn[i] = false;
|
||||
mFadingOut[i] = false;
|
||||
mSkelAnimations[i] = mSkeleton->getAnimation(animNames[i]);
|
||||
for (const auto &it : mSkelAnimations[i]->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack *track = it.second;
|
||||
Ogre::String trackName =
|
||||
track->getAssociatedNode()->getName();
|
||||
if (trackName == "mixamorig:Hips") {
|
||||
mHipsTracks[i] = track;
|
||||
} else if (trackName == "Root") {
|
||||
mRootTracks[i] = track;
|
||||
// mRootTracks[i]->removeAllKeyFrames();
|
||||
}
|
||||
}
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 motion = Ogre::Vector3::ZERO;
|
||||
for (j = 0; j < mRootTracks[i]->getNumKeyFrames(); j++) {
|
||||
Ogre::Vector3 trans = mRootTracks[i]
|
||||
->getNodeKeyFrame(j)
|
||||
->getTranslate();
|
||||
if (j == 0)
|
||||
delta = trans;
|
||||
else
|
||||
delta = trans - motion;
|
||||
mRootTracks[i]->getNodeKeyFrame(j)->setTranslate(delta);
|
||||
motion = trans;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for(i = 0; i < NUM_ANIMS - 1; i++) {
|
||||
// need to cache
|
||||
int j;
|
||||
Ogre::String animName = mAnims[i]->getAnimationName();
|
||||
Ogre::Animation *anim = mSkeleton->getAnimation(animName);
|
||||
Ogre::NodeAnimationTrack *hips_track = nullptr, *root_track = nullptr;
|
||||
Ogre::Node *root_node = nullptr;
|
||||
for (const auto& it : anim->_getNodeTrackList()) {
|
||||
Ogre::NodeAnimationTrack* track = it.second;
|
||||
Ogre::String trackName = track->getAssociatedNode()->getName();
|
||||
std::cout << animName << " track: " << trackName << "\n";
|
||||
if (trackName == "mixamorig:Hips")
|
||||
hips_track = track;
|
||||
else if (trackName == "Root") {
|
||||
root_track = track;
|
||||
root_node = track->getAssociatedNode();
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
root_track->removeAllKeyFrames();
|
||||
std::cout << hips_track << " " << root_track << "\n";
|
||||
std::cout << hips_track->getNumKeyFrames() << " " << root_track->getNumKeyFrames() << "\n";
|
||||
assert(hips_track && root_track);
|
||||
Ogre::Vector3 delta = Ogre::Vector3::ZERO;
|
||||
for(j = 0; j < hips_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
Ogre::Vector3 hips_trans(0, 0, 0);
|
||||
Ogre::Vector3 root_trans(0, 0, 0);
|
||||
hips_track->getNodeKeyFrame(j)->setTranslate(hips_trans);
|
||||
Ogre::TransformKeyFrame *nk = root_track->createNodeKeyFrame(timePos);
|
||||
nk->setTranslate(root_trans - delta);
|
||||
nk->setScale(Ogre::Vector3(1, 1, 1));
|
||||
nk->setRotation(Ogre::Quaternion());
|
||||
std::cout << animName << " delta: " << j << " " << timePos << " " << root_trans - delta << "\n";
|
||||
delta = root_trans;
|
||||
}
|
||||
for(j = 0; j < root_track->getNumKeyFrames(); j++) {
|
||||
float timePos = hips_track->getNodeKeyFrame(j)->getTime();
|
||||
Ogre::Vector3 root_trans = hips_track->getNodeKeyFrame(j)->getTranslate();
|
||||
std::cout << animName << " delta: root: " << j << " " << timePos << " " << root_trans << "\n";
|
||||
}
|
||||
}
|
||||
// assert(false);
|
||||
#endif
|
||||
setAnimation(ANIM_IDLE);
|
||||
}
|
||||
void Character::updateBody(Ogre::Real delta)
|
||||
{
|
||||
Ogre::Quaternion toGoal =
|
||||
mBodyNode->getOrientation().zAxis().getRotationTo(
|
||||
mGoalDirection);
|
||||
// calculate how much the character has to turn to face goal direction
|
||||
Ogre::Real yawToGoal = toGoal.getYaw().valueDegrees();
|
||||
// this is how much the character CAN turn this frame
|
||||
Ogre::Real yawAtSpeed =
|
||||
yawToGoal / Ogre::Math::Abs(yawToGoal) * delta * TURN_SPEED;
|
||||
// reduce "turnability" if we're in midair
|
||||
// if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;
|
||||
if (yawToGoal < 0)
|
||||
yawToGoal = std::min<Ogre::Real>(
|
||||
0,
|
||||
std::max<Ogre::Real>(
|
||||
yawToGoal,
|
||||
yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
|
||||
else if (yawToGoal > 0)
|
||||
yawToGoal = std::max<Ogre::Real>(
|
||||
0,
|
||||
std::min<Ogre::Real>(
|
||||
yawToGoal,
|
||||
yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
|
||||
mBodyNode->yaw(Ogre::Degree(yawToGoal));
|
||||
}
|
||||
void Character::updateAnimations(Ogre::Real delta)
|
||||
{
|
||||
int i, j, k;
|
||||
Ogre::Real animSpeed = 1;
|
||||
mTimer += delta;
|
||||
{
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
OgreAssert(!Ogre::Math::isNaN(rot.x), "NaN");
|
||||
OgreAssert(!Ogre::Math::isNaN(rot.y), "NaN");
|
||||
OgreAssert(!Ogre::Math::isNaN(rot.z), "NaN");
|
||||
}
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
if (mAnimID == ANIM_WALK)
|
||||
mAnims[mAnimID]->addTime(delta * 1.0f);
|
||||
else
|
||||
mAnims[mAnimID]->addTime(delta * animSpeed);
|
||||
}
|
||||
fadeAnimations(delta);
|
||||
}
|
||||
void Character::updateRootMotion(Ogre::Real delta)
|
||||
{
|
||||
Ogre::Vector3 boneMotion = mRootBone->getPosition();
|
||||
OgreAssert(delta > 0.0f, "Zero delta");
|
||||
Ogre::Vector3 motion = boneMotion - rootMotion;
|
||||
if (motion.squaredLength() > 0.1f * 0.1f)
|
||||
motion = Ogre::Vector3();
|
||||
rootMotion = boneMotion;
|
||||
#if 0
|
||||
float mass = mRigidBody->getMass();
|
||||
std::cout << "Root bone position: " << boneMotion << "\n";
|
||||
std::cout << "body mass: " << mass << "\n";
|
||||
#endif
|
||||
/* Kinematic motion */
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
// Ogre::Vector3 gravity(0, -9.8, 0);
|
||||
Ogre::Vector3 gravity(0, 0, 0);
|
||||
Ogre::Vector3 velocity = rot * boneMotion / delta;
|
||||
velocity += gravity * delta;
|
||||
Ogre::Vector3 rotMotion = velocity * delta;
|
||||
btTransform from(convert(mBodyNode->getOrientation()),
|
||||
convert(mBodyNode->getPosition()));
|
||||
mBodyNode->setPosition(mBodyNode->getPosition() + rotMotion);
|
||||
// WorldData::get_singleton()->getWorld()->testBodyMotion(mRigidBody, from, Ogre::Bullet::convert(rotMotion), true,
|
||||
// nullptr, false, std::set<btCollisionObject *>());
|
||||
}
|
||||
void Character::fadeAnimations(Ogre::Real delta)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_ANIMS; i++) {
|
||||
if (mFadingIn[i]) {
|
||||
// slowly fade this animation in until it has full weight
|
||||
Ogre::Real newWeight = mAnims[i]->getWeight() +
|
||||
delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(
|
||||
Ogre::Math::Clamp<Ogre::Real>(newWeight, 0, 1));
|
||||
if (newWeight >= 1)
|
||||
mFadingIn[i] = false;
|
||||
} else if (mFadingOut[i]) {
|
||||
// slowly fade this animation out until it has no weight, and then disable it
|
||||
Ogre::Real newWeight = mAnims[i]->getWeight() -
|
||||
delta * ANIM_FADE_SPEED;
|
||||
mAnims[i]->setWeight(
|
||||
Ogre::Math::Clamp<Ogre::Real>(newWeight, 0, 1));
|
||||
if (newWeight <= 0) {
|
||||
mAnims[i]->setEnabled(false);
|
||||
mFadingOut[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Character::setAnimation(AnimID id, bool reset)
|
||||
{
|
||||
assert(id >= 0 && id < NUM_ANIMS);
|
||||
if (mAnimID != ANIM_NONE) {
|
||||
mFadingIn[mAnimID] = false;
|
||||
mFadingOut[mAnimID] = true;
|
||||
}
|
||||
mAnimID = id;
|
||||
if (id != ANIM_NONE) {
|
||||
mAnims[id]->setEnabled(true);
|
||||
mAnims[id]->setWeight(0);
|
||||
mFadingOut[id] = false;
|
||||
mFadingIn[id] = true;
|
||||
if (reset)
|
||||
mAnims[id]->setTimePosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool Character::act_run()
|
||||
{
|
||||
if (mAnimID == ANIM_IDLE)
|
||||
setAnimation(ANIM_RUN, true);
|
||||
else if (mAnimID == ANIM_WALK)
|
||||
setAnimation(ANIM_RUN);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Character::act_walk()
|
||||
{
|
||||
if (mAnimID == ANIM_IDLE)
|
||||
setAnimation(ANIM_WALK, true);
|
||||
else if (mAnimID == ANIM_RUN)
|
||||
setAnimation(ANIM_WALK);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Character::act_idle()
|
||||
{
|
||||
setAnimation(ANIM_IDLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Character::isRunning()
|
||||
{
|
||||
return mAnimID == ANIM_RUN;
|
||||
}
|
||||
|
||||
bool Character::isWalking()
|
||||
{
|
||||
return mAnimID == ANIM_WALK;
|
||||
}
|
||||
|
||||
Ogre::Vector3 Character::getPosition()
|
||||
{
|
||||
return mBodyNode->_getDerivedPosition();
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
#include <Ogre.h>
|
||||
#include <OgreFrameListener.h>
|
||||
#include <OgreBullet.h>
|
||||
class btCompoundShape;
|
||||
class btPairCachingGhostObject;
|
||||
class Character : public Ogre::FrameListener {
|
||||
enum AnimID {
|
||||
ANIM_IDLE = 0,
|
||||
ANIM_WALK,
|
||||
ANIM_RUN,
|
||||
NUM_ANIMS,
|
||||
ANIM_NONE = NUM_ANIMS
|
||||
};
|
||||
Ogre::String mModelName;
|
||||
Ogre::Node *mRootBone;
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
|
||||
Ogre::SceneNode *mCameraPivot;
|
||||
Ogre::SceneNode *mCameraGoal, *mBodyNode;
|
||||
Ogre::Entity *mBodyEnt;
|
||||
Ogre::Real mPivotPitch;
|
||||
Ogre::Real mVerticalVelocity;
|
||||
Ogre::Vector3 mGoalDirection; // actual intended direction in world-space
|
||||
Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list
|
||||
Ogre::Animation *mSkelAnimations[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS];
|
||||
Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS];
|
||||
AnimID mAnimID;
|
||||
bool mFadingIn[NUM_ANIMS]; // which animations are fading in
|
||||
bool mFadingOut[NUM_ANIMS]; // which animations are fading out
|
||||
Ogre::Real
|
||||
mTimer; // general timer to see how long animations have been playing
|
||||
Ogre::Skeleton *mSkeleton;
|
||||
bool mRunning;
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
Ogre::Bullet::DynamicsWorld *mWorld;
|
||||
bool mUpdate;
|
||||
|
||||
public:
|
||||
Character(Ogre::SceneManager *scnMgr, const Ogre::String &modelName,
|
||||
Ogre::Bullet::DynamicsWorld *world);
|
||||
~Character();
|
||||
|
||||
private:
|
||||
void setupBody();
|
||||
void setupAnimations();
|
||||
|
||||
public:
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
bool frameEnded(const Ogre::FrameEvent &evt) override;
|
||||
bool frameRenderingQueued(const Ogre::FrameEvent &evt) override;
|
||||
|
||||
private:
|
||||
void updateBody(Ogre::Real deltaTime);
|
||||
void updateAnimations(Ogre::Real deltaTime);
|
||||
void updateRootMotion(Ogre::Real deltaTime);
|
||||
void fadeAnimations(Ogre::Real deltaTime);
|
||||
void setAnimation(AnimID id, bool reset = false);
|
||||
inline btQuaternion convert(const Ogre::Quaternion &q)
|
||||
{
|
||||
return btQuaternion(q.x, q.y, q.z, q.w);
|
||||
}
|
||||
inline btVector3 convert(const Ogre::Vector3 &v)
|
||||
{
|
||||
return btVector3(v.x, v.y, v.z);
|
||||
}
|
||||
inline btTransform convert(const Ogre::Quaternion &q,
|
||||
const Ogre::Vector3 &v)
|
||||
{
|
||||
btQuaternion mq = convert(q);
|
||||
btVector3 mv = convert(v);
|
||||
return btTransform(mq, mv);
|
||||
}
|
||||
inline Ogre::Quaternion convert(const btQuaternion &q)
|
||||
{
|
||||
return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z());
|
||||
}
|
||||
inline Ogre::Vector3 convert(const btVector3 &v)
|
||||
{
|
||||
return Ogre::Vector3(v.x(), v.y(), v.z());
|
||||
}
|
||||
inline void convert(const btTransform &from, Ogre::Quaternion &q,
|
||||
Ogre::Vector3 &v)
|
||||
{
|
||||
q = convert(from.getRotation());
|
||||
v = convert(from.getOrigin());
|
||||
}
|
||||
|
||||
public:
|
||||
bool isIdle()
|
||||
{
|
||||
return mAnimID == ANIM_IDLE;
|
||||
}
|
||||
bool act_run();
|
||||
bool act_walk();
|
||||
bool act_idle();
|
||||
bool isRunning();
|
||||
bool isWalking();
|
||||
bool isMoving()
|
||||
{
|
||||
return isRunning() || isWalking();
|
||||
}
|
||||
void setGoalDirection(const Ogre::Vector3 &goalDirection)
|
||||
{
|
||||
mGoalDirection = goalDirection;
|
||||
}
|
||||
Ogre::Vector3 getGoalDirection()
|
||||
{
|
||||
return mGoalDirection;
|
||||
}
|
||||
Ogre::Vector3 getPosition();
|
||||
void enableUpdates()
|
||||
{
|
||||
mUpdate = true;
|
||||
}
|
||||
void disableUpdates()
|
||||
{
|
||||
mUpdate = false;
|
||||
}
|
||||
bool getUpdates()
|
||||
{
|
||||
return mUpdate;
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "loader.h"
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "BoatModule.h"
|
||||
|
||||
namespace ECS
|
||||
@@ -14,7 +15,107 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<BoatModule>();
|
||||
ecs.component<BoatBase>();
|
||||
ecs.component<BoatBody>();
|
||||
ecs.component<BoatType>();
|
||||
ecs.component<SpawnBoat>();
|
||||
ecs.observer<const EngineData, const BoatType>("CreateBoat")
|
||||
.event(flecs::OnSet)
|
||||
.without<BoatBase>()
|
||||
.without<SpawnBoat>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const BoatType &type) { e.add<SpawnBoat>(); });
|
||||
ecs.system<const EngineData, const BoatType>("CreateBoat")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<BoatBase>()
|
||||
.with<WaterReady>()
|
||||
.with<SpawnBoat>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const BoatType &type) {
|
||||
if (type.resourceName.find(".scene") !=
|
||||
std::string::npos) {
|
||||
BoatBase &boat = e.ensure<BoatBase>();
|
||||
int i;
|
||||
std::vector<Ogre::SceneNode *> colliderTarget;
|
||||
boat.mNode =
|
||||
ECS::get<EngineData>()
|
||||
.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode(
|
||||
type.position,
|
||||
type.orientation);
|
||||
auto pnodes = boat.mNode->getChildren();
|
||||
for (i = 0; i < pnodes.size(); i++) {
|
||||
Ogre::SceneNode *pnode =
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
pnodes[i]);
|
||||
Ogre::Any any =
|
||||
pnode->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
if (obj_type == "hull-collider") {
|
||||
/* FIXME */
|
||||
}
|
||||
}
|
||||
{
|
||||
Ogre::SceneNode *attachment =
|
||||
eng.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode();
|
||||
Ogre::DataStreamPtr scene =
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.openResource(
|
||||
type.resourceName,
|
||||
Ogre::ResourceGroupManager::
|
||||
AUTODETECT_RESOURCE_GROUP_NAME);
|
||||
SceneLoader loader;
|
||||
loader.load(scene, "General",
|
||||
attachment, e);
|
||||
// attachment->loadChildren(type.resourceName);
|
||||
std::vector<Ogre::Node *> v =
|
||||
attachment->getChildren();
|
||||
OgreAssert(v.size() == 1,
|
||||
"Bad root nodes count in " +
|
||||
type.resourceName);
|
||||
Ogre::Any any =
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
v[0])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
OgreAssert(any.has_value(),
|
||||
"no \"type\" costom prop");
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
std::cout << "type: " << obj_type
|
||||
<< std::endl;
|
||||
OgreAssert(obj_type == "boat",
|
||||
"not a boat");
|
||||
boat.mNode =
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
v[0]);
|
||||
boat.mNode->_setDerivedPosition(
|
||||
type.position);
|
||||
boat.mNode->_setDerivedOrientation(
|
||||
type.orientation);
|
||||
boat.mEnt = static_cast<Ogre::Entity *>(
|
||||
boat.mNode->getAttachedObject(
|
||||
std::to_string(
|
||||
(int)e.raw_id()) +
|
||||
"/boat"));
|
||||
loader.setupPhysicsBody(boat.mNode,
|
||||
boat.mEnt, e);
|
||||
e.remove<SpawnBoat>();
|
||||
e.modified<BoatBase>();
|
||||
}
|
||||
// BoatBody &body = e.ensure<BoatBody>();
|
||||
// e.modified<BoatBase>();
|
||||
}
|
||||
// ECS::get_mut<ECS::EngineData>().enableDbgDraw = true;
|
||||
// ECS::modified<ECS::EngineData>();
|
||||
// e.modified<BoatBody>();
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, BoatType, Body2Entity>("CreateBoat")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<BoatBase>()
|
||||
@@ -33,6 +134,7 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
type.orientation);
|
||||
boat.mNode->attachObject(boat.mEnt);
|
||||
|
||||
#if 0
|
||||
BoatBody &body = e.ensure<BoatBody>();
|
||||
body.body =
|
||||
ECS::get<EngineData>()
|
||||
@@ -41,6 +143,7 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
Ogre::Bullet::CT_TRIMESH,
|
||||
nullptr, 2, 0x7fffffff);
|
||||
b2e.entities[body.body] = e;
|
||||
#endif
|
||||
} else if (type.resourceName.find(".scene") !=
|
||||
std::string::npos) {
|
||||
int i;
|
||||
@@ -105,14 +208,27 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
boat.mNode->getAttachedObject(
|
||||
std::to_string((int)e.raw_id()) +
|
||||
"/boat"));
|
||||
loader.setupPhysicsBody(boat.mNode, boat.mEnt);
|
||||
BoatBody &body = e.ensure<BoatBody>();
|
||||
#if 0
|
||||
Ogre::Any bodyA =
|
||||
boat.mNode->getUserObjectBindings()
|
||||
.getUserAny("bodyPointer");
|
||||
if (bodyA.has_value())
|
||||
body.body =
|
||||
Ogre::any_cast<btRigidBody *>(
|
||||
bodyA);
|
||||
#if 0
|
||||
body.body =
|
||||
ECS::get<EngineData>()
|
||||
.mWorld->addRigidBody(
|
||||
0, boat.mEnt,
|
||||
Ogre::Bullet::CT_TRIMESH,
|
||||
nullptr, 2, 0x7fffffff);
|
||||
#endif
|
||||
OgreAssert(body.body, "No body :()");
|
||||
b2e.entities[body.body] = e;
|
||||
#endif
|
||||
std::vector<Ogre::Node *> slots =
|
||||
boat.mNode->getChildren();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
@@ -167,7 +283,10 @@ BoatModule::BoatModule(flecs::world &ecs)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ECS::get_mut<ECS::EngineData>().enableDbgDraw = true;
|
||||
// ECS::modified<ECS::EngineData>();
|
||||
e.modified<BoatBody>();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@ struct BoatBase {
|
||||
Ogre::Entity *mEnt;
|
||||
Ogre::SceneNode *mNode;
|
||||
};
|
||||
struct BoatBody {
|
||||
btRigidBody *body;
|
||||
};
|
||||
struct SpawnBoat {};
|
||||
struct BoatModule {
|
||||
BoatModule(flecs::world &ecs);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
project(gamedata)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG)
|
||||
find_package(Bullet REQUIRED)
|
||||
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp
|
||||
BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp SmartObject.cpp goap.cpp)
|
||||
target_link_libraries(GameData PUBLIC OgreMain OgreBites OgreBullet
|
||||
OgrePaging OgreTerrain OgreOverlay flecs::flecs_static
|
||||
lua ${BULLET_LIBRARIES} PRIVATE sceneloader world-build)
|
||||
target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${BULLET_INCLUDE_DIR})
|
||||
BoatModule.cpp EventTriggerModule.cpp CharacterAnimationModule.cpp PhysicsModule.cpp SmartObject.cpp SlotsModule.cpp goap.cpp)
|
||||
target_link_libraries(GameData PUBLIC lua flecs::flecs_static OgreMain OgreBites
|
||||
OgrePaging OgreTerrain OgreOverlay
|
||||
PRIVATE sceneloader world-build physics)
|
||||
target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${BULLET_INCLUDE_DIR} ../luaaa)
|
||||
target_compile_definitions(GameData PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Components.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "world-build.h"
|
||||
namespace ECS
|
||||
@@ -228,6 +229,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
}
|
||||
#endif
|
||||
v.velocity = rot * boneMotion / safeDelta;
|
||||
#if 0
|
||||
if (!e.has<CharacterDisablePhysics>() &&
|
||||
!e.has<CharacterInActuator>()) {
|
||||
if (eng.startupDelay <= 0.0f)
|
||||
@@ -235,6 +237,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
v.velocity.y = Ogre::Math::Clamp(v.velocity.y,
|
||||
-10.5f, 10.0f);
|
||||
}
|
||||
#endif
|
||||
// if (v.velocity.squaredLength() > 1.4f * 1.4f)
|
||||
// v.velocity = v.velocity.normalisedCopy() * 1.4f;
|
||||
// ch.mBoneMotion = Ogre::Vector3::ZERO;
|
||||
@@ -246,7 +249,11 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
Ogre::Math::Clamp(v.velocity.z, -16.0f, 16.0f);
|
||||
v.velocity.y =
|
||||
Ogre::Math::Clamp(v.velocity.y, -10.5f, 10.0f);
|
||||
#if 0
|
||||
v.velocity.y = 0.0f;
|
||||
#endif
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const AnimationControl,
|
||||
const CharacterBase, CharacterVelocity>("HandleSwimming")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -271,12 +278,13 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
h * eng.delta;
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, CharacterBase, CharacterBody,
|
||||
AnimationControl, CharacterVelocity>("HandleRootMotion")
|
||||
#endif
|
||||
ecs.system<const EngineData, CharacterBase, AnimationControl,
|
||||
CharacterVelocity>("HandleRootMotion")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
CharacterBase &ch, CharacterBody &body,
|
||||
AnimationControl &anim, CharacterVelocity &v) {
|
||||
CharacterBase &ch, AnimationControl &anim,
|
||||
CharacterVelocity &v) {
|
||||
if (!ch.mBodyNode)
|
||||
return;
|
||||
if (eng.delta < 0.0000001f)
|
||||
@@ -286,6 +294,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
Ogre::Vector3 colNormal;
|
||||
bool is_on_floor = false;
|
||||
bool penetration = false;
|
||||
#if 0
|
||||
if (eng.startupDelay < 0.0f) {
|
||||
if (body.mController) {
|
||||
Ogre::Vector3 rotMotion =
|
||||
@@ -321,7 +330,9 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
rotMotion);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
});
|
||||
#if 0
|
||||
ecs.system<CharacterVelocity, CharacterBase>("HandleRootMotionEnd")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](flecs::entity e, CharacterVelocity &v,
|
||||
@@ -330,6 +341,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
// v.velocity = Ogre::Vector3::ZERO;
|
||||
// ch.mBoneMotion = Ogre::Vector3::ZERO;
|
||||
});
|
||||
#endif
|
||||
|
||||
ecs.system<const Input, const CharacterBase, AnimationControl>(
|
||||
"HandleNPCAnimations")
|
||||
@@ -576,6 +588,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
<< std::endl;
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterBase, CharacterBody>(
|
||||
"UpdateBodyCast")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -655,6 +668,7 @@ CharacterAnimationModule::CharacterAnimationModule(flecs::world &ecs)
|
||||
result.m_collisionObject)));
|
||||
}
|
||||
});
|
||||
#endif
|
||||
struct AnimationSetCommand : public GameWorld::Command {
|
||||
int operator()(const std::vector<GameWorld::Parameter *> &args)
|
||||
override
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
#include "GameData.h"
|
||||
#include "WaterModule.h"
|
||||
#include "TerrainModule.h"
|
||||
#include "Components.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "goap.h"
|
||||
@@ -17,8 +17,10 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
ecs.component<Character>();
|
||||
ecs.component<Player>();
|
||||
ecs.component<CharacterBase>();
|
||||
ecs.component<CharacterVelocity>();
|
||||
ecs.component<CharacterBody>();
|
||||
ecs.component<CharacterGravity>();
|
||||
ecs.component<CharacterLocation>();
|
||||
ecs.component<CharacterBuoyancy>();
|
||||
ecs.component<CharacterConf>();
|
||||
ecs.component<CharacterDisablePhysics>();
|
||||
ecs.component<CharacterUpdatePhysicsState>();
|
||||
ecs.component<CharacterInActuator>();
|
||||
@@ -125,6 +127,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
else if (current_subm < 0.8f)
|
||||
ch.is_submerged = false;
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
|
||||
"HandleGravityBouyanceWater")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -164,6 +167,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
gr.gvelocity *= (1.0 - eng.delta);
|
||||
gr.velocity.y *= (1.0 - eng.delta);
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
|
||||
"HandleGravityNoWater")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -183,6 +188,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
gr.gvelocity *= (1.0 - eng.delta);
|
||||
gr.velocity.y *= (1.0 - eng.delta);
|
||||
});
|
||||
#endif
|
||||
#define TURN_SPEED 500.0f // character turning in degrees per second
|
||||
ecs.system<const Input, const Camera, CharacterBase>("UpdateBody")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -235,6 +241,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
ch.mBodyNode->yaw(Ogre::Degree(yawToGoal));
|
||||
}
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, CharacterLocation, CharacterBase,
|
||||
CharacterBody>("UpdateCharacterBase")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -251,6 +258,40 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
ch.mBodyNode->_getDerivedPosition();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
ecs.observer<const EngineData, const CharacterLocation,
|
||||
const CharacterConf>("SetupCharacterM")
|
||||
.event(flecs::OnSet)
|
||||
.with<Character>()
|
||||
.without<CharacterBase>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterLocation &loc,
|
||||
const CharacterConf &conf) {
|
||||
CharacterBase &ch = e.ensure<CharacterBase>();
|
||||
AnimationControl &anim = e.ensure<AnimationControl>();
|
||||
ch.mBodyEnt = eng.mScnMgr->createEntity(conf.type);
|
||||
ch.mBodyNode = eng.mScnMgr->getRootSceneNode()
|
||||
->createChildSceneNode();
|
||||
ch.mBodyNode->setOrientation(loc.orientation);
|
||||
ch.mBodyNode->setPosition(loc.position);
|
||||
ch.mBodyNode->attachObject(ch.mBodyEnt);
|
||||
ch.mSkeleton = ch.mBodyEnt->getSkeleton();
|
||||
OgreAssert(ch.mBodyEnt->getSkeleton()->hasBone("Root"),
|
||||
"No root bone");
|
||||
OgreAssert(ch.mSkeleton->hasBone("Root"),
|
||||
"No root bone");
|
||||
ch.mRootBone = ch.mSkeleton->getBone("Root");
|
||||
OgreAssert(ch.mRootBone, "No root bone");
|
||||
// body.mController = nullptr;
|
||||
ch.mBoneMotion = Ogre::Vector3::ZERO;
|
||||
ch.mBonePrevMotion = Ogre::Vector3::ZERO;
|
||||
e.set<CharacterVelocity>(
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
|
||||
e.add<CharacterGravity>();
|
||||
e.add<CharacterBuoyancy>();
|
||||
anim.configured = false;
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const CharacterLocation,
|
||||
const CharacterConf, Body2Entity>("SetupCharacter")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -276,13 +317,14 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
"No root bone");
|
||||
ch.mRootBone = ch.mSkeleton->getBone("Root");
|
||||
OgreAssert(ch.mRootBone, "No root bone");
|
||||
body.mController = nullptr;
|
||||
// body.mController = nullptr;
|
||||
ch.mBoneMotion = Ogre::Vector3::ZERO;
|
||||
ch.mBonePrevMotion = Ogre::Vector3::ZERO;
|
||||
e.set<CharacterVelocity>(
|
||||
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
|
||||
body.checkGround = false;
|
||||
body.checkGroundResult = false;
|
||||
#if 0
|
||||
body.mCollisionShape = nullptr;
|
||||
body.mGhostObject = nullptr;
|
||||
body.mController = nullptr;
|
||||
@@ -320,12 +362,15 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
body.mGhostObject, ch.mBodyEnt, 1, 0x7FFFFFFF);
|
||||
OgreAssert(body.mGhostObject, "Need GhostObject");
|
||||
OgreAssert(body.mCollisionShape, "No collision shape");
|
||||
#endif
|
||||
e.add<CharacterGravity>();
|
||||
e.add<CharacterBuoyancy>();
|
||||
anim.configured = false;
|
||||
OgreAssert(body.mGhostObject->hasContactResponse(),
|
||||
"need contact response");
|
||||
// OgreAssert(body.mGhostObject->hasContactResponse(),
|
||||
// "need contact response");
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, CharacterBase, CharacterBody>(
|
||||
"UpdateCharacterPhysics")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -334,17 +379,21 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
.with<WaterReady>()
|
||||
.each([](const EngineData &eng, CharacterBase &ch,
|
||||
CharacterBody &body) {
|
||||
#if 0
|
||||
if (ch.mBodyNode && !body.mController &&
|
||||
eng.startupDelay < 0.0f) {
|
||||
body.mController =
|
||||
new Ogre::Bullet::KinematicMotionSimple(
|
||||
body.mGhostObject,
|
||||
ch.mBodyNode);
|
||||
body.mController->enableManualNarrowPhase(true);
|
||||
eng.mWorld->getBtWorld()->addAction(
|
||||
body.mController);
|
||||
OgreAssert(body.mController, "Need controller");
|
||||
}
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
#define CAM_HEIGHT 1.6f // height of camera above character's center of mass
|
||||
ecs.system<const EngineData, Camera, const CharacterBase>(
|
||||
"UpdateCamera")
|
||||
@@ -394,6 +443,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
Ogre::Node::TS_PARENT);
|
||||
}
|
||||
});
|
||||
#if 0
|
||||
class ClosestNotMeRayResultCallback
|
||||
: public btCollisionWorld::ClosestRayResultCallback {
|
||||
btCollisionObject *mMe;
|
||||
@@ -416,12 +466,14 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
rayResult, normalInWorldSpace);
|
||||
}
|
||||
};
|
||||
ecs.system<const EngineData, CharacterBody>("CheckGround")
|
||||
#endif
|
||||
ecs.system<const EngineData, CharacterBase>("CheckGround")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<Character>()
|
||||
.with<Player>()
|
||||
.without<GroundCheckReady>()
|
||||
.each([](const EngineData &eng, CharacterBody &body) {
|
||||
.each([](const EngineData &eng, CharacterBase &ch) {
|
||||
#if 0
|
||||
if (body.mGhostObject) {
|
||||
btVector3 from =
|
||||
body.mGhostObject->getWorldTransform()
|
||||
@@ -437,7 +489,10 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
if (resultCallback.hasHit())
|
||||
ECS::get().add<GroundCheckReady>();
|
||||
}
|
||||
#endif
|
||||
ECS::get().add<GroundCheckReady>();
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const WaterBody, const CharacterBase, CharacterBody>(
|
||||
"CharacterWater1")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -445,11 +500,13 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
.without<InWater>()
|
||||
.each([](flecs::entity e, const WaterBody &waterb,
|
||||
const CharacterBase &ch, CharacterBody &body) {
|
||||
#if 0
|
||||
if (waterb.isInWater(body.mGhostObject) &&
|
||||
ch.mBodyNode->_getDerivedPosition().y < -0.05f) {
|
||||
e.add<InWater>();
|
||||
std::cout << "Big Splash\n";
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (waterb.mInWater.find(body.mGhostObject) ==
|
||||
waterb.mInWater.end())
|
||||
@@ -457,6 +514,8 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
std::cout << waterb.mInWater.size() << " InWater\n";
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const WaterBody, const CharacterBase, CharacterBody>(
|
||||
"CharacterWater2")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -465,12 +524,15 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
.each([](flecs::entity e, const WaterBody &waterb,
|
||||
const CharacterBase &ch, CharacterBody &body) {
|
||||
float h = ch.mBodyNode->_getDerivedPosition().y;
|
||||
#if 0
|
||||
if (waterb.isInWater(body.mGhostObject) && h > 0.05f)
|
||||
e.remove<InWater>();
|
||||
else if (!waterb.isInWater(body.mGhostObject) &&
|
||||
h > 0.05f)
|
||||
e.remove<InWater>();
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
ecs.system<const EngineData, CharacterBase, CharacterBody>(
|
||||
"DisplayPlayerPos")
|
||||
@@ -483,39 +545,14 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
<< "\n";
|
||||
});
|
||||
#endif
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot>(
|
||||
"UpdatePhysics2")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterDisablePhysics>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot) {
|
||||
if (slot.parent_e.has<ObjectSlots>()) {
|
||||
const ObjectSlots &slots =
|
||||
slot.parent_e.get<ObjectSlots>();
|
||||
if (slots.slots.find(slot.slot_name) ==
|
||||
slots.slots.end())
|
||||
// invalid setting
|
||||
e.remove<ParentSlot>();
|
||||
if (slot.activated)
|
||||
return;
|
||||
Ogre::SceneNode *slot_base =
|
||||
slots.slots.at(slot.slot_name).second;
|
||||
Ogre::Vector3 position =
|
||||
slot_base->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
slot_base->_getDerivedOrientation();
|
||||
ch.mBodyNode->_setDerivedPosition(position);
|
||||
ch.mBodyNode->_setDerivedOrientation(
|
||||
orientation);
|
||||
slot.activated = true;
|
||||
}
|
||||
});
|
||||
#if 0
|
||||
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 0
|
||||
if (e.has<CharacterDisablePhysics>()) {
|
||||
eng.mWorld->getBtWorld()->removeAction(
|
||||
body.mController);
|
||||
@@ -523,8 +560,10 @@ CharacterModule::CharacterModule(flecs::world &ecs)
|
||||
eng.mWorld->getBtWorld()->addAction(
|
||||
body.mController);
|
||||
}
|
||||
#endif
|
||||
e.remove<CharacterUpdatePhysicsState>();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void CharacterModule::updateCameraGoal(Camera &camera, Ogre::Real deltaYaw,
|
||||
@@ -726,4 +765,4 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef CHARACTER_MODULE_H_
|
||||
#define CHARACTER_MODULE_H_
|
||||
#include <flecs.h>
|
||||
#include <Ogre.h>
|
||||
#include "goap.h"
|
||||
namespace ECS
|
||||
{
|
||||
@@ -34,17 +35,6 @@ struct CharacterLocation {
|
||||
struct CharacterConf {
|
||||
Ogre::String type;
|
||||
};
|
||||
struct CharacterBody {
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
btCompoundShape *mCollisionShape;
|
||||
Ogre::Bullet::KinematicMotionSimple *mController;
|
||||
bool checkGround;
|
||||
bool checkGroundResult;
|
||||
};
|
||||
struct CharacterVelocity {
|
||||
Ogre::Vector3 gvelocity;
|
||||
Ogre::Vector3 velocity;
|
||||
};
|
||||
struct CharacterInActuator {
|
||||
Ogre::String animationState;
|
||||
Vector3 prevMotion;
|
||||
@@ -73,4 +63,4 @@ struct CharacterAIModule {
|
||||
CharacterAIModule(flecs::world &ecs);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define COMPONENTS_H_
|
||||
#include <flecs.h>
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
namespace Ogre
|
||||
{
|
||||
class ImGuiOverlay;
|
||||
@@ -20,7 +19,6 @@ struct GameData {
|
||||
};
|
||||
struct EngineData {
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
Ogre::Bullet::DynamicsWorld *mWorld;
|
||||
float delta;
|
||||
float startupDelay;
|
||||
int width;
|
||||
@@ -75,24 +73,15 @@ struct App {
|
||||
std::vector<OgreBites::InputListener *> listeners;
|
||||
};
|
||||
struct CollisionShape {
|
||||
btCollisionShape *shape;
|
||||
void *shape;
|
||||
};
|
||||
struct InWater {};
|
||||
struct TerrainReady {};
|
||||
struct WaterAlmostReady {};
|
||||
struct WaterReady {};
|
||||
struct GroundCheckReady {};
|
||||
struct ParentSlot {
|
||||
flecs::entity parent_e;
|
||||
Ogre::String slot_name;
|
||||
bool activated;
|
||||
};
|
||||
struct ObjectSlots {
|
||||
std::unordered_map<Ogre::String,
|
||||
std::pair<Ogre::String, Ogre::SceneNode *> >
|
||||
slots;
|
||||
};
|
||||
struct Body2Entity {
|
||||
std::unordered_map<btCollisionObject *, flecs::entity> entities;
|
||||
/* std::unordered_map<btCollisionObject *, flecs::entity> entities; */
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +1,14 @@
|
||||
#include <iostream>
|
||||
#include <OgreBullet.h>
|
||||
#include <OgreMeshManager.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "LuaData.h"
|
||||
#include "EventTriggerModule.h"
|
||||
|
||||
struct TriggerBody {
|
||||
void *data;
|
||||
};
|
||||
#if 0
|
||||
struct TriggerBody {
|
||||
btPairCachingGhostObject *mBody;
|
||||
btCylinderShape *shape;
|
||||
@@ -58,10 +61,22 @@ struct DeepPenetrationContactResultCallback : public btManifoldResult {
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<EventTriggerModule>();
|
||||
ecs.component<EventTrigger>();
|
||||
ecs.component<EventTriggerData>();
|
||||
ecs.observer<const EngineData, const EventTrigger>("CreateTrigger")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &trigger) {
|
||||
e.set<EventTriggerData>({});
|
||||
ECS::get<LuaBase>().mLua->call_handler(
|
||||
"actuator_created", e, e);
|
||||
});
|
||||
#if 0
|
||||
ecs.component<EventTriggerData>();
|
||||
ecs.component<TriggerBody>().on_add([](flecs::entity e,
|
||||
TriggerBody &body) {
|
||||
@@ -311,4 +326,5 @@ ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
|
||||
it++;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "BoatModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "world-build.h"
|
||||
|
||||
namespace ECS
|
||||
@@ -27,6 +28,7 @@ void setup_minimal()
|
||||
ecs.import <GameWorldModule>();
|
||||
ecs.component<InWater>();
|
||||
ecs.component<WaterReady>().add(flecs::Singleton);
|
||||
ecs.component<WaterAlmostReady>().add(flecs::Singleton);
|
||||
ecs.component<GroundCheckReady>().add(flecs::Singleton);
|
||||
ecs.component<App>()
|
||||
.on_add([](App &app) {
|
||||
@@ -37,26 +39,24 @@ void setup_minimal()
|
||||
.add(flecs::Singleton);
|
||||
/* lots of things depend on it */
|
||||
ecs.component<TerrainReady>().add(flecs::Singleton);
|
||||
ecs.component<ParentSlot>();
|
||||
ecs.component<ObjectSlots>();
|
||||
ecs.component<Body2Entity>().add(flecs::Singleton);
|
||||
}
|
||||
void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
Ogre::SceneNode *cameraNode, Ogre::Camera *camera,
|
||||
Ogre::RenderWindow *window)
|
||||
void setup(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
|
||||
Ogre::Camera *camera, Ogre::RenderWindow *window)
|
||||
{
|
||||
std::cout << "Setup GameData\n";
|
||||
setup_minimal();
|
||||
ecs.import <WaterModule>();
|
||||
ecs.component<RenderWindow>().add(flecs::Singleton);
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.import <TerrainModule>();
|
||||
ecs.import <BoatModule>();
|
||||
ecs.import <PhysicsModule>();
|
||||
ecs.import <WaterModule>();
|
||||
ecs.import <SunModule>();
|
||||
ecs.import <TerrainModule>();
|
||||
ecs.import <GUIModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <LuaModule>();
|
||||
ecs.import <WorldMapModule>();
|
||||
ecs.import <LuaModule>();
|
||||
ecs.import <BoatModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <CharacterAnimationModule>();
|
||||
|
||||
ecs.system<EngineData>("UpdateDelta")
|
||||
@@ -89,9 +89,8 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
std::cout << "ground check ready\n";
|
||||
#endif
|
||||
});
|
||||
ecs.set<EngineData>({ scnMgr, world, 0.0f, 5.0f,
|
||||
(int)window->getWidth(), (int)window->getHeight(),
|
||||
false });
|
||||
ecs.set<EngineData>({ scnMgr, 0.0f, 5.0f, (int)window->getWidth(),
|
||||
(int)window->getHeight(), false });
|
||||
ecs.set<Camera>({ cameraNode, camera, false });
|
||||
ecs.add<GameData>();
|
||||
ecs.add<Input>();
|
||||
@@ -105,7 +104,7 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
nullptr,
|
||||
false,
|
||||
{ 0, 0, 0 } });
|
||||
ecs.set<Body2Entity>({});
|
||||
// ecs.set<Body2Entity>({});
|
||||
std::cout << "Setup GameData done\n";
|
||||
|
||||
/* Create player */
|
||||
@@ -129,4 +128,4 @@ bool Vector3::zeroLength() const
|
||||
float l = x * x + y * y + z * z;
|
||||
return (l < 1e-06 * 1e-06);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#ifndef GAMEDATA_H
|
||||
#define GAMEDATA_H
|
||||
#include <OgreBullet.h>
|
||||
#include <flecs.h>
|
||||
namespace ECS
|
||||
{
|
||||
extern flecs::entity player;
|
||||
void setup_minimal();
|
||||
void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
|
||||
Ogre::SceneNode *cameraNode, Ogre::Camera *camera,
|
||||
Ogre::RenderWindow *window);
|
||||
void setup(Ogre::SceneManager *scnMgr, Ogre::SceneNode *cameraNode,
|
||||
Ogre::Camera *camera, Ogre::RenderWindow *window);
|
||||
void update(float delta);
|
||||
flecs::world get();
|
||||
template <class T> const T &get()
|
||||
|
||||
@@ -2,15 +2,67 @@
|
||||
#include "GameData.h"
|
||||
#include "Components.h"
|
||||
#include "GUIModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "CharacterAnimationModule.h"
|
||||
#include "BoatModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "SlotsModule.h"
|
||||
#include "world-build.h"
|
||||
#include "LuaData.h"
|
||||
|
||||
#include "luaaa.hpp"
|
||||
extern "C" {
|
||||
int luaopen_lpeg(lua_State *L);
|
||||
}
|
||||
struct FooPosition {
|
||||
Ogre::Vector3 value;
|
||||
Ogre::Vector3 &get()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
namespace luaaa
|
||||
{
|
||||
template <> struct LuaStack<FooPosition> {
|
||||
inline static FooPosition get(lua_State *L, int idx)
|
||||
{
|
||||
FooPosition result;
|
||||
if (lua_istable(L, idx)) {
|
||||
lua_pushnil(L);
|
||||
while (0 != lua_next(L, idx)) {
|
||||
const int top = lua_gettop(L);
|
||||
const char *name =
|
||||
LuaStack<const char *>::get(L, top - 1);
|
||||
if (strncmp(name, "x", 1) == 0)
|
||||
result.value.x =
|
||||
LuaStack<float>::get(L, top);
|
||||
else if (strncmp(name, "y", 1) == 0)
|
||||
result.value.y =
|
||||
LuaStack<float>::get(L, top);
|
||||
else if (strncmp(name, "z", 1) == 0)
|
||||
result.value.z =
|
||||
LuaStack<float>::get(L, top);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
inline static void put(lua_State *L, const FooPosition &v)
|
||||
{
|
||||
lua_newtable(L);
|
||||
LuaStack<const char *>::put(L, "x");
|
||||
LuaStack<float>::put(L, v.value.x);
|
||||
lua_rawset(L, -3);
|
||||
LuaStack<const char *>::put(L, "y");
|
||||
LuaStack<float>::put(L, v.value.y);
|
||||
lua_rawset(L, -3);
|
||||
LuaStack<const char *>::put(L, "z");
|
||||
LuaStack<float>::put(L, v.value.z);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
namespace ECS
|
||||
{
|
||||
@@ -194,6 +246,46 @@ LuaData::LuaData()
|
||||
#endif
|
||||
installLibraryLoader(L);
|
||||
lua_pop(L, 1);
|
||||
|
||||
#if 0
|
||||
luaaa::LuaClass<Ogre::Vector3> luaVector3(L, "Vector3");
|
||||
luaVector3.ctor<float, float, float>();
|
||||
luaVector3.get("x", [](Ogre::Vector3 &v) -> float { return v.x; });
|
||||
luaVector3.set("x", [](Ogre::Vector3 &v, float value) -> void {
|
||||
v.x = value;
|
||||
});
|
||||
luaVector3.get("y", [](Ogre::Vector3 &v) -> float { return v.y; });
|
||||
luaVector3.set("y", [](Ogre::Vector3 &v, float value) -> void {
|
||||
v.y = value;
|
||||
});
|
||||
luaVector3.get("z", [](Ogre::Vector3 &v) -> float { return v.z; });
|
||||
luaVector3.set("z", [](Ogre::Vector3 &v, float value) -> void {
|
||||
v.z = value;
|
||||
});
|
||||
luaVector3.fun("squaredLength", &Ogre::Vector3::squaredLength);
|
||||
luaVector3.fun("length", &Ogre::Vector3::length);
|
||||
luaVector3.fun("squaredDistance", &Ogre::Vector3::squaredDistance);
|
||||
luaVector3.fun("distance", &Ogre::Vector3::distance);
|
||||
#endif
|
||||
luaaa::LuaModule luaECS(L, "_ecs");
|
||||
luaECS.fun("position", [](int id) -> FooPosition {
|
||||
#if 0
|
||||
flecs::entity e = idmap.get_entity(id);
|
||||
if (e.has<CharacterBase>()) {
|
||||
const CharacterBase &cb = e.get<CharacterBase>();
|
||||
return cb.mBodyNode->_getDerivedPosition();
|
||||
} else if (e.has<BoatBase>()) {
|
||||
const BoatBase &boat = e.get<BoatBase>();
|
||||
return boat.mNode->_getDerivedPosition();
|
||||
} else if (e.has<EventTrigger>()) {
|
||||
const EventTrigger &trigger = e.get<EventTrigger>();
|
||||
return trigger.position;
|
||||
} else
|
||||
return Ogre::Vector3(0, 0, 0);
|
||||
#endif
|
||||
return FooPosition();
|
||||
});
|
||||
|
||||
lua_pushcfunction(L, [](lua_State *L) -> int {
|
||||
OgreAssert(false, "Crash function called");
|
||||
return 0;
|
||||
@@ -567,7 +659,9 @@ LuaData::LuaData()
|
||||
Ogre::String slot = lua_tostring(L, 3);
|
||||
flecs::entity parent_e = idmap.get_entity(parent);
|
||||
flecs::entity object_e = idmap.get_entity(object);
|
||||
object_e.set<ParentSlot>({ parent_e, slot, false });
|
||||
if (!object_e.has<CharacterDisablePhysics>())
|
||||
object_e.add<CharacterDisablePhysics>();
|
||||
object_e.set<ParentSlot>({ parent_e, slot });
|
||||
return 0;
|
||||
});
|
||||
lua_setglobal(L, "ecs_set_slot");
|
||||
@@ -737,6 +831,7 @@ void LuaData::lateSetup()
|
||||
LuaModule::LuaModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<LuaModule>();
|
||||
ecs.import <SlotsModule>();
|
||||
ecs.component<LuaChildEventTrigger>();
|
||||
ecs.component<LuaBase>()
|
||||
.on_add([](LuaBase &lua) {
|
||||
|
||||
535
src/gamedata/PhysicsModule.cpp
Normal file
535
src/gamedata/PhysicsModule.cpp
Normal file
@@ -0,0 +1,535 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Physics/Body/BodyID.h>
|
||||
#include <Jolt/Physics/Character/CharacterBase.h>
|
||||
#include <Jolt/Physics/Character/Character.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
|
||||
#include <Jolt/Physics/Body/BodyLock.h>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "WaterModule.h"
|
||||
#include "BoatModule.h"
|
||||
#include "EventTriggerModule.h"
|
||||
#include "physics.h"
|
||||
#include "loader.h"
|
||||
#include "PhysicsModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
struct PhysicsShape {
|
||||
JPH::ShapeRefC shape;
|
||||
};
|
||||
struct ConvexHull {};
|
||||
struct WaterBody {
|
||||
std::set<JPH::BodyID> inWater;
|
||||
bool isInWater(const JPH::BodyID &id) const;
|
||||
};
|
||||
struct TriggerBody {
|
||||
void *foo;
|
||||
};
|
||||
|
||||
PhysicsModule::PhysicsModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<PhysicsModule>();
|
||||
ecs.import <EventTriggerModule>();
|
||||
ecs.import <BoatModule>();
|
||||
flecs::entity PhysicsPreUpdate =
|
||||
ecs.entity().add(flecs::Phase).depends_on(flecs::OnUpdate);
|
||||
flecs::entity PhysicsUpdate =
|
||||
ecs.entity().add(flecs::Phase).depends_on(PhysicsPreUpdate);
|
||||
flecs::entity PhysicsPostUpdate =
|
||||
ecs.entity().add(flecs::Phase).depends_on(PhysicsUpdate);
|
||||
ecs.component<Physics>().add(flecs::Singleton);
|
||||
ecs.component<JPH::BodyID>().member<uint32_t>("mID");
|
||||
/* for terrain */
|
||||
ecs.component<PhysicsBody>();
|
||||
ecs.component<PhysicsShape>();
|
||||
ecs.component<PhysicsNode>();
|
||||
ecs.component<PhysicsMeshName>();
|
||||
ecs.component<PhysicsMeshPtr>();
|
||||
ecs.component<PhysicsHeightfieldData>();
|
||||
|
||||
ecs.component<CharacterBody>();
|
||||
ecs.component<TriggerBody>();
|
||||
ecs.component<CharacterVelocity>();
|
||||
ecs.component<WaterBody>().add(flecs::Singleton);
|
||||
ecs.system<const EngineData, const Camera>("physics_init")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.without<Physics>()
|
||||
.each([&](const EngineData &e, const Camera &c) {
|
||||
Physics &ph = ECS::get().ensure<Physics>();
|
||||
ph.physics = new JoltPhysicsWrapper(e.mScnMgr,
|
||||
c.mCameraNode);
|
||||
ECS::modified<Physics>();
|
||||
});
|
||||
#if 0
|
||||
ecs.system<PhysicsBody>("create_body")
|
||||
.kind(flecs::OnUpdate)
|
||||
.without<JPH::BodyID>()
|
||||
.each([&](flecs::entity e, PhysicsBody &rb) {
|
||||
JPH::BodyID id =
|
||||
JoltPhysicsWrapper::getSingleton().createBody(
|
||||
rb.shape.get(), rb.node,
|
||||
(JPH::EMotionType)rb.motion,
|
||||
(JPH::ObjectLayer)rb.layer);
|
||||
e.set<JPH::BodyID>(id);
|
||||
});
|
||||
#endif
|
||||
ecs.system<EngineData, Physics>("physics_update")
|
||||
.kind(PhysicsUpdate)
|
||||
.each([&](EngineData &e, Physics &ph) {
|
||||
ph.physics->update(e.delta);
|
||||
});
|
||||
ecs.observer<const EngineData, PhysicsMeshName>(
|
||||
"create_shape_mesh_name")
|
||||
.event(flecs::OnSet)
|
||||
.without<PhysicsShape>()
|
||||
.with<Physics>()
|
||||
.write<PhysicsShape>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
PhysicsMeshName &name) {
|
||||
Ogre::DefaultHardwareBufferManagerBase dmgr;
|
||||
Ogre::MeshPtr mesh =
|
||||
Ogre::MeshManager::getSingleton().getByName(
|
||||
name.meshName);
|
||||
mesh->setHardwareBufferManager(&dmgr);
|
||||
mesh->load();
|
||||
JPH::ShapeRefC shape =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.createMeshShape(mesh);
|
||||
PhysicsShape &s = e.ensure<PhysicsShape>();
|
||||
s.shape = shape;
|
||||
e.modified<PhysicsShape>();
|
||||
});
|
||||
ecs.observer<const EngineData, PhysicsMeshPtr>("create_shape_mesh_ptr")
|
||||
.event(flecs::OnSet)
|
||||
.without<PhysicsShape>()
|
||||
.with<Physics>()
|
||||
.write<PhysicsShape>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
PhysicsMeshPtr &meshPtr) {
|
||||
Ogre::DefaultHardwareBufferManager dmgr;
|
||||
Ogre::MeshPtr mesh = meshPtr.mesh;
|
||||
if (!mesh->isLoaded()) {
|
||||
mesh->setHardwareBufferManager(&dmgr);
|
||||
mesh->load();
|
||||
}
|
||||
JPH::ShapeRefC shape =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.createMeshShape(mesh);
|
||||
PhysicsShape &s = e.ensure<PhysicsShape>();
|
||||
s.shape = shape;
|
||||
e.modified<PhysicsShape>();
|
||||
});
|
||||
ecs.observer<const EngineData, PhysicsHeightfieldData>(
|
||||
"create_shape_heightfield")
|
||||
.event(flecs::OnSet)
|
||||
.without<PhysicsShape>()
|
||||
.with<Physics>()
|
||||
.write<PhysicsShape>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
PhysicsHeightfieldData &hfd) {
|
||||
JPH::ShapeRefC shape =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.createHeightfieldShape(
|
||||
hfd.samples, hfd.offset,
|
||||
hfd.scale, hfd.sampleCount);
|
||||
PhysicsShape &s = e.ensure<PhysicsShape>();
|
||||
s.shape = shape;
|
||||
e.modified<PhysicsShape>();
|
||||
delete hfd.samples;
|
||||
e.remove<PhysicsHeightfieldData>();
|
||||
});
|
||||
#if 1
|
||||
ecs.observer<const EngineData, const PhysicsShape, const PhysicsNode,
|
||||
const PhysicsBody>("create_body_from_shape")
|
||||
.event(flecs::OnSet)
|
||||
.without<JPH::BodyID>()
|
||||
.with<Physics>()
|
||||
.write<PhysicsShape>()
|
||||
.write<JPH::BodyID>()
|
||||
.each([&](flecs::entity e, const EngineData &eng,
|
||||
const PhysicsShape &shape, const PhysicsNode &node,
|
||||
const PhysicsBody &body) {
|
||||
JPH::BodyID id =
|
||||
JoltPhysicsWrapper::getSingleton().createBody(
|
||||
shape.shape.GetPtr(), 0.0f, node.node,
|
||||
(JPH::EMotionType)body.motion,
|
||||
(JPH::ObjectLayer)body.layer);
|
||||
e.set<JPH::BodyID>(id);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
id, JPH::EActivation::Activate);
|
||||
});
|
||||
#endif
|
||||
ecs.observer<const JPH::BodyID>("remove_body")
|
||||
.event(flecs::OnRemove)
|
||||
.each([&](flecs::entity e, const JPH::BodyID &id) {
|
||||
JoltPhysicsWrapper::getSingleton().removeBody(id);
|
||||
JoltPhysicsWrapper::getSingleton().destroyBody(id);
|
||||
std::cout << "body destroyed" << std::endl;
|
||||
});
|
||||
ecs.observer<const EngineData, const CharacterBase>("SetupCharacterPh")
|
||||
.event(flecs::OnSet)
|
||||
.with<Character>()
|
||||
.without<CharacterBody>()
|
||||
.write<CharacterBody>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &base) {
|
||||
CharacterBody &b = e.ensure<CharacterBody>();
|
||||
b.ch.reset(JoltPhysicsWrapper::getSingleton()
|
||||
.createCharacter(base.mBodyNode,
|
||||
1.75f, 0.23f));
|
||||
if (!e.has<CharacterDisablePhysics>())
|
||||
static_cast<JPH::Character *>(b.ch.get())
|
||||
->AddToPhysicsSystem(
|
||||
JPH::EActivation::Activate);
|
||||
e.modified<CharacterBody>();
|
||||
});
|
||||
ecs.observer<const EngineData, const EventTrigger>(
|
||||
"CreateTriggerPhysics")
|
||||
.event(flecs::OnSet)
|
||||
.without<JPH::BodyID>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &trigger) {
|
||||
JPH::ShapeRefC shape =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.createCylinderShape(trigger.halfheight,
|
||||
trigger.radius);
|
||||
JPH::BodyID id =
|
||||
JoltPhysicsWrapper::getSingleton().createSensor(
|
||||
shape.GetPtr(), trigger.node,
|
||||
JPH::EMotionType::Kinematic,
|
||||
Layers::MOVING);
|
||||
e.set<JPH::BodyID>(id);
|
||||
// JoltPhysicsWrapper::getSingleton().setDebugDraw(true);
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
id, JPH::EActivation::Activate);
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const EventTrigger, const JPH::BodyID>(
|
||||
"UpdateTriggerPhysicsPre")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<WaterBody>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &trigger, const JPH::BodyID &id) {
|
||||
/* FIXME: update positions for triggers, probably need to move somewhere */
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.setPositionAndRotation(
|
||||
id, trigger.node->_getDerivedPosition(),
|
||||
trigger.node->_getDerivedOrientation());
|
||||
#if 0
|
||||
std::cout << trigger.node->_getDerivedPosition() << " "
|
||||
<< trigger.node->getPosition() << " "
|
||||
<< trigger.node->getParent()->getName()
|
||||
<< ": " << trigger.node->getName()
|
||||
<< std::endl;
|
||||
// OgreAssert(false, "update triggers");
|
||||
#endif
|
||||
});
|
||||
ecs.system<const EngineData, const EventTrigger, const JPH::BodyID>(
|
||||
"UpdateTriggerPhysicsPost")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<WaterBody>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const EventTrigger &trigger, const JPH::BodyID &id) {
|
||||
/* FIXME: update positions for triggers, probably need to move somewhere */
|
||||
Ogre::Vector3 position;
|
||||
Ogre::Quaternion rotation;
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.getPositionAndRotation(id, position, rotation);
|
||||
trigger.node->_setDerivedPosition(position);
|
||||
trigger.node->_setDerivedOrientation(rotation);
|
||||
});
|
||||
#endif
|
||||
ecs.system<const EngineData>("init_water")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterAlmostReady>()
|
||||
.without<WaterBody>()
|
||||
.each([this](const EngineData &eng) {
|
||||
ECS::get().set<WaterBody>({});
|
||||
});
|
||||
ecs.system<const EngineData, WaterBody>("update_water")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterAlmostReady>()
|
||||
.each([this](const EngineData &eng, WaterBody &body) {
|
||||
const WaterSurface &water = ECS::get<WaterSurface>();
|
||||
JoltPhysicsWrapper::getSingleton().broadphaseQuery(
|
||||
eng.delta,
|
||||
water.mWaterNode->_getDerivedPosition(),
|
||||
body.inWater);
|
||||
#if 0
|
||||
for (JPH::BodyID inBodyID : body.inWater) {
|
||||
if (JoltPhysicsWrapper::getSingleton().isActive(
|
||||
inBodyID)) {
|
||||
float my =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.getPosition(inBodyID)
|
||||
.y;
|
||||
float myv =
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.getLinearVelocity(
|
||||
inBodyID)
|
||||
.y;
|
||||
float b = 1.0f;
|
||||
float drag = 0.5f;
|
||||
float adrag = 0.05f;
|
||||
float level = -1.3f;
|
||||
float mdec = 1.0f;
|
||||
float minc = 1.0f;
|
||||
float h = -my + level;
|
||||
if (h < 0)
|
||||
h = 0;
|
||||
if (my < level - 0.1f)
|
||||
b *= 1.1f * (1.0f + 1.2f * h);
|
||||
else if (my > level + 0.1f) {
|
||||
b *= 0.8f;
|
||||
if (myv > 0.1f)
|
||||
b *= 0.9f;
|
||||
if (my > level + 0.4f)
|
||||
b *= 0.5f;
|
||||
}
|
||||
if (myv < 0.0f)
|
||||
drag = 0.7f;
|
||||
JoltPhysicsWrapper::getSingleton().applyBuoyancyImpulse(
|
||||
inBodyID,
|
||||
water.mWaterNode->_getDerivedPosition() -
|
||||
Ogre::Vector3(0, 0.1f,
|
||||
0),
|
||||
Ogre::Vector3::UNIT_Y, b, drag,
|
||||
adrag, Ogre::Vector3::ZERO,
|
||||
eng.delta);
|
||||
// std::cout << b << std::endl;
|
||||
#if 0
|
||||
std::cout << "addHit: "
|
||||
<< JoltPhysics::convert(
|
||||
body.GetPosition())
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ECS::get().add<WaterReady>();
|
||||
});
|
||||
ecs.system<const JPH::BodyID, const WaterBody>("update_water_status1")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<InWater>()
|
||||
.each([this](flecs::entity e, const JPH::BodyID &id,
|
||||
const WaterBody &body) {
|
||||
if (!body.isInWater(id))
|
||||
e.remove<InWater>();
|
||||
});
|
||||
ecs.system<const JPH::BodyID, const WaterBody>("update_water_status2")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.without<InWater>()
|
||||
.each([this](flecs::entity e, const JPH::BodyID &id,
|
||||
const WaterBody &body) {
|
||||
if (body.isInWater(id))
|
||||
e.add<InWater>();
|
||||
});
|
||||
ecs.system<const CharacterBody, const WaterBody>(
|
||||
"update_water_character1")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<InWater>()
|
||||
.each([this](flecs::entity e, const CharacterBody &ch,
|
||||
const WaterBody &body) {
|
||||
JPH::Character *chptr =
|
||||
static_cast<JPH::Character *>(ch.ch.get());
|
||||
if (!body.isInWater(chptr->GetBodyID()))
|
||||
e.remove<InWater>();
|
||||
});
|
||||
ecs.system<const CharacterBody, const WaterBody>(
|
||||
"update_water_character2")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.without<InWater>()
|
||||
.each([this](flecs::entity e, const CharacterBody &ch,
|
||||
const WaterBody &body) {
|
||||
JPH::Character *chptr =
|
||||
static_cast<JPH::Character *>(ch.ch.get());
|
||||
if (body.isInWater(chptr->GetBodyID()))
|
||||
e.add<InWater>();
|
||||
});
|
||||
ecs.system<const EngineData, const BoatBase, const WaterBody,
|
||||
const JPH::BodyID>("update_water_boat_enable")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat, const WaterBody &body,
|
||||
const JPH::BodyID &id) {
|
||||
if (!JoltPhysicsWrapper::getSingleton().isAdded(id))
|
||||
JoltPhysicsWrapper::getSingleton().addBody(
|
||||
id, JPH::EActivation::Activate);
|
||||
});
|
||||
ecs.system<const EngineData, const BoatBase, const WaterBody,
|
||||
const JPH::BodyID>("update_water_boat_activation")
|
||||
.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) {
|
||||
if (!JoltPhysicsWrapper::getSingleton().isActive(id))
|
||||
JoltPhysicsWrapper::getSingleton().activate(id);
|
||||
});
|
||||
ecs.system<const EngineData, const BoatBase, const WaterBody,
|
||||
const JPH::BodyID>("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 WaterSurface &water = ECS::get<WaterSurface>();
|
||||
float b = 1.0f, drag = 0.5f, adrag = 0.5f;
|
||||
float level = 0.1f;
|
||||
float my = JoltPhysicsWrapper::getSingleton()
|
||||
.getPosition(id)
|
||||
.y;
|
||||
float myv = JoltPhysicsWrapper::getSingleton()
|
||||
.getLinearVelocity(id)
|
||||
.y;
|
||||
#if 0
|
||||
if (my < level && myv < 0)
|
||||
b = 10.0f;
|
||||
else if (my > level && myv > 0)
|
||||
b = 0.8f;
|
||||
#endif
|
||||
if (my < level)
|
||||
b = 1.7f;
|
||||
else if (my > level)
|
||||
b = 0.9f;
|
||||
// std::cout << my << std::endl;
|
||||
JoltPhysicsWrapper::getSingleton().applyBuoyancyImpulse(
|
||||
id, water.mWaterNode->_getDerivedPosition(),
|
||||
Ogre::Vector3::UNIT_Y, b, drag, adrag,
|
||||
Ogre::Vector3::ZERO, eng.delta);
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, const WaterBody>(
|
||||
"update_water_character_buoyancy")
|
||||
.kind(PhysicsPreUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.with<InWater>()
|
||||
.without<CharacterDisablePhysics>()
|
||||
.with<CharacterBuoyancy>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBody &ch, const WaterBody &body) {
|
||||
JPH::Character *chptr =
|
||||
static_cast<JPH::Character *>(ch.ch.get());
|
||||
JPH::BodyID id = chptr->GetBodyID();
|
||||
if (JoltPhysicsWrapper::getSingleton().isActive(id)) {
|
||||
const WaterSurface &water =
|
||||
ECS::get<WaterSurface>();
|
||||
float my = JoltPhysicsWrapper::getSingleton()
|
||||
.getPosition(id)
|
||||
.y;
|
||||
float myv = JoltPhysicsWrapper::getSingleton()
|
||||
.getLinearVelocity(id)
|
||||
.y;
|
||||
float b = 1.0f;
|
||||
float drag = 0.5f;
|
||||
float adrag = 0.05f;
|
||||
float level = -1.3f;
|
||||
float mdec = 1.0f;
|
||||
float minc = 1.0f;
|
||||
float h = -my + level;
|
||||
if (h < 0)
|
||||
h = 0;
|
||||
if (my < level - 0.1f)
|
||||
b *= 1.1f * (1.0f + 1.2f * h);
|
||||
else if (my > level + 0.1f) {
|
||||
b *= 0.8f;
|
||||
if (myv > 0.1f)
|
||||
b *= 0.9f;
|
||||
if (my > level + 0.4f)
|
||||
b *= 0.5f;
|
||||
}
|
||||
if (myv < 0.0f)
|
||||
drag = 0.7f;
|
||||
JoltPhysicsWrapper::getSingleton()
|
||||
.applyBuoyancyImpulse(
|
||||
id,
|
||||
water.mWaterNode
|
||||
->_getDerivedPosition(),
|
||||
Ogre::Vector3::UNIT_Y, b, drag,
|
||||
adrag, Ogre::Vector3::ZERO,
|
||||
eng.delta);
|
||||
// std::cout << b << std::endl;
|
||||
#if 0
|
||||
std::cout << "addHit: "
|
||||
<< JoltPhysics::convert(
|
||||
body.GetPosition())
|
||||
<< std::endl;
|
||||
#endif
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBody, CharacterVelocity>(
|
||||
"HandleVelocity")
|
||||
.kind(PhysicsPostUpdate)
|
||||
.with<TerrainReady>()
|
||||
.with<WaterReady>()
|
||||
.without<CharacterDisablePhysics>()
|
||||
.without<CharacterUpdatePhysicsState>()
|
||||
.each([this](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBody &body, CharacterVelocity &gr) {
|
||||
Ogre::Vector3 v = gr.velocity;
|
||||
v.y = 0.0f;
|
||||
JPH::Character *ch =
|
||||
static_cast<JPH::Character *>(body.ch.get());
|
||||
if (!e.has<InWater>()) {
|
||||
if (ch->IsSupported()) {
|
||||
v.y = gr.velocity.y;
|
||||
gr.gvelocity.y = 0;
|
||||
} else {
|
||||
v.y = gr.velocity.y;
|
||||
v.y += gr.gvelocity.y;
|
||||
gr.gvelocity.y += -9.8f * eng.delta;
|
||||
}
|
||||
} else {
|
||||
v = JoltPhysics::convert(
|
||||
ch->GetLinearVelocity());
|
||||
v.x = gr.velocity.x;
|
||||
v.z = gr.velocity.z;
|
||||
}
|
||||
// gr.velocity.y = 0.0f;
|
||||
// v.y = 0.0f;
|
||||
ch->SetLinearVelocity(JoltPhysics::convert(v));
|
||||
gr.velocity = Ogre::Vector3::ZERO;
|
||||
});
|
||||
}
|
||||
flecs::entity PhysicsModule::createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
float *samples,
|
||||
const Ogre::Vector3 &offset,
|
||||
const Ogre::Vector3 &scale,
|
||||
int sampleCount)
|
||||
{
|
||||
flecs::entity e = ECS::get().entity();
|
||||
e.set<PhysicsHeightfieldData>({ samples, offset, scale, sampleCount });
|
||||
e.set<PhysicsBody>({ (uint32_t)JPH::EMotionType::Static,
|
||||
(uint32_t)Layers::NON_MOVING });
|
||||
e.set<PhysicsNode>({ node });
|
||||
|
||||
return e;
|
||||
}
|
||||
bool WaterBody::isInWater(const JPH::BodyID &id) const
|
||||
{
|
||||
return inWater.find(id) != inWater.end();
|
||||
}
|
||||
}
|
||||
57
src/gamedata/PhysicsModule.h
Normal file
57
src/gamedata/PhysicsModule.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef _PHYSICS_MODULE_H_
|
||||
#define _PHYSICS_MODULE_H_
|
||||
#include <flecs.h>
|
||||
class JoltPhysicsWrapper;
|
||||
namespace JPH
|
||||
{
|
||||
class Shape;
|
||||
class CharacterBase;
|
||||
}
|
||||
namespace Ogre
|
||||
{
|
||||
class TerrainGroup;
|
||||
}
|
||||
namespace ECS
|
||||
{
|
||||
struct Physics {
|
||||
JoltPhysicsWrapper *physics;
|
||||
};
|
||||
struct PhysicsNode {
|
||||
Ogre::SceneNode *node;
|
||||
};
|
||||
struct PhysicsMeshName {
|
||||
Ogre::String meshName;
|
||||
};
|
||||
struct PhysicsMeshPtr {
|
||||
Ogre::MeshPtr mesh;
|
||||
};
|
||||
struct PhysicsBody {
|
||||
uint32_t motion;
|
||||
uint32_t layer;
|
||||
};
|
||||
struct CharacterBody {
|
||||
std::shared_ptr<JPH::CharacterBase> ch;
|
||||
};
|
||||
struct BoatBody {
|
||||
void *tmp;
|
||||
};
|
||||
struct PhysicsHeightfieldData {
|
||||
const float *samples;
|
||||
Ogre::Vector3 offset;
|
||||
Ogre::Vector3 scale;
|
||||
int sampleCount;
|
||||
};
|
||||
struct CharacterVelocity {
|
||||
Ogre::Vector3 gvelocity;
|
||||
Ogre::Vector3 velocity;
|
||||
};
|
||||
struct PhysicsModule {
|
||||
PhysicsModule(flecs::world &ecs);
|
||||
static flecs::entity createTerrainChunkBody(Ogre::SceneNode *node,
|
||||
float *samples,
|
||||
const Ogre::Vector3 &offset,
|
||||
const Ogre::Vector3 &scale,
|
||||
int sampleCount);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
153
src/gamedata/SlotsModule.cpp
Normal file
153
src/gamedata/SlotsModule.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <iostream>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "BoatModule.h"
|
||||
#include "SlotsModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
SlotsModule::SlotsModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<SlotsModule>();
|
||||
ecs.import <CharacterModule>();
|
||||
ecs.component<ParentSlot>();
|
||||
ecs.component<ParentSlotData>();
|
||||
ecs.component<ObjectSlots>();
|
||||
ecs.observer<const EngineData, const BoatBase>("CreateBoatSlots")
|
||||
.event(flecs::OnSet)
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const BoatBase &boat) {
|
||||
int i;
|
||||
std::vector<Ogre::Node *> slots =
|
||||
boat.mNode->getChildren();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any =
|
||||
static_cast<Ogre::SceneNode *>(slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(any);
|
||||
std::cout << "child type: " << obj_type
|
||||
<< std::endl;
|
||||
}
|
||||
if (slots.size() > 0) {
|
||||
ObjectSlots &vs = e.ensure<ObjectSlots>();
|
||||
for (i = 0; i < slots.size(); i++) {
|
||||
Ogre::Any any =
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("type");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_type =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
any = static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
->getUserObjectBindings()
|
||||
.getUserAny("name");
|
||||
if (!any.has_value())
|
||||
continue;
|
||||
Ogre::String obj_name =
|
||||
Ogre::any_cast<Ogre::String>(
|
||||
any);
|
||||
vs.slots[obj_name] = {
|
||||
obj_type,
|
||||
static_cast<Ogre::SceneNode *>(
|
||||
slots[i])
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot,
|
||||
ParentSlotData>("UpdatePhysics2a")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterDisablePhysics>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot,
|
||||
ParentSlotData &psdata) {
|
||||
if (slot.slot_name == "") {
|
||||
e.remove<ParentSlot>();
|
||||
e.remove<ParentSlotData>();
|
||||
}
|
||||
|
||||
if (slot.parent_e.has<ObjectSlots>()) {
|
||||
const ObjectSlots &slots =
|
||||
slot.parent_e.get<ObjectSlots>();
|
||||
if (slots.slots.find(slot.slot_name) ==
|
||||
slots.slots.end()) {
|
||||
// invalid setting
|
||||
e.remove<ParentSlot>();
|
||||
return;
|
||||
}
|
||||
Ogre::SceneNode *slot_base =
|
||||
slots.slots.at(slot.slot_name).second;
|
||||
#if 0
|
||||
ch.mBodyNode->getParent()->removeChild(
|
||||
ch.mBodyNode);
|
||||
#endif
|
||||
slot_base->addChild(ch.mBodyNode);
|
||||
Ogre::Vector3 position =
|
||||
slot_base->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
slot_base->_getDerivedOrientation();
|
||||
ch.mBodyNode->_setDerivedPosition(position);
|
||||
ch.mBodyNode->_setDerivedOrientation(
|
||||
orientation);
|
||||
psdata.parent_e = slot.parent_e;
|
||||
psdata.parentNode = slot_base;
|
||||
psdata.slot_name = slot.slot_name;
|
||||
e.remove<ParentSlot>();
|
||||
e.modified<ParentSlotData>();
|
||||
std::cout << "base: " << slot_base->getName();
|
||||
}
|
||||
});
|
||||
ecs.system<const EngineData, const CharacterBase, ParentSlot>(
|
||||
"UpdatePhysics2")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<CharacterDisablePhysics>()
|
||||
.without<ParentSlotData>()
|
||||
.with<WaterReady>()
|
||||
.each([](flecs::entity e, const EngineData &eng,
|
||||
const CharacterBase &ch, ParentSlot &slot) {
|
||||
std::cout << e.name() << std::endl;
|
||||
if (!slot.parent_e.has<ObjectSlots>())
|
||||
return;
|
||||
OgreAssert(slot.parent_e.has<ObjectSlots>(),
|
||||
"parent has no slots");
|
||||
OgreAssert(e.has<Character>(), "not a character");
|
||||
if (slot.parent_e.has<ObjectSlots>()) {
|
||||
const ObjectSlots &slots =
|
||||
slot.parent_e.get<ObjectSlots>();
|
||||
if (slot.slot_name == "")
|
||||
return;
|
||||
if (slots.slots.find(slot.slot_name) ==
|
||||
slots.slots.end()) {
|
||||
// invalid setting
|
||||
e.remove<ParentSlot>();
|
||||
OgreAssert(false, "bad slot");
|
||||
return;
|
||||
}
|
||||
ParentSlotData &psdata =
|
||||
e.ensure<ParentSlotData>();
|
||||
Ogre::SceneNode *slot_base =
|
||||
slots.slots.at(slot.slot_name).second;
|
||||
Ogre::Vector3 position =
|
||||
slot_base->_getDerivedPosition();
|
||||
Ogre::Quaternion orientation =
|
||||
slot_base->_getDerivedOrientation();
|
||||
ch.mBodyNode->_setDerivedPosition(position);
|
||||
ch.mBodyNode->_setDerivedOrientation(
|
||||
orientation);
|
||||
psdata.parent_e = slot.parent_e;
|
||||
psdata.parentNode = slot_base;
|
||||
psdata.slot_name = slot.slot_name;
|
||||
e.remove<ParentSlot>();
|
||||
e.modified<ParentSlotData>();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
25
src/gamedata/SlotsModule.h
Normal file
25
src/gamedata/SlotsModule.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _SLOTS_MODULE_H_
|
||||
#define _SLOTS_MODULE_H_
|
||||
#include <flecs.h>
|
||||
#include <Ogre.h>
|
||||
namespace ECS
|
||||
{
|
||||
struct ParentSlot {
|
||||
flecs::entity parent_e;
|
||||
Ogre::String slot_name;
|
||||
};
|
||||
struct ParentSlotData {
|
||||
Ogre::String slot_name;
|
||||
flecs::entity parent_e;
|
||||
Ogre::SceneNode *parentNode;
|
||||
};
|
||||
struct ObjectSlots {
|
||||
std::unordered_map<Ogre::String,
|
||||
std::pair<Ogre::String, Ogre::SceneNode *> >
|
||||
slots;
|
||||
};
|
||||
struct SlotsModule {
|
||||
SlotsModule(flecs::world &ecs);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <OgreTerrain.h>
|
||||
#include <OgreTerrainGroup.h>
|
||||
@@ -14,6 +13,7 @@
|
||||
#include "Components.h"
|
||||
#include "CharacterModule.h"
|
||||
#include "SunModule.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "TerrainModule.h"
|
||||
|
||||
#define TERRAIN_SIZE 129
|
||||
@@ -173,7 +173,7 @@ class FlatTerrainDefiner
|
||||
: public Ogre::TerrainPagedWorldSection::TerrainDefiner,
|
||||
public Ogre::FrameListener {
|
||||
Ogre::SceneManager *mScnMgr;
|
||||
Ogre::Bullet::DynamicsWorld *mWorld;
|
||||
// Ogre::Bullet::DynamicsWorld *mWorld;
|
||||
struct gen_collider {
|
||||
Ogre::TerrainGroup *group;
|
||||
long x;
|
||||
@@ -182,18 +182,44 @@ class FlatTerrainDefiner
|
||||
std::deque<struct gen_collider> collider_queue;
|
||||
|
||||
public:
|
||||
FlatTerrainDefiner(Ogre::SceneManager *scm,
|
||||
Ogre::Bullet::DynamicsWorld *world)
|
||||
FlatTerrainDefiner(Ogre::SceneManager *
|
||||
scm /*, Ogre::Bullet::DynamicsWorld *world */)
|
||||
: Ogre::TerrainPagedWorldSection::TerrainDefiner()
|
||||
, Ogre::FrameListener()
|
||||
, mScnMgr(scm)
|
||||
, mWorld(world)
|
||||
// , mWorld(world)
|
||||
{
|
||||
Ogre::Root::getSingleton().addFrameListener(this);
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
void createTerrainChunk(Ogre::TerrainGroup *terrainGroup, long x,
|
||||
long y)
|
||||
{
|
||||
Ogre::Terrain *terrain = terrainGroup->getTerrain(x, y);
|
||||
float minH = terrain->getMinHeight();
|
||||
float maxH = terrain->getMaxHeight();
|
||||
uint16_t terrainSize = terrainGroup->getTerrainSize();
|
||||
OgreAssert(terrain && terrain->getHeightData() &&
|
||||
terrain->isLoaded(),
|
||||
"invalid terrain supplied");
|
||||
uint16_t size = terrain->getSize();
|
||||
float *heightData = terrain->getHeightData();
|
||||
Ogre::SceneNode *node = terrain->_getRootSceneNode();
|
||||
float worldSize = terrain->getWorldSize();
|
||||
float scaled = worldSize / (size - 1);
|
||||
Ogre::Vector3 bodyPosition = terrain->getPosition();
|
||||
bodyPosition.y += (maxH + minH) / 2.0f;
|
||||
bodyPosition.x += worldSize / 2.0f;
|
||||
bodyPosition.z += worldSize / 2.0f;
|
||||
Ogre::Vector3 offset =
|
||||
node->_getDerivedPosition() - bodyPosition;
|
||||
flecs::entity e = PhysicsModule::createTerrainChunkBody(
|
||||
node, heightData, offset,
|
||||
Ogre::Vector3(scaled, 1, scaled), size);
|
||||
node->getUserObjectBindings().setUserAny("_collider", e);
|
||||
}
|
||||
void define(Ogre::TerrainGroup *terrainGroup, long x, long y) override
|
||||
{
|
||||
uint16_t terrainSize = terrainGroup->getTerrainSize();
|
||||
@@ -258,6 +284,10 @@ public:
|
||||
float maxH = terrain->getMaxHeight();
|
||||
int size = terrain->getSize();
|
||||
float worldSize = terrain->getWorldSize();
|
||||
{
|
||||
createTerrainChunk(group, x, y);
|
||||
}
|
||||
#if 0
|
||||
if (true) {
|
||||
btRigidBody *body =
|
||||
mWorld->addTerrainRigidBody(
|
||||
@@ -297,6 +327,7 @@ public:
|
||||
y));
|
||||
created = true;
|
||||
}
|
||||
#endif
|
||||
collider_queue.pop_front();
|
||||
// FIXME: create entities and components instead
|
||||
Ogre::SceneNode *items =
|
||||
@@ -317,11 +348,6 @@ public:
|
||||
what->attachObject(ent);
|
||||
what->setOrientation(item.rotation);
|
||||
what->setPosition(item.position);
|
||||
ECS::get<EngineData>()
|
||||
.mWorld->addRigidBody(
|
||||
0, ent,
|
||||
Ogre::Bullet::CT_TRIMESH,
|
||||
nullptr, 2, 0x7fffffff);
|
||||
}
|
||||
} else {
|
||||
output.push_back(collider_queue.front());
|
||||
@@ -338,13 +364,10 @@ public:
|
||||
};
|
||||
class DummyPageProvider : public Ogre::PageProvider {
|
||||
public:
|
||||
DummyPageProvider(btDynamicsWorld *world)
|
||||
DummyPageProvider(/* btDynamicsWorld *world */)
|
||||
: Ogre::PageProvider()
|
||||
, mBtWorld(world)
|
||||
{
|
||||
}
|
||||
std::unordered_map<Ogre::PageID, btRigidBody *> body;
|
||||
btDynamicsWorld *mBtWorld;
|
||||
bool prepareProceduralPage(Ogre::Page *page,
|
||||
Ogre::PagedWorldSection *section)
|
||||
{
|
||||
@@ -377,6 +400,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
ecs.component<CanSetPlayerPosition>().add(flecs::Singleton);
|
||||
ecs.component<Terrain>().add(flecs::Singleton);
|
||||
ecs.component<TerrainPrivate>().add(flecs::Singleton);
|
||||
ecs.component<PlacementObjects>();
|
||||
ecs.set<TerrainPrivate>({ nullptr, {} });
|
||||
ecs.system<const EngineData, const Camera, const Sun, Terrain,
|
||||
TerrainPrivate>("SetupUpdateTerrain")
|
||||
@@ -389,8 +413,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
if (!priv.mDummyPageProvider)
|
||||
priv.mDummyPageProvider =
|
||||
new DummyPageProvider(
|
||||
eng.mWorld
|
||||
->getBtWorld());
|
||||
/* eng.mWorld
|
||||
->getBtWorld() */);
|
||||
terrain.mTerrainGlobals =
|
||||
OGRE_NEW Ogre::TerrainGlobalOptions();
|
||||
|
||||
@@ -477,7 +501,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
|
||||
|
||||
terrain.mTerrainPagedWorldSection->setDefiner(
|
||||
OGRE_NEW FlatTerrainDefiner(
|
||||
eng.mScnMgr, eng.mWorld));
|
||||
eng.mScnMgr /*, eng.mWorld */));
|
||||
|
||||
terrain.mTerrainGroup->freeTemporaryResources();
|
||||
std::cout << "Terrain setup done\n";
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "WaterModule.h"
|
||||
namespace ECS
|
||||
{
|
||||
#if 0
|
||||
class WaterPhysicsAction : public btActionInterface {
|
||||
btPairCachingGhostObject *mWaterBody;
|
||||
btManifoldArray mManifoldArray;
|
||||
@@ -53,13 +54,13 @@ public:
|
||||
return (mInWater.find(body) != mInWater.end());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
static const uint32_t WATER_MASK = 0xF00;
|
||||
WaterModule::WaterModule(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<WaterModule>();
|
||||
ecs.component<WaterSurface>()
|
||||
.on_add([](flecs::entity e, WaterSurface &water) {
|
||||
ECS::get().add<WaterBody>();
|
||||
water.mAbove = false;
|
||||
water.mDepthMaterial = nullptr;
|
||||
water.mDepthTech = nullptr;
|
||||
@@ -457,10 +458,14 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
eng.mScnMgr->getRenderQueue()->setRenderableListener(
|
||||
&water.mRenderTargetListener);
|
||||
std::cout << "Water setup done\n";
|
||||
ECS::get().add<WaterAlmostReady>();
|
||||
})
|
||||
.add(flecs::Singleton);
|
||||
#if 0
|
||||
ecs.component<WaterBody>().add(flecs::Singleton);
|
||||
ecs.component<WaterBody>()
|
||||
.on_add([this](WaterBody &body) {
|
||||
#if 0
|
||||
body.mShapeAabbMax = btVector3(0, 0, 0);
|
||||
body.mShapeAabbMin = btVector3(0, 0, 0);
|
||||
body.mSurface.clear();
|
||||
@@ -489,9 +494,11 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
.get<EngineData>()
|
||||
.mWorld->getBtWorld()
|
||||
->addAction(body.action);
|
||||
#endif
|
||||
ECS::get().add<WaterReady>();
|
||||
})
|
||||
.add(flecs::Singleton);
|
||||
#endif
|
||||
ecs.system<const EngineData, const Camera, WaterSurface>("UpdateWater")
|
||||
.kind(flecs::OnUpdate)
|
||||
.with<WaterReady>()
|
||||
@@ -520,6 +527,7 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
// water.mRenderTargetListener.mInDepth = false;
|
||||
// water.mWaterEnt->setVisible(true);
|
||||
});
|
||||
#if 0
|
||||
ecs.system<const EngineData, const WaterSurface, WaterBody>(
|
||||
"UpdateWaterBody")
|
||||
.kind(flecs::OnUpdate)
|
||||
@@ -527,6 +535,7 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
.each([this](const EngineData &eng, const WaterSurface &water,
|
||||
WaterBody &body) {
|
||||
int i;
|
||||
#if 0
|
||||
OgreAssert(body.mWaterBody, "Water not ready");
|
||||
std::set<btCollisionObject *> currentOverlaps;
|
||||
Ogre::Vector3 waterPos =
|
||||
@@ -542,6 +551,7 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
body.mWaterBody->getWorldTransform().setOrigin(
|
||||
Ogre::Bullet::convert(waterBodyPos +
|
||||
d));
|
||||
#endif
|
||||
#if 0
|
||||
btCompoundShape *mshape =
|
||||
static_cast<btCompoundShape *>(
|
||||
@@ -646,6 +656,7 @@ WaterModule::WaterModule(flecs::world &ecs)
|
||||
}
|
||||
#endif
|
||||
});
|
||||
#endif
|
||||
}
|
||||
struct shapeParams {
|
||||
float offsetX, offsetY, offsetZ;
|
||||
@@ -654,6 +665,7 @@ struct shapeParams {
|
||||
static struct shapeParams childShapes[] = {
|
||||
{ 0.0f, 0.0f, 0.0f, 100.0f, 100.0f, 100.0f },
|
||||
};
|
||||
#if 0
|
||||
void WaterModule::createWaterShape(WaterBody *water)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -684,6 +696,7 @@ void WaterModule::createWaterShape(WaterBody *water)
|
||||
shape->recalculateLocalAabb();
|
||||
water->mWaterShape = shape;
|
||||
}
|
||||
#endif
|
||||
void WaterSurface::RenderTextureListener::preRenderTargetUpdate(
|
||||
const Ogre::RenderTargetEvent &evt)
|
||||
{
|
||||
@@ -712,6 +725,7 @@ bool WaterSurface::RenderTextureListener::renderableQueued(
|
||||
*ppTech = mSurface->mDepthTech;
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
struct DeepPenetrationContactResultCallback : public btManifoldResult {
|
||||
DeepPenetrationContactResultCallback(
|
||||
const btCollisionObjectWrapper *body0Wrap,
|
||||
@@ -954,8 +968,11 @@ void WaterPhysicsAction::debugDraw(btIDebugDraw *debugDrawer)
|
||||
void WaterPhysicsAction::setupBody()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
bool WaterBody::isInWater(const btCollisionObject *body) const
|
||||
{
|
||||
return static_cast<WaterPhysicsAction *>(action)->isInWater(body);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -37,20 +37,10 @@ struct WaterSurface {
|
||||
mRefractionClipPlaneBelow;
|
||||
Ogre::Viewport *mViewports[4];
|
||||
};
|
||||
struct WaterBody {
|
||||
std::vector<btCollisionShape *> mChildShapes;
|
||||
btCollisionShape *mWaterShape;
|
||||
btPairCachingGhostObject *mWaterBody;
|
||||
std::unordered_map<btCollisionObject *, float> mSurface;
|
||||
btVector3 mShapeAabbMin, mShapeAabbMax;
|
||||
int count;
|
||||
btActionInterface *action;
|
||||
bool isInWater(const btCollisionObject *body) const;
|
||||
};
|
||||
struct WaterModule {
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
// btPairCachingGhostObject *mGhostObject;
|
||||
WaterModule(flecs::world &ecs);
|
||||
void createWaterShape(WaterBody *water);
|
||||
// void createWaterShape(WaterBody *water);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@
|
||||
#define H_GOAP_H_
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <flecs.h>
|
||||
namespace ECS
|
||||
{
|
||||
@@ -346,4 +347,4 @@ template <class RunnerType> struct DeclareAction : public BaseAction {
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
18
src/physics/CMakeLists.txt
Normal file
18
src/physics/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.13.0)
|
||||
project(jolt-physics)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
# The COMPONENTS part checks that OGRE was built the way we need it
|
||||
# The CONFIG flag makes sure we get OGRE instead of OGRE-next
|
||||
find_package(Jolt REQUIRED)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Paging Terrain CONFIG)
|
||||
find_package(ZLIB)
|
||||
find_package(SDL2)
|
||||
find_package(assimp REQUIRED CONFIG)
|
||||
find_package(OgreProcedural REQUIRED CONFIG)
|
||||
find_package(pugixml REQUIRED CONFIG)
|
||||
find_package(flecs REQUIRED CONFIG)
|
||||
|
||||
add_library(physics STATIC physics.cpp)
|
||||
target_link_libraries(physics PUBLIC OgreMain Jolt::Jolt)
|
||||
target_include_directories(physics PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
1660
src/physics/physics.cpp
Normal file
1660
src/physics/physics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
143
src/physics/physics.h
Normal file
143
src/physics/physics.h
Normal file
@@ -0,0 +1,143 @@
|
||||
#ifndef __PHYSICS_H_
|
||||
#define __PHYSICS_H_
|
||||
#include <Ogre.h>
|
||||
#include <OgreSingleton.h>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/EActivation.h>
|
||||
void physics();
|
||||
namespace JPH
|
||||
{
|
||||
class CharacterBase;
|
||||
}
|
||||
// Layer that objects can be in, determines which other objects it can collide with
|
||||
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
|
||||
// layers if you want. E.g. you could have a layer for high detail collision (which is not used by the physics simulation
|
||||
// but only if you do collision testing).
|
||||
namespace Layers
|
||||
{
|
||||
static constexpr JPH::ObjectLayer NON_MOVING = 0;
|
||||
static constexpr JPH::ObjectLayer MOVING = 1;
|
||||
static constexpr JPH::ObjectLayer NUM_LAYERS = 2;
|
||||
};
|
||||
|
||||
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
|
||||
// a layer for non-moving and moving objects to avoid having to update a tree full of static objects every frame.
|
||||
// You can have a 1-on-1 mapping between object layers and broadphase layers (like in this case) but if you have
|
||||
// many object layers you'll be creating many broad phase trees, which is not efficient. If you want to fine tune
|
||||
// your broadphase layers define JPH_TRACK_BROADPHASE_STATS and look at the stats reported on the TTY.
|
||||
namespace BroadPhaseLayers
|
||||
{
|
||||
static constexpr JPH::BroadPhaseLayer NON_MOVING(0);
|
||||
static constexpr JPH::BroadPhaseLayer MOVING(1);
|
||||
static constexpr uint NUM_LAYERS(2);
|
||||
};
|
||||
|
||||
namespace JoltPhysics
|
||||
{
|
||||
Ogre::Vector3 convert(const JPH::Vec3Arg &vec);
|
||||
JPH::Vec3 convert(const Ogre::Vector3 &vec);
|
||||
Ogre::Quaternion convert(const JPH::QuatArg &rot);
|
||||
JPH::Quat convert(const Ogre::Quaternion &rot);
|
||||
struct ShapeData;
|
||||
struct CompoundShapeBuilder {
|
||||
JPH::StaticCompoundShapeSettings shapeSettings;
|
||||
void addShape(JPH::ShapeRefC shape, const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation);
|
||||
JPH::ShapeRefC build();
|
||||
};
|
||||
}
|
||||
|
||||
class JoltPhysicsWrapper : public Ogre::Singleton<JoltPhysicsWrapper> {
|
||||
public:
|
||||
JoltPhysicsWrapper(Ogre::SceneManager *scnMgr,
|
||||
Ogre::SceneNode *cameraNode);
|
||||
~JoltPhysicsWrapper();
|
||||
void update(float dt);
|
||||
void addBody(const JPH::BodyID &body, JPH::EActivation activation);
|
||||
bool isAdded(const JPH::BodyID &body);
|
||||
JPH::ShapeRefC createBoxShape(const Ogre::Vector3 &extents);
|
||||
JPH::ShapeRefC createSphereShape(float radius);
|
||||
JPH::ShapeRefC createCylinderShape(float halfHeight, float radius);
|
||||
JPH::ShapeRefC createMeshShape(Ogre::MeshPtr mesh);
|
||||
JPH::ShapeRefC createMeshShape(Ogre::String meshName);
|
||||
JPH::ShapeRefC createConvexHullShape(Ogre::MeshPtr mesh);
|
||||
JPH::ShapeRefC createConvexHullShape(Ogre::String meshName);
|
||||
JPH::ShapeRefC createHeightfieldShape(const float *samples,
|
||||
Ogre::Vector3 offset,
|
||||
Ogre::Vector3 scale,
|
||||
int sampleCount);
|
||||
JPH::ShapeRefC createMutableCompoundShape(
|
||||
const std::vector<JPH::ShapeRefC> &shapes,
|
||||
const std::vector<Ogre::Vector3> &positions,
|
||||
const std::vector<Ogre::Quaternion> &rotations);
|
||||
JPH::ShapeRefC createStaticCompoundShape(
|
||||
const std::vector<JPH::ShapeRefC> &shapes,
|
||||
const std::vector<Ogre::Vector3> &positions,
|
||||
const std::vector<Ogre::Quaternion> &rotations);
|
||||
JPH::ShapeRefC
|
||||
createOffsetCenterOfMassShape(const Ogre::Vector3 &offset,
|
||||
JPH::ShapeRefC shape);
|
||||
JPH::BodyID createBody(const JPH::BodyCreationSettings &settings);
|
||||
JPH::BodyID createBody(const JPH::Shape *shape, float mass,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation,
|
||||
JPH::EMotionType motion, JPH::ObjectLayer layer);
|
||||
JPH::BodyID createBody(const JPH::Shape *shape, float mass,
|
||||
Ogre::SceneNode *node, JPH::EMotionType motion,
|
||||
JPH::ObjectLayer layer);
|
||||
JPH::BodyID createSensor(const JPH::Shape *shape,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation,
|
||||
JPH::EMotionType motion,
|
||||
JPH::ObjectLayer layer);
|
||||
JPH::BodyID createSensor(const JPH::Shape *shape, Ogre::SceneNode *node,
|
||||
JPH::EMotionType motion,
|
||||
JPH::ObjectLayer layer);
|
||||
JPH::CharacterBase *createCharacter(Ogre::SceneNode *node,
|
||||
float characterHeight,
|
||||
float characterRadius);
|
||||
void addShapeToCompound(JPH::Ref<JPH::Shape> compoundShape,
|
||||
JPH::ShapeRefC childShape,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation);
|
||||
void removeBody(const JPH::BodyID &id);
|
||||
void destroyBody(const JPH::BodyID &id);
|
||||
void setDebugDraw(bool enable);
|
||||
void broadphaseQuery(float dt, const Ogre::Vector3 &position,
|
||||
std::set<JPH::BodyID> &inWater);
|
||||
void applyBuoyancyImpulse(JPH::BodyID id,
|
||||
const Ogre::Vector3 &surfacePosition,
|
||||
const Ogre::Vector3 &surfaceNormal,
|
||||
float buoyancy, float linearDrag,
|
||||
float angularDrag,
|
||||
const Ogre::Vector3 &fluidVelocity,
|
||||
const Ogre::Vector3 &gravity, float dt);
|
||||
void applyBuoyancyImpulse(JPH::BodyID id,
|
||||
const Ogre::Vector3 &surfacePosition,
|
||||
const Ogre::Vector3 &surfaceNormal,
|
||||
float buoyancy, float linearDrag,
|
||||
float angularDrag,
|
||||
const Ogre::Vector3 &fluidVelocity, float dt);
|
||||
bool isActive(JPH::BodyID id);
|
||||
void activate(JPH::BodyID id);
|
||||
Ogre::Vector3 getPosition(JPH::BodyID id);
|
||||
void setPosition(JPH::BodyID id, const Ogre::Vector3 &position,
|
||||
bool activate = true);
|
||||
void setRotation(JPH::BodyID id, const Ogre::Quaternion &rotation,
|
||||
bool activate = true);
|
||||
void getPositionAndRotation(JPH::BodyID id, Ogre::Vector3 &position,
|
||||
Ogre::Quaternion &rotation);
|
||||
void setPositionAndRotation(JPH::BodyID id,
|
||||
const Ogre::Vector3 &position,
|
||||
const Ogre::Quaternion &rotation,
|
||||
bool activate = true);
|
||||
Ogre::Vector3 getLinearVelocity(JPH::BodyID id);
|
||||
void addAngularImpulse(const JPH::BodyID &id,
|
||||
const Ogre::Vector3 &impulse);
|
||||
};
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
project(sceneloader)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_library(sceneloader STATIC loader.cpp)
|
||||
target_include_directories(sceneloader PUBLIC .)
|
||||
target_link_libraries(sceneloader PUBLIC OgreMain PRIVATE pugixml GameData)
|
||||
target_link_libraries(sceneloader PUBLIC OgreMain PRIVATE pugixml GameData physics)
|
||||
target_link_libraries(sceneloader PUBLIC OgreTerrain)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,13 @@
|
||||
#ifndef LOADER_H_
|
||||
#define LOADER_H_
|
||||
#include <pugixml.hpp>
|
||||
#include <flecs.h>
|
||||
#include <OgreColourValue.h>
|
||||
#include <OgreQuaternion.h>
|
||||
#include <OgreResourceGroupManager.h>
|
||||
#include <OgreString.h>
|
||||
#include <OgrePlugin.h>
|
||||
#include <OgreCodec.h>
|
||||
#include <flecs.h>
|
||||
|
||||
class SceneLoader {
|
||||
public:
|
||||
@@ -23,6 +24,9 @@ public:
|
||||
{
|
||||
return mBackgroundColour;
|
||||
}
|
||||
static void setupPhysicsBody(Ogre::SceneNode *node,
|
||||
Ogre::MovableObject *entity,
|
||||
flecs::entity base_e);
|
||||
|
||||
protected:
|
||||
void writeNode(pugi::xml_node &parentXML, const Ogre::SceneNode *node);
|
||||
@@ -68,7 +72,6 @@ protected:
|
||||
Ogre::Light *pLight);
|
||||
void processLightSourceSize(pugi::xml_node &XMLNode,
|
||||
Ogre::Light *pLight);
|
||||
|
||||
Ogre::SceneManager *mSceneMgr;
|
||||
Ogre::SceneNode *mAttachNode;
|
||||
Ogre::String m_sGroupName;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreTerrainAutoUpdateLod.h>
|
||||
#include <OgreTerrainPagedWorldSection.h>
|
||||
#include <OgreBullet.h>
|
||||
#include <OgreMath.h>
|
||||
#include <OgreLogManager.h>
|
||||
#include "terrain.h"
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <OgreTerrain.h>
|
||||
#include <OgreTerrainGroup.h>
|
||||
#include <OgrePageManager.h>
|
||||
@@ -404,9 +402,11 @@ public:
|
||||
return body;
|
||||
}
|
||||
#endif
|
||||
bool isLoadedAt(const Ogre::Vector3 &position) const {
|
||||
bool isLoadedAt(const Ogre::Vector3 &position) const
|
||||
{
|
||||
long x, y;
|
||||
mTerrainGroup->convertWorldPositionToTerrainSlot(position, &x, &y);
|
||||
mTerrainGroup->convertWorldPositionToTerrainSlot(position, &x,
|
||||
&y);
|
||||
if (mTerrainGroup->getTerrain(x, y))
|
||||
return mTerrainGroup->getTerrain(x, y)->isLoaded();
|
||||
return false;
|
||||
|
||||
@@ -7,4 +7,6 @@ add_executable(check_uv check_uv.cpp)
|
||||
target_link_libraries(check_uv ${ASSIMP_LIBRARIES})
|
||||
add_executable(ogre_check_uv ogre_check_uv.cpp)
|
||||
target_link_libraries(ogre_check_uv OgreBites OgreMain)
|
||||
add_executable(check_scene_loader check_scene_loader.cpp)
|
||||
target_link_libraries(check_scene_loader OgreBites OgreMain)
|
||||
|
||||
|
||||
64
src/tests/check_scene_loader.cpp
Normal file
64
src/tests/check_scene_loader.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreCodec.h>
|
||||
#include <OgreFileSystem.h>
|
||||
#include <OgreFileSystemLayer.h>
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreShaderGenerator.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
Ogre::LogManager logMgr;
|
||||
logMgr.createLog("messages.log", true, true, true);
|
||||
Ogre::DefaultHardwareBufferManager
|
||||
bufferManager; // needed because we don't have a rendersystem
|
||||
Ogre::Root *ogre = new Ogre::Root("", "", "");
|
||||
Ogre::ConfigFile pluginsCfg;
|
||||
Ogre::FileSystemLayer fsLayer("Ogre3D");
|
||||
pluginsCfg.load(fsLayer.getConfigFilePath("plugins.cfg"));
|
||||
|
||||
auto pluginDir = Ogre::FileSystemLayer::resolveBundlePath(
|
||||
pluginsCfg.getSetting("PluginFolder") + "/");
|
||||
ogre->loadPlugin(pluginDir + "/Codec_Assimp");
|
||||
ogre->loadPlugin(pluginDir + "/Plugin_DotScene");
|
||||
Ogre::MaterialManager::getSingleton().initialise();
|
||||
Ogre::RTShader::ShaderGenerator::initialize();
|
||||
Ogre::DefaultTextureManager texMgr;
|
||||
|
||||
auto &shadergen = Ogre::RTShader::ShaderGenerator::getSingleton();
|
||||
shadergen.setTargetLanguage(
|
||||
"glsl"); // must be valid, but otherwise arbitrary
|
||||
shadergen.getRenderState(Ogre::MSN_SHADERGEN)
|
||||
->setLightCountAutoUpdate(false);
|
||||
shadergen.validateScheme(Ogre::MSN_SHADERGEN);
|
||||
Ogre::SceneManager *sceneManager =
|
||||
ogre->createSceneManager("DefaultSceneManager");
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"resources/vehicles", "FileSystem", "Generic", true, true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"../resources/vehicles", "FileSystem", "Generic", true, true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"../../resources/vehicles", "FileSystem", "Generic", true,
|
||||
true);
|
||||
std::map<Ogre::String, Ogre::Any> options;
|
||||
options["prefix"] = Ogre::String("0/");
|
||||
Ogre::SceneNode *p1 =
|
||||
sceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
Ogre::Any optionsAny1 = options;
|
||||
p1->getUserObjectBindings().setUserAny("_DotSceneLoaderOptions",
|
||||
optionsAny1);
|
||||
p1->loadChildren("boat.scene");
|
||||
options["prefix"] = Ogre::String("1/");
|
||||
Ogre::SceneNode *p2 =
|
||||
sceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
Ogre::Any optionsAny2 = options;
|
||||
p2->getUserObjectBindings().setUserAny("_DotSceneLoaderOptions",
|
||||
optionsAny2);
|
||||
p2->loadChildren("boat.scene");
|
||||
// Ogre::DataStreamPtr sceneData =
|
||||
// Ogre::ResourceGroupManager::getSingleton().openResource(
|
||||
// "boat.scene", "General");
|
||||
// auto codec = Ogre::Codec::getCodec("scene");
|
||||
// codec->decode(sceneData, sceneManager->getRootSceneNode());
|
||||
return 0;
|
||||
}
|
||||
@@ -1,18 +1,20 @@
|
||||
project(world)
|
||||
find_package(Bullet)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG)
|
||||
add_library(action action.cpp)
|
||||
target_link_libraries(action PUBLIC GameData OgreBullet)
|
||||
add_library(action STATIC action.cpp)
|
||||
target_link_libraries(action PRIVATE GameData)
|
||||
target_include_directories(action PUBLIC .)
|
||||
add_library(world-build world-build.cpp)
|
||||
target_link_libraries(world-build PUBLIC GameData OgreBullet)
|
||||
add_library(world-build STATIC world-build.cpp)
|
||||
target_link_libraries(world-build PRIVATE GameData)
|
||||
target_include_directories(world-build PUBLIC .)
|
||||
|
||||
add_executable(test test.cpp)
|
||||
target_link_libraries(test PRIVATE OgreMain OgreBullet action world-build lua)
|
||||
target_link_libraries(test PRIVATE action world-build lua GameData OgreMain)
|
||||
|
||||
add_executable(test2 test2.cpp)
|
||||
target_link_libraries(test2 PRIVATE OgreMain OgreBullet action world-build lua)
|
||||
target_link_libraries(test2 PRIVATE action world-build lua GameData OgreMain)
|
||||
|
||||
add_executable(mark_harbors mark_harbors.cpp)
|
||||
target_link_libraries(mark_harbors PRIVATE OgreMain OgreBullet lua)
|
||||
target_link_libraries(mark_harbors PRIVATE lua OgreMain OgreRTShaderSystem)
|
||||
|
||||
add_custom_target(world ALL DEPENDS test test2)
|
||||
|
||||
@@ -150,7 +150,7 @@ int main()
|
||||
ecs.component<Female>();
|
||||
ecs.component<Position>();
|
||||
ecs.component<Target>();
|
||||
ecs.set<ECS::EngineData>({ nullptr, nullptr, 0.0f, 5.0f, 0, 0, false });
|
||||
ecs.set<ECS::EngineData>({ nullptr, 0.0f, 5.0f, 0, 0, false });
|
||||
|
||||
flecs::entity e1 = ecs.entity("e1");
|
||||
e1.set<Blackboard>({ e1, 100, 100, 100, 0 });
|
||||
|
||||
@@ -443,7 +443,7 @@ int main()
|
||||
ecs.import <ECS::CharacterAIModule>();
|
||||
ecs.import <ECS::CharacterAIExtraModule>();
|
||||
ecs.import <ECS::GameWorldModule>();
|
||||
ecs.set<ECS::EngineData>({ nullptr, nullptr, 0.0f, 5.0f, 0, 0, false });
|
||||
ecs.set<ECS::EngineData>({ nullptr, 0.0f, 5.0f, 0, 0, false });
|
||||
CopulationGoal goal_copulation;
|
||||
SustainabilityGoal goal_sustainability;
|
||||
ECS::Planner &planner = ecs.ensure<ECS::Planner>();
|
||||
|
||||
Reference in New Issue
Block a user