compute and store Ragdoll::_accumulatedMovement

This commit is contained in:
Andrew Meadows 2014-08-18 12:53:04 -07:00
parent 3e2095332f
commit 7e7978de1a
4 changed files with 34 additions and 21 deletions

View file

@ -14,14 +14,11 @@
#include <VerletCapsuleShape.h>
#include <VerletSphereShape.h>
#include <DistanceConstraint.h>
#include <FixedConstraint.h>
#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);

View file

@ -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);

View file

@ -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<Shape*> otherShapes = _otherEntities.at(i)->getShapes();
ShapeCollider::collideShapesWithShapes(shapes, otherShapes, _collisions);
otherCollisions = ShapeCollider::collideShapesWithShapes(shapes, otherShapes, _collisions) || otherCollisions;
}
return otherCollisions;
}
void PhysicsSimulation::resolveCollisions() {

View file

@ -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();