diff --git a/rwengine/src/engine/GameWorld.cpp b/rwengine/src/engine/GameWorld.cpp index d19f0db1..88fd4c46 100644 --- a/rwengine/src/engine/GameWorld.cpp +++ b/rwengine/src/engine/GameWorld.cpp @@ -280,18 +280,23 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, auto model = vti->getModel(); auto info = data->vehicleInfo.find(vti->handling_); - if (model && info != data->vehicleInfo.end()) { - if (info->second->wheels.size() == 0 && - info->second->seats.size() == 0) { - for (const ModelFrame* f : model->frames) { - const std::string& name = f->getName(); + if (model && info != data->vehicleInfo.end() && + info->second->wheels.size() == 0 && info->second->seats.size() == 0) { + auto root = model->getFrame(); + for (const auto& frame : root->getChildren()) { + const std::string& name = frame->getName(); - if (name.size() > 5 && name.substr(0, 5) == "wheel") { - auto frameTrans = f->getMatrix(); - info->second->wheels.push_back({glm::vec3(frameTrans[3])}); - } - if (name == "ped_frontseat") { - auto p = f->getDefaultTranslation(); + if (name.size() > 5 && name.substr(0, 5) == "wheel") { + auto frameTrans = frame->getMatrix(); + info->second->wheels.push_back({glm::vec3(frameTrans[3])}); + } + + if (name == "chassis_dummy") { + // These are nested within chassis_dummy + auto frontseat = frame->findDescendant("ped_frontseat"); + auto backseat = frame->findDescendant("ped_backseat"); + if (frontseat) { + auto p = frontseat->getDefaultTranslation(); // Left seat p.x = -p.x; info->second->seats.front.push_back({p}); @@ -299,10 +304,10 @@ VehicleObject* GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, p.x = -p.x; info->second->seats.front.push_back({p}); } - if (name == "ped_backseat") { + if (backseat) { // @todo how does this work for the barracks, ambulance // or coach? - auto p = f->getDefaultTranslation(); + auto p = backseat->getDefaultTranslation(); // Left seat p.x = -p.x; info->second->seats.back.push_back({p}); diff --git a/rwengine/src/objects/VehicleObject.cpp b/rwengine/src/objects/VehicleObject.cpp index 2afcebca..d75be0fe 100644 --- a/rwengine/src/objects/VehicleObject.cpp +++ b/rwengine/src/objects/VehicleObject.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include #include @@ -153,18 +153,13 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, setModel(getVehicle()->getModel()); - for (ModelFrame* frame : getModel()->frames) { + // Create meta-data for dummy parts + auto chassisframe = getModel()->findFrame("chassis_dummy"); + for (auto& frame : chassisframe->getChildren()) { auto& name = frame->getName(); - bool isDam = name.find("_dam") != name.npos; - bool isLod = name.find("lo") != name.npos; bool isDum = name.find("_dummy") != name.npos; - /*bool isOk = name.find("_ok") != name.npos;*/ - if (isDam || isLod || isDum) { - skeleton->setEnabled(frame, false); - } - if (isDum) { - registerPart(frame); + registerPart(frame.get()); } } } @@ -551,13 +546,11 @@ bool VehicleObject::takeDamage(const GameObject::DamageInfo& dmg) { if (p->normal == nullptr) continue; if (skeleton->getData(p->normal->getIndex()).enabled) { - auto& geom = - getModel()->geometries[p->normal->getGeometries()[0]]; - auto pp = - p->normal->getMatrix() * glm::vec4(0.f, 0.f, 0.f, 1.f); - float td = glm::distance( - glm::vec3(pp) + geom->geometryBounds.center, dpoint); - if (td < geom->geometryBounds.radius * 1.2f) { + /// @todo correct logic + float damageradius = 0.1f; + auto center = glm::vec3(p->normal->getMatrix()[3]); + float td = glm::distance(center, dpoint); + if (td < damageradius * 1.2f) { setPartState(p, DAM); } /// @todo determine when doors etc. should un-latch @@ -638,20 +631,13 @@ VehicleObject::Part* VehicleObject::getPart(const std::string& name) { return nullptr; } -ModelFrame* findStateFrame(ModelFrame* f, const std::string& state) { - auto it = std::find_if( - f->getChildren().begin(), f->getChildren().end(), [&](ModelFrame* c) { - return c->getName().find(state) != std::string::npos; - }); - if (it != f->getChildren().end()) { - return *it; - } - return nullptr; -} - void VehicleObject::registerPart(ModelFrame* mf) { - auto normal = findStateFrame(mf, "_ok"); - auto damage = findStateFrame(mf, "_dam"); + auto dummynameend = mf->getName().find("_dummy"); + 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"); if (normal == nullptr && damage == nullptr) { // Not actually a useful part, just a dummy. @@ -672,20 +658,12 @@ void VehicleObject::createObjectHinge(Part* part) { auto& fn = part->dummy->getName(); - ModelFrame* okframe = part->normal; - - if (okframe->getGeometries().size() == 0) return; - - auto& geom = getModel()->geometries[okframe->getGeometries()[0]]; - auto gbounds = geom->geometryBounds; - if (fn.find("door") != fn.npos) { hingeAxis = {0.f, 0.f, 1.f}; // hingePosition = {0.f, 0.2f, 0.f}; boxSize = {0.15f, 0.5f, 0.6f}; // boxOffset = {0.f,-0.2f, gbounds.center.z/2.f}; - auto tf = gbounds.center; - boxOffset = btVector3(tf.x, tf.y, tf.z); + boxOffset = btVector3(0.f, -0.25f, 0.f); hingePosition = -boxOffset; if (sign < 0.f) {