converted to Jolt physics
This commit is contained in:
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "Ogre.h"
|
||||
#include "OgreApplicationContext.h"
|
||||
#include "Bullet/OgreBullet.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "OgrePageManager.h"
|
||||
|
||||
#define CAM_HEIGHT 1.6f // height of camera above character's center of mass
|
||||
@@ -21,11 +18,15 @@ using Real = Ogre::Real;
|
||||
using Math = Ogre::Math;
|
||||
|
||||
class WorldData {
|
||||
#if 0
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
#endif
|
||||
std::unique_ptr<Ogre::Root> mRoot;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
#if 0
|
||||
std::unique_ptr<btDynamicsWorld> mbtWorld;
|
||||
#endif
|
||||
std::unique_ptr<Ogre::PageManager> mPageManager;
|
||||
Ogre::PagedWorld *mPagedWorld;
|
||||
|
||||
@@ -61,13 +62,14 @@ private:
|
||||
DummyPageProvider mDummyPageProvider;
|
||||
|
||||
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
: mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
: /*mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, mDbgDraw(new Ogre::Bullet::DebugDrawer(
|
||||
scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
|
||||
, mRoot(root)
|
||||
, */
|
||||
mRoot(root)
|
||||
, mScnMgr(scnMgr)
|
||||
, mbtWorld(mDynWorld->getBtWorld())
|
||||
/*, mbtWorld(mDynWorld->getBtWorld()) */
|
||||
, mPageManager(nullptr)
|
||||
, mPagedWorld(nullptr)
|
||||
{
|
||||
@@ -122,6 +124,7 @@ public:
|
||||
#endif
|
||||
return ghost;
|
||||
}
|
||||
#if 0
|
||||
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct, int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
@@ -182,11 +185,14 @@ public:
|
||||
{
|
||||
return mDynWorld.get();
|
||||
}
|
||||
#endif
|
||||
void update(float delta)
|
||||
{
|
||||
#if 0
|
||||
WorldData::get_singleton()->getBtWorld()->stepSimulation(delta,
|
||||
10);
|
||||
mDbgDraw->update();
|
||||
#endif
|
||||
}
|
||||
void initPagedWorld(Ogre::Camera *camera)
|
||||
{
|
||||
@@ -200,7 +206,7 @@ public:
|
||||
WorldData *WorldData::singleton = nullptr;
|
||||
|
||||
class MainWorld : public Ogre::FrameListener {
|
||||
btRigidBody *mFloorBody;
|
||||
// btRigidBody *mFloorBody;
|
||||
|
||||
public:
|
||||
void setup()
|
||||
@@ -219,14 +225,18 @@ public:
|
||||
WorldData::get_singleton()->getSceneManager();
|
||||
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
|
||||
scnMgr->getRootSceneNode()->attachObject(floor);
|
||||
#if 0
|
||||
mFloorBody = WorldData::get_singleton()->addRigidBody(
|
||||
0, floor, Ogre::Bullet::CT_TRIMESH);
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
|
||||
{
|
||||
return WorldData::get_singleton()->addKinematicRigidBody(
|
||||
mass, ent, Ogre::Bullet::CT_COMPOUND);
|
||||
}
|
||||
#endif
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
class CharacterController : public OgreBites::InputListener,
|
||||
@@ -265,8 +275,10 @@ class CharacterController : public OgreBites::InputListener,
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
#if 0
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
#endif
|
||||
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
|
||||
@@ -315,6 +327,7 @@ private:
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
#endif
|
||||
#if 0
|
||||
inline btQuaternion convert(const Ogre::Quaternion &q)
|
||||
{
|
||||
return btQuaternion(q.x, q.y, q.z, q.w);
|
||||
@@ -344,6 +357,7 @@ private:
|
||||
q = convert(from.getRotation());
|
||||
v = convert(from.getOrigin());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
Ogre::Camera *cam,
|
||||
|
||||
@@ -27,11 +27,10 @@ file(GLOB WATER_SRC ${CMAKE_SOURCE_DIR}/water/*.cpp)
|
||||
|
||||
# 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(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain CONFIG)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites Paging Terrain CONFIG)
|
||||
find_package(ZLIB)
|
||||
find_package(SDL2)
|
||||
find_package(assimp REQUIRED CONFIG)
|
||||
find_package(Bullet)
|
||||
find_package(OgreProcedural REQUIRED CONFIG)
|
||||
find_package(pugixml REQUIRED CONFIG)
|
||||
find_package(flecs REQUIRED CONFIG)
|
||||
@@ -66,46 +65,24 @@ set_target_properties(fix::pugixml PROPERTIES
|
||||
|
||||
|
||||
add_subdirectory(src/lua)
|
||||
add_subdirectory(src/characters)
|
||||
add_subdirectory(src/gamedata)
|
||||
add_subdirectory(src/miniaudio)
|
||||
add_subdirectory(src/sound)
|
||||
add_subdirectory(src/sceneloader)
|
||||
add_subdirectory(audio/gui)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(lua-scripts)
|
||||
add_subdirectory(morph)
|
||||
add_subdirectory(src/world)
|
||||
add_subdirectory(src/tests)
|
||||
add_subdirectory(src/physics)
|
||||
|
||||
# add the source files as usual
|
||||
add_executable(0_Bootstrap Bootstrap.cpp)
|
||||
|
||||
# this also sets the includes and pulls third party dependencies
|
||||
target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${ASSIMP_LIBRARIES}
|
||||
-Wl,--as-needed
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
target_link_options(0_Bootstrap PRIVATE -static-libstdc++ -static-libgcc)
|
||||
endif()
|
||||
add_dependencies(0_Bootstrap stage_files import_vrm)
|
||||
|
||||
add_executable(Editor Editor.cpp ${WATER_SRC})
|
||||
target_link_libraries(Editor OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}
|
||||
-Wl,--as-needed
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
target_link_options(Editor PRIVATE -static-libstdc++ -static-libgcc)
|
||||
endif()
|
||||
add_dependencies(Editor stage_files import_buildings import_water_stuff import_vehicles import_vrm)
|
||||
add_executable(Game Game.cpp ${WATER_SRC})
|
||||
target_include_directories(Game PRIVATE src/gamedata)
|
||||
target_link_libraries(Game OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator
|
||||
OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY}
|
||||
${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}
|
||||
target_link_libraries(Game OgreBites OgrePaging OgreTerrain OgreMeshLodGenerator
|
||||
OgreProcedural::OgreProcedural
|
||||
GameData
|
||||
sound
|
||||
sceneloader
|
||||
sceneloader physics
|
||||
flecs::flecs_static
|
||||
-Wl,--as-needed
|
||||
)
|
||||
@@ -115,9 +92,8 @@ endif()
|
||||
add_dependencies(Game stage_files import_buildings import_water_stuff import_vehicles import_vrm audio_data_gui)
|
||||
|
||||
add_executable(Procedural Procedural.cpp)
|
||||
target_link_libraries(Procedural OgreBites OgreBullet OgrePaging OgreTerrain
|
||||
OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY}
|
||||
${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}
|
||||
target_link_libraries(Procedural OgreBites OgrePaging OgreTerrain
|
||||
OgreProcedural::OgreProcedural
|
||||
-Wl,--as-needed
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
@@ -205,7 +181,7 @@ list(APPEND WATER_STUFF ${CMAKE_BINARY_DIR}/water/sea.glb)
|
||||
add_custom_target(import_water_stuff ALL DEPENDS ${WATER_STUFF})
|
||||
|
||||
add_executable(TerrainTest terrain.cpp)
|
||||
target_link_libraries(TerrainTest OgreBites OgreBullet OgrePaging OgreTerrain lua ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY}
|
||||
target_link_libraries(TerrainTest OgreBites OgrePaging OgreTerrain lua
|
||||
-Wl,--as-needed
|
||||
)
|
||||
target_include_directories(TerrainTest PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
|
||||
@@ -213,8 +189,6 @@ if(OGRE_STATIC)
|
||||
target_link_libraries(TerrainTest fix::assimp pugixml)
|
||||
target_link_options(TerrainTest PRIVATE -static-libstdc++ -static-libgcc)
|
||||
target_link_libraries(Procedural fix::assimp pugixml)
|
||||
target_link_libraries(0_Bootstrap fix::assimp pugixml)
|
||||
target_link_libraries(Editor fix::assimp pugixml)
|
||||
endif()
|
||||
|
||||
add_dependencies(TerrainTest stage_lua_scripts stage_files)
|
||||
@@ -407,6 +381,7 @@ add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MA
|
||||
add_custom_target(remove_scenes COMMAND rm -f ${VRM_SOURCE} ${VRM_IMPORTED_BLENDS} ${CHARACTER_GLBS})
|
||||
|
||||
add_custom_target(import_vrm DEPENDS ${CHARACTER_GLBS})
|
||||
target_compile_definitions(Game PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION)
|
||||
|
||||
install(TARGETS Editor DESTINATION bin)
|
||||
install(TARGETS Game DESTINATION bin)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <Ogre.h>
|
||||
#include <OgreBullet.h>
|
||||
#include <OgreApplicationContext.h>
|
||||
#include <OgreOverlaySystem.h>
|
||||
#include <OgreOverlayManager.h>
|
||||
@@ -245,8 +244,6 @@ public:
|
||||
void initGui();
|
||||
};
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::Real mPivotPitch;
|
||||
@@ -376,8 +373,6 @@ public:
|
||||
: OgreBites::ApplicationContext("ChoroEditor")
|
||||
, mKbd(this)
|
||||
, m_edit_ui(this)
|
||||
, mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
{
|
||||
}
|
||||
virtual ~App()
|
||||
@@ -393,8 +388,6 @@ public:
|
||||
mScnMgr->addRenderQueueListener(pOverlaySystem);
|
||||
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
|
||||
// getRenderWindow());
|
||||
mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(
|
||||
mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
|
||||
}
|
||||
void locateResources() override
|
||||
{
|
||||
@@ -455,8 +448,10 @@ public:
|
||||
std::cout << "Init camera" << "\n";
|
||||
initCamera();
|
||||
std::cout << "Set up water" << "\n";
|
||||
#if 0
|
||||
m_water.createWater(getRenderWindow(), mCamera,
|
||||
mDynWorld.get());
|
||||
#endif
|
||||
std::cout << "Set up cursor" << "\n";
|
||||
Ogre::ResourceGroupManager::getSingleton()
|
||||
.initialiseAllResourceGroups();
|
||||
|
||||
12
Game.cpp
12
Game.cpp
@@ -289,8 +289,6 @@ public:
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal;
|
||||
Ogre::Camera *mCamera;
|
||||
Ogre::Real mPivotPitch;
|
||||
@@ -304,8 +302,6 @@ public:
|
||||
App()
|
||||
: OgreBites::ApplicationContext("ChoroGame")
|
||||
, mKbd(this)
|
||||
, mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, mGrab(false)
|
||||
{
|
||||
}
|
||||
@@ -322,8 +318,6 @@ public:
|
||||
mScnMgr->addRenderQueueListener(pOverlaySystem);
|
||||
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
|
||||
// getRenderWindow());
|
||||
mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(
|
||||
mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
|
||||
}
|
||||
bool isWindowGrab()
|
||||
{
|
||||
@@ -432,7 +426,9 @@ public:
|
||||
}
|
||||
void updateWorld(float delta)
|
||||
{
|
||||
#if 0
|
||||
mDynWorld->getBtWorld()->stepSimulation(delta, 3);
|
||||
#endif
|
||||
if (!ECS::get().has<ECS::GUI>())
|
||||
return;
|
||||
/* Update window grab */
|
||||
@@ -444,8 +440,10 @@ public:
|
||||
}
|
||||
ECS::update(delta);
|
||||
|
||||
#if 0
|
||||
if (ECS::get<ECS::EngineData>().enableDbgDraw)
|
||||
mDbgDraw->update();
|
||||
#endif
|
||||
}
|
||||
class InputListenerChainFlexible : public OgreBites::InputListener {
|
||||
protected:
|
||||
@@ -598,7 +596,7 @@ public:
|
||||
"Skybox/Dynamic", "General");
|
||||
OgreAssert(m, "Sky box material not found.");
|
||||
m->load();
|
||||
ECS::setup(mScnMgr, mDynWorld.get(), mCameraNode, mCamera,
|
||||
ECS::setup(mScnMgr, /*mDynWorld.get(), */ mCameraNode, mCamera,
|
||||
getRenderWindow());
|
||||
ECS::get().set<ECS::RenderWindow>(
|
||||
{ getRenderWindow(), getDisplayDPI() });
|
||||
|
||||
209
Procedural.cpp
209
Procedural.cpp
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "Ogre.h"
|
||||
#include "OgreApplicationContext.h"
|
||||
#include "Bullet/OgreBullet.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "OgrePageManager.h"
|
||||
#include "Procedural.h"
|
||||
|
||||
@@ -22,11 +19,8 @@ using Real = Ogre::Real;
|
||||
using Math = Ogre::Math;
|
||||
|
||||
class WorldData {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
std::unique_ptr<Ogre::Root> mRoot;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
std::unique_ptr<btDynamicsWorld> mbtWorld;
|
||||
std::unique_ptr<Ogre::PageManager> mPageManager;
|
||||
Ogre::PagedWorld *mPagedWorld;
|
||||
|
||||
@@ -62,13 +56,8 @@ private:
|
||||
DummyPageProvider mDummyPageProvider;
|
||||
|
||||
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr)
|
||||
: mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, mDbgDraw(new Ogre::Bullet::DebugDrawer(
|
||||
scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
|
||||
, mRoot(root)
|
||||
: mRoot(root)
|
||||
, mScnMgr(scnMgr)
|
||||
, mbtWorld(mDynWorld->getBtWorld())
|
||||
, mPageManager(nullptr)
|
||||
, mPagedWorld(nullptr)
|
||||
{
|
||||
@@ -100,94 +89,8 @@ public:
|
||||
void createTrimesh(Ogre::Entity *entity)
|
||||
{
|
||||
}
|
||||
btPairCachingGhostObject *addGhostObject(Ogre::Entity *ent,
|
||||
btCollisionShape *shape,
|
||||
int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
btPairCachingGhostObject *ghost =
|
||||
new btPairCachingGhostObject();
|
||||
ghost->setCollisionShape(shape);
|
||||
ghost->setCollisionFlags(
|
||||
ghost->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
getWorld()->attachCollisionObject(ghost, ent, group, mask);
|
||||
#if 0
|
||||
getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
ghost->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
#endif
|
||||
return ghost;
|
||||
}
|
||||
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct, int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
Ogre::Bullet::RigidBodyState *state =
|
||||
new Ogre::Bullet::RigidBodyState(node);
|
||||
btCollisionShape *cs;
|
||||
btCollisionShape *shape;
|
||||
btVector3 inertia(0, 0, 0);
|
||||
switch (ct) {
|
||||
case Ogre::Bullet::CT_TRIMESH: {
|
||||
cs = Ogre::Bullet::createTrimeshCollider(ent);
|
||||
if (mass != 0)
|
||||
cs->calculateLocalInertia(mass, inertia);
|
||||
} break;
|
||||
case Ogre::Bullet::CT_CAPSULE: {
|
||||
cs = new btCompoundShape(false);
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
shape = new btCapsuleShape(radius,
|
||||
2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(cs)->addChildShape(
|
||||
transform, shape);
|
||||
btScalar masses[1] = { mass };
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(cs)
|
||||
->calculatePrincipalAxisTransform(
|
||||
masses, principal, inertia);
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
btRigidBody *body = new btRigidBody(mass, state, cs, inertia);
|
||||
getWorld()->attachRigidBody(body, ent, nullptr, group, mask);
|
||||
#if 0
|
||||
body->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
// btRigidBody *body = mDynWorld->addRigidBody(0, ent, Ogre::Bullet::CT_TRIMESH);
|
||||
#endif
|
||||
return body;
|
||||
}
|
||||
btRigidBody *addKinematicRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct,
|
||||
int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
return mDynWorld->addKinematicRigidBody(ent, ct, group, mask);
|
||||
}
|
||||
btDynamicsWorld *getBtWorld()
|
||||
{
|
||||
return mDynWorld->getBtWorld();
|
||||
}
|
||||
Ogre::Bullet::DynamicsWorld *getWorld()
|
||||
{
|
||||
return mDynWorld.get();
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
WorldData::get_singleton()->getBtWorld()->stepSimulation(delta,
|
||||
10);
|
||||
mDbgDraw->update();
|
||||
}
|
||||
void initPagedWorld(Ogre::Camera *camera)
|
||||
{
|
||||
@@ -201,8 +104,6 @@ public:
|
||||
WorldData *WorldData::singleton = nullptr;
|
||||
|
||||
class MainWorld : public Ogre::FrameListener {
|
||||
btRigidBody *mFloorBody;
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
@@ -220,13 +121,6 @@ public:
|
||||
WorldData::get_singleton()->getSceneManager();
|
||||
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
|
||||
scnMgr->getRootSceneNode()->attachObject(floor);
|
||||
mFloorBody = WorldData::get_singleton()->addRigidBody(
|
||||
0, floor, Ogre::Bullet::CT_TRIMESH);
|
||||
}
|
||||
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
|
||||
{
|
||||
return WorldData::get_singleton()->addKinematicRigidBody(
|
||||
mass, ent, Ogre::Bullet::CT_COMPOUND);
|
||||
}
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
@@ -266,8 +160,6 @@ class CharacterController : public OgreBites::InputListener,
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
|
||||
@@ -316,35 +208,6 @@ private:
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
#endif
|
||||
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());
|
||||
}
|
||||
};
|
||||
CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
Ogre::Camera *cam,
|
||||
@@ -358,8 +221,6 @@ CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
, mAnimID(ANIM_NONE)
|
||||
, mRunning(false)
|
||||
, world(world)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
{
|
||||
setupBody();
|
||||
setupCamera();
|
||||
@@ -374,72 +235,6 @@ void CharacterController::setupBody()
|
||||
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(false);
|
||||
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);
|
||||
WorldData::get_singleton()->getWorld()->attachCollisionObject(
|
||||
mGhostObject, mBodyEnt, btBroadphaseProxy::AllFilter,
|
||||
btBroadphaseProxy::AllFilter);
|
||||
WorldData::get_singleton()->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);
|
||||
@@ -740,8 +535,6 @@ void CharacterController::updateRootMotion(Real delta)
|
||||
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 *>());
|
||||
|
||||
@@ -92,8 +92,8 @@ class OgreCollisionOp(bpy.types.Operator):
|
||||
def get_subcollisions( self, ob, create=True ):
|
||||
r = get_subcollisions( ob )
|
||||
if not r and create:
|
||||
method = getattr(self, 'create_%s'%ob.collision_mode)
|
||||
p = method(ob)
|
||||
# method = getattr(self, 'create_%s'%ob.collision_mode)
|
||||
# p = method(ob)
|
||||
p.name = '%s.%s' %(ob.collision_mode, ob.name)
|
||||
p.subcollision = True
|
||||
r.append( p )
|
||||
|
||||
@@ -52,7 +52,7 @@ def dot_scene(path, scene_name=None):
|
||||
linkedgroups = []
|
||||
invalidnamewarnings = []
|
||||
for ob in bpy.context.scene.objects:
|
||||
if ob.subcollision:
|
||||
if ob.subcollision or "collision_type" in ob:
|
||||
continue
|
||||
if ((config.get("EXPORT_HIDDEN") is False) and (ob not in bpy.context.visible_objects)):
|
||||
continue
|
||||
@@ -184,6 +184,7 @@ def dot_scene(path, scene_name=None):
|
||||
|
||||
mesh_collision_prims = {}
|
||||
mesh_collision_files = {}
|
||||
compound_collision_shapes = {}
|
||||
|
||||
# Export the objects in the scene
|
||||
for root in roots:
|
||||
@@ -193,6 +194,7 @@ def dot_scene(path, scene_name=None):
|
||||
meshes = meshes,
|
||||
mesh_collision_prims = mesh_collision_prims,
|
||||
mesh_collision_files = mesh_collision_files,
|
||||
compound_collision_shapes = compound_collision_shapes,
|
||||
exported_armatures = exported_armatures,
|
||||
prefix = prefix,
|
||||
objects = objects,
|
||||
@@ -655,14 +657,16 @@ def dot_scene_skybox_export( path ):
|
||||
|
||||
# Recursive Node export
|
||||
def dot_scene_node_export( ob, path, doc=None, rex=None,
|
||||
exported_meshes=[], meshes=[], mesh_collision_prims={}, mesh_collision_files={},
|
||||
exported_meshes=[], meshes=[], mesh_collision_prims={}, mesh_collision_files={}, compound_collision_shapes={},
|
||||
exported_armatures=[], prefix='', objects=[], xmlparent=None ):
|
||||
print("Nodes... " + ob.name)
|
||||
|
||||
o = _ogre_node_helper( doc, ob )
|
||||
xmlparent.appendChild(o)
|
||||
|
||||
# if config.get('EXPORT_USER') is True:
|
||||
# Custom user props
|
||||
user = None
|
||||
if len(ob.items()) > 0:
|
||||
user = doc.createElement('userData')
|
||||
o.appendChild(user)
|
||||
@@ -672,46 +676,116 @@ def dot_scene_node_export( ob, path, doc=None, rex=None,
|
||||
if not propname.startswith('_'):
|
||||
_property_helper(doc, user, propname, propvalue)
|
||||
|
||||
if ob.type == 'MESH' or ob.type == 'EMPTY':
|
||||
if not user:
|
||||
user = doc.createElement('userData')
|
||||
o.appendChild(user)
|
||||
if ob.rigid_body:
|
||||
_property_helper(doc, user, "blenderCollisionType", ob.rigid_body.type)
|
||||
_property_helper(doc, user, "blenderCollisionShape", ob.rigid_body.collision_shape)
|
||||
_property_helper(doc, user, "blenderCollisionEnabled", ob.rigid_body.enabled)
|
||||
_property_helper(doc, user, "blenderCollisionKinematic", ob.rigid_body.kinematic)
|
||||
_property_helper(doc, user, "blenderCollisionMass", ob.rigid_body.mass)
|
||||
if ob.rigid_body.collision_shape == "CONVEX_HULL":
|
||||
_property_helper(doc, user, "collisionType", "convexHull")
|
||||
elif ob.rigid_body.collision_shape == "MESH":
|
||||
_property_helper(doc, user, "collisionType", "mesh")
|
||||
elif ob.rigid_body.collision_shape == "COMPOUND":
|
||||
_property_helper(doc, user, "collisionType", "compound")
|
||||
_property_helper(doc, user, "collisionBodyMass", ob.rigid_body.mass)
|
||||
if ob.type == 'MESH':
|
||||
if (not ob.parent) or (ob.parent and not ob.parent.rigid_body) or (ob.parent and ob.parent.rigid_body and ob.parent.rigid_body.collision_shape != "COMPOUND"):
|
||||
# no compound parent
|
||||
if ob.rigid_body.collision_shape in ["CONVEX_HULL", "MESH"]:
|
||||
mesh.dot_mesh(ob, path, force_name='%s_collision_%s' % (prefix, ob.data.name) )
|
||||
skeleton.dot_skeleton(ob, path)
|
||||
_property_helper(doc, user, "collisionFile", '%s_collision_%s.mesh' % (prefix, ob.data.name))
|
||||
|
||||
elif ob.parent and ob.parent.rigid_body.collision_shape == "COMPOUND":
|
||||
# has compound parent
|
||||
mesh.dot_mesh(ob, path, force_name='%s_collision_%s_%s' % (prefix, ob.parent.data.name, ob.data.name) )
|
||||
skeleton.dot_skeleton(ob, path)
|
||||
_property_helper(doc, user, "collisionFile", '%s_collision_%s_%s.mesh' % (prefix, ob.parent.data.name, ob.data.name))
|
||||
if (not ob.parent) or (ob.parent and not ob.parent.rigid_body) or (ob.parent and ob.parent.rigid_body and ob.parent.rigid_body.collision_shape != "COMPOUND"):
|
||||
if ob.rigid_body.type == 'ACTIVE':
|
||||
if not ob.rigid_body.kinematic:
|
||||
_property_helper(doc, user, "collisionBodyType", "dynamic")
|
||||
else:
|
||||
_property_helper(doc, user, "collisionBodyType", "ghost")
|
||||
else:
|
||||
if not ob.rigid_body.kinematic:
|
||||
_property_helper(doc, user, "collisionBodyType", "static")
|
||||
else:
|
||||
_property_helper(doc, user, "collisionBodyType", "kinematic")
|
||||
|
||||
|
||||
if ob.type == 'MESH':
|
||||
# ob.data.tessfaces is empty. always until the following call
|
||||
ob.data.update()
|
||||
ob.data.calc_loop_triangles()
|
||||
# if it has no faces at all, the object itself will not be exported, BUT
|
||||
# it might have children
|
||||
|
||||
if ob.type == 'MESH' and len(ob.data.loop_triangles):
|
||||
print("Loopie..." + ob.data.name + " ", ob.data.loop_triangles)
|
||||
compoundParent = False
|
||||
hasPhysics = False
|
||||
if ob.rigid_body:
|
||||
hasPhysics = True
|
||||
if ob.parent:
|
||||
if ob.parent.rigid_body:
|
||||
if ob.parent.rigid_body.collision_shape == "COMPOUND":
|
||||
compoundParent = True
|
||||
createEntity = not (compoundParent and hasPhysics)
|
||||
if ob.type == 'MESH' and len(ob.data.loop_triangles) and createEntity:
|
||||
collisionFile = None
|
||||
collisionPrim = None
|
||||
compoundColliders = None
|
||||
if ob.data.name in mesh_collision_prims:
|
||||
collisionPrim = mesh_collision_prims[ ob.data.name ]
|
||||
if ob.data.name in mesh_collision_files:
|
||||
collisionFile = mesh_collision_files[ ob.data.name ]
|
||||
|
||||
e = doc.createElement('entity')
|
||||
o.appendChild(e); e.setAttribute('name', ob.name)
|
||||
prefix = ''
|
||||
e.setAttribute('meshFile', '%s%s.mesh' % (prefix, clean_object_name(ob.data.name)) )
|
||||
|
||||
# Set the instancing attribute if the object belongs to the correct group
|
||||
_mesh_instance_helper(e, ob, "static")
|
||||
_mesh_instance_helper(e, ob, "instanced")
|
||||
if ob.data.name in compound_collision_shapes:
|
||||
compoundColliders = compound_collision_shapes[ ob.data.name ]
|
||||
print("Meshie..." + ob.data.name)
|
||||
if True:
|
||||
e = doc.createElement('entity')
|
||||
o.appendChild(e); e.setAttribute('name', ob.name)
|
||||
prefix = ''
|
||||
e.setAttribute('meshFile', '%s%s.mesh' % (prefix, clean_object_name(ob.data.name)) )
|
||||
|
||||
# Set the instancing attribute if the object belongs to the correct group
|
||||
_mesh_instance_helper(e, ob, "static")
|
||||
_mesh_instance_helper(e, ob, "instanced")
|
||||
if not collisionPrim and not collisionFile:
|
||||
print("Collisions..." + ob.data.name)
|
||||
for child in ob.children:
|
||||
if child.type == 'MESH':
|
||||
print("\tCollisions... " + child.data.name)
|
||||
#if child.rigid_body:
|
||||
# print("physics body")
|
||||
# if child.rigid_body.collision_shape == 'CONVEX_HULL':
|
||||
# collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
# elif child.rigid_body.collision_shape == 'MESH':
|
||||
# collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
# break
|
||||
if child.subcollision and child.name.startswith('DECIMATE'):
|
||||
collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
break
|
||||
elif "collision_type" in child and child.name.startswith('DECIMATE'):
|
||||
collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
break
|
||||
elif "collision_type" in child:
|
||||
collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
break
|
||||
if collisionFile:
|
||||
print("CollisionFile:")
|
||||
mesh_collision_files[ ob.data.name ] = collisionFile
|
||||
mesh.dot_mesh(child, path, force_name='%s_collision_%s' % (prefix, ob.data.name) )
|
||||
skeleton.dot_skeleton(child, path)
|
||||
|
||||
if not collisionPrim and not collisionFile:
|
||||
for child in ob.children:
|
||||
if child.subcollision and child.name.startswith('DECIMATE'):
|
||||
collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
break
|
||||
if child.name.endswith("-collision")
|
||||
collisionFile = '%s_collision_%s.mesh' % (prefix, ob.data.name)
|
||||
if collisionFile:
|
||||
mesh_collision_files[ ob.data.name ] = collisionFile
|
||||
mesh.dot_mesh(child, path, force_name='%s_collision_%s' % (prefix, ob.data.name) )
|
||||
skeleton.dot_skeleton(child, path)
|
||||
|
||||
if collisionPrim:
|
||||
e.setAttribute('collisionPrim', collisionPrim )
|
||||
elif collisionFile:
|
||||
e.setAttribute('collisionFile', collisionFile )
|
||||
if collisionPrim:
|
||||
e.setAttribute('collisionPrim', collisionPrim )
|
||||
elif collisionFile:
|
||||
e.setAttribute('collisionFile', collisionFile )
|
||||
|
||||
#if config.get('EXPORT_USER') is True:
|
||||
_mesh_entity_helper( doc, ob, e )
|
||||
|
||||
@@ -769,14 +769,21 @@ def get_subcollision_meshes():
|
||||
''' returns all collision meshes found in the scene '''
|
||||
r = []
|
||||
for ob in bpy.context.scene.objects:
|
||||
if ob.type=='MESH' and ob.subcollision: r.append( ob )
|
||||
if ob.type=='MESH' and (ob.subcollision or "collision_type" in ob):
|
||||
r.append( ob )
|
||||
return r
|
||||
|
||||
def get_objects_with_subcollision():
|
||||
''' returns objects that have active sub-collisions '''
|
||||
r = []
|
||||
for ob in bpy.context.scene.objects:
|
||||
if ob.type=='MESH' and ob.collision_mode not in ('NONE', 'PRIMITIVE'):
|
||||
if ob.type != 'MESH':
|
||||
continue
|
||||
if not ob.rigid_body:
|
||||
continue
|
||||
if ob.rigid_body.collision_shape in ('CONVEX_HULL', 'MESH'):
|
||||
r.append( ob )
|
||||
elif ob.type=='MESH' and not ob.collision_mode in ('NONE', 'PRIMITIVE'):
|
||||
r.append( ob )
|
||||
return r
|
||||
|
||||
@@ -784,7 +791,7 @@ def get_subcollisions(ob):
|
||||
prefix = '%s.' %ob.collision_mode
|
||||
r = []
|
||||
for child in ob.children:
|
||||
if child.subcollision and child.name.startswith( prefix ):
|
||||
if (child.subcollision or "collision_type" in ob) and child.name.startswith( prefix ):
|
||||
r.append( child )
|
||||
return r
|
||||
|
||||
|
||||
@@ -11,13 +11,18 @@ from math import radians, pi
|
||||
argv = sys.argv
|
||||
argv = argv[argv.index("--") + 1:]
|
||||
|
||||
sys.path.insert(0, os.getcwd() + "/assets/blender/scripts")
|
||||
sys.path.insert(1, os.getcwd() + "/assets/blender/scripts/blender2ogre")
|
||||
incpath = os.path.dirname(__file__)
|
||||
|
||||
sys.path.insert(0, incpath)
|
||||
sys.path.insert(1, incpath + "/blender2ogre")
|
||||
|
||||
|
||||
import io_ogre
|
||||
io_ogre.register()
|
||||
|
||||
gltf_file = argv[0]
|
||||
print("Exporting to " + gltf_file)
|
||||
basepath = os.getcwd()
|
||||
basepath = incpath
|
||||
# bpy.ops.export_scene.gltf(filepath="", check_existing=True,
|
||||
# export_import_convert_lighting_mode='SPEC', gltf_export_id="",
|
||||
# export_format='GLB', ui_tab='GENERAL', export_copyright="", export_image_format='AUTO',
|
||||
@@ -47,6 +52,7 @@ for obj in bpy.data.objects:
|
||||
bpy.data.objects.remove(obj)
|
||||
|
||||
scene_file = gltf_file.replace(".glb", "").replace(".gltf", "") + ".scene"
|
||||
|
||||
bpy.ops.ogre.export(filepath=scene_file,
|
||||
EX_SWAP_AXIS='xz-y',
|
||||
EX_V2_MESH_TOOL_VERSION='v2',
|
||||
|
||||
Binary file not shown.
@@ -277,6 +277,7 @@ function BoatControlQuest()
|
||||
ecs_character("set-actuator", ent, "sitting")
|
||||
ecs_set_slot(this.boat.boat_id, ent, "seat1")
|
||||
ecs_character("set-actuator", ent, "sitting")
|
||||
print("SLOT", "captain_seat", "boo1")
|
||||
ecs_set_slot(this.boat.boat_id, ent, "captain_seat")
|
||||
ecs_character("set-actuator", ent, "sitting")
|
||||
end
|
||||
@@ -420,6 +421,7 @@ function create_boat()
|
||||
ecs_character("physics-control", npc_id, false)
|
||||
ecs_character("params-set", npc_id, "gravity", false)
|
||||
ecs_character("params-set", npc_id, "buoyancy", false)
|
||||
print("SLOT", "captain_seat", "boo")
|
||||
ecs_set_slot(boat.boat_id, npc_id, "captain_seat")
|
||||
ecs_character("set-actuator", npc_id, "sitting")
|
||||
-- ecs_set_animation_state(npc_id, "main", "actuator", true)
|
||||
@@ -466,6 +468,7 @@ function create_actuator2(ent)
|
||||
end
|
||||
table.insert(this.contained, what)
|
||||
this.activated = true
|
||||
print("position: ", _ecs.position(what).y)
|
||||
end,
|
||||
exit = function(this, what)
|
||||
print(this.id, "left by", what)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
project(morph)
|
||||
add_executable(MorphTargetsResearch MorphTargetsResearch.cpp)
|
||||
target_link_libraries(MorphTargetsResearch OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${ASSIMP_LIBRARIES}
|
||||
target_link_libraries(MorphTargetsResearch OgreBites OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${ASSIMP_LIBRARIES}
|
||||
-Wl,--as-needed
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
|
||||
@@ -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>();
|
||||
|
||||
205
terrain.cpp
205
terrain.cpp
@@ -6,9 +6,6 @@
|
||||
// #include <OgreRenderTarget.h>
|
||||
|
||||
#include "OgreApplicationContext.h"
|
||||
#include "Bullet/OgreBullet.h"
|
||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "OgrePageManager.h"
|
||||
#include "lua_control.h"
|
||||
|
||||
@@ -21,11 +18,8 @@ using Real = Ogre::Real;
|
||||
using Math = Ogre::Math;
|
||||
|
||||
class WorldData {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
std::unique_ptr<Ogre::Root> mRoot;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
std::unique_ptr<btDynamicsWorld> mbtWorld;
|
||||
std::unique_ptr<Ogre::PageManager> mPageManager;
|
||||
Ogre::PagedWorld *mPagedWorld;
|
||||
float fps_time;
|
||||
@@ -64,13 +58,8 @@ private:
|
||||
|
||||
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr,
|
||||
Ogre::RenderWindow *renderWindow)
|
||||
: mDynWorld(new Ogre::Bullet::DynamicsWorld(
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, mDbgDraw(new Ogre::Bullet::DebugDrawer(
|
||||
scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
|
||||
, mRoot(root)
|
||||
: mRoot(root)
|
||||
, mScnMgr(scnMgr)
|
||||
, mbtWorld(mDynWorld->getBtWorld())
|
||||
, mPageManager(nullptr)
|
||||
, mPagedWorld(nullptr)
|
||||
, mRenderWindow(renderWindow)
|
||||
@@ -105,94 +94,8 @@ public:
|
||||
void createTrimesh(Ogre::Entity *entity)
|
||||
{
|
||||
}
|
||||
btPairCachingGhostObject *addGhostObject(Ogre::Entity *ent,
|
||||
btCollisionShape *shape,
|
||||
int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
btPairCachingGhostObject *ghost =
|
||||
new btPairCachingGhostObject();
|
||||
ghost->setCollisionShape(shape);
|
||||
ghost->setCollisionFlags(
|
||||
ghost->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
getWorld()->attachCollisionObject(ghost, ent, group, mask);
|
||||
#if 0
|
||||
getBtWorld()
|
||||
->getBroadphase()->getOverlappingPairCache()
|
||||
->setInternalGhostPairCallback(new btGhostPairCallback());
|
||||
ghost->setUserPointer(new Ogre::Bullet::EntityCollisionListener{ent, nullptr});
|
||||
#endif
|
||||
return ghost;
|
||||
}
|
||||
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct, int group = 1,
|
||||
int mask = 0xFFFF)
|
||||
{
|
||||
btDynamicsWorld *world = mDynWorld->getBtWorld();
|
||||
Ogre::SceneNode *node = ent->getParentSceneNode();
|
||||
Ogre::Bullet::RigidBodyState *state =
|
||||
new Ogre::Bullet::RigidBodyState(node);
|
||||
btCollisionShape *cs;
|
||||
btCollisionShape *shape;
|
||||
btVector3 inertia(0, 0, 0);
|
||||
switch (ct) {
|
||||
case Ogre::Bullet::CT_TRIMESH: {
|
||||
cs = Ogre::Bullet::createTrimeshCollider(ent);
|
||||
if (mass != 0)
|
||||
cs->calculateLocalInertia(mass, inertia);
|
||||
} break;
|
||||
case Ogre::Bullet::CT_CAPSULE: {
|
||||
cs = new btCompoundShape(false);
|
||||
btScalar height = 1.0f;
|
||||
btScalar radius = 0.3f;
|
||||
shape = new btCapsuleShape(radius,
|
||||
2 * height - 2 * radius);
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1, 0));
|
||||
static_cast<btCompoundShape *>(cs)->addChildShape(
|
||||
transform, shape);
|
||||
btScalar masses[1] = { mass };
|
||||
btTransform principal;
|
||||
static_cast<btCompoundShape *>(cs)
|
||||
->calculatePrincipalAxisTransform(
|
||||
masses, principal, inertia);
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
btRigidBody *body = new btRigidBody(mass, state, cs, inertia);
|
||||
getWorld()->attachRigidBody(body, ent, nullptr, group, mask);
|
||||
#if 0
|
||||
body->setUserPointer(new EntityCollisionListener{ent, nullptr});
|
||||
// btRigidBody *body = mDynWorld->addRigidBody(0, ent, Ogre::Bullet::CT_TRIMESH);
|
||||
#endif
|
||||
return body;
|
||||
}
|
||||
btRigidBody *addKinematicRigidBody(float mass, Ogre::Entity *ent,
|
||||
Ogre::Bullet::ColliderType ct,
|
||||
int group = 1, int mask = 0xFFFF)
|
||||
{
|
||||
return mDynWorld->addKinematicRigidBody(ent, ct, group, mask);
|
||||
}
|
||||
btDynamicsWorld *getBtWorld()
|
||||
{
|
||||
return mDynWorld->getBtWorld();
|
||||
}
|
||||
Ogre::Bullet::DynamicsWorld *getWorld()
|
||||
{
|
||||
return mDynWorld.get();
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
WorldData::get_singleton()->getBtWorld()->stepSimulation(delta,
|
||||
50);
|
||||
mDbgDraw->update();
|
||||
fps_time += delta;
|
||||
if (fps_time > 1.0f) {
|
||||
fps_time -= 1.0f;
|
||||
@@ -213,8 +116,6 @@ public:
|
||||
WorldData *WorldData::singleton = nullptr;
|
||||
|
||||
class MainWorld : public Ogre::FrameListener {
|
||||
btRigidBody *mFloorBody;
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
@@ -232,13 +133,6 @@ public:
|
||||
WorldData::get_singleton()->getSceneManager();
|
||||
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
|
||||
scnMgr->getRootSceneNode()->attachObject(floor);
|
||||
mFloorBody = WorldData::get_singleton()->addRigidBody(
|
||||
0, floor, Ogre::Bullet::CT_TRIMESH);
|
||||
}
|
||||
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
|
||||
{
|
||||
return WorldData::get_singleton()->addKinematicRigidBody(
|
||||
mass, ent, Ogre::Bullet::CT_COMPOUND);
|
||||
}
|
||||
bool frameStarted(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
@@ -278,8 +172,6 @@ class CharacterController : public OgreBites::InputListener,
|
||||
Ogre::Vector3 rootMotion;
|
||||
Ogre::Quaternion rootRotation;
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
|
||||
@@ -328,35 +220,6 @@ private:
|
||||
recoverResult *recover_result,
|
||||
const std::set<btCollisionObject *> &exclude);
|
||||
#endif
|
||||
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());
|
||||
}
|
||||
};
|
||||
CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
Ogre::Camera *cam,
|
||||
@@ -370,8 +233,6 @@ CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
, mAnimID(ANIM_NONE)
|
||||
, mRunning(false)
|
||||
, world(world)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
{
|
||||
setupBody();
|
||||
setupCamera();
|
||||
@@ -388,70 +249,6 @@ void CharacterController::setupBody()
|
||||
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);
|
||||
WorldData::get_singleton()->getWorld()->attachCollisionObject(
|
||||
mGhostObject, mBodyEnt, btBroadphaseProxy::AllFilter,
|
||||
btBroadphaseProxy::AllFilter);
|
||||
WorldData::get_singleton()->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);
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
project(tests)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bullet CONFIG)
|
||||
find_package(Bullet REQUIRED)
|
||||
add_executable(compound_shapes compound_shapes.cpp)
|
||||
target_link_libraries(compound_shapes OgreBullet ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
include_directories(${BULLET_INCLUDE_DIRS})
|
||||
|
||||
add_custom_target(tests ALL DEPENDS compound_shapes)
|
||||
@@ -1,290 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <OgreBullet.h>
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
#include <btBulletCollisionCommon.h>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
|
||||
struct objects {
|
||||
btDynamicsWorld *world;
|
||||
btRigidBody *groundBody;
|
||||
btPairCachingGhostObject *characterBody;
|
||||
btPairCachingGhostObject *waterBody;
|
||||
};
|
||||
void setupGround(btDynamicsWorld *world, struct objects *objects)
|
||||
{
|
||||
// Static ground
|
||||
btCollisionShape *groundShape =
|
||||
new btBoxShape(btVector3(1000, 1, 1000));
|
||||
btDefaultMotionState *groundMotionState = new btDefaultMotionState(
|
||||
btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, -10, 0)));
|
||||
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(
|
||||
0, groundMotionState, groundShape, btVector3(0, 0, 0));
|
||||
btRigidBody *groundRigidBody = new btRigidBody(groundRigidBodyCI);
|
||||
world->addRigidBody(groundRigidBody, 2, 0x7fffffff & ~16);
|
||||
objects->groundBody = groundRigidBody;
|
||||
}
|
||||
void setupCharacter(btDynamicsWorld *world, struct objects *objects)
|
||||
{
|
||||
btCompoundShape *shape = new btCompoundShape();
|
||||
btCapsuleShape *subshape = new btCapsuleShape(0.2f, 1.5f);
|
||||
btTransform shapePos;
|
||||
shapePos.setIdentity();
|
||||
shapePos.setOrigin(btVector3(0, 0.75f, 0));
|
||||
shape->addChildShape(shapePos, subshape);
|
||||
btPairCachingGhostObject *characterBody =
|
||||
new btPairCachingGhostObject();
|
||||
characterBody->setCollisionFlags(
|
||||
characterBody->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
btTransform bodyPos;
|
||||
bodyPos.setIdentity();
|
||||
bodyPos.setOrigin(btVector3(0, 0.4f, 0));
|
||||
characterBody->setWorldTransform(bodyPos);
|
||||
characterBody->setCollisionShape(shape);
|
||||
world->addCollisionObject(characterBody, 1, 0x7fffffff);
|
||||
objects->characterBody = characterBody;
|
||||
}
|
||||
void setupWater(btDynamicsWorld *world, struct objects *objects)
|
||||
{
|
||||
btCompoundShape *shape = new btCompoundShape();
|
||||
btBoxShape *subshape =
|
||||
new btBoxShape(btVector3(1000.0f, 100.0f, 1000.0f));
|
||||
btTransform shapePos;
|
||||
shapePos.setIdentity();
|
||||
shapePos.setOrigin(btVector3(0, -100, 0));
|
||||
shape->addChildShape(shapePos, subshape);
|
||||
btPairCachingGhostObject *waterBody = new btPairCachingGhostObject();
|
||||
waterBody->setCollisionFlags(waterBody->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
btTransform bodyPos;
|
||||
bodyPos.setIdentity();
|
||||
waterBody->setWorldTransform(bodyPos);
|
||||
waterBody->setCollisionShape(shape);
|
||||
world->addCollisionObject(waterBody, 16, 0x7fffffff & ~2);
|
||||
objects->waterBody = waterBody;
|
||||
}
|
||||
struct DeepPenetrationContactResultCallback : public btManifoldResult {
|
||||
DeepPenetrationContactResultCallback(
|
||||
const btCollisionObjectWrapper *body0Wrap,
|
||||
const btCollisionObjectWrapper *body1Wrap)
|
||||
: btManifoldResult(body0Wrap, body1Wrap)
|
||||
, mPenetrationDistance(0)
|
||||
, mOtherIndex(0)
|
||||
{
|
||||
}
|
||||
float mPenetrationDistance;
|
||||
int mOtherIndex;
|
||||
btVector3 mNormal, mPoint;
|
||||
void reset()
|
||||
{
|
||||
mPenetrationDistance = 0.0f;
|
||||
}
|
||||
bool hasHit()
|
||||
{
|
||||
return mPenetrationDistance < 0.0f;
|
||||
}
|
||||
virtual void addContactPoint(const btVector3 &normalOnBInWorld,
|
||||
const btVector3 &pointInWorldOnB,
|
||||
btScalar depth)
|
||||
{
|
||||
std::cout
|
||||
<< "contact: " << Ogre::Bullet::convert(pointInWorldOnB)
|
||||
<< " " << Ogre::Bullet::convert(normalOnBInWorld)
|
||||
<< "\n";
|
||||
if (mPenetrationDistance > depth) { // Has penetration?
|
||||
|
||||
const bool isSwapped =
|
||||
m_manifoldPtr->getBody0() !=
|
||||
m_body0Wrap->getCollisionObject();
|
||||
mPenetrationDistance = depth;
|
||||
mOtherIndex = isSwapped ? m_index0 : m_index1;
|
||||
mPoint = isSwapped ? (pointInWorldOnB +
|
||||
(normalOnBInWorld * depth)) :
|
||||
pointInWorldOnB;
|
||||
|
||||
mNormal = isSwapped ? normalOnBInWorld * -1 :
|
||||
normalOnBInWorld;
|
||||
}
|
||||
}
|
||||
};
|
||||
void dumpCompoundShape(const char *what, const btCollisionObject *body)
|
||||
{
|
||||
if (body->getCollisionShape()->isCompound()) {
|
||||
const btCompoundShape *shape =
|
||||
static_cast<const btCompoundShape *>(
|
||||
body->getCollisionShape());
|
||||
int i;
|
||||
for (i = 0; i < shape->getNumChildShapes(); i++) {
|
||||
btTransform transform = body->getWorldTransform() *
|
||||
shape->getChildTransform(i);
|
||||
std::cout << what << ": " << " shape: " << i << ": "
|
||||
<< transform.getOrigin().getX() << ", ";
|
||||
std::cout << transform.getOrigin().getY() << ", ";
|
||||
std::cout << transform.getOrigin().getZ();
|
||||
std::cout << " convex: "
|
||||
<< shape->getChildShape(i)->isConvex();
|
||||
std::cout << " shape name: "
|
||||
<< shape->getChildShape(i)->getName();
|
||||
switch (shape->getChildShape(i)->getShapeType()) {
|
||||
case 0: {
|
||||
const btBoxShape *box =
|
||||
static_cast<const btBoxShape *>(
|
||||
shape->getChildShape(i));
|
||||
btVector3 hextents =
|
||||
box->getHalfExtentsWithoutMargin();
|
||||
std::cout << " box: " << hextents.getX() << ", "
|
||||
<< hextents.getY() << ", "
|
||||
<< hextents.getZ();
|
||||
} break;
|
||||
case 10: {
|
||||
const btCapsuleShape *capsule =
|
||||
static_cast<const btCapsuleShape *>(
|
||||
shape->getChildShape(i));
|
||||
float hh = capsule->getHalfHeight();
|
||||
float r = capsule->getRadius();
|
||||
std::cout << " capsule: " << hh << ", " << r;
|
||||
} break;
|
||||
default:
|
||||
std::cout << " shape type: "
|
||||
<< shape->getChildShape(i)
|
||||
->getShapeType();
|
||||
break;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
void showContacts(btCollisionWorld *world, struct objects *objects)
|
||||
{
|
||||
int numManifolds = world->getDispatcher()->getNumManifolds();
|
||||
if (numManifolds == 0)
|
||||
std::cout << "No contacts in world\n";
|
||||
for (int i = 0; i < numManifolds; i++) {
|
||||
btPersistentManifold *contactManifold =
|
||||
world->getDispatcher()->getManifoldByIndexInternal(i);
|
||||
const btCollisionObject *obA = contactManifold->getBody0();
|
||||
const btCollisionObject *obB = contactManifold->getBody1();
|
||||
|
||||
int numContacts = contactManifold->getNumContacts();
|
||||
for (int j = 0; j < numContacts; j++) {
|
||||
btManifoldPoint &pt =
|
||||
contactManifold->getContactPoint(j);
|
||||
if (pt.getDistance() < 0.f) {
|
||||
const btVector3 &ptA = pt.getPositionWorldOnA();
|
||||
const btVector3 &ptB = pt.getPositionWorldOnB();
|
||||
const btVector3 &normalOnB =
|
||||
pt.m_normalWorldOnB;
|
||||
std::cout << "contact: " << i << " " << j << " "
|
||||
<< ptA.getX() << ", " << ptA.getY()
|
||||
<< ", " << ptA.getZ() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int main()
|
||||
{
|
||||
struct objects objects;
|
||||
btDefaultCollisionConfiguration collisionConfig;
|
||||
btCollisionDispatcher dispatcher(&collisionConfig);
|
||||
btCollisionDispatcher *dispatch = &dispatcher;
|
||||
btDbvtBroadphase broadphase;
|
||||
btSequentialImpulseConstraintSolver solver;
|
||||
btDiscreteDynamicsWorld world(&dispatcher, &broadphase, &solver,
|
||||
&collisionConfig);
|
||||
world.setGravity(btVector3(0, -9.81, 0));
|
||||
setupGround(&world, &objects);
|
||||
setupCharacter(&world, &objects);
|
||||
setupWater(&world, &objects);
|
||||
|
||||
#if 0
|
||||
btCompoundShape *compoundShape = new btCompoundShape();
|
||||
|
||||
// Add shapes to the compound shape
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
btBoxShape *box = new btBoxShape(btVector3(1, 1, 1));
|
||||
btTransform transform;
|
||||
transform.setIdentity();
|
||||
transform.setOrigin(btVector3(0, 1 - i, 0));
|
||||
compoundShape->addChildShape(transform, box);
|
||||
}
|
||||
|
||||
btDefaultMotionState *compoundMotionState = new btDefaultMotionState(
|
||||
btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 10, 0)));
|
||||
btScalar mass = 5.0;
|
||||
btVector3 inertia(0, 0, 0);
|
||||
compoundShape->calculateLocalInertia(mass, inertia);
|
||||
btRigidBody::btRigidBodyConstructionInfo compoundRigidBodyCI(
|
||||
mass, compoundMotionState, compoundShape, inertia);
|
||||
btRigidBody *compoundRigidBody = new btRigidBody(compoundRigidBodyCI);
|
||||
world.addRigidBody(compoundRigidBody);
|
||||
#endif
|
||||
|
||||
// Simulation
|
||||
btVector3 velocity(0, 0, 0);
|
||||
for (int i = 0; i < 300; i++) {
|
||||
world.stepSimulation(1.f / 60.f, 10);
|
||||
showContacts(&world, &objects);
|
||||
|
||||
#if 0
|
||||
btTransform transform;
|
||||
compoundRigidBody->getMotionState()->getWorldTransform(
|
||||
transform);
|
||||
std::cout << "Step " << i
|
||||
<< ": Position = " << transform.getOrigin().getX()
|
||||
<< ", " << transform.getOrigin().getY() << ", "
|
||||
<< transform.getOrigin().getZ() << std::endl;
|
||||
std::cout << "water overlaps:"
|
||||
<< objects.waterBody->getOverlappingPairCache()
|
||||
->getNumOverlappingPairs()
|
||||
<< "\n";
|
||||
#endif
|
||||
btTransform transform;
|
||||
transform = objects.characterBody->getWorldTransform();
|
||||
std::cout << "Step " << i << " ";
|
||||
std::cout << "Character: "
|
||||
<< "Position = " << transform.getOrigin().getX()
|
||||
<< ", " << transform.getOrigin().getY() << ", "
|
||||
<< transform.getOrigin().getZ() << std::endl;
|
||||
transform = objects.waterBody->getWorldTransform();
|
||||
std::cout << "Water: "
|
||||
<< "Position = " << transform.getOrigin().getX()
|
||||
<< ", " << transform.getOrigin().getY() << ", "
|
||||
<< transform.getOrigin().getZ() << std::endl;
|
||||
std::cout << "water overlaps:"
|
||||
<< objects.waterBody->getOverlappingPairCache()
|
||||
->getNumOverlappingPairs()
|
||||
<< "\n";
|
||||
dumpCompoundShape("Character", objects.characterBody);
|
||||
dumpCompoundShape("Water", objects.waterBody);
|
||||
btCollisionObjectWrapper obA(
|
||||
NULL, objects.waterBody->getCollisionShape(),
|
||||
objects.waterBody,
|
||||
objects.waterBody->getWorldTransform(), -1, 0);
|
||||
btCollisionObjectWrapper obB(
|
||||
NULL, objects.characterBody->getCollisionShape(),
|
||||
objects.characterBody,
|
||||
objects.characterBody->getWorldTransform(), -1, 0);
|
||||
std::cout << __func__ << ": call findAlgorithm: ";
|
||||
btCollisionAlgorithm *algorithm = dispatch->findAlgorithm(
|
||||
&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS);
|
||||
std::cout << "found algorithm: " << algorithm << "\n";
|
||||
if (!algorithm)
|
||||
continue;
|
||||
std::cout << "algorithm: " << algorithm << "\n";
|
||||
DeepPenetrationContactResultCallback contactPointResult(&obA,
|
||||
&obB);
|
||||
std::cout << "process collision\n";
|
||||
algorithm->processCollision(&obA, &obB, world.getDispatchInfo(),
|
||||
&contactPointResult);
|
||||
algorithm->~btCollisionAlgorithm();
|
||||
dispatch->freeCollisionAlgorithm(algorithm);
|
||||
if (contactPointResult.hasHit()) {
|
||||
std::cout << "InWater!!1\n";
|
||||
}
|
||||
velocity += btVector3(0, -9.8, 0) * 1.0f / 16.0f;
|
||||
objects.characterBody->getWorldTransform().getOrigin() += velocity * 1.0f / 16.0f;
|
||||
std::cout << "process collision done\n";
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <OgreMeshLodGenerator.h>
|
||||
#include <OgreCompositorManager.h>
|
||||
#include <OgreMaterialManager.h>
|
||||
#include <OgreBullet.h>
|
||||
#include "water.h"
|
||||
|
||||
/* TODO: use blender glb model for water shape.
|
||||
@@ -32,8 +31,10 @@ Water::Water()
|
||||
, mRefractionClipPlaneBelow(Ogre::Vector3(0.0, 1.0, 0.0),
|
||||
0.0f /* water height */ - 2.0)
|
||||
, mAbove(true)
|
||||
#if 0
|
||||
, mWaterBody(nullptr)
|
||||
, mDynWorld(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,6 +44,7 @@ Water::~Water()
|
||||
mScnMgr->destroySceneNode(mWaterNode);
|
||||
if (mReflectionTexture)
|
||||
mReflectionTexture->removeAllListeners();
|
||||
#if 0
|
||||
if (mWaterBody) {
|
||||
if (mWaterBody->getWorldArrayIndex() >= 0)
|
||||
if (mDynWorld)
|
||||
@@ -51,6 +53,7 @@ Water::~Water()
|
||||
delete mWaterBody;
|
||||
mWaterBody = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Water::create_cameras()
|
||||
@@ -167,11 +170,13 @@ void Water::init()
|
||||
water_ent->setMaterial(mat);
|
||||
mWaterNode->attachObject(water_ent);
|
||||
mWaterMeshes.push_back(water_ent);
|
||||
#if 0
|
||||
mDynWorld->attachCollisionObject(mWaterBody, water_ent, 1, 0x7FFFFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Water::createWater(Ogre::RenderWindow *window, Ogre::Camera *camera,
|
||||
Ogre::Bullet::DynamicsWorld *world)
|
||||
void Water::createWater(Ogre::RenderWindow *window, Ogre::Camera *camera /*,
|
||||
Ogre::Bullet::DynamicsWorld *world */)
|
||||
{
|
||||
int i;
|
||||
mCamera = camera;
|
||||
@@ -181,6 +186,7 @@ void Water::createWater(Ogre::RenderWindow *window, Ogre::Camera *camera,
|
||||
mWindow = window;
|
||||
mCameraPosition = mCameraNode->getPosition();
|
||||
create_textures();
|
||||
#if 0
|
||||
mDynWorld = world;
|
||||
mWaterBody = new btGhostObject;
|
||||
btBoxShape *boxShape = new btBoxShape(btVector3(1000, 1000, 1000));
|
||||
@@ -192,6 +198,7 @@ void Water::createWater(Ogre::RenderWindow *window, Ogre::Camera *camera,
|
||||
mWaterBody->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE |
|
||||
btCollisionObject::CF_STATIC_OBJECT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Water::updateWater(float delta)
|
||||
@@ -228,11 +235,13 @@ void Water::updateWater(float delta)
|
||||
mViewports[i]->update();
|
||||
for (i = 0; i < mWaterMeshes.size(); i++)
|
||||
mWaterMeshes[i]->setVisible(true);
|
||||
#if 0
|
||||
mOverlaps.clear();
|
||||
for (i = 0; i < mWaterBody->getNumOverlappingObjects(); i++) {
|
||||
btCollisionObject *sb = mWaterBody->getOverlappingObject(i);
|
||||
mOverlaps.insert(sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
|
||||
|
||||
@@ -24,17 +24,20 @@ class Water : public /* Ogre::FrameListener, */ Ogre::RenderTargetListener {
|
||||
bool mInRefTexUpdate;
|
||||
Ogre::Timer mtexture_dump;
|
||||
void create_cameras();
|
||||
#if 0
|
||||
btGhostObject *mWaterBody;
|
||||
Ogre::Bullet::DynamicsWorld *mDynWorld;
|
||||
std::set<btCollisionObject *> mOverlaps;
|
||||
#endif
|
||||
|
||||
public:
|
||||
Water();
|
||||
virtual ~Water();
|
||||
void create_textures();
|
||||
void dump_textures();
|
||||
void createWater(Ogre::RenderWindow *window, Ogre::Camera *camera,
|
||||
Ogre::Bullet::DynamicsWorld *world);
|
||||
void createWater(
|
||||
Ogre::RenderWindow *window,
|
||||
Ogre::Camera *camera /*, Ogre::Bullet::DynamicsWorld *world */);
|
||||
void init();
|
||||
void updateWater(float delta);
|
||||
/* bool frameEnded(const Ogre::FrameEvent &evt) override; */
|
||||
@@ -44,10 +47,12 @@ public:
|
||||
postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override;
|
||||
void add_submerged_entity(Ogre::Entity *ent);
|
||||
void add_surface_entity(Ogre::Entity *ent);
|
||||
#if 0
|
||||
bool isInWater(const btCollisionObject *body) const
|
||||
{
|
||||
btCollisionObject *test = const_cast<btCollisionObject *>(body);
|
||||
return mOverlaps.find(test) != mOverlaps.end();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user