Showing the changes to libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp (1 of 1 file). Show all
Unified · Split
| @@ -324,9 +324,64 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, int index) { · 323 unmodified lines | |||
| 324 | glm::vec3 position = extractTranslation(mat); | 324 | glm::vec3 position = extractTranslation(mat); |
| 325 | glm::quat rotation = glm::quat_cast(mat); | 325 | glm::quat rotation = glm::quat_cast(mat); |
| 326 | 326 | ||
| 327 | // Flip the rotation appropriately for each hand | 327 | // When the sensor-to-world rotation is identity the coordinate axes look like this: |
| 328 | int sign = index == LEFT_HAND ? 1 : -1; | 328 | // |
| 329 | rotation = rotation * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); | 329 | // user |
| 330 | // forward | ||
| 331 | // z | ||
| 332 | // | | ||
| 333 | // y| user | ||
| 334 | // y o----x right | ||
| 335 | // o-----x user | ||
| 336 | // | up | ||
| 337 | // | | ||
| 338 | // z | ||
| 339 | // | ||
| 340 | // Vive | ||
| 341 | // | ||
| 342 | |||
| 343 | // From ABOVE the hand canonical axes looks like this: | ||
| 344 | // | ||
| 345 | // | | | | y | | | | | ||
| 346 | // | | | | | | | | | | ||
| 347 | // | | | | | | ||
| 348 | // |left | / x---- + \ |right| | ||
| 349 | // | _/ z \_ | | ||
| 350 | // | | | | | ||
| 351 | // | | | | | ||
| 352 | // | ||
| 353 | |||
| 354 | // So when the user is standing in Vive space facing the -zAxis with hands outstretched and palms down | ||
| 355 | // the rotation to align the Vive axes with those of the hands is: | ||
| 356 | // | ||
| 357 | // QviveToHand = halfTurnAboutY * quaterTurnAboutX | ||
| 358 | |||
| 359 | // Due to how the Vive controllers fit into the palm there is an offset that is different for each hand. | ||
| 360 | // You can think of this offset as the inverse of the measured rotation when the hands are posed, such that | ||
| 361 | // the combination (measurement * offset) is identity at this orientation. | ||
| 362 | // | ||
| 363 | // Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down) | ||
| 364 | // | ||
| 365 | // An approximate offset for the Vive can be obtained by inpection: | ||
| 366 | // | ||
| 367 | // Qoffset = glm::inverse(glm::angleAxis(sign * PI/4.0f, zAxis) * glm::angleAxis(PI/2.0f, xAxis)) | ||
| 368 | // | ||
| 369 | |||
| 370 | // Finally there is another flip around the yAxis to re-align from model to Vive space, so the full equation is: | ||
| 371 | // | ||
| 372 | // Q = yFlip * combinedMeasurement * viveToHand | ||
| 373 | // | ||
| 374 | // Q = yFlip * (deltaQ * QOffset) * (yFlip * quarterTurnAboutX) | ||
| 375 | // | ||
| 376 | // Q = yFlip * (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX) | ||
| 377 | |||
| 378 | const glm::quat quarterX = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); | ||
| 379 | const glm::quat yFlip = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); | ||
| 380 | float sign = (index == LEFT_HAND) ? -1.0f : 1.0f; | ||
| 381 | const glm::quat signedQuaterZ = glm::angleAxis(sign * PI / 2.0f, glm::vec3(0.0f, 0.0f, 1.0f)); | ||
| 382 | const glm::quat eighthX = glm::angleAxis(PI / 4.0f, glm::vec3(1.0f, 0.0f, 0.0f)); | ||
| 383 | const glm::quat offset = glm::inverse(signedQuaterZ * eighthX); | ||
| 384 | rotation = yFlip * rotation * offset * yFlip * quarterX; | ||
| 330 | 385 | ||
| 331 | position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET); | 386 | position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET); |
| 332 | 387 | ||