1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 10:22:52 +01:00

Add water dynamics to dynamic instances

This commit is contained in:
Daniel Evans 2014-06-15 01:34:13 +01:00
parent bec157c598
commit 014bff2a4e
7 changed files with 91 additions and 11 deletions

View File

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

View File

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

View File

@ -15,6 +15,7 @@ struct InstanceObject : public GameObject
std::shared_ptr<ObjectData> object;
std::shared_ptr<InstanceObject> LODinstance;
std::shared_ptr<DynamicObjectData> dynamics;
float _collisionHeight;
InstanceObject(
GameWorld* engine,
@ -29,6 +30,8 @@ struct InstanceObject : public GameObject
Type type() { return Instance; }
void tick(float dt);
virtual bool takeDamage(const DamageInfo& damage);
};

View File

@ -36,9 +36,6 @@ private:
float brake;
bool handbrake;
unsigned int damageFlags;
// Used to determine in water status
float _lastHeight;
public:
VehicleDataHandle vehicle;

View File

@ -11,7 +11,7 @@ InstanceObject::InstanceObject(GameWorld* engine,
std::shared_ptr<InstanceObject> lod,
std::shared_ptr<DynamicObjectData> 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<float>::max(),
colMax = std::numeric_limits<float>::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;

View File

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

View File

@ -7,6 +7,7 @@
#include <render/Model.hpp>
#include <objects/VehicleObject.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/InstanceObject.hpp>
#include <ai/CharacterController.hpp>
#include <glm/glm.hpp>
@ -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);