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:
parent
bec157c598
commit
014bff2a4e
@ -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() {}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
@ -28,6 +29,8 @@ struct InstanceObject : public GameObject
|
||||
);
|
||||
|
||||
Type type() { return Instance; }
|
||||
|
||||
void tick(float dt);
|
||||
|
||||
virtual bool takeDamage(const DamageInfo& damage);
|
||||
};
|
||||
|
@ -36,9 +36,6 @@ private:
|
||||
float brake;
|
||||
bool handbrake;
|
||||
unsigned int damageFlags;
|
||||
|
||||
// Used to determine in water status
|
||||
float _lastHeight;
|
||||
public:
|
||||
|
||||
VehicleDataHandle vehicle;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user