Skip to content

Commit eb2caa8

Browse files
committed
Collision perf: first test collcab aabb with actor aabb.
When searching for colliding nodes in the pre-buffered `contactable_point_pool`, first check if the collcab AABB intersects with the 'collision partner' actor's AABB, only then search the actor's nodes for intersection. To do this, we need to know where each actor starts and ends in the `contactable_point_pool`. For this purpose, `struct ColActor` was added.
1 parent 376dade commit eb2caa8

8 files changed

+199
-145
lines changed

source/main/ForwardDeclarations.h

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ namespace RoR
101101
struct GuiManagerImpl;
102102
class HydraxWater;
103103
class InputEngine;
104+
class InterPointColDetector;
105+
class IntraPointColDetector;
104106
class IWater;
105107
class Landusemap;
106108
class LanguageEngine;

source/main/physics/Actor.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -938,12 +938,13 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction)
938938
node_t* na = &actor->ar_nodes[actor->ar_cabs[tmpv + 1]];
939939
node_t* nb = &actor->ar_nodes[actor->ar_cabs[tmpv + 2]];
940940

941-
m_intra_point_col_detector->query(no->AbsPosition - collision_offset,
941+
collision = m_intra_point_col_detector->QueryCollisionsWithAllPartners(
942+
no->AbsPosition - collision_offset,
942943
na->AbsPosition - collision_offset,
943944
nb->AbsPosition - collision_offset,
944945
actor->ar_collision_range * 3.0f);
945946

946-
if (collision = !m_intra_point_col_detector->hit_list.empty())
947+
if (collision)
947948
break;
948949
}
949950

@@ -988,12 +989,13 @@ Vector3 Actor::calculateCollisionOffset(Vector3 direction)
988989
node_t* na = &ar_nodes[ar_cabs[tmpv + 1]];
989990
node_t* nb = &ar_nodes[ar_cabs[tmpv + 2]];
990991

991-
m_inter_point_col_detector->query(no->AbsPosition + collision_offset,
992+
collision = m_inter_point_col_detector->QueryCollisionsWithAllPartners(
993+
no->AbsPosition + collision_offset,
992994
na->AbsPosition + collision_offset,
993995
nb->AbsPosition + collision_offset,
994996
ar_collision_range * 3.0f);
995997

996-
if (collision = !m_inter_point_col_detector->hit_list.empty())
998+
if (collision)
997999
break;
9981000
}
9991001
}

source/main/physics/Actor.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,8 @@ class Actor : public RefCountingObject<Actor>
533533
int m_num_proped_wheels = 0; //!< Physics attr, filled at spawn - Number of propelled wheels.
534534
float m_avg_proped_wheel_radius = 0.f; //!< Physics attr, filled at spawn - Average proped wheel radius.
535535
float m_avionic_chatter_timer = 11.f; //!< Sound fx state (some pseudo random number, doesn't matter)
536-
PointColDetector* m_inter_point_col_detector = nullptr; //!< Physics
537-
PointColDetector* m_intra_point_col_detector = nullptr; //!< Physics
536+
InterPointColDetector* m_inter_point_col_detector = nullptr; //!< Physics
537+
IntraPointColDetector* m_intra_point_col_detector = nullptr; //!< Physics
538538

539539
Ogre::Vector3 m_avg_node_position = Ogre::Vector3::ZERO; //!< average node position
540540
Ogre::Real m_min_camera_radius = 0.f;

source/main/physics/ActorSpawner.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,12 @@ void ActorSpawner::InitializeRig()
370370

371371
if (!App::sim_no_collisions->getBool())
372372
{
373-
m_actor->m_inter_point_col_detector = new PointColDetector(m_actor);
373+
m_actor->m_inter_point_col_detector = new InterPointColDetector(m_actor);
374374
}
375375

376376
if (!App::sim_no_self_collisions->getBool())
377377
{
378-
m_actor->m_intra_point_col_detector = new PointColDetector(m_actor);
378+
m_actor->m_intra_point_col_detector = new IntraPointColDetector(m_actor);
379379
}
380380

381381
m_actor->ar_submesh_ground_model = App::GetGameContext()->GetTerrain()->GetCollisions()->defaultgm;

source/main/physics/collision/DynamicCollisions.cpp

+101-94
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ void ResolveCollisionForces(const float penetration_depth,
114114
no.Forces -= forcevec * gamma;
115115
}
116116

117-
118-
void RoR::ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD,
117+
// STUPID OLD CODE: all the following params always belong to the same actor, see `ActorManager::UpdatePhysicsSimulation()`
118+
void RoR::ResolveInterActorCollisions(const float dt, InterPointColDetector &interPointCD,
119119
const int free_collcab, int collcabs[], int cabs[],
120120
collcab_rate_t inter_collcabrate[], node_t nodes[],
121121
const float collrange,
@@ -137,69 +137,73 @@ void RoR::ResolveInterActorCollisions(const float dt, PointColDetector &interPoi
137137
const auto na = &nodes[cabs[tmpv+1]];
138138
const auto nb = &nodes[cabs[tmpv+2]];
139139

140-
interPointCD.query(no->AbsPosition
141-
, na->AbsPosition
142-
, nb->AbsPosition, collrange);
140+
Ogre::AxisAlignedBox collcab_box;
141+
collcab_box.merge(no->AbsPosition);
142+
collcab_box.merge(na->AbsPosition);
143+
collcab_box.merge(nb->AbsPosition);
144+
collcab_box.setMinimum(collcab_box.getMinimum() - collrange);
145+
collcab_box.setMaximum(collcab_box.getMaximum() + collrange);
143146

144-
if (!interPointCD.hit_list.empty())
147+
for (const PointColDetector::ColActor& partner: interPointCD.collision_partners)
145148
{
146-
// setup transformation of points to triangle local coordinates
147-
const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition);
148-
const CartesianToTriangleTransform transform(triangle);
149-
150-
for (ColPointID_t i_hit : interPointCD.hit_list)
149+
if (interPointCD.QueryCollisionsWithSinglePartner(collcab_box, partner))
151150
{
152-
const PointColDetector::ColPoint& h = interPointCD.contactable_point_pool[i_hit];
153-
const ActorPtr& hit_actor = App::GetGameContext()->GetActorManager()->GetActorById(h.actorid);
154-
node_t& hitnode = hit_actor->ar_nodes[h.nodenum];
151+
// setup transformation of points to triangle local coordinates
152+
const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition);
153+
const CartesianToTriangleTransform transform(triangle);
155154

156-
// transform point to triangle local coordinates
157-
const auto local_point = transform(hitnode.AbsPosition);
158-
159-
// collision test
160-
const bool is_colliding = InsideTriangleTest(local_point, collrange);
161-
if (is_colliding)
155+
for (NodeNum_t hitnode_num: interPointCD.hit_list)
162156
{
163-
inter_collcabrate[i].rate = 0;
157+
node_t& hitnode = partner.actor->ar_nodes[hitnode_num];
164158

165-
const auto coord = local_point.barycentric;
166-
auto distance = local_point.distance;
167-
auto normal = triangle.normal();
159+
// transform point to triangle local coordinates
160+
const auto local_point = transform(hitnode.AbsPosition);
168161

169-
// adapt in case the collision is occuring on the backface of the triangle
170-
const auto neighbour_node_ids = hit_actor->ar_node_to_node_connections[h.nodenum];
171-
const bool is_backface = BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, hit_actor->ar_nodes);
172-
if (is_backface)
162+
// collision test
163+
const bool is_colliding = InsideTriangleTest(local_point, collrange);
164+
if (is_colliding)
173165
{
174-
// flip surface normal and distance to triangle plane
175-
normal = -normal;
176-
distance = -distance;
166+
inter_collcabrate[i].rate = 0;
167+
168+
const auto coord = local_point.barycentric;
169+
auto distance = local_point.distance;
170+
auto normal = triangle.normal();
171+
172+
// adapt in case the collision is occuring on the backface of the triangle
173+
const auto neighbour_node_ids = partner.actor->ar_node_to_node_connections[hitnode_num];
174+
const bool is_backface = BackfaceCollisionTest(distance, normal, *no, neighbour_node_ids, partner.actor->ar_nodes);
175+
if (is_backface)
176+
{
177+
// flip surface normal and distance to triangle plane
178+
normal = -normal;
179+
distance = -distance;
180+
}
181+
182+
const auto penetration_depth = collrange - distance;
183+
184+
const bool remote = (partner.actor->ar_state == ActorState::NETWORKED_OK);
185+
186+
ResolveCollisionForces(penetration_depth, hitnode, *na, *nb, *no, coord.alpha,
187+
coord.beta, coord.gamma, normal, dt, remote, submesh_ground_model);
188+
189+
hitnode.nd_last_collision_gm = &submesh_ground_model;
190+
hitnode.nd_has_mesh_contact = true;
191+
na->nd_has_mesh_contact = true;
192+
nb->nd_has_mesh_contact = true;
193+
no->nd_has_mesh_contact = true;
177194
}
178-
179-
const auto penetration_depth = collrange - distance;
180-
181-
const bool remote = (hit_actor->ar_state == ActorState::NETWORKED_OK);
182-
183-
ResolveCollisionForces(penetration_depth, hitnode, *na, *nb, *no, coord.alpha,
184-
coord.beta, coord.gamma, normal, dt, remote, submesh_ground_model);
185-
186-
hitnode.nd_last_collision_gm = &submesh_ground_model;
187-
hitnode.nd_has_mesh_contact = true;
188-
na->nd_has_mesh_contact = true;
189-
nb->nd_has_mesh_contact = true;
190-
no->nd_has_mesh_contact = true;
191195
}
192196
}
193-
}
194-
else
195-
{
196-
inter_collcabrate[i].rate++;
197+
else
198+
{
199+
inter_collcabrate[i].rate++;
200+
}
197201
}
198202
}
199203
}
200204

201-
202-
void RoR::ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD,
205+
// STUPID OLD CODE: all the following params always belong to the same actor, see `Actor::CalcCabCollisions()`
206+
void RoR::ResolveIntraActorCollisions(const float dt, IntraPointColDetector &intraPointCD,
203207
const int free_collcab, int collcabs[], int cabs[],
204208
collcab_rate_t intra_collcabrate[], node_t nodes[],
205209
const float collrange,
@@ -224,64 +228,67 @@ void RoR::ResolveIntraActorCollisions(const float dt, PointColDetector &intraPoi
224228
const auto na = &nodes[cabs[tmpv+1]];
225229
const auto nb = &nodes[cabs[tmpv+2]];
226230

227-
intraPointCD.query(no->AbsPosition
228-
, na->AbsPosition
229-
, nb->AbsPosition, collrange);
231+
Ogre::AxisAlignedBox collcab_box;
232+
collcab_box.merge(no->AbsPosition);
233+
collcab_box.merge(na->AbsPosition);
234+
collcab_box.merge(nb->AbsPosition);
235+
collcab_box.setMinimum(collcab_box.getMinimum() - collrange);
236+
collcab_box.setMaximum(collcab_box.getMaximum() + collrange);
230237

231238
bool collision = false;
232-
233-
if (!intraPointCD.hit_list.empty())
239+
for (const PointColDetector::ColActor& partner: intraPointCD.collision_partners)
234240
{
235-
// setup transformation of points to triangle local coordinates
236-
const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition);
237-
const CartesianToTriangleTransform transform(triangle);
238-
239-
for (ColPointID_t i_hit : intraPointCD.hit_list)
241+
if (intraPointCD.QueryCollisionsWithSinglePartner(collcab_box, partner))
240242
{
241-
const PointColDetector::ColPoint& h = intraPointCD.contactable_point_pool[i_hit];
242-
const ActorPtr& hit_actor = App::GetGameContext()->GetActorManager()->GetActorById(h.actorid);
243-
node_t& hitnode = hit_actor->ar_nodes[h.nodenum];
244-
245-
//ignore wheel/chassis self contact
246-
if (hitnode.nd_tyre_node) continue;
247-
if (no == &hitnode || na == &hitnode || nb == &hitnode) continue;
243+
// setup transformation of points to triangle local coordinates
244+
const Triangle triangle(na->AbsPosition, nb->AbsPosition, no->AbsPosition);
245+
const CartesianToTriangleTransform transform(triangle);
248246

249-
// transform point to triangle local coordinates
250-
const auto local_point = transform(hitnode.AbsPosition);
251-
252-
// collision test
253-
const bool is_colliding = InsideTriangleTest(local_point, collrange);
254-
if (is_colliding)
247+
for (NodeNum_t hitnode_num: intraPointCD.hit_list)
255248
{
256-
collision = true;
249+
node_t& hitnode = partner.actor->ar_nodes[hitnode_num];
250+
251+
//ignore wheel/chassis self contact
252+
if (hitnode.nd_tyre_node) continue;
253+
if (no == &hitnode || na == &hitnode || nb == &hitnode) continue;
257254

258-
const auto coord = local_point.barycentric;
259-
auto distance = local_point.distance;
260-
auto normal = triangle.normal();
255+
// transform point to triangle local coordinates
256+
const auto local_point = transform(hitnode.AbsPosition);
261257

262-
// adapt in case the collision is occuring on the backface of the triangle
263-
if (distance < 0)
258+
// collision test
259+
const bool is_colliding = InsideTriangleTest(local_point, collrange);
260+
if (is_colliding)
264261
{
265-
// flip surface normal and distance to triangle plane
266-
normal = -normal;
267-
distance = -distance;
268-
}
262+
collision = true;
263+
264+
const auto coord = local_point.barycentric;
265+
auto distance = local_point.distance;
266+
auto normal = triangle.normal();
269267

270-
const auto penetration_depth = collrange - distance;
268+
// adapt in case the collision is occuring on the backface of the triangle
269+
if (distance < 0)
270+
{
271+
// flip surface normal and distance to triangle plane
272+
normal = -normal;
273+
distance = -distance;
274+
}
271275

272-
ResolveCollisionForces(penetration_depth, hitnode, *na, *nb, *no, coord.alpha,
273-
coord.beta, coord.gamma, normal, dt, false, submesh_ground_model);
276+
const auto penetration_depth = collrange - distance;
277+
278+
ResolveCollisionForces(penetration_depth, hitnode, *na, *nb, *no, coord.alpha,
279+
coord.beta, coord.gamma, normal, dt, false, submesh_ground_model);
280+
}
274281
}
275282
}
276-
}
277283

278-
if (collision)
279-
{
280-
intra_collcabrate[i].rate = -20000;
281-
}
282-
else
283-
{
284-
intra_collcabrate[i].rate++;
284+
if (collision)
285+
{
286+
intra_collcabrate[i].rate = -20000;
287+
}
288+
else
289+
{
290+
intra_collcabrate[i].rate++;
291+
}
285292
}
286293
}
287294
}

source/main/physics/collision/DynamicCollisions.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ namespace RoR {
3232
/// @addtogroup Collisions
3333
/// @{
3434

35-
void ResolveInterActorCollisions(const float dt, PointColDetector &interPointCD,
35+
void ResolveInterActorCollisions(const float dt, InterPointColDetector &interPointCD,
3636
const int free_collcab, int collcabs[], int cabs[],
3737
collcab_rate_t inter_collcabrate[], node_t nodes[],
3838
const float collrange,
3939
ground_model_t &submesh_ground_model);
4040

41-
void ResolveIntraActorCollisions(const float dt, PointColDetector &intraPointCD,
41+
void ResolveIntraActorCollisions(const float dt, IntraPointColDetector &intraPointCD,
4242
const int free_collcab, int collcabs[], int cabs[],
4343
collcab_rate_t intra_collcabrate[], node_t nodes[],
4444
const float collrange,

0 commit comments

Comments
 (0)