Ragdoll cannot assume skeleton's rootIndex is 0

some Models have extra "joints" not part of the normal skeleton
This commit is contained in:
Andrew Meadows 2014-08-19 11:31:50 -07:00
parent f2069ba7d7
commit f511fe2657
4 changed files with 29 additions and 23 deletions

View file

@ -576,6 +576,7 @@ SkeletonRagdoll* SkeletonModel::buildRagdoll() {
if (!_ragdoll) {
_ragdoll = new SkeletonRagdoll(this);
if (_enableShapes) {
clearShapes();
buildShapes();
}
}
@ -600,6 +601,7 @@ void SkeletonModel::buildShapes() {
if (!_ragdoll) {
_ragdoll = new SkeletonRagdoll(this);
}
_ragdoll->setRootIndex(geometry.rootJointIndex);
_ragdoll->initPoints();
QVector<VerletPoint>& points = _ragdoll->getPoints();
@ -614,15 +616,14 @@ void SkeletonModel::buildShapes() {
float radius = uniformScale * joint.boneRadius;
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
Shape::Type type = joint.shapeType;
if (i == 0 || (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON)) {
int parentIndex = joint.parentIndex;
if (parentIndex == -1 || radius < EPSILON) {
type = Shape::UNKNOWN_SHAPE;
} else if (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON) {
// this shape is forced to be a sphere
type = Shape::SPHERE_SHAPE;
}
if (radius < EPSILON) {
type = Shape::UNKNOWN_SHAPE;
}
Shape* shape = NULL;
int parentIndex = joint.parentIndex;
if (type == Shape::SPHERE_SHAPE) {
shape = new VerletSphereShape(radius, &(points[i]));
shape->setEntity(this);
@ -637,18 +638,16 @@ void SkeletonModel::buildShapes() {
points[i].setMass(mass);
totalMass += mass;
}
if (parentIndex != -1) {
if (shape && parentIndex != -1) {
// always disable collisions between joint and its parent
if (shape) {
disableCollisions(i, parentIndex);
}
disableCollisions(i, parentIndex);
}
_shapes.push_back(shape);
}
// set the mass of the root
if (numStates > 0) {
points[0].setMass(totalMass);
points[_ragdoll->getRootIndex()].setMass(totalMass);
}
// This method moves the shapes to their default positions in Model frame.

View file

@ -36,8 +36,9 @@ void SkeletonRagdoll::stepForward(float deltaTime) {
void SkeletonRagdoll::slamPointPositions() {
QVector<JointState>& jointStates = _model->getJointStates();
int numStates = jointStates.size();
for (int i = 0; i < numStates; ++i) {
const int numPoints = _points.size();
assert(numPoints == jointStates.size());
for (int i = _rootIndex; i < numPoints; ++i) {
_points[i].initPosition(jointStates.at(i).getPosition());
}
}
@ -49,8 +50,7 @@ void SkeletonRagdoll::initPoints() {
initTransform();
// one point for each joint
QVector<JointState>& jointStates = _model->getJointStates();
int numStates = jointStates.size();
int numStates = _model->getJointStates().size();
_points.fill(VerletPoint(), numStates);
slamPointPositions();
}
@ -67,7 +67,7 @@ void SkeletonRagdoll::buildConstraints() {
float minBone = FLT_MAX;
float maxBone = -FLT_MAX;
QMultiMap<int, int> families;
for (int i = 0; i < numPoints; ++i) {
for (int i = _rootIndex; i < numPoints; ++i) {
const JointState& state = jointStates.at(i);
int parentIndex = state.getParentIndex();
if (parentIndex != -1) {
@ -105,7 +105,7 @@ void SkeletonRagdoll::buildConstraints() {
float MAX_STRENGTH = 0.6f;
float MIN_STRENGTH = 0.05f;
// each joint gets a MuscleConstraint to its parent
for (int i = 1; i < numPoints; ++i) {
for (int i = _rootIndex + 1; i < numPoints; ++i) {
const JointState& state = jointStates.at(i);
int p = state.getParentIndex();
if (p == -1) {

View file

@ -20,7 +20,7 @@
#include "SharedUtil.h" // for EPSILON
Ragdoll::Ragdoll() : _massScale(1.0f), _translation(0.0f), _translationInSimulationFrame(0.0f),
_accumulatedMovement(0.0f), _simulation(NULL) {
_rootIndex(0), _accumulatedMovement(0.0f), _simulation(NULL) {
}
Ragdoll::~Ragdoll() {
@ -35,7 +35,7 @@ void Ragdoll::stepForward(float deltaTime) {
updateSimulationTransforms(_translation - _simulation->getTranslation(), _rotation);
}
int numPoints = _points.size();
for (int i = 0; i < numPoints; ++i) {
for (int i = _rootIndex; i < numPoints; ++i) {
_points[i].integrateForward();
}
}
@ -77,7 +77,9 @@ void Ragdoll::initTransform() {
}
void Ragdoll::setTransform(const glm::vec3& translation, const glm::quat& rotation) {
_translation = translation;
if (translation != _translation) {
_translation = translation;
}
_rotation = rotation;
}
@ -95,7 +97,7 @@ void Ragdoll::updateSimulationTransforms(const glm::vec3& translation, const glm
// apply the deltas to all ragdollPoints
int numPoints = _points.size();
for (int i = 0; i < numPoints; ++i) {
for (int i = _rootIndex; i < numPoints; ++i) {
_points[i].move(deltaPosition, deltaRotation, _translationInSimulationFrame);
}
@ -111,7 +113,7 @@ void Ragdoll::setMassScale(float scale) {
if (scale != _massScale) {
float rescale = scale / _massScale;
int numPoints = _points.size();
for (int i = 0; i < numPoints; ++i) {
for (int i = _rootIndex; i < numPoints; ++i) {
_points[i].setMass(rescale * _points[i].getMass());
}
_massScale = scale;
@ -122,10 +124,10 @@ void Ragdoll::removeRootOffset(bool accumulateMovement) {
const int numPoints = _points.size();
if (numPoints > 0) {
// shift all points so that the root aligns with the the ragdoll's position in the simulation
glm::vec3 offset = _translationInSimulationFrame - _points[0]._position;
glm::vec3 offset = _translationInSimulationFrame - _points[_rootIndex]._position;
float offsetLength = glm::length(offset);
if (offsetLength > EPSILON) {
for (int i = 0; i < numPoints; ++i) {
for (int i = _rootIndex; i < numPoints; ++i) {
_points[i].shift(offset);
}
const float MIN_ROOT_OFFSET = 0.02f;

View file

@ -52,6 +52,10 @@ public:
void setMassScale(float scale);
float getMassScale() const { return _massScale; }
// the ragdoll's rootIndex (within a Model's joints) is not always zero so must be settable
void setRootIndex(int index) { _rootIndex = index; }
int getRootIndex() const { return _rootIndex; }
void clearConstraintsAndPoints();
virtual void initPoints() = 0;
virtual void buildConstraints() = 0;
@ -66,6 +70,7 @@ protected:
glm::quat _rotation; // world-frame
glm::vec3 _translationInSimulationFrame;
glm::quat _rotationInSimulationFrame;
int _rootIndex;
QVector<VerletPoint> _points;
QVector<DistanceConstraint*> _boneConstraints;