Use Optional::valueOr() instead of Optional::value_or()
[WebKit-https.git] / Source / WebCore / Modules / webvr / VRFrameData.cpp
1 /*
2  * Copyright (C) 2017 Igalia S.L. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "config.h"
26 #include "VRFrameData.h"
27
28 #include "VREyeParameters.h"
29 #include "VRPlatformDisplay.h"
30 #include "VRPose.h"
31
32 namespace WebCore {
33
34 VRFrameData::VRFrameData()
35     : m_pose(VRPose::create())
36 {
37 }
38
39 static Ref<Float32Array> matrixToArray(const TransformationMatrix& matrix)
40 {
41     auto columnMajorMatrix = matrix.toColumnMajorFloatArray();
42     return Float32Array::create(columnMajorMatrix.data(), 16);
43 }
44
45 Ref<Float32Array> VRFrameData::leftProjectionMatrix() const
46 {
47     return matrixToArray(m_leftProjectionMatrix);
48 }
49
50 Ref<Float32Array> VRFrameData::leftViewMatrix() const
51 {
52     return matrixToArray(m_leftViewMatrix);
53 }
54
55 Ref<Float32Array> VRFrameData::rightProjectionMatrix() const
56 {
57     return matrixToArray(m_rightProjectionMatrix);
58 }
59
60 Ref<Float32Array> VRFrameData::rightViewMatrix() const
61 {
62     return matrixToArray(m_rightViewMatrix);
63 }
64
65 const VRPose& VRFrameData::pose() const
66 {
67     return m_pose;
68 }
69
70 static TransformationMatrix projectionMatrixFromFieldOfView(const VRFieldOfView& fov, double depthNear, double depthFar)
71 {
72     double upTan = tan(deg2rad(fov.upDegrees()));
73     double downTan = tan(deg2rad(fov.downDegrees()));
74     double leftTan = tan(deg2rad(fov.leftDegrees()));
75     double rightTan = tan(deg2rad(fov.rightDegrees()));
76
77     double xScale = 2 / (leftTan + rightTan);
78     double yScale = 2 / (upTan + downTan);
79
80     TransformationMatrix projectionMatrix;
81     projectionMatrix.setM11(xScale);
82     projectionMatrix.setM22(yScale);
83     projectionMatrix.setM32((upTan - downTan) * yScale * 0.5);
84     projectionMatrix.setM31(-((leftTan - rightTan) * xScale * 0.5));
85     projectionMatrix.setM33((depthNear + depthFar) / (depthNear - depthFar));
86     projectionMatrix.setM34(-1);
87     projectionMatrix.setM43((2 * depthFar * depthNear) / (depthNear - depthFar));
88     projectionMatrix.setM44(0);
89
90     return projectionMatrix;
91 }
92
93 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
94 static TransformationMatrix rotationMatrixFromQuaternion(const VRPlatformTrackingInfo::Quaternion& quaternion)
95 {
96     double magnitude = (quaternion.x * quaternion.x) + (quaternion.y * quaternion.y) + (quaternion.z * quaternion.z) + (quaternion.w * quaternion.w);
97     VRPlatformTrackingInfo::Quaternion normalizedQuaternion(quaternion.x / magnitude, quaternion.y / magnitude, quaternion.z / magnitude, quaternion.w / magnitude);
98     double x2 = normalizedQuaternion.x * normalizedQuaternion.x;
99     double y2 = normalizedQuaternion.y * normalizedQuaternion.y;
100     double z2 = normalizedQuaternion.z * normalizedQuaternion.z;
101     double w2 = normalizedQuaternion.w * normalizedQuaternion.w;
102     double xy = normalizedQuaternion.x * normalizedQuaternion.y;
103     double zw = normalizedQuaternion.z * normalizedQuaternion.w;
104     double xz = normalizedQuaternion.x * normalizedQuaternion.z;
105     double yw = normalizedQuaternion.y * normalizedQuaternion.w;
106     double yz = normalizedQuaternion.y * normalizedQuaternion.z;
107     double xw = normalizedQuaternion.x * normalizedQuaternion.w;
108
109     return TransformationMatrix(
110         x2 - y2 - z2 + w2, 2.0 * (xy - zw), 2.0 * (xz + yw), 0,
111         2.0 * (xy + zw), -x2 + y2 - z2 + w2, 2.0 * (yz - xw), 0,
112         2.0 * (xz - yw), 2.0 * (yz + xw), -x2 - y2 + z2 + w2, 0,
113         0, 0, 0, 1);
114 }
115
116 static void applyHeadToEyeTransform(TransformationMatrix& matrix, const FloatPoint3D& translation)
117 {
118     matrix.setM41(matrix.m41() - translation.x());
119     matrix.setM42(matrix.m42() - translation.y());
120     matrix.setM43(matrix.m43() - translation.z());
121 }
122
123 void VRFrameData::update(const VRPlatformTrackingInfo& trackingInfo, const VREyeParameters& leftEye, const VREyeParameters& rightEye, double depthNear, double depthFar)
124 {
125     m_leftProjectionMatrix = projectionMatrixFromFieldOfView(leftEye.fieldOfView(), depthNear, depthFar);
126     m_rightProjectionMatrix = projectionMatrixFromFieldOfView(rightEye.fieldOfView(), depthNear, depthFar);
127
128     m_timestamp = trackingInfo.timestamp;
129     m_pose->update(trackingInfo);
130
131     auto rotationMatrix = rotationMatrixFromQuaternion(trackingInfo.orientation.valueOr(VRPlatformTrackingInfo::Quaternion(0, 0, 0, 1)));
132     FloatPoint3D position = trackingInfo.position.valueOr(FloatPoint3D(0, 0, 0));
133     rotationMatrix.translate3d(-position.x(), -position.y(), -position.z());
134
135     m_leftViewMatrix = rotationMatrix;
136     applyHeadToEyeTransform(m_leftViewMatrix, leftEye.rawOffset());
137
138     m_rightViewMatrix = rotationMatrix;
139     applyHeadToEyeTransform(m_rightViewMatrix, rightEye.rawOffset());
140 }
141
142 } // namespace WebCore