// main void PhysicsWorld::Step(float dt, unsigned char velocityIterations, unsigned char positionIterations) { const TimeStep timeStep(dt, velocityIterations, positionIterations, mParams, mStats); Stopwatch timer; mStats.Clear(); // update rigid bodies const float linearDampFactor = 1.0f - Clamp(mParams.linearDamping * timeStep.dt, 0.0f, 1.0f); const float angularDampFactor = 1.0f - Clamp(mParams.angularDamping * timeStep.dt, 0.0f, 1.0f); timer.Start(); for (auto &body : mRigidBodies) { // TODOKai mass if (!body.CollidersValid()) body.ValidateColliders(); // update body.UpdateMassAndLocalCentroid(); body.UpdateOrientation(); body.UpdatePositionFromGlobalCentroid(); body.UpdateGlobalInverseInertiaTensor(); body.UpdateProxies(); timeStep.stats.colliders += body.mColliders.size(); } timeStep.stats.rigidBodies = mRigidBodies.size(); timeStep.stats.integration += timer.Stop(); // broadphase timer.Start(); auto &pairList = mBroadphase->ComputePairs(); timeStep.stats.broadphasePairs = pairList.size(); timeStep.stats.broadphase += timer.Stop(); // narrowphase timer.Start(); mContactManager.PreNarrowphase(); for (ColliderPair &pair : pairList) { Collider *colliderA = pair.mCollider1; Collider *colliderB = pair.mCollider2; RigidBody &bodyA = *colliderA->mParent; RigidBody &bodyB = *colliderB->mParent; CPhysics* cphyA = bodyA.mParent->cphy; CPhysics* cphyB = bodyB.mParent->cphy; if (!bodyA.CanCollide(bodyB) || !colliderA->CanBeCollide(*colliderB)) continue; // collision table check if (!cphyA->gameObject->GetState()->GetCollisionTable()->GetDoesIDsCollide(cphyA->GetCOllisionID(), cphyB->GetCOllisionID())) continue; // make sure colliderA is always less than colliderB in memory address for consistency if (colliderA > colliderB) { std::swap(colliderA, colliderB); auto temp = cphyA; cphyA = cphyB; cphyB = temp; } ContactManifold *manifold = new (mManifoldAllocator.Allocate()) ContactManifold(); manifold->colliderA = colliderA; manifold->colliderB = colliderB; //TODO manifold->isColliding = Collide(*manifold, *colliderA->mGeometry, *colliderB->mGeometry, mContactAllocator); if (!manifold->isColliding || !mContactManager.Add(*manifold, mParams.contactPersistenceThreshold * mParams.contactPersistenceThreshold)) { // manifold not colliding OR persistent manifold already exists, delete manifold->~ContactManifold(); mManifoldAllocator.Free(manifold); } else { //these will be deleted by the script subsystem CollisionData* dataA = new CollisionData(); CollisionData* dataB = new CollisionData(); // send manifold to OnCollide function { dataA->isA = true; dataA->collidedObj = cphyB->gameObject; dataA->selfCPhy = cphyA; dataA->collidedObjCPhy = cphyB; dataA->numContacts = manifold->numContacts; for (int i = 0; i < dataA->numContacts; ++i) { dataA->normals.push_back(manifold->contacts[i]->normal); } ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyA->gameObject, "OnCollisionEnter", dataA); } { dataB->isA = false; dataB->collidedObj = cphyA->gameObject; dataB->selfCPhy = cphyB; dataB->collidedObjCPhy = cphyA; dataB->numContacts = manifold->numContacts; for (int i = 0; i < dataB->numContacts; ++i) { dataB->normals.push_back(manifold->contacts[i]->normal); } ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyB->gameObject, "OnCollisionEnter", dataB); } if (cphyA->mIsTriggered || cphyB->mIsTriggered) { manifold->~ContactManifold(); mManifoldAllocator.Free(manifold); } } } mContactManager.PostNarrowphase(); timeStep.stats.narrowphase += timer.Stop(); SimulateIslands(timeStep); // update broadphase after position integration mBroadphase->Update(timeStep); mContactManager.Draw(); }