Fixed physics

This commit is contained in:
2025-07-11 09:52:13 +03:00
parent 0c27405da7
commit 9ef3194cde
4 changed files with 57 additions and 173 deletions

181
Game.cpp
View File

@@ -259,7 +259,6 @@ class App : public OgreBites::ApplicationContext {
Ogre::Light *mSun;
SkyBoxRenderer *sky;
Water m_water;
// OgreBites::TrayManager *mTrayMgr;
class KeyboardListener : public OgreBites::InputListener,
public Ogre::FrameListener {
App *mApp;
@@ -326,26 +325,19 @@ class App : public OgreBites::ApplicationContext {
{
if (gui_active)
return false;
/* no special mouse handling */
return false;
// update camera goal based on mouse movement
mApp->updateCameraGoal(-0.18f * evt.xrel,
-0.12f * evt.yrel, 0);
return true;
}
bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt)
{
if (gui_active)
return false;
/* no special mouse wheel handling */
return false;
// update camera goal based on mouse movement
mApp->updateCameraGoal(0, 0, -0.15f * evt.y);
return true;
}
void update(float delta)
{
return;
// float fade = (1.0f - delta) * 0.98f;
// motion *= fade;
}
void frameRendered(const Ogre::FrameEvent &evt) override
{
@@ -370,11 +362,10 @@ class App : public OgreBites::ApplicationContext {
}
update(evt.timeSinceLastFrame);
if (!gui_active) {
mApp->updateMotion(evt.timeSinceLastFrame);
mApp->updateCamera(evt.timeSinceLastFrame);
mApp->updateSun(evt.timeSinceLastFrame);
mApp->updateTerrain(evt.timeSinceLastFrame);
mApp->updateWater(evt.timeSinceLastFrame);
mApp->updateWorld(evt.timeSinceLastFrame);
}
}
};
@@ -472,147 +463,25 @@ public:
.initialiseAllResourceGroups();
// OgreBites::ApplicationContext::loadResources();
// setupCursor();
setupPlayer();
std::cout << "Create content" << "\n";
createContent();
std::cout << "Setup terrain" << "\n";
setupTerrain();
m_water.init();
setupPlayer();
setupInput();
}
void setupPlayer()
{
OgreAssert(mDynWorld.get(), "No physics world controller");
mCharacterController = new CharacterController(
mCameraNode, mCamera, mScnMgr, mDynWorld.get());
#if 0
/* FIXME: make proper player setup */
Ogre::Entity *ent =
mScnMgr->createEntity("PlayerBoat", "boat.glb");
mCameraPivot->attachObject(ent);
#endif
}
void setupCursor()
{
// mKeyDirection = Ogre::Vector3::ZERO;
// mVerticalVelocity = 0;
Ogre::ManualObject *mobj =
mScnMgr->createManualObject("cursorGen");
#if 0
Ogre::MaterialPtr mat =
Ogre::static_pointer_cast<Ogre::Material>(
Ogre::MaterialManager::getSingleton()
.createOrRetrieve("Debug/Red2",
"General")
.first);
mat->removeAllTechniques();
Ogre::Technique *tech = mat->createTechnique();
tech->setDiffuse(Ogre::ColourValue(1, 0, 0, 1));
tech->setName("Debug/S");
tech->setDepthCheckEnabled(false);
tech->setLightingEnabled(false);
mobj->begin(mat, Ogre::RenderOperation::OT_LINE_LIST);
#endif
mobj->begin("Debug/Red", Ogre::RenderOperation::OT_LINE_LIST);
mobj->position(0, 0, 0);
mobj->colour(Ogre::ColourValue(1, 0, 0));
mobj->position(0, 2, 0);
mobj->colour(Ogre::ColourValue(1, 0, 0));
mobj->position(-1, 1, 0);
mobj->colour(Ogre::ColourValue(1, 0, 0));
mobj->position(1, 1, 0);
mobj->colour(Ogre::ColourValue(1, 0, 0));
mobj->index(0);
mobj->index(1);
mobj->index(2);
mobj->index(3);
mobj->end();
mCameraPivot->attachObject(mobj);
OgreAssert(mCharacterController, "No character controller");
}
Ogre::SceneManager *getSceneManager()
{
return mScnMgr;
}
void updateMotion(float delta)
{
if (delta == 0.0f)
return;
#if 0
Ogre::Vector3 move(mCameraNode->getOrientation().zAxis() *
mKbd.motion.z);
move += Ogre::Vector3(mCameraNode->getOrientation().xAxis() *
mKbd.motion.x);
move.y = 0.0f;
float speed = 15.0f;
if (mKbd.fast)
speed = 40.0f;
Ogre::Vector3 opos = mCameraPivot->getPosition();
Ogre::Vector3 pos =
mCameraPivot->getPosition() + move * speed * delta;
float y = m_terrain.get_height(pos);
if (y < 0)
y = 0.0f;
pos.y = y;
mCameraPivot->translate(pos - opos);
// mKbd.motion = Ogre::Vector3(0, 0, 0);
// if (move.squaredLength() > 0)
// std::cout << move << "\n";
#endif
}
void updateCamera(Ogre::Real delta)
{
if (delta == 0.0f)
return;
#if 0
// place the camera pivot roughly at the character's shoulder
// mCameraPivot->setPosition(mBodyNode->getPosition() +
// Ogre::Vector3::UNIT_Y * CAM_HEIGHT);
// move the camera smoothly to the goal
Ogre::Vector3 goalOffset = mCameraGoal->_getDerivedPosition() -
mCameraNode->getPosition();
float l = goalOffset.squaredLength();
Ogre::Vector3 v = goalOffset * 10.0 * delta;
if (v.squaredLength() > l * 0.5f - delta)
v = goalOffset * delta;
mCameraNode->translate(v);
// mCameraNode->translate(goalOffset);
// always look at the pivot
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(),
Ogre::Node::TS_PARENT);
#endif
}
void updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch,
Ogre::Real deltaZoom)
{
#if 0
mCameraPivot->yaw(Ogre::Degree(deltaYaw),
Ogre::Node::TS_PARENT);
if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0)) {
mCameraPivot->pitch(Ogre::Degree(deltaPitch),
Ogre::Node::TS_LOCAL);
mPivotPitch += deltaPitch;
}
Ogre::Real dist = mCameraGoal->_getDerivedPosition().distance(
mCameraPivot->_getDerivedPosition());
Ogre::Real distChange = deltaZoom * dist * 0.5f;
if (distChange > 0 && dist + distChange > 30)
distChange *= 0.3f;
if (distChange < 0 && dist + distChange < 5)
distChange *= 0.2f;
// bound the zoom
if (!(dist + distChange < 3 && distChange < 0) &&
!(dist + distChange > 60 && distChange > 0))
mCameraGoal->translate(0, 0, distChange,
Ogre::Node::TS_LOCAL);
Ogre::Vector3 mh = mCameraGoal->_getDerivedPosition();
float h = m_terrain.get_height(mh);
if (h + 10 > mh.y)
mCameraGoal->translate(0, 10.0f * deltaZoom, distChange,
Ogre::Node::TS_LOCAL);
#endif
}
Ogre::SceneNode *mSunGoal;
Ogre::SceneNode *mSunNode;
Ogre::SceneNode *mSunTarget;
@@ -628,8 +497,6 @@ public:
"SunGoalTarget",
Ogre::Vector3(100.0f, -400.0f, -400.0f),
Ogre::Quaternion::IDENTITY);
// mSunNode->setAutoTracking(true, sun_target);
// lightNode->setPosition(0, 10, 15);
mSunNode->attachObject(light);
light->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDiffuseColour(Ogre::ColourValue::White);
@@ -667,36 +534,29 @@ public:
Ogre::Timer mTerrainUpd;
void updateTerrain(float delta)
{
// mDbgDraw->update();
#if 0
if (mTerrainUpd.getMilliseconds() > 1000) {
m_terrain.create_colliders();
mTerrainUpd.reset();
}
#endif
}
void updateWorld(float delta)
{
mDynWorld->getBtWorld()->stepSimulation(delta, 10);
}
void updateWater(float delta)
{
m_water.updateWater(delta);
}
void setupInput()
{
mInput = OgreBites::InputListenerChain(
{ getImGuiInputListener(), &mKbd,
mCharacterController });
addInputListener(&mInput);
}
void createContent()
{
int i;
m_edit_ui.init_glb_list();
m_edit_ui.initGui();
createSun();
mInput = OgreBites::InputListenerChain(
{ getImGuiInputListener(), &mKbd,
mCharacterController });
addInputListener(&mInput);
getRoot()->addFrameListener(&mKbd);
// mTrayMgr->showCursor();
// OgreBites::TrayManager *mTrayMgr = new OgreBites::TrayManager(
// "InterfaceName", getRenderWindow());
// mScnMgr->setSkyBox(true, "Skybox/Dynamic", 490);
// /* mCamera->getCameraToViewportRay(left, top); */
#if 1
sky = new SkyBoxRenderer(getSceneManager());
bool drawFirst = true;
uint8_t renderQueue = drawFirst ?
@@ -713,7 +573,6 @@ public:
"Skybox/Dynamic", "General");
OgreAssert(m, "Sky box material not found.");
m->load();
#endif
}
void create_entity_node(const Ogre::String &name, int key)
{
@@ -900,9 +759,9 @@ void EditUI::initGui()
{
mScnMgr = m_app->getSceneManager();
float vpScale = m_app->getDisplayDPI() / 96 *
(float)m_app->getRenderWindow()->getWidth() / 1280;
(float)m_app->getRenderWindow()->getWidth() / 1600.0f;
panel_width =
380.0f * (float)m_app->getRenderWindow()->getWidth() / 1280;
380.0f * (float)m_app->getRenderWindow()->getWidth() / 1600.0f;
Ogre::OverlayManager::getSingleton().setPixelRatio(vpScale);
mGuiOverlay = m_app->initialiseImGui();
// float vpScale =

View File

@@ -81,8 +81,8 @@ void Character::setupBody()
inertia);
}
mGhostObject->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT |
btCollisionObject::CF_NO_CONTACT_RESPONSE);
btCollisionObject::CF_KINEMATIC_OBJECT /* |
btCollisionObject::CF_NO_CONTACT_RESPONSE */);
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
Ogre::Bullet::KinematicMotionSimple *controller =
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,

View File

@@ -224,17 +224,19 @@ void CharacterController::setupBody()
}
mGhostObject->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT |
btCollisionObject::CF_NO_CONTACT_RESPONSE);
btCollisionObject::CF_NO_CONTACT_RESPONSE );
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
mWorld->attachCollisionObject(mGhostObject, mBodyEnt,
1,
0x7FFFFFF);
Ogre::Bullet::KinematicMotionSimple *controller =
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,
mBodyNode);
mWorld->attachCollisionObject(mGhostObject, mBodyEnt,
btBroadphaseProxy::AllFilter,
btBroadphaseProxy::AllFilter);
OgreAssert(mGhostObject, "Need GhostObject");
OgreAssert(controller, "Need controller");
mWorld->getBtWorld()->addAction(controller);
assert(mCollisionShape);
OgreAssert(mCollisionShape, "No collision shape");
#if 0
if (mRigidBody->getMass() == 0) {
#if 0
@@ -264,9 +266,9 @@ void CharacterController::setupBody()
WorldData::get_singleton()->getBtWorld()->addAction(mController);
}
#endif
assert(mSkeleton->hasBone("Root"));
OgreAssert(mSkeleton->hasBone("Root"), "No root bone");
mRootBone = mSkeleton->getBone("Root");
assert(mRootBone);
OgreAssert(mRootBone, "No root bone");
}
void CharacterController::setupCamera()
{
@@ -544,6 +546,11 @@ void CharacterController::updateAnimations(Ogre::Real delta)
}
fadeAnimations(delta);
}
struct EntityCollisionListener
{
const Ogre::MovableObject* entity;
Ogre::Bullet::CollisionListener* listener;
};
void CharacterController::updateRootMotion(Ogre::Real delta)
{
Ogre::Vector3 boneMotion = mRootBone->getPosition();
@@ -562,15 +569,33 @@ void CharacterController::updateRootMotion(Ogre::Real delta)
/* Kinematic motion */
Ogre::Quaternion rot = mBodyNode->getOrientation();
Ogre::Vector3 gravity(0, -9.8, 0);
gravity.y = 0.5f;
Ogre::Vector3 velocity = rot * boneMotion / delta;
velocity += gravity * delta;
velocity += gravity * 10.0f * 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 *>());
#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";
}
}
#endif
}
void CharacterController::fadeAnimations(Ogre::Real delta)
{

View File

@@ -159,4 +159,4 @@ private:
q = convert(from.getRotation());
v = convert(from.getOrigin());
}
};
};