summaryrefslogtreecommitdiff
path: root/src/intel/vulkan/grl/include/affinespace.h
blob: 36ebae0ede62662a0c7d6c9d4fa78023913d009d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//
// Copyright (C) 2009-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT
//
//

#pragma once

#include "GRLRTASCommon.h"

GRL_NAMESPACE_BEGIN(GRL)
GRL_NAMESPACE_BEGIN(RTAS)
inline float3 GRL_OVERLOADABLE cross(const float3 a, const float3 b)
{
    float3 res = { a.y * b.z - a.z * b.y,
                   a.z * b.x - a.x * b.z,
                   a.x * b.y - a.y * b.x };
    return res;
}

struct LinearSpace3f
{
    float3 vx;
    float3 vy;
    float3 vz;
};

/* compute the determinant of the matrix */
GRL_INLINE struct LinearSpace3f LinearSpace3f_Constructor(const float3 vx, const float3 vy, const float3 vz)
{
    struct LinearSpace3f xfm;
    xfm.vx = vx;
    xfm.vy = vy;
    xfm.vz = vz;
    return xfm;
}

/* compute the determinant of the matrix */
GRL_INLINE float LinearSpace3f_det(struct LinearSpace3f xfm)
{
    return dot(xfm.vx, cross(xfm.vy, xfm.vz));
}

/* compute transposed matrix */
GRL_INLINE struct LinearSpace3f LinearSpace3f_transpose(struct LinearSpace3f in)
{
    float3 x = { in.vx.x, in.vy.x, in.vz.x };
    float3 y = { in.vx.y, in.vy.y, in.vz.y };
    float3 z = { in.vx.z, in.vy.z, in.vz.z };

    return LinearSpace3f_Constructor(x,
                                     y,
                                     z);
}

/* compute adjoint matrix */
GRL_INLINE const struct LinearSpace3f LinearSpace3f_adjoint(struct LinearSpace3f in)
{
    return LinearSpace3f_transpose(LinearSpace3f_Constructor(cross(in.vy, in.vz),
                                                             cross(in.vz, in.vx),
                                                             cross(in.vx, in.vy)));
}

/* compute inverse matrix */
GRL_INLINE struct LinearSpace3f LinearSpace3f_invert(struct LinearSpace3f in)
{
    const float det = LinearSpace3f_det(in);
    const struct LinearSpace3f adj = LinearSpace3f_adjoint(in);
    return LinearSpace3f_Constructor(adj.vx / det, adj.vy / det, adj.vz / det);
}

GRL_INLINE float3 GRL_OVERLOADABLE xfmPoint(struct LinearSpace3f xfm, float3 p)
{
    return xfm.vx * p.x + xfm.vy * p.y + xfm.vz * p.z;
}

struct AffineSpace3f
{
    struct LinearSpace3f l;
    float3 p;
};

GRL_INLINE struct AffineSpace3f AffineSpace3f_Constructor(struct LinearSpace3f l, float3 p)
{
    struct AffineSpace3f out;
    out.l = l;
    out.p = p;
    return out;
}

GRL_INLINE struct AffineSpace3f AffineSpace3f_load_row_major(const float *in)
{
    struct AffineSpace3f out;
    out.l.vx.x = in[0];
    out.l.vx.y = in[4];
    out.l.vx.z = in[8];
    out.l.vy.x = in[1];
    out.l.vy.y = in[5];
    out.l.vy.z = in[9];
    out.l.vz.x = in[2];
    out.l.vz.y = in[6];
    out.l.vz.z = in[10];
    out.p.x = in[3];
    out.p.y = in[7];
    out.p.z = in[11];
    return out;
}

// squared proportion of oriented transformed cube to aa box that would contain it.
// the smaller it is the more overhead transformation produces
GRL_INLINE
float transformation_bbox_surf_overhead(const float* Transform)
{
    // We use an abs-matrix to transform the AABB extent vector, which is enough to compute the area
    //     New AABB is center +- Extent.
    //
    // For derivation see:
    //    https://zeux.io/2010/10/17/aabb-from-obb-with-component-wise-abs/
    //


    // take the cube of side 1 and see how big aabb containing it transformed is vs just surface of transformed
    float ex = fabs(Transform[0]) + fabs(Transform[1]) + fabs(Transform[2]);
    float ey = fabs(Transform[4]) + fabs(Transform[5]) + fabs(Transform[6]);
    float ez = fabs(Transform[8]) + fabs(Transform[9]) + fabs(Transform[10]);

    // we will compare squared sizes
    ex = ex * ex;
    ey = ey * ey;
    ez = ez * ez;

    // surface of aabb containing oriented box;
    float aabb_sq_half_surf = ex * ey + ey * ez + ez * ex;

    // ^2 lengths of transformed <1,0,0>, <0,1,0>, <0,0,1>
    float obx = Transform[0] * Transform[0] + Transform[4] * Transform[4] + Transform[8] * Transform[8];
    float oby = Transform[1] * Transform[1] + Transform[5] * Transform[5] + Transform[9] * Transform[9];
    float obz = Transform[2] * Transform[2] + Transform[6] * Transform[6] + Transform[10] * Transform[10];

    float obb_sq_half_surf = obx * oby + oby * obz + obz * obx;

    return obb_sq_half_surf / aabb_sq_half_surf;

    // ex = 2.0
    // ey = 2.0
    // ez = 2.0
    // ex = 4.0
    // ey = 4.0
    // ez = 4.0
    // aabb_half_surf = 16+16 *2.0 +  2.0*2.0+ 2.0*2.0; = 12;
    // aabb_sq_half_surf = 144;
    //
    // obx = 4.0;
    // oby = 4.0;
    // obz = 4.0;
    // obb_sq_half_surf = 16 + 16+ 16;
    // obb_sq_half_surf = 16.0 *3 = 48
}

GRL_INLINE void load_row_major_from_AffineSpace3f(struct AffineSpace3f in, float* out)
{
    out[0]  = in.l.vx.x;
    out[4]  = in.l.vx.y;
    out[8]  = in.l.vx.z;
    out[1]  = in.l.vy.x;
    out[5]  = in.l.vy.y;
    out[9]  = in.l.vy.z;
    out[2]  = in.l.vz.x;
    out[6]  = in.l.vz.y;
    out[10] = in.l.vz.z;

    out[3]  = in.p.x;
    out[7]  = in.p.y;
    out[11] = in.p.z;
}

GRL_INLINE float3 GRL_OVERLOADABLE xfmPoint(struct AffineSpace3f xfm, float3 p)
{
    return xfmPoint(xfm.l, p) + xfm.p;
}

/* compute inverse matrix */
GRL_INLINE struct AffineSpace3f AffineSpace3f_invert(struct AffineSpace3f in)
{
    const struct LinearSpace3f il = LinearSpace3f_invert(in.l);
    float3 ip = -xfmPoint(il, in.p);
    return AffineSpace3f_Constructor(il, ip);
}

GRL_NAMESPACE_END(RTAS)
GRL_NAMESPACE_END(GRL)