Skeleton removal checkpoint; compiles, but there are a few bits missing.

This commit is contained in:
Andrzej Kapolka 2014-01-15 15:14:50 -08:00
parent 7be1d4d8c0
commit 2c7b6b9696
13 changed files with 25 additions and 587 deletions

View file

@ -2349,7 +2349,7 @@ void Application::updateTransmitter(float deltaTime) {
// no transmitter drive implies transmitter pick
if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) {
_transmitterPickStart = _myAvatar.getSkeleton().joint[AVATAR_JOINT_CHEST].position;
_transmitterPickStart = _myAvatar.getChestJointPosition();
glm::vec3 direction = _myAvatar.getOrientation() *
glm::quat(glm::radians(_myTransmitter.getEstimatedRotation())) * IDENTITY_FRONT;

View file

@ -772,4 +772,4 @@ void Audio::renderToolIcon(int screenHeight) {
}
glDisable(GL_TEXTURE_2D);
}
}

View file

@ -383,13 +383,6 @@ Menu::Menu() :
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
addCheckableActionToQMenuAndActionHash(trackingOptionsMenu,
MenuOption::SkeletonTracking,
0,
false,
appInstance->getWebcam(),
SLOT(setSkeletonTrackingOn(bool)));
addCheckableActionToQMenuAndActionHash(trackingOptionsMenu,
MenuOption::LEDTracking,
0,

View file

@ -246,7 +246,6 @@ namespace MenuOption {
const QString SimulateLeapHand = "Simulate Leap Hand";
const QString VoxelDrumming = "Voxel Drumming";
const QString PlaySlaps = "Play Slaps";
const QString SkeletonTracking = "Skeleton Tracking";
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
const QString LEDTracking = "LED Tracking";
const QString Stars = "Stars";

View file

@ -97,9 +97,7 @@ Avatar::Avatar(Node* owningNode) :
_isCollisionsOn(true),
_moving(false),
_initialized(false),
_handHoldingPosition(0.0f, 0.0f, 0.0f),
_maxArmLength(0.0f),
_pelvisStandingHeight(0.0f)
_handHoldingPosition(0.0f, 0.0f, 0.0f)
{
// we may have been created in the network thread, but we live in the main thread
moveToThread(Application::getInstance()->thread());
@ -108,14 +106,10 @@ Avatar::Avatar(Node* owningNode) :
_headData = &_head;
_handData = &_hand;
_skeleton.initialize();
_height = _skeleton.getHeight();
_height = 0.0f; // _skeleton.getHeight();
_maxArmLength = _skeleton.getArmLength();
_pelvisStandingHeight = _skeleton.getPelvisStandingHeight();
_pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight();
_pelvisToHeadLength = _skeleton.getPelvisToHeadLength();
_pelvisFloatingHeight = 0.0f; // _skeleton.getPelvisFloatingHeight();
_pelvisToHeadLength = 0.0f; // _skeleton.getPelvisToHeadLength();
}
@ -153,22 +147,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
// copy velocity so we can use it later for acceleration
glm::vec3 oldVelocity = getVelocity();
// update torso rotation based on head lean
_skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3(
_head.getLeanForward(), 0.0f, _head.getLeanSideways())));
// apply joint data (if any) to skeleton
bool enableHandMovement = true;
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
_skeleton.joint[it->jointID].rotation = it->rotation;
// disable hand movement if we have joint info for the right wrist
enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST);
}
// update avatar skeleton
_skeleton.update(deltaTime, getOrientation(), _position);
_hand.simulate(deltaTime, false);
_skeletonModel.simulate(deltaTime);
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
@ -444,13 +422,9 @@ void Avatar::setScale(const float scale) {
_scale = _targetScale;
}
_skeleton.setScale(_scale);
_height = 0.0f; // _skeleton.getHeight();
_height = _skeleton.getHeight();
_maxArmLength = _skeleton.getArmLength();
_pelvisStandingHeight = _skeleton.getPelvisStandingHeight();
_pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight();
_pelvisToHeadLength = _skeleton.getPelvisToHeadLength();
_pelvisFloatingHeight = 0.0f; // _skeleton.getPelvisFloatingHeight();
_pelvisToHeadLength = 0.0f; // _skeleton.getPelvisToHeadLength();
}

View file

@ -18,7 +18,6 @@
#include "Hand.h"
#include "Head.h"
#include "InterfaceConfig.h"
#include "Skeleton.h"
#include "SkeletonModel.h"
#include "world.h"
#include "devices/Transmitter.h"
@ -142,11 +141,10 @@ public:
//getters
bool isInitialized() const { return _initialized; }
const Skeleton& getSkeleton() const { return _skeleton; }
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
float getHeadYawRate() const { return _head.yawRate; }
const glm::vec3& getHeadJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position; }
const glm::vec3& getChestJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_CHEST ].position; }
const glm::vec3& getHeadJointPosition() const { return _position; }
const glm::vec3& getChestJointPosition() const { return _position; }
float getScale() const { return _scale; }
const glm::vec3& getVelocity() const { return _velocity; }
Head& getHead() { return _head; }
@ -182,23 +180,8 @@ public slots:
protected:
struct AvatarBall {
AvatarJointID parentJoint; /// the skeletal joint that serves as a reference for determining the position
glm::vec3 parentOffset; /// a 3D vector in the frame of reference of the parent skeletal joint
AvatarBodyBallID parentBall; /// the ball to which this ball is constrained for spring forces
glm::vec3 position; /// the actual dynamic position of the ball at any given time
glm::quat rotation; /// the rotation of the ball
glm::vec3 velocity; /// the velocity of the ball
float springLength; /// the ideal length of the spring between this ball and its parentBall
float jointTightness; /// how tightly the ball position attempts to stay at its ideal position (determined by parentOffset)
float radius; /// the radius of the ball
bool isCollidable; /// whether or not the ball responds to collisions
float touchForce; /// a scalar determining the amount that the cursor (or hand) is penetrating the ball
};
Head _head;
Hand _hand;
Skeleton _skeleton;
SkeletonModel _skeletonModel;
bool _ballSpringsInitialized;
float _bodyYawDelta;
@ -234,8 +217,6 @@ private:
bool _initialized;
glm::vec3 _handHoldingPosition;
float _maxArmLength;
float _pelvisStandingHeight;
// private methods...

View file

@ -24,22 +24,18 @@ void FaceModel::simulate(float deltaTime) {
}
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
glm::vec3 neckPosition;
glm::vec3 modelTranslation;
if (!owningAvatar->getSkeletonModel().getNeckPosition(neckPosition)) {
neckPosition = owningAvatar->getSkeleton().joint[AVATAR_JOINT_NECK_BASE].position;
const glm::vec3 OLD_SKELETON_MODEL_TRANSLATION(0.0f, -60.0f, 40.0f);
modelTranslation = OLD_SKELETON_MODEL_TRANSLATION;
neckPosition = owningAvatar->getPosition();
}
setTranslation(neckPosition);
glm::quat neckRotation;
if (!owningAvatar->getSkeletonModel().getNeckRotation(neckRotation)) {
neckRotation = owningAvatar->getSkeleton().joint[AVATAR_JOINT_NECK_BASE].absoluteRotation *
glm::angleAxis(180.0f, 0.0f, 1.0f, 0.0f);
neckRotation = owningAvatar->getOrientation();
}
setRotation(neckRotation);
const float MODEL_SCALE = 0.0006f;
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE);
setOffset(modelTranslation - _geometry->getFBXGeometry().neckPivot);
setOffset(-_geometry->getFBXGeometry().neckPivot);
setPupilDilation(_owningHead->getPupilDilation());
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());

View file

@ -102,21 +102,8 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
// calculate speed
_speed = glm::length(_velocity);
// update torso rotation based on head lean
_skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3(
_head.getLeanForward(), 0.0f, _head.getLeanSideways())));
// apply joint data (if any) to skeleton
bool enableHandMovement = true;
for (vector<JointData>::iterator it = _joints.begin(); it != _joints.end(); it++) {
_skeleton.joint[it->jointID].rotation = it->rotation;
// disable hand movement if we have joint info for the right wrist
enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST);
}
// update the movement of the hand and process handshaking with other avatars...
updateHandMovementAndTouching(deltaTime, enableHandMovement);
updateHandMovementAndTouching(deltaTime);
// apply gravity
// For gravity, always move the avatar by the amount driven by gravity, so that the collision
@ -267,7 +254,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
_position += _velocity * deltaTime;
// update avatar skeleton and simulate hand and head
_skeleton.update(deltaTime, getOrientation(), _position);
_hand.simulate(deltaTime, true);
_skeletonModel.simulate(deltaTime);
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
@ -331,21 +317,6 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) {
// apply face data
_head.getVideoFace().setFrameFromWebcam();
// compute and store the joint rotations
const JointVector& joints = webcam->getEstimatedJoints();
_joints.clear();
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
if (joints.size() > i && joints[i].isValid) {
JointData data = { i, joints[i].rotation };
_joints.push_back(data);
if (i == AVATAR_JOINT_CHEST) {
// if we have a chest rotation, don't apply lean based on head
estimatedPosition = glm::vec3();
}
}
}
} else {
_head.getVideoFace().clearFrame();
}
@ -547,12 +518,6 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const {
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, _pelvisToHeadLength, 0.0f);
}
glm::vec3 MyAvatar::getEyeLevelPosition() const {
const float EYE_UP_OFFSET = 0.36f;
return _position + getWorldAlignedOrientation() * _skeleton.joint[AVATAR_JOINT_TORSO].rotation *
glm::vec3(0.0f, _pelvisToHeadLength + _scale * BODY_BALL_RADIUS_HEAD_BASE * EYE_UP_OFFSET, 0.0f);
}
void MyAvatar::renderBody(bool forceRenderHead) {
if (_head.getVideoFace().isFullFrame()) {
@ -690,7 +655,7 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
_isThrustOn = (glm::length(_thrust) > EPSILON);
}
void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovement) {
void MyAvatar::updateHandMovementAndTouching(float deltaTime) {
glm::quat orientation = getOrientation();
@ -698,7 +663,7 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMov
glm::vec3 up = orientation * IDENTITY_UP;
bool pointing = false;
if (enableHandMovement && glm::length(_mouseRayDirection) > EPSILON && !Application::getInstance()->isMouseHidden()) {
if (glm::length(_mouseRayDirection) > EPSILON && !Application::getInstance()->isMouseHidden()) {
// confine to the approximate shoulder plane
glm::vec3 pointDirection = _mouseRayDirection;
if (glm::dot(_mouseRayDirection, up) > 0.0f) {

View file

@ -53,7 +53,6 @@ public:
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
glm::vec3 getGravity() const { return _gravity; }
glm::vec3 getUprightHeadPosition() const;
glm::vec3 getEyeLevelPosition() const;
// get/set avatar data
void saveData(QSettings* settings);
@ -92,7 +91,7 @@ private:
// private methods
void renderBody(bool forceRenderHead);
void updateThrust(float deltaTime, Transmitter * transmitter);
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
void updateHandMovementAndTouching(float deltaTime);
void updateAvatarCollisions(float deltaTime);
void updateCollisionWithEnvironment(float deltaTime);
void updateCollisionWithVoxels(float deltaTime);

View file

@ -1,201 +0,0 @@
//
// Skeleton.cpp
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "Skeleton.h"
#include "Util.h"
#include "world.h"
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f;
const float FLOATING_HEIGHT = 0.13f;
const glm::vec3 AVATAR_JOINT_POSITION_PELVIS = glm::vec3(0.0, 0.0, 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_TORSO = glm::vec3( 0.0, 0.09, -0.01);
const glm::vec3 AVATAR_JOINT_POSITION_CHEST = glm::vec3( 0.0, 0.09, -0.01);
const glm::vec3 AVATAR_JOINT_POSITION_NECK_BASE = glm::vec3( 0.0, 0.14, 0.01);
const glm::vec3 AVATAR_JOINT_POSITION_HEAD_BASE = glm::vec3( 0.0, 0.04, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_HEAD_TOP = glm::vec3( 0.0, 0.04, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_COLLAR = glm::vec3(-0.06, 0.04, 0.01);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_SHOULDER = glm::vec3(-0.05, 0.0 , 0.01);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_ELBOW = glm::vec3(-0.16, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_WRIST = glm::vec3(-0.12, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_FINGERTIPS = glm::vec3(-0.1, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_COLLAR = glm::vec3( 0.06, 0.04, 0.01);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_SHOULDER = glm::vec3( 0.05, 0.0 , 0.01);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_ELBOW = glm::vec3( 0.16, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_WRIST = glm::vec3( 0.12, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_FINGERTIPS = glm::vec3( 0.1, 0.0 , 0.0 );
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_HIP = glm::vec3(-0.05, 0.0 , 0.02);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_KNEE = glm::vec3( 0.00, -0.25, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_HEEL = glm::vec3( 0.00, -0.23, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_LEFT_TOES = glm::vec3( 0.00, 0.00, -0.06);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_HIP = glm::vec3( 0.05, 0.0 , 0.02);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_KNEE = glm::vec3( 0.00, -0.25, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_HEEL = glm::vec3( 0.00, -0.23, 0.00);
const glm::vec3 AVATAR_JOINT_POSITION_RIGHT_TOES = glm::vec3( 0.00, 0.00, -0.06);
Skeleton::Skeleton() : _floatingHeight(FLOATING_HEIGHT){
}
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].rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
joint[b].length = 0.0;
joint[b].bindRadius = 1.0f / 8;
}
// put the arms at the side
joint[AVATAR_JOINT_LEFT_ELBOW].rotation = glm::quat(glm::vec3(0.0f, 0.0f, PIf * 0.5f));
joint[AVATAR_JOINT_RIGHT_ELBOW].rotation = glm::quat(glm::vec3(0.0f, 0.0f, -PIf * 0.5f));
// bend the knees
joint[AVATAR_JOINT_LEFT_KNEE].rotation = joint[AVATAR_JOINT_RIGHT_KNEE].rotation =
glm::quat(glm::vec3(PIf / 8.0f, 0.0f, 0.0f));
joint[AVATAR_JOINT_LEFT_HEEL].rotation = joint[AVATAR_JOINT_RIGHT_HEEL].rotation =
glm::quat(glm::vec3(-PIf / 4.0f, 0.0f, 0.0f));
// specify the parental hierarchy
joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL;
joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO;
joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE;
joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE;
joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR;
joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER;
joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW;
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST;
joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST;
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR;
joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER;
joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW;
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST;
joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP;
joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE;
joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL;
joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS;
joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP;
joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
setScale(1.0f);
}
void Skeleton::setScale(float scale) {
// specify the bind pose position
joint[ AVATAR_JOINT_PELVIS ].bindPosePosition = scale * AVATAR_JOINT_POSITION_PELVIS;
joint[ AVATAR_JOINT_TORSO ].bindPosePosition = scale * AVATAR_JOINT_POSITION_TORSO;
joint[ AVATAR_JOINT_CHEST ].bindPosePosition = scale * AVATAR_JOINT_POSITION_CHEST;
joint[ AVATAR_JOINT_NECK_BASE ].bindPosePosition = scale * AVATAR_JOINT_POSITION_NECK_BASE;
joint[ AVATAR_JOINT_HEAD_BASE ].bindPosePosition = scale * AVATAR_JOINT_POSITION_HEAD_BASE;
joint[ AVATAR_JOINT_HEAD_TOP ].bindPosePosition = scale * AVATAR_JOINT_POSITION_HEAD_TOP;
joint[ AVATAR_JOINT_LEFT_COLLAR ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_COLLAR;
joint[ AVATAR_JOINT_LEFT_SHOULDER ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_SHOULDER;
joint[ AVATAR_JOINT_LEFT_ELBOW ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_ELBOW;
joint[ AVATAR_JOINT_LEFT_WRIST ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_WRIST;
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_FINGERTIPS;
joint[ AVATAR_JOINT_RIGHT_COLLAR ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_COLLAR;
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_SHOULDER;
joint[ AVATAR_JOINT_RIGHT_ELBOW ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_ELBOW;
joint[ AVATAR_JOINT_RIGHT_WRIST ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_WRIST;
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_FINGERTIPS;
joint[ AVATAR_JOINT_LEFT_HIP ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_HIP;
joint[ AVATAR_JOINT_LEFT_KNEE ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_KNEE;
joint[ AVATAR_JOINT_LEFT_HEEL ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_HEEL;
joint[ AVATAR_JOINT_LEFT_TOES ].bindPosePosition = scale * AVATAR_JOINT_POSITION_LEFT_TOES;
joint[ AVATAR_JOINT_RIGHT_HIP ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_HIP;
joint[ AVATAR_JOINT_RIGHT_KNEE ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_KNEE;
joint[ AVATAR_JOINT_RIGHT_HEEL ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_HEEL;
joint[ AVATAR_JOINT_RIGHT_TOES ].bindPosePosition = scale * AVATAR_JOINT_POSITION_RIGHT_TOES;
// calculate bone length, absolute bind positions/rotations
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
joint[b].length = glm::length(joint[b].bindPosePosition);
if (joint[b].parent == AVATAR_JOINT_NULL) {
joint[b].absoluteBindPosePosition = joint[b].bindPosePosition;
joint[b].absoluteBindPoseRotation = glm::quat();
} else {
joint[b].absoluteBindPosePosition = joint[ joint[b].parent ].absoluteBindPosePosition +
joint[b].bindPosePosition;
glm::vec3 parentDirection = joint[ joint[b].parent ].absoluteBindPoseRotation * JOINT_DIRECTION;
joint[b].absoluteBindPoseRotation = rotationBetween(parentDirection, joint[b].bindPosePosition) *
joint[ joint[b].parent ].absoluteBindPoseRotation;
}
}
_floatingHeight = scale * FLOATING_HEIGHT;
}
// calculate positions and rotations of all bones by traversing the skeleton tree:
void Skeleton::update(float deltaTime, const glm::quat& orientation, glm::vec3 position) {
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
if (joint[b].parent == AVATAR_JOINT_NULL) {
joint[b].absoluteRotation = orientation * joint[b].rotation;
joint[b].position = position;
}
else {
joint[b].absoluteRotation = joint[ joint[b].parent ].absoluteRotation * joint[b].rotation;
joint[b].position = joint[ joint[b].parent ].position;
}
glm::vec3 rotatedJointVector = joint[b].absoluteRotation * joint[b].bindPosePosition;
joint[b].position += rotatedJointVector;
}
}
float Skeleton::getArmLength() {
return joint[ AVATAR_JOINT_RIGHT_ELBOW ].length
+ joint[ AVATAR_JOINT_RIGHT_WRIST ].length
+ joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length;
}
float Skeleton::getHeight() {
return
joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length +
joint[ AVATAR_JOINT_PELVIS ].length +
joint[ AVATAR_JOINT_TORSO ].length +
joint[ AVATAR_JOINT_CHEST ].length +
joint[ AVATAR_JOINT_NECK_BASE ].length +
joint[ AVATAR_JOINT_HEAD_BASE ].length;
}
float Skeleton::getPelvisStandingHeight() {
return joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length;
}
float Skeleton::getPelvisFloatingHeight() {
return joint[ AVATAR_JOINT_LEFT_HEEL ].length +
joint[ AVATAR_JOINT_LEFT_KNEE ].length +
_floatingHeight;
}
float Skeleton::getPelvisToHeadLength() {
return
joint[ AVATAR_JOINT_TORSO ].length +
joint[ AVATAR_JOINT_CHEST ].length +
joint[ AVATAR_JOINT_NECK_BASE ].length +
joint[ AVATAR_JOINT_HEAD_BASE ].length;
}

View file

@ -1,80 +0,0 @@
//
// Skeleton.h
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef hifi_Skeleton_h
#define hifi_Skeleton_h
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
enum AvatarJointID
{
AVATAR_JOINT_NULL = -1,
AVATAR_JOINT_PELVIS,
AVATAR_JOINT_TORSO,
AVATAR_JOINT_CHEST,
AVATAR_JOINT_NECK_BASE,
AVATAR_JOINT_HEAD_BASE,
AVATAR_JOINT_HEAD_TOP,
AVATAR_JOINT_LEFT_COLLAR,
AVATAR_JOINT_LEFT_SHOULDER,
AVATAR_JOINT_LEFT_ELBOW,
AVATAR_JOINT_LEFT_WRIST,
AVATAR_JOINT_LEFT_FINGERTIPS,
AVATAR_JOINT_RIGHT_COLLAR,
AVATAR_JOINT_RIGHT_SHOULDER,
AVATAR_JOINT_RIGHT_ELBOW,
AVATAR_JOINT_RIGHT_WRIST,
AVATAR_JOINT_RIGHT_FINGERTIPS,
AVATAR_JOINT_LEFT_HIP,
AVATAR_JOINT_LEFT_KNEE,
AVATAR_JOINT_LEFT_HEEL,
AVATAR_JOINT_LEFT_TOES,
AVATAR_JOINT_RIGHT_HIP,
AVATAR_JOINT_RIGHT_KNEE,
AVATAR_JOINT_RIGHT_HEEL,
AVATAR_JOINT_RIGHT_TOES,
NUM_AVATAR_JOINTS
};
const glm::vec3 JOINT_DIRECTION = glm::vec3(0.0f, 1.0f, 0.0f);
class Skeleton {
public:
Skeleton();
void initialize();
void setScale(float scale);
void update(float deltaTime, const glm::quat&, glm::vec3 position);
void render();
float getArmLength();
float getHeight();
float getPelvisStandingHeight();
float getPelvisFloatingHeight();
float getPelvisToHeadLength();
//glm::vec3 getJointVectorFromParent(AvatarJointID jointID) {return joint[jointID].position - joint[joint[jointID].parent].position; }
struct AvatarJoint
{
AvatarJointID parent; // which joint is this joint connected to?
glm::vec3 position; // the position at the "end" of the joint - in global space
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
glm::quat absoluteRotation; // the absolute rotation of the joint as a quaternion
float length; // the length of vector connecting the joint and its parent
};
AvatarJoint joint[ NUM_AVATAR_JOINTS ];
float _floatingHeight;
};
#endif

View file

@ -29,12 +29,11 @@ using namespace xn;
#endif
// register types with Qt metatype system
int jointVectorMetaType = qRegisterMetaType<JointVector>("JointVector");
int keyPointVectorMetaType = qRegisterMetaType<KeyPointVector>("KeyPointVector");
int matMetaType = qRegisterMetaType<Mat>("cv::Mat");
int rotatedRectMetaType = qRegisterMetaType<RotatedRect>("cv::RotatedRect");
Webcam::Webcam() : _enabled(false), _active(false), _colorTextureID(0), _depthTextureID(0), _skeletonTrackingOn(false) {
Webcam::Webcam() : _enabled(false), _active(false), _colorTextureID(0), _depthTextureID(0) {
// the grabber simply runs as fast as possible
_grabber = new FrameGrabber();
_grabber->moveToThread(&_grabberThread);
@ -111,20 +110,6 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
if (!_joints.isEmpty()) {
glColor3f(1.0f, 0.0f, 0.0f);
glPointSize(4.0f);
glBegin(GL_POINTS);
float projectedScale = PREVIEW_HEIGHT / _textureSize.height;
foreach (const Joint& joint, _joints) {
if (joint.isValid) {
glVertex2f(left + joint.projected.x * projectedScale,
top - PREVIEW_HEIGHT + joint.projected.y * projectedScale);
}
}
glEnd();
glPointSize(1.0f);
}
} else {
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
@ -238,7 +223,7 @@ static float computeTransformFromKeyPoints(const KeyPointVector& keyPoints, glm:
const float METERS_PER_MM = 1.0f / 1000.0f;
void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midFaceDepth, float aspectRatio,
const RotatedRect& faceRect, bool sending, const JointVector& joints, const KeyPointVector& keyPoints) {
const RotatedRect& faceRect, bool sending, const KeyPointVector& keyPoints) {
if (!_enabled) {
return; // was queued before we shut down; ignore
}
@ -289,7 +274,6 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midF
_aspectRatio = aspectRatio;
_faceRect = faceRect;
_sending = sending;
_joints = _skeletonTrackingOn ? joints : JointVector();
_keyPoints = keyPoints;
_frameCount++;
@ -304,32 +288,8 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midF
}
_lastFrameTimestamp = now;
// see if we have joint data
if (!_joints.isEmpty()) {
_estimatedJoints.resize(NUM_AVATAR_JOINTS);
glm::vec3 origin;
if (_joints[AVATAR_JOINT_LEFT_HIP].isValid && _joints[AVATAR_JOINT_RIGHT_HIP].isValid) {
origin = glm::mix(_joints[AVATAR_JOINT_LEFT_HIP].position, _joints[AVATAR_JOINT_RIGHT_HIP].position, 0.5f);
} else if (_joints[AVATAR_JOINT_TORSO].isValid) {
const glm::vec3 TORSO_TO_PELVIS = glm::vec3(0.0f, -0.09f, -0.01f);
origin = _joints[AVATAR_JOINT_TORSO].position + TORSO_TO_PELVIS;
}
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
if (!_joints[i].isValid) {
continue;
}
const float JOINT_SMOOTHING = 0.5f;
_estimatedJoints[i].isValid = true;
_estimatedJoints[i].position = glm::mix(_joints[i].position - origin,
_estimatedJoints[i].position, JOINT_SMOOTHING);
_estimatedJoints[i].rotation = safeMix(_joints[i].rotation,
_estimatedJoints[i].rotation, JOINT_SMOOTHING);
}
_estimatedRotation = safeEulerAngles(_estimatedJoints[AVATAR_JOINT_HEAD_BASE].rotation);
_estimatedPosition = _estimatedJoints[AVATAR_JOINT_HEAD_BASE].position;
} else if (!keyPoints.empty()) {
// see if we have key points
if (!keyPoints.empty()) {
glm::quat rotation;
glm::vec3 position;
float scale = computeTransformFromKeyPoints(keyPoints, rotation, position);
@ -415,51 +375,6 @@ FrameGrabber::~FrameGrabber() {
}
#ifdef HAVE_OPENNI
static AvatarJointID xnToAvatarJoint(XnSkeletonJoint joint) {
switch (joint) {
case XN_SKEL_HEAD: return AVATAR_JOINT_HEAD_TOP;
case XN_SKEL_NECK: return AVATAR_JOINT_HEAD_BASE;
case XN_SKEL_TORSO: return AVATAR_JOINT_CHEST;
case XN_SKEL_LEFT_SHOULDER: return AVATAR_JOINT_RIGHT_ELBOW;
case XN_SKEL_LEFT_ELBOW: return AVATAR_JOINT_RIGHT_WRIST;
case XN_SKEL_RIGHT_SHOULDER: return AVATAR_JOINT_LEFT_ELBOW;
case XN_SKEL_RIGHT_ELBOW: return AVATAR_JOINT_LEFT_WRIST;
case XN_SKEL_LEFT_HIP: return AVATAR_JOINT_RIGHT_KNEE;
case XN_SKEL_LEFT_KNEE: return AVATAR_JOINT_RIGHT_HEEL;
case XN_SKEL_LEFT_FOOT: return AVATAR_JOINT_RIGHT_TOES;
case XN_SKEL_RIGHT_HIP: return AVATAR_JOINT_LEFT_KNEE;
case XN_SKEL_RIGHT_KNEE: return AVATAR_JOINT_LEFT_HEEL;
case XN_SKEL_RIGHT_FOOT: return AVATAR_JOINT_LEFT_TOES;
default: return AVATAR_JOINT_NULL;
}
}
static int getParentJoint(XnSkeletonJoint joint) {
switch (joint) {
case XN_SKEL_HEAD: return XN_SKEL_NECK;
case XN_SKEL_TORSO: return -1;
case XN_SKEL_LEFT_ELBOW: return XN_SKEL_LEFT_SHOULDER;
case XN_SKEL_LEFT_HAND: return XN_SKEL_LEFT_ELBOW;
case XN_SKEL_RIGHT_ELBOW: return XN_SKEL_RIGHT_SHOULDER;
case XN_SKEL_RIGHT_HAND: return XN_SKEL_RIGHT_ELBOW;
case XN_SKEL_LEFT_KNEE: return XN_SKEL_LEFT_HIP;
case XN_SKEL_LEFT_FOOT: return XN_SKEL_LEFT_KNEE;
case XN_SKEL_RIGHT_KNEE: return XN_SKEL_RIGHT_HIP;
case XN_SKEL_RIGHT_FOOT: return XN_SKEL_RIGHT_KNEE;
default: return XN_SKEL_TORSO;
}
}
static glm::vec3 xnToGLM(const XnVector3D& vector, bool flip = false) {
return glm::vec3(vector.X * (flip ? -1 : 1), vector.Y, vector.Z);
}
@ -471,31 +386,6 @@ static glm::quat xnToGLM(const XnMatrix3X3& matrix) {
matrix.elements[6], matrix.elements[7], matrix.elements[8]));
return glm::quat(rotation.w, -rotation.x, rotation.y, rotation.z);
}
static void XN_CALLBACK_TYPE newUser(UserGenerator& generator, XnUserID id, void* cookie) {
qDebug("Found user %d.", id);
generator.GetSkeletonCap().RequestCalibration(id, false);
}
static void XN_CALLBACK_TYPE lostUser(UserGenerator& generator, XnUserID id, void* cookie) {
qDebug("Lost user %d.", id);
}
static void XN_CALLBACK_TYPE calibrationStarted(SkeletonCapability& capability, XnUserID id, void* cookie) {
qDebug("Calibration started for user %d.", id);
}
static void XN_CALLBACK_TYPE calibrationCompleted(SkeletonCapability& capability,
XnUserID id, XnCalibrationStatus status, void* cookie) {
if (status == XN_CALIBRATION_STATUS_OK) {
qDebug("Calibration completed for user %d.", id);
capability.StartTracking(id);
} else {
qDebug("Calibration failed to user %d.", id);
capability.RequestCalibration(id, true);
}
}
#endif
void FrameGrabber::cycleVideoSendMode() {
@ -517,12 +407,6 @@ void FrameGrabber::setLEDTrackingOn(bool ledTrackingOn) {
void FrameGrabber::reset() {
_searchWindow = cv::Rect(0, 0, 0, 0);
#ifdef HAVE_OPENNI
if (_userGenerator.IsValid() && _userGenerator.GetSkeletonCap().IsTracking(_userID)) {
_userGenerator.GetSkeletonCap().RequestCalibration(_userID, true);
}
#endif
}
void FrameGrabber::shutdown() {
@ -551,7 +435,6 @@ void FrameGrabber::grabFrame() {
}
int format = GL_BGR;
Mat color, depth;
JointVector joints;
#ifdef HAVE_OPENNI
if (_depthGenerator.IsValid()) {
@ -560,37 +443,6 @@ void FrameGrabber::grabFrame() {
format = GL_RGB;
depth = Mat(_depthMetaData.YRes(), _depthMetaData.XRes(), CV_16UC1, (void*)_depthGenerator.GetDepthMap());
_userID = 0;
XnUInt16 userCount = 1;
_userGenerator.GetUsers(&_userID, userCount);
if (userCount > 0 && _userGenerator.GetSkeletonCap().IsTracking(_userID)) {
joints.resize(NUM_AVATAR_JOINTS);
const int MAX_ACTIVE_JOINTS = 16;
XnSkeletonJoint activeJoints[MAX_ACTIVE_JOINTS];
XnUInt16 activeJointCount = MAX_ACTIVE_JOINTS;
_userGenerator.GetSkeletonCap().EnumerateActiveJoints(activeJoints, activeJointCount);
XnSkeletonJointTransformation transform;
for (int i = 0; i < activeJointCount; i++) {
AvatarJointID avatarJoint = xnToAvatarJoint(activeJoints[i]);
if (avatarJoint == AVATAR_JOINT_NULL) {
continue;
}
_userGenerator.GetSkeletonCap().GetSkeletonJoint(_userID, activeJoints[i], transform);
XnVector3D projected;
_depthGenerator.ConvertRealWorldToProjective(1, &transform.position.position, &projected);
glm::quat rotation = xnToGLM(transform.orientation.orientation);
int parentJoint = getParentJoint(activeJoints[i]);
if (parentJoint != -1) {
XnSkeletonJointOrientation parentOrientation;
_userGenerator.GetSkeletonCap().GetSkeletonJointOrientation(
_userID, (XnSkeletonJoint)parentJoint, parentOrientation);
rotation = glm::inverse(xnToGLM(parentOrientation.orientation)) * rotation;
}
joints[avatarJoint] = Joint(xnToGLM(transform.position.position, true) * METERS_PER_MM,
rotation, xnToGLM(projected));
}
}
}
#endif
@ -929,7 +781,7 @@ void FrameGrabber::grabFrame() {
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
Q_ARG(cv::Mat, color), Q_ARG(int, format), Q_ARG(cv::Mat, _grayDepthFrame), Q_ARG(float, _smoothedMidFaceDepth),
Q_ARG(float, aspectRatio), Q_ARG(cv::RotatedRect, _smoothedFaceRect), Q_ARG(bool, !payload.isEmpty()),
Q_ARG(JointVector, joints), Q_ARG(KeyPointVector, keyPoints));
Q_ARG(KeyPointVector, keyPoints));
}
bool FrameGrabber::init() {
@ -945,20 +797,11 @@ bool FrameGrabber::init() {
// first try for a Kinect
#ifdef HAVE_OPENNI
_xnContext.Init();
if (_depthGenerator.Create(_xnContext) == XN_STATUS_OK && _imageGenerator.Create(_xnContext) == XN_STATUS_OK &&
_userGenerator.Create(_xnContext) == XN_STATUS_OK &&
_userGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON)) {
if (_depthGenerator.Create(_xnContext) == XN_STATUS_OK && _imageGenerator.Create(_xnContext) == XN_STATUS_OK) {
_depthGenerator.GetMetaData(_depthMetaData);
_imageGenerator.SetPixelFormat(XN_PIXEL_FORMAT_RGB24);
_imageGenerator.GetMetaData(_imageMetaData);
XnCallbackHandle userCallbacks, calibrationStartCallback, calibrationCompleteCallback;
_userGenerator.RegisterUserCallbacks(newUser, lostUser, 0, userCallbacks);
_userGenerator.GetSkeletonCap().RegisterToCalibrationStart(calibrationStarted, 0, calibrationStartCallback);
_userGenerator.GetSkeletonCap().RegisterToCalibrationComplete(calibrationCompleted, 0, calibrationCompleteCallback);
_userGenerator.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_UPPER);
// make the depth viewpoint match that of the video image
if (_depthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT)) {
_depthGenerator.GetAlternativeViewPointCap().SetViewPoint(_imageGenerator);
@ -1018,10 +861,3 @@ void FrameGrabber::destroyCodecs() {
_depthCodec.name = 0;
}
}
Joint::Joint(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& projected) :
isValid(true), position(position), rotation(rotation), projected(projected) {
}
Joint::Joint() : isValid(false) {
}

View file

@ -31,9 +31,7 @@ class QImage;
struct CvCapture;
class FrameGrabber;
class Joint;
typedef QVector<Joint> JointVector;
typedef std::vector<cv::KeyPoint> KeyPointVector;
/// Handles interaction with the webcam (including depth cameras such as the Kinect).
@ -61,7 +59,6 @@ public:
const glm::vec3& getEstimatedPosition() const { return _estimatedPosition; }
const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }
const JointVector& getEstimatedJoints() const { return _estimatedJoints; }
void reset();
void renderPreview(int screenWidth, int screenHeight);
@ -70,8 +67,7 @@ public slots:
void setEnabled(bool enabled);
void setFrame(const cv::Mat& color, int format, const cv::Mat& depth, float midFaceDepth, float aspectRatio,
const cv::RotatedRect& faceRect, bool sending, const JointVector& joints, const KeyPointVector& keyPoints);
void setSkeletonTrackingOn(bool toggle) { _skeletonTrackingOn = toggle; };
const cv::RotatedRect& faceRect, bool sending, const KeyPointVector& keyPoints);
private:
@ -88,7 +84,6 @@ private:
cv::RotatedRect _faceRect;
cv::RotatedRect _initialFaceRect;
float _initialFaceDepth;
JointVector _joints;
KeyPointVector _keyPoints;
glm::quat _initialLEDRotation;
@ -102,9 +97,6 @@ private:
glm::vec3 _estimatedPosition;
glm::vec3 _estimatedRotation;
JointVector _estimatedJoints;
bool _skeletonTrackingOn;
};
/// Acquires and processes video frames in a dedicated thread.
@ -164,27 +156,11 @@ private:
xn::Context _xnContext;
xn::DepthGenerator _depthGenerator;
xn::ImageGenerator _imageGenerator;
xn::UserGenerator _userGenerator;
xn::DepthMetaData _depthMetaData;
xn::ImageMetaData _imageMetaData;
XnUserID _userID;
#endif
};
/// Contains the 3D transform and 2D projected position of a tracked joint.
class Joint {
public:
Joint(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& projected);
Joint();
bool isValid;
glm::vec3 position;
glm::quat rotation;
glm::vec3 projected;
};
Q_DECLARE_METATYPE(JointVector)
Q_DECLARE_METATYPE(KeyPointVector)
Q_DECLARE_METATYPE(cv::Mat)
Q_DECLARE_METATYPE(cv::RotatedRect)