mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 02:12:45 +01:00
Initial dynamic object implementation
This commit is contained in:
parent
0cdbb0c09c
commit
65b5c84b92
@ -84,6 +84,11 @@ struct GameObject
|
||||
* Type of the damage
|
||||
*/
|
||||
DamageType type;
|
||||
|
||||
/**
|
||||
* Physics impulse.
|
||||
*/
|
||||
float impulse;
|
||||
};
|
||||
|
||||
virtual bool takeDamage(const DamageInfo& damage) { return false; }
|
||||
|
@ -196,6 +196,12 @@ public:
|
||||
btSequentialImpulseConstraintSolver* solver;
|
||||
btDiscreteDynamicsWorld* dynamicsWorld;
|
||||
|
||||
/**
|
||||
* @brief handleCollisionResponses performs physics response checking
|
||||
* for collisions between vehicles, objects etc.
|
||||
*/
|
||||
void handleCollisionResponses();
|
||||
|
||||
/**
|
||||
* Work related
|
||||
*/
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef _OBJECTINSTANCE_HPP_
|
||||
#define _OBJECTINSTANCE_HPP_
|
||||
#include <engine/GameObject.hpp>
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
|
||||
/**
|
||||
* @struct InstanceObject
|
||||
@ -10,8 +11,10 @@
|
||||
struct InstanceObject : public GameObject
|
||||
{
|
||||
glm::vec3 scale;
|
||||
btRigidBody* body = nullptr;
|
||||
std::shared_ptr<ObjectData> object;
|
||||
std::shared_ptr<InstanceObject> LODinstance;
|
||||
std::shared_ptr<DynamicObjectData> dynamics;
|
||||
|
||||
InstanceObject(
|
||||
GameWorld* engine,
|
||||
@ -20,12 +23,13 @@ struct InstanceObject : public GameObject
|
||||
ModelHandle* model,
|
||||
const glm::vec3& scale,
|
||||
std::shared_ptr<ObjectData> obj,
|
||||
std::shared_ptr<InstanceObject> lod
|
||||
std::shared_ptr<InstanceObject> lod,
|
||||
std::shared_ptr<DynamicObjectData> dyn
|
||||
);
|
||||
|
||||
Type type() { return Instance; }
|
||||
|
||||
virtual bool takeDamage(const DamageInfo& damage);
|
||||
virtual bool takeDamage(const DamageInfo& damage);
|
||||
};
|
||||
|
||||
|
||||
|
@ -474,15 +474,31 @@ void GameData::loadDynamicObjects(const std::string& name)
|
||||
std::shared_ptr<DynamicObjectData> dyndata(new DynamicObjectData);
|
||||
|
||||
ss >> dyndata->modelName;
|
||||
auto cpos = dyndata->modelName.find(',');
|
||||
if( cpos != dyndata->modelName.npos ) {
|
||||
dyndata->modelName.erase(cpos);
|
||||
}
|
||||
ss >> dyndata->mass;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->turnMass;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->airRes;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->elacticity;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->bouancy;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->uprootForce;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->collDamageMulti;
|
||||
ss >> dyndata->collDamageFlags;
|
||||
ss >> dyndata->collResponseFlags;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
int tmp;
|
||||
ss >> tmp;
|
||||
dyndata->collDamageFlags = tmp;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> tmp;
|
||||
dyndata->collResponseFlags = tmp;
|
||||
if(ss.peek() == ',') ss.ignore(1);
|
||||
ss >> dyndata->cameraAvoid;
|
||||
|
||||
dynamicObjectData.insert({dyndata->modelName, dyndata});
|
||||
|
@ -187,6 +187,13 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
|
||||
if(! oi->second->textureName.empty()) {
|
||||
gameData.loadTXD(oi->second->textureName + ".txd", true);
|
||||
}
|
||||
|
||||
// Check for dynamic data.
|
||||
auto dyit = gameData.dynamicObjectData.find(oi->second->modelName);
|
||||
std::shared_ptr<DynamicObjectData> dydata;
|
||||
if( dyit != gameData.dynamicObjectData.end() ) {
|
||||
dydata = dyit->second;
|
||||
}
|
||||
|
||||
auto instance = std::shared_ptr<InstanceObject>(new InstanceObject(
|
||||
this,
|
||||
@ -194,7 +201,7 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
|
||||
rot,
|
||||
gameData.models[oi->second->modelName],
|
||||
glm::vec3(1.f, 1.f, 1.f),
|
||||
oi->second, nullptr
|
||||
oi->second, nullptr, dydata
|
||||
));
|
||||
|
||||
objectInstances.push_back(instance);
|
||||
@ -350,3 +357,59 @@ int GameWorld::getMinute()
|
||||
{
|
||||
return fmod(gameTime, 60.f);
|
||||
}
|
||||
|
||||
void GameWorld::handleCollisionResponses()
|
||||
{
|
||||
int numManifolds = dynamicsWorld->getDispatcher()->getNumManifolds();
|
||||
for (int i = 0; i < numManifolds; i++)
|
||||
{
|
||||
btPersistentManifold* contactManifold = dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
|
||||
auto obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
|
||||
auto obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
|
||||
|
||||
int numContacts = contactManifold->getNumContacts();
|
||||
for (int j = 0; j < numContacts; j++)
|
||||
{
|
||||
// Check that at least one of the objects involved is an instance.
|
||||
GameObject* a = static_cast<GameObject*>(obA->getUserPointer());
|
||||
GameObject* b = static_cast<GameObject*>(obB->getUserPointer());
|
||||
btManifoldPoint& pt = contactManifold->getContactPoint(j);
|
||||
|
||||
if(a && a->type() == GameObject::Instance) {
|
||||
auto inst = static_cast<InstanceObject*>(a);
|
||||
if( inst->dynamics ) {
|
||||
if( pt.getAppliedImpulse() > inst->dynamics->uprootForce ) {
|
||||
auto dmg = pt.getPositionWorldOnA();
|
||||
auto src = pt.getPositionWorldOnB();
|
||||
|
||||
inst->takeDamage({
|
||||
{dmg.x(), dmg.y(), dmg.z()},
|
||||
{src.x(), src.y(), src.z()},
|
||||
0.f,
|
||||
GameObject::DamageInfo::Physics,
|
||||
pt.getAppliedImpulse()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if(b && b->type() == GameObject::Instance) {
|
||||
auto inst = static_cast<InstanceObject*>(b);
|
||||
if( inst->dynamics ) {
|
||||
if( pt.getAppliedImpulse() > inst->dynamics->uprootForce ) {
|
||||
auto dmg = pt.getPositionWorldOnB();
|
||||
auto src = pt.getPositionWorldOnA();
|
||||
|
||||
inst->takeDamage({
|
||||
{dmg.x(), dmg.y(), dmg.z()},
|
||||
{src.x(), src.y(), src.z()},
|
||||
0.f,
|
||||
GameObject::DamageInfo::Physics,
|
||||
pt.getAppliedImpulse()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,11 +8,11 @@ InstanceObject::InstanceObject(GameWorld* engine,
|
||||
ModelHandle *model,
|
||||
const glm::vec3& scale,
|
||||
std::shared_ptr<ObjectData> obj,
|
||||
std::shared_ptr<InstanceObject> lod
|
||||
)
|
||||
: GameObject(engine, pos, rot, model), scale(scale), object(obj), LODinstance(lod)
|
||||
std::shared_ptr<InstanceObject> lod,
|
||||
std::shared_ptr<DynamicObjectData> dyn)
|
||||
: GameObject(engine, pos, rot, model), scale(scale), object(obj),
|
||||
LODinstance(lod), dynamics(dyn)
|
||||
{
|
||||
btRigidBody* body = nullptr;
|
||||
auto phyit = engine->gameData.collisions.find(obj->modelName);
|
||||
if( phyit != engine->gameData.collisions.end()) {
|
||||
btCompoundShape* cmpShape = new btCompoundShape;
|
||||
@ -62,9 +62,23 @@ InstanceObject::InstanceObject(GameWorld* engine,
|
||||
cmpShape->addChildShape(t, trishape);
|
||||
}
|
||||
|
||||
if( dynamics ) {
|
||||
if( dynamics->uprootForce > 0.f ) {
|
||||
info.m_mass = 0.f;
|
||||
}
|
||||
else {
|
||||
btVector3 inert;
|
||||
cmpShape->calculateLocalInertia(dynamics->mass, inert);
|
||||
info.m_mass = dynamics->mass;
|
||||
info.m_localInertia = inert;
|
||||
}
|
||||
}
|
||||
|
||||
body = new btRigidBody(info);
|
||||
body->setUserPointer(this);
|
||||
engine->dynamicsWorld->addRigidBody(body);
|
||||
|
||||
body->setActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
|
||||
auto pathit = engine->objectNodes.find(obj->ID);
|
||||
@ -81,6 +95,18 @@ bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg)
|
||||
{
|
||||
bool explodeOnHit = (object->flags&ObjectData::EXPLODEONHIT) == ObjectData::EXPLODEONHIT;
|
||||
bool smash = (object->flags&ObjectData::SMASHABLE) == ObjectData::SMASHABLE;
|
||||
if( dynamics ) {
|
||||
smash = dynamics->collDamageFlags == 80;
|
||||
|
||||
if( dmg.impulse >= dynamics->uprootForce && (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);
|
||||
}
|
||||
}
|
||||
if(explodeOnHit || smash)
|
||||
{
|
||||
if(explodeOnHit) {
|
||||
@ -95,3 +121,4 @@ bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -327,9 +327,14 @@ void GameRenderer::renderWorld(float alpha)
|
||||
}
|
||||
|
||||
glm::mat4 matrixModel;
|
||||
matrixModel = glm::translate(matrixModel, inst.position);
|
||||
matrixModel = glm::scale(matrixModel, inst.scale);
|
||||
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
|
||||
if( inst.body ) {
|
||||
inst.body->getWorldTransform().getOpenGLMatrix(glm::value_ptr(matrixModel));
|
||||
}
|
||||
else {
|
||||
matrixModel = glm::translate(matrixModel, inst.position);
|
||||
matrixModel = glm::scale(matrixModel, inst.scale);
|
||||
matrixModel = matrixModel * glm::mat4_cast(inst.rotation);
|
||||
}
|
||||
|
||||
float mindist = 100000.f;
|
||||
for (size_t g = 0; g < inst.model->model->geometries.size(); g++)
|
||||
|
@ -345,10 +345,10 @@ void update(float dt)
|
||||
v--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
gta->dynamicsWorld->stepSimulation(dt, 2, dt);
|
||||
|
||||
gta->handleCollisionResponses();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,7 @@ BOOST_AUTO_TEST_CASE(instance_test_damage)
|
||||
glm::vec3(0.f, 0.f, 0.f),
|
||||
glm::quat(), nullptr,
|
||||
glm::vec3(1.f),
|
||||
object,
|
||||
nullptr
|
||||
object, nullptr, nullptr
|
||||
);
|
||||
GameObject::DamageInfo dmg;
|
||||
dmg.type = GameObject::DamageInfo::Bullet;
|
||||
@ -40,8 +39,7 @@ BOOST_AUTO_TEST_CASE(instance_test_destroy)
|
||||
glm::vec3(0.f, 0.f, 0.f),
|
||||
glm::quat(), nullptr,
|
||||
glm::vec3(1.f),
|
||||
object,
|
||||
nullptr
|
||||
object, nullptr, nullptr
|
||||
);
|
||||
GameObject::DamageInfo dmg;
|
||||
dmg.type = GameObject::DamageInfo::Bullet;
|
||||
|
Loading…
Reference in New Issue
Block a user