mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 05:03:31 +02:00
Skeleton removal checkpoint; compiles, but there are a few bits missing.
This commit is contained in:
parent
7be1d4d8c0
commit
2c7b6b9696
13 changed files with 25 additions and 587 deletions
|
@ -2349,7 +2349,7 @@ void Application::updateTransmitter(float deltaTime) {
|
||||||
|
|
||||||
// no transmitter drive implies transmitter pick
|
// no transmitter drive implies transmitter pick
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) {
|
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::vec3 direction = _myAvatar.getOrientation() *
|
||||||
glm::quat(glm::radians(_myTransmitter.getEstimatedRotation())) * IDENTITY_FRONT;
|
glm::quat(glm::radians(_myTransmitter.getEstimatedRotation())) * IDENTITY_FRONT;
|
||||||
|
|
||||||
|
|
|
@ -383,13 +383,6 @@ Menu::Menu() :
|
||||||
|
|
||||||
|
|
||||||
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
||||||
addCheckableActionToQMenuAndActionHash(trackingOptionsMenu,
|
|
||||||
MenuOption::SkeletonTracking,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
appInstance->getWebcam(),
|
|
||||||
SLOT(setSkeletonTrackingOn(bool)));
|
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(trackingOptionsMenu,
|
addCheckableActionToQMenuAndActionHash(trackingOptionsMenu,
|
||||||
MenuOption::LEDTracking,
|
MenuOption::LEDTracking,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -246,7 +246,6 @@ namespace MenuOption {
|
||||||
const QString SimulateLeapHand = "Simulate Leap Hand";
|
const QString SimulateLeapHand = "Simulate Leap Hand";
|
||||||
const QString VoxelDrumming = "Voxel Drumming";
|
const QString VoxelDrumming = "Voxel Drumming";
|
||||||
const QString PlaySlaps = "Play Slaps";
|
const QString PlaySlaps = "Play Slaps";
|
||||||
const QString SkeletonTracking = "Skeleton Tracking";
|
|
||||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||||
const QString LEDTracking = "LED Tracking";
|
const QString LEDTracking = "LED Tracking";
|
||||||
const QString Stars = "Stars";
|
const QString Stars = "Stars";
|
||||||
|
|
|
@ -97,9 +97,7 @@ Avatar::Avatar(Node* owningNode) :
|
||||||
_isCollisionsOn(true),
|
_isCollisionsOn(true),
|
||||||
_moving(false),
|
_moving(false),
|
||||||
_initialized(false),
|
_initialized(false),
|
||||||
_handHoldingPosition(0.0f, 0.0f, 0.0f),
|
_handHoldingPosition(0.0f, 0.0f, 0.0f)
|
||||||
_maxArmLength(0.0f),
|
|
||||||
_pelvisStandingHeight(0.0f)
|
|
||||||
{
|
{
|
||||||
// we may have been created in the network thread, but we live in the main thread
|
// we may have been created in the network thread, but we live in the main thread
|
||||||
moveToThread(Application::getInstance()->thread());
|
moveToThread(Application::getInstance()->thread());
|
||||||
|
@ -108,14 +106,10 @@ Avatar::Avatar(Node* owningNode) :
|
||||||
_headData = &_head;
|
_headData = &_head;
|
||||||
_handData = &_hand;
|
_handData = &_hand;
|
||||||
|
|
||||||
_skeleton.initialize();
|
_height = 0.0f; // _skeleton.getHeight();
|
||||||
|
|
||||||
_height = _skeleton.getHeight();
|
_pelvisFloatingHeight = 0.0f; // _skeleton.getPelvisFloatingHeight();
|
||||||
|
_pelvisToHeadLength = 0.0f; // _skeleton.getPelvisToHeadLength();
|
||||||
_maxArmLength = _skeleton.getArmLength();
|
|
||||||
_pelvisStandingHeight = _skeleton.getPelvisStandingHeight();
|
|
||||||
_pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight();
|
|
||||||
_pelvisToHeadLength = _skeleton.getPelvisToHeadLength();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,22 +147,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
// copy velocity so we can use it later for acceleration
|
// copy velocity so we can use it later for acceleration
|
||||||
glm::vec3 oldVelocity = getVelocity();
|
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);
|
_hand.simulate(deltaTime, false);
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
|
@ -444,13 +422,9 @@ void Avatar::setScale(const float scale) {
|
||||||
_scale = _targetScale;
|
_scale = _targetScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
_skeleton.setScale(_scale);
|
_height = 0.0f; // _skeleton.getHeight();
|
||||||
|
|
||||||
_height = _skeleton.getHeight();
|
_pelvisFloatingHeight = 0.0f; // _skeleton.getPelvisFloatingHeight();
|
||||||
|
_pelvisToHeadLength = 0.0f; // _skeleton.getPelvisToHeadLength();
|
||||||
_maxArmLength = _skeleton.getArmLength();
|
|
||||||
_pelvisStandingHeight = _skeleton.getPelvisStandingHeight();
|
|
||||||
_pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight();
|
|
||||||
_pelvisToHeadLength = _skeleton.getPelvisToHeadLength();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "Hand.h"
|
#include "Hand.h"
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "Skeleton.h"
|
|
||||||
#include "SkeletonModel.h"
|
#include "SkeletonModel.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "devices/Transmitter.h"
|
#include "devices/Transmitter.h"
|
||||||
|
@ -142,11 +141,10 @@ public:
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
bool isInitialized() const { return _initialized; }
|
bool isInitialized() const { return _initialized; }
|
||||||
const Skeleton& getSkeleton() const { return _skeleton; }
|
|
||||||
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
SkeletonModel& getSkeletonModel() { return _skeletonModel; }
|
||||||
float getHeadYawRate() const { return _head.yawRate; }
|
float getHeadYawRate() const { return _head.yawRate; }
|
||||||
const glm::vec3& getHeadJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position; }
|
const glm::vec3& getHeadJointPosition() const { return _position; }
|
||||||
const glm::vec3& getChestJointPosition() const { return _skeleton.joint[ AVATAR_JOINT_CHEST ].position; }
|
const glm::vec3& getChestJointPosition() const { return _position; }
|
||||||
float getScale() const { return _scale; }
|
float getScale() const { return _scale; }
|
||||||
const glm::vec3& getVelocity() const { return _velocity; }
|
const glm::vec3& getVelocity() const { return _velocity; }
|
||||||
Head& getHead() { return _head; }
|
Head& getHead() { return _head; }
|
||||||
|
@ -182,23 +180,8 @@ public slots:
|
||||||
|
|
||||||
|
|
||||||
protected:
|
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;
|
Head _head;
|
||||||
Hand _hand;
|
Hand _hand;
|
||||||
Skeleton _skeleton;
|
|
||||||
SkeletonModel _skeletonModel;
|
SkeletonModel _skeletonModel;
|
||||||
bool _ballSpringsInitialized;
|
bool _ballSpringsInitialized;
|
||||||
float _bodyYawDelta;
|
float _bodyYawDelta;
|
||||||
|
@ -234,8 +217,6 @@ private:
|
||||||
|
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
glm::vec3 _handHoldingPosition;
|
glm::vec3 _handHoldingPosition;
|
||||||
float _maxArmLength;
|
|
||||||
float _pelvisStandingHeight;
|
|
||||||
|
|
||||||
|
|
||||||
// private methods...
|
// private methods...
|
||||||
|
|
|
@ -24,22 +24,18 @@ void FaceModel::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
|
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
|
||||||
glm::vec3 neckPosition;
|
glm::vec3 neckPosition;
|
||||||
glm::vec3 modelTranslation;
|
|
||||||
if (!owningAvatar->getSkeletonModel().getNeckPosition(neckPosition)) {
|
if (!owningAvatar->getSkeletonModel().getNeckPosition(neckPosition)) {
|
||||||
neckPosition = owningAvatar->getSkeleton().joint[AVATAR_JOINT_NECK_BASE].position;
|
neckPosition = owningAvatar->getPosition();
|
||||||
const glm::vec3 OLD_SKELETON_MODEL_TRANSLATION(0.0f, -60.0f, 40.0f);
|
|
||||||
modelTranslation = OLD_SKELETON_MODEL_TRANSLATION;
|
|
||||||
}
|
}
|
||||||
setTranslation(neckPosition);
|
setTranslation(neckPosition);
|
||||||
glm::quat neckRotation;
|
glm::quat neckRotation;
|
||||||
if (!owningAvatar->getSkeletonModel().getNeckRotation(neckRotation)) {
|
if (!owningAvatar->getSkeletonModel().getNeckRotation(neckRotation)) {
|
||||||
neckRotation = owningAvatar->getSkeleton().joint[AVATAR_JOINT_NECK_BASE].absoluteRotation *
|
neckRotation = owningAvatar->getOrientation();
|
||||||
glm::angleAxis(180.0f, 0.0f, 1.0f, 0.0f);
|
|
||||||
}
|
}
|
||||||
setRotation(neckRotation);
|
setRotation(neckRotation);
|
||||||
const float MODEL_SCALE = 0.0006f;
|
const float MODEL_SCALE = 0.0006f;
|
||||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE);
|
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());
|
setPupilDilation(_owningHead->getPupilDilation());
|
||||||
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());
|
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());
|
||||||
|
|
|
@ -102,21 +102,8 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) {
|
||||||
// calculate speed
|
// calculate speed
|
||||||
_speed = glm::length(_velocity);
|
_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...
|
// update the movement of the hand and process handshaking with other avatars...
|
||||||
updateHandMovementAndTouching(deltaTime, enableHandMovement);
|
updateHandMovementAndTouching(deltaTime);
|
||||||
|
|
||||||
// apply gravity
|
// apply gravity
|
||||||
// For gravity, always move the avatar by the amount driven by gravity, so that the collision
|
// 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;
|
_position += _velocity * deltaTime;
|
||||||
|
|
||||||
// update avatar skeleton and simulate hand and head
|
// update avatar skeleton and simulate hand and head
|
||||||
_skeleton.update(deltaTime, getOrientation(), _position);
|
|
||||||
_hand.simulate(deltaTime, true);
|
_hand.simulate(deltaTime, true);
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
|
@ -331,21 +317,6 @@ void MyAvatar::updateFromGyrosAndOrWebcam(bool turnWithHead) {
|
||||||
|
|
||||||
// apply face data
|
// apply face data
|
||||||
_head.getVideoFace().setFrameFromWebcam();
|
_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 {
|
} else {
|
||||||
_head.getVideoFace().clearFrame();
|
_head.getVideoFace().clearFrame();
|
||||||
}
|
}
|
||||||
|
@ -547,12 +518,6 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const {
|
||||||
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, _pelvisToHeadLength, 0.0f);
|
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) {
|
void MyAvatar::renderBody(bool forceRenderHead) {
|
||||||
|
|
||||||
if (_head.getVideoFace().isFullFrame()) {
|
if (_head.getVideoFace().isFullFrame()) {
|
||||||
|
@ -690,7 +655,7 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
|
||||||
_isThrustOn = (glm::length(_thrust) > EPSILON);
|
_isThrustOn = (glm::length(_thrust) > EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMovement) {
|
void MyAvatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
|
|
||||||
glm::quat orientation = getOrientation();
|
glm::quat orientation = getOrientation();
|
||||||
|
|
||||||
|
@ -698,7 +663,7 @@ void MyAvatar::updateHandMovementAndTouching(float deltaTime, bool enableHandMov
|
||||||
glm::vec3 up = orientation * IDENTITY_UP;
|
glm::vec3 up = orientation * IDENTITY_UP;
|
||||||
|
|
||||||
bool pointing = false;
|
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
|
// confine to the approximate shoulder plane
|
||||||
glm::vec3 pointDirection = _mouseRayDirection;
|
glm::vec3 pointDirection = _mouseRayDirection;
|
||||||
if (glm::dot(_mouseRayDirection, up) > 0.0f) {
|
if (glm::dot(_mouseRayDirection, up) > 0.0f) {
|
||||||
|
|
|
@ -53,7 +53,6 @@ public:
|
||||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
||||||
glm::vec3 getGravity() const { return _gravity; }
|
glm::vec3 getGravity() const { return _gravity; }
|
||||||
glm::vec3 getUprightHeadPosition() const;
|
glm::vec3 getUprightHeadPosition() const;
|
||||||
glm::vec3 getEyeLevelPosition() const;
|
|
||||||
|
|
||||||
// get/set avatar data
|
// get/set avatar data
|
||||||
void saveData(QSettings* settings);
|
void saveData(QSettings* settings);
|
||||||
|
@ -92,7 +91,7 @@ private:
|
||||||
// private methods
|
// private methods
|
||||||
void renderBody(bool forceRenderHead);
|
void renderBody(bool forceRenderHead);
|
||||||
void updateThrust(float deltaTime, Transmitter * transmitter);
|
void updateThrust(float deltaTime, Transmitter * transmitter);
|
||||||
void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement);
|
void updateHandMovementAndTouching(float deltaTime);
|
||||||
void updateAvatarCollisions(float deltaTime);
|
void updateAvatarCollisions(float deltaTime);
|
||||||
void updateCollisionWithEnvironment(float deltaTime);
|
void updateCollisionWithEnvironment(float deltaTime);
|
||||||
void updateCollisionWithVoxels(float deltaTime);
|
void updateCollisionWithVoxels(float deltaTime);
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
|
@ -29,12 +29,11 @@ using namespace xn;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// register types with Qt metatype system
|
// register types with Qt metatype system
|
||||||
int jointVectorMetaType = qRegisterMetaType<JointVector>("JointVector");
|
|
||||||
int keyPointVectorMetaType = qRegisterMetaType<KeyPointVector>("KeyPointVector");
|
int keyPointVectorMetaType = qRegisterMetaType<KeyPointVector>("KeyPointVector");
|
||||||
int matMetaType = qRegisterMetaType<Mat>("cv::Mat");
|
int matMetaType = qRegisterMetaType<Mat>("cv::Mat");
|
||||||
int rotatedRectMetaType = qRegisterMetaType<RotatedRect>("cv::RotatedRect");
|
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
|
// the grabber simply runs as fast as possible
|
||||||
_grabber = new FrameGrabber();
|
_grabber = new FrameGrabber();
|
||||||
_grabber->moveToThread(&_grabberThread);
|
_grabber->moveToThread(&_grabberThread);
|
||||||
|
@ -111,20 +110,6 @@ void Webcam::renderPreview(int screenWidth, int screenHeight) {
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
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 {
|
} else {
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
@ -238,7 +223,7 @@ static float computeTransformFromKeyPoints(const KeyPointVector& keyPoints, glm:
|
||||||
const float METERS_PER_MM = 1.0f / 1000.0f;
|
const float METERS_PER_MM = 1.0f / 1000.0f;
|
||||||
|
|
||||||
void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midFaceDepth, float aspectRatio,
|
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) {
|
if (!_enabled) {
|
||||||
return; // was queued before we shut down; ignore
|
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;
|
_aspectRatio = aspectRatio;
|
||||||
_faceRect = faceRect;
|
_faceRect = faceRect;
|
||||||
_sending = sending;
|
_sending = sending;
|
||||||
_joints = _skeletonTrackingOn ? joints : JointVector();
|
|
||||||
_keyPoints = keyPoints;
|
_keyPoints = keyPoints;
|
||||||
_frameCount++;
|
_frameCount++;
|
||||||
|
|
||||||
|
@ -304,32 +288,8 @@ void Webcam::setFrame(const Mat& color, int format, const Mat& depth, float midF
|
||||||
}
|
}
|
||||||
_lastFrameTimestamp = now;
|
_lastFrameTimestamp = now;
|
||||||
|
|
||||||
// see if we have joint data
|
// see if we have key points
|
||||||
if (!_joints.isEmpty()) {
|
if (!keyPoints.empty()) {
|
||||||
_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()) {
|
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
float scale = computeTransformFromKeyPoints(keyPoints, rotation, position);
|
float scale = computeTransformFromKeyPoints(keyPoints, rotation, position);
|
||||||
|
@ -415,51 +375,6 @@ FrameGrabber::~FrameGrabber() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OPENNI
|
#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) {
|
static glm::vec3 xnToGLM(const XnVector3D& vector, bool flip = false) {
|
||||||
return glm::vec3(vector.X * (flip ? -1 : 1), vector.Y, vector.Z);
|
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]));
|
matrix.elements[6], matrix.elements[7], matrix.elements[8]));
|
||||||
return glm::quat(rotation.w, -rotation.x, rotation.y, rotation.z);
|
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
|
#endif
|
||||||
|
|
||||||
void FrameGrabber::cycleVideoSendMode() {
|
void FrameGrabber::cycleVideoSendMode() {
|
||||||
|
@ -517,12 +407,6 @@ void FrameGrabber::setLEDTrackingOn(bool ledTrackingOn) {
|
||||||
|
|
||||||
void FrameGrabber::reset() {
|
void FrameGrabber::reset() {
|
||||||
_searchWindow = cv::Rect(0, 0, 0, 0);
|
_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() {
|
void FrameGrabber::shutdown() {
|
||||||
|
@ -551,7 +435,6 @@ void FrameGrabber::grabFrame() {
|
||||||
}
|
}
|
||||||
int format = GL_BGR;
|
int format = GL_BGR;
|
||||||
Mat color, depth;
|
Mat color, depth;
|
||||||
JointVector joints;
|
|
||||||
|
|
||||||
#ifdef HAVE_OPENNI
|
#ifdef HAVE_OPENNI
|
||||||
if (_depthGenerator.IsValid()) {
|
if (_depthGenerator.IsValid()) {
|
||||||
|
@ -560,37 +443,6 @@ void FrameGrabber::grabFrame() {
|
||||||
format = GL_RGB;
|
format = GL_RGB;
|
||||||
|
|
||||||
depth = Mat(_depthMetaData.YRes(), _depthMetaData.XRes(), CV_16UC1, (void*)_depthGenerator.GetDepthMap());
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -929,7 +781,7 @@ void FrameGrabber::grabFrame() {
|
||||||
QMetaObject::invokeMethod(Application::getInstance()->getWebcam(), "setFrame",
|
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(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(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() {
|
bool FrameGrabber::init() {
|
||||||
|
@ -945,20 +797,11 @@ bool FrameGrabber::init() {
|
||||||
// first try for a Kinect
|
// first try for a Kinect
|
||||||
#ifdef HAVE_OPENNI
|
#ifdef HAVE_OPENNI
|
||||||
_xnContext.Init();
|
_xnContext.Init();
|
||||||
if (_depthGenerator.Create(_xnContext) == XN_STATUS_OK && _imageGenerator.Create(_xnContext) == XN_STATUS_OK &&
|
if (_depthGenerator.Create(_xnContext) == XN_STATUS_OK && _imageGenerator.Create(_xnContext) == XN_STATUS_OK) {
|
||||||
_userGenerator.Create(_xnContext) == XN_STATUS_OK &&
|
|
||||||
_userGenerator.IsCapabilitySupported(XN_CAPABILITY_SKELETON)) {
|
|
||||||
_depthGenerator.GetMetaData(_depthMetaData);
|
_depthGenerator.GetMetaData(_depthMetaData);
|
||||||
_imageGenerator.SetPixelFormat(XN_PIXEL_FORMAT_RGB24);
|
_imageGenerator.SetPixelFormat(XN_PIXEL_FORMAT_RGB24);
|
||||||
_imageGenerator.GetMetaData(_imageMetaData);
|
_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
|
// make the depth viewpoint match that of the video image
|
||||||
if (_depthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT)) {
|
if (_depthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT)) {
|
||||||
_depthGenerator.GetAlternativeViewPointCap().SetViewPoint(_imageGenerator);
|
_depthGenerator.GetAlternativeViewPointCap().SetViewPoint(_imageGenerator);
|
||||||
|
@ -1018,10 +861,3 @@ void FrameGrabber::destroyCodecs() {
|
||||||
_depthCodec.name = 0;
|
_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) {
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,9 +31,7 @@ class QImage;
|
||||||
struct CvCapture;
|
struct CvCapture;
|
||||||
|
|
||||||
class FrameGrabber;
|
class FrameGrabber;
|
||||||
class Joint;
|
|
||||||
|
|
||||||
typedef QVector<Joint> JointVector;
|
|
||||||
typedef std::vector<cv::KeyPoint> KeyPointVector;
|
typedef std::vector<cv::KeyPoint> KeyPointVector;
|
||||||
|
|
||||||
/// Handles interaction with the webcam (including depth cameras such as the Kinect).
|
/// 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& getEstimatedPosition() const { return _estimatedPosition; }
|
||||||
const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }
|
const glm::vec3& getEstimatedRotation() const { return _estimatedRotation; }
|
||||||
const JointVector& getEstimatedJoints() const { return _estimatedJoints; }
|
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void renderPreview(int screenWidth, int screenHeight);
|
void renderPreview(int screenWidth, int screenHeight);
|
||||||
|
@ -70,8 +67,7 @@ public slots:
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFrame(const cv::Mat& color, int format, const cv::Mat& depth, float midFaceDepth, float aspectRatio,
|
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);
|
const cv::RotatedRect& faceRect, bool sending, const KeyPointVector& keyPoints);
|
||||||
void setSkeletonTrackingOn(bool toggle) { _skeletonTrackingOn = toggle; };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -88,7 +84,6 @@ private:
|
||||||
cv::RotatedRect _faceRect;
|
cv::RotatedRect _faceRect;
|
||||||
cv::RotatedRect _initialFaceRect;
|
cv::RotatedRect _initialFaceRect;
|
||||||
float _initialFaceDepth;
|
float _initialFaceDepth;
|
||||||
JointVector _joints;
|
|
||||||
KeyPointVector _keyPoints;
|
KeyPointVector _keyPoints;
|
||||||
|
|
||||||
glm::quat _initialLEDRotation;
|
glm::quat _initialLEDRotation;
|
||||||
|
@ -102,9 +97,6 @@ private:
|
||||||
|
|
||||||
glm::vec3 _estimatedPosition;
|
glm::vec3 _estimatedPosition;
|
||||||
glm::vec3 _estimatedRotation;
|
glm::vec3 _estimatedRotation;
|
||||||
JointVector _estimatedJoints;
|
|
||||||
|
|
||||||
bool _skeletonTrackingOn;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Acquires and processes video frames in a dedicated thread.
|
/// Acquires and processes video frames in a dedicated thread.
|
||||||
|
@ -164,27 +156,11 @@ private:
|
||||||
xn::Context _xnContext;
|
xn::Context _xnContext;
|
||||||
xn::DepthGenerator _depthGenerator;
|
xn::DepthGenerator _depthGenerator;
|
||||||
xn::ImageGenerator _imageGenerator;
|
xn::ImageGenerator _imageGenerator;
|
||||||
xn::UserGenerator _userGenerator;
|
|
||||||
xn::DepthMetaData _depthMetaData;
|
xn::DepthMetaData _depthMetaData;
|
||||||
xn::ImageMetaData _imageMetaData;
|
xn::ImageMetaData _imageMetaData;
|
||||||
XnUserID _userID;
|
|
||||||
#endif
|
#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(KeyPointVector)
|
||||||
Q_DECLARE_METATYPE(cv::Mat)
|
Q_DECLARE_METATYPE(cv::Mat)
|
||||||
Q_DECLARE_METATYPE(cv::RotatedRect)
|
Q_DECLARE_METATYPE(cv::RotatedRect)
|
||||||
|
|
Loading…
Reference in a new issue