History

Skeleton now creates VerletShape

Andrew Meadows committed 12 years ago

Commit d4b55501 parent 715cc3410 files · +116 −188Browse files

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

Unified · Split

interface/src/avatar/SkeletonModel.cpp+78−109
@@ -11,8 +11,8 @@ · 10 unmodified lines
11 11
12#include <glm/gtx/transform.hpp>12#include <glm/gtx/transform.hpp>
13 13
14#include <CapsuleShape.h>14#include <VerletCapsuleShape.h>
15#include <SphereShape.h>15#include <VerletSphereShape.h>
16 16
17#include "Application.h"17#include "Application.h"
18#include "Avatar.h"18#include "Avatar.h"
@@ -31,20 +31,10 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : · 12 unmodified lines
31void SkeletonModel::setJointStates(QVector<JointState> states) {31void SkeletonModel::setJointStates(QVector<JointState> states) {
32 Model::setJointStates(states);32 Model::setJointStates(states);
33 33
34 if (isActive() && _owningAvatar->isMyAvatar()) {34 clearShapes();
35 // extract lists of parentIndex and position from _jointStates...35 clearRagdollConstraintsAndPoints();
36 QVector<int> parentIndices;36 if (_enableShapes) {
37 QVector<glm::vec3> points;37 buildShapes();
38 int numJoints = _jointStates.size();
39 parentIndices.reserve(numJoints);
40 points.reserve(numJoints);
41 for (int i = 0; i < numJoints; ++i) {
42 JointState& state = _jointStates[i];
43 parentIndices.push_back(state.getFBXJoint().parentIndex);
44 points.push_back(state.getPosition());
45 }
46 // ... and feed the results to Ragdoll
47 initShapesAndPoints(&_shapes, parentIndices, points);
48 }38 }
49}39}
50 40
@@ -110,14 +100,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { · 59 unmodified lines
110}100}
111 101
112void SkeletonModel::simulateRagdoll(float deltaTime) {102void SkeletonModel::simulateRagdoll(float deltaTime) {
113 // move ragdoll _points toward joints103 // move _ragdollPoints toward joints
114 const int numStates = _jointStates.size();104 const int numStates = _jointStates.size();
115 assert(numStates == _points.size());105 assert(numStates == _ragdollPoints.size());
116 float fraction = 0.1f; // fraction = 0.1f left intentionally low for demo purposes106 float fraction = 0.1f; // fraction = 0.1f left intentionally low for demo purposes
117 float oneMinusFraction = 1.0f - fraction;107 moveShapesTowardJoints(fraction);
118 for (int i = 0; i < numStates; ++i) {
119 _points[i] = oneMinusFraction * _points[i] + fraction * _jointStates[i].getPosition();
120 }
121 108
122 // enforce the constraints109 // enforce the constraints
123 float MIN_CONSTRAINT_ERROR = 0.005f; // 5mm110 float MIN_CONSTRAINT_ERROR = 0.005f; // 5mm
@@ -125,7 +112,7 @@ void SkeletonModel::simulateRagdoll(float deltaTime) { · 1 unmodified line
125 int iterations = 0;112 int iterations = 0;
126 float delta = 0.0f;113 float delta = 0.0f;
127 do {114 do {
128 delta = enforceConstraints();115 delta = enforceRagdollConstraints();
129 ++iterations;116 ++iterations;
130 } while (delta > MIN_CONSTRAINT_ERROR && iterations < MAX_ITERATIONS);117 } while (delta > MIN_CONSTRAINT_ERROR && iterations < MAX_ITERATIONS);
131}118}
@@ -274,16 +261,6 @@ void SkeletonModel::updateJointState(int index) { · 142 unmodified lines
274 }261 }
275}262}
276 263
277void SkeletonModel::updateShapePositions() {
278 if (isActive() && _owningAvatar->isMyAvatar() &&
279 Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
280 // TODO: Andrew to move shape updates to SimulationEngine
281 //updateShapes(_rotation, _translation);
282 } else {
283 Model::updateShapePositions();
284 }
285}
286
287void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {264void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
288 if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) {265 if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) {
289 return;266 return;
@@ -516,14 +493,14 @@ void SkeletonModel::renderRagdoll() { · 226 unmodified lines
516 glPushMatrix();493 glPushMatrix();
517 494
518 Application::getInstance()->loadTranslatedViewMatrix(_translation);495 Application::getInstance()->loadTranslatedViewMatrix(_translation);
519 int numPoints = _points.size();496 int numPoints = _ragdollPoints.size();
520 float alpha = 0.3f;497 float alpha = 0.3f;
521 float radius1 = 0.008f;498 float radius1 = 0.008f;
522 float radius2 = 0.01f;499 float radius2 = 0.01f;
523 for (int i = 0; i < numPoints; ++i) {500 for (int i = 0; i < numPoints; ++i) {
524 glPushMatrix();501 glPushMatrix();
525 // draw each point as a yellow hexagon with black border502 // draw each point as a yellow hexagon with black border
526 glm::vec3 position = _rotation * _points[i];503 glm::vec3 position = _rotation * _ragdollPoints[i];
527 glTranslatef(position.x, position.y, position.z);504 glTranslatef(position.x, position.y, position.z);
528 glColor4f(0.0f, 0.0f, 0.0f, alpha);505 glColor4f(0.0f, 0.0f, 0.0f, alpha);
529 glutSolidSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);506 glutSolidSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
@@ -536,6 +513,22 @@ void SkeletonModel::renderRagdoll() { · 6 unmodified lines
536 glEnable(GL_LIGHTING);513 glEnable(GL_LIGHTING);
537}514}
538 515
516// virtual
517void SkeletonModel::initRagdollPoints() {
518 assert(_ragdollPoints.size() == 0);
519 // one point for each joint
520 int numJoints = _jointStates.size();
521 _ragdollPoints.reserve(numJoints);
522 for (int i = 0; i < numJoints; ++i) {
523 const JointState& state = _jointStates.at(i);
524 _ragdollPoints.push_back(state.getPosition());
525 }
526}
527
528// virtual
529void SkeletonModel::stepRagdollForward(float deltaTime) {
530}
531
539// virtual532// virtual
540void SkeletonModel::buildShapes() {533void SkeletonModel::buildShapes() {
541 if (!_geometry || _rootIndex == -1) {534 if (!_geometry || _rootIndex == -1) {
@@ -546,42 +539,53 @@ void SkeletonModel::buildShapes() { · 4 unmodified lines
546 if (geometry.joints.isEmpty()) {539 if (geometry.joints.isEmpty()) {
547 return;540 return;
548 }541 }
549 // We create the shapes with proper dimensions, but we set their transforms later.542
543 initRagdollPoints();
544
550 float uniformScale = extractUniformScale(_scale);545 float uniformScale = extractUniformScale(_scale);
551 for (int i = 0; i < _jointStates.size(); i++) {546 const int numStates = _jointStates.size();
547 for (int i = 0; i < numStates; i++) {
552 const FBXJoint& joint = geometry.joints[i];548 const FBXJoint& joint = geometry.joints[i];
553
554 float radius = uniformScale * joint.boneRadius;549 float radius = uniformScale * joint.boneRadius;
555 float halfHeight = 0.5f * uniformScale * joint.distanceToParent;550 float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
556 Shape::Type type = joint.shapeType;551 Shape::Type type = joint.shapeType;
557 if (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON) {552 if (i == 0 || (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON)) {
558 // this capsule is effectively a sphere553 // this shape is forced to be a sphere
559 type = Shape::SPHERE_SHAPE;554 type = Shape::SPHERE_SHAPE;
560 }555 }
561 if (type == Shape::CAPSULE_SHAPE) {556 Shape* shape = NULL;
562 CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);557 if (type == Shape::SPHERE_SHAPE) {
563 capsule->setEntity(this);558 shape = new VerletSphereShape(radius, &(_ragdollPoints[i]));
564 _shapes.push_back(capsule);559 shape->setEntity(this);
565 } else if (type == Shape::SPHERE_SHAPE) {560 } else if (type == Shape::CAPSULE_SHAPE) {
566 SphereShape* sphere = new SphereShape(radius, glm::vec3(0.0f));561 int parentIndex = joint.parentIndex;
567 _shapes.push_back(sphere);562 assert(parentIndex != -1);
568 sphere->setEntity(this);563 shape = new VerletCapsuleShape(radius, &(_ragdollPoints[parentIndex]), &(_ragdollPoints[i]));
569 } else {564 shape->setEntity(this);
570 // this shape type is not handled and the joint shouldn't collide, 565 }
571 // however we must have a Shape* for each joint, so we push NULL566 _shapes.push_back(shape);
572 _shapes.push_back(NULL);
573 }
574 }567 }
575 568
576 // This method moves the shapes to their default positions in Model frame569 // This method moves the shapes to their default positions in Model frame
577 // which is where we compute the bounding shape's parameters.570 // which is where we compute the bounding shape's parameters.
578 computeBoundingShape(geometry);571 computeBoundingShape(geometry);
579 572
580 // finally sync shapes to joint positions573 // move shapes to joint positions
581 _shapesAreDirty = true;574 moveShapesTowardJoints(1.0f);
582 updateShapePositions();
583}575}
584 576
577void SkeletonModel::moveShapesTowardJoints(float fraction) {
578 assert(fraction >= 0.0f && fraction <= 1.0f);
579 if (_ragdollPoints.size() == _jointStates.size()) {
580 float oneMinusFraction = 1.0f - fraction;
581 int numJoints = _jointStates.size();
582 for (int i = 0; i < numJoints; ++i) {
583 _ragdollPoints[i] = oneMinusFraction * _ragdollPoints[i] + fraction * _jointStates.at(i).getPosition();
584 }
585 }
586}
587
588/* TODO: Andrew to remove this when done with ragdoll work.
585void SkeletonModel::updateShapePositionsLegacy() {589void SkeletonModel::updateShapePositionsLegacy() {
586 if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {590 if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {
587 glm::vec3 rootPosition(0.0f);591 glm::vec3 rootPosition(0.0f);
@@ -612,65 +616,28 @@ void SkeletonModel::updateShapePositionsLegacy() { · 24 unmodified lines
612 _boundingShape.setRotation(_rotation);616 _boundingShape.setRotation(_rotation);
613 }617 }
614}618}
619*/
615 620
616void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {621void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
617 // compute default joint transforms and rotations 622 // compute default joint transforms
618 // (in local frame, ignoring Model translation and rotation)
619 int numJoints = geometry.joints.size();623 int numJoints = geometry.joints.size();
624 if (numJoints != _ragdollPoints.size()) {
625 return;
626 }
620 QVector<glm::mat4> transforms;627 QVector<glm::mat4> transforms;
621 transforms.fill(glm::mat4(), numJoints);628 transforms.fill(glm::mat4(), numJoints);
622 QVector<glm::quat> finalRotations;
623 finalRotations.fill(glm::quat(), numJoints);
624
625 QVector<bool> shapeIsSet;
626 shapeIsSet.fill(false, numJoints);
627 int numShapesSet = 0;
628 int lastNumShapesSet = -1;
629 while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
630 lastNumShapesSet = numShapesSet;
631 for (int i = 0; i < numJoints; i++) {
632 const FBXJoint& joint = geometry.joints.at(i);
633 int parentIndex = joint.parentIndex;
634
635 if (parentIndex == -1) {
636 glm::mat4 baseTransform = glm::scale(_scale) * glm::translate(_offset);
637 glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
638 glm::mat4 rootTransform = baseTransform * geometry.offset * glm::translate(joint.translation)
639 * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
640 // remove the tranlsation part before we save the root transform
641 transforms[i] = glm::translate(- extractTranslation(rootTransform)) * rootTransform;
642
643 finalRotations[i] = combinedRotation;
644 ++numShapesSet;
645 shapeIsSet[i] = true;
646 } else if (shapeIsSet[parentIndex]) {
647 glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
648 transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
649 * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
650 finalRotations[i] = finalRotations[parentIndex] * combinedRotation;
651 ++numShapesSet;
652 shapeIsSet[i] = true;
653 }
654 }
655 }
656 629
657 // sync shapes to joints630 transforms[0] = glm::scale(_scale);
658 _boundingRadius = 0.0f;631 for (int i = 1; i < numJoints; i++) {
659 float uniformScale = extractUniformScale(_scale);632 const FBXJoint& joint = geometry.joints.at(i);
660 for (int i = 0; i < _shapes.size(); i++) {633 int parentIndex = joint.parentIndex;
661 Shape* shape = _shapes[i];634 assert(parentIndex != -1);
662 if (!shape) {635
663 continue;636 glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
664 }637 transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
665 const FBXJoint& joint = geometry.joints[i];638 * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
666 glm::vec3 jointToShapeOffset = uniformScale * (finalRotations[i] * joint.shapePosition);639 // setting the ragdollPoints here slams the VerletShapes into their default positions
667 glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset;640 _ragdollPoints[i] = extractTranslation(transforms[i]);
668 shape->setTranslation(localPosition);
669 shape->setRotation(finalRotations[i] * joint.shapeRotation);
670 float distance = glm::length(localPosition) + shape->getBoundingRadius();
671 if (distance > _boundingRadius) {
672 _boundingRadius = distance;
673 }
674 }641 }
675 642
676 // compute bounding box643 // compute bounding box
@@ -682,6 +649,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { · 5 unmodified lines
682 if (!shape) {649 if (!shape) {
683 continue;650 continue;
684 }651 }
652 // TODO: skip hand and arm joints when computing bounding dimensions
685 Extents shapeExtents;653 Extents shapeExtents;
686 shapeExtents.reset();654 shapeExtents.reset();
687 glm::vec3 localPosition = shape->getTranslation();655 glm::vec3 localPosition = shape->getTranslation();
@@ -715,6 +683,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { · 27 unmodified lines
715 _boundingShape.setRadius(capsuleRadius);683 _boundingShape.setRadius(capsuleRadius);
716 _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);684 _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
717 _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum);685 _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum);
686 _boundingRadius = 0.5f * glm::length(diagonal);
718}687}
719 688
720void SkeletonModel::resetShapePositions() {689void SkeletonModel::resetShapePositions() {

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