diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index ffe711b03b..536f957143 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -14,14 +14,11 @@ #include #include -#include -#include #include "Application.h" #include "Avatar.h" #include "Hand.h" #include "Menu.h" -#include "MuscleConstraint.h" #include "SkeletonModel.h" #include "SkeletonRagdoll.h" @@ -606,6 +603,7 @@ void SkeletonModel::buildShapes() { float uniformScale = extractUniformScale(_scale); const int numStates = _jointStates.size(); + float totalMass = 0.0f; for (int i = 0; i < numStates; i++) { JointState& state = _jointStates[i]; const FBXJoint& joint = state.getFBXJoint(); @@ -624,26 +622,31 @@ void SkeletonModel::buildShapes() { if (type == Shape::SPHERE_SHAPE) { shape = new VerletSphereShape(radius, &(points[i])); shape->setEntity(this); - points[i].setMass(massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume())); + float mass = massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume()); + points[i].setMass(mass); + totalMass += mass; } else if (type == Shape::CAPSULE_SHAPE) { assert(parentIndex != -1); shape = new VerletCapsuleShape(radius, &(points[parentIndex]), &(points[i])); shape->setEntity(this); - points[i].setMass(massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume())); + float mass = massScale * glm::max(MIN_JOINT_MASS, DENSITY_OF_WATER * shape->getVolume()); + points[i].setMass(mass); + totalMass += mass; } if (parentIndex != -1) { // always disable collisions between joint and its parent if (shape) { disableCollisions(i, parentIndex); } - } else { - // give the base joint a very large mass since it doesn't actually move - // in the local-frame simulation (it defines the origin) - points[i].setMass(VERY_BIG_MASS); - } + } _shapes.push_back(shape); } + // set the mass of the root + if (numStates > 0) { + points[0].setMass(totalMass); + } + // This method moves the shapes to their default positions in Model frame. computeBoundingShape(geometry); diff --git a/interface/src/avatar/SkeletonRagdoll.cpp b/interface/src/avatar/SkeletonRagdoll.cpp index 503f38f00f..6318323990 100644 --- a/interface/src/avatar/SkeletonRagdoll.cpp +++ b/interface/src/avatar/SkeletonRagdoll.cpp @@ -70,10 +70,7 @@ void SkeletonRagdoll::buildConstraints() { for (int i = 0; i < numPoints; ++i) { const JointState& state = jointStates.at(i); int parentIndex = state.getParentIndex(); - if (parentIndex == -1) { - FixedConstraint* anchor = new FixedConstraint(&_translationInSimulationFrame, &(_points[i])); - _fixedConstraints.push_back(anchor); - } else { + if (parentIndex != -1) { DistanceConstraint* bone = new DistanceConstraint(&(_points[i]), &(_points[parentIndex])); bone->setDistance(state.getDistanceToParent()); _boneConstraints.push_back(bone); diff --git a/libraries/shared/src/PhysicsSimulation.cpp b/libraries/shared/src/PhysicsSimulation.cpp index a62b3816af..6c4901bcd5 100644 --- a/libraries/shared/src/PhysicsSimulation.cpp +++ b/libraries/shared/src/PhysicsSimulation.cpp @@ -163,10 +163,10 @@ bool PhysicsSimulation::addRagdoll(Ragdoll* doll) { } void PhysicsSimulation::removeRagdoll(Ragdoll* doll) { - int numDolls = _otherRagdolls.size(); - if (doll->_simulation != this) { + if (!doll || doll->_simulation != this) { return; } + int numDolls = _otherRagdolls.size(); for (int i = 0; i < numDolls; ++i) { if (doll == _otherRagdolls[i]) { if (i == numDolls - 1) { @@ -205,10 +205,11 @@ void PhysicsSimulation::stepForward(float deltaTime, float minError, int maxIter } } + bool collidedWithOtherRagdoll = false; int iterations = 0; float error = 0.0f; do { - computeCollisions(); + collidedWithOtherRagdoll = computeCollisions() || collidedWithOtherRagdoll; updateContacts(); resolveCollisions(); @@ -225,6 +226,14 @@ void PhysicsSimulation::stepForward(float deltaTime, float minError, int maxIter now = usecTimestampNow(); } while (_collisions.size() != 0 && (iterations < maxIterations) && (error > minError) && (now < expiry)); + // the collisions may have moved the main ragdoll from the simulation center + // so we remove this offset (potentially storing it as movement of the Ragdoll owner) + _ragdoll->removeRootOffset(collidedWithOtherRagdoll); + + // also remove any offsets from the other ragdolls + for (int i = 0; i < numDolls; ++i) { + _otherRagdolls[i]->removeRootOffset(false); + } pruneContacts(); } @@ -237,7 +246,7 @@ void PhysicsSimulation::moveRagdolls(float deltaTime) { } } -void PhysicsSimulation::computeCollisions() { +bool PhysicsSimulation::computeCollisions() { PerformanceTimer perfTimer("collide"); _collisions.clear(); @@ -258,11 +267,13 @@ void PhysicsSimulation::computeCollisions() { } // collide main ragdoll with others + bool otherCollisions = false; int numEntities = _otherEntities.size(); for (int i = 0; i < numEntities; ++i) { const QVector otherShapes = _otherEntities.at(i)->getShapes(); - ShapeCollider::collideShapesWithShapes(shapes, otherShapes, _collisions); + otherCollisions = ShapeCollider::collideShapesWithShapes(shapes, otherShapes, _collisions) || otherCollisions; } + return otherCollisions; } void PhysicsSimulation::resolveCollisions() { diff --git a/libraries/shared/src/PhysicsSimulation.h b/libraries/shared/src/PhysicsSimulation.h index 881007208b..1db56a46e2 100644 --- a/libraries/shared/src/PhysicsSimulation.h +++ b/libraries/shared/src/PhysicsSimulation.h @@ -53,9 +53,11 @@ public: protected: void moveRagdolls(float deltaTime); - void computeCollisions(); - void resolveCollisions(); + /// \return true if main ragdoll collides with other avatar + bool computeCollisions(); + + void resolveCollisions(); void enforceContacts(); void applyContactFriction(); void updateContacts();