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:
commit
de8131924d
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user