diff --git a/source/main/physics/Actor.cpp b/source/main/physics/Actor.cpp index 44356c4a9c..936a56133d 100644 --- a/source/main/physics/Actor.cpp +++ b/source/main/physics/Actor.cpp @@ -1116,12 +1116,18 @@ void Actor::UpdateBoundingBoxes() // Reset ar_bounding_box = AxisAlignedBox::BOX_NULL; ar_predicted_bounding_box = AxisAlignedBox::BOX_NULL; + ar_cabnodes_bounding_box = AxisAlignedBox::BOX_NULL; for (size_t i = 0; i < ar_collision_bounding_boxes.size(); ++i) { ar_collision_bounding_boxes[i] = AxisAlignedBox::BOX_NULL; ar_predicted_coll_bounding_boxes[i] = AxisAlignedBox::BOX_NULL; } + // To avoid performance choking by overstretched bounding box (happens when vehicle drops some nodes), + // we set a maximum distance limit from the main camera. + const float CABNODE_MAX_CAMDIST = 15.f; + const Ogre::Vector3 mainCamPos = ar_nodes[ar_main_camera_node_pos].RelPosition; + // Update for (int i = 0; i < ar_num_nodes; i++) { @@ -1130,6 +1136,11 @@ void Actor::UpdateBoundingBoxes() int16_t cid = ar_nodes[i].nd_coll_bbox_id; ar_bounding_box.merge(pos); // Current box + if (ar_nodes[i].nd_cab_node // Current cab-nodes box (for eventbox collisions) + && (mainCamPos.squaredDistance(ar_nodes[i].RelPosition)) < (CABNODE_MAX_CAMDIST*CABNODE_MAX_CAMDIST)) // ... we compare squared distance for performance + { + ar_cabnodes_bounding_box.merge(pos); + } ar_predicted_bounding_box.merge(pos); // Predicted box (current position) ar_predicted_bounding_box.merge(pos + vel); // Predicted box (future position) if (cid != node_t::INVALID_BBOX) diff --git a/source/main/physics/Actor.h b/source/main/physics/Actor.h index 6b21a044e9..8a1fe5f4b2 100644 --- a/source/main/physics/Actor.h +++ b/source/main/physics/Actor.h @@ -290,6 +290,7 @@ class Actor : public RefCountingObject std::vector ar_airbrakes; CmdKeyArray ar_command_key; //!< BEWARE: commandkeys are indexed 1-MAX_COMMANDS! Ogre::AxisAlignedBox ar_bounding_box; //!< standard bounding box (surrounds all nodes of an actor) + Ogre::AxisAlignedBox ar_cabnodes_bounding_box; //!< bounding box around cab-triangle nodes only Ogre::AxisAlignedBox ar_predicted_bounding_box; float ar_initial_total_mass = 0.f; std::vector ar_initial_node_masses; diff --git a/source/main/physics/collision/Collisions.cpp b/source/main/physics/collision/Collisions.cpp index 353436a185..d2fdfe3dbf 100644 --- a/source/main/physics/collision/Collisions.cpp +++ b/source/main/physics/collision/Collisions.cpp @@ -1088,8 +1088,11 @@ bool Collisions::nodeCollision(node_t *node, float dt) void Collisions::findPotentialEventBoxes(Actor* actor, CollisionBoxPtrVec& out_boxes) { + // NOTE: Only collision-cab nodes are considered for eventbox triggering! + // ---------------------------------------------------------------------- + // Find collision cells occupied by the actor (remember 'Y' is 'up'). - const AxisAlignedBox aabb = actor->ar_bounding_box; + const AxisAlignedBox aabb = actor->ar_cabnodes_bounding_box; const int cell_lo_x = (int)(aabb.getMinimum().x / (float)CELL_SIZE); const int cell_lo_z = (int)(aabb.getMinimum().z / (float)CELL_SIZE); const int cell_hi_x = (int)(aabb.getMaximum().x / (float)CELL_SIZE);