History

JointStates are owned by Rig objects. Model, FaceModel, SkeletonModel call into their Rig pointer to access JointStates.

Seth Alves committed 11 years ago

Commit ee334ff1 parent 47965bc19 files · +549 −622Browse files

Showing the changes to libraries/render-utils/src/Model.cpp (1 of 19 files). Show all

Unified · Split

libraries/render-utils/src/Model.cpp+58−363
@@ -60,7 +60,7 @@ static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<Net · 59 unmodified lines
6060 static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
6161 float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
6262
63−Model::Model(QObject* parent, RigPointer rig) :
63+Model::Model(RigPointer rig, QObject* parent) :
6464 QObject(parent),
6565 _scale(1.0f, 1.0f, 1.0f),
6666 _scaleToFit(false),
@@ -87,7 +87,7 @@ Model::Model(QObject* parent, RigPointer rig) : · 20 unmodified lines
8787 if (_viewState) {
8888 moveToThread(_viewState->getMainThread());
8989 }
90−
90+
9191 setSnapModelToRegistrationPoint(true, glm::vec3(0.5f));
9292 }
9393
@@ -252,22 +252,9 @@ QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) { · 158 unmodified lines
252252 };
253253
254254 void Model::initJointTransforms() {
255− // compute model transforms
256− int numStates = _jointStates.size();
257− for (int i = 0; i < numStates; ++i) {
258− JointState& state = _jointStates[i];
259− const FBXJoint& joint = state.getFBXJoint();
260− int parentIndex = joint.parentIndex;
261− if (parentIndex == -1) {
262− const FBXGeometry& geometry = _geometry->getFBXGeometry();
263− // NOTE: in practice geometry.offset has a non-unity scale (rather than a translation)
264− glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
265− state.initTransform(parentTransform);
266− } else {
267− const JointState& parentState = _jointStates.at(parentIndex);
268− state.initTransform(parentState.getTransform());
269− }
270− }
255+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
256+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
257+ _rig->initJointTransforms(parentTransform);
271258 }
272259
273260 void Model::init() {
@@ -396,14 +383,8 @@ void Model::init() { · 122 unmodified lines
396383 }
397384
398385 void Model::reset() {
399− if (_jointStates.isEmpty()) {
400− return;
401− }
402386 const FBXGeometry& geometry = _geometry->getFBXGeometry();
403− for (int i = 0; i < _jointStates.size(); i++) {
404− _jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f);
405− }
406−
387+ _rig->reset(geometry.joints);
407388 _meshGroupsKnown = false;
408389 _readyWhenAdded = false; // in case any of our users are using scenes
409390 invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
@@ -436,28 +417,30 @@ bool Model::updateGeometry() { · 26 unmodified lines
436417
437418 const FBXGeometry& newGeometry = geometry->getFBXGeometry();
438419 QVector<JointState> newJointStates = createJointStates(newGeometry);
439− if (! _jointStates.isEmpty()) {
420+
421+ if (! _rig->jointStatesEmpty()) {
440422 // copy the existing joint states
441423 const FBXGeometry& oldGeometry = _geometry->getFBXGeometry();
442424 for (QHash<QString, int>::const_iterator it = oldGeometry.jointIndices.constBegin();
443− it != oldGeometry.jointIndices.constEnd(); it++) {
425+ it != oldGeometry.jointIndices.constEnd(); it++) {
444426 int oldIndex = it.value() - 1;
445427 int newIndex = newGeometry.getJointIndex(it.key());
446428 if (newIndex != -1) {
447− newJointStates[newIndex].copyState(_jointStates[oldIndex]);
429+ newJointStates[newIndex].copyState(_rig->getJointState(oldIndex));
448430 }
449431 }
450− }
432+ }
433+
451434 deleteGeometry();
452435 _dilatedTextures.clear();
453436 setGeometry(geometry);
454−
437+
455438 _meshGroupsKnown = false;
456439 _readyWhenAdded = false; // in case any of our users are using scenes
457440 invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
458441 initJointStates(newJointStates);
459442 needToRebuild = true;
460− } else if (_jointStates.isEmpty()) {
443+ } else if (_rig->jointStatesEmpty()) {
461444 const FBXGeometry& fbxGeometry = geometry->getFBXGeometry();
462445 if (fbxGeometry.joints.size() > 0) {
463446 initJointStates(createJointStates(fbxGeometry));
@@ -493,22 +476,9 @@ bool Model::updateGeometry() { · 29 unmodified lines
493476
494477 // virtual
495478 void Model::initJointStates(QVector<JointState> states) {
496− _jointStates = states;
497− initJointTransforms();
498−
499− int numStates = _jointStates.size();
500− float radius = 0.0f;
501− for (int i = 0; i < numStates; ++i) {
502− float distance = glm::length(_jointStates[i].getPosition());
503− if (distance > radius) {
504− radius = distance;
505− }
506− _jointStates[i].buildConstraint();
507− }
508− for (int i = 0; i < _jointStates.size(); i++) {
509− _jointStates[i].slaveVisibleTransform();
510− }
511− _boundingRadius = radius;
479+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
480+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
481+ _boundingRadius = _rig->initJointStates(states, parentTransform);
512482 }
513483
514484 bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
@@ -1070,51 +1040,24 @@ glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { · 555 unmodified lines
10701040 return translatedPoint;
10711041 }
10721042
1073−
10741043 bool Model::getJointState(int index, glm::quat& rotation) const {
1075− if (index == -1 || index >= _jointStates.size()) {
1076− return false;
1077− }
1078− const JointState& state = _jointStates.at(index);
1079− rotation = state.getRotationInConstrainedFrame();
1080− return !state.rotationIsDefault(rotation);
1044+ return _rig->getJointStateRotation(index, rotation);
10811045 }
10821046
10831047 bool Model::getVisibleJointState(int index, glm::quat& rotation) const {
1084− if (index == -1 || index >= _jointStates.size()) {
1085− return false;
1086− }
1087− const JointState& state = _jointStates.at(index);
1088− rotation = state.getVisibleRotationInConstrainedFrame();
1089− return !state.rotationIsDefault(rotation);
1048+ return _rig->getVisibleJointState(index, rotation);
10901049 }
10911050
10921051 void Model::clearJointState(int index) {
1093− if (index != -1 && index < _jointStates.size()) {
1094− JointState& state = _jointStates[index];
1095− state.setRotationInConstrainedFrame(glm::quat(), 0.0f);
1096− }
1052+ _rig->clearJointState(index);
10971053 }
10981054
10991055 void Model::clearJointAnimationPriority(int index) {
1100− if (_rig) {
1101− _rig->clearJointAnimationPriority(index);
1102− } else {
1103− if (index != -1 && index < _jointStates.size()) {
1104− _jointStates[index]._animationPriority = 0.0f;
1105− }
1106− }
1056+ _rig->clearJointAnimationPriority(index);
11071057 }
11081058
11091059 void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) {
1110− if (index != -1 && index < _jointStates.size()) {
1111− JointState& state = _jointStates[index];
1112− if (valid) {
1113− state.setRotationInConstrainedFrame(rotation, priority);
1114− } else {
1115− state.restoreRotation(1.0f, priority);
1116− }
1117− }
1060+ _rig->setJointState(index, valid, rotation, priority);
11181061 }
11191062
11201063 int Model::getParentJointIndex(int jointIndex) const {
@@ -1189,62 +1132,31 @@ void Model::setCollisionModelURL(const QUrl& url) { · 68 unmodified lines
11891132 }
11901133
11911134 bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
1192− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1193− return false;
1194− }
1195− // position is in world-frame
1196− position = _translation + _rotation * _jointStates[jointIndex].getPosition();
1197− return true;
1135+ return _rig->getJointPositionInWorldFrame(jointIndex, position, _translation, _rotation);
11981136 }
11991137
12001138 bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
1201− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1202− return false;
1203− }
1204− // position is in model-frame
1205− position = extractTranslation(_jointStates[jointIndex].getTransform());
1206− return true;
1139+ return _rig->getJointPosition(jointIndex, position);
12071140 }
12081141
12091142 bool Model::getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
1210− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1211− return false;
1212− }
1213− rotation = _rotation * _jointStates[jointIndex].getRotation();
1214− return true;
1143+ return _rig->getJointRotationInWorldFrame(jointIndex, rotation, _rotation);
12151144 }
12161145
12171146 bool Model::getJointRotation(int jointIndex, glm::quat& rotation) const {
1218− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1219− return false;
1220− }
1221− rotation = _jointStates[jointIndex].getRotation();
1222− return true;
1147+ return _rig->getJointRotation(jointIndex, rotation);
12231148 }
12241149
12251150 bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const {
1226− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1227− return false;
1228− }
1229− rotation = _rotation * _jointStates[jointIndex].getRotation();
1230− return true;
1151+ return _rig->getJointCombinedRotation(jointIndex, rotation, _rotation);
12311152 }
12321153
12331154 bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
1234− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1235− return false;
1236− }
1237− // position is in world-frame
1238− position = _translation + _rotation * _jointStates[jointIndex].getVisiblePosition();
1239− return true;
1155+ return _rig->getVisibleJointPositionInWorldFrame(jointIndex, position, _translation, _rotation);
12401156 }
12411157
12421158 bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
1243− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
1244− return false;
1245− }
1246− rotation = _rotation * _jointStates[jointIndex].getVisibleRotation();
1247− return true;
1159+ return _rig->getVisibleJointRotationInWorldFrame(jointIndex, rotation, _rotation);
12481160 }
12491161
12501162 QStringList Model::getJointNames() const {
@@ -1438,12 +1350,14 @@ void Model::updateClusterMatrices() { · 187 unmodified lines
14381350 if (_showTrueJointTransforms) {
14391351 for (int j = 0; j < mesh.clusters.size(); j++) {
14401352 const FBXCluster& cluster = mesh.clusters.at(j);
1441− state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
1353+ state.clusterMatrices[j] =
1354+ modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
14421355 }
14431356 } else {
14441357 for (int j = 0; j < mesh.clusters.size(); j++) {
14451358 const FBXCluster& cluster = mesh.clusters.at(j);
1446− state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix;
1359+ state.clusterMatrices[j] =
1360+ modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
14471361 }
14481362 }
14491363 }
@@ -1457,16 +1371,12 @@ void Model::simulateInternal(float deltaTime) { · 7 unmodified lines
14571371 handle->simulate(deltaTime);
14581372 }
14591373
1460− for (int i = 0; i < _jointStates.size(); i++) {
1461− updateJointState(i);
1462− }
1463− for (int i = 0; i < _jointStates.size(); i++) {
1464− _jointStates[i].resetTransformChanged();
1465− }
1374+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
1375+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1376+ _rig->simulateInternal(parentTransform);
14661377
14671378 _shapesAreDirty = !_shapes.isEmpty();
14681379
1469− const FBXGeometry& geometry = _geometry->getFBXGeometry();
14701380 glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
14711381 for (int i = 0; i < _meshStates.size(); i++) {
14721382 MeshState& state = _meshStates[i];
@@ -1474,12 +1384,14 @@ void Model::simulateInternal(float deltaTime) { · 1 unmodified line
14741384 if (_showTrueJointTransforms) {
14751385 for (int j = 0; j < mesh.clusters.size(); j++) {
14761386 const FBXCluster& cluster = mesh.clusters.at(j);
1477− state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
1387+ state.clusterMatrices[j] =
1388+ modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
14781389 }
14791390 } else {
14801391 for (int j = 0; j < mesh.clusters.size(); j++) {
14811392 const FBXCluster& cluster = mesh.clusters.at(j);
1482− state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix;
1393+ state.clusterMatrices[j] =
1394+ modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
14831395 }
14841396 }
14851397 }
@@ -1492,261 +1404,42 @@ void Model::simulateInternal(float deltaTime) { · 6 unmodified lines
14921404 }
14931405
14941406 void Model::updateJointState(int index) {
1495− JointState& state = _jointStates[index];
1496− const FBXJoint& joint = state.getFBXJoint();
1497−
1498− // compute model transforms
1499− int parentIndex = joint.parentIndex;
1500− if (parentIndex == -1) {
1501− const FBXGeometry& geometry = _geometry->getFBXGeometry();
1502− glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1503− state.computeTransform(parentTransform);
1504− } else {
1505− // guard against out-of-bounds access to _jointStates
1506− if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) {
1507− const JointState& parentState = _jointStates.at(parentIndex);
1508− state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
1509− }
1510− }
1511−}
1512−
1513−void Model::updateVisibleJointStates() {
1514− if (_showTrueJointTransforms) {
1515− // no need to update visible transforms
1516− return;
1517− }
1518− for (int i = 0; i < _jointStates.size(); i++) {
1519− _jointStates[i].slaveVisibleTransform();
1520− }
1407+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
1408+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1409+ _rig->updateJointState(index, parentTransform);
15211410 }
15221411
15231412 bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation,
1524− int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
1525− if (jointIndex == -1 || _jointStates.isEmpty()) {
1526− return false;
1527− }
1413+ int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
15281414 const FBXGeometry& geometry = _geometry->getFBXGeometry();
15291415 const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
1530− if (freeLineage.isEmpty()) {
1531− return false;
1532− }
1533− if (lastFreeIndex == -1) {
1534− lastFreeIndex = freeLineage.last();
1535− }
1536−
1537− // this is a cyclic coordinate descent algorithm: see
1538− // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
1539− const int ITERATION_COUNT = 1;
1540− glm::vec3 worldAlignment = alignment;
1541− for (int i = 0; i < ITERATION_COUNT; i++) {
1542− // first, try to rotate the end effector as close as possible to the target rotation, if any
1543− glm::quat endRotation;
1544− if (useRotation) {
1545− JointState& state = _jointStates[jointIndex];
1546−
1547− state.setRotationInBindFrame(rotation, priority);
1548− endRotation = state.getRotationInBindFrame();
1549− }
1550−
1551− // then, we go from the joint upwards, rotating the end as close as possible to the target
1552− glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].getTransform());
1553− for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) {
1554− int index = freeLineage.at(j);
1555− JointState& state = _jointStates[index];
1556− const FBXJoint& joint = state.getFBXJoint();
1557− if (!(joint.isFree || allIntermediatesFree)) {
1558− continue;
1559− }
1560− glm::vec3 jointPosition = extractTranslation(state.getTransform());
1561− glm::vec3 jointVector = endPosition - jointPosition;
1562− glm::quat oldCombinedRotation = state.getRotation();
1563− glm::quat combinedDelta;
1564− float combinedWeight;
1565− if (useRotation) {
1566− combinedDelta = safeMix(rotation * glm::inverse(endRotation),
1567− rotationBetween(jointVector, position - jointPosition), 0.5f);
1568− combinedWeight = 2.0f;
1569−
1570− } else {
1571− combinedDelta = rotationBetween(jointVector, position - jointPosition);
1572− combinedWeight = 1.0f;
1573− }
1574− if (alignment != glm::vec3() && j > 1) {
1575− jointVector = endPosition - jointPosition;
1576− glm::vec3 positionSum;
1577− for (int k = j - 1; k > 0; k--) {
1578− int index = freeLineage.at(k);
1579− updateJointState(index);
1580− positionSum += extractTranslation(_jointStates.at(index).getTransform());
1581− }
1582− glm::vec3 projectedCenterOfMass = glm::cross(jointVector,
1583− glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector));
1584− glm::vec3 projectedAlignment = glm::cross(jointVector, glm::cross(worldAlignment, jointVector));
1585− const float LENGTH_EPSILON = 0.001f;
1586− if (glm::length(projectedCenterOfMass) > LENGTH_EPSILON && glm::length(projectedAlignment) > LENGTH_EPSILON) {
1587− combinedDelta = safeMix(combinedDelta, rotationBetween(projectedCenterOfMass, projectedAlignment),
1588− 1.0f / (combinedWeight + 1.0f));
1589− }
1590− }
1591− state.applyRotationDelta(combinedDelta, true, priority);
1592− glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation);
1593− endPosition = actualDelta * jointVector + jointPosition;
1594− if (useRotation) {
1595− endRotation = actualDelta * endRotation;
1596− }
1597− }
1598− }
1599−
1600− // now update the joint states from the top
1601− for (int j = freeLineage.size() - 1; j >= 0; j--) {
1602− updateJointState(freeLineage.at(j));
1416+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1417+ if (_rig->setJointPosition(jointIndex, position, rotation, useRotation,
1418+ lastFreeIndex, allIntermediatesFree, alignment, priority, freeLineage, parentTransform)) {
1419+ _shapesAreDirty = !_shapes.isEmpty();
1420+ return true;
16031421 }
1604− _shapesAreDirty = !_shapes.isEmpty();
1605−
1606− return true;
1422+ return false;
16071423 }
16081424
16091425 void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {
1610− // NOTE: targetRotation is from bind- to model-frame
1611−
1612− if (endIndex == -1 || _jointStates.isEmpty()) {
1613− return;
1614− }
1615−
16161426 const FBXGeometry& geometry = _geometry->getFBXGeometry();
16171427 const QVector<int>& freeLineage = geometry.joints.at(endIndex).freeLineage;
1618− if (freeLineage.isEmpty()) {
1619− return;
1620− }
1621− int numFree = freeLineage.size();
1622−
1623− // store and remember topmost parent transform
1624− glm::mat4 topParentTransform;
1625− {
1626− int index = freeLineage.last();
1627− const JointState& state = _jointStates.at(index);
1628− const FBXJoint& joint = state.getFBXJoint();
1629− int parentIndex = joint.parentIndex;
1630− if (parentIndex == -1) {
1631− const FBXGeometry& geometry = _geometry->getFBXGeometry();
1632− topParentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1633− } else {
1634− topParentTransform = _jointStates[parentIndex].getTransform();
1635− }
1636− }
1637−
1638− // this is a cyclic coordinate descent algorithm: see
1639− // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
1640−
1641− // keep track of the position of the end-effector
1642− JointState& endState = _jointStates[endIndex];
1643− glm::vec3 endPosition = endState.getPosition();
1644− float distanceToGo = glm::distance(targetPosition, endPosition);
1645−
1646− const int MAX_ITERATION_COUNT = 2;
1647− const float ACCEPTABLE_IK_ERROR = 0.005f; // 5mm
1648− int numIterations = 0;
1649− do {
1650− ++numIterations;
1651− // moving up, rotate each free joint to get endPosition closer to target
1652− for (int j = 1; j < numFree; j++) {
1653− int nextIndex = freeLineage.at(j);
1654− JointState& nextState = _jointStates[nextIndex];
1655− FBXJoint nextJoint = nextState.getFBXJoint();
1656− if (! nextJoint.isFree) {
1657− continue;
1658− }
1659−
1660− glm::vec3 pivot = nextState.getPosition();
1661− glm::vec3 leverArm = endPosition - pivot;
1662− float leverLength = glm::length(leverArm);
1663− if (leverLength < EPSILON) {
1664− continue;
1665− }
1666− glm::quat deltaRotation = rotationBetween(leverArm, targetPosition - pivot);
1667−
1668− // We want to mix the shortest rotation with one that will pull the system down with gravity
1669− // so that limbs don't float unrealistically. To do this we compute a simplified center of mass
1670− // where each joint has unit mass and we don't bother averaging it because we only need direction.
1671− if (j > 1) {
1672−
1673− glm::vec3 centerOfMass(0.0f);
1674− for (int k = 0; k < j; ++k) {
1675− int massIndex = freeLineage.at(k);
1676− centerOfMass += _jointStates[massIndex].getPosition() - pivot;
1677− }
1678− // the gravitational effect is a rotation that tends to align the two cross products
1679− const glm::vec3 worldAlignment = glm::vec3(0.0f, -1.0f, 0.0f);
1680− glm::quat gravityDelta = rotationBetween(glm::cross(centerOfMass, leverArm),
1681− glm::cross(worldAlignment, leverArm));
1682−
1683− float gravityAngle = glm::angle(gravityDelta);
1684− const float MIN_GRAVITY_ANGLE = 0.1f;
1685− float mixFactor = 0.5f;
1686− if (gravityAngle < MIN_GRAVITY_ANGLE) {
1687− // the final rotation is a mix of the two
1688− mixFactor = 0.5f * gravityAngle / MIN_GRAVITY_ANGLE;
1689− }
1690− deltaRotation = safeMix(deltaRotation, gravityDelta, mixFactor);
1691− }
1692−
1693− // Apply the rotation, but use mixRotationDelta() which blends a bit of the default pose
1694− // in the process. This provides stability to the IK solution for most models.
1695− glm::quat oldNextRotation = nextState.getRotation();
1696− float mixFactor = 0.03f;
1697− nextState.mixRotationDelta(deltaRotation, mixFactor, priority);
1698−
1699− // measure the result of the rotation which may have been modified by
1700− // blending and constraints
1701− glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
1702− endPosition = pivot + actualDelta * leverArm;
1703− }
1704−
1705− // recompute transforms from the top down
1706− glm::mat4 parentTransform = topParentTransform;
1707− for (int j = numFree - 1; j >= 0; --j) {
1708− JointState& freeState = _jointStates[freeLineage.at(j)];
1709− freeState.computeTransform(parentTransform);
1710− parentTransform = freeState.getTransform();
1711− }
1712−
1713− // measure our success
1714− endPosition = endState.getPosition();
1715− distanceToGo = glm::distance(targetPosition, endPosition);
1716− } while (numIterations < MAX_ITERATION_COUNT && distanceToGo < ACCEPTABLE_IK_ERROR);
1717−
1718− // set final rotation of the end joint
1719− endState.setRotationInBindFrame(targetRotation, priority, true);
1720−
1428+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
1429+ _rig->inverseKinematics(endIndex, targetPosition, targetRotation, priority, freeLineage, parentTransform);
17211430 _shapesAreDirty = !_shapes.isEmpty();
17221431 }
17231432
17241433 bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) {
1725− if (jointIndex == -1 || _jointStates.isEmpty()) {
1726− return false;
1727− }
17281434 const FBXGeometry& geometry = _geometry->getFBXGeometry();
17291435 const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
1730−
1731− foreach (int index, freeLineage) {
1732− JointState& state = _jointStates[index];
1733− state.restoreRotation(fraction, priority);
1734− }
1735− return true;
1436+ return _rig->restoreJointPosition(jointIndex, fraction, priority, freeLineage);
17361437 }
17371438
17381439 float Model::getLimbLength(int jointIndex) const {
1739− if (jointIndex == -1 || _jointStates.isEmpty()) {
1740− return 0.0f;
1741− }
17421440 const FBXGeometry& geometry = _geometry->getFBXGeometry();
17431441 const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
1744− float length = 0.0f;
1745− float lengthScale = (_scale.x + _scale.y + _scale.z) / 3.0f;
1746− for (int i = freeLineage.size() - 2; i >= 0; i--) {
1747− length += geometry.joints.at(freeLineage.at(i)).distanceToParent * lengthScale;
1748− }
1749− return length;
1442+ return _rig->getLimbLength(jointIndex, freeLineage, _scale, geometry.joints);
17501443 }
17511444
17521445 void Model::renderJointCollisionShapes(float alpha) {
@@ -1816,7 +1509,7 @@ void Model::applyNextGeometry() { · 63 unmodified lines
18161509
18171510 void Model::deleteGeometry() {
18181511 _blendedVertexBuffers.clear();
1819− _jointStates.clear();
1512+ _rig->clearJointStates();
18201513 _meshStates.clear();
18211514 clearShapes();
18221515
@@ -1945,7 +1638,9 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran · 122 unmodified lines
19451638 args, locations);
19461639
19471640 {
1948− updateVisibleJointStates();
1641+ if (!_showTrueJointTransforms) {
1642+ _rig->updateVisibleJointStates();
1643+ } // else no need to update visible transforms
19491644 }
19501645
19511646 // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown