Only bind vertices within an adjustable radius.

This commit is contained in:
Andrzej Kapolka 2013-06-04 10:40:08 -07:00
parent bc8eadd526
commit 90a53bc518
4 changed files with 26 additions and 9 deletions

View file

@ -957,7 +957,7 @@ void Avatar::updateBodyBalls(float deltaTime) {
_bodyBall[b].position += _bodyBall[b].velocity * deltaTime;
// update rotation
if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL || length < 0.1f) {
if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL || length < EPSILON) {
_bodyBall[b].rotation = orientation * _skeleton.joint[b].absoluteBindPoseRotation;
} else {
_bodyBall[b].rotation = rotationBetween(jointDirection, springVector) * orientation;

View file

@ -202,7 +202,7 @@ void AvatarVoxelSystem::handleVoxelReplyError() {
class IndexDistance {
public:
IndexDistance(GLubyte index = 0, float distance = FLT_MAX) : index(index), distance(distance) { }
IndexDistance(GLubyte index = AVATAR_JOINT_PELVIS, float distance = FLT_MAX) : index(index), distance(distance) { }
GLubyte index;
float distance;
@ -214,11 +214,15 @@ 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];
const Skeleton& skeleton = _avatar->getSkeleton();
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
AvatarJointID parent = _avatar->getSkeleton().joint[i].parent;
AvatarJointID parent = skeleton.joint[i].parent;
float distance = glm::length(computeVectorFromPointToSegment(jointVertex,
_avatar->getSkeleton().joint[parent == AVATAR_JOINT_NULL ? i : parent].absoluteBindPosePosition,
_avatar->getSkeleton().joint[i].absoluteBindPosePosition));
skeleton.joint[parent == AVATAR_JOINT_NULL ? i : parent].absoluteBindPosePosition,
skeleton.joint[i].absoluteBindPosePosition));
if (distance > skeleton.joint[i].bindRadius) {
continue;
}
for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) {
if (distance < nearest[j].distance) {
// move the rest of the indices down
@ -235,11 +239,22 @@ void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, Bo
float totalWeight = 0.0f;
for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) {
indices[i] = nearest[i].index;
weights[i] = 1.0f / glm::max(nearest[i].distance, EPSILON);
totalWeight += weights[i];
if (nearest[i].distance != FLT_MAX) {
weights[i] = 1.0f / glm::max(nearest[i].distance, EPSILON);
totalWeight += weights[i];
} else {
weights[i] = 0.0f;
}
}
// normalize the weights
// if it's not attached to anything, consider it attached to the hip
if (totalWeight == 0.0f) {
weights[0] = 1.0f;
return;
}
// ortherwise, normalize the weights
for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) {
weights[i] /= totalWeight;
}

View file

@ -18,9 +18,10 @@ void Skeleton::initialize() {
for (int b=0; b<NUM_AVATAR_JOINTS; b++) {
joint[b].parent = AVATAR_JOINT_NULL;
joint[b].position = glm::vec3(0.0, 0.0, 0.0);
joint[b].bindPosePosition = glm::vec3(0.0, 0.0, 0.0);
joint[b].defaultPosePosition = glm::vec3(0.0, 0.0, 0.0);
joint[b].rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
joint[b].length = 0.0;
joint[b].bindRadius = 1.0f / 16;
}
// specify the parental hierarchy

View file

@ -65,6 +65,7 @@ public:
glm::vec3 bindPosePosition; // the parent relative position when the avatar is in the "T-pose"
glm::vec3 absoluteBindPosePosition; // the absolute position when the avatar is in the "T-pose"
glm::quat absoluteBindPoseRotation; // the absolute rotation when the avatar is in the "T-pose"
float bindRadius; // the radius of the bone capsule that envelops the vertices to bind
glm::quat rotation; // the parent-relative rotation (orientation) of the joint as a quaternion
float length; // the length of vector connecting the joint and its parent
};