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

Implement Vehicle dynamics with Frames instead of Skeleton

This commit is contained in:
Daniel Evans 2017-01-08 01:36:08 +00:00
parent f64104600e
commit 1514bd2cc5
3 changed files with 27 additions and 37 deletions

View File

@ -70,11 +70,7 @@ public:
const auto& rot = tform.getRotation();
auto r2 = inv * glm::quat(rot.w(), rot.x(), rot.y(), rot.z());
auto skeleton = m_object->skeleton;
auto& prev = skeleton->getData(m_part->dummy->getIndex()).a;
auto next = prev;
next.rotation = r2;
skeleton->setData(m_part->dummy->getIndex(), {next, prev, true});
m_part->dummy->setRotation(glm::mat3_cast(r2));
}
private:
@ -148,9 +144,6 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos,
: 1.f - info->handling.tractionBias);
}
// Hide all LOD and damage frames.
skeleton = new Skeleton;
setModel(getVehicle()->getModel());
setClump(ClumpPtr(getModelInfo<VehicleModelInfo>()->getModel()->clone()));
@ -557,16 +550,14 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) {
if (p->normal == nullptr) continue;
if (skeleton->getData(p->normal->getIndex()).enabled) {
/// @todo correct logic
float damageradius = 0.1f;
auto center = glm::vec3(p->normal->getWorldTransform()[3]);
float td = glm::distance(center, dpoint);
if (td < damageradius * 1.2f) {
setPartState(p, DAM);
}
/// @todo determine when doors etc. should un-latch
/// @todo correct logic
float damageradius = 0.1f;
auto center = glm::vec3(p->dummy->getWorldTransform()[3]);
float td = glm::distance(center, dpoint);
if (td < damageradius * 1.2f) {
setPartState(p, DAM);
}
/// @todo determine when doors etc. should un-latch
}
}
@ -576,11 +567,11 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) {
void VehicleObject::setPartState(VehicleObject::Part* part,
VehicleObject::FrameState state) {
if (state == VehicleObject::OK) {
if (part->normal) skeleton->setEnabled(part->normal, true);
if (part->damaged) skeleton->setEnabled(part->damaged, false);
if (part->normal) part->normal->setFlag(Atomic::ATOMIC_RENDER, true);
if (part->damaged) part->damaged->setFlag(Atomic::ATOMIC_RENDER, false);
} else if (state == VehicleObject::DAM) {
if (part->normal) skeleton->setEnabled(part->normal, false);
if (part->damaged) skeleton->setEnabled(part->damaged, true);
if (part->normal) part->normal->setFlag(Atomic::ATOMIC_RENDER, false);
if (part->damaged) part->damaged->setFlag(Atomic::ATOMIC_RENDER, true);
}
}
@ -611,10 +602,7 @@ void VehicleObject::setPartLocked(VehicleObject::Part* part, bool locked) {
destroyObjectHinge(part);
// Restore default bone transform
auto dt = part->dummy->getDefaultTranslation();
auto dr = glm::quat_cast(part->dummy->getDefaultRotation());
Skeleton::FrameTransform tf{dt, dr};
skeleton->setData(part->dummy->getIndex(), {tf, tf, true});
part->dummy->reset();
}
}
@ -648,10 +636,10 @@ void VehicleObject::registerPart(ModelFrame* mf) {
RW_CHECK(dummynameend != std::string::npos,
"Can't create part from non-dummy");
auto dummyname = mf->getName().substr(0, dummynameend);
auto normal = mf->findDescendant(dummyname + "_hi_ok");
auto damage = mf->findDescendant(dummyname + "_hi_dam");
auto normalframe = mf->findDescendant(dummyname + "_hi_ok");
auto damageframe = mf->findDescendant(dummyname + "_hi_dam");
if (normal == nullptr && damage == nullptr) {
if (normalframe == nullptr && damageframe == nullptr) {
// Not actually a useful part, just a dummy.
return;
}

View File

@ -36,8 +36,8 @@ public:
struct Part {
ModelFrame* dummy;
ModelFrame* normal;
ModelFrame* damaged;
Atomic* normal;
Atomic* damaged;
btRigidBody* body;
btHingeConstraint* constraint;
bool moveToAngle;

View File

@ -41,8 +41,11 @@ BOOST_AUTO_TEST_CASE(vehicle_parts) {
BOOST_REQUIRE(part->normal != nullptr);
BOOST_REQUIRE(part->damaged != nullptr);
BOOST_CHECK_EQUAL(part->normal->getName(), "bonnet_hi_ok");
BOOST_CHECK_EQUAL(part->damaged->getName(), "bonnet_hi_dam");
BOOST_REQUIRE(part->normal->getFrame());
BOOST_REQUIRE(part->damaged->getFrame());
BOOST_CHECK_EQUAL(part->normal->getFrame()->getName(), "bonnet_hi_ok");
BOOST_CHECK_EQUAL(part->damaged->getFrame()->getName(), "bonnet_hi_dam");
Global::get().e->destroyObject(vehicle);
}
@ -55,17 +58,16 @@ BOOST_AUTO_TEST_CASE(vehicle_part_vis) {
BOOST_REQUIRE(vehicle->getModel() != nullptr);
VehicleObject::Part* bonnetpart = vehicle->getPart("bonnet_dummy");
auto skel = vehicle->skeleton;
vehicle->setPartState(bonnetpart, VehicleObject::DAM);
BOOST_CHECK(!skel->getData(bonnetpart->normal->getIndex()).enabled);
BOOST_CHECK(skel->getData(bonnetpart->damaged->getIndex()).enabled);
BOOST_CHECK((bonnetpart->normal->getFlags() & Atomic::ATOMIC_RENDER) == 0);
BOOST_CHECK((bonnetpart->damaged->getFlags() & Atomic::ATOMIC_RENDER) != 0);
vehicle->setPartState(bonnetpart, VehicleObject::OK);
BOOST_CHECK(skel->getData(bonnetpart->normal->getIndex()).enabled);
BOOST_CHECK(!skel->getData(bonnetpart->damaged->getIndex()).enabled);
BOOST_CHECK((bonnetpart->normal->getFlags() & Atomic::ATOMIC_RENDER) != 0);
BOOST_CHECK((bonnetpart->damaged->getFlags() & Atomic::ATOMIC_RENDER) == 0);
Global::get().e->destroyObject(vehicle);
}