From 014bff2a4ec46ed618f89d06768a00acd0012e88 Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Sun, 15 Jun 2014 01:34:13 +0100 Subject: [PATCH] Add water dynamics to dynamic instances --- rwengine/include/engine/GameObject.hpp | 5 +- rwengine/include/engine/RWTypes.hpp | 2 + rwengine/include/objects/InstanceObject.hpp | 3 + rwengine/include/objects/VehicleObject.hpp | 3 - rwengine/src/objects/InstanceObject.cpp | 77 ++++++++++++++++++++- rwengine/src/objects/VehicleObject.cpp | 8 +-- rwgame/main.cpp | 4 ++ 7 files changed, 91 insertions(+), 11 deletions(-) diff --git a/rwengine/include/engine/GameObject.hpp b/rwengine/include/engine/GameObject.hpp index 385c6001..7758e456 100644 --- a/rwengine/include/engine/GameObject.hpp +++ b/rwengine/include/engine/GameObject.hpp @@ -35,9 +35,12 @@ struct GameObject bool _inWater; + // Used to determine in water status + float _lastHeight; + GameObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model) : position(pos), rotation(rot), model(model), engine(engine), animator(nullptr), mHealth(0.f), - _inWater(false) + _inWater(false), _lastHeight(0.f) {} virtual ~GameObject() {} diff --git a/rwengine/include/engine/RWTypes.hpp b/rwengine/include/engine/RWTypes.hpp index 217adc37..79f4f705 100644 --- a/rwengine/include/engine/RWTypes.hpp +++ b/rwengine/include/engine/RWTypes.hpp @@ -14,6 +14,8 @@ #define WATER_HQ_DISTANCE 128.f #define WATER_SCALE 0.05f #define WATER_HEIGHT 0.5f +#define WATER_BUOYANCY_K 25000.f +#define WATER_BUOYANCY_C 100.f class Animation; diff --git a/rwengine/include/objects/InstanceObject.hpp b/rwengine/include/objects/InstanceObject.hpp index 6ca8291f..08ab798d 100644 --- a/rwengine/include/objects/InstanceObject.hpp +++ b/rwengine/include/objects/InstanceObject.hpp @@ -15,6 +15,7 @@ struct InstanceObject : public GameObject std::shared_ptr object; std::shared_ptr LODinstance; std::shared_ptr dynamics; + float _collisionHeight; InstanceObject( GameWorld* engine, @@ -28,6 +29,8 @@ struct InstanceObject : public GameObject ); Type type() { return Instance; } + + void tick(float dt); virtual bool takeDamage(const DamageInfo& damage); }; diff --git a/rwengine/include/objects/VehicleObject.hpp b/rwengine/include/objects/VehicleObject.hpp index 92028e28..ff5577af 100644 --- a/rwengine/include/objects/VehicleObject.hpp +++ b/rwengine/include/objects/VehicleObject.hpp @@ -36,9 +36,6 @@ private: float brake; bool handbrake; unsigned int damageFlags; - - // Used to determine in water status - float _lastHeight; public: VehicleDataHandle vehicle; diff --git a/rwengine/src/objects/InstanceObject.cpp b/rwengine/src/objects/InstanceObject.cpp index 6fb05470..91bd4833 100644 --- a/rwengine/src/objects/InstanceObject.cpp +++ b/rwengine/src/objects/InstanceObject.cpp @@ -11,7 +11,7 @@ InstanceObject::InstanceObject(GameWorld* engine, std::shared_ptr lod, std::shared_ptr dyn) : GameObject(engine, pos, rot, model), scale(scale), object(obj), - LODinstance(lod), dynamics(dyn) + LODinstance(lod), dynamics(dyn), _collisionHeight(0.f) { auto phyit = engine->gameData.collisions.find(obj->modelName); if( phyit != engine->gameData.collisions.end()) { @@ -28,6 +28,9 @@ InstanceObject::InstanceObject(GameWorld* engine, btRigidBody::btRigidBodyConstructionInfo info(0.f, msta, cmpShape); CollisionModel& physInst = *phyit->second.get(); + float colMin = std::numeric_limits::max(), + colMax = std::numeric_limits::lowest(); + // Boxes for( size_t i = 0; i < physInst.boxes.size(); ++i ) { auto& box = physInst.boxes[i]; @@ -37,6 +40,9 @@ InstanceObject::InstanceObject(GameWorld* engine, btTransform t; t.setIdentity(); t.setOrigin(btVector3(mid.x, mid.y, mid.z)); cmpShape->addChildShape(t, bshape); + + colMin = std::min(colMin, mid.z - size.z); + colMax = std::max(colMax, mid.z + size.z); } // Spheres @@ -46,6 +52,9 @@ InstanceObject::InstanceObject(GameWorld* engine, btTransform t; t.setIdentity(); t.setOrigin(btVector3(sphere.center.x, sphere.center.y, sphere.center.z)); cmpShape->addChildShape(t, sshape); + + colMin = std::min(colMin, sphere.center.z - sphere.radius); + colMax = std::max(colMax, sphere.center.z + sphere.radius); } if( physInst.vertices.size() > 0 && physInst.indices.size() >= 3 ) { @@ -62,6 +71,8 @@ InstanceObject::InstanceObject(GameWorld* engine, cmpShape->addChildShape(t, trishape); } + _collisionHeight = colMax - colMin; + if( dynamics ) { if( dynamics->uprootForce > 0.f ) { info.m_mass = 0.f; @@ -91,6 +102,70 @@ InstanceObject::InstanceObject(GameWorld* engine, } } +void InstanceObject::tick(float dt) +{ + if( dynamics ) { + auto _bws = body->getWorldTransform().getOrigin(); + glm::vec3 ws(_bws.x(), _bws.y(), _bws.z()); + auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE)); + auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE)); + float vH = ws.z;// - _collisionHeight/2.f; + float wH = 0.f; + + if( wX >= 0 && wX < WATER_HQ_DATA_SIZE && wY >= 0 && wY < WATER_HQ_DATA_SIZE ) { + int i = (wX*WATER_HQ_DATA_SIZE) + wY; + int hI = engine->gameData.realWater[i]; + if( hI < NO_WATER_INDEX ) { + wH = engine->gameData.waterHeights[hI]; + wH += engine->gameData.getWaveHeightAt(ws); + if( vH <= wH ) { + _inWater = true; + } + else { + _inWater = false; + } + } + else { + _inWater = false; + } + } + _lastHeight = ws.z; + + if( _inWater ) { + float oZ = -(_collisionHeight * (dynamics->bouancy/100.f)); + body->activate(true); + // Damper motion + body->setDamping(0.95f, 0.9f); + + auto wi = engine->gameData.getWaterIndexAt(ws); + if(wi != NO_WATER_INDEX) { + float h = engine->gameData.waterHeights[wi] + oZ; + + // Calculate wave height + h += engine->gameData.getWaveHeightAt(ws); + + if ( ws.z <= h ) { + if( dynamics->uprootForce > 0.f && (body->getCollisionFlags() & btRigidBody::CF_STATIC_OBJECT) != 0 ) { + // Apparently bodies must be removed and re-added if their mass changes. + engine->dynamicsWorld->removeRigidBody(body); + btVector3 inert; + body->getCollisionShape()->calculateLocalInertia(dynamics->mass, inert); + body->setMassProps(dynamics->mass, inert); + engine->dynamicsWorld->addRigidBody(body); + } + + float x = (h - ws.z); + float F = WATER_BUOYANCY_K * x + -WATER_BUOYANCY_C * body->getLinearVelocity().z(); + btVector3 forcePos = btVector3(0.f, 0.f, 2.f).rotate( + body->getOrientation().getAxis(), body->getOrientation().getAngle()); + body->applyForce(btVector3(0.f, 0.f, F), + forcePos); + } + } + } + } +} + bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) { bool explodeOnHit = (object->flags&ObjectData::EXPLODEONHIT) == ObjectData::EXPLODEONHIT; diff --git a/rwengine/src/objects/VehicleObject.cpp b/rwengine/src/objects/VehicleObject.cpp index c2ec72ee..8a23958a 100644 --- a/rwengine/src/objects/VehicleObject.cpp +++ b/rwengine/src/objects/VehicleObject.cpp @@ -9,8 +9,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::vec3& prim, const glm::vec3& sec) : GameObject(engine, pos, rot, model), steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false), - damageFlags(0), _lastHeight(0.f), vehicle(data), - info(info), colourPrimary(prim), + damageFlags(0), vehicle(data), info(info), colourPrimary(prim), colourSecondary(sec), physBody(nullptr), physVehicle(nullptr) { mHealth = 100.f; @@ -386,9 +385,6 @@ bool VehicleObject::isFrameVisible(ModelFrame *frame) const return true; } -float buoyancyK = 25000.f; -float buoyancyC = 100.f; - void VehicleObject::applyWaterFloat(const glm::vec3 &relPt, float waterOffset) { auto ws = getPosition() + relPt; @@ -401,7 +397,7 @@ void VehicleObject::applyWaterFloat(const glm::vec3 &relPt, float waterOffset) if ( ws.z <= h ) { float x = (h - ws.z); - float F = buoyancyK * x + -buoyancyC * physBody->getLinearVelocity().z(); + float F = WATER_BUOYANCY_K * x + -WATER_BUOYANCY_C * physBody->getLinearVelocity().z(); physBody->applyForce(btVector3(0.f, 0.f, F), btVector3(relPt.x, relPt.y, relPt.z)); } diff --git a/rwgame/main.cpp b/rwgame/main.cpp index 7fff023e..77d93f5a 100644 --- a/rwgame/main.cpp +++ b/rwgame/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -345,6 +346,9 @@ void update(float dt) v--; } } + for( size_t p = 0; p < gta->objectInstances.size(); ++p) { + gta->objectInstances[p]->tick(dt); + } gta->dynamicsWorld->stepSimulation(dt, 2, dt);