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
1111
1212 #include <glm/gtx/transform.hpp>
1313
14−#include <CapsuleShape.h>
15−#include <SphereShape.h>
14+#include <VerletCapsuleShape.h>
15+#include <VerletSphereShape.h>
1616
1717 #include "Application.h"
1818 #include "Avatar.h"
@@ -31,20 +31,10 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : · 12 unmodified lines
3131 void SkeletonModel::setJointStates(QVector<JointState> states) {
3232 Model::setJointStates(states);
3333
34− if (isActive() && _owningAvatar->isMyAvatar()) {
35− // extract lists of parentIndex and position from _jointStates...
36− QVector<int> parentIndices;
37− QVector<glm::vec3> points;
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);
34+ clearShapes();
35+ clearRagdollConstraintsAndPoints();
36+ if (_enableShapes) {
37+ buildShapes();
4838 }
4939 }
5040
@@ -110,14 +100,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { · 59 unmodified lines
110100 }
111101
112102 void SkeletonModel::simulateRagdoll(float deltaTime) {
113− // move ragdoll _points toward joints
103+ // move _ragdollPoints toward joints
114104 const int numStates = _jointStates.size();
115− assert(numStates == _points.size());
105+ assert(numStates == _ragdollPoints.size());
116106 float fraction = 0.1f; // fraction = 0.1f left intentionally low for demo purposes
117− float oneMinusFraction = 1.0f - fraction;
118− for (int i = 0; i < numStates; ++i) {
119− _points[i] = oneMinusFraction * _points[i] + fraction * _jointStates[i].getPosition();
120− }
107+ moveShapesTowardJoints(fraction);
121108
122109 // enforce the constraints
123110 float MIN_CONSTRAINT_ERROR = 0.005f; // 5mm
@@ -125,7 +112,7 @@ void SkeletonModel::simulateRagdoll(float deltaTime) { · 1 unmodified line
125112 int iterations = 0;
126113 float delta = 0.0f;
127114 do {
128− delta = enforceConstraints();
115+ delta = enforceRagdollConstraints();
129116 ++iterations;
130117 } while (delta > MIN_CONSTRAINT_ERROR && iterations < MAX_ITERATIONS);
131118 }
@@ -274,16 +261,6 @@ void SkeletonModel::updateJointState(int index) { · 142 unmodified lines
274261 }
275262 }
276263
277−void 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−
287264 void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
288265 if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) {
289266 return;
@@ -516,14 +493,14 @@ void SkeletonModel::renderRagdoll() { · 226 unmodified lines
516493 glPushMatrix();
517494
518495 Application::getInstance()->loadTranslatedViewMatrix(_translation);
519− int numPoints = _points.size();
496+ int numPoints = _ragdollPoints.size();
520497 float alpha = 0.3f;
521498 float radius1 = 0.008f;
522499 float radius2 = 0.01f;
523500 for (int i = 0; i < numPoints; ++i) {
524501 glPushMatrix();
525502 // draw each point as a yellow hexagon with black border
526− glm::vec3 position = _rotation * _points[i];
503+ glm::vec3 position = _rotation * _ragdollPoints[i];
527504 glTranslatef(position.x, position.y, position.z);
528505 glColor4f(0.0f, 0.0f, 0.0f, alpha);
529506 glutSolidSphere(radius2, BALL_SUBDIVISIONS, BALL_SUBDIVISIONS);
@@ -536,6 +513,22 @@ void SkeletonModel::renderRagdoll() { · 6 unmodified lines
536513 glEnable(GL_LIGHTING);
537514 }
538515
516+// virtual
517+void 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
529+void SkeletonModel::stepRagdollForward(float deltaTime) {
530+}
531+
539532 // virtual
540533 void SkeletonModel::buildShapes() {
541534 if (!_geometry || _rootIndex == -1) {
@@ -546,42 +539,53 @@ void SkeletonModel::buildShapes() { · 4 unmodified lines
546539 if (geometry.joints.isEmpty()) {
547540 return;
548541 }
549− // We create the shapes with proper dimensions, but we set their transforms later.
542+
543+ initRagdollPoints();
544+
550545 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++) {
552548 const FBXJoint& joint = geometry.joints[i];
553−
554549 float radius = uniformScale * joint.boneRadius;
555550 float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
556551 Shape::Type type = joint.shapeType;
557− if (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON) {
558− // this capsule is effectively a sphere
552+ if (i == 0 || (type == Shape::CAPSULE_SHAPE && halfHeight < EPSILON)) {
553+ // this shape is forced to be a sphere
559554 type = Shape::SPHERE_SHAPE;
560555 }
561− if (type == Shape::CAPSULE_SHAPE) {
562− CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
563− capsule->setEntity(this);
564− _shapes.push_back(capsule);
565− } else if (type == Shape::SPHERE_SHAPE) {
566− SphereShape* sphere = new SphereShape(radius, glm::vec3(0.0f));
567− _shapes.push_back(sphere);
568− sphere->setEntity(this);
569− } else {
570− // this shape type is not handled and the joint shouldn't collide,
571− // however we must have a Shape* for each joint, so we push NULL
572− _shapes.push_back(NULL);
573− }
556+ Shape* shape = NULL;
557+ if (type == Shape::SPHERE_SHAPE) {
558+ shape = new VerletSphereShape(radius, &(_ragdollPoints[i]));
559+ shape->setEntity(this);
560+ } else if (type == Shape::CAPSULE_SHAPE) {
561+ int parentIndex = joint.parentIndex;
562+ assert(parentIndex != -1);
563+ shape = new VerletCapsuleShape(radius, &(_ragdollPoints[parentIndex]), &(_ragdollPoints[i]));
564+ shape->setEntity(this);
565+ }
566+ _shapes.push_back(shape);
574567 }
575568
576569 // This method moves the shapes to their default positions in Model frame
577570 // which is where we compute the bounding shape's parameters.
578571 computeBoundingShape(geometry);
579572
580− // finally sync shapes to joint positions
581− _shapesAreDirty = true;
582− updateShapePositions();
573+ // move shapes to joint positions
574+ moveShapesTowardJoints(1.0f);
583575 }
584576
577+void 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.
585589 void SkeletonModel::updateShapePositionsLegacy() {
586590 if (_shapesAreDirty && _shapes.size() == _jointStates.size()) {
587591 glm::vec3 rootPosition(0.0f);
@@ -612,65 +616,28 @@ void SkeletonModel::updateShapePositionsLegacy() { · 24 unmodified lines
612616 _boundingShape.setRotation(_rotation);
613617 }
614618 }
619+*/
615620
616621 void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
617− // compute default joint transforms and rotations
618− // (in local frame, ignoring Model translation and rotation)
622+ // compute default joint transforms
619623 int numJoints = geometry.joints.size();
624+ if (numJoints != _ragdollPoints.size()) {
625+ return;
626+ }
620627 QVector<glm::mat4> transforms;
621628 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− }
656629
657− // sync shapes to joints
658− _boundingRadius = 0.0f;
659− float uniformScale = extractUniformScale(_scale);
660− for (int i = 0; i < _shapes.size(); i++) {
661− Shape* shape = _shapes[i];
662− if (!shape) {
663− continue;
664− }
665− const FBXJoint& joint = geometry.joints[i];
666− glm::vec3 jointToShapeOffset = uniformScale * (finalRotations[i] * joint.shapePosition);
667− glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset;
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− }
630+ transforms[0] = glm::scale(_scale);
631+ for (int i = 1; i < numJoints; i++) {
632+ const FBXJoint& joint = geometry.joints.at(i);
633+ int parentIndex = joint.parentIndex;
634+ assert(parentIndex != -1);
635+
636+ glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
637+ transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
638+ * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
639+ // setting the ragdollPoints here slams the VerletShapes into their default positions
640+ _ragdollPoints[i] = extractTranslation(transforms[i]);
674641 }
675642
676643 // compute bounding box
@@ -682,6 +649,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { · 5 unmodified lines
682649 if (!shape) {
683650 continue;
684651 }
652+ // TODO: skip hand and arm joints when computing bounding dimensions
685653 Extents shapeExtents;
686654 shapeExtents.reset();
687655 glm::vec3 localPosition = shape->getTranslation();
@@ -715,6 +683,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { · 27 unmodified lines
715683 _boundingShape.setRadius(capsuleRadius);
716684 _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
717685 _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum);
686+ _boundingRadius = 0.5f * glm::length(diagonal);
718687 }
719688
720689 void 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