mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 11:53:28 +02:00
Ragdoll cannot assume skeleton's rootIndex is 0
some Models have extra "joints" not part of the normal skeleton
This commit is contained in:
parent
f2069ba7d7
commit
f511fe2657
4 changed files with 29 additions and 23 deletions
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue