From f511fe2657a1b9a7192ae819b3af61d6ccbf87d0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Aug 2014 11:31:50 -0700 Subject: [PATCH] Ragdoll cannot assume skeleton's rootIndex is 0 some Models have extra "joints" not part of the normal skeleton --- interface/src/avatar/SkeletonModel.cpp | 19 +++++++++---------- interface/src/avatar/SkeletonRagdoll.cpp | 12 ++++++------ libraries/shared/src/Ragdoll.cpp | 16 +++++++++------- libraries/shared/src/Ragdoll.h | 5 +++++ 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f9a73f2431..dd398f2b2b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -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& 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. diff --git a/interface/src/avatar/SkeletonRagdoll.cpp b/interface/src/avatar/SkeletonRagdoll.cpp index 6318323990..7c0e056826 100644 --- a/interface/src/avatar/SkeletonRagdoll.cpp +++ b/interface/src/avatar/SkeletonRagdoll.cpp @@ -36,8 +36,9 @@ void SkeletonRagdoll::stepForward(float deltaTime) { void SkeletonRagdoll::slamPointPositions() { QVector& 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& 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 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) { diff --git a/libraries/shared/src/Ragdoll.cpp b/libraries/shared/src/Ragdoll.cpp index 70ea63930b..c0f0eb4b27 100644 --- a/libraries/shared/src/Ragdoll.cpp +++ b/libraries/shared/src/Ragdoll.cpp @@ -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; diff --git a/libraries/shared/src/Ragdoll.h b/libraries/shared/src/Ragdoll.h index 1ffbdb29ab..5234397833 100644 --- a/libraries/shared/src/Ragdoll.h +++ b/libraries/shared/src/Ragdoll.h @@ -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 _points; QVector _boneConstraints;