1 //
2 // Copyright (C) 2009-2021 Intel Corporation
3 //
4 // SPDX-License-Identifier: MIT
5 //
6 //
7
8 #pragma once
9
10 #include "GRLRTASCommon.h"
11
12 GRL_NAMESPACE_BEGIN(GRL)
GRL_NAMESPACE_BEGIN(RTAS)13 GRL_NAMESPACE_BEGIN(RTAS)
14 inline float3 GRL_OVERLOADABLE cross(const float3 a, const float3 b)
15 {
16 float3 res = { a.y * b.z - a.z * b.y,
17 a.z * b.x - a.x * b.z,
18 a.x * b.y - a.y * b.x };
19 return res;
20 }
21
22 struct LinearSpace3f
23 {
24 float3 vx;
25 float3 vy;
26 float3 vz;
27 };
28
29 /* compute the determinant of the matrix */
LinearSpace3f_Constructor(const float3 vx,const float3 vy,const float3 vz)30 GRL_INLINE struct LinearSpace3f LinearSpace3f_Constructor(const float3 vx, const float3 vy, const float3 vz)
31 {
32 struct LinearSpace3f xfm;
33 xfm.vx = vx;
34 xfm.vy = vy;
35 xfm.vz = vz;
36 return xfm;
37 }
38
39 /* compute the determinant of the matrix */
LinearSpace3f_det(struct LinearSpace3f xfm)40 GRL_INLINE float LinearSpace3f_det(struct LinearSpace3f xfm)
41 {
42 return dot(xfm.vx, cross(xfm.vy, xfm.vz));
43 }
44
45 /* compute transposed matrix */
LinearSpace3f_transpose(struct LinearSpace3f in)46 GRL_INLINE struct LinearSpace3f LinearSpace3f_transpose(struct LinearSpace3f in)
47 {
48 float3 x = { in.vx.x, in.vy.x, in.vz.x };
49 float3 y = { in.vx.y, in.vy.y, in.vz.y };
50 float3 z = { in.vx.z, in.vy.z, in.vz.z };
51
52 return LinearSpace3f_Constructor(x,
53 y,
54 z);
55 }
56
57 /* compute adjoint matrix */
LinearSpace3f_adjoint(struct LinearSpace3f in)58 GRL_INLINE const struct LinearSpace3f LinearSpace3f_adjoint(struct LinearSpace3f in)
59 {
60 return LinearSpace3f_transpose(LinearSpace3f_Constructor(cross(in.vy, in.vz),
61 cross(in.vz, in.vx),
62 cross(in.vx, in.vy)));
63 }
64
65 /* compute inverse matrix */
LinearSpace3f_invert(struct LinearSpace3f in)66 GRL_INLINE struct LinearSpace3f LinearSpace3f_invert(struct LinearSpace3f in)
67 {
68 const float det = LinearSpace3f_det(in);
69 const struct LinearSpace3f adj = LinearSpace3f_adjoint(in);
70 return LinearSpace3f_Constructor(adj.vx / det, adj.vy / det, adj.vz / det);
71 }
72
xfmPoint(struct LinearSpace3f xfm,float3 p)73 GRL_INLINE float3 GRL_OVERLOADABLE xfmPoint(struct LinearSpace3f xfm, float3 p)
74 {
75 return xfm.vx * p.x + xfm.vy * p.y + xfm.vz * p.z;
76 }
77
78 struct AffineSpace3f
79 {
80 struct LinearSpace3f l;
81 float3 p;
82 };
83
AffineSpace3f_Constructor(struct LinearSpace3f l,float3 p)84 GRL_INLINE struct AffineSpace3f AffineSpace3f_Constructor(struct LinearSpace3f l, float3 p)
85 {
86 struct AffineSpace3f out;
87 out.l = l;
88 out.p = p;
89 return out;
90 }
91
AffineSpace3f_load_row_major(const float * in)92 GRL_INLINE struct AffineSpace3f AffineSpace3f_load_row_major(const float *in)
93 {
94 struct AffineSpace3f out;
95 out.l.vx.x = in[0];
96 out.l.vx.y = in[4];
97 out.l.vx.z = in[8];
98 out.l.vy.x = in[1];
99 out.l.vy.y = in[5];
100 out.l.vy.z = in[9];
101 out.l.vz.x = in[2];
102 out.l.vz.y = in[6];
103 out.l.vz.z = in[10];
104 out.p.x = in[3];
105 out.p.y = in[7];
106 out.p.z = in[11];
107 return out;
108 }
109
110 // squared proportion of oriented transformed cube to aa box that would contain it.
111 // the smaller it is the more overhead transformation produces
112 GRL_INLINE
transformation_bbox_surf_overhead(const float * Transform)113 float transformation_bbox_surf_overhead(const float* Transform)
114 {
115 // We use an abs-matrix to transform the AABB extent vector, which is enough to compute the area
116 // New AABB is center +- Extent.
117 //
118 // For derivation see:
119 // https://zeux.io/2010/10/17/aabb-from-obb-with-component-wise-abs/
120 //
121
122
123 // take the cube of side 1 and see how big aabb containing it transformed is vs just surface of transformed
124 float ex = fabs(Transform[0]) + fabs(Transform[1]) + fabs(Transform[2]);
125 float ey = fabs(Transform[4]) + fabs(Transform[5]) + fabs(Transform[6]);
126 float ez = fabs(Transform[8]) + fabs(Transform[9]) + fabs(Transform[10]);
127
128 // we will compare squared sizes
129 ex = ex * ex;
130 ey = ey * ey;
131 ez = ez * ez;
132
133 // surface of aabb containing oriented box;
134 float aabb_sq_half_surf = ex * ey + ey * ez + ez * ex;
135
136 // ^2 lengths of transformed <1,0,0>, <0,1,0>, <0,0,1>
137 float obx = Transform[0] * Transform[0] + Transform[4] * Transform[4] + Transform[8] * Transform[8];
138 float oby = Transform[1] * Transform[1] + Transform[5] * Transform[5] + Transform[9] * Transform[9];
139 float obz = Transform[2] * Transform[2] + Transform[6] * Transform[6] + Transform[10] * Transform[10];
140
141 float obb_sq_half_surf = obx * oby + oby * obz + obz * obx;
142
143 return obb_sq_half_surf / aabb_sq_half_surf;
144
145 // ex = 2.0
146 // ey = 2.0
147 // ez = 2.0
148 // ex = 4.0
149 // ey = 4.0
150 // ez = 4.0
151 // aabb_half_surf = 16+16 *2.0 + 2.0*2.0+ 2.0*2.0; = 12;
152 // aabb_sq_half_surf = 144;
153 //
154 // obx = 4.0;
155 // oby = 4.0;
156 // obz = 4.0;
157 // obb_sq_half_surf = 16 + 16+ 16;
158 // obb_sq_half_surf = 16.0 *3 = 48
159 }
160
load_row_major_from_AffineSpace3f(struct AffineSpace3f in,float * out)161 GRL_INLINE void load_row_major_from_AffineSpace3f(struct AffineSpace3f in, float* out)
162 {
163 out[0] = in.l.vx.x;
164 out[4] = in.l.vx.y;
165 out[8] = in.l.vx.z;
166 out[1] = in.l.vy.x;
167 out[5] = in.l.vy.y;
168 out[9] = in.l.vy.z;
169 out[2] = in.l.vz.x;
170 out[6] = in.l.vz.y;
171 out[10] = in.l.vz.z;
172
173 out[3] = in.p.x;
174 out[7] = in.p.y;
175 out[11] = in.p.z;
176 }
177
xfmPoint(struct AffineSpace3f xfm,float3 p)178 GRL_INLINE float3 GRL_OVERLOADABLE xfmPoint(struct AffineSpace3f xfm, float3 p)
179 {
180 return xfmPoint(xfm.l, p) + xfm.p;
181 }
182
183 /* compute inverse matrix */
AffineSpace3f_invert(struct AffineSpace3f in)184 GRL_INLINE struct AffineSpace3f AffineSpace3f_invert(struct AffineSpace3f in)
185 {
186 const struct LinearSpace3f il = LinearSpace3f_invert(in.l);
187 float3 ip = -xfmPoint(il, in.p);
188 return AffineSpace3f_Constructor(il, ip);
189 }
190
191 GRL_NAMESPACE_END(RTAS)
192 GRL_NAMESPACE_END(GRL)
193