History

Merge branch 'master' into plugins

Bradley Austin Davis committed 11 years ago

Commit 7e60aee2 parents d415ee1 9215ea8181 files · +5728 −48029Browse files

Showing the changes to interface/src/avatar/SkeletonModel.cpp (1 of 181 files). Show all

Unified · Split

interface/src/avatar/SkeletonModel.cpp+97−369
@@ -12,9 +12,7 @@ · 11 unmodified lines
1212 #include <glm/gtx/transform.hpp>
1313 #include <QMultiMap>
1414
15−#include <CapsuleShape.h>
1615 #include <DeferredLightingEffect.h>
17−#include <SphereShape.h>
1816
1917 #include "Application.h"
2018 #include "Avatar.h"
@@ -24,29 +22,47 @@ · 3 unmodified lines
2422 #include "Util.h"
2523 #include "InterfaceLogging.h"
2624
27−SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
28− Model(parent),
25+SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
26+ Model(rig, parent),
2927 _triangleFanID(DependencyManager::get<GeometryCache>()->allocateID()),
3028 _owningAvatar(owningAvatar),
31− _boundingShape(),
32− _boundingShapeLocalOffset(0.0f),
29+ _boundingCapsuleLocalOffset(0.0f),
30+ _boundingCapsuleRadius(0.0f),
31+ _boundingCapsuleHeight(0.0f),
3332 _defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)),
34− _headClipDistance(DEFAULT_NEAR_CLIP),
35− _isFirstPerson(false)
33+ _headClipDistance(DEFAULT_NEAR_CLIP)
3634 {
35+ assert(_rig);
3736 assert(_owningAvatar);
38− _enableShapes = true;
3937 }
4038
4139 SkeletonModel::~SkeletonModel() {
4240 }
4341
4442 void SkeletonModel::initJointStates(QVector<JointState> states) {
45− Model::initJointStates(states);
43+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
44+ glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
45+
46+ int rootJointIndex = geometry.rootJointIndex;
47+ int leftHandJointIndex = geometry.leftHandJointIndex;
48+ int leftElbowJointIndex = leftHandJointIndex >= 0 ? geometry.joints.at(leftHandJointIndex).parentIndex : -1;
49+ int leftShoulderJointIndex = leftElbowJointIndex >= 0 ? geometry.joints.at(leftElbowJointIndex).parentIndex : -1;
50+ int rightHandJointIndex = geometry.rightHandJointIndex;
51+ int rightElbowJointIndex = rightHandJointIndex >= 0 ? geometry.joints.at(rightHandJointIndex).parentIndex : -1;
52+ int rightShoulderJointIndex = rightElbowJointIndex >= 0 ? geometry.joints.at(rightElbowJointIndex).parentIndex : -1;
53+
54+ _boundingRadius = _rig->initJointStates(states, parentTransform,
55+ rootJointIndex,
56+ leftHandJointIndex,
57+ leftElbowJointIndex,
58+ leftShoulderJointIndex,
59+ rightHandJointIndex,
60+ rightElbowJointIndex,
61+ rightShoulderJointIndex);
4662
4763 // Determine the default eye position for avatar scale = 1.0
4864 int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
49− if (0 <= headJointIndex && headJointIndex < _jointStates.size()) {
65+ if (0 <= headJointIndex && headJointIndex < _rig->getJointStateCount()) {
5066
5167 glm::vec3 leftEyePosition, rightEyePosition;
5268 getEyeModelPositions(leftEyePosition, rightEyePosition);
@@ -66,14 +82,11 @@ void SkeletonModel::initJointStates(QVector<JointState> states) { · 13 unmodified lines
6682 // the SkeletonModel override of updateJointState() will clear the translation part
6783 // of its root joint and we need that done before we try to build shapes hence we
6884 // recompute all joint transforms at this time.
69− for (int i = 0; i < _jointStates.size(); i++) {
70− updateJointState(i);
85+ for (int i = 0; i < _rig->getJointStateCount(); i++) {
86+ _rig->updateJointState(i, parentTransform);
7187 }
7288
73− clearShapes();
74− if (_enableShapes) {
75− buildShapes();
76− }
89+ buildShapes();
7790
7891 Extents meshExtents = getMeshExtents();
7992 _headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z);
@@ -84,7 +97,31 @@ void SkeletonModel::initJointStates(QVector<JointState> states) { · 4 unmodified lines
8497 }
8598
8699 const float PALM_PRIORITY = DEFAULT_PRIORITY;
87−const float LEAN_PRIORITY = DEFAULT_PRIORITY;
100+
101+void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
102+ if (_owningAvatar->isMyAvatar()) {
103+ _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation());
104+ }
105+ Model::updateRig(deltaTime, parentTransform);
106+ if (_owningAvatar->isMyAvatar()) {
107+ const FBXGeometry& geometry = _geometry->getFBXGeometry();
108+
109+ Rig::HeadParameters params;
110+ params.leanSideways = _owningAvatar->getHead()->getFinalLeanSideways();
111+ params.leanForward = _owningAvatar->getHead()->getFinalLeanSideways();
112+ params.torsoTwist = _owningAvatar->getHead()->getTorsoTwist();
113+ params.localHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInLocalFrame();
114+ params.worldHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInWorldFrame();
115+ params.eyeLookAt = _owningAvatar->getHead()->getCorrectedLookAtPosition();
116+ params.eyeSaccade = _owningAvatar->getHead()->getSaccade();
117+ params.leanJointIndex = geometry.leanJointIndex;
118+ params.neckJointIndex = geometry.neckJointIndex;
119+ params.leftEyeJointIndex = geometry.leftEyeJointIndex;
120+ params.rightEyeJointIndex = geometry.rightEyeJointIndex;
121+
122+ _rig->updateFromHeadParameters(params);
123+ }
124+}
88125
89126 void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
90127 setTranslation(_owningAvatar->getSkeletonPosition());
@@ -141,49 +178,6 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { · 50 unmodified lines
141178 restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
142179 }
143180 }
144−
145− if (_isFirstPerson) {
146− cauterizeHead();
147− updateClusterMatrices();
148− }
149−
150− _boundingShape.setTranslation(_translation + _rotation * _boundingShapeLocalOffset);
151− _boundingShape.setRotation(_rotation);
152−}
153−
154−void SkeletonModel::getHandShapes(int jointIndex, QVector<const Shape*>& shapes) const {
155− if (jointIndex < 0 || jointIndex >= int(_shapes.size())) {
156− return;
157− }
158− if (jointIndex == getLeftHandJointIndex()
159− || jointIndex == getRightHandJointIndex()) {
160− // get all shapes that have this hand as an ancestor in the skeleton heirarchy
161− const FBXGeometry& geometry = _geometry->getFBXGeometry();
162− for (int i = 0; i < _jointStates.size(); i++) {
163− const FBXJoint& joint = geometry.joints[i];
164− int parentIndex = joint.parentIndex;
165− Shape* shape = _shapes[i];
166− if (i == jointIndex) {
167− // this shape is the hand
168− if (shape) {
169− shapes.push_back(shape);
170− }
171− if (parentIndex != -1 && _shapes[parentIndex]) {
172− // also add the forearm
173− shapes.push_back(_shapes[parentIndex]);
174− }
175− } else if (shape) {
176− while (parentIndex != -1) {
177− if (parentIndex == jointIndex) {
178− // this shape is a child of the hand
179− shapes.push_back(shape);
180− break;
181− }
182− parentIndex = geometry.joints[parentIndex].parentIndex;
183− }
184− }
185− }
186− }
187181 }
188182
189183 void SkeletonModel::renderIKConstraints(gpu::Batch& batch) {
@@ -202,7 +196,7 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) { · 12 unmodified lines
202196 }
203197
204198 void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) {
205− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
199+ if (jointIndex == -1 || jointIndex >= _rig->getJointStateCount()) {
206200 return;
207201 }
208202 // NOTE: 'position' is in model-frame
@@ -217,16 +211,20 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) · 8 unmodified lines
217211 if (forearmLength < EPSILON) {
218212 return;
219213 }
220− JointState& state = _jointStates[jointIndex];
221− glm::quat handRotation = state.getRotation();
214+ glm::quat handRotation;
215+ if (!_rig->getJointStateRotation(jointIndex, handRotation)) {
216+ return;
217+ }
222218
223219 // align hand with forearm
224220 float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
225− state.applyRotationDelta(rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), true, PALM_PRIORITY);
221+ _rig->applyJointRotationDelta(jointIndex,
222+ rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector),
223+ true, PALM_PRIORITY);
226224 }
227225
228226 void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
229− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
227+ if (jointIndex == -1 || jointIndex >= _rig->getJointStateCount()) {
230228 return;
231229 }
232230 const FBXGeometry& geometry = _geometry->getFBXGeometry();
@@ -246,85 +244,36 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { · 13 unmodified lines
246244 palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), fingerDirection) * palmRotation;
247245
248246 if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
249− setHandPosition(jointIndex, palmPosition, palmRotation);
247+ _rig->setHandPosition(jointIndex, palmPosition, palmRotation, extractUniformScale(_scale), PALM_PRIORITY);
250248 } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
251249 float forearmLength = geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale);
252250 glm::vec3 forearm = palmRotation * glm::vec3(sign * forearmLength, 0.0f, 0.0f);
253251 setJointPosition(parentJointIndex, palmPosition + forearm,
254252 glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
255− JointState& parentState = _jointStates[parentJointIndex];
256− parentState.setRotationInBindFrame(palmRotation, PALM_PRIORITY);
253+ _rig->setJointRotationInBindFrame(parentJointIndex, palmRotation, PALM_PRIORITY);
257254 // lock hand to forearm by slamming its rotation (in parent-frame) to identity
258− _jointStates[jointIndex].setRotationInConstrainedFrame(glm::quat(), PALM_PRIORITY);
255+ _rig->setJointRotationInConstrainedFrame(jointIndex, glm::quat(), PALM_PRIORITY);
259256 } else {
260257 inverseKinematics(jointIndex, palmPosition, palmRotation, PALM_PRIORITY);
261258 }
262259 }
263260
264−void SkeletonModel::updateJointState(int index) {
265− if (index < 0 && index >= _jointStates.size()) {
266− return; // bail
267− }
268− JointState& state = _jointStates[index];
269− const FBXJoint& joint = state.getFBXJoint();
270− if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) {
271− const JointState& parentState = _jointStates.at(joint.parentIndex);
272− const FBXGeometry& geometry = _geometry->getFBXGeometry();
273− if (index == geometry.leanJointIndex) {
274− maybeUpdateLeanRotation(parentState, state);
275−
276− } else if (index == geometry.neckJointIndex) {
277− maybeUpdateNeckRotation(parentState, joint, state);
278−
279− } else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) {
280− maybeUpdateEyeRotation(parentState, joint, state);
281− }
282− }
283−
284− Model::updateJointState(index);
285−
286− if (index == _geometry->getFBXGeometry().rootJointIndex) {
287− state.clearTransformTranslation();
288− }
289−}
290−
291−void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, JointState& state) {
292− if (!_owningAvatar->isMyAvatar()) {
293− return;
294− }
295− // get the rotation axes in joint space and use them to adjust the rotation
296− glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
297− glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
298− glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
299− glm::quat inverse = glm::inverse(parentState.getRotation() * state.getDefaultRotationInParentFrame());
300− state.setRotationInConstrainedFrame(
301− glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), inverse * zAxis)
302− * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), inverse * xAxis)
303− * glm::angleAxis(RADIANS_PER_DEGREE * _owningAvatar->getHead()->getTorsoTwist(), inverse * yAxis)
304− * state.getFBXJoint().rotation, LEAN_PRIORITY);
305−}
306−
307−void SkeletonModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
308− _owningAvatar->getHead()->getFaceModel().maybeUpdateNeckRotation(parentState, joint, state);
309−}
310−
311−void SkeletonModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
312− _owningAvatar->getHead()->getFaceModel().maybeUpdateEyeRotation(this, parentState, joint, state);
313−}
314−
315261 void SkeletonModel::renderJointConstraints(gpu::Batch& batch, int jointIndex) {
316− if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
262+ if (jointIndex == -1 || jointIndex >= _rig->getJointStateCount()) {
317263 return;
318264 }
319265 const FBXGeometry& geometry = _geometry->getFBXGeometry();
320266 const float BASE_DIRECTION_SIZE = 0.3f;
321267 float directionSize = BASE_DIRECTION_SIZE * extractUniformScale(_scale);
322− batch._glLineWidth(3.0f);
268+ // FIXME: THe line width of 3.0f is not supported anymore, we ll need a workaround
269+
323270 do {
324271 const FBXJoint& joint = geometry.joints.at(jointIndex);
325− const JointState& jointState = _jointStates.at(jointIndex);
272+ const JointState& jointState = _rig->getJointState(jointIndex);
326273 glm::vec3 position = _rotation * jointState.getPosition() + _translation;
327− glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _rotation * _jointStates.at(joint.parentIndex).getRotation();
274+ glm::quat parentRotation = (joint.parentIndex == -1) ?
275+ _rotation :
276+ _rotation * _rig->getJointState(joint.parentIndex).getRotation();
328277 float fanScale = directionSize * 0.75f;
329278
330279 Transform transform = Transform();
@@ -401,72 +350,6 @@ void SkeletonModel::renderOrientationDirections(gpu::Batch& batch, int jointInde · 70 unmodified lines
401350 geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front);
402351 }
403352
404−
405−
406−void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) {
407− // this algorithm is from sample code from sixense
408− const FBXGeometry& geometry = _geometry->getFBXGeometry();
409− int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex;
410− if (elbowJointIndex == -1) {
411− return;
412− }
413− int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex;
414− glm::vec3 shoulderPosition;
415− if (!getJointPosition(shoulderJointIndex, shoulderPosition)) {
416− return;
417− }
418− // precomputed lengths
419− float scale = extractUniformScale(_scale);
420− float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale;
421− float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale;
422−
423− // first set wrist position
424− glm::vec3 wristPosition = position;
425−
426− glm::vec3 shoulderToWrist = wristPosition - shoulderPosition;
427− float distanceToWrist = glm::length(shoulderToWrist);
428−
429− // prevent gimbal lock
430− if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) {
431− distanceToWrist = upperArmLength + lowerArmLength - EPSILON;
432− shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist;
433− wristPosition = shoulderPosition + shoulderToWrist;
434− }
435−
436− // cosine of angle from upper arm to hand vector
437− float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) /
438− (2 * upperArmLength * distanceToWrist);
439− float mid = upperArmLength * cosA;
440− float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA);
441−
442− // direction of the elbow
443− glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist
444− glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down
445− const float NORMAL_WEIGHT = 0.5f;
446− glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT);
447−
448− bool rightHand = (jointIndex == geometry.rightHandJointIndex);
449− if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) {
450− finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis)
451− }
452−
453− glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal));
454−
455− // ik solution
456− glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height;
457− glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f);
458− glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
459−
460− JointState& shoulderState = _jointStates[shoulderJointIndex];
461− shoulderState.setRotationInBindFrame(shoulderRotation, PALM_PRIORITY);
462−
463− JointState& elbowState = _jointStates[elbowJointIndex];
464− elbowState.setRotationInBindFrame(rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY);
465−
466− JointState& handState = _jointStates[jointIndex];
467− handState.setRotationInBindFrame(rotation, PALM_PRIORITY);
468−}
469−
470353 bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
471354 return getJointPositionInWorldFrame(getLeftHandJointIndex(), position);
472355 }
@@ -523,7 +406,7 @@ bool SkeletonModel::getNeckParentRotationFromDefaultOrientation(glm::quat& neckP · 50 unmodified lines
523406 glm::quat worldFrameRotation;
524407 bool success = getJointRotationInWorldFrame(parentIndex, worldFrameRotation);
525408 if (success) {
526− neckParentRotation = worldFrameRotation * _jointStates[parentIndex].getFBXJoint().inverseDefaultRotation;
409+ neckParentRotation = worldFrameRotation * _rig->getJointState(parentIndex).getFBXJoint().inverseDefaultRotation;
527410 }
528411 return success;
529412 }
@@ -574,7 +457,7 @@ float VERY_BIG_MASS = 1.0e6f; · 44 unmodified lines
574457
575458 // virtual
576459 void SkeletonModel::buildShapes() {
577− if (_geometry == NULL || _jointStates.isEmpty()) {
460+ if (_geometry == NULL || _rig->jointStatesEmpty()) {
578461 return;
579462 }
580463
@@ -583,46 +466,12 @@ void SkeletonModel::buildShapes() { · 2 unmodified lines
583466 // rootJointIndex == -1 if the avatar model has no skeleton
584467 return;
585468 }
586−
587− float uniformScale = extractUniformScale(_scale);
588− const int numStates = _jointStates.size();
589− for (int i = 0; i < numStates; i++) {
590− JointState& state = _jointStates[i];
591− const FBXJoint& joint = state.getFBXJoint();
592− float radius = uniformScale * joint.boneRadius;
593− float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
594− Shape::Type type = joint.shapeType;
595− int parentIndex = joint.parentIndex;
596− if (parentIndex == -1 || radius < EPSILON) {
597− type = INVALID_SHAPE;
598− } else if (type == CAPSULE_SHAPE && halfHeight < EPSILON) {
599− // this shape is forced to be a sphere
600− type = SPHERE_SHAPE;
601− }
602− Shape* shape = NULL;
603− if (type == SPHERE_SHAPE) {
604− shape = new SphereShape(radius);
605− shape->setEntity(this);
606− } else if (type == CAPSULE_SHAPE) {
607− assert(parentIndex != -1);
608− shape = new CapsuleShape(radius, halfHeight);
609− shape->setEntity(this);
610− }
611− if (shape && parentIndex != -1) {
612− // always disable collisions between joint and its parent
613− disableCollisions(i, parentIndex);
614− }
615− _shapes.push_back(shape);
616− }
617−
618− // This method moves the shapes to their default positions in Model frame.
619469 computeBoundingShape(geometry);
620470 }
621471
622472 void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
623473 // compute default joint transforms
624− int numStates = _jointStates.size();
625− assert(numStates == _shapes.size());
474+ int numStates = _rig->getJointStateCount();
626475 QVector<glm::mat4> transforms;
627476 transforms.fill(glm::mat4(), numStates);
628477
@@ -632,190 +481,69 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { · 3 unmodified lines
632481 totalExtents.addPoint(glm::vec3(0.0f));
633482 for (int i = 0; i < numStates; i++) {
634483 // compute the default transform of this joint
635− JointState& state = _jointStates[i];
484+ const JointState& state = _rig->getJointState(i);
636485 const FBXJoint& joint = state.getFBXJoint();
637486 int parentIndex = joint.parentIndex;
638487 if (parentIndex == -1) {
639− transforms[i] = _jointStates[i].getTransform();
488+ transforms[i] = _rig->getJointTransform(i);
640489 } else {
641490 glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
642491 transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
643492 * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
644493 }
645494
646− // Each joint contributes its point to the bounding box
495+ // Each joint contributes a sphere at its position
496+ glm::vec3 axis(joint.boneRadius);
647497 glm::vec3 jointPosition = extractTranslation(transforms[i]);
648− totalExtents.addPoint(jointPosition);
649−
650− Shape* shape = _shapes[i];
651− if (!shape) {
652− continue;
653− }
654−
655− // Each joint with a shape contributes to the totalExtents: a box
656− // that contains the sphere centered at the end of the joint with radius of the bone.
657−
658− // TODO: skip hand and arm shapes for bounding box calculation
659− int type = shape->getType();
660− if (type == CAPSULE_SHAPE) {
661− // add the two furthest surface points of the capsule
662− CapsuleShape* capsule = static_cast<CapsuleShape*>(shape);
663− float radius = capsule->getRadius();
664− glm::vec3 axis(radius);
665− Extents shapeExtents;
666− shapeExtents.reset();
667− shapeExtents.addPoint(jointPosition + axis);
668− shapeExtents.addPoint(jointPosition - axis);
669− totalExtents.addExtents(shapeExtents);
670− } else if (type == SPHERE_SHAPE) {
671− float radius = shape->getBoundingRadius();
672− glm::vec3 axis(radius);
673− Extents shapeExtents;
674− shapeExtents.reset();
675− shapeExtents.addPoint(jointPosition + axis);
676− shapeExtents.addPoint(jointPosition - axis);
677− totalExtents.addExtents(shapeExtents);
678− }
498+ totalExtents.addPoint(jointPosition + axis);
499+ totalExtents.addPoint(jointPosition - axis);
679500 }
680501
681502 // compute bounding shape parameters
682503 // NOTE: we assume that the longest side of totalExtents is the yAxis...
683504 glm::vec3 diagonal = totalExtents.maximum - totalExtents.minimum;
684505 // ... and assume the radius is half the RMS of the X and Z sides:
685− float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
686− _boundingShape.setRadius(capsuleRadius);
687− _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
506+ _boundingCapsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
507+ _boundingCapsuleHeight = diagonal.y - 2.0f * _boundingCapsuleRadius;
688508
689− glm::vec3 rootPosition = _jointStates[geometry.rootJointIndex].getPosition();
690− _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
509+ glm::vec3 rootPosition = _rig->getJointState(geometry.rootJointIndex).getPosition();
510+ _boundingCapsuleLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition;
691511 _boundingRadius = 0.5f * glm::length(diagonal);
692512 }
693513
694−void SkeletonModel::resetShapePositionsToDefaultPose() {
695− // DEBUG method.
696− // Moves shapes to the joint default locations for debug visibility into
697− // how the bounding shape is computed.
698−
699− if (!_geometry || _shapes.isEmpty()) {
700− // geometry or joints have not yet been created
701− return;
702− }
703−
704− const FBXGeometry& geometry = _geometry->getFBXGeometry();
705− if (geometry.joints.isEmpty()) {
706− return;
707− }
708−
709− // The shapes are moved to their default positions in computeBoundingShape().
710− computeBoundingShape(geometry);
711−
712− // Then we move them into world frame for rendering at the Model's location.
713− for (int i = 0; i < _shapes.size(); i++) {
714− Shape* shape = _shapes[i];
715− if (shape) {
716− shape->setTranslation(_translation + _rotation * shape->getTranslation());
717− shape->setRotation(_rotation * shape->getRotation());
718− }
719− }
720− _boundingShape.setTranslation(_translation + _rotation * _boundingShapeLocalOffset);
721− _boundingShape.setRotation(_rotation);
722−}
723−
724514 void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) {
725515 const int BALL_SUBDIVISIONS = 10;
726−#if 0
727− if (_shapes.isEmpty()) {
728− // the bounding shape has not been properly computed
729− // so no need to render it
730− return;
731− }
732516
733517 auto geometryCache = DependencyManager::get<GeometryCache>();
734518 auto deferredLighting = DependencyManager::get<DeferredLightingEffect>();
735519 Transform transform; // = Transform();
736520
737− // draw a blue sphere at the capsule end point
738− glm::vec3 endPoint;
739− _boundingShape.getEndPoint(endPoint);
740− endPoint = endPoint + _translation;
741− transform.setTranslation(endPoint);
521+ // draw a blue sphere at the capsule top point
522+ glm::vec3 topPoint = _translation + _boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * glm::vec3(0.0f, 1.0f, 0.0f);
523+ transform.setTranslation(topPoint);
742524 batch.setModelTransform(transform);
743525 deferredLighting->bindSimpleProgram(batch);
744− geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
526+ geometryCache->renderSphere(batch, _boundingCapsuleRadius, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
745527 glm::vec4(0.6f, 0.6f, 0.8f, alpha));
746528
747− // draw a yellow sphere at the capsule start point
748− glm::vec3 startPoint;
749− _boundingShape.getStartPoint(startPoint);
750− startPoint = startPoint + _translation;
751− glm::vec3 axis = endPoint - startPoint;
752− transform.setTranslation(startPoint);
529+ // draw a yellow sphere at the capsule bottom point
530+ glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, -_boundingCapsuleHeight, 0.0f);
531+ glm::vec3 axis = topPoint - bottomPoint;
532+ transform.setTranslation(bottomPoint);
753533 batch.setModelTransform(transform);
754534 deferredLighting->bindSimpleProgram(batch);
755− geometryCache->renderSphere(batch, _boundingShape.getRadius(), BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
535+ geometryCache->renderSphere(batch, _boundingCapsuleRadius, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS,
756536 glm::vec4(0.8f, 0.8f, 0.6f, alpha));
757537
758538 // draw a green cylinder between the two points
759539 glm::vec3 origin(0.0f);
760− Avatar::renderJointConnectingCone(batch, origin, axis, _boundingShape.getRadius(), _boundingShape.getRadius(),
540+ Avatar::renderJointConnectingCone(batch, origin, axis, _boundingCapsuleRadius, _boundingCapsuleRadius,
761541 glm::vec4(0.6f, 0.8f, 0.6f, alpha));
762−#endif
763542 }
764543
765544 bool SkeletonModel::hasSkeleton() {
766545 return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
767546 }
768547
769−void SkeletonModel::initHeadBones() {
770− _headBones.clear();
771− const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
772− const int neckJointIndex = fbxGeometry.neckJointIndex;
773− std::queue<int> q;
774− q.push(neckJointIndex);
775− _headBones.push_back(neckJointIndex);
776−
777− // fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
778− while (q.size() > 0) {
779− int jointIndex = q.front();
780− for (int i = 0; i < fbxGeometry.joints.size(); i++) {
781− const FBXJoint& fbxJoint = fbxGeometry.joints[i];
782− if (jointIndex == fbxJoint.parentIndex) {
783− _headBones.push_back(i);
784− q.push(i);
785− }
786− }
787− q.pop();
788− }
789−}
790−
791−void SkeletonModel::invalidateHeadBones() {
792− _headBones.clear();
793−}
794−
795−void SkeletonModel::cauterizeHead() {
796− if (isActive()) {
797− const FBXGeometry& geometry = _geometry->getFBXGeometry();
798− const int neckJointIndex = geometry.neckJointIndex;
799− if (neckJointIndex > 0 && neckJointIndex < _jointStates.size()) {
800−
801− // lazy init of headBones
802− if (_headBones.size() == 0) {
803− initHeadBones();
804− }
805−
806− // preserve the translation for the neck
807− glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3];
808− glm::vec4 zero(0, 0, 0, 0);
809− for (const int &i : _headBones) {
810− JointState& joint = _jointStates[i];
811− glm::mat4 newXform(zero, zero, zero, trans);
812− joint.setTransform(newXform);
813− joint.setVisibleTransform(newXform);
814− }
815− }
816− }
817−}
818−
819548 void SkeletonModel::onInvalidate() {
820− invalidateHeadBones();
821549 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t