void PhysicsEngine::stepSimulation() { CProfileManager::Reset(); BT_PROFILE("stepSimulation"); // NOTE: the grand order of operations is: // (1) pull incoming changes // (2) step simulation // (3) synchronize outgoing motion states // (4) send outgoing packets const float MAX_TIMESTEP = (float)PHYSICS_ENGINE_MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP; float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds()); _clock.reset(); float timeStep = btMin(dt, MAX_TIMESTEP); if (_myAvatarController) { BT_PROFILE("avatarController"); // TODO: move this stuff outside and in front of stepSimulation, because // the updateShapeIfNecessary() call needs info from MyAvatar and should // be done on the main thread during the pre-simulation stuff if (_myAvatarController->needsRemoval()) { _myAvatarController->setDynamicsWorld(nullptr); // We must remove any existing contacts for the avatar so that any new contacts will have // valid data. MyAvatar's RigidBody is the ONLY one in the simulation that does not yet // have a MotionState so we pass nullptr to removeContacts(). removeContacts(nullptr); } _myAvatarController->updateShapeIfNecessary(); if (_myAvatarController->needsAddition()) { _myAvatarController->setDynamicsWorld(_dynamicsWorld); } _myAvatarController->preSimulation(); } auto onSubStep = [this]() { updateContactMap(); }; int numSubsteps = _dynamicsWorld->stepSimulationWithSubstepCallback(timeStep, PHYSICS_ENGINE_MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP, onSubStep); if (numSubsteps > 0) { BT_PROFILE("postSimulation"); _numSubsteps += (uint32_t)numSubsteps; ObjectMotionState::setWorldSimulationStep(_numSubsteps); if (_myAvatarController) { _myAvatarController->postSimulation(); } _hasOutgoingChanges = true; } }
void PhysicsEngine::stepSimulation() { CProfileManager::Reset(); BT_PROFILE("stepSimulation"); // NOTE: the grand order of operations is: // (1) pull incoming changes // (2) step simulation // (3) synchronize outgoing motion states // (4) send outgoing packets const float MAX_TIMESTEP = (float)PHYSICS_ENGINE_MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP; float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds()); _clock.reset(); float timeStep = btMin(dt, MAX_TIMESTEP); // TODO: move character->preSimulation() into relayIncomingChanges if (_characterController) { if (_characterController->needsRemoval()) { _characterController->setDynamicsWorld(nullptr); } _characterController->updateShapeIfNecessary(); if (_characterController->needsAddition()) { _characterController->setDynamicsWorld(_dynamicsWorld); } _characterController->preSimulation(timeStep); } int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, PHYSICS_ENGINE_MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP); if (numSubsteps > 0) { BT_PROFILE("postSimulation"); _numSubsteps += (uint32_t)numSubsteps; ObjectMotionState::setWorldSimulationStep(_numSubsteps); if (_characterController) { _characterController->postSimulation(); } updateContactMap(); _hasOutgoingChanges = true; } }