OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/android/vr_shell/vr_math.h" | |
6 | |
7 #include <cmath> | |
8 | |
9 #include "base/logging.h" | |
10 | |
11 namespace vr_shell { | |
12 | |
13 // Internal matrix layout: | |
14 // | |
15 // m[0][0], m[0][1], m[0][2], m[0][3], | |
16 // m[1][0], m[1][1], m[1][2], m[1][3], | |
17 // m[2][0], m[2][1], m[2][2], m[2][3], | |
18 // m[3][0], m[3][1], m[3][2], m[3][3], | |
19 // | |
20 // The translation component is in the right column m[i][3]. | |
21 // | |
22 // The bottom row m[3][i] is (0, 0, 0, 1) for non-perspective transforms. | |
23 // | |
24 // These matrices are intended to be used to premultiply column vectors | |
25 // for transforms, so successive transforms need to be left-multiplied. | |
26 | |
27 void SetIdentityM(gvr::Mat4f& mat) { | |
28 float* m = reinterpret_cast<float*>(mat.m); | |
29 for (int i = 0; i < 16; i++) { | |
30 m[i] = 0; | |
31 } | |
32 for (int i = 0; i < 16; i += 5) { | |
33 m[i] = 1.0f; | |
34 } | |
35 } | |
36 | |
37 // Left multiply a translation matrix. | |
38 void TranslateM(gvr::Mat4f& tmat, gvr::Mat4f& mat, float x, float y, float z) { | |
39 if (&tmat != &mat) { | |
40 for (int i = 0; i < 4; ++i) { | |
41 for (int j = 0; j < 4; ++j) { | |
42 tmat.m[i][j] = mat.m[i][j]; | |
43 } | |
44 } | |
45 } | |
46 tmat.m[0][3] += x; | |
47 tmat.m[1][3] += y; | |
48 tmat.m[2][3] += z; | |
49 } | |
50 | |
51 // Left multiply a scale matrix. | |
52 void ScaleM(gvr::Mat4f& tmat, | |
53 const gvr::Mat4f& mat, | |
54 float x, | |
55 float y, | |
56 float z) { | |
57 if (&tmat != &mat) { | |
58 for (int i = 0; i < 4; ++i) { | |
59 for (int j = 0; j < 3; ++j) { | |
60 tmat.m[i][j] = mat.m[i][j]; | |
61 } | |
62 } | |
63 } | |
64 // Multiply all rows including translation components. | |
65 for (int j = 0; j < 4; ++j) { | |
66 tmat.m[0][j] *= x; | |
67 tmat.m[1][j] *= y; | |
68 tmat.m[2][j] *= z; | |
69 } | |
70 } | |
71 | |
72 gvr::Vec3f MatrixVectorMul(const gvr::Mat4f& m, const gvr::Vec3f& v) { | |
73 gvr::Vec3f res; | |
74 res.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]; | |
75 res.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]; | |
76 res.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]; | |
77 return res; | |
78 } | |
79 | |
80 // Rotation only, ignore translation components. | |
81 gvr::Vec3f MatrixVectorRotate(const gvr::Mat4f& m, const gvr::Vec3f& v) { | |
82 gvr::Vec3f res; | |
83 res.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z; | |
84 res.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z; | |
85 res.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z; | |
86 return res; | |
87 } | |
88 | |
89 gvr::Mat4f MatrixMul(const gvr::Mat4f& matrix1, const gvr::Mat4f& matrix2) { | |
90 gvr::Mat4f result; | |
91 for (int i = 0; i < 4; ++i) { | |
92 for (int j = 0; j < 4; ++j) { | |
93 result.m[i][j] = 0.0f; | |
94 for (int k = 0; k < 4; ++k) { | |
95 result.m[i][j] += matrix1.m[i][k] * matrix2.m[k][j]; | |
96 } | |
97 } | |
98 } | |
99 return result; | |
100 } | |
101 | |
102 gvr::Mat4f PerspectiveMatrixFromView(const gvr::Rectf& fov, | |
103 float z_near, | |
104 float z_far) { | |
105 gvr::Mat4f result; | |
106 const float x_left = -std::tan(fov.left * M_PI / 180.0f) * z_near; | |
107 const float x_right = std::tan(fov.right * M_PI / 180.0f) * z_near; | |
108 const float y_bottom = -std::tan(fov.bottom * M_PI / 180.0f) * z_near; | |
109 const float y_top = std::tan(fov.top * M_PI / 180.0f) * z_near; | |
110 | |
111 DCHECK(x_left < x_right && y_bottom < y_top && z_near < z_far && | |
112 z_near > 0.0f && z_far > 0.0f); | |
113 const float X = (2 * z_near) / (x_right - x_left); | |
114 const float Y = (2 * z_near) / (y_top - y_bottom); | |
115 const float A = (x_right + x_left) / (x_right - x_left); | |
116 const float B = (y_top + y_bottom) / (y_top - y_bottom); | |
117 const float C = (z_near + z_far) / (z_near - z_far); | |
118 const float D = (2 * z_near * z_far) / (z_near - z_far); | |
119 | |
120 for (int i = 0; i < 4; ++i) { | |
121 for (int j = 0; j < 4; ++j) { | |
122 result.m[i][j] = 0.0f; | |
123 } | |
124 } | |
125 result.m[0][0] = X; | |
126 result.m[0][2] = A; | |
127 result.m[1][1] = Y; | |
128 result.m[1][2] = B; | |
129 result.m[2][2] = C; | |
130 result.m[2][3] = D; | |
131 result.m[3][2] = -1; | |
132 | |
133 return result; | |
134 } | |
135 | |
136 gvr::Vec3f GetForwardVector(const gvr::Mat4f& matrix) { | |
137 // Same as multiplying the inverse of the rotation component of the matrix by | |
138 // (0, 0, -1, 0). | |
139 return {-matrix.m[2][0], -matrix.m[2][1], -matrix.m[2][2]}; | |
140 } | |
141 | |
142 gvr::Vec3f GetTranslation(const gvr::Mat4f& matrix) { | |
143 return {matrix.m[0][3], matrix.m[1][3], matrix.m[2][3]}; | |
144 } | |
145 | |
146 float VectorLength(const gvr::Vec3f& vec) { | |
147 return sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z); | |
148 } | |
149 | |
150 gvr::Vec3f VectorSubtract(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
151 return {a.x - b.x, a.y - b.y, a.z - b.z}; | |
152 } | |
153 | |
154 float NormalizeVector(gvr::Vec3f& vec) { | |
155 float len = VectorLength(vec); | |
156 vec.x /= len; | |
157 vec.y /= len; | |
158 vec.z /= len; | |
159 return len; | |
160 } | |
161 | |
162 float VectorDot(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
163 return a.x * b.x + a.y * b.y + a.z * b.z; | |
164 } | |
165 | |
166 void NormalizeQuat(gvr::Quatf& quat) { | |
167 float len = sqrt(quat.qx * quat.qx + quat.qy * quat.qy + quat.qz * quat.qz + | |
168 quat.qw * quat.qw); | |
169 quat.qx /= len; | |
170 quat.qy /= len; | |
171 quat.qz /= len; | |
172 quat.qw /= len; | |
173 } | |
174 | |
175 gvr::Quatf QuatFromAxisAngle(const gvr::Vec3f& axis, float angle) { | |
176 // Rotation angle is the product of |angle| and the magnitude of |axis|. | |
177 gvr::Vec3f normal = axis; | |
178 float length = NormalizeVector(normal); | |
179 angle *= length; | |
180 | |
181 gvr::Quatf res; | |
182 float s = sin(angle / 2); | |
183 res.qx = normal.x * s; | |
184 res.qy = normal.y * s; | |
185 res.qz = normal.z * s; | |
186 res.qw = cos(angle / 2); | |
187 return res; | |
188 } | |
189 | |
190 gvr::Quatf QuatMultiply(const gvr::Quatf& a, const gvr::Quatf& b) { | |
191 gvr::Quatf res; | |
192 res.qw = a.qw * b.qw - a.qx * b.qx - a.qy * b.qy - a.qz * b.qz; | |
193 res.qx = a.qw * b.qx + a.qx * b.qw + a.qy * b.qz - a.qz * b.qy; | |
194 res.qy = a.qw * b.qy - a.qx * b.qz + a.qy * b.qw + a.qz * b.qx; | |
195 res.qz = a.qw * b.qz + a.qx * b.qy - a.qy * b.qx + a.qz * b.qw; | |
196 return res; | |
197 } | |
198 | |
199 gvr::Mat4f QuatToMatrix(const gvr::Quatf& quat) { | |
200 const float x2 = quat.qx * quat.qx; | |
201 const float y2 = quat.qy * quat.qy; | |
202 const float z2 = quat.qz * quat.qz; | |
203 const float xy = quat.qx * quat.qy; | |
204 const float xz = quat.qx * quat.qz; | |
205 const float xw = quat.qx * quat.qw; | |
206 const float yz = quat.qy * quat.qz; | |
207 const float yw = quat.qy * quat.qw; | |
208 const float zw = quat.qz * quat.qw; | |
209 | |
210 const float m11 = 1.0f - 2.0f * y2 - 2.0f * z2; | |
211 const float m12 = 2.0f * (xy - zw); | |
212 const float m13 = 2.0f * (xz + yw); | |
213 const float m21 = 2.0f * (xy + zw); | |
214 const float m22 = 1.0f - 2.0f * x2 - 2.0f * z2; | |
215 const float m23 = 2.0f * (yz - xw); | |
216 const float m31 = 2.0f * (xz - yw); | |
217 const float m32 = 2.0f * (yz + xw); | |
218 const float m33 = 1.0f - 2.0f * x2 - 2.0f * y2; | |
219 | |
220 return {{{m11, m12, m13, 0.0f}, | |
221 {m21, m22, m23, 0.0f}, | |
222 {m31, m32, m33, 0.0f}, | |
223 {0.0f, 0.0f, 0.0f, 1.0f}}}; | |
224 } | |
225 | |
226 gvr::Vec3f GetRayPoint(const gvr::Vec3f& rayOrigin, | |
227 const gvr::Vec3f& rayVector, | |
228 float scale) { | |
229 gvr::Vec3f v; | |
230 v.x = rayOrigin.x + scale * rayVector.x; | |
231 v.y = rayOrigin.y + scale * rayVector.y; | |
232 v.z = rayOrigin.z + scale * rayVector.z; | |
233 return v; | |
234 } | |
235 | |
236 float Distance(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2) { | |
237 return VectorLength(VectorSubtract(vec1, vec2)); | |
238 } | |
239 | |
240 bool XZAngle(const gvr::Vec3f& vec1, const gvr::Vec3f& vec2, float* angle) { | |
241 float len1 = VectorLength(vec1); | |
242 float len2 = VectorLength(vec2); | |
243 if (len1 == 0 || len2 == 0) | |
244 return false; | |
245 float cross_p = vec1.x * vec2.z - vec1.z * vec2.x; | |
246 *angle = asin(cross_p / (len1 * len2)); | |
247 return true; | |
248 } | |
249 | |
250 } // namespace vr_shell | |
OLD | NEW |