RavEngine
Loading...
Searching...
No Matches
soa_float4x4.h
1//----------------------------------------------------------------------------//
2// //
3// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
4// and distributed under the MIT License (MIT). //
5// //
6// Copyright (c) Guillaume Blanc //
7// //
8// Permission is hereby granted, free of charge, to any person obtaining a //
9// copy of this software and associated documentation files (the "Software"), //
10// to deal in the Software without restriction, including without limitation //
11// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
12// and/or sell copies of the Software, and to permit persons to whom the //
13// Software is furnished to do so, subject to the following conditions: //
14// //
15// The above copyright notice and this permission notice shall be included in //
16// all copies or substantial portions of the Software. //
17// //
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
21// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
24// DEALINGS IN THE SOFTWARE. //
25// //
26//----------------------------------------------------------------------------//
27
28#ifndef OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
29#define OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
30
31#include <cassert>
32
33#include "ozz/base/maths/soa_float.h"
34#include "ozz/base/maths/soa_quaternion.h"
35#include "ozz/base/platform.h"
36
37namespace ozz {
38namespace math {
39
40// Declare the 4x4 soa matrix type. Uses the column major convention where the
41// matrix-times-vector is written v'=Mv:
42// [ m.cols[0].x m.cols[1].x m.cols[2].x m.cols[3].x ] {v.x}
43// | m.cols[0].y m.cols[1].y m.cols[2].y m.cols[3].y | * {v.y}
44// | m.cols[0].z m.cols[1].y m.cols[2].y m.cols[3].y | {v.z}
45// [ m.cols[0].w m.cols[1].w m.cols[2].w m.cols[3].w ] {v.1}
47 // Soa matrix columns.
48 SoaFloat4 cols[4];
49
50 // Returns the identity matrix.
51 static OZZ_INLINE SoaFloat4x4 identity() {
52 const SimdFloat4 zero = simd_float4::zero();
53 const SimdFloat4 one = simd_float4::one();
54 SoaFloat4x4 ret = {{{one, zero, zero, zero},
55 {zero, one, zero, zero},
56 {zero, zero, one, zero},
57 {zero, zero, zero, one}}};
58 return ret;
59 }
60
61 // Returns a scaling matrix that scales along _v.
62 // _v.w is ignored.
63 static OZZ_INLINE SoaFloat4x4 Scaling(const SoaFloat4& _v) {
64 const SimdFloat4 zero = simd_float4::zero();
65 const SimdFloat4 one = simd_float4::one();
66 const SoaFloat4x4 ret = {{{_v.x, zero, zero, zero},
67 {zero, _v.y, zero, zero},
68 {zero, zero, _v.z, zero},
69 {zero, zero, zero, one}}};
70 return ret;
71 }
72
73 // Returns the rotation matrix built from quaternion defined by x, y, z and w
74 // components of _v.
75 static OZZ_INLINE SoaFloat4x4 FromQuaternion(const SoaQuaternion& _q) {
76 assert(AreAllTrue(IsNormalizedEst(_q)));
77
78 const SimdFloat4 zero = simd_float4::zero();
79 const SimdFloat4 one = simd_float4::one();
80 const SimdFloat4 two = one + one;
81
82 const SimdFloat4 xx = _q.x * _q.x;
83 const SimdFloat4 xy = _q.x * _q.y;
84 const SimdFloat4 xz = _q.x * _q.z;
85 const SimdFloat4 xw = _q.x * _q.w;
86 const SimdFloat4 yy = _q.y * _q.y;
87 const SimdFloat4 yz = _q.y * _q.z;
88 const SimdFloat4 yw = _q.y * _q.w;
89 const SimdFloat4 zz = _q.z * _q.z;
90 const SimdFloat4 zw = _q.z * _q.w;
91
92 const SoaFloat4x4 ret = {
93 {{one - two * (yy + zz), two * (xy + zw), two * (xz - yw), zero},
94 {two * (xy - zw), one - two * (xx + zz), two * (yz + xw), zero},
95 {two * (xz + yw), two * (yz - xw), one - two * (xx + yy), zero},
96 {zero, zero, zero, one}}};
97 return ret;
98 }
99
100 // Returns the affine transformation matrix built from split translation,
101 // rotation (quaternion) and scale.
102 static OZZ_INLINE SoaFloat4x4 FromAffine(const SoaFloat3& _translation,
103 const SoaQuaternion& _quaternion,
104 const SoaFloat3& _scale) {
105 assert(AreAllTrue(IsNormalizedEst(_quaternion)));
106
107 const SimdFloat4 zero = simd_float4::zero();
108 const SimdFloat4 one = simd_float4::one();
109 const SimdFloat4 two = one + one;
110
111 const SimdFloat4 xx = _quaternion.x * _quaternion.x;
112 const SimdFloat4 xy = _quaternion.x * _quaternion.y;
113 const SimdFloat4 xz = _quaternion.x * _quaternion.z;
114 const SimdFloat4 xw = _quaternion.x * _quaternion.w;
115 const SimdFloat4 yy = _quaternion.y * _quaternion.y;
116 const SimdFloat4 yz = _quaternion.y * _quaternion.z;
117 const SimdFloat4 yw = _quaternion.y * _quaternion.w;
118 const SimdFloat4 zz = _quaternion.z * _quaternion.z;
119 const SimdFloat4 zw = _quaternion.z * _quaternion.w;
120
121 const SoaFloat4x4 ret = {
122 {{_scale.x * (one - two * (yy + zz)), _scale.x * two * (xy + zw),
123 _scale.x * two * (xz - yw), zero},
124 {_scale.y * two * (xy - zw), _scale.y * (one - two * (xx + zz)),
125 _scale.y * two * (yz + xw), zero},
126 {_scale.z * two * (xz + yw), _scale.z * two * (yz - xw),
127 _scale.z * (one - two * (xx + yy)), zero},
128 {_translation.x, _translation.y, _translation.z, one}}};
129 return ret;
130 }
131};
132
133// Returns the transpose of matrix _m.
134OZZ_INLINE SoaFloat4x4 Transpose(const SoaFloat4x4& _m) {
135 const SoaFloat4x4 ret = {
136 {{_m.cols[0].x, _m.cols[1].x, _m.cols[2].x, _m.cols[3].x},
137 {_m.cols[0].y, _m.cols[1].y, _m.cols[2].y, _m.cols[3].y},
138 {_m.cols[0].z, _m.cols[1].z, _m.cols[2].z, _m.cols[3].z},
139 {_m.cols[0].w, _m.cols[1].w, _m.cols[2].w, _m.cols[3].w}}};
140 return ret;
141}
142
143// Returns the inverse of matrix _m.
144// If _invertible is not nullptr, each component will be set to true if its
145// respective matrix is invertible. If _invertible is nullptr, then an assert is
146// triggered in case any of the 4 matrices isn't invertible.
147OZZ_INLINE SoaFloat4x4 Invert(const SoaFloat4x4& _m,
148 SimdInt4* _invertible = nullptr) {
149 const SoaFloat4* cols = _m.cols;
150 const SimdFloat4 a00 = cols[2].z * cols[3].w - cols[3].z * cols[2].w;
151 const SimdFloat4 a01 = cols[2].y * cols[3].w - cols[3].y * cols[2].w;
152 const SimdFloat4 a02 = cols[2].y * cols[3].z - cols[3].y * cols[2].z;
153 const SimdFloat4 a03 = cols[2].x * cols[3].w - cols[3].x * cols[2].w;
154 const SimdFloat4 a04 = cols[2].x * cols[3].z - cols[3].x * cols[2].z;
155 const SimdFloat4 a05 = cols[2].x * cols[3].y - cols[3].x * cols[2].y;
156 const SimdFloat4 a06 = cols[1].z * cols[3].w - cols[3].z * cols[1].w;
157 const SimdFloat4 a07 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
158 const SimdFloat4 a08 = cols[1].y * cols[3].z - cols[3].y * cols[1].z;
159 const SimdFloat4 a09 = cols[1].x * cols[3].w - cols[3].x * cols[1].w;
160 const SimdFloat4 a10 = cols[1].x * cols[3].z - cols[3].x * cols[1].z;
161 const SimdFloat4 a11 = cols[1].y * cols[3].w - cols[3].y * cols[1].w;
162 const SimdFloat4 a12 = cols[1].x * cols[3].y - cols[3].x * cols[1].y;
163 const SimdFloat4 a13 = cols[1].z * cols[2].w - cols[2].z * cols[1].w;
164 const SimdFloat4 a14 = cols[1].y * cols[2].w - cols[2].y * cols[1].w;
165 const SimdFloat4 a15 = cols[1].y * cols[2].z - cols[2].y * cols[1].z;
166 const SimdFloat4 a16 = cols[1].x * cols[2].w - cols[2].x * cols[1].w;
167 const SimdFloat4 a17 = cols[1].x * cols[2].z - cols[2].x * cols[1].z;
168 const SimdFloat4 a18 = cols[1].x * cols[2].y - cols[2].x * cols[1].y;
169
170 const SimdFloat4 b0x = cols[1].y * a00 - cols[1].z * a01 + cols[1].w * a02;
171 const SimdFloat4 b1x = -cols[1].x * a00 + cols[1].z * a03 - cols[1].w * a04;
172 const SimdFloat4 b2x = cols[1].x * a01 - cols[1].y * a03 + cols[1].w * a05;
173 const SimdFloat4 b3x = -cols[1].x * a02 + cols[1].y * a04 - cols[1].z * a05;
174
175 const SimdFloat4 b0y = -cols[0].y * a00 + cols[0].z * a01 - cols[0].w * a02;
176 const SimdFloat4 b1y = cols[0].x * a00 - cols[0].z * a03 + cols[0].w * a04;
177 const SimdFloat4 b2y = -cols[0].x * a01 + cols[0].y * a03 - cols[0].w * a05;
178 const SimdFloat4 b3y = cols[0].x * a02 - cols[0].y * a04 + cols[0].z * a05;
179
180 const SimdFloat4 b0z = cols[0].y * a06 - cols[0].z * a07 + cols[0].w * a08;
181 const SimdFloat4 b1z = -cols[0].x * a06 + cols[0].z * a09 - cols[0].w * a10;
182 const SimdFloat4 b2z = cols[0].x * a11 - cols[0].y * a09 + cols[0].w * a12;
183 const SimdFloat4 b3z = -cols[0].x * a08 + cols[0].y * a10 - cols[0].z * a12;
184
185 const SimdFloat4 b0w = -cols[0].y * a13 + cols[0].z * a14 - cols[0].w * a15;
186 const SimdFloat4 b1w = cols[0].x * a13 - cols[0].z * a16 + cols[0].w * a17;
187 const SimdFloat4 b2w = -cols[0].x * a14 + cols[0].y * a16 - cols[0].w * a18;
188 const SimdFloat4 b3w = cols[0].x * a15 - cols[0].y * a17 + cols[0].z * a18;
189
190 const SimdFloat4 det =
191 cols[0].x * b0x + cols[0].y * b1x + cols[0].z * b2x + cols[0].w * b3x;
192 const SimdInt4 invertible = CmpNe(det, simd_float4::zero());
193 assert((_invertible || AreAllTrue(invertible)) && "Matrix is not invertible");
194 if (_invertible != nullptr) {
195 *_invertible = invertible;
196 }
197 const SimdFloat4 inv_det =
198 Select(invertible, RcpEstNR(det), simd_float4::zero());
199
200 const SoaFloat4x4 ret = {
201 {{b0x * inv_det, b0y * inv_det, b0z * inv_det, b0w * inv_det},
202 {b1x * inv_det, b1y * inv_det, b1z * inv_det, b1w * inv_det},
203 {b2x * inv_det, b2y * inv_det, b2z * inv_det, b2w * inv_det},
204 {b3x * inv_det, b3y * inv_det, b3z * inv_det, b3w * inv_det}}};
205
206 return ret;
207}
208
209// Scales matrix _m along the axis defined by _v components.
210// _v.w is ignored.
211OZZ_INLINE SoaFloat4x4 Scale(const SoaFloat4x4& _m, const SoaFloat4& _v) {
212 const SoaFloat4x4 ret = {{{_m.cols[0].x * _v.x, _m.cols[0].y * _v.x,
213 _m.cols[0].z * _v.x, _m.cols[0].w * _v.x},
214 {_m.cols[1].x * _v.y, _m.cols[1].y * _v.y,
215 _m.cols[1].z * _v.y, _m.cols[1].w * _v.y},
216 {_m.cols[2].x * _v.z, _m.cols[2].y * _v.z,
217 _m.cols[2].z * _v.z, _m.cols[2].w * _v.z},
218 _m.cols[3]}};
219 return ret;
220}
221} // namespace math
222} // namespace ozz
223
224// Computes the multiplication of matrix Float4x4 and vector _v.
225OZZ_INLINE ozz::math::SoaFloat4 operator*(const ozz::math::SoaFloat4x4& _m,
226 const ozz::math::SoaFloat4& _v) {
227 const ozz::math::SoaFloat4 ret = {
228 _m.cols[0].x * _v.x + _m.cols[1].x * _v.y + _m.cols[2].x * _v.z +
229 _m.cols[3].x * _v.w,
230 _m.cols[0].y * _v.x + _m.cols[1].y * _v.y + _m.cols[2].y * _v.z +
231 _m.cols[3].y * _v.w,
232 _m.cols[0].z * _v.x + _m.cols[1].z * _v.y + _m.cols[2].z * _v.z +
233 _m.cols[3].z * _v.w,
234 _m.cols[0].w * _v.x + _m.cols[1].w * _v.y + _m.cols[2].w * _v.z +
235 _m.cols[3].w * _v.w};
236 return ret;
237}
238
239// Computes the multiplication of two matrices _a and _b.
240OZZ_INLINE ozz::math::SoaFloat4x4 operator*(const ozz::math::SoaFloat4x4& _a,
241 const ozz::math::SoaFloat4x4& _b) {
242 const ozz::math::SoaFloat4x4 ret = {
243 {_a * _b.cols[0], _a * _b.cols[1], _a * _b.cols[2], _a * _b.cols[3]}};
244 return ret;
245}
246
247// Computes the per element addition of two matrices _a and _b.
248OZZ_INLINE ozz::math::SoaFloat4x4 operator+(const ozz::math::SoaFloat4x4& _a,
249 const ozz::math::SoaFloat4x4& _b) {
250 const ozz::math::SoaFloat4x4 ret = {
251 {{_a.cols[0].x + _b.cols[0].x, _a.cols[0].y + _b.cols[0].y,
252 _a.cols[0].z + _b.cols[0].z, _a.cols[0].w + _b.cols[0].w},
253 {_a.cols[1].x + _b.cols[1].x, _a.cols[1].y + _b.cols[1].y,
254 _a.cols[1].z + _b.cols[1].z, _a.cols[1].w + _b.cols[1].w},
255 {_a.cols[2].x + _b.cols[2].x, _a.cols[2].y + _b.cols[2].y,
256 _a.cols[2].z + _b.cols[2].z, _a.cols[2].w + _b.cols[2].w},
257 {_a.cols[3].x + _b.cols[3].x, _a.cols[3].y + _b.cols[3].y,
258 _a.cols[3].z + _b.cols[3].z, _a.cols[3].w + _b.cols[3].w}}};
259 return ret;
260}
261
262// Computes the per element subtraction of two matrices _a and _b.
263OZZ_INLINE ozz::math::SoaFloat4x4 operator-(const ozz::math::SoaFloat4x4& _a,
264 const ozz::math::SoaFloat4x4& _b) {
265 const ozz::math::SoaFloat4x4 ret = {
266 {{_a.cols[0].x - _b.cols[0].x, _a.cols[0].y - _b.cols[0].y,
267 _a.cols[0].z - _b.cols[0].z, _a.cols[0].w - _b.cols[0].w},
268 {_a.cols[1].x - _b.cols[1].x, _a.cols[1].y - _b.cols[1].y,
269 _a.cols[1].z - _b.cols[1].z, _a.cols[1].w - _b.cols[1].w},
270 {_a.cols[2].x - _b.cols[2].x, _a.cols[2].y - _b.cols[2].y,
271 _a.cols[2].z - _b.cols[2].z, _a.cols[2].w - _b.cols[2].w},
272 {_a.cols[3].x - _b.cols[3].x, _a.cols[3].y - _b.cols[3].y,
273 _a.cols[3].z - _b.cols[3].z, _a.cols[3].w - _b.cols[3].w}}};
274 return ret;
275}
276#endif // OZZ_OZZ_BASE_MATHS_SOA_FLOAT4X4_H_
Definition simd_math_config.h:121
Definition soa_float.h:69
Definition soa_float.h:114
Definition soa_float4x4.h:46
Definition soa_quaternion.h:39