@@ -28,6 +28,31 @@ static_assert(sizeof(b2FixtureData_map) <= sizeof(void*), "Cannot pack data into
2828
2929// ////////////////////////////////////////////////////////////////////////
3030
31+ // choose fixture by category bits (any of it)
32+ inline b2Fixture* FilterFixture (b2Fixture* fixtureA, b2Fixture* fixtureB, unsigned short categoryBits)
33+ {
34+ if ((fixtureA->GetFilterData ().categoryBits & categoryBits) > 0 )
35+ return fixtureA;
36+
37+ if ((fixtureB->GetFilterData ().categoryBits & categoryBits) > 0 )
38+ return fixtureB;
39+
40+ return nullptr ;
41+ }
42+
43+ template <typename TUserDataClass>
44+ inline TUserDataClass* CastBodyData (b2Body* physicsBody)
45+ {
46+ debug_assert (physicsBody);
47+
48+ void * userdata = physicsBody->GetUserData ();
49+ debug_assert (userdata);
50+
51+ return (TUserDataClass*) userdata;
52+ }
53+
54+ // ////////////////////////////////////////////////////////////////////////
55+
3156PhysicsManager gPhysics ;
3257
3358PhysicsManager::PhysicsManager ()
@@ -271,89 +296,107 @@ void PhysicsManager::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
271296 b2Fixture* fixtureA = contact->GetFixtureA ();
272297 b2Fixture* fixtureB = contact->GetFixtureB ();
273298
274- b2Fixture* fixtureMapSolidBlock = nullptr ;
275- b2Fixture* fixturePed = nullptr ;
276- b2Fixture* fixtureCar = nullptr ;
277- if (fixtureA->GetFilterData ().categoryBits == PHYSICS_OBJCAT_MAP_SOLID_BLOCK)
278- {
279- fixtureMapSolidBlock = fixtureA;
280- }
281- if (fixtureB->GetFilterData ().categoryBits == PHYSICS_OBJCAT_MAP_SOLID_BLOCK)
282- {
283- fixtureMapSolidBlock = fixtureB;
284- }
285-
286- if (fixtureA->GetFilterData ().categoryBits == PHYSICS_OBJCAT_PED)
287- {
288- fixturePed = fixtureA;
289- }
290- if (fixtureB->GetFilterData ().categoryBits == PHYSICS_OBJCAT_PED)
291- {
292- fixturePed = fixtureB;
293- }
294-
295- if (fixtureA->GetFilterData ().categoryBits == PHYSICS_OBJCAT_CAR)
296- {
297- fixtureCar = fixtureA;
298- }
299- if (fixtureB->GetFilterData ().categoryBits == PHYSICS_OBJCAT_CAR)
300- {
301- fixtureCar = fixtureB;
302- }
303-
304299 bool hasCollision = true ;
305- for (;;)
300+ if (fixtureA->GetFilterData ().categoryBits ==
301+ fixtureB->GetFilterData ().categoryBits )
306302 {
307- if (fixtureA-> GetFilterData (). categoryBits == PHYSICS_OBJCAT_PED &&
308- fixtureB ->GetFilterData ().categoryBits == PHYSICS_OBJCAT_PED)
303+ // ped vs ped
304+ if (fixtureA ->GetFilterData ().categoryBits == PHYSICS_OBJCAT_PED)
309305 {
310- PedPhysicsComponent* physicsComponentA = ( PedPhysicsComponent*) fixtureA->GetBody ()-> GetUserData ( );
311- PedPhysicsComponent* physicsComponentB = ( PedPhysicsComponent*) fixtureB->GetBody ()-> GetUserData ( );
312- hasCollision = CollidePedVsPed (contact, physicsComponentA, physicsComponentB);
306+ PedPhysicsComponent* physicsComponentA = CastBodyData< PedPhysicsComponent>( fixtureA->GetBody ());
307+ PedPhysicsComponent* physicsComponentB = CastBodyData< PedPhysicsComponent>( fixtureB->GetBody ());
308+ hasCollision = HasCollisionPedVsPed (contact, physicsComponentA, physicsComponentB);
313309 }
314-
315- if (hasCollision && fixturePed )
310+ // car vs car
311+ if (fixtureA-> GetFilterData (). categoryBits == PHYSICS_OBJCAT_CAR )
316312 {
317- PedPhysicsComponent* physicsComponent = (PedPhysicsComponent*) fixturePed->GetBody ()->GetUserData ();
318- debug_assert (physicsComponent);
319-
320- hasCollision = physicsComponent->ShouldCollideWith ((fixtureA != fixturePed ? fixtureA : fixtureB)->GetFilterData ().categoryBits );
313+ CarPhysicsComponent* physicsComponentA = CastBodyData<CarPhysicsComponent>(fixtureA->GetBody ());
314+ CarPhysicsComponent* physicsComponentB = CastBodyData<CarPhysicsComponent>(fixtureB->GetBody ());
315+ hasCollision = HasCollisionCarVsCar (contact, physicsComponentA, physicsComponentB);
321316 }
322-
323- if (hasCollision && fixtureMapSolidBlock && fixturePed)
317+ }
318+ else
319+ {
320+ b2Fixture* fixtureMapSolidBlock = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_MAP_SOLID_BLOCK);
321+ b2Fixture* fixturePed = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_PED);
322+ b2Fixture* fixtureCar = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_CAR);
323+
324+ if (fixturePed)
324325 {
325- b2FixtureData_map fxdata = fixtureMapSolidBlock->GetUserData ();
326- PhysicsComponent* physicsObject = (PhysicsComponent*) fixturePed->GetBody ()->GetUserData ();
327- debug_assert (physicsObject);
326+ PedPhysicsComponent* pedPhysicsObject = CastBodyData<PedPhysicsComponent>(fixturePed->GetBody ());
327+ debug_assert (pedPhysicsObject);
328328
329- // detect height
330- float height = gGameMap .GetHeightAtPosition (physicsObject->GetPosition ());
331- hasCollision = HasCollisionPedestrianVsMap (fxdata.mX , fxdata.mZ , height);
329+ // ped vs map solid block
330+ if (fixtureMapSolidBlock)
331+ {
332+ b2FixtureData_map fxdata = fixtureMapSolidBlock->GetUserData ();
333+
334+ float height = gGameMap .GetHeightAtPosition (pedPhysicsObject->GetPosition ());
335+ hasCollision = pedPhysicsObject->ShouldCollideWith (PHYSICS_OBJCAT_MAP_SOLID_BLOCK) &&
336+ HasCollisionPedVsMap (fxdata.mX , fxdata.mZ , height);
337+ }
338+ // ped vs car
339+ else if (fixtureCar)
340+ {
341+ CarPhysicsComponent* carPhysicsObject = CastBodyData<CarPhysicsComponent>(fixtureCar->GetBody ());
342+ hasCollision = pedPhysicsObject->ShouldCollideWith (PHYSICS_OBJCAT_CAR) &&
343+ HasCollisionPedVsCar (contact, pedPhysicsObject, carPhysicsObject);
344+ }
332345 }
333-
334- if (hasCollision && fixtureMapSolidBlock && fixtureCar )
346+ // car vs map solid block
347+ else if (fixtureCar && fixtureMapSolidBlock)
335348 {
336349 b2FixtureData_map fxdata = fixtureMapSolidBlock->GetUserData ();
337350 hasCollision = HasCollisionCarVsMap (contact, fixtureCar, fxdata.mX , fxdata.mZ );
338351 }
339-
340- if (hasCollision && fixtureCar && fixturePed)
341- {
342- hasCollision = HasCollisionPedestrianVsCar (contact, fixturePed, fixtureCar);
343- }
344-
345- break ;
346352 }
347353
348354 contact->SetEnabled (hasCollision);
349355}
350356
351357void PhysicsManager::PostSolve (b2Contact* contact, const b2ContactImpulse* impulse)
352358{
359+ b2Fixture* fixtureA = contact->GetFixtureA ();
360+ b2Fixture* fixtureB = contact->GetFixtureB ();
361+
362+ // check car vs car
363+ if (fixtureA->GetFilterData ().categoryBits ==
364+ fixtureB->GetFilterData ().categoryBits )
365+ {
366+ if (fixtureA->GetFilterData ().categoryBits == PHYSICS_OBJCAT_CAR)
367+ {
368+ // todo
369+ }
370+
371+ return ;
372+ }
373+
374+ // find impulse
375+ float maxImpulse = 0 .0f ;
376+ for (int icurr = 0 ; icurr < impulse->count ; ++icurr)
377+ {
378+ maxImpulse = glm::max (maxImpulse, fabs (impulse->normalImpulses [icurr]));
379+ }
380+
381+ if (maxImpulse < 0 .01f ) // impact is too small, ignore
382+ return ;
383+
384+ b2Fixture* fixtureMapSolidBlock = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_MAP_SOLID_BLOCK);
385+ b2Fixture* fixturePed = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_PED);
386+ b2Fixture* fixtureCar = FilterFixture (fixtureA, fixtureB, PHYSICS_OBJCAT_CAR);
387+
388+ if (fixtureCar && fixturePed)
389+ {
390+ CarPhysicsComponent* physicsComponentCar = CastBodyData<CarPhysicsComponent>(fixtureCar->GetBody ());
391+ PedPhysicsComponent* physicsComponentPed = CastBodyData<PedPhysicsComponent>(fixturePed->GetBody ());
392+ HandleContactPedVsCar (contact, maxImpulse, physicsComponentPed, physicsComponentCar);
393+ }
353394}
354395
355396void PhysicsManager::FixedStepGravity ()
356397{
398+ // todo: cleanup this mess
399+
357400 // cars
358401 for (Vehicle* currCar: gGameObjectsManager .mCarsList )
359402 {
@@ -444,14 +487,24 @@ void PhysicsManager::FixedStepGravity()
444487 }
445488}
446489
447- bool PhysicsManager::CollidePedVsPed (b2Contact* contact, PedPhysicsComponent* pedA, PedPhysicsComponent* pedB)
490+ bool PhysicsManager::HasCollisionPedVsPed (b2Contact* contact, PedPhysicsComponent* pedA, PedPhysicsComponent* pedB) const
448491{
449492 // todo: temporary implementation
450493
451494 return false ;
452495}
453496
454- bool PhysicsManager::HasCollisionPedestrianVsMap (int mapx, int mapz, float height) const
497+ bool PhysicsManager::HasCollisionCarVsCar (b2Contact* contact, CarPhysicsComponent* carA, CarPhysicsComponent* carB) const
498+ {
499+ int carLayerA = (int ) (Convert::MetersToMapUnits (carA->mHeight ) + 0 .5f );
500+ int carLayerB = (int ) (Convert::MetersToMapUnits (carB->mHeight ) + 0 .5f );
501+
502+ // todo: handle slopes
503+
504+ return carLayerA == carLayerB;
505+ }
506+
507+ bool PhysicsManager::HasCollisionPedVsMap (int mapx, int mapz, float height) const
455508{
456509 int mapLayer = (int ) (Convert::MetersToMapUnits (height) + 0 .5f );
457510
@@ -463,7 +516,7 @@ bool PhysicsManager::HasCollisionPedestrianVsMap(int mapx, int mapz, float heigh
463516
464517bool PhysicsManager::HasCollisionCarVsMap (b2Contact* contact, b2Fixture* fixtureCar, int mapx, int mapz) const
465518{
466- CarPhysicsComponent* carPhysicsComponent = ( CarPhysicsComponent*) fixtureCar->GetBody ()-> GetUserData ( );
519+ CarPhysicsComponent* carPhysicsComponent = CastBodyData< CarPhysicsComponent>( fixtureCar->GetBody ());
467520 debug_assert (carPhysicsComponent);
468521
469522 int mapLayer = (int ) (Convert::MetersToMapUnits (carPhysicsComponent->mHeight ) + 0 .5f );
@@ -474,11 +527,12 @@ bool PhysicsManager::HasCollisionCarVsMap(b2Contact* contact, b2Fixture* fixture
474527 return (blockData->mGroundType == eGroundType_Building);
475528}
476529
477- bool PhysicsManager::HasCollisionPedestrianVsCar (b2Contact* contact, b2Fixture* fixturePed, b2Fixture* fixtureCar)
530+ bool PhysicsManager::HasCollisionPedVsCar (b2Contact* contact, PedPhysicsComponent* ped, CarPhysicsComponent* car) const
478531{
479- CarPhysicsComponent* carPhysicsObject = (CarPhysicsComponent*) fixtureCar->GetBody ()->GetUserData ();
480- PedPhysicsComponent* pedPhysicsObject = (PedPhysicsComponent*) fixturePed->GetBody ()->GetUserData ();
481- return true ;
532+ // check car bounds height
533+ // todo: get car height!
534+ return ((ped->mHeight >= car->mHeight ) &&
535+ (ped->mHeight <= (car->mHeight + 2 .0f )));
482536}
483537
484538bool PhysicsManager::ProcessSensorContact (b2Contact* contact, bool onBegin)
@@ -492,10 +546,12 @@ bool PhysicsManager::ProcessSensorContact(b2Contact* contact, bool onBegin)
492546 if (!(sensorA ^ sensorB))
493547 return false ;
494548
495- PedPhysicsComponent* pedPhysicsComponent = nullptr ;
496- CarPhysicsComponent* carPhysicsComponent = nullptr ;
497- if (GetContactComponents (contact, pedPhysicsComponent, carPhysicsComponent) )
549+ b2Fixture* pedFixture = FilterFixture (contact-> GetFixtureA (), contact-> GetFixtureB (), PHYSICS_OBJCAT_PED | PHYSICS_OBJCAT_PED_SENSOR) ;
550+ b2Fixture* carFixture = FilterFixture (contact-> GetFixtureA (), contact-> GetFixtureB (), PHYSICS_OBJCAT_CAR) ;
551+ if (pedFixture && carFixture )
498552 {
553+ PedPhysicsComponent* pedPhysicsComponent = CastBodyData<PedPhysicsComponent>(pedFixture->GetBody ());
554+ CarPhysicsComponent* carPhysicsComponent = CastBodyData<CarPhysicsComponent>(carFixture->GetBody ());
499555 if (onBegin)
500556 {
501557 pedPhysicsComponent->HandleCarContactBegin ();
@@ -506,48 +562,9 @@ bool PhysicsManager::ProcessSensorContact(b2Contact* contact, bool onBegin)
506562 }
507563 return true ;
508564 }
509-
510565 return false ;
511566}
512567
513- bool PhysicsManager::GetContactComponents (b2Contact* contact, PedPhysicsComponent*& pedPhysicsObject, CarPhysicsComponent*& carPhysicsObject) const
514- {
515- b2Fixture* fixtureA = contact->GetFixtureA ();
516- b2Fixture* fixtureB = contact->GetFixtureB ();
517-
518- b2Fixture* fixturePed = nullptr ;
519- b2Fixture* fixtureCar = nullptr ;
520-
521- const b2Filter& filterA = fixtureA->GetFilterData ();
522- if ((filterA.categoryBits == PHYSICS_OBJCAT_PED) || (filterA.categoryBits == PHYSICS_OBJCAT_PED_SENSOR))
523- {
524- fixturePed = fixtureA;
525- }
526- else if (filterA.categoryBits == PHYSICS_OBJCAT_CAR)
527- {
528- fixtureCar = fixtureA;
529- }
530-
531- const b2Filter& filterB = fixtureB->GetFilterData ();
532- if ((filterB.categoryBits == PHYSICS_OBJCAT_PED) || (filterB.categoryBits == PHYSICS_OBJCAT_PED_SENSOR))
533- {
534- fixturePed = fixtureB;
535- }
536- else if (filterB.categoryBits == PHYSICS_OBJCAT_CAR)
537- {
538- fixtureCar = fixtureB;
539- }
540-
541- if (fixturePed == nullptr || fixtureCar == nullptr )
542- return false ;
543-
544- carPhysicsObject = (CarPhysicsComponent*) fixtureCar->GetBody ()->GetUserData ();
545- pedPhysicsObject = (PedPhysicsComponent*) fixturePed->GetBody ()->GetUserData ();
546-
547- debug_assert (carPhysicsObject && pedPhysicsObject);
548- return true ;
549- }
550-
551568void PhysicsManager::QueryObjectsLinecast (const glm::vec2& pointA, const glm::vec2& pointB, PhysicsLinecastResult& outputResult) const
552569{
553570 outputResult.SetNull ();
@@ -570,13 +587,13 @@ void PhysicsManager::QueryObjectsLinecast(const glm::vec2& pointA, const glm::ve
570587 if (filterData.categoryBits == PHYSICS_OBJCAT_CAR)
571588 {
572589 currHit = &mOutput .mHits [mOutput .mHitsCount ++];
573- currHit->mCarComponent = ( CarPhysicsComponent*) fixture->GetBody ()-> GetUserData ( );
590+ currHit->mCarComponent = CastBodyData< CarPhysicsComponent>( fixture->GetBody ());
574591
575592 }
576593 if (filterData.categoryBits == PHYSICS_OBJCAT_PED)
577594 {
578595 currHit = &mOutput .mHits [mOutput .mHitsCount ++];
579- currHit->mPedComponent = ( PedPhysicsComponent*) fixture->GetBody ()-> GetUserData ( );
596+ currHit->mPedComponent = CastBodyData< PedPhysicsComponent>( fixture->GetBody ());
580597 }
581598 if (currHit)
582599 {
@@ -617,13 +634,13 @@ void PhysicsManager::QueryObjectsWithinBox(const glm::vec2& aaboxCenter, const g
617634 if (filterData.categoryBits == PHYSICS_OBJCAT_CAR)
618635 {
619636 PhysicsQueryElement& currElement = mOutput .mElements [mOutput .mElementsCount ++];
620- currElement.mCarComponent = ( CarPhysicsComponent*) fixture->GetBody ()-> GetUserData ( );
637+ currElement.mCarComponent = CastBodyData< CarPhysicsComponent>( fixture->GetBody ());
621638 }
622639
623640 if (filterData.categoryBits == PHYSICS_OBJCAT_PED)
624641 {
625642 PhysicsQueryElement& currElement = mOutput .mElements [mOutput .mElementsCount ++];
626- currElement.mPedComponent = ( PedPhysicsComponent*) fixture->GetBody ()-> GetUserData ( );
643+ currElement.mPedComponent = CastBodyData< PedPhysicsComponent>( fixture->GetBody ());
627644 }
628645 return true ;
629646 }
@@ -638,4 +655,9 @@ void PhysicsManager::QueryObjectsWithinBox(const glm::vec2& aaboxCenter, const g
638655 aabb.upperBound .x = (aaboxCenter.x + aabboxExtents.x );
639656 aabb.upperBound .y = (aaboxCenter.y + aabboxExtents.y );
640657 mPhysicsWorld ->QueryAABB (&query_callback, aabb);
641- }
658+ }
659+
660+ void PhysicsManager::HandleContactPedVsCar (b2Contact* contact, float impulse, PedPhysicsComponent* ped, CarPhysicsComponent* car)
661+ {
662+
663+ }
0 commit comments