void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, const int free_collcab, int collcabs[], int cabs[], collcab_rate_t inter_collcabrate[], node_t nodes[], const float collrange, ground_model_t &submesh_ground_model) { Actor** actor_slots = RoR::App::GetSimController()->GetBeamFactory()->GetInternalActorSlots(); for (int i=0; i<free_collcab; i++) { if (inter_collcabrate[i].rate > 0) { inter_collcabrate[i].distance++; inter_collcabrate[i].rate--; continue; } inter_collcabrate[i].rate = std::min(inter_collcabrate[i].distance, 12); inter_collcabrate[i].distance = 0; int tmpv = collcabs[i]*3; const auto no = &nodes[cabs[tmpv]]; const auto na = &nodes[cabs[tmpv+1]]; const auto nb = &nodes[cabs[tmpv+2]]; interPointCD.query(no->AbsPosition , na->AbsPosition , nb->AbsPosition, collrange); if (interPointCD.hit_count > 0) { // setup transformation of points to triangle local coordinates const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); const CartesianToTriangleTransform transform(triangle); for (int h=0; h<interPointCD.hit_count; h++) { const auto hitnodeid = interPointCD.hit_list[h]->node_id; const auto hit_actor_id = interPointCD.hit_list[h]->actor_id; const auto hitnode = &actor_slots[hit_actor_id]->ar_nodes[hitnodeid]; const Actor* hit_actor = actor_slots[hit_actor_id]; // transform point to triangle local coordinates const auto local_point = transform(hitnode->AbsPosition); // collision test const bool is_colliding = InsideTriangleTest(local_point, collrange); if (is_colliding) { inter_collcabrate[i].rate = 0; const auto coord = local_point.barycentric; auto distance = local_point.distance; auto normal = triangle.normal(); // adapt in case the collision is occuring on the backface of the triangle const auto neighbour_node_ids = hit_actor->ar_node_to_node_connections[hitnodeid]; const bool is_backface = BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, hit_actor->ar_nodes); if (is_backface) { // flip surface normal and distance to triangle plane normal = -normal; distance = -distance; } const auto penetration_depth = collrange - distance; ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, coord.beta, coord.gamma, normal, dt, submesh_ground_model); } } } else { inter_collcabrate[i].rate++; } } }
void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD, const int free_collcab, int collcabs[], int cabs[], collcab_rate_t intra_collcabrate[], node_t nodes[], const float collrange, ground_model_t &submesh_ground_model) { for (int i=0; i<free_collcab; i++) { if (intra_collcabrate[i].rate > 0) { intra_collcabrate[i].distance++; intra_collcabrate[i].rate--; continue; } if (intra_collcabrate[i].distance > 0) { intra_collcabrate[i].rate = std::min(intra_collcabrate[i].distance, 12); intra_collcabrate[i].distance = 0; } int tmpv = collcabs[i]*3; const auto no = &nodes[cabs[tmpv]]; const auto na = &nodes[cabs[tmpv+1]]; const auto nb = &nodes[cabs[tmpv+2]]; intraPointCD.query(no->AbsPosition , na->AbsPosition , nb->AbsPosition, collrange); bool collision = false; if (intraPointCD.hit_count > 0) { // setup transformation of points to triangle local coordinates const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); const CartesianToTriangleTransform transform(triangle); for (int h=0; h<intraPointCD.hit_count; h++) { const auto hitnodeid = intraPointCD.hit_list[h]->node_id; const auto hitnode = &nodes[hitnodeid]; //ignore wheel/chassis self contact if (hitnode->iswheel) continue; if (no == hitnode || na == hitnode || nb == hitnode) continue; // transform point to triangle local coordinates const auto local_point = transform(hitnode->AbsPosition); // collision test const bool is_colliding = InsideTriangleTest(local_point, collrange); if (is_colliding) { collision = true; const auto coord = local_point.barycentric; auto distance = local_point.distance; auto normal = triangle.normal(); // adapt in case the collision is occuring on the backface of the triangle if (distance < 0) { // flip surface normal and distance to triangle plane normal = -normal; distance = -distance; } const auto penetration_depth = collrange - distance; ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, coord.beta, coord.gamma, normal, dt, submesh_ground_model); } } } if (collision) { intra_collcabrate[i].rate = -20000; } else { intra_collcabrate[i].rate++; } } }
void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD, const int free_collcab, int collcabs[], int cabs[], collcab_rate_t inter_collcabrate[], node_t nodes[], const float collrange, ground_model_t &submesh_ground_model) { for (int i=0; i<free_collcab; i++) { if (inter_collcabrate[i].rate > 0) { inter_collcabrate[i].distance++; inter_collcabrate[i].rate--; continue; } inter_collcabrate[i].rate = std::min(inter_collcabrate[i].distance, 12); inter_collcabrate[i].distance = 0; int tmpv = collcabs[i]*3; const auto no = &nodes[cabs[tmpv]]; const auto na = &nodes[cabs[tmpv+1]]; const auto nb = &nodes[cabs[tmpv+2]]; interPointCD.query(no->AbsPosition , na->AbsPosition , nb->AbsPosition, collrange); if (!interPointCD.hit_list.empty()) { // setup transformation of points to triangle local coordinates const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition); const CartesianToTriangleTransform transform(triangle); for (auto h : interPointCD.hit_list) { const auto hit_actor = h->actor; const auto hitnode = &hit_actor->ar_nodes[h->node_id]; // transform point to triangle local coordinates const auto local_point = transform(hitnode->AbsPosition); // collision test const bool is_colliding = InsideTriangleTest(local_point, collrange); if (is_colliding) { inter_collcabrate[i].rate = 0; const auto coord = local_point.barycentric; auto distance = local_point.distance; auto normal = triangle.normal(); // adapt in case the collision is occuring on the backface of the triangle const auto neighbour_node_ids = hit_actor->ar_node_to_node_connections[h->node_id]; const bool is_backface = BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, hit_actor->ar_nodes); if (is_backface) { // flip surface normal and distance to triangle plane normal = -normal; distance = -distance; } const auto penetration_depth = collrange - distance; const bool remote = (hit_actor->ar_sim_state == Actor::SimState::NETWORKED_OK); ResolveCollisionForces(penetration_depth, *hitnode, *na, *nb, *no, coord.alpha, coord.beta, coord.gamma, normal, dt, remote, submesh_ground_model); hitnode->nd_last_collision_gm = &submesh_ground_model; hitnode->nd_has_mesh_contact = true; na->nd_has_mesh_contact = true; nb->nd_has_mesh_contact = true; no->nd_has_mesh_contact = true; } } } else { inter_collcabrate[i].rate++; } } }