OWL
Loading...
Searching...
No Matches
LinearSpace.h
1// ======================================================================== //
2// Copyright 2018-2019 Ingo Wald //
3// //
4// Licensed under the Apache License, Version 2.0 (the "License"); //
5// you may not use this file except in compliance with the License. //
6// You may obtain a copy of the License at //
7// //
8// http://www.apache.org/licenses/LICENSE-2.0 //
9// //
10// Unless required by applicable law or agreed to in writing, software //
11// distributed under the License is distributed on an "AS IS" BASIS, //
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
13// See the License for the specific language governing permissions and //
14// limitations under the License. //
15// ======================================================================== //
16
17/* originally taken (and adapted) from ospray, under following license */
18
19// ======================================================================== //
20// Copyright 2009-2018 Intel Corporation //
21// //
22// Licensed under the Apache License, Version 2.0 (the "License"); //
23// you may not use this file except in compliance with the License. //
24// You may obtain a copy of the License at //
25// //
26// http://www.apache.org/licenses/LICENSE-2.0 //
27// //
28// Unless required by applicable law or agreed to in writing, software //
29// distributed under the License is distributed on an "AS IS" BASIS, //
30// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
31// See the License for the specific language governing permissions and //
32// limitations under the License. //
33// ======================================================================== //
34
35#pragma once
36
37#include "../math/vec.h"
38#include "../math/Quaternion.h"
39
40namespace owl {
41 namespace common {
42
46
47 template<typename T> struct OWL_INTERFACE LinearSpace2
48 {
49 using vector_t = T;
50 // using Scalar = typename T::scalar_t;
51 // using vector_t = T;
52 using scalar_t = typename T::scalar_t;
53
55 inline LinearSpace2 ( ) = default;
56 inline __both__ LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
57 inline __both__ LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
58
59 template<typename L1> inline __both__ LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
60
62 inline __both__ LinearSpace2(const vector_t& vx, const vector_t& vy)
63 : vx(vx), vy(vy) {}
64
66 inline __both__ LinearSpace2(const scalar_t& m00, const scalar_t& m01,
67 const scalar_t& m10, const scalar_t& m11)
68 : vx(m00,m10), vy(m01,m11) {}
69
71 inline __both__ const scalar_t det() const { return vx.x*vy.y - vx.y*vy.x; }
72
74 inline __both__ const LinearSpace2 adjoint() const { return LinearSpace2(vy.y,-vy.x,-vx.y,vx.x); }
75
77 inline __both__ const LinearSpace2 inverse() const { return adjoint()/det(); }
78
80 inline __both__ const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
81
83 inline const vector_t row0() const { return vector_t(vx.x,vy.x); }
84
86 inline const vector_t row1() const { return vector_t(vx.y,vy.y); }
87
91
92 inline __both__ LinearSpace2( ZeroTy ) : vx(ZeroTy()), vy(ZeroTy()) {}
93 inline __both__ LinearSpace2( OneTy ) : vx(OneTy(), ZeroTy()), vy(ZeroTy(), OneTy()) {}
94
96 static inline LinearSpace2 scale(const vector_t& s) {
97 return LinearSpace2(s.x, 0,
98 0 , s.y);
99 }
100
102 static inline LinearSpace2 rotate(const scalar_t& r) {
103 scalar_t s = sin(r), c = cos(r);
104 return LinearSpace2(c, -s,
105 s, c);
106 }
107
110 LinearSpace2 m = *this;
111
112 // mirrored?
113 scalar_t mirror{scalar_t(OneTy())};
114 if (m.det() < scalar_t(ZeroTy())) {
115 m.vx = -m.vx;
116 mirror = -mirror;
117 }
118
119 // rotation
120 for (int i = 0; i < 99; i++) {
121 const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
122 const LinearSpace2 d = m_next - m;
123 m = m_next;
124 // norm^2 of difference small enough?
125 if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
126 break;
127 }
128
129 // rotation * mirror_x
130 return LinearSpace2(mirror*m.vx, m.vy);
131 }
132
133 public:
134
136 vector_t vx,vy;
137 };
138
140 // Unary Operators
142
143 template<typename T> __both__ inline LinearSpace2<T> operator -( const LinearSpace2<T>& a ) { return LinearSpace2<T>(-a.vx,-a.vy); }
144 template<typename T> __both__ inline LinearSpace2<T> operator +( const LinearSpace2<T>& a ) { return LinearSpace2<T>(+a.vx,+a.vy); }
145 template<typename T> __both__ inline LinearSpace2<T> rcp ( const LinearSpace2<T>& a ) { return a.inverse(); }
146
148 // Binary Operators
150
151 template<typename T> inline __both__ LinearSpace2<T> operator +( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx+b.vx,a.vy+b.vy); }
152 template<typename T> inline __both__ LinearSpace2<T> operator -( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx-b.vx,a.vy-b.vy); }
153
154 template<typename T> inline __both__ LinearSpace2<T> operator*(const typename T::scalar_t & a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
155 template<typename T> inline __both__ T operator*(const LinearSpace2<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy; }
156 template<typename T> inline __both__ LinearSpace2<T> operator*(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
157
158 template<typename T> inline __both__ LinearSpace2<T> operator/(const LinearSpace2<T>& a, const typename T::scalar_t & b) { return LinearSpace2<T>(a.vx/b, a.vy/b); }
159 template<typename T> inline __both__ LinearSpace2<T> operator/(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return a * rcp(b); }
160
161 template<typename T> inline __both__ LinearSpace2<T>& operator *=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a * b; }
162 template<typename T> inline __both__ LinearSpace2<T>& operator /=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a / b; }
163
167
168 template<typename T> inline __both__ bool operator ==( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx == b.vx && a.vy == b.vy; }
169 template<typename T> inline __both__ bool operator !=( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx != b.vx || a.vy != b.vy; }
170
174
175 template<typename T> static std::ostream& operator<<(std::ostream& cout, const LinearSpace2<T>& m) {
176 return cout << "{ vx = " << m.vx << ", vy = " << m.vy << "}";
177 }
178
182
183 template<typename T>
184 struct OWL_INTERFACE LinearSpace3
185 {
186 // using vector_t = T;
187 using scalar_t = typename T::scalar_t;
188 using vector_t = T;
189 // using scalar_t = typename T::scalar_t;
190
192 // inline LinearSpace3 ( ) = default;
193 inline __both__ LinearSpace3()
194 : vx(OneTy(),ZeroTy(),ZeroTy()),
195 vy(ZeroTy(),OneTy(),ZeroTy()),
196 vz(ZeroTy(),ZeroTy(),OneTy())
197 {}
198
199 inline// __both__
200 LinearSpace3 ( const LinearSpace3& other ) = default;
201 inline __both__ LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
202
203 template<typename L1> inline __both__ LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
204
206 inline __both__ LinearSpace3(const vector_t& vx, const vector_t& vy, const vector_t& vz)
207 : vx(vx), vy(vy), vz(vz) {}
208
210 inline __both__ LinearSpace3( const QuaternionT<scalar_t>& q )
211 : vx((q.r*q.r + q.i*q.i - q.j*q.j - q.k*q.k), 2.0f*(q.i*q.j + q.r*q.k), 2.0f*(q.i*q.k - q.r*q.j))
212 , vy(2.0f*(q.i*q.j - q.r*q.k), (q.r*q.r - q.i*q.i + q.j*q.j - q.k*q.k), 2.0f*(q.j*q.k + q.r*q.i))
213 , vz(2.0f*(q.i*q.k + q.r*q.j), 2.0f*(q.j*q.k - q.r*q.i), (q.r*q.r - q.i*q.i - q.j*q.j + q.k*q.k)) {}
214
216 inline __both__ LinearSpace3(const scalar_t& m00, const scalar_t& m01, const scalar_t& m02,
217 const scalar_t& m10, const scalar_t& m11, const scalar_t& m12,
218 const scalar_t& m20, const scalar_t& m21, const scalar_t& m22)
219 : vx(m00,m10,m20), vy(m01,m11,m21), vz(m02,m12,m22) {}
220
222 inline __both__ const scalar_t det() const { return dot(vx,cross(vy,vz)); }
223
225 inline __both__ const LinearSpace3 adjoint() const { return LinearSpace3(cross(vy,vz),cross(vz,vx),cross(vx,vy)).transposed(); }
226
228 inline __both__ const LinearSpace3 inverse() const { return adjoint()/det(); }
229
231 inline __both__ const LinearSpace3 transposed() const { return LinearSpace3(vx.x,vx.y,vx.z,vy.x,vy.y,vy.z,vz.x,vz.y,vz.z); }
232
234 inline __both__ const vector_t row0() const { return vector_t(vx.x,vy.x,vz.x); }
235
237 inline __both__ const vector_t row1() const { return vector_t(vx.y,vy.y,vz.y); }
238
240 inline __both__ const vector_t row2() const { return vector_t(vx.z,vy.z,vz.z); }
241
245
246// #ifdef __CUDA_ARCH__
247 inline __both__ LinearSpace3( const ZeroTy & )
248 : vx(ZeroTy()), vy(ZeroTy()), vz(ZeroTy())
249 {}
250 inline __both__ LinearSpace3( const OneTy & )
251 : vx(OneTy(), ZeroTy(), ZeroTy()),
252 vy(ZeroTy(), OneTy(), ZeroTy()),
253 vz(ZeroTy(), ZeroTy(), OneTy())
254 {}
255// #else
256// inline __both__ LinearSpace3( ZeroTy ) : vx(zero), vy(zero), vz(zero) {}
257// inline __both__ LinearSpace3( OneTy ) : vx(one, zero, zero), vy(zero, one, zero), vz(zero, zero, one) {}
258// #endif
259
261 static inline __both__ LinearSpace3 scale(const vector_t& s) {
262 return LinearSpace3(s.x, 0, 0,
263 0 , s.y, 0,
264 0 , 0, s.z);
265 }
266
268 static inline __both__ LinearSpace3 rotate(const vector_t& _u, const scalar_t& r) {
269 vector_t u = normalize(_u);
270 scalar_t s = sin(r), c = cos(r);
271 return LinearSpace3(u.x*u.x+(1-u.x*u.x)*c, u.x*u.y*(1-c)-u.z*s, u.x*u.z*(1-c)+u.y*s,
272 u.x*u.y*(1-c)+u.z*s, u.y*u.y+(1-u.y*u.y)*c, u.y*u.z*(1-c)-u.x*s,
273 u.x*u.z*(1-c)-u.y*s, u.y*u.z*(1-c)+u.x*s, u.z*u.z+(1-u.z*u.z)*c);
274 }
275
277 static inline __both__ QuaternionT<scalar_t> rotation(const LinearSpace3 &a) {
278 scalar_t tr = a.vx.x+a.vy.y+a.vz.z+1;
279 vector_t diag(a.vx.x,a.vy.y,a.vz.z);
280 if (tr > 1) {
281 scalar_t s = owl::common::polymorphic::sqrt(tr) * 2;
282 return QuaternionT<scalar_t>(.25f * s,
283 (a.vz.y-a.vy.z)/s,
284 (a.vx.z-a.vz.x)/s,
285 (a.vy.x-a.vx.y)/s);
286 } else if (arg_max(diag) == 0) {
287 scalar_t s = owl::common::polymorphic::sqrt(1.f+diag.x-diag.y-diag.z)*2.f;
288 return QuaternionT<scalar_t>((a.vz.y-a.vy.z)/s,
289 .25f * s,
290 (a.vx.y-a.vy.x)/s,
291 (a.vx.z-a.vz.x)/s);
292 } else if (arg_max(diag) == 1) {
293 scalar_t s = owl::common::polymorphic::sqrt(1.f+diag.y-diag.x-diag.z)*2.f;
294 return QuaternionT<scalar_t>((a.vx.z-a.vz.x)/s,
295 (a.vx.y-a.vy.x)/s,
296 .25f * s,
297 (a.vy.z-a.vz.y)/s);
298 } else {
299 scalar_t s = owl::common::polymorphic::sqrt(1.f+diag.z-diag.x-diag.y)*2.f;
300 return QuaternionT<scalar_t>((a.vy.x-a.vx.y)/s,
301 (a.vx.z-a.vz.x)/s,
302 (a.vy.z-a.vz.y)/s,
303 .25f * s);
304 }
305 }
306
307 public:
308
310 T vx,vy,vz;
311 };
312
314 // Unary Operators
316
317 template<typename T> inline __both__ LinearSpace3<T> operator -( const LinearSpace3<T>& a ) { return LinearSpace3<T>(-a.vx,-a.vy,-a.vz); }
318 template<typename T> inline __both__ LinearSpace3<T> operator +( const LinearSpace3<T>& a ) { return LinearSpace3<T>(+a.vx,+a.vy,+a.vz); }
319 template<typename T> inline __both__ LinearSpace3<T> rcp ( const LinearSpace3<T>& a ) { return a.inverse(); }
320
321 /* constructs a coordinate frame form a normalized normal */
322 template<typename T>
323 inline __both__ LinearSpace3<T> frame(const T &N)
324 {
325// #ifdef __CUDA_ARCH__
326 const T dx0 = cross(T(OneTy(),ZeroTy(),ZeroTy()),N);
327 const T dx1 = cross(T(ZeroTy(),OneTy(),ZeroTy()),N);
328// #else
329// const T dx0 = cross(T(one,zero,zero),N);
330// const T dx1 = cross(T(zero,one,zero),N);
331// #endif
332 const T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
333 const T dy = normalize(cross(N,dx));
334 return LinearSpace3<T>(dx,dy,N);
335 }
336
337 /* constructs a coordinate frame from a normal and approximate x-direction */
338 template<typename T> inline __both__ LinearSpace3<T> frame(const T& N, const T& dxi)
339 {
340 if (abs(dot(dxi,N)) > 0.99f) return frame(N); // fallback in case N and dxi are very parallel
341 const T dx = normalize(cross(dxi,N));
342 const T dy = normalize(cross(N,dx));
343 return LinearSpace3<T>(dx,dy,N);
344 }
345
346 /* clamps linear space to range -1 to +1 */
347 template<typename T> inline __both__ LinearSpace3<T> clamp(const LinearSpace3<T>& space) {
348 return LinearSpace3<T>(clamp(space.vx,T(-1.0f),T(1.0f)),
349 clamp(space.vy,T(-1.0f),T(1.0f)),
350 clamp(space.vz,T(-1.0f),T(1.0f)));
351 }
352
354 // Binary Operators
356
357 template<typename T> inline __both__ LinearSpace3<T> operator +( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx+b.vx,a.vy+b.vy,a.vz+b.vz); }
358 template<typename T> inline __both__ LinearSpace3<T> operator -( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx-b.vx,a.vy-b.vy,a.vz-b.vz); }
359
360 template<typename T> inline __both__ LinearSpace3<T> operator*(const typename T::scalar_t & a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
361 template<typename T> inline __both__ T operator*(const LinearSpace3<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy + b.z*a.vz; }
362 template<typename T> inline __both__ LinearSpace3<T> operator*(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
363
364 template<typename T> inline __both__ LinearSpace3<T> operator/(const LinearSpace3<T>& a, const typename T::scalar_t & b) { return LinearSpace3<T>(a.vx/b, a.vy/b, a.vz/b); }
365
366 template<typename T> inline __both__ LinearSpace3<T> operator/(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return a * rcp(b); }
367
368 template<typename T> inline LinearSpace3<T>& operator *=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a * b; }
369 template<typename T> inline LinearSpace3<T>& operator /=( LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a = a / b; }
370
371 template<typename T> inline __both__ T xfmPoint (const LinearSpace3<T>& s, const T& a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z*s.vz))); }
372 template<typename T> inline __both__ T xfmVector(const LinearSpace3<T>& s, const T& a) { return madd(T(a.x),s.vx,madd(T(a.y),s.vy,T(a.z*s.vz))); }
373 template<typename T> inline __both__ T xfmNormal(const LinearSpace3<T>& s, const T& a) { return xfmVector(s.inverse().transposed(),a); }
374
378
379 template<typename T> inline bool operator ==( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx == b.vx && a.vy == b.vy && a.vz == b.vz; }
380 template<typename T> inline bool operator !=( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx != b.vx || a.vy != b.vy || a.vz != b.vz; }
381
385
386 template<typename T> inline std::ostream& operator<<(std::ostream& cout, const LinearSpace3<T>& m) {
387 return cout << "{ vx = " << m.vx << ", vy = " << m.vy << ", vz = " << m.vz << "}";
388 }
389
391 using LinearSpace2f = LinearSpace2<vec2f> ;
392 using LinearSpace3f = LinearSpace3<vec3f> ;
393 using LinearSpace3fa = LinearSpace3<vec3fa>;
394
395 using linear2f = LinearSpace2f;
396 using linear3f = LinearSpace3f;
397
398 } // ::owl::common
399} // ::owl
2D Linear Transform (2x2 Matrix)
Definition: LinearSpace.h:48
static LinearSpace2 scale(const vector_t &s)
Definition: LinearSpace.h:96
__both__ const LinearSpace2 inverse() const
Definition: LinearSpace.h:77
static LinearSpace2 rotate(const scalar_t &r)
Definition: LinearSpace.h:102
__both__ LinearSpace2(const scalar_t &m00, const scalar_t &m01, const scalar_t &m10, const scalar_t &m11)
Definition: LinearSpace.h:66
__both__ const LinearSpace2 adjoint() const
Definition: LinearSpace.h:74
vector_t vx
Definition: LinearSpace.h:136
LinearSpace2 orthogonal() const
Definition: LinearSpace.h:109
__both__ LinearSpace2(ZeroTy)
Constants.
Definition: LinearSpace.h:92
__both__ LinearSpace2(const vector_t &vx, const vector_t &vy)
Definition: LinearSpace.h:62
const vector_t row1() const
Definition: LinearSpace.h:86
__both__ const LinearSpace2 transposed() const
Definition: LinearSpace.h:80
const vector_t row0() const
Definition: LinearSpace.h:83
__both__ const scalar_t det() const
Definition: LinearSpace.h:71
3D Linear Transform (3x3 Matrix)
Definition: LinearSpace.h:185
__both__ const LinearSpace3 inverse() const
Definition: LinearSpace.h:228
__both__ const vector_t row1() const
Definition: LinearSpace.h:237
__both__ const LinearSpace3 adjoint() const
Definition: LinearSpace.h:225
__both__ LinearSpace3(const vector_t &vx, const vector_t &vy, const vector_t &vz)
Definition: LinearSpace.h:206
__both__ LinearSpace3(const ZeroTy &)
Constants.
Definition: LinearSpace.h:247
__both__ const LinearSpace3 transposed() const
Definition: LinearSpace.h:231
T vx
Definition: LinearSpace.h:310
__both__ LinearSpace3(const QuaternionT< scalar_t > &q)
Definition: LinearSpace.h:210
__both__ const vector_t row2() const
Definition: LinearSpace.h:240
__both__ LinearSpace3()
Definition: LinearSpace.h:193
__both__ LinearSpace3(const scalar_t &m00, const scalar_t &m01, const scalar_t &m02, const scalar_t &m10, const scalar_t &m11, const scalar_t &m12, const scalar_t &m20, const scalar_t &m21, const scalar_t &m22)
Definition: LinearSpace.h:216
static __both__ LinearSpace3 rotate(const vector_t &_u, const scalar_t &r)
Definition: LinearSpace.h:268
static __both__ QuaternionT< scalar_t > rotation(const LinearSpace3 &a)
Definition: LinearSpace.h:277
__both__ const scalar_t det() const
Definition: LinearSpace.h:222
static __both__ LinearSpace3 scale(const vector_t &s)
Definition: LinearSpace.h:261
__both__ const vector_t row0() const
Definition: LinearSpace.h:234
Definition: Quaternion.h:48