void AvatarManager::rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, OtherAvatarPointer avatar) { if (!avatar->_motionState) { avatar->_motionState = new AvatarMotionState(avatar, nullptr); } AvatarMotionState* motionState = avatar->_motionState; ShapeInfo shapeInfo; avatar->computeShapeInfo(shapeInfo); const btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); assert(shape); motionState->setShape(shape); motionState->setMass(avatar->computeMass()); if (motionState->getRigidBody()) { transaction.objectsToReinsert.push_back(motionState); } else { transaction.objectsToAdd.push_back(motionState); } motionState->clearIncomingDirtyFlags(); // Rather than reconcile numbers of joints after change to model or LOD // we blow away old detailedMotionStates and create anew all around. // delete old detailedMotionStates auto& detailedMotionStates = avatar->getDetailedMotionStates(); if (detailedMotionStates.size() != 0) { for (auto& detailedMotionState : detailedMotionStates) { transaction.objectsToRemove.push_back(detailedMotionState); } avatar->resetDetailedMotionStates(); } // build new detailedMotionStates OtherAvatar::BodyLOD lod = avatar->getBodyLOD(); if (lod == OtherAvatar::BodyLOD::Sphere) { auto dMotionState = createDetailedMotionState(avatar, -1); if (dMotionState) { detailedMotionStates.push_back(dMotionState); transaction.objectsToAdd.push_back(dMotionState); } } else { int32_t numJoints = avatar->getJointCount(); for (int32_t i = 0; i < numJoints; i++) { auto dMotionState = createDetailedMotionState(avatar, i); if (dMotionState) { detailedMotionStates.push_back(dMotionState); transaction.objectsToAdd.push_back(dMotionState); } } } avatar->_needsReinsertion = false; }
void AvatarManager::buildPhysicsTransaction(PhysicsEngine::Transaction& transaction) { _myAvatar->getCharacterController()->buildPhysicsTransaction(transaction); for (auto avatar : _otherAvatarsToChangeInPhysics) { bool isInPhysics = avatar->isInPhysicsSimulation(); if (isInPhysics != avatar->shouldBeInPhysicsSimulation()) { if (isInPhysics) { transaction.objectsToRemove.push_back(avatar->_motionState); avatar->_motionState = nullptr; auto& detailedMotionStates = avatar->getDetailedMotionStates(); for (auto& motionState : detailedMotionStates) { transaction.objectsToRemove.push_back(motionState); } avatar->resetDetailedMotionStates(); } else { rebuildAvatarPhysics(transaction, avatar); } } else if (isInPhysics) { AvatarMotionState* motionState = avatar->_motionState; uint32_t flags = motionState->getIncomingDirtyFlags(); if (flags & EASY_DIRTY_PHYSICS_FLAGS) { motionState->handleEasyChanges(flags); } // NOTE: we don't call detailedMotionState->handleEasyChanges() here because they are KINEMATIC // and Bullet will automagically call DetailedMotionState::getWorldTransform() on all that are active. if (motionState->needsNewShape()) { rebuildAvatarPhysics(transaction, avatar); } else { if (flags & (Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_COLLISION_GROUP)) { transaction.objectsToReinsert.push_back(motionState); } motionState->clearIncomingDirtyFlags(); } } } }