1+ #ifndef _NBL_BUILTIN_HLSL_TRANSFORMATION_MATRIX_UTILS_INCLUDED_
2+ #define _NBL_BUILTIN_HLSL_TRANSFORMATION_MATRIX_UTILS_INCLUDED_
3+
4+ #include <nbl/builtin/hlsl/cpp_compat.hlsl>
5+
6+ namespace nbl
7+ {
8+ namespace hlsl
9+ {
10+ //TODO: stolen from cameraz branch, don't have epsilonEqual here, maybe uncomment when merging from imguizmo-lights branch
11+ //// TODO: -> move somewhere else and nbl:: to implement it
12+ //template<typename T, typename E = double>
13+ //bool isOrthoBase(const T& x, const T& y, const T& z, const E epsilon = 1e-6)
14+ //{
15+ // auto isNormalized = [](const auto& v, const auto& epsilon) -> bool
16+ // {
17+ // return glm::epsilonEqual(glm::length(v), 1.0, epsilon);
18+ // };
19+ //
20+ // auto isOrthogonal = [](const auto& a, const auto& b, const auto& epsilon) -> bool
21+ // {
22+ // return glm::epsilonEqual(glm::dot(a, b), 0.0, epsilon);
23+ // };
24+ //
25+ // return isNormalized(x, epsilon) && isNormalized(y, epsilon) && isNormalized(z, epsilon) &&
26+ // isOrthogonal(x, y, epsilon) && isOrthogonal(x, z, epsilon) && isOrthogonal(y, z, epsilon);
27+ //}
28+ //// <-
29+
30+ template<typename T>
31+ matrix <T, 4 , 4 > getMatrix3x4As4x4 (const matrix <T, 3 , 4 >& mat)
32+ {
33+ matrix <T, 4 , 4 > output;
34+ for (int i = 0 ; i < 3 ; ++i)
35+ output[i] = mat[i];
36+ output[3 ] = float32_t4 (0.0f , 0.0f , 0.0f , 1.0f );
37+
38+ return output;
39+ }
40+
41+ template<typename T>
42+ matrix <T, 4 , 4 > getMatrix3x3As4x4 (const matrix <T, 3 , 3 >& mat)
43+ {
44+ matrix <T, 4 , 4 > output;
45+ for (int i = 0 ; i < 3 ; ++i)
46+ output[i] = float32_t4 (mat[i], 1.0f );
47+ output[3 ] = float32_t4 (0.0f , 0.0f , 0.0f , 1.0f );
48+
49+ return output;
50+ }
51+
52+ template<typename Tout, typename Tin, uint32_t N>
53+ inline vector <Tout, N> getCastedVector (const vector <Tin, N>& in )
54+ {
55+ vector <Tout, N> out ;
56+
57+ for (int i = 0 ; i < N; ++i)
58+ out [i] = (Tout)(in [i]);
59+
60+ return out ;
61+ }
62+
63+ template<typename Tout, typename Tin, uint32_t N, uint32_t M>
64+ inline matrix <Tout, N, M> getCastedMatrix (const matrix <Tin, N, M>& in )
65+ {
66+ matrix <Tout, N, M> out ;
67+
68+ for (int i = 0 ; i < N; ++i)
69+ out [i] = getCastedVector<Tout>(in [i]);
70+
71+ return out ;
72+ }
73+
74+ // TODO: use portable_float when merged
75+ //! multiplies matrices a and b, 3x4 matrices are treated as 4x4 matrices with 4th row set to (0, 0, 0 ,1)
76+ template<typename T>
77+ inline matrix <T, 3 , 4 > concatenateBFollowedByA (const matrix <T, 3 , 4 >& a, const matrix <T, 3 , 4 >& b)
78+ {
79+ const auto a4x4 = getMatrix3x4As4x4 (a);
80+ const auto b4x4 = getMatrix3x4As4x4 (b);
81+ return matrix <T, 3 , 4 >(mul (a4x4, b4x4));
82+ }
83+
84+ // /Arek: glm:: for normalize till dot product is fixed (ambiguity with glm namespace + linker issues)
85+
86+ template<typename T>
87+ inline matrix <T, 3 , 4 > buildCameraLookAtMatrixLH (
88+ const vector <T, 3 >& position,
89+ const vector <T, 3 >& target,
90+ const vector <T, 3 >& upVector)
91+ {
92+ const vector <T, 3 > zaxis = glm::normalize (target - position);
93+ const vector <T, 3 > xaxis = glm::normalize (hlsl::cross (upVector, zaxis));
94+ const vector <T, 3 > yaxis = hlsl::cross (zaxis, xaxis);
95+
96+ matrix <T, 3 , 4 > r;
97+ r[0 ] = vector <T, 4 >(xaxis, -hlsl::dot (xaxis, position));
98+ r[1 ] = vector <T, 4 >(yaxis, -hlsl::dot (yaxis, position));
99+ r[2 ] = vector <T, 4 >(zaxis, -hlsl::dot (zaxis, position));
100+
101+ return r;
102+ }
103+
104+ template<typename T>
105+ inline matrix <T, 3 , 4 > buildCameraLookAtMatrixRH (
106+ const vector <T, 3 >& position,
107+ const vector <T, 3 >& target,
108+ const vector <T, 3 >& upVector)
109+ {
110+ const vector <T, 3 > zaxis = glm::normalize (position - target);
111+ const vector <T, 3 > xaxis = glm::normalize (hlsl::cross (upVector, zaxis));
112+ const vector <T, 3 > yaxis = hlsl::cross (zaxis, xaxis);
113+
114+ matrix <T, 3 , 4 > r;
115+ r[0 ] = vector <T, 4 >(xaxis, -hlsl::dot (xaxis, position));
116+ r[1 ] = vector <T, 4 >(yaxis, -hlsl::dot (yaxis, position));
117+ r[2 ] = vector <T, 4 >(zaxis, -hlsl::dot (zaxis, position));
118+
119+ return r;
120+ }
121+
122+ // TODO: test, check if there is better implementation
123+ // TODO: move quaternion to nbl::hlsl
124+ // TODO: why NBL_REF_ARG(MatType) doesn't work?????
125+
126+ //! Replaces curent rocation and scale by rotation represented by quaternion `quat`, leaves 4th row and 4th colum unchanged
127+ template<typename T, uint32_t N>
128+ inline void setRotation (matrix <T, N, 4 >& outMat, NBL_CONST_REF_ARG (core::quaternion) quat)
129+ {
130+ static_assert (N == 3 || N == 4 );
131+
132+ outMat[0 ] = vector <T, 4 >(
133+ 1 - 2 * (quat.y * quat.y + quat.z * quat.z),
134+ 2 * (quat.x * quat.y - quat.z * quat.w),
135+ 2 * (quat.x * quat.z + quat.y * quat.w),
136+ outMat[0 ][3 ]
137+ );
138+
139+ outMat[1 ] = vector <T, 4 >(
140+ 2 * (quat.x * quat.y + quat.z * quat.w),
141+ 1 - 2 * (quat.x * quat.x + quat.z * quat.z),
142+ 2 * (quat.y * quat.z - quat.x * quat.w),
143+ outMat[1 ][3 ]
144+ );
145+
146+ outMat[2 ] = vector <T, 4 >(
147+ 2 * (quat.x * quat.z - quat.y * quat.w),
148+ 2 * (quat.y * quat.z + quat.x * quat.w),
149+ 1 - 2 * (quat.x * quat.x + quat.y * quat.y),
150+ outMat[2 ][3 ]
151+ );
152+ }
153+
154+ template<typename T, uint32_t N>
155+ inline void setTranslation (matrix <T, N, 4 >& outMat, NBL_CONST_REF_ARG (vector <T, 3 >) translation)
156+ {
157+ static_assert (N == 3 || N == 4 );
158+
159+ outMat[0 ].w = translation.x;
160+ outMat[1 ].w = translation.y;
161+ outMat[2 ].w = translation.z;
162+ }
163+
164+
165+ template<typename T>
166+ inline matrix <T, 4 , 4 > buildProjectionMatrixPerspectiveFovRH (float fieldOfViewRadians, float aspectRatio, float zNear, float zFar)
167+ {
168+ const float h = core::reciprocal<float >(tanf (fieldOfViewRadians * 0.5f ));
169+ _NBL_DEBUG_BREAK_IF (aspectRatio == 0.f ); //division by zero
170+ const float w = h / aspectRatio;
171+
172+ _NBL_DEBUG_BREAK_IF (zNear == zFar); //division by zero
173+
174+ matrix <T, 4 , 4 > m;
175+ m[0 ] = vector <T, 4 >(w, 0.f , 0.f , 0.f );
176+ m[1 ] = vector <T, 4 >(0.f , -h, 0.f , 0.f );
177+ m[2 ] = vector <T, 4 >(0.f , 0.f , -zFar / (zFar - zNear), -zNear * zFar / (zFar - zNear));
178+ m[3 ] = vector <T, 4 >(0.f , 0.f , -1.f , 0.f );
179+
180+ return m;
181+ }
182+ template<typename T>
183+ inline matrix <T, 4 , 4 > buildProjectionMatrixPerspectiveFovLH (float fieldOfViewRadians, float aspectRatio, float zNear, float zFar)
184+ {
185+ const float h = core::reciprocal<float >(tanf (fieldOfViewRadians * 0.5f ));
186+ _NBL_DEBUG_BREAK_IF (aspectRatio == 0.f ); //division by zero
187+ const float w = h / aspectRatio;
188+
189+ _NBL_DEBUG_BREAK_IF (zNear == zFar); //division by zero
190+
191+ matrix <T, 4 , 4 > m;
192+ m[0 ] = vector <T, 4 >(w, 0.f , 0.f , 0.f );
193+ m[1 ] = vector <T, 4 >(0.f , -h, 0.f , 0.f );
194+ m[2 ] = vector <T, 4 >(0.f , 0.f , zFar / (zFar - zNear), -zNear * zFar / (zFar - zNear));
195+ m[3 ] = vector <T, 4 >(0.f , 0.f , 1.f , 0.f );
196+
197+ return m;
198+ }
199+
200+ template<typename T>
201+ inline matrix <T, 4 , 4 > buildProjectionMatrixOrthoRH (float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
202+ {
203+ _NBL_DEBUG_BREAK_IF (widthOfViewVolume == 0.f ); //division by zero
204+ _NBL_DEBUG_BREAK_IF (heightOfViewVolume == 0.f ); //division by zero
205+ _NBL_DEBUG_BREAK_IF (zNear == zFar); //division by zero
206+
207+ matrix <T, 4 , 4 > m;
208+ m[0 ] = vector <T, 4 >(2.f / widthOfViewVolume, 0.f , 0.f , 0.f );
209+ m[1 ] = vector <T, 4 >(0.f , -2.f / heightOfViewVolume, 0.f , 0.f );
210+ m[2 ] = vector <T, 4 >(0.f , 0.f , -1.f / (zFar - zNear), -zNear / (zFar - zNear));
211+ m[3 ] = vector <T, 4 >(0.f , 0.f , 0.f , 1.f );
212+
213+ return m;
214+ }
215+
216+ template<typename T>
217+ inline matrix <T, 4 , 4 > buildProjectionMatrixOrthoLH (float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
218+ {
219+ _NBL_DEBUG_BREAK_IF (widthOfViewVolume == 0.f ); //division by zero
220+ _NBL_DEBUG_BREAK_IF (heightOfViewVolume == 0.f ); //division by zero
221+ _NBL_DEBUG_BREAK_IF (zNear == zFar); //division by zero
222+
223+ matrix <T, 4 , 4 > m;
224+ m[0 ] = vector <T, 4 >(2.f / widthOfViewVolume, 0.f , 0.f , 0.f );
225+ m[1 ] = vector <T, 4 >(0.f , -2.f / heightOfViewVolume, 0.f , 0.f );
226+ m[2 ] = vector <T, 4 >(0.f , 0.f , 1.f / (zFar - zNear), -zNear / (zFar - zNear));
227+ m[3 ] = vector <T, 4 >(0.f , 0.f , 0.f , 1.f );
228+
229+ return m;
230+ }
231+
232+ }
233+ }
234+
235+ #endif
0 commit comments