Compare commits

..

2 Commits

Author SHA1 Message Date
503db60c60 Fixed build system 2025-08-28 02:32:43 +03:00
c730ca5222 updates 2025-08-26 08:13:21 +03:00
8 changed files with 115 additions and 107 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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