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

Merge pull request #450 from husho/objphy

[Ready] Fixed script objects falling through the ground
This commit is contained in:
Daniel Evans 2018-05-22 23:35:59 +01:00 committed by GitHub
commit de8131924d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 55 deletions

View File

@ -19,10 +19,13 @@ InstanceObject::InstanceObject(GameWorld* engine, const glm::vec3& pos,
const std::shared_ptr<DynamicObjectData>& dyn) const std::shared_ptr<DynamicObjectData>& dyn)
: GameObject(engine, pos, rot, modelinfo) : GameObject(engine, pos, rot, modelinfo)
, health(100.f) , health(100.f)
, visible(true)
, floating(false)
, usePhysics(false)
, changeAtomic(-1)
, scale(scale) , scale(scale)
, body(nullptr) , body(nullptr)
, dynamics(dyn) , dynamics(dyn) {
, _enablePhysics(false) {
if (modelinfo) { if (modelinfo) {
changeModel(modelinfo); changeModel(modelinfo);
setPosition(pos); setPosition(pos);
@ -68,12 +71,10 @@ void InstanceObject::tickPhysics(float dt) {
changeModel(getModelInfo<SimpleModelInfo>(), changeAtomic); changeModel(getModelInfo<SimpleModelInfo>(), changeAtomic);
changeAtomic = -1; changeAtomic = -1;
} }
if (_enablePhysics) {
if (body->getBulletBody()->isStaticObject()) {
body->changeMass(dynamics->mass);
}
}
if (usePhysics) {
body->changeMass(dynamics->mass);
}
// Only certain objects should float on water // Only certain objects should float on water
if (floating) { if (floating) {
@ -127,7 +128,7 @@ void InstanceObject::tickPhysics(float dt) {
->getOrientation() ->getOrientation()
.getAngle()); .getAngle());
body->getBulletBody()->applyImpulse(btVector3(0.f, 0.f, F), body->getBulletBody()->applyImpulse(btVector3(0.f, 0.f, F),
forcePos); forcePos);
} }
} }
} }
@ -149,7 +150,8 @@ void InstanceObject::changeModel(BaseModelInfo* incoming, int atomicNumber) {
setModel(getModelInfo<SimpleModelInfo>()->getModel()); setModel(getModelInfo<SimpleModelInfo>()->getModel());
auto collision = getModelInfo<SimpleModelInfo>()->getCollision(); auto collision = getModelInfo<SimpleModelInfo>()->getCollision();
RW_ASSERT(getModelInfo<SimpleModelInfo>()->getNumAtomics() > atomicNumber); RW_ASSERT(getModelInfo<SimpleModelInfo>()->getNumAtomics() >
atomicNumber);
auto atomic = getModelInfo<SimpleModelInfo>()->getAtomic(atomicNumber); auto atomic = getModelInfo<SimpleModelInfo>()->getAtomic(atomicNumber);
if (atomic) { if (atomic) {
auto previous = atomic_; auto previous = atomic_;
@ -190,6 +192,19 @@ void InstanceObject::setRotation(const glm::quat& r) {
GameObject::setRotation(r); GameObject::setRotation(r);
} }
void InstanceObject::setStatic(bool s) {
int flags = body->getBulletBody()->getCollisionFlags();
if (s) {
flags |= btCollisionObject::CF_STATIC_OBJECT;
} else {
flags &= ~btCollisionObject::CF_STATIC_OBJECT;
}
body->getBulletBody()->setCollisionFlags(flags);
static_ = s;
}
bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) { bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) {
if (!dynamics) { if (!dynamics) {
return false; return false;
@ -198,13 +213,20 @@ bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) {
const auto effect = dynamics->collDamageEffect; const auto effect = dynamics->collDamageEffect;
if (dmg.hitpoints > 0.f) { if (dmg.hitpoints > 0.f) {
if (effect || dynamics->collResponseFlags) {
if (dmg.impulse >= dynamics->uprootForce && !isStatic()) {
usePhysics = true;
}
}
switch (effect) { switch (effect) {
case DynamicObjectData::Damage_ChangeModel: case DynamicObjectData::Damage_ChangeModel:
changeAtomic = 1; changeAtomic = 1;
break; break;
case DynamicObjectData::Damage_ChangeThenSmash: case DynamicObjectData::Damage_ChangeThenSmash:
changeAtomic = 1; changeAtomic = 1;
RW_UNIMPLEMENTED("Collision Damage Effect: Changing, then Smashing"); RW_UNIMPLEMENTED(
"Collision Damage Effect: Changing, then Smashing");
break; break;
case DynamicObjectData::Damage_Smash: case DynamicObjectData::Damage_Smash:
RW_UNIMPLEMENTED("Collision Damage Effect: Smashing"); RW_UNIMPLEMENTED("Collision Damage Effect: Smashing");
@ -220,11 +242,6 @@ bool InstanceObject::takeDamage(const GameObject::DamageInfo& dmg) {
} }
} }
if (dmg.impulse >= dynamics->uprootForce &&
body->getBulletBody()->isStaticObject()) {
_enablePhysics = true;
}
return true; return true;
} }

View File

@ -18,9 +18,11 @@ class GameWorld;
*/ */
class InstanceObject : public GameObject { class InstanceObject : public GameObject {
float health; float health;
bool visible = true; bool visible;
bool floating = false; bool floating;
int changeAtomic = -1; bool static_;
bool usePhysics;
int changeAtomic;
/** /**
* The Atomic instance for this object * The Atomic instance for this object
@ -31,7 +33,6 @@ public:
glm::vec3 scale; glm::vec3 scale;
std::unique_ptr<CollisionInstance> body; std::unique_ptr<CollisionInstance> body;
std::shared_ptr<DynamicObjectData> dynamics; std::shared_ptr<DynamicObjectData> dynamics;
bool _enablePhysics;
InstanceObject(GameWorld* engine, const glm::vec3& pos, InstanceObject(GameWorld* engine, const glm::vec3& pos,
const glm::quat& rot, const glm::vec3& scale, const glm::quat& rot, const glm::vec3& scale,
@ -59,19 +60,27 @@ public:
bool takeDamage(const DamageInfo& damage) override; bool takeDamage(const DamageInfo& damage) override;
void setSolid(bool solid); void setSolid(bool s);
void setVisible(bool visible) { void setStatic(bool s);
this->visible = visible;
bool isStatic() const {
return static_;
} }
float getVisible() const {
void setVisible(bool v) {
visible = v;
}
bool isVisible() const {
return visible; return visible;
} }
void setFloating(bool floating) { void setFloating(bool f) {
this->floating = floating; floating = f;
} }
float getFloating() const {
bool isFloating() const {
return floating; return floating;
} }

View File

@ -35,10 +35,9 @@ constexpr float kMagicLODDistance = 330.f;
constexpr float kVehicleLODDistance = 70.f; constexpr float kVehicleLODDistance = 70.f;
constexpr float kVehicleDrawDistance = 280.f; constexpr float kVehicleDrawDistance = 280.f;
RenderKey createKey(float normalizedDepth, RenderKey createKey(float normalizedDepth, Renderer::Textures& textures) {
Renderer::Textures& textures) {
return (uint32_t(0x7FFFFF * normalizedDepth) << 8 | return (uint32_t(0x7FFFFF * normalizedDepth) << 8 |
uint8_t(0xFF & (!textures.empty() ? textures[0] : 0))); uint8_t(0xFF & (!textures.empty() ? textures[0] : 0)));
} }
void ObjectRenderer::renderGeometry(Geometry* geom, void ObjectRenderer::renderGeometry(Geometry* geom,
@ -106,9 +105,8 @@ void ObjectRenderer::renderGeometry(Geometry* geom,
float distance = glm::length(m_camera.position - position); float distance = glm::length(m_camera.position - position);
float depth = (distance - m_camera.frustum.near) / float depth = (distance - m_camera.frustum.near) /
(m_camera.frustum.far - m_camera.frustum.near); (m_camera.frustum.far - m_camera.frustum.near);
outList.emplace_back( outList.emplace_back(createKey(depth * depth, dp.textures), modelMatrix,
createKey(depth * depth, dp.textures), modelMatrix, &geom->dbuff, dp);
&geom->dbuff, dp);
} }
} }
@ -154,7 +152,7 @@ void ObjectRenderer::renderInstance(InstanceObject* instance,
} }
// Only draw visible objects // Only draw visible objects
if (!instance->getVisible()) { if (!instance->isVisible()) {
return; return;
} }
@ -226,7 +224,8 @@ void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,
} }
} }
renderClump(pedestrian->getClump().get(), glm::mat4(1.0f), nullptr, outList); renderClump(pedestrian->getClump().get(), glm::mat4(1.0f), nullptr,
outList);
auto item = pedestrian->getActiveItem(); auto item = pedestrian->getActiveItem();
const auto& weapon = pedestrian->engine->data->weaponData[item]; const auto& weapon = pedestrian->engine->data->weaponData[item];
@ -254,7 +253,8 @@ void ObjectRenderer::renderVehicle(VehicleObject* vehicle,
return; return;
} }
float mindist = glm::length(vehicle->getPosition() - m_camera.position) / kVehicleDrawDistanceFactor; float mindist = glm::length(vehicle->getPosition() - m_camera.position) /
kVehicleDrawDistanceFactor;
if (mindist > kVehicleDrawDistance) { if (mindist > kVehicleDrawDistance) {
culled++; culled++;
return; return;
@ -308,7 +308,8 @@ void ObjectRenderer::renderVehicle(VehicleObject* vehicle,
void ObjectRenderer::renderPickup(PickupObject* pickup, RenderList& outList) { void ObjectRenderer::renderPickup(PickupObject* pickup, RenderList& outList) {
if (!pickup->isEnabled()) return; if (!pickup->isEnabled()) return;
glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), pickup->getPosition()); glm::mat4 modelMatrix =
glm::translate(glm::mat4(1.0f), pickup->getPosition());
modelMatrix = glm::rotate(modelMatrix, m_world->getGameTime(), modelMatrix = glm::rotate(modelMatrix, m_world->getGameTime(),
glm::vec3(0.f, 0.f, 1.f)); glm::vec3(0.f, 0.f, 1.f));

View File

@ -2989,11 +2989,10 @@ bool opcode_0106(const ScriptArguments& args, const ScriptCharacter character0,
@arg object Object @arg object Object
*/ */
void opcode_0107(const ScriptArguments& args, const ScriptModel model, ScriptVec3 coord, ScriptObject& object) { void opcode_0107(const ScriptArguments& args, const ScriptModel model, ScriptVec3 coord, ScriptObject& object) {
RW_UNIMPLEMENTED_OPCODE(0x0107); // @todo calculate distance from centre of mass to base of model and apply it as spawnOffset
RW_UNUSED(model); coord = script::getGround(args, coord);
RW_UNUSED(coord); object = args.getWorld()->createInstance(script::getModel(args, model), coord);
RW_UNUSED(object); object->setStatic(true);
RW_UNUSED(args);
} }
/** /**
@ -6890,15 +6889,9 @@ void opcode_0299(const ScriptArguments& args, const ScriptGarage garage) {
@arg object Object @arg object Object
*/ */
void opcode_029b(const ScriptArguments& args, const ScriptModel model, ScriptVec3 coord, ScriptObject& object) { void opcode_029b(const ScriptArguments& args, const ScriptModel model, ScriptVec3 coord, ScriptObject& object) {
auto modelid = model; coord = script::getGround(args, coord);
if (modelid < 0) { object = args.getWorld()->createInstance(script::getModel(args, model), coord);
/// @todo move this to args.getModel(); object->setStatic(true);
auto& models = args.getVM()->getFile()->getModels();
auto& modelname = models[-modelid];
modelid = args.getWorld()->data->findModelObject(modelname);
}
object = args.getWorld()->createInstance(modelid, coord);
} }
/** /**
@ -10435,13 +10428,11 @@ void opcode_0391(const ScriptArguments& args) {
opcode 0392 opcode 0392
@arg object Object @arg object Object
@arg arg2 Boolean true/false @arg dynamic Boolean true/false
*/ */
void opcode_0392(const ScriptArguments& args, const ScriptObject object, const ScriptBoolean arg2) { void opcode_0392(const ScriptArguments& args, const ScriptObject object, const ScriptBoolean dynamic) {
RW_UNIMPLEMENTED_OPCODE(0x0392);
RW_UNUSED(object);
RW_UNUSED(arg2);
RW_UNUSED(args); RW_UNUSED(args);
object->setStatic(!dynamic);
} }
/** /**