neruonAvatar.js: now sets rotations in correct frame.

The rotations from the neuron are effectively in world space and are deltas
from the default pose.

There still is an issue with the thumb, due to the missing joint from the Neuron.
The Neuron only has 3 thumb joints, not 4.
This commit is contained in:
Anthony Thibault 2015-12-24 17:14:17 -08:00
parent c44f69b370
commit 8b979b67ee
2 changed files with 119 additions and 28 deletions

View file

@ -61,6 +61,70 @@ var JOINT_NAME_MAP = {
LeftHandPinky3: "LeftHandPinky4"
};
var JOINT_PARENT_MAP = {
Hips: "",
RightUpLeg: "Hips",
RightLeg: "RightUpLeg",
RightFoot: "RightLeg",
LeftUpLeg: "Hips",
LeftLeg: "LeftUpLeg",
LeftFoot: "LeftLeg",
Spine: "Hips",
Spine1: "Spine",
Spine2: "Spine1",
Spine3: "Spine2",
Neck: "Spine3",
Head: "Neck",
RightShoulder: "Spine3",
RightArm: "RightShoulder",
RightForeArm: "RightArm",
RightHand: "RightForeArm",
RightHandThumb1: "RightHand",
RightHandThumb2: "RightHandThumb1",
RightHandThumb3: "RightHandThumb2",
RightHandThumb4: "RightHandThumb3",
RightHandIndex1: "RightHand",
RightHandIndex2: "RightHandIndex1",
RightHandIndex3: "RightHandIndex2",
RightHandIndex4: "RightHandIndex3",
RightHandMiddle1: "RightHand",
RightHandMiddle2: "RightHandMiddle1",
RightHandMiddle3: "RightHandMiddle2",
RightHandMiddle4: "RightHandMiddle3",
RightHandRing1: "RightHand",
RightHandRing2: "RightHandRing1",
RightHandRing3: "RightHandRing2",
RightHandRing4: "RightHandRing3",
RightHandPinky1: "RightHand",
RightHandPinky2: "RightHandPinky1",
RightHandPinky3: "RightHandPinky2",
RightHandPinky4: "RightHandPinky3",
LeftShoulder: "Spine3",
LeftArm: "LeftShoulder",
LeftForeArm: "LeftArm",
LeftHand: "LeftForeArm",
LeftHandThumb1: "LeftHand",
LeftHandThumb2: "LeftHandThumb1",
LeftHandThumb3: "LeftHandThumb2",
LeftHandThumb4: "LeftHandThumb3",
LeftHandIndex1: "LeftHand",
LeftHandIndex2: "LeftHandIndex1",
LeftHandIndex3: "LeftHandIndex2",
LeftHandIndex4: "LeftHandIndex3",
LeftHandMiddle1: "LeftHand",
LeftHandMiddle2: "LeftHandMiddle1",
LeftHandMiddle3: "LeftHandMiddle2",
LeftHandMiddle4: "LeftHandMiddle3",
LeftHandRing1: "LeftHand",
LeftHandRing2: "LeftHandRing1",
LeftHandRing3: "LeftHandRing2",
LeftHandRing4: "LeftHandRing3",
LeftHandPinky1: "LeftHand",
LeftHandPinky2: "LeftHandPinky1",
LeftHandPinky3: "LeftHandPinky2",
LeftHandPinky: "LeftHandPinky3",
};
function dumpHardwareMapping() {
Object.keys(Controller.Hardware).forEach(function (deviceName) {
Object.keys(Controller.Hardware[deviceName]).forEach(function (input) {
@ -103,6 +167,21 @@ NeuronAvatar.prototype.activate = function () {
Script.update.connect(updateCallback);
}
this._active = true;
// build absDefaultPoseMap
this._absDefaultRotMap = {};
var keys = Object.keys(JOINT_NAME_MAP);
var i, l = keys.length;
for (i = 0; i < l; i++) {
var jointName = JOINT_NAME_MAP[keys[i]];
var j = MyAvatar.getJointIndex(jointName);
var parentJointName = JOINT_PARENT_MAP[jointName];
if (parentJointName === "") {
this._absDefaultRotMap[jointName] = MyAvatar.getDefaultJointRotation(j);
} else {
this._absDefaultRotMap[jointName] = Quat.multiply(this._absDefaultRotMap[parentJointName], MyAvatar.getDefaultJointRotation(j));
}
}
};
NeuronAvatar.prototype.deactivate = function () {
@ -117,14 +196,22 @@ NeuronAvatar.prototype.deactivate = function () {
NeuronAvatar.prototype.update = function (deltaTime) {
var keys = Object.keys(JOINT_NAME_MAP);
var i, l = keys.length;
var absDefaultRot = {};
for (i = 0; i < l; i++) {
var channel = Controller.Hardware.Neuron[keys[i]];
if (channel) {
var pose = Controller.getPoseValue(channel);
var j = MyAvatar.getJointIndex(JOINT_NAME_MAP[keys[i]]);
var defaultRot = MyAvatar.getDefaultJointRotation(j);
var rot = Quat.multiply(Quat.inverse(defaultRot), Quat.multiply(pose.rotation, defaultRot));
MyAvatar.setJointRotation(j, Quat.multiply(defaultRot, rot));
var jointName = JOINT_NAME_MAP[keys[i]];
var parentJointName = JOINT_PARENT_MAP[jointName];
var j = MyAvatar.getJointIndex(jointName);
var defaultAbsRot = this._absDefaultRotMap[jointName];
var parentDefaultAbsRot;
if (parentJointName === "") {
parentDefaultAbsRot = {x: 0, y: 0, z: 0, w: 1};
} else {
parentDefaultAbsRot = this._absDefaultRotMap[parentJointName];
}
MyAvatar.setJointRotation(j, Quat.multiply(Quat.inverse(parentDefaultAbsRot), Quat.multiply(pose.rotation, defaultAbsRot)));
//MyAvatar.setJointTranslation(j, Vec3.multiply(100.0, pose.translation));
}
}

View file

@ -107,21 +107,37 @@ void FrameDataReceivedCallback(void* context, SOCKET_REF sender, BvhDataHeaderEx
// version 1.0
if (header->DataVersion.Major == 1 && header->DataVersion.Minor == 0) {
std::lock_guard<std::mutex> guard(neuronPlugin->_jointsMutex);
// Data is 6 floats: 3 position values, 3 rotation euler angles (degrees)
// resize vector if necessary
const size_t NUM_FLOATS_PER_JOINT = 6;
const size_t NUM_JOINTS = header->DataCount / NUM_FLOATS_PER_JOINT;
if (neuronPlugin->_joints.size() != NUM_JOINTS) {
neuronPlugin->_joints.resize(NUM_JOINTS, { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
// skip reference joint if present
if (header->WithReference && header->WithDisp) {
data += 6;
} else if (header->WithReference && !header->WithDisp) {
data += 3;
}
assert(sizeof(NeuronPlugin::NeuronJoint) == (NUM_FLOATS_PER_JOINT * sizeof(float)));
if (header->WithDisp) {
// enter mutex
std::lock_guard<std::mutex> guard(neuronPlugin->_jointsMutex);
// copy the data
memcpy(&(neuronPlugin->_joints[0]), data, sizeof(NeuronPlugin::NeuronJoint) * NUM_JOINTS);
//
// Data is 6 floats per joint: 3 position values, 3 rotation euler angles (degrees)
//
// resize vector if necessary
const size_t NUM_FLOATS_PER_JOINT = 6;
const size_t NUM_JOINTS = header->DataCount / NUM_FLOATS_PER_JOINT;
if (neuronPlugin->_joints.size() != NUM_JOINTS) {
neuronPlugin->_joints.resize(NUM_JOINTS, { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
}
assert(sizeof(NeuronPlugin::NeuronJoint) == (NUM_FLOATS_PER_JOINT * sizeof(float)));
// copy the data
memcpy(&(neuronPlugin->_joints[0]), data, sizeof(NeuronPlugin::NeuronJoint) * NUM_JOINTS);
} else {
qCCritical(inputplugins) << "NeruonPlugin: format not supported";
}
} else {
static bool ONCE = false;
@ -368,18 +384,6 @@ void NeuronPlugin::InputDevice::update(float deltaTime, const std::vector<Neuron
angularVel = glm::vec3(d.x, d.y, d.z) / (0.5f * deltaTime);
}
_poseStateMap[poseIndex] = controller::Pose(pos, rot, linearVel, angularVel);
// dump the first 5 joints
if (i <= JointIndex::LeftFoot) {
qCDebug(inputplugins) << neuronJointName((JointIndex)i);
qCDebug(inputplugins) << " trans = " << joints[i].pos;
qCDebug(inputplugins) << " euler = " << joints[i].euler;
}
/*
if (glm::length(angularVel) > 0.5f) {
qCDebug(inputplugins) << "Movement in joint" << i << neuronJointName((JointIndex)i);
}
*/
}
}