From 73f8fca2afaa182d93d9a11e9510d6d8141e5891 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 3 Jun 2013 13:00:54 -0700 Subject: [PATCH] More work on voxeltars; added rotations. --- interface/src/Avatar.cpp | 8 +++- interface/src/AvatarVoxelSystem.cpp | 9 ++-- interface/src/Skeleton.cpp | 65 +++++++++++++-------------- interface/src/Skeleton.h | 68 +++++++++++++++-------------- interface/src/Util.cpp | 21 +++++++++ interface/src/Util.h | 2 + 6 files changed, 103 insertions(+), 70 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 2250bda751..fa193d3a70 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -909,6 +909,8 @@ void Avatar::updateBodyBalls(float deltaTime) { if (glm::length(_position - _bodyBall[AVATAR_JOINT_PELVIS].position) > BEYOND_BODY_SPRING_RANGE) { resetBodyBalls(); } + glm::quat orientation = getOrientation(); + glm::vec3 jointDirection = orientation * JOINT_DIRECTION; for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { glm::vec3 springVector(_bodyBall[b].position); @@ -955,7 +957,11 @@ void Avatar::updateBodyBalls(float deltaTime) { _bodyBall[b].position += _bodyBall[b].velocity * deltaTime; // update rotation - _bodyBall[b].rotation = _skeleton.joint[b].rotation; + if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL || length < 0.1f) { + _bodyBall[b].rotation = orientation * _skeleton.joint[b].absoluteBindPoseRotation; + } else { + _bodyBall[b].rotation = rotationBetween(jointDirection, springVector) * orientation; + } } } diff --git a/interface/src/AvatarVoxelSystem.cpp b/interface/src/AvatarVoxelSystem.cpp index d6b51bec82..9e441c148c 100644 --- a/interface/src/AvatarVoxelSystem.cpp +++ b/interface/src/AvatarVoxelSystem.cpp @@ -144,10 +144,11 @@ void AvatarVoxelSystem::applyScaleAndBindProgram(bool texture) { glm::vec3 position; glm::quat orientation; _avatar->getBodyBallTransform((AvatarJointID)i, position, orientation); - boneMatrices[i].translate(position.x, position.y, position.z); + boneMatrices[i].translate(position.x, position.y, position.z); + orientation = orientation * glm::inverse(_avatar->getSkeleton().joint[i].absoluteBindPoseRotation); boneMatrices[i].rotate(QQuaternion(orientation.w, orientation.x, orientation.y, orientation.z)); - const glm::vec3& defaultPosition = _avatar->getSkeleton().joint[i].absoluteDefaultPosePosition; - boneMatrices[i].translate(-defaultPosition.x, -defaultPosition.y, -defaultPosition.z); + const glm::vec3& bindPosition = _avatar->getSkeleton().joint[i].absoluteBindPosePosition; + boneMatrices[i].translate(-bindPosition.x, -bindPosition.y, -bindPosition.z); boneMatrices[i] *= baseMatrix; } _skinProgram->setUniformValueArray(_boneMatricesLocation, boneMatrices, NUM_AVATAR_JOINTS); @@ -182,7 +183,7 @@ void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, Bo // find the nearest four joints (TODO: use a better data structure for the pose positions to speed this up) IndexDistance nearest[BONE_ELEMENTS_PER_VERTEX]; for (int i = 0; i < NUM_AVATAR_JOINTS; i++) { - float distance = glm::distance(jointVertex, _avatar->getSkeleton().joint[i].absoluteDefaultPosePosition); + float distance = glm::distance(jointVertex, _avatar->getSkeleton().joint[i].absoluteBindPosePosition); for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) { if (distance < nearest[j].distance) { // move the rest of the indices down diff --git a/interface/src/Skeleton.cpp b/interface/src/Skeleton.cpp index ae31810d8e..136cb6f619 100644 --- a/interface/src/Skeleton.cpp +++ b/interface/src/Skeleton.cpp @@ -5,6 +5,7 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include "Skeleton.h" +#include "Util.h" const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f; const float FLOATING_HEIGHT = 0.13f; @@ -17,7 +18,7 @@ void Skeleton::initialize() { for (int b=0; b 179.99f) { // 180 degree rotation; must use another axis + axis = glm::cross(v1, glm::vec3(1.0f, 0.0f, 0.0f)); + float axisLength = glm::length(axis); + if (axisLength < EPSILON) { // parallel to x; y will work + axis = glm::normalize(glm::cross(v1, glm::vec3(0.0f, 1.0f, 0.0f))); + } else { + axis /= axisLength; + } + } else { + axis = glm::normalize(glm::cross(v1, v2)); + } + return glm::angleAxis(angle, axis); +} + // Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's // http://www.geometrictools.com/Documentation/EulerAngles.pdf (via Clyde, // https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) diff --git a/interface/src/Util.h b/interface/src/Util.h index 0823ac405b..0187d93da5 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -45,6 +45,8 @@ void drawVector(glm::vec3* vector); float angleBetween(const glm::vec3& v1, const glm::vec3& v2); +glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); + glm::vec3 safeEulerAngles(const glm::quat& q); glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);