OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/vr_shell/vr_math.h" | 5 #include "chrome/browser/android/vr_shell/vr_math.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... | |
27 void SetIdentityM(gvr::Mat4f& mat) { | 27 void SetIdentityM(gvr::Mat4f& mat) { |
28 float* m = reinterpret_cast<float*>(mat.m); | 28 float* m = reinterpret_cast<float*>(mat.m); |
29 for (int i = 0; i < 16; i++) { | 29 for (int i = 0; i < 16; i++) { |
30 m[i] = 0; | 30 m[i] = 0; |
31 } | 31 } |
32 for (int i = 0; i < 16; i += 5) { | 32 for (int i = 0; i < 16; i += 5) { |
33 m[i] = 1.0f; | 33 m[i] = 1.0f; |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 // Left multiply a translation matrix. | |
38 void TranslateM(gvr::Mat4f& tmat, gvr::Mat4f& mat, float x, float y, float z) { | 37 void TranslateM(gvr::Mat4f& tmat, gvr::Mat4f& mat, float x, float y, float z) { |
39 if (&tmat != &mat) { | 38 if (&tmat != &mat) { |
40 for (int i = 0; i < 4; ++i) { | 39 for (int i = 0; i < 4; ++i) { |
41 for (int j = 0; j < 4; ++j) { | 40 for (int j = 0; j < 4; ++j) { |
42 tmat.m[i][j] = mat.m[i][j]; | 41 tmat.m[i][j] = mat.m[i][j]; |
43 } | 42 } |
44 } | 43 } |
45 } | 44 } |
46 tmat.m[0][3] += x; | 45 tmat.m[0][3] += x; |
47 tmat.m[1][3] += y; | 46 tmat.m[1][3] += y; |
48 tmat.m[2][3] += z; | 47 tmat.m[2][3] += z; |
49 } | 48 } |
50 | 49 |
51 // Left multiply a scale matrix. | |
52 void ScaleM(gvr::Mat4f& tmat, | 50 void ScaleM(gvr::Mat4f& tmat, |
53 const gvr::Mat4f& mat, | 51 const gvr::Mat4f& mat, |
54 float x, | 52 float x, |
55 float y, | 53 float y, |
56 float z) { | 54 float z) { |
57 if (&tmat != &mat) { | 55 if (&tmat != &mat) { |
58 for (int i = 0; i < 4; ++i) { | 56 for (int i = 0; i < 4; ++i) { |
59 for (int j = 0; j < 3; ++j) { | 57 for (int j = 0; j < 3; ++j) { |
60 tmat.m[i][j] = mat.m[i][j]; | 58 tmat.m[i][j] = mat.m[i][j]; |
61 } | 59 } |
62 } | 60 } |
63 } | 61 } |
64 // Multiply all rows including translation components. | 62 // Multiply all rows including translation components. |
65 for (int j = 0; j < 4; ++j) { | 63 for (int j = 0; j < 4; ++j) { |
66 tmat.m[0][j] *= x; | 64 tmat.m[0][j] *= x; |
67 tmat.m[1][j] *= y; | 65 tmat.m[1][j] *= y; |
68 tmat.m[2][j] *= z; | 66 tmat.m[2][j] *= z; |
69 } | 67 } |
70 } | 68 } |
71 | 69 |
70 float Clampf(float value, float min, float max) { | |
cjgrant
2017/04/03 19:25:00
std::clamp is a thing, maybe we should use it inst
acondor_
2017/04/19 18:44:27
I checked, and it is a C++17 feature.
| |
71 if (value < min) | |
72 return min; | |
73 if (value > max) | |
74 return max; | |
75 return value; | |
76 } | |
77 | |
78 float ToDegrees(float radians) { | |
79 return (radians * 180.f) / M_PI; | |
cjgrant
2017/04/03 19:24:59
No braces needed here.
acondor_
2017/04/19 18:44:27
Done.
| |
80 } | |
81 | |
82 gvr::Vec3f QuatSlerp(gvr::Vec3f start, gvr::Vec3f end, float percent) { | |
83 NormalizeVector(start); | |
84 NormalizeVector(end); | |
85 float dot = Clampf(VectorDot(start, end), -1.f, 1.f); | |
cjgrant
2017/04/03 19:25:00
1.0f etc?
acondor_
2017/04/19 18:44:27
Done.
| |
86 float theta = acos(dot) * percent; | |
87 auto relative_vec = VectorSubtract(end, VectorScalarMul(start, dot)); | |
88 NormalizeVector(relative_vec); | |
89 return VectorAdd(VectorScalarMul(start, cos(theta)), | |
90 VectorScalarMul(relative_vec, sin(theta))); | |
91 } | |
92 | |
72 gvr::Vec3f MatrixVectorMul(const gvr::Mat4f& m, const gvr::Vec3f& v) { | 93 gvr::Vec3f MatrixVectorMul(const gvr::Mat4f& m, const gvr::Vec3f& v) { |
73 gvr::Vec3f res; | 94 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]; | 95 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]; | 96 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]; | 97 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; | 98 return res; |
78 } | 99 } |
79 | 100 |
80 // Rotation only, ignore translation components. | |
81 gvr::Vec3f MatrixVectorRotate(const gvr::Mat4f& m, const gvr::Vec3f& v) { | 101 gvr::Vec3f MatrixVectorRotate(const gvr::Mat4f& m, const gvr::Vec3f& v) { |
82 gvr::Vec3f res; | 102 gvr::Vec3f res; |
83 res.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z; | 103 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; | 104 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; | 105 res.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z; |
86 return res; | 106 return res; |
87 } | 107 } |
88 | 108 |
89 gvr::Mat4f MatrixMul(const gvr::Mat4f& matrix1, const gvr::Mat4f& matrix2) { | 109 gvr::Mat4f MatrixMul(const gvr::Mat4f& matrix1, const gvr::Mat4f& matrix2) { |
90 gvr::Mat4f result; | 110 gvr::Mat4f result; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 gvr::Vec3f GetForwardVector(const gvr::Mat4f& matrix) { | 156 gvr::Vec3f GetForwardVector(const gvr::Mat4f& matrix) { |
137 // Same as multiplying the inverse of the rotation component of the matrix by | 157 // Same as multiplying the inverse of the rotation component of the matrix by |
138 // (0, 0, -1, 0). | 158 // (0, 0, -1, 0). |
139 return {-matrix.m[2][0], -matrix.m[2][1], -matrix.m[2][2]}; | 159 return {-matrix.m[2][0], -matrix.m[2][1], -matrix.m[2][2]}; |
140 } | 160 } |
141 | 161 |
142 gvr::Vec3f GetTranslation(const gvr::Mat4f& matrix) { | 162 gvr::Vec3f GetTranslation(const gvr::Mat4f& matrix) { |
143 return {matrix.m[0][3], matrix.m[1][3], matrix.m[2][3]}; | 163 return {matrix.m[0][3], matrix.m[1][3], matrix.m[2][3]}; |
144 } | 164 } |
145 | 165 |
166 float VectorLengthSquared(const gvr::Vec3f& vec) { | |
167 return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z; | |
168 } | |
169 | |
146 float VectorLength(const gvr::Vec3f& vec) { | 170 float VectorLength(const gvr::Vec3f& vec) { |
147 return sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z); | 171 return sqrt(VectorLengthSquared(vec)); |
148 } | 172 } |
149 | 173 |
150 gvr::Vec3f VectorSubtract(const gvr::Vec3f& a, const gvr::Vec3f& b) { | 174 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}; | 175 return {a.x - b.x, a.y - b.y, a.z - b.z}; |
152 } | 176 } |
153 | 177 |
178 gvr::Vec3f VectorAdd(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
179 return {a.x + b.x, a.y + b.y, a.z + b.z}; | |
180 } | |
181 | |
154 float NormalizeVector(gvr::Vec3f& vec) { | 182 float NormalizeVector(gvr::Vec3f& vec) { |
155 float len = VectorLength(vec); | 183 float len = VectorLength(vec); |
156 vec.x /= len; | 184 if (len != 0.0f) |
157 vec.y /= len; | 185 len = 1.f / len; |
158 vec.z /= len; | 186 vec.x *= len; |
187 vec.y *= len; | |
188 vec.z *= len; | |
159 return len; | 189 return len; |
160 } | 190 } |
161 | 191 |
162 float VectorDot(const gvr::Vec3f& a, const gvr::Vec3f& b) { | 192 float VectorDot(const gvr::Vec3f& a, const gvr::Vec3f& b) { |
163 return a.x * b.x + a.y * b.y + a.z * b.z; | 193 return a.x * b.x + a.y * b.y + a.z * b.z; |
164 } | 194 } |
165 | 195 |
196 gvr::Vec3f VectorCross(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
197 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; | |
198 } | |
199 | |
200 gvr::Vec3f PointwiseVectorMul(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
201 return {a.x * b.x, a.y * b.y, a.z * b.z}; | |
202 } | |
203 | |
204 gvr::Vec3f VectorScalarMul(const gvr::Vec3f& a, float s) { | |
205 return {a.x * s, a.y * s, a.z * s}; | |
206 } | |
207 | |
208 float VectorAngleDegrees(const gvr::Vec3f& a, const gvr::Vec3f& b) { | |
209 float angle_radians = acos(VectorDot(a, b)); | |
210 return ToDegrees(angle_radians); | |
cjgrant
2017/04/03 19:24:59
Could drop the intermediate variable here.
acondor_
2017/04/19 18:44:27
Done.
| |
211 } | |
212 | |
166 void NormalizeQuat(gvr::Quatf& quat) { | 213 void NormalizeQuat(gvr::Quatf& quat) { |
167 float len = sqrt(quat.qx * quat.qx + quat.qy * quat.qy + quat.qz * quat.qz + | 214 float len = sqrt(quat.qx * quat.qx + quat.qy * quat.qy + quat.qz * quat.qz + |
168 quat.qw * quat.qw); | 215 quat.qw * quat.qw); |
169 quat.qx /= len; | 216 quat.qx /= len; |
170 quat.qy /= len; | 217 quat.qy /= len; |
171 quat.qz /= len; | 218 quat.qz /= len; |
172 quat.qw /= len; | 219 quat.qw /= len; |
173 } | 220 } |
174 | 221 |
222 gvr::Quatf QuatInverted(const gvr::Quatf& quat) { | |
223 return {-quat.qx, -quat.qy, -quat.qz, quat.qw}; | |
224 } | |
225 | |
226 float QuatAngleDegrees(const gvr::Quatf& a, const gvr::Quatf& b) { | |
227 return QuatMultiply(b, QuatInverted(a)).qw; | |
228 } | |
229 | |
230 gvr::Quatf QuatLerp(const gvr::Quatf& a, const gvr::Quatf& b, float t) { | |
231 auto result = QuatAdd(QuatScalarMul(a, 1.f - t), QuatScalarMul(b, t)); | |
232 NormalizeQuat(result); | |
cjgrant
2017/04/03 19:24:59
With the quantity of math changes here, it might b
acondor_
2017/04/19 18:44:27
The change was already done. I just need to rebase
| |
233 return result; | |
234 } | |
235 | |
175 gvr::Quatf QuatFromAxisAngle(const gvr::Vec3f& axis, float angle) { | 236 gvr::Quatf QuatFromAxisAngle(const gvr::Vec3f& axis, float angle) { |
176 // Rotation angle is the product of |angle| and the magnitude of |axis|. | 237 // Rotation angle is the product of |angle| and the magnitude of |axis|. |
177 gvr::Vec3f normal = axis; | 238 gvr::Vec3f normal = axis; |
178 float length = NormalizeVector(normal); | 239 float length = NormalizeVector(normal); |
179 angle *= length; | 240 angle *= length; |
180 | 241 |
181 gvr::Quatf res; | 242 gvr::Quatf res; |
182 float s = sin(angle / 2); | 243 float s = sin(angle / 2); |
183 res.qx = normal.x * s; | 244 res.qx = normal.x * s; |
184 res.qy = normal.y * s; | 245 res.qy = normal.y * s; |
185 res.qz = normal.z * s; | 246 res.qz = normal.z * s; |
186 res.qw = cos(angle / 2); | 247 res.qw = cos(angle / 2); |
187 return res; | 248 return res; |
188 } | 249 } |
189 | 250 |
251 gvr::Quatf FromToRotation(const gvr::Vec3f& from, const gvr::Vec3f& to) { | |
252 float dot = VectorDot(from, to); | |
253 float norm = sqrt(VectorLengthSquared(from) * VectorLengthSquared(to)); | |
254 float real = norm + dot; | |
255 gvr::Vec3f w; | |
256 if (real < 1.e-6f * norm) { | |
257 real = 0.f; | |
258 w = fabsf(from.x) > fabsf(from.z) ? gvr::Vec3f{-from.y, from.x, 0.f} | |
259 : gvr::Vec3f{0.f, -from.z, from.y}; | |
260 } else { | |
261 w = VectorCross(from, to); | |
262 } | |
263 gvr::Quatf result{w.x, w.y, w.z, real}; | |
264 NormalizeQuat(result); | |
265 return result; | |
266 } | |
267 | |
190 gvr::Quatf QuatMultiply(const gvr::Quatf& a, const gvr::Quatf& b) { | 268 gvr::Quatf QuatMultiply(const gvr::Quatf& a, const gvr::Quatf& b) { |
191 gvr::Quatf res; | 269 gvr::Quatf res; |
192 res.qw = a.qw * b.qw - a.qx * b.qx - a.qy * b.qy - a.qz * b.qz; | 270 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; | 271 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; | 272 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; | 273 res.qz = a.qw * b.qz + a.qx * b.qy - a.qy * b.qx + a.qz * b.qw; |
196 return res; | 274 return res; |
197 } | 275 } |
198 | 276 |
277 gvr::Quatf QuatAdd(const gvr::Quatf& a, const gvr::Quatf& b) { | |
278 return {a.qx + b.qx, a.qy + b.qy, a.qz + b.qz, a.qw + b.qw}; | |
279 } | |
280 | |
281 gvr::Quatf QuatScalarMul(const gvr::Quatf& quat, float s) { | |
282 return {quat.qx * s, quat.qy * s, quat.qz * s, quat.qw * s}; | |
283 } | |
284 | |
199 gvr::Mat4f QuatToMatrix(const gvr::Quatf& quat) { | 285 gvr::Mat4f QuatToMatrix(const gvr::Quatf& quat) { |
200 const float x2 = quat.qx * quat.qx; | 286 const float x2 = quat.qx * quat.qx; |
201 const float y2 = quat.qy * quat.qy; | 287 const float y2 = quat.qy * quat.qy; |
202 const float z2 = quat.qz * quat.qz; | 288 const float z2 = quat.qz * quat.qz; |
203 const float xy = quat.qx * quat.qy; | 289 const float xy = quat.qx * quat.qy; |
204 const float xz = quat.qx * quat.qz; | 290 const float xz = quat.qx * quat.qz; |
205 const float xw = quat.qx * quat.qw; | 291 const float xw = quat.qx * quat.qw; |
206 const float yz = quat.qy * quat.qz; | 292 const float yz = quat.qy * quat.qz; |
207 const float yw = quat.qy * quat.qw; | 293 const float yw = quat.qy * quat.qw; |
208 const float zw = quat.qz * quat.qw; | 294 const float zw = quat.qz * quat.qw; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 float len1 = VectorLength(vec1); | 327 float len1 = VectorLength(vec1); |
242 float len2 = VectorLength(vec2); | 328 float len2 = VectorLength(vec2); |
243 if (len1 == 0 || len2 == 0) | 329 if (len1 == 0 || len2 == 0) |
244 return false; | 330 return false; |
245 float cross_p = vec1.x * vec2.z - vec1.z * vec2.x; | 331 float cross_p = vec1.x * vec2.z - vec1.z * vec2.x; |
246 *angle = asin(cross_p / (len1 * len2)); | 332 *angle = asin(cross_p / (len1 * len2)); |
247 return true; | 333 return true; |
248 } | 334 } |
249 | 335 |
250 } // namespace vr_shell | 336 } // namespace vr_shell |
OLD | NEW |