converted to Jolt physics

This commit is contained in:
2025-11-23 02:00:31 +03:00
parent 3f0484e87c
commit cd82fb0eed
52 changed files with 4302 additions and 1458 deletions

View File

@@ -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})

View File

@@ -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();
}

View File

@@ -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;
}
};

View File

@@ -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
}
}

View File

@@ -18,9 +18,7 @@ struct BoatBase {
Ogre::Entity *mEnt;
Ogre::SceneNode *mNode;
};
struct BoatBody {
btRigidBody *body;
};
struct SpawnBoat {};
struct BoatModule {
BoatModule(flecs::world &ecs);
};

View File

@@ -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)

View File

@@ -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

View File

@@ -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)
}
});
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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);
}
}
}

View File

@@ -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()

View File

@@ -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) {

View 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();
}
}

View 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

View 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>();
}
});
}
}

View 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

View File

@@ -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";

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View 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

File diff suppressed because it is too large Load Diff

143
src/physics/physics.h Normal file
View 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

View File

@@ -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

View File

@@ -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;

View File

@@ -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"

View File

@@ -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;

View File

@@ -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)

View 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;
}

View File

@@ -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)

View File

@@ -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 });

View File

@@ -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>();