Title: [230428] trunk/Source/WebCore
Revision
230428
Author
svil...@igalia.com
Date
2018-04-09 07:40:51 -0700 (Mon, 09 Apr 2018)

Log Message

[OpenVR][WebVR] Retrieve FrameData in WebVR's rAF
https://bugs.webkit.org/show_bug.cgi?id=184265

Reviewed by Žan Doberšek.

VRFrameData contains all the required information to properly render a VR scene like view
and projection matrices, pose data (position & orientation) and linear & angular velocity
among others. The getFrameData() call must be issued inside a WebVR's own
requestAnimationFrame.

* Modules/webvr/VRDisplay.cpp:
(WebCore::VRDisplay::getFrameData const):
(WebCore::VRDisplay::getPose const):
(WebCore::VRDisplay::requestAnimationFrame):
(WebCore::VRDisplay::cancelAnimationFrame):
* Modules/webvr/VRDisplay.h:
* Modules/webvr/VREyeParameters.h:
(WebCore::VREyeParameters::rawOffset const): Required to compute view matrices.
* Modules/webvr/VRFrameData.cpp:
(WebCore::matrixToArray):
(WebCore::VRFrameData::leftProjectionMatrix const):
(WebCore::VRFrameData::leftViewMatrix const):
(WebCore::VRFrameData::rightProjectionMatrix const):
(WebCore::VRFrameData::rightViewMatrix const):
(WebCore::projectionMatrixFromFieldOfView):
(WebCore::rotationMatrixFromQuaternion):
(WebCore::applyHeadToEyeTransform):
(WebCore::VRFrameData::update):
(WebCore::VRFrameData::timestamp const): Deleted.
* Modules/webvr/VRFrameData.h:
(WebCore::VRFrameData::timestamp const):
* Modules/webvr/VRPose.cpp:
(WebCore::optionalFloat3ToJSCArray):
(WebCore::VRPose::position const):
(WebCore::VRPose::linearVelocity const):
(WebCore::VRPose::linearAcceleration const):
(WebCore::VRPose::orientation const):
(WebCore::VRPose::angularVelocity const):
(WebCore::VRPose::angularAcceleration const):
* Modules/webvr/VRPose.h:
(WebCore::VRPose::create):
(WebCore::VRPose::update):
(WebCore::VRPose::VRPose):
* platform/vr/VRPlatformDisplay.h:
(WebCore::VRPlatformTrackingInfo::Quaternion::Quaternion):
(WebCore::VRPlatformTrackingInfo::Quaternion::conjugate):
(WebCore::VRPlatformTrackingInfo::Quaternion::operator*):
(WebCore::VRPlatformTrackingInfo::Float3::Float3): Just a group of 3 floats used to store
both velocity and acceleration in a format which is very convenient to later generate JSC
arrays.
(WebCore::VRPlatformTrackingInfo::clear):
* platform/vr/openvr/VRPlatformDisplayOpenVR.cpp:
(WebCore::VRPlatformDisplayOpenVR::VRPlatformDisplayOpenVR):
(WebCore::rotationMatrixToQuaternion):
(WebCore::VRPlatformDisplayOpenVR::getTrackingInfo):
* platform/vr/openvr/VRPlatformDisplayOpenVR.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (230427 => 230428)


--- trunk/Source/WebCore/ChangeLog	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/ChangeLog	2018-04-09 14:40:51 UTC (rev 230428)
@@ -1,3 +1,62 @@
+2018-04-03  Sergio Villar Senin  <svil...@igalia.com>
+
+        [OpenVR][WebVR] Retrieve FrameData in WebVR's rAF
+        https://bugs.webkit.org/show_bug.cgi?id=184265
+
+        Reviewed by Žan Doberšek.
+
+        VRFrameData contains all the required information to properly render a VR scene like view
+        and projection matrices, pose data (position & orientation) and linear & angular velocity
+        among others. The getFrameData() call must be issued inside a WebVR's own
+        requestAnimationFrame.
+
+        * Modules/webvr/VRDisplay.cpp:
+        (WebCore::VRDisplay::getFrameData const):
+        (WebCore::VRDisplay::getPose const):
+        (WebCore::VRDisplay::requestAnimationFrame):
+        (WebCore::VRDisplay::cancelAnimationFrame):
+        * Modules/webvr/VRDisplay.h:
+        * Modules/webvr/VREyeParameters.h:
+        (WebCore::VREyeParameters::rawOffset const): Required to compute view matrices.
+        * Modules/webvr/VRFrameData.cpp:
+        (WebCore::matrixToArray):
+        (WebCore::VRFrameData::leftProjectionMatrix const):
+        (WebCore::VRFrameData::leftViewMatrix const):
+        (WebCore::VRFrameData::rightProjectionMatrix const):
+        (WebCore::VRFrameData::rightViewMatrix const):
+        (WebCore::projectionMatrixFromFieldOfView):
+        (WebCore::rotationMatrixFromQuaternion):
+        (WebCore::applyHeadToEyeTransform):
+        (WebCore::VRFrameData::update):
+        (WebCore::VRFrameData::timestamp const): Deleted.
+        * Modules/webvr/VRFrameData.h:
+        (WebCore::VRFrameData::timestamp const):
+        * Modules/webvr/VRPose.cpp:
+        (WebCore::optionalFloat3ToJSCArray):
+        (WebCore::VRPose::position const):
+        (WebCore::VRPose::linearVelocity const):
+        (WebCore::VRPose::linearAcceleration const):
+        (WebCore::VRPose::orientation const):
+        (WebCore::VRPose::angularVelocity const):
+        (WebCore::VRPose::angularAcceleration const):
+        * Modules/webvr/VRPose.h:
+        (WebCore::VRPose::create):
+        (WebCore::VRPose::update):
+        (WebCore::VRPose::VRPose):
+        * platform/vr/VRPlatformDisplay.h:
+        (WebCore::VRPlatformTrackingInfo::Quaternion::Quaternion):
+        (WebCore::VRPlatformTrackingInfo::Quaternion::conjugate):
+        (WebCore::VRPlatformTrackingInfo::Quaternion::operator*):
+        (WebCore::VRPlatformTrackingInfo::Float3::Float3): Just a group of 3 floats used to store
+        both velocity and acceleration in a format which is very convenient to later generate JSC
+        arrays.
+        (WebCore::VRPlatformTrackingInfo::clear):
+        * platform/vr/openvr/VRPlatformDisplayOpenVR.cpp:
+        (WebCore::VRPlatformDisplayOpenVR::VRPlatformDisplayOpenVR):
+        (WebCore::rotationMatrixToQuaternion):
+        (WebCore::VRPlatformDisplayOpenVR::getTrackingInfo):
+        * platform/vr/openvr/VRPlatformDisplayOpenVR.h:
+
 2018-04-09  Michael Catanzaro  <mcatanz...@igalia.com>
 
         [GTK] WaylandCompositorDisplay leaks its wl_display

Modified: trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp	2018-04-09 14:40:51 UTC (rev 230428)
@@ -26,8 +26,12 @@
 #include "config.h"
 #include "VRDisplay.h"
 
+#include "Chrome.h"
+#include "Page.h"
+#include "ScriptedAnimationController.h"
 #include "VRDisplayCapabilities.h"
 #include "VREyeParameters.h"
+#include "VRFrameData.h"
 #include "VRLayerInit.h"
 #include "VRPlatformDisplay.h"
 #include "VRPose.h"
@@ -85,14 +89,19 @@
     return eye == VREye::Left ? *m_leftEyeParameters : *m_rightEyeParameters;
 }
 
-bool VRDisplay::getFrameData(VRFrameData&) const
+bool VRDisplay::getFrameData(VRFrameData& frameData) const
 {
-    return false;
+    if (!m_capabilities->hasPosition() || !m_capabilities->hasOrientation())
+        return false;
+
+    // FIXME: ensure that this is only called inside WebVR's rAF.
+    frameData.update(m_display->getTrackingInfo(), getEyeParameters(VREye::Left), getEyeParameters(VREye::Right), m_depthNear, m_depthFar);
+    return true;
 }
 
 Ref<VRPose> VRDisplay::getPose() const
 {
-    return VRPose::create();
+    return VRPose::create(m_display->getTrackingInfo());
 }
 
 void VRDisplay::resetPose()
@@ -99,13 +108,28 @@
 {
 }
 
-long VRDisplay::requestAnimationFrame(Ref<RequestAnimationFrameCallback>&&)
+uint32_t VRDisplay::requestAnimationFrame(Ref<RequestAnimationFrameCallback>&& callback)
 {
-    return 0;
+    if (!m_scriptedAnimationController) {
+        auto* document = downcast<Document>(scriptExecutionContext());
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+        // FIXME: Get the display id of the HMD as it should use the HMD native refresh rate.
+        PlatformDisplayID displayID = document->page() ? document->page()->chrome().displayID() : 0;
+        m_scriptedAnimationController = ScriptedAnimationController::create(*document, displayID);
+#else
+        m_scriptedAnimationController = ScriptedAnimationController::create(*document, 0);
+#endif
+    }
+
+    return m_scriptedAnimationController->registerCallback(WTFMove(callback));
 }
 
-void VRDisplay::cancelAnimationFrame(unsigned)
+void VRDisplay::cancelAnimationFrame(uint32_t id)
 {
+    if (!m_scriptedAnimationController)
+        return;
+
+    m_scriptedAnimationController->cancelCallback(id);
 }
 
 void VRDisplay::requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&)

Modified: trunk/Source/WebCore/Modules/webvr/VRDisplay.h (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRDisplay.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplay.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class RequestAnimationFrameCallback;
+class ScriptedAnimationController;
 class VRDisplayCapabilities;
 class VREyeParameters;
 class VRFrameData;
@@ -72,8 +73,8 @@
     double depthFar() const { return m_depthFar; }
     void setDepthFar(double depthFar) { m_depthFar = depthFar; }
 
-    long requestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
-    void cancelAnimationFrame(unsigned);
+    uint32_t requestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
+    void cancelAnimationFrame(uint32_t);
 
     void requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&);
     void exitPresent(Ref<DeferredPromise>&&);
@@ -111,6 +112,8 @@
 
     double m_depthNear { 0.01 }; // Default value from the specs.
     double m_depthFar { 10000 }; // Default value from the specs.
+
+    RefPtr<ScriptedAnimationController> m_scriptedAnimationController;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webvr/VREyeParameters.h (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VREyeParameters.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VREyeParameters.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -43,6 +43,7 @@
     }
 
     Ref<Float32Array> offset() const;
+    const FloatPoint3D& rawOffset() const { return m_offset; }
 
     const VRFieldOfView& fieldOfView() const;
 

Modified: trunk/Source/WebCore/Modules/webvr/VRFrameData.cpp (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRFrameData.cpp	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRFrameData.cpp	2018-04-09 14:40:51 UTC (rev 230428)
@@ -25,6 +25,8 @@
 #include "config.h"
 #include "VRFrameData.h"
 
+#include "VREyeParameters.h"
+#include "VRPlatformDisplay.h"
 #include "VRPose.h"
 
 namespace WebCore {
@@ -34,29 +36,31 @@
 {
 }
 
-double VRFrameData::timestamp() const
+static Ref<Float32Array> matrixToArray(const TransformationMatrix& matrix)
 {
-    return 0;
+    TransformationMatrix::FloatMatrix4 columnMajorMatrix;
+    matrix.toColumnMajorFloatArray(columnMajorMatrix);
+    return Float32Array::create(columnMajorMatrix, 16).releaseNonNull();
 }
 
-Float32Array* VRFrameData::leftProjectionMatrix() const
+Ref<Float32Array> VRFrameData::leftProjectionMatrix() const
 {
-    return nullptr;
+    return matrixToArray(m_leftProjectionMatrix);
 }
 
-Float32Array* VRFrameData::leftViewMatrix() const
+Ref<Float32Array> VRFrameData::leftViewMatrix() const
 {
-    return nullptr;
+    return matrixToArray(m_leftViewMatrix);
 }
 
-Float32Array* VRFrameData::rightProjectionMatrix() const
+Ref<Float32Array> VRFrameData::rightProjectionMatrix() const
 {
-    return nullptr;
+    return matrixToArray(m_rightProjectionMatrix);
 }
 
-Float32Array* VRFrameData::rightViewMatrix() const
+Ref<Float32Array> VRFrameData::rightViewMatrix() const
 {
-    return nullptr;
+    return matrixToArray(m_rightViewMatrix);
 }
 
 const VRPose& VRFrameData::pose() const
@@ -64,4 +68,76 @@
     return m_pose;
 }
 
+static TransformationMatrix projectionMatrixFromFieldOfView(const VRFieldOfView& fov, double depthNear, double depthFar)
+{
+    double upTan = tan(deg2rad(fov.upDegrees()));
+    double downTan = tan(deg2rad(fov.downDegrees()));
+    double leftTan = tan(deg2rad(fov.leftDegrees()));
+    double rightTan = tan(deg2rad(fov.rightDegrees()));
+
+    double xScale = 2 / (leftTan + rightTan);
+    double yScale = 2 / (upTan + downTan);
+
+    TransformationMatrix projectionMatrix;
+    projectionMatrix.setM11(xScale);
+    projectionMatrix.setM22(yScale);
+    projectionMatrix.setM32((upTan - downTan) * yScale * 0.5);
+    projectionMatrix.setM31(-((leftTan - rightTan) * xScale * 0.5));
+    projectionMatrix.setM33((depthNear + depthFar) / (depthNear - depthFar));
+    projectionMatrix.setM34(-1);
+    projectionMatrix.setM43((2 * depthFar * depthNear) / (depthNear - depthFar));
+    projectionMatrix.setM44(0);
+
+    return projectionMatrix;
+}
+
+// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
+static TransformationMatrix rotationMatrixFromQuaternion(const VRPlatformTrackingInfo::Quaternion& quaternion)
+{
+    double magnitude = (quaternion.x * quaternion.x) + (quaternion.y * quaternion.y) + (quaternion.z * quaternion.z) + (quaternion.w * quaternion.w);
+    VRPlatformTrackingInfo::Quaternion normalizedQuaternion(quaternion.x / magnitude, quaternion.y / magnitude, quaternion.z / magnitude, quaternion.w / magnitude);
+    double x2 = normalizedQuaternion.x * normalizedQuaternion.x;
+    double y2 = normalizedQuaternion.y * normalizedQuaternion.y;
+    double z2 = normalizedQuaternion.z * normalizedQuaternion.z;
+    double w2 = normalizedQuaternion.w * normalizedQuaternion.w;
+    double xy = normalizedQuaternion.x * normalizedQuaternion.y;
+    double zw = normalizedQuaternion.z * normalizedQuaternion.w;
+    double xz = normalizedQuaternion.x * normalizedQuaternion.z;
+    double yw = normalizedQuaternion.y * normalizedQuaternion.w;
+    double yz = normalizedQuaternion.y * normalizedQuaternion.z;
+    double xw = normalizedQuaternion.x * normalizedQuaternion.w;
+
+    return TransformationMatrix(
+        x2 - y2 - z2 + w2, 2.0 * (xy - zw), 2.0 * (xz + yw), 0,
+        2.0 * (xy + zw), -x2 + y2 - z2 + w2, 2.0 * (yz - xw), 0,
+        2.0 * (xz - yw), 2.0 * (yz + xw), -x2 - y2 + z2 + w2, 0,
+        0, 0, 0, 1);
+}
+
+static void applyHeadToEyeTransform(TransformationMatrix& matrix, const FloatPoint3D& translation)
+{
+    matrix.setM41(matrix.m41() - translation.x());
+    matrix.setM42(matrix.m42() - translation.y());
+    matrix.setM43(matrix.m43() - translation.z());
+}
+
+void VRFrameData::update(const VRPlatformTrackingInfo& trackingInfo, const VREyeParameters& leftEye, const VREyeParameters& rightEye, double depthNear, double depthFar)
+{
+    m_leftProjectionMatrix = projectionMatrixFromFieldOfView(leftEye.fieldOfView(), depthNear, depthFar);
+    m_rightProjectionMatrix = projectionMatrixFromFieldOfView(rightEye.fieldOfView(), depthNear, depthFar);
+
+    m_timestamp = trackingInfo.timestamp;
+    m_pose->update(trackingInfo);
+
+    auto rotationMatrix = rotationMatrixFromQuaternion(trackingInfo.orientation.value_or(VRPlatformTrackingInfo::Quaternion(0, 0, 0, 1)));
+    FloatPoint3D position = trackingInfo.position.value_or(FloatPoint3D(0, 0, 0));
+    rotationMatrix.translate3d(-position.x(), -position.y(), -position.z());
+
+    m_leftViewMatrix = rotationMatrix;
+    applyHeadToEyeTransform(m_leftViewMatrix, leftEye.rawOffset());
+
+    m_rightViewMatrix = rotationMatrix;
+    applyHeadToEyeTransform(m_rightViewMatrix, rightEye.rawOffset());
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webvr/VRFrameData.h (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRFrameData.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRFrameData.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -24,12 +24,15 @@
  */
 #pragma once
 
+#include "TransformationMatrix.h"
 #include <_javascript_Core/Float32Array.h>
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
 
+class VREyeParameters;
 class VRPose;
+struct VRPlatformTrackingInfo;
 
 class VRFrameData : public RefCounted<VRFrameData> {
 public:
@@ -38,20 +41,27 @@
         return adoptRef(*new VRFrameData);
     }
 
-    double timestamp() const;
+    double timestamp() const { return m_timestamp; }
 
-    Float32Array* leftProjectionMatrix() const;
-    Float32Array* leftViewMatrix() const;
+    Ref<Float32Array> leftProjectionMatrix() const;
+    Ref<Float32Array> leftViewMatrix() const;
 
-    Float32Array* rightProjectionMatrix() const;
-    Float32Array* rightViewMatrix() const;
+    Ref<Float32Array> rightProjectionMatrix() const;
+    Ref<Float32Array> rightViewMatrix() const;
 
     const VRPose& pose() const;
 
+    void update(const VRPlatformTrackingInfo&, const VREyeParameters& leftEye, const VREyeParameters& rightEye, double depthNear, double depthFar);
+
 private:
     VRFrameData();
 
+    double m_timestamp { 0 };
     Ref<VRPose> m_pose;
+    TransformationMatrix m_leftProjectionMatrix;
+    TransformationMatrix m_rightProjectionMatrix;
+    TransformationMatrix m_leftViewMatrix;
+    TransformationMatrix m_rightViewMatrix;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webvr/VRPose.cpp (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRPose.cpp	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRPose.cpp	2018-04-09 14:40:51 UTC (rev 230428)
@@ -27,36 +27,52 @@
 
 namespace WebCore {
 
-VRPose::VRPose() = default;
+static RefPtr<Float32Array> optionalFloat3ToJSCArray(const std::optional<VRPlatformTrackingInfo::Float3>& data)
+{
+    if (!data)
+        return nullptr;
 
-Float32Array* VRPose::position() const
+    return Float32Array::create(data->data, 3).releaseNonNull();
+}
+
+RefPtr<Float32Array> VRPose::position() const
 {
-    return nullptr;
+    if (!m_trackingInfo.position)
+        return nullptr;
+
+    auto& position = *m_trackingInfo.position;
+    float positionData[3] = { position.x(), position.y(), position.z() };
+    return Float32Array::create(positionData, 3).releaseNonNull();
 }
 
-Float32Array* VRPose::linearVelocity() const
+RefPtr<Float32Array> VRPose::linearVelocity() const
 {
-    return nullptr;
+    return optionalFloat3ToJSCArray(m_trackingInfo.linearVelocity);
 }
 
-Float32Array* VRPose::linearAcceleration() const
+RefPtr<Float32Array> VRPose::linearAcceleration() const
 {
-    return nullptr;
+    return optionalFloat3ToJSCArray(m_trackingInfo.linearAcceleration);
 }
 
-Float32Array* VRPose::orientation() const
+RefPtr<Float32Array> VRPose::orientation() const
 {
-    return nullptr;
+    if (!m_trackingInfo.orientation)
+        return nullptr;
+
+    auto& orientation = *m_trackingInfo.orientation;
+    float orientationData[4] = { orientation.x, orientation.y, orientation.z, orientation.w };
+    return Float32Array::create(orientationData, 4).releaseNonNull();
 }
 
-Float32Array* VRPose::angularVelocity() const
+RefPtr<Float32Array> VRPose::angularVelocity() const
 {
-    return nullptr;
+    return optionalFloat3ToJSCArray(m_trackingInfo.angularVelocity);
 }
 
-Float32Array* VRPose::angularAcceleration() const
+RefPtr<Float32Array> VRPose::angularAcceleration() const
 {
-    return nullptr;
+    return optionalFloat3ToJSCArray(m_trackingInfo.angularAcceleration);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webvr/VRPose.h (230427 => 230428)


--- trunk/Source/WebCore/Modules/webvr/VRPose.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/Modules/webvr/VRPose.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -24,6 +24,7 @@
  */
 #pragma once
 
+#include "VRPlatformDisplay.h"
 #include <_javascript_Core/Float32Array.h>
 #include <wtf/RefCounted.h>
 
@@ -36,16 +37,30 @@
         return adoptRef(*new VRPose);
     }
 
-    Float32Array* position() const;
-    Float32Array* linearVelocity() const;
-    Float32Array* linearAcceleration() const;
+    static Ref<VRPose> create(const VRPlatformTrackingInfo& trackingInfo)
+    {
+        return adoptRef(*new VRPose(trackingInfo));
+    }
 
-    Float32Array* orientation() const;
-    Float32Array* angularVelocity() const;
-    Float32Array* angularAcceleration() const;
+    RefPtr<Float32Array> position() const;
+    RefPtr<Float32Array> linearVelocity() const;
+    RefPtr<Float32Array> linearAcceleration() const;
 
+    RefPtr<Float32Array> orientation() const;
+    RefPtr<Float32Array> angularVelocity() const;
+    RefPtr<Float32Array> angularAcceleration() const;
+
+    void update(const VRPlatformTrackingInfo& trackingInfo) { m_trackingInfo = trackingInfo; };
+
 private:
-    VRPose();
+    VRPose() = default;
+
+    VRPose(const VRPlatformTrackingInfo& trackingInfo)
+        : m_trackingInfo(trackingInfo)
+    {
+    }
+
+    VRPlatformTrackingInfo m_trackingInfo;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/vr/VRPlatformDisplay.h (230427 => 230428)


--- trunk/Source/WebCore/platform/vr/VRPlatformDisplay.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/platform/vr/VRPlatformDisplay.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -103,9 +103,64 @@
     std::optional<TransformationMatrix> m_sittingToStandingTransform;
 };
 
+struct VRPlatformTrackingInfo {
+    struct Quaternion {
+        Quaternion()
+            : x(0), y(0), z(0), w(1) { }
+
+        Quaternion(float x, float y, float z, float w)
+            : x(x), y(y), z(z), w(w) { }
+
+        Quaternion& conjugate()
+        {
+            x *= -1;
+            y *= -1;
+            z *= -1;
+            return *this;
+        }
+
+        Quaternion& operator*(float factor)
+        {
+            x *= factor;
+            y *= factor;
+            z *= factor;
+            w *= factor;
+            return *this;
+        }
+        float x, y, z, w;
+    };
+
+    struct Float3 {
+        Float3(float a, float b, float c)
+            : data { a, b, c } { }
+
+        float data[3];
+    };
+
+    void clear()
+    {
+        timestamp = 0;
+        position = std::nullopt;
+        orientation = std::nullopt;
+        angularAcceleration = std::nullopt;
+        angularVelocity = std::nullopt;
+        linearAcceleration = std::nullopt;
+        linearVelocity = std::nullopt;
+    }
+
+    std::optional<Quaternion> orientation;
+    std::optional<FloatPoint3D> position;
+    std::optional<Float3> angularAcceleration;
+    std::optional<Float3> angularVelocity;
+    std::optional<Float3> linearAcceleration;
+    std::optional<Float3> linearVelocity;
+    double timestamp { 0 };
+};
+
 class VRPlatformDisplay {
 public:
     virtual VRPlatformDisplayInfo getDisplayInfo() = 0;
+    virtual VRPlatformTrackingInfo getTrackingInfo() = 0;
     virtual ~VRPlatformDisplay() = default;
 
     WeakPtr<VRPlatformDisplay> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(*this); }

Modified: trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.cpp (230427 => 230428)


--- trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.cpp	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.cpp	2018-04-09 14:40:51 UTC (rev 230428)
@@ -50,6 +50,8 @@
     // FIXME: We're assuming an HTC Vive HMD here. Get this info from OpenVR?.
     m_displayInfo.setCapabilityFlags(VRDisplayCapabilityFlag::None | VRDisplayCapabilityFlag::Position | VRDisplayCapabilityFlag::Orientation | VRDisplayCapabilityFlag::ExternalDisplay | VRDisplayCapabilityFlag::Present);
 
+    m_compositor->SetTrackingSpace(vr::TrackingUniverseSeated);
+
     updateEyeParameters();
     updateStageParameters();
 }
@@ -99,6 +101,63 @@
     m_displayInfo.setPlayAreaBounds(FloatSize(playAreaWidth, playAreaDepth));
 }
 
+// FIXME: we might want to generalize this function for other backends.
+static VRPlatformTrackingInfo::Quaternion rotationMatrixToQuaternion(const float (&matrix)[3][4])
+{
+    // See https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf.
+    VRPlatformTrackingInfo::Quaternion quaternion;
+    float trace;
+    if (matrix[2][2] < 0) {
+        if (matrix[0][0] > matrix[1][1]) {
+            trace = 1 + matrix[0][0] - matrix[1][1] - matrix[2][2];
+            quaternion = { trace, matrix[0][1]+matrix[1][0], matrix[2][0]+matrix[0][2], matrix[1][2] - matrix[2][1] };
+        } else {
+            trace = 1 - matrix[0][0] + matrix[1][1] - matrix[2][2];
+            quaternion = { matrix[0][1]+matrix[1][0], trace, matrix[1][2]+matrix[2][1], matrix[2][0] - matrix[0][2] };
+        }
+    } else {
+        if (matrix[0][0] < -matrix[1][1]) {
+            trace = 1 - matrix[0][0] - matrix[1][1] + matrix[2][2];
+            quaternion = { matrix[2][0]+matrix[0][2], matrix[1][2]+matrix[2][1], trace , matrix[0][1] - matrix[1][0] };
+        } else {
+            trace = 1 + matrix[0][0] + matrix[1][1] + matrix[2][2];
+            quaternion = { matrix[1][2] - matrix[2][1], matrix[2][0] - matrix[0][2], matrix[0][1] - matrix[1][0], trace };
+        }
+    }
+    return quaternion * (0.5 / sqrt(trace));
+}
+
+VRPlatformTrackingInfo VRPlatformDisplayOpenVR::getTrackingInfo()
+{
+    vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];
+
+    m_compositor->WaitGetPoses(nullptr, 0, poses, vr::k_unMaxTrackedDeviceCount);
+
+    m_trackingInfo.clear();
+
+    vr::Compositor_FrameTiming timing;
+    timing.m_nSize = sizeof(vr::Compositor_FrameTiming);
+    m_compositor->GetFrameTiming(&timing);
+    m_trackingInfo.timestamp = timing.m_flSystemTimeInSeconds;
+
+    if (!poses[vr::k_unTrackedDeviceIndex_Hmd].bDeviceIsConnected
+        || !poses[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid
+        || poses[vr::k_unTrackedDeviceIndex_Hmd].eTrackingResult != vr::TrackingResult_Running_OK) {
+        // FIXME: Init some data maybe???.
+        return m_trackingInfo;
+    }
+
+    const auto& HMDPose = poses[vr::k_unTrackedDeviceIndex_Hmd];
+    const auto& transform = HMDPose.mDeviceToAbsoluteTracking;
+    m_trackingInfo.orientation = rotationMatrixToQuaternion(transform.m);
+    m_trackingInfo.orientation->conjugate();
+    m_trackingInfo.position = FloatPoint3D(transform.m[0][3], transform.m[1][3], transform.m[2][3]);
+    m_trackingInfo.angularVelocity = VRPlatformTrackingInfo::Float3(HMDPose.vAngularVelocity.v[0], HMDPose.vAngularVelocity.v[1], HMDPose.vAngularVelocity.v[2]);
+    m_trackingInfo.linearVelocity = VRPlatformTrackingInfo::Float3(HMDPose.vVelocity.v[0], HMDPose.vVelocity.v[1], HMDPose.vVelocity.v[2]);
+
+    return m_trackingInfo;
+}
+
 }; // namespace WebCore
 
 #endif // USE(OPENVR)

Modified: trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.h (230427 => 230428)


--- trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.h	2018-04-09 13:56:21 UTC (rev 230427)
+++ trunk/Source/WebCore/platform/vr/openvr/VRPlatformDisplayOpenVR.h	2018-04-09 14:40:51 UTC (rev 230428)
@@ -34,6 +34,7 @@
 
     ~VRPlatformDisplayOpenVR() = default;
     VRPlatformDisplayInfo getDisplayInfo() override { return m_displayInfo; }
+    VRPlatformTrackingInfo getTrackingInfo() override;
 
 private:
     VRPlatformDisplayInfo::FieldOfView computeFieldOfView(vr::Hmd_Eye);
@@ -47,6 +48,7 @@
     vr::IVRCompositor* m_compositor;
 
     VRPlatformDisplayInfo m_displayInfo;
+    VRPlatformTrackingInfo m_trackingInfo;
 };
 
 }; // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to