Compare commits
2 Commits
2349bbc77e
...
503db60c60
| Author | SHA1 | Date | |
|---|---|---|---|
| 503db60c60 | |||
| c730ca5222 |
@@ -1,5 +1,5 @@
|
||||
project(world2)
|
||||
cmake_minimum_required(VERSION 3.13.0)
|
||||
project(world2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(BLENDER ${CMAKE_SOURCE_DIR}/../../blender-bin/bin/blender)
|
||||
@@ -16,8 +16,6 @@ set(CREATE_DIRECTORIES
|
||||
# ${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
|
||||
# )
|
||||
|
||||
option(OGRE_DYNAMIC "Build against dynamic ogre" ON)
|
||||
|
||||
# workaround horribly broken assimp cmake, fixed with assimp 5.1
|
||||
#add_library(assimp INTERFACE IMPORTED)
|
||||
#set_target_properties(assimp PROPERTIES
|
||||
@@ -55,7 +53,7 @@ set_target_properties(fix::OgreProcedural PROPERTIES
|
||||
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
|
||||
)
|
||||
|
||||
if(NOT OGRE_DYNAMIC)
|
||||
if(OGRE_STATIC)
|
||||
add_library(OgreGLSupportStatic INTERFACE IMPORTED)
|
||||
set_target_properties(OgreGLSupportStatic PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "OgreGLSupportStatic"
|
||||
@@ -78,21 +76,17 @@ 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})
|
||||
target_include_directories(0_Bootstrap PUBLIC OgreBites OgrePaging OgreBullet)
|
||||
add_dependencies(0_Bootstrap stage_files import_vrm)
|
||||
|
||||
add_executable(Editor Editor.cpp ${TERRAIN_SRC} ${WATER_SRC} ${CHARACTERS_SRC})
|
||||
target_link_libraries(Editor OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(Editor PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreMeshLodGenerator ${OgreProcedural_INCLUDE_DIRS})
|
||||
target_link_libraries(Editor OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
add_dependencies(Editor stage_files import_buildings import_water_stuff import_vehicles import_vrm)
|
||||
add_executable(Game Game.cpp ${TERRAIN_SRC} ${WATER_SRC} ${CHARACTERS_SRC})
|
||||
target_link_libraries(Game OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(Game PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreMeshLodGenerator ${OgreProcedural_INCLUDE_DIRS})
|
||||
target_link_libraries(Game OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
add_dependencies(Game stage_files import_buildings import_water_stuff import_vehicles import_vrm)
|
||||
|
||||
add_executable(Procedural Procedural.cpp ${TERRAIN_SRC})
|
||||
target_link_libraries(Procedural OgreBites OgreBullet OgrePaging OgreTerrain OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(Procedural PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreProcedural::OgreProcedural ${CMAKE_PREFIX_PATH}/include/OgreProcedural)
|
||||
add_dependencies(Procedural stage_files import_buildings)
|
||||
file(GLOB BUILDINGS_SRC ${CMAKE_SOURCE_DIR}/assets/blender/buildings/*.blend)
|
||||
set(BUILDING_OUTPUT_FILES)
|
||||
@@ -145,15 +139,14 @@ add_custom_target(import_water_stuff ALL DEPENDS ${WATER_STUFF})
|
||||
|
||||
add_executable(TerrainTest terrain.cpp ${TERRAIN_SRC})
|
||||
target_link_libraries(TerrainTest OgreBites OgreBullet OgrePaging OgreTerrain lua ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
|
||||
target_include_directories(TerrainTest PUBLIC OgreBites OgrePaging OgreTerrain OgreBullet PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
|
||||
if(NOT OGRE_DYNAMIC)
|
||||
target_include_directories(TerrainTest PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
|
||||
if(OGRE_STATIC)
|
||||
target_link_libraries(TerrainTest fix::assimp pugixml)
|
||||
target_link_libraries(Procedural fix::assimp pugixml)
|
||||
target_link_libraries(0_Bootstrap fix::assimp pugixml)
|
||||
target_link_libraries(Editor fix::assimp pugixml)
|
||||
endif()
|
||||
|
||||
|
||||
file(GLOB LUA_SCRIPTS_SRC ${CMAKE_SOURCE_DIR}/lua-scripts/*.lua)
|
||||
set(LUA_SCRIPTS_OUTPUT)
|
||||
foreach(LUA_SCRIPT_FILE ${LUA_SCRIPTS_SRC})
|
||||
|
||||
17
Game.cpp
17
Game.cpp
@@ -244,7 +244,7 @@ public:
|
||||
float panel_width;
|
||||
void initGui();
|
||||
};
|
||||
#undef WATER
|
||||
#define WATER
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
|
||||
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
|
||||
@@ -262,6 +262,7 @@ class App : public OgreBites::ApplicationContext {
|
||||
#ifdef WATER
|
||||
Water m_water;
|
||||
#endif
|
||||
bool mTerrainReady;
|
||||
class KeyboardListener : public OgreBites::InputListener,
|
||||
public Ogre::FrameListener {
|
||||
App *mApp;
|
||||
@@ -366,8 +367,10 @@ class App : public OgreBites::ApplicationContext {
|
||||
update(evt.timeSinceLastFrame);
|
||||
if (mApp->getCharacterController() && gui_active)
|
||||
mApp->getCharacterController()->disableUpdates();
|
||||
else if (mApp->getCharacterController() && !gui_active)
|
||||
else if (mApp->getCharacterController() && !gui_active && mApp->isTerrainReady()) {
|
||||
OgreAssert(mApp->isTerrainReady(), "terrain is not ready");
|
||||
mApp->getCharacterController()->enableUpdates();
|
||||
}
|
||||
if (!gui_active) {
|
||||
mApp->updateSun(evt.timeSinceLastFrame);
|
||||
mApp->updateTerrain(evt.timeSinceLastFrame);
|
||||
@@ -387,6 +390,7 @@ public:
|
||||
Ogre::Vector3(0, -9.8, 0)))
|
||||
, m_terrain(mDynWorld->getBtWorld())
|
||||
, mCharacterController(nullptr)
|
||||
, mTerrainReady(false)
|
||||
{
|
||||
}
|
||||
virtual ~App()
|
||||
@@ -550,6 +554,15 @@ public:
|
||||
Ogre::Timer mTerrainUpd;
|
||||
void updateTerrain(float delta)
|
||||
{
|
||||
Ogre::Vector3 pos = mCharacterController->getPosition();
|
||||
if (!mTerrainReady && m_terrain.isLoadedAt(pos) && mCharacterController->checkGround()) {
|
||||
std::cout << "terrain ready\n";
|
||||
mTerrainReady = true;
|
||||
}
|
||||
}
|
||||
bool isTerrainReady()
|
||||
{
|
||||
return mTerrainReady;
|
||||
}
|
||||
// TODO: implement rough water level calculation
|
||||
float getWaterLevel(const Ogre::Vector3 &position)
|
||||
|
||||
@@ -184,6 +184,7 @@ CharacterController::CharacterController(Ogre::SceneNode *camNode,
|
||||
, mWorld(world)
|
||||
, mCollisionShape(nullptr)
|
||||
, mGhostObject(nullptr)
|
||||
, gvelocity(0.0f, 0.0f, 0.0f)
|
||||
, mUpdate(false)
|
||||
{
|
||||
setupBody();
|
||||
@@ -231,12 +232,12 @@ void CharacterController::setupBody()
|
||||
mWorld->attachCollisionObject(mGhostObject, mBodyEnt,
|
||||
1,
|
||||
0x7FFFFFF);
|
||||
Ogre::Bullet::KinematicMotionSimple *controller =
|
||||
mController =
|
||||
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,
|
||||
mBodyNode);
|
||||
OgreAssert(mGhostObject, "Need GhostObject");
|
||||
OgreAssert(controller, "Need controller");
|
||||
mWorld->getBtWorld()->addAction(controller);
|
||||
OgreAssert(mController, "Need controller");
|
||||
mWorld->getBtWorld()->addAction(mController);
|
||||
|
||||
OgreAssert(mCollisionShape, "No collision shape");
|
||||
#if 0
|
||||
@@ -555,105 +556,48 @@ struct EntityCollisionListener
|
||||
const Ogre::MovableObject* entity;
|
||||
Ogre::Bullet::CollisionListener* listener;
|
||||
};
|
||||
static bool is_on_floor = false;
|
||||
static bool penetration = false;
|
||||
static int is_on_floor_count = 0;
|
||||
void CharacterController::updateRootMotion(Ogre::Real delta)
|
||||
{
|
||||
int i, j, k;
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
Ogre::Vector3 pos = mBodyNode->getPosition();
|
||||
Ogre::Vector3 boneMotion = mRootBone->getPosition();
|
||||
Ogre::Vector3 velocity = rot * boneMotion / delta;
|
||||
OgreAssert(delta > 0.0f, "Zero delta");
|
||||
int maxPen = 0;
|
||||
Ogre::Vector3 colNormal;
|
||||
btVector3 currentPosition = mGhostObject->getWorldTransform().getOrigin();
|
||||
for (i = 0; i < mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++) {
|
||||
btManifoldArray manifoldArray;
|
||||
btBroadphasePair *collisionPair = &mGhostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
||||
if (collisionPair->m_algorithm)
|
||||
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
|
||||
for (j = 0; j < manifoldArray.size(); j++) {
|
||||
btPersistentManifold * manifold = manifoldArray[j];
|
||||
btScalar directionSign = manifold->getBody0() == mGhostObject ? btScalar(-1) : btScalar(1);
|
||||
for (k = 0; k < manifold->getNumContacts(); k++) {
|
||||
const btManifoldPoint &pt = manifold->getContactPoint(k);
|
||||
btScalar dist = pt.getDistance();
|
||||
if (dist < 0) {
|
||||
maxPen = dist;
|
||||
btVector3 touchingNormal = pt.m_normalWorldOnB;
|
||||
colNormal = Ogre::Bullet::convert(touchingNormal);
|
||||
if (touchingNormal.y() > 0 && (
|
||||
touchingNormal.y() > Ogre::Math::Abs(touchingNormal.x()) ||
|
||||
touchingNormal.y() > Ogre::Math::Abs(touchingNormal.z())))
|
||||
is_on_floor = true;
|
||||
penetration = true;
|
||||
}
|
||||
currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
|
||||
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
std::cout << "overlapping: " << i << " "
|
||||
<< manifoldArray.size()
|
||||
<< " is_on_floor = " << is_on_floor
|
||||
<< " position: " << Ogre::Bullet::convert(currentPosition)
|
||||
<< " colNormal: " << colNormal
|
||||
<< " penetration: " << penetration
|
||||
<< " dist: " << maxPen << "\n";
|
||||
#endif
|
||||
}
|
||||
btTransform newTrans = mGhostObject->getWorldTransform();
|
||||
newTrans.setOrigin(currentPosition);
|
||||
#if 0
|
||||
Ogre::Vector3 motion = boneMotion - rootMotion;
|
||||
if (motion.squaredLength() > 0.1f * 0.1f)
|
||||
motion = Ogre::Vector3();
|
||||
rootMotion = boneMotion;
|
||||
#endif
|
||||
#if 0
|
||||
float mass = mRigidBody->getMass();
|
||||
std::cout << "Root bone position: " << boneMotion << "\n";
|
||||
std::cout << "body mass: " << mass << "\n";
|
||||
#endif
|
||||
/* Kinematic motion */
|
||||
if (is_on_floor)
|
||||
is_on_floor_count++;
|
||||
else
|
||||
is_on_floor_count--;
|
||||
Ogre::Quaternion rot = mBodyNode->getOrientation();
|
||||
bool is_on_floor = false;
|
||||
bool penetration = false;
|
||||
Ogre::Vector3 gravity(0, -9.8, 0);
|
||||
Ogre::Vector3 velocity = rot * boneMotion / delta;
|
||||
if (is_on_floor_count < 0 && !penetration)
|
||||
velocity += gravity;
|
||||
if (is_on_floor_count < 0 && penetration)
|
||||
velocity += gravity * delta;
|
||||
if (is_on_floor_count < -1)
|
||||
is_on_floor_count = -1;
|
||||
if (is_on_floor_count > 1)
|
||||
is_on_floor_count = 1;
|
||||
gvelocity += gravity * delta;
|
||||
velocity += gvelocity;
|
||||
Ogre::Vector3 rotMotion = velocity * delta;
|
||||
btVector3 currentPosition = mGhostObject->getWorldTransform().getOrigin();
|
||||
is_on_floor = mController->isOnFloor();
|
||||
penetration = mController->isPenetrating();
|
||||
if (is_on_floor)
|
||||
gvelocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
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 *>());
|
||||
#if 0
|
||||
if (mGhostObject->getNumOverlappingObjects() > 0) {
|
||||
int i;
|
||||
std::cout << "overlaps: " << mGhostObject->getNumOverlappingObjects() << "\n";
|
||||
for (i = 0; i < mGhostObject->getNumOverlappingObjects(); i++) {
|
||||
btCollisionObject *collided = nullptr;
|
||||
EntityCollisionListener *a = nullptr;
|
||||
collided = mGhostObject->getOverlappingObject(i);
|
||||
if (collided)
|
||||
a = static_cast<EntityCollisionListener*>(collided->getUserPointer());
|
||||
std::cout << i << " " << collided << " " << a << " ";
|
||||
if (a)
|
||||
std::cout << a->entity << " ";
|
||||
if (a->entity)
|
||||
std::cout << a->entity->getName();
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
std::cout << "rotMotion: " << rotMotion
|
||||
<< " isOnFloor: " << is_on_floor
|
||||
<< " pairs: " << mGhostObject->getOverlappingPairCache()->getNumOverlappingPairs()
|
||||
<< " manifolds: " << mController->getManifolds()
|
||||
<< " penetration: " << penetration << "\n";
|
||||
std::cout << " position: " << mBodyNode->getPosition() << "\n";
|
||||
#endif
|
||||
#if 0
|
||||
std::cout
|
||||
<< " velocity: " << velocity
|
||||
<< " penetration: " << penetration
|
||||
<< " rotMotion: " << rotMotion
|
||||
<< "\n";
|
||||
std::cout << "old position: " << pos
|
||||
<< " new position: " << mBodyNode->getPosition()
|
||||
<< "\n";
|
||||
#endif
|
||||
}
|
||||
void CharacterController::fadeAnimations(Ogre::Real delta)
|
||||
|
||||
@@ -80,8 +80,10 @@ class CharacterController : public OgreBites::InputListener,
|
||||
// btRigidBody *mRigidBody;
|
||||
btCompoundShape *mCollisionShape;
|
||||
btPairCachingGhostObject *mGhostObject;
|
||||
Ogre::Vector3 gvelocity;
|
||||
|
||||
bool mUpdate;
|
||||
Ogre::Bullet::KinematicMotionSimple *mController;
|
||||
|
||||
public:
|
||||
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
|
||||
@@ -174,4 +176,42 @@ public:
|
||||
{
|
||||
return mUpdate;
|
||||
}
|
||||
Ogre::Vector3 getPosition() const
|
||||
{
|
||||
return mBodyNode->getPosition();
|
||||
}
|
||||
Ogre::Quaternion getRotation() const
|
||||
{
|
||||
return mBodyNode->getOrientation();
|
||||
}
|
||||
class ClosestNotMeRayResultCallback: public btCollisionWorld::ClosestRayResultCallback {
|
||||
btCollisionObject *mMe;
|
||||
public:
|
||||
ClosestNotMeRayResultCallback(
|
||||
btCollisionObject *me,
|
||||
const btVector3 &from,
|
||||
const btVector3 &to):
|
||||
btCollisionWorld::ClosestRayResultCallback(from, to) {
|
||||
mMe = me;
|
||||
}
|
||||
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
|
||||
{
|
||||
if (rayResult.m_collisionObject == mMe)
|
||||
return 1.0f;
|
||||
return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
|
||||
}
|
||||
};
|
||||
bool checkGround()
|
||||
{
|
||||
btVector3 from = mGhostObject->getWorldTransform().getOrigin() + btVector3(0, 0.2f, 0);
|
||||
btVector3 to = from + btVector3(0, -3000.0f, 0);
|
||||
ClosestNotMeRayResultCallback
|
||||
resultCallback(mGhostObject, from, to);
|
||||
mGhostObject->rayTest(from, to, resultCallback);
|
||||
// std::cout << (resultCallback.hasHit() ? "hit" : "no hit");
|
||||
// if (resultCallback.hasHit())
|
||||
// std::cout << " " << Ogre::Bullet::convert(resultCallback.m_hitPointWorld);
|
||||
// std::cout << "\n";
|
||||
return resultCallback.hasHit();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,8 +23,8 @@ target_include_directories(lua PRIVATE lua-5.4.8/src)
|
||||
add_executable(luavm lua-5.4.8/src/lua.c)
|
||||
target_link_libraries(luavm lua m)
|
||||
target_include_directories(luavm PRIVATE lua-5.4.8/src)
|
||||
add_executable(luac lua-5.4.8/src/luac.c)
|
||||
target_link_libraries(luac lua m)
|
||||
add_executable(luac lua-5.4.8/src/luac.c ${LUA_SRC})
|
||||
target_link_libraries(luac m)
|
||||
target_include_directories(luac PRIVATE lua-5.4.8/src)
|
||||
|
||||
|
||||
|
||||
@@ -404,5 +404,12 @@ public:
|
||||
return body;
|
||||
}
|
||||
#endif
|
||||
bool isLoadedAt(const Ogre::Vector3 &position) const {
|
||||
long x, y;
|
||||
mTerrainGroup->convertWorldPositionToTerrainSlot(position, &x, &y);
|
||||
if (mTerrainGroup->getTerrain(x, y))
|
||||
return mTerrainGroup->getTerrain(x, y)->isLoaded();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -228,6 +228,11 @@ void Water::updateWater(float delta)
|
||||
mViewports[i]->update();
|
||||
for (i = 0; i < mWaterMeshes.size(); i++)
|
||||
mWaterMeshes[i]->setVisible(true);
|
||||
mOverlaps.clear();
|
||||
for (i = 0; i < mWaterBody->getNumOverlappingObjects(); i++) {
|
||||
btCollisionObject *sb = mWaterBody->getOverlappingObject(i);
|
||||
mOverlaps.insert(sb);
|
||||
}
|
||||
}
|
||||
|
||||
void Water::preRenderTargetUpdate(const Ogre::RenderTargetEvent &evt)
|
||||
|
||||
@@ -26,6 +26,7 @@ class Water : public /* Ogre::FrameListener, */ Ogre::RenderTargetListener {
|
||||
void create_cameras();
|
||||
btGhostObject *mWaterBody;
|
||||
Ogre::Bullet::DynamicsWorld *mDynWorld;
|
||||
std::set<btCollisionObject *> mOverlaps;
|
||||
|
||||
public:
|
||||
Water();
|
||||
@@ -43,5 +44,10 @@ public:
|
||||
postRenderTargetUpdate(const Ogre::RenderTargetEvent &evt) override;
|
||||
void add_submerged_entity(Ogre::Entity *ent);
|
||||
void add_surface_entity(Ogre::Entity *ent);
|
||||
bool isInWater(const btCollisionObject *body) const
|
||||
{
|
||||
btCollisionObject *test = const_cast<btCollisionObject *>(body);
|
||||
return mOverlaps.find(test) != mOverlaps.end();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user