From 0321821b559b94125d9e2d217a478af931a79079 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 13 May 2014 11:38:24 -0700 Subject: [PATCH] More work on PrioVR integration. --- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/avatar/MyAvatar.h | 2 +- interface/src/avatar/SkeletonModel.cpp | 12 ++--- interface/src/avatar/SkeletonModel.h | 3 +- interface/src/devices/PrioVR.cpp | 35 ++++++++++---- interface/src/devices/PrioVR.h | 5 +- libraries/fbx/src/FBXReader.cpp | 65 +++++++++++++++----------- libraries/fbx/src/FBXReader.h | 9 ++-- 8 files changed, 81 insertions(+), 54 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 36c51dc9fd..e6d6634653 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -111,7 +111,7 @@ void MyAvatar::reset() { void MyAvatar::update(float deltaTime) { Head* head = getHead(); head->relaxLean(deltaTime); - updateFromFaceTracker(deltaTime); + updateFromTrackers(deltaTime); if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) { // Faceshift drive is enabled, set the avatar drive based on the head position moveWithLean(); @@ -241,7 +241,7 @@ void MyAvatar::simulate(float deltaTime) { } // Update avatar head rotation with sensor data -void MyAvatar::updateFromFaceTracker(float deltaTime) { +void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d446c2e895..2df74f23c2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -38,7 +38,7 @@ public: void reset(); void update(float deltaTime); void simulate(float deltaTime); - void updateFromFaceTracker(float deltaTime); + void updateFromTrackers(float deltaTime); void moveWithLean(); void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8c21a3240f..96510dad25 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -52,15 +52,12 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } else if (leftPalmIndex == rightPalmIndex) { // right hand only - applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices, - hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); restoreLeftHandPosition(HAND_RESTORATION_RATE); } else { - applyPalmData(geometry.leftHandJointIndex, geometry.leftFingerJointIndices, geometry.leftFingertipJointIndices, - hand->getPalms()[leftPalmIndex]); - applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices, - hand->getPalms()[rightPalmIndex]); + applyPalmData(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); + applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[rightPalmIndex]); } } @@ -140,8 +137,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector)); } -void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJointIndices, - const QVector& fingertipJointIndices, PalmData& palm) { +void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { if (jointIndex == -1) { return; } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index ee6b3b9de3..20384829ea 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -39,8 +39,7 @@ protected: void applyHandPosition(int jointIndex, const glm::vec3& position); - void applyPalmData(int jointIndex, const QVector& fingerJointIndices, - const QVector& fingertipJointIndices, PalmData& palm); + void applyPalmData(int jointIndex, PalmData& palm); /// Updates the state of the joint at the specified index. virtual void updateJointState(int index); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index 9b5427be07..5fe6b56b11 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -11,22 +11,44 @@ #include +#include + #include "PrioVR.h" -const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, 0x0000000C, 0x0000000D, - 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; +const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, + 0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; const unsigned char AXIS_LIST[] = { 9, 43, 37, 37, 37, 13, 13, 13, 52, 52, 28, 28 }; const int LIST_LENGTH = sizeof(SERIAL_LIST) / sizeof(SERIAL_LIST[0]); +const char* JOINT_NAMES[] = { "Head", "Spine", "LeftArm", "LeftForeArm", "LeftHand", "RightArm", + "RightForeArm", "RightHand", "LeftUpLeg", "LeftLeg", "RightUpLeft", "RightLeg" }; + +#ifdef HAVE_PRIOVR +static int indexOfHumanIKJoint(const char* jointName) { + for (int i = 0;; i++) { + QByteArray humanIKJoint = HUMANIK_JOINTS[i]; + if (humanIKJoint.isEmpty()) { + return -1; + } + if (humanIKJoint == jointName) { + return i; + } + } +} +#endif + PrioVR::PrioVR() { #ifdef HAVE_PRIOVR - _jointsDiscovered.resize(LIST_LENGTH); + char jointsDiscovered[LIST_LENGTH]; _skeletalDevice = yei_setUpPrioVRSensors(0x00000000, const_cast(SERIAL_LIST), - const_cast(AXIS_LIST), _jointsDiscovered.data(), LIST_LENGTH, YEI_TIMESTAMP_SYSTEM); + const_cast(AXIS_LIST), jointsDiscovered, LIST_LENGTH, YEI_TIMESTAMP_SYSTEM); if (!_skeletalDevice) { return; } _jointRotations.resize(LIST_LENGTH); + for (int i = 0; i < LIST_LENGTH; i++) { + _humanIKJointIndices.append(jointsDiscovered[i] ? indexOfHumanIKJoint(JOINT_NAMES[i]) : -1); + } yei_tareSensors(_skeletalDevice); #endif } @@ -47,10 +69,5 @@ void PrioVR::update() { unsigned int timestamp; yei_getLastStreamDataAll(_skeletalDevice, (char*)_jointRotations.data(), _jointRotations.size() * sizeof(glm::quat), ×tamp); - for (int i = 0; i < _jointsDiscovered.size(); i++) { - if (_jointsDiscovered.at(i)) { - qDebug() << i << _jointRotations.at(i).x << _jointRotations.at(i).y << _jointRotations.at(i).z << _jointRotations.at(i).w; - } - } #endif } diff --git a/interface/src/devices/PrioVR.h b/interface/src/devices/PrioVR.h index 1c26009b33..8bb21f4357 100644 --- a/interface/src/devices/PrioVR.h +++ b/interface/src/devices/PrioVR.h @@ -31,6 +31,9 @@ public: PrioVR(); virtual ~PrioVR(); + + const QVector& getHumanIKJointIndices() const { return _humanIKJointIndices; } + const QVector& getJointRotations() const { return _jointRotations; } void update(); @@ -39,7 +42,7 @@ private: YEI_Device_Id _skeletalDevice; #endif - QVector _jointsDiscovered; + QVector _humanIKJointIndices; QVector _jointRotations; }; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1fc03ceb66..8d2ba4001a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -577,6 +577,25 @@ const char* FACESHIFT_BLENDSHAPES[] = { "" }; +const char* HUMANIK_JOINTS[] = { + "RightHand", + "RightForeArm", + "RightArm", + "Head", + "LeftArm", + "LeftForeArm", + "LeftHand", + "Spine", + "Hips", + "RightUpLeg", + "LeftUpLeg", + "RightLeg", + "LeftLeg", + "RightFoot", + "LeftFoot", + "" +}; + class FBXModel { public: QString name; @@ -1012,10 +1031,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QString jointHeadName = processID(getString(joints.value("jointHead", "jointHead"))); QString jointLeftHandName = processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); QString jointRightHandName = processID(getString(joints.value("jointRightHand", "jointRightHand"))); - QVariantList jointLeftFingerNames = joints.values("jointLeftFinger"); - QVariantList jointRightFingerNames = joints.values("jointRightFinger"); - QVariantList jointLeftFingertipNames = joints.values("jointLeftFingertip"); - QVariantList jointRightFingertipNames = joints.values("jointRightFingertip"); QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; @@ -1024,10 +1039,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) QString jointHeadID; QString jointLeftHandID; QString jointRightHandID; - QVector jointLeftFingerIDs(jointLeftFingerNames.size()); - QVector jointRightFingerIDs(jointRightFingerNames.size()); - QVector jointLeftFingertipIDs(jointLeftFingertipNames.size()); - QVector jointRightFingertipIDs(jointRightFingertipNames.size()); + + QVector humanIKJointNames; + for (int i = 0;; i++) { + QByteArray jointName = HUMANIK_JOINTS[i]; + if (jointName.isEmpty()) { + break; + } + humanIKJointNames.append(processID(getString(joints.value(jointName, jointName)))); + } + QVector humanIKJointIDs(humanIKJointNames.size()); QVariantHash blendshapeMappings = mapping.value("bs").toHash(); QMultiHash blendshapeIndices; @@ -1091,7 +1112,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else { name = getID(object.properties); } - int index; if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { jointEyeLeftID = getID(object.properties); @@ -1115,19 +1135,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (name == jointRightHandName) { jointRightHandID = getID(object.properties); - - } else if ((index = jointLeftFingerNames.indexOf(name)) != -1) { - jointLeftFingerIDs[index] = getID(object.properties); - - } else if ((index = jointRightFingerNames.indexOf(name)) != -1) { - jointRightFingerIDs[index] = getID(object.properties); - - } else if ((index = jointLeftFingertipNames.indexOf(name)) != -1) { - jointLeftFingertipIDs[index] = getID(object.properties); - - } else if ((index = jointRightFingertipNames.indexOf(name)) != -1) { - jointRightFingertipIDs[index] = getID(object.properties); } + int humanIKJointIndex = humanIKJointNames.indexOf(name); + if (humanIKJointIndex != -1) { + humanIKJointIDs[humanIKJointIndex] = getID(object.properties); + } + glm::vec3 translation; // NOTE: the euler angles as supplied by the FBX file are in degrees glm::vec3 rotationOffset; @@ -1513,11 +1526,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.headJointIndex = modelIDs.indexOf(jointHeadID); geometry.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID); geometry.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); - geometry.leftFingerJointIndices = getIndices(jointLeftFingerIDs, modelIDs); - geometry.rightFingerJointIndices = getIndices(jointRightFingerIDs, modelIDs); - geometry.leftFingertipJointIndices = getIndices(jointLeftFingertipIDs, modelIDs); - geometry.rightFingertipJointIndices = getIndices(jointRightFingertipIDs, modelIDs); - + + foreach (const QString& id, humanIKJointIDs) { + geometry.humanIKJointIndices.append(modelIDs.indexOf(id)); + } + // extract the translation component of the neck transform if (geometry.neckJointIndex != -1) { const glm::mat4& transform = geometry.joints.at(geometry.neckJointIndex).transform; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 51e7380181..38251e4065 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -30,6 +30,9 @@ typedef QList FBXNodeList; /// The names of the blendshapes expected by Faceshift, terminated with an empty string. extern const char* FACESHIFT_BLENDSHAPES[]; +/// The names of the joints in the Maya HumanIK rig, terminated with an empty string. +extern const char* HUMANIK_JOINTS[]; + class Extents { public: /// set minimum and maximum to FLT_MAX and -FLT_MAX respectively @@ -199,11 +202,7 @@ public: int leftHandJointIndex; int rightHandJointIndex; - QVector leftFingerJointIndices; - QVector rightFingerJointIndices; - - QVector leftFingertipJointIndices; - QVector rightFingertipJointIndices; + QVector humanIKJointIndices; glm::vec3 palmDirection;