OXYGENHUB
◆ main openmsx / src / unittest / gl_vec.cc
18.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "catch.hpp"
2
#include "gl_vec.hh"
3
4
#include "Math.hh"
5
6
#include <concepts>
7
8
using namespace gl;
9
10
// Test approximations.
11
template<std::floating_point T>
12
bool approxEq(T x, T y)
13
{
14
	return std::abs(x - y) < T(1.0e-5);
15
}
16
template<int N, std::floating_point T>
17
bool approxEq(const vecN<N, T>& x, const vecN<N, T>&y)
18
{
19
	return length2(x - y) < T(1.0e-4);
20
}
21
22
23
TEST_CASE("gl_vec: rsqrt")
24
{
25
	CHECK(gl::rsqrt(16.0f) == 0.25f);
26
	CHECK(gl::rsqrt(16.0 ) == 0.25 );
27
}
28
29
TEST_CASE("gl_vec: radians, degrees")
30
{
31
	CHECK(approxEq(radians(  0.0), 0.0         ));
32
	CHECK(approxEq(radians( 90.0), Math::pi / 2));
33
	CHECK(approxEq(radians(180.0), Math::pi    ));
34
	CHECK(approxEq(degrees(0.0         ),   0.0));
35
	CHECK(approxEq(degrees(Math::pi / 2),  90.0));
36
	CHECK(approxEq(degrees(Math::pi    ), 180.0));
37
}
38
39
// It's useful to test both integer and float variants because the
40
// former are implemented in plain C++ and (only) the latter have SSE
41
// optimizations.
42
43
TEST_CASE("gl_vec: constructors")
44
{
45
	SECTION("default constructor") {
46
		vec2 v2;
47
		CHECK(v2[0] == 0);
48
		CHECK(v2[1] == 0);
49
		ivec2 i2;
50
		CHECK(i2[0] == 0);
51
		CHECK(i2[1] == 0);
52
53
		vec3 v3;
54
		CHECK(v3[0] == 0);
55
		CHECK(v3[1] == 0);
56
		CHECK(v3[2] == 0);
57
		ivec3 i3;
58
		CHECK(i3[0] == 0);
59
		CHECK(i3[1] == 0);
60
		CHECK(i3[2] == 0);
61
62
		vec4 v4;
63
		CHECK(v4[0] == 0);
64
		CHECK(v4[1] == 0);
65
		CHECK(v4[2] == 0);
66
		CHECK(v4[3] == 0);
67
		ivec4 i4;
68
		CHECK(i4[0] == 0);
69
		CHECK(i4[1] == 0);
70
		CHECK(i4[2] == 0);
71
		CHECK(i4[3] == 0);
72
	}
73
	SECTION("broadcast constructor") {
74
		vec2 v2(2);
75
		CHECK(v2[0] == 2);
76
		CHECK(v2[1] == 2);
77
		ivec2 i2(2);
78
		CHECK(i2[0] == 2);
79
		CHECK(i2[1] == 2);
80
81
		vec3 v3(3);
82
		CHECK(v3[0] == 3);
83
		CHECK(v3[1] == 3);
84
		CHECK(v3[2] == 3);
85
		ivec3 i3(3);
86
		CHECK(i3[0] == 3);
87
		CHECK(i3[1] == 3);
88
		CHECK(i3[2] == 3);
89
90
		vec4 v4(4);
91
		CHECK(v4[0] == 4);
92
		CHECK(v4[1] == 4);
93
		CHECK(v4[2] == 4);
94
		CHECK(v4[3] == 4);
95
		ivec4 i4(4);
96
		CHECK(i4[0] == 4);
97
		CHECK(i4[1] == 4);
98
		CHECK(i4[2] == 4);
99
		CHECK(i4[3] == 4);
100
	}
101
	SECTION("per-element constructor") {
102
		vec2 v2(2, 3);
103
		CHECK(v2[0] == 2);
104
		CHECK(v2[1] == 3);
105
		ivec2 i2(2, 3);
106
		CHECK(i2[0] == 2);
107
		CHECK(i2[1] == 3);
108
109
		vec3 v3(3, 4, 5);
110
		CHECK(v3[0] == 3);
111
		CHECK(v3[1] == 4);
112
		CHECK(v3[2] == 5);
113
		ivec3 i3(3, 4, 5);
114
		CHECK(i3[0] == 3);
115
		CHECK(i3[1] == 4);
116
		CHECK(i3[2] == 5);
117
118
		vec4 v4(4, 5, 6, 7);
119
		CHECK(v4[0] == 4);
120
		CHECK(v4[1] == 5);
121
		CHECK(v4[2] == 6);
122
		CHECK(v4[3] == 7);
123
		ivec4 i4(4, 5, 6, 7);
124
		CHECK(i4[0] == 4);
125
		CHECK(i4[1] == 5);
126
		CHECK(i4[2] == 6);
127
		CHECK(i4[3] == 7);
128
	}
129
	SECTION("construct from smaller vectors/scalar") {
130
		vec3 v3(3, vec2(4, 5));
131
		CHECK(v3[0] == 3);
132
		CHECK(v3[1] == 4);
133
		CHECK(v3[2] == 5);
134
		ivec3 i3(ivec2(4, 5), 3);
135
		CHECK(i3[0] == 4);
136
		CHECK(i3[1] == 5);
137
		CHECK(i3[2] == 3);
138
139
		vec4 v4(4, vec3(5, 6, 7));
140
		CHECK(v4[0] == 4);
141
		CHECK(v4[1] == 5);
142
		CHECK(v4[2] == 6);
143
		CHECK(v4[3] == 7);
144
		ivec4 i4(ivec3(5, 6, 7), 4);
145
		CHECK(i4[0] == 5);
146
		CHECK(i4[1] == 6);
147
		CHECK(i4[2] == 7);
148
		CHECK(i4[3] == 4);
149
150
		vec4 w4(vec2(5, 6), vec2(7, 8));
151
		CHECK(w4[0] == 5);
152
		CHECK(w4[1] == 6);
153
		CHECK(w4[2] == 7);
154
		CHECK(w4[3] == 8);
155
		ivec4 j4(ivec2(5, 6), ivec2(7, 8));
156
		CHECK(j4[0] == 5);
157
		CHECK(j4[1] == 6);
158
		CHECK(j4[2] == 7);
159
		CHECK(j4[3] == 8);
160
161
	#if 0
162
		// Not implemented yet (also not yet needed).
163
		vec4 x4(1, vec2(3, 5), 7);
164
		CHECK(x4[0] == 1);
165
		CHECK(x4[1] == 3);
166
		CHECK(x4[2] == 5);
167
		CHECK(x4[3] == 7);
168
		ivec4 k4(2, ivec2(4, 6), 8);
169
		CHECK(k4[0] == 2);
170
		CHECK(k4[1] == 4);
171
		CHECK(k4[2] == 6);
172
		CHECK(k4[3] == 8);
173
	#endif
174
175
	#if 0
176
		// Ok, compile error:
177
		//   static assertion failed: wrong vector length in constructor
178
		ivec3 wrong1(3, ivec3(4, 5, 6));
179
		ivec4 wrong2(3, ivec2(4, 5));
180
		ivec4 wrong3(ivec2(4, 5), ivec3(8, 9));
181
	#endif
182
	}
183
}
184
185
TEST_CASE("gl_vec: modify elements")
186
{
187
	vec2 v2;
188
	v2[0] = 5;
189
	CHECK(v2[0] == 5);
190
	CHECK(v2[1] == 0);
191
	v2[1] = 7;
192
	CHECK(v2[0] == 5);
193
	CHECK(v2[1] == 7);
194
	ivec2 i2;
195
	i2[0] = 5;
196
	CHECK(i2[0] == 5);
197
	CHECK(i2[1] == 0);
198
	i2[1] = 7;
199
	CHECK(i2[0] == 5);
200
	CHECK(i2[1] == 7);
201
202
	vec3 v3(1);
203
	v3[1] = 2;
204
	CHECK(v3[0] == 1);
205
	CHECK(v3[1] == 2);
206
	CHECK(v3[2] == 1);
207
	ivec3 i3(1);
208
	i3[1] = 2;
209
	CHECK(i3[0] == 1);
210
	CHECK(i3[1] == 2);
211
	CHECK(i3[2] == 1);
212
213
	vec4 v4(1, 2, 3, 4);
214
	v4[0] = 9; v4[2] = 8;
215
	CHECK(v4[0] == 9);
216
	CHECK(v4[1] == 2);
217
	CHECK(v4[2] == 8);
218
	CHECK(v4[3] == 4);
219
	ivec4 i4(1, 2, 3, 4);
220
	i4[0] = 9; i4[2] = 8;
221
	CHECK(i4[0] == 9);
222
	CHECK(i4[1] == 2);
223
	CHECK(i4[2] == 8);
224
	CHECK(i4[3] == 4);
225
}
226
227
TEST_CASE("gl_vec: (in)equality")
228
{
229
	CHECK( vec2(1, 2) ==  vec2(1, 2));
230
	CHECK( vec2(1, 2) !=  vec2(1, 4));
231
	CHECK( vec2(1, 2) !=  vec2(3, 2));
232
	CHECK( vec2(1, 2) !=  vec2(3, 4));
233
	CHECK(ivec2(1, 2) == ivec2(1, 2));
234
	CHECK(ivec2(1, 2) != ivec2(1, 4));
235
	CHECK(ivec2(1, 2) != ivec2(3, 2));
236
	CHECK(ivec2(1, 2) != ivec2(3, 4));
237
238
	CHECK( vec3(1, 2, 3) ==  vec3(1, 2, 3));
239
	CHECK( vec3(1, 2, 3) !=  vec3(1, 2, 4));
240
	CHECK(ivec3(1, 2, 3) == ivec3(1, 2, 3));
241
	CHECK(ivec3(1, 2, 3) != ivec3(1, 2, 4));
242
243
	CHECK( vec4(1, 2, 3, 4) ==  vec4(1, 2, 3, 4));
244
	CHECK( vec4(1, 2, 3, 4) !=  vec4(1, 2, 4, 4));
245
	CHECK(ivec4(1, 2, 3, 4) == ivec4(1, 2, 3, 4));
246
	CHECK(ivec4(1, 2, 3, 4) != ivec4(1, 2, 4, 4));
247
}
248
249
TEST_CASE("gl_vec: copy constructor, assignment")
250
{
251
	SECTION("vec2") {
252
		vec2 v(2, 3);
253
		vec2 w(v); CHECK(v == w);
254
		v[0] = 9;  CHECK(v != w);
255
		w = v;     CHECK(v == w);
256
	}
257
	SECTION("ivec2") {
258
		ivec2 v(2, 3);
259
		ivec2 w(v); CHECK(v == w);
260
		v[1] = 9;   CHECK(v != w);
261
		w = v;      CHECK(v == w);
262
	}
263
	SECTION("vec3") {
264
		vec3 v(3, 4, 5);
265
		vec3 w(v); CHECK(v == w);
266
		v[2] = 8;  CHECK(v != w);
267
		w = v;     CHECK(v == w);
268
	}
269
	SECTION("ivec3") {
270
		ivec3 v(3, 4, 5);
271
		ivec3 w(v); CHECK(v == w);
272
		v[1] = 8;   CHECK(v != w);
273
		w = v;      CHECK(v == w);
274
	}
275
	SECTION("vec4") {
276
		vec4 v(4, 5, 6, 7);
277
		vec4 w(v); CHECK(v == w);
278
		v[3] = 0;  CHECK(v != w);
279
		w = v;     CHECK(v == w);
280
	}
281
	SECTION("ivec4") {
282
		ivec4 v(4, 5, 6, 7);
283
		ivec4 w(v); CHECK(v == w);
284
		v[0] = 1;   CHECK(v != w);
285
		w = v;      CHECK(v == w);
286
	}
287
}
288
289
TEST_CASE("gl_vec: construct from larger vector")
290
{
291
	vec4 v4(1, 2, 3, 4);
292
	vec3 v3(7, 8, 9);
293
	CHECK(vec3(v4) == vec3(1, 2, 3));
294
	CHECK(vec2(v4) == vec2(1, 2));
295
	CHECK(vec2(v3) == vec2(7, 8));
296
297
	ivec4 i4(1, 2, 3, 4);
298
	ivec3 i3(7, 8, 9);
299
	CHECK(ivec3(i4) == ivec3(1, 2, 3));
300
	CHECK(ivec2(i4) == ivec2(1, 2));
301
	CHECK(ivec2(i3) == ivec2(7, 8));
302
}
303
304
// From here on I'll skip tests on vec2 and ivec2.
305
// Vectors of dimension 2 and 3 are handled by the same C++ code, so
306
// if there's a bug it should show up in both types.
307
308
TEST_CASE("gl_vec: vector add")
309
{
310
	 vec3 v3(1, 2, 3);  vec4 v4(1, 2, 3, 4);
311
	ivec3 i3(1, 2, 3); ivec4 i4(1, 2, 3, 4);
312
	CHECK((v3 +  vec3(4, 5, 6))    ==  vec3(5, 7, 9));
313
	CHECK((i3 + ivec3(4, 5, 6))    == ivec3(5, 7, 9));
314
	CHECK((v4 +  vec4(4, 5, 6, 7)) ==  vec4(5, 7, 9, 11));
315
	CHECK((i4 + ivec4(4, 5, 6, 7)) == ivec4(5, 7, 9, 11));
316
317
	v3 +=  vec3(2, 3, 4);
318
	i3 += ivec3(2, 3, 4);
319
	v4 +=  vec4(2, 3, 4, 5);
320
	i4 += ivec4(2, 3, 4, 5);
321
	CHECK(v3 ==  vec3(3, 5, 7));
322
	CHECK(i3 == ivec3(3, 5, 7));
323
	CHECK(v4 ==  vec4(3, 5, 7, 9));
324
	CHECK(i4 == ivec4(3, 5, 7, 9));
325
}
326
327
TEST_CASE("gl_vec: vector subtract")
328
{
329
	 vec3 v3(1, 2, 3);  vec4 v4(1, 2, 3, 4);
330
	ivec3 i3(1, 2, 3); ivec4 i4(1, 2, 3, 4);
331
	CHECK((v3 -  vec3(4, 3, 2))    ==  vec3(-3, -1, 1));
332
	CHECK((i3 - ivec3(4, 3, 2))    == ivec3(-3, -1, 1));
333
	CHECK((v4 -  vec4(4, 3, 2, 1)) ==  vec4(-3, -1, 1, 3));
334
	CHECK((i4 - ivec4(4, 3, 2, 1)) == ivec4(-3, -1, 1, 3));
335
336
	v3 -=  vec3(2, 4, 6);
337
	i3 -= ivec3(2, 4, 6);
338
	v4 -=  vec4(2, 4, 6, 8);
339
	i4 -= ivec4(2, 4, 6, 8);
340
	CHECK(v3 ==  vec3(-1, -2, -3));
341
	CHECK(i3 == ivec3(-1, -2, -3));
342
	CHECK(v4 ==  vec4(-1, -2, -3, -4));
343
	CHECK(i4 == ivec4(-1, -2, -3, -4));
344
}
345
346
TEST_CASE("gl_vec: vector negate")
347
{
348
	CHECK((- vec3(4, -3, 2))     ==  vec3(-4, 3, -2));
349
	CHECK((-ivec3(4, -3, 2))     == ivec3(-4, 3, -2));
350
	CHECK((- vec4(4, -3, 2, -1)) ==  vec4(-4, 3, -2, 1));
351
	CHECK((-ivec4(4, -3, 2, -1)) == ivec4(-4, 3, -2, 1));
352
}
353
354
TEST_CASE("gl_vec: component-wise vector multiplication")
355
{
356
	 vec3 v3(0, 2, -3);  vec4 v4(0, 2, -3, 4);
357
	ivec3 i3(0, 2, -3); ivec4 i4(0, 2, -3, 4);
358
	// scalar * vector
359
	CHECK((2.0f * v3) ==  vec3(0, 4, -6));
360
	CHECK((2    * i3) == ivec3(0, 4, -6));
361
	CHECK((2.0f * v4) ==  vec4(0, 4, -6, 8));
362
	CHECK((2    * i4) == ivec4(0, 4, -6, 8));
363
	// vector * scalar
364
	CHECK((v3 * 2.0f) ==  vec3(0, 4, -6));
365
	CHECK((i3 * 2   ) == ivec3(0, 4, -6));
366
	CHECK((v4 * 2.0f) ==  vec4(0, 4, -6, 8));
367
	CHECK((i4 * 2   ) == ivec4(0, 4, -6, 8));
368
	// vector * vector
369
	 vec3 w3(-1, 2, -3);  vec4 w4(-1, 2, -3, -4);
370
	ivec3 j3(-1, 2, -3); ivec4 j4(-1, 2, -3, -4);
371
	CHECK((v3 * w3) ==  vec3(0, 4, 9));
372
	CHECK((i3 * j3) == ivec3(0, 4, 9));
373
	CHECK((v4 * w4) ==  vec4(0, 4, 9, -16));
374
	CHECK((i4 * j4) == ivec4(0, 4, 9, -16));
375
	// *= scalar
376
	v3 *= 2.0f; CHECK(v3 ==  vec3(0, 4, -6));
377
	i3 *= 2;    CHECK(i3 == ivec3(0, 4, -6));
378
	v4 *= 2.0f; CHECK(v4 ==  vec4(0, 4, -6, 8));
379
	i4 *= 2;    CHECK(i4 == ivec4(0, 4, -6, 8));
380
	// *= vector
381
	v3 *= w3; CHECK(v3 ==  vec3(0, 8, 18));
382
	i3 *= j3; CHECK(i3 == ivec3(0, 8, 18));
383
	v4 *= w4; CHECK(v4 ==  vec4(0, 8, 18, -32));
384
	i4 *= j4; CHECK(i4 == ivec4(0, 8, 18, -32));
385
}
386
387
TEST_CASE("gl_vec: reciprocal (only floating point)")
388
{
389
	CHECK(approxEq(recip(vec3(4, 2, 0.5)),    vec3(0.25, 0.5, 2)));
390
	CHECK(approxEq(recip(vec4(4, 2, 0.5, 1)), vec4(0.25, 0.5, 2, 1)));
391
}
392
393
TEST_CASE("gl_vec: component-wise division (only floating point)")
394
{
395
	vec3 v3( 0,  1, -4);
396
	vec3 w3(-1, -2,  2);
397
	CHECK((v3 / 2.0f) == vec3( 0,  0.5f, -2));
398
	CHECK((6.0f / w3) == vec3(-6, -3, 3));
399
	CHECK((v3 / w3)   == vec3( 0, -0.5f, -2));
400
401
	vec4 v4( 2, 1, -4, -3);
402
	vec4 w4(-1, 2,  2, -6);
403
	CHECK(approxEq((v4 / -2.0f), vec4(-1, -0.5f, 2, 1.5f)));
404
	CHECK(approxEq((6.0f / w4), vec4(-6, 3, 3, -1)));
405
	CHECK(approxEq((v4 / w4), vec4(-2, 0.5f, -2, 0.5f)));
406
}
407
408
TEST_CASE("gl_vec: component-wise min/max")
409
{
410
	CHECK(min( vec3(2, 3, 4),  vec3(1, -5, 7)) ==  vec3(1, -5, 4));
411
	CHECK(min(ivec3(2, 3, 4), ivec3(1, -5, 7)) == ivec3(1, -5, 4));
412
	CHECK(min( vec4(1, -2, 5, -7),  vec4(0, 2, -4, -3)) ==  vec4(0, -2, -4, -7));
413
	CHECK(min(ivec4(1, -2, 5, -7), ivec4(0, 2, -4, -3)) == ivec4(0, -2, -4, -7));
414
415
	CHECK(max( vec3(2, 3, 4),  vec3(1, -5, 7)) ==  vec3(2, 3, 7));
416
	CHECK(max(ivec3(2, 3, 4), ivec3(1, -5, 7)) == ivec3(2, 3, 7));
417
	CHECK(max( vec4(1, -2, 5, -7),  vec4(0, 2, -4, -3)) ==  vec4(1, 2, 5, -3));
418
	CHECK(max(ivec4(1, -2, 5, -7), ivec4(0, 2, -4, -3)) == ivec4(1, 2, 5, -3));
419
}
420
421
TEST_CASE("gl_vec: minimum component within a vector")
422
{
423
	CHECK(min_component( vec3(1, 5, -7.2f)) == -7.2f);
424
	CHECK(min_component(ivec3(3, 2, 4)) == 2);
425
	CHECK(min_component( vec4(-1, 2, 5.2f, 0)) == -1);
426
	CHECK(min_component(ivec4(1, -2, 5, -7)) == -7);
427
}
428
429
TEST_CASE("gl_vec: clamp") {
430
	CHECK(clamp( vec3(2, 3, 4),  vec3(0, 4, -4),  vec3(4, 7, 0)) ==  vec3(2, 4, 0));
431
	CHECK(clamp(ivec3(2, 3, 4), ivec3(0, 4, -4), ivec3(4, 7, 0)) == ivec3(2, 4, 0));
432
	CHECK(clamp( vec4(4, 2, 7, 1),  vec4(0, 3, 2, 1),  vec4(4, 6, 8, 3)) ==  vec4(4, 3, 7, 1));
433
	CHECK(clamp(ivec4(4, 2, 7, 1), ivec4(0, 3, 2, 1), ivec4(4, 6, 8, 3)) == ivec4(4, 3, 7, 1));
434
435
	CHECK(clamp( vec3(2, 3, 4), 1.0f, 3.0f) ==  vec3(2, 3, 3));
436
	CHECK(clamp(ivec3(2, 3, 4), 1,    3   ) == ivec3(2, 3, 3));
437
	CHECK(clamp( vec4(4, 2, 7, 1), 2.0f, 6.0f) ==  vec4(4, 2, 6, 2));
438
	CHECK(clamp(ivec4(4, 2, 7, 1), 2,    6   ) == ivec4(4, 2, 6, 2));
439
}
440
441
TEST_CASE("gl_vec: sum of vector components")
442
{
443
	CHECK(sum( vec3(4, -3, 2))     == 3.0f);
444
	CHECK(sum(ivec3(4, -3, 2))     == 3   );
445
	CHECK(sum( vec4(4, -3, 2, -1)) == 2.0f);
446
	CHECK(sum(ivec4(4, -3, 2, -1)) == 2   );
447
448
	CHECK(sum_broadcast(vec3(4, -3, 2))     == vec3(3.0f));
449
	CHECK(sum_broadcast(vec4(4, -3, 2, -1)) == vec4(2.0f));
450
}
451
452
TEST_CASE("gl_vec: dot product")
453
{
454
	CHECK(dot( vec3(4, -3, 2),      vec3(-1, 3, 2)    ) == -9.0f);
455
	CHECK(dot(ivec3(4, -3, 2),     ivec3(-1, 3, 2)    ) == -9   );
456
	CHECK(dot( vec4(4, -3, 2, -1),  vec4(-1, 3, 2, -2)) == -7.0f);
457
	CHECK(dot(ivec4(4, -3, 2, -1), ivec4(-1, 3, 2, -2)) == -7   );
458
459
	CHECK(dot_broadcast(vec3(4, -3, 2),     vec3(-1, 3, 2)    ) == vec3(-9.0f));
460
	CHECK(dot_broadcast(vec4(4, -3, 2, -1), vec4(-1, 3, 2, -2)) == vec4(-7.0f));
461
}
462
463
TEST_CASE("gl_vec: cross product (only for vectors of length 3)")
464
{
465
	CHECK(cross( vec3(4, -3, 2),  vec3(-1, 3, 2)) ==  vec3(-12, -10, 9));
466
	CHECK(cross(ivec3(4, -3, 2), ivec3(-1, 3, 2)) == ivec3(-12, -10, 9));
467
}
468
469
TEST_CASE("gl_vec: vector length squared (2-norm squared)")
470
{
471
	CHECK(length2( vec3(4, -3, 2    )) == 29.0f);
472
	CHECK(length2(ivec3(4, -3, 2    )) == 29   );
473
	CHECK(length2( vec4(4, -3, 2, -1)) == 30.0f);
474
	CHECK(length2(ivec4(4, -3, 2, -1)) == 30   );
475
}
476
TEST_CASE("gl_vec: vector length (2-norm), (only floating point)")
477
{
478
	CHECK(length(vec3(4, -3, 2    )) == sqrtf(29.0f));
479
	CHECK(length(vec4(4, -3, 2, -1)) == sqrtf(30.0f));
480
}
481
482
TEST_CASE("gl_vec: vector normalization, only floating point")
483
{
484
	CHECK(normalize(vec3( 0, 4, -3   )) == vec3( 0.0f, 0.8f, -0.6f));
485
	CHECK(normalize(vec4(-4, 0,  0, 3)) == vec4(-0.8f, 0.0f,  0.0f, 0.6f));
486
}
487
488
TEST_CASE("gl_vec: round")
489
{
490
	CHECK(round(vec3( 1.1f, 2.6f, -3.8f))        == ivec3( 1, 3, -4));
491
	CHECK(round(vec4(-1.1f, 2.4f,  3.8f, -4.6f)) == ivec4(-1, 2,  4, -5));
492
	// round integers, nop
493
	CHECK(round(ivec4(1, -2, 3, -4)) == ivec4(1, -2, 3, -4));
494
}
495
496
TEST_CASE("gl_vec: trunc")
497
{
498
	CHECK(trunc(vec3( 1.1f, 2.5f, -3.8f))        == ivec3( 1, 2, -3));
499
	CHECK(trunc(vec4(-1.1f, 2.5f,  3.8f, -4.5f)) == ivec4(-1, 2,  3, -4));
500
	// trunc integers, nop
501
	CHECK(trunc(ivec4(1, -2, 3, -4)) == ivec4(1, -2, 3, -4));
502
}
503
504
TEST_CASE("gl_vec: named elements")
505
{
506
	SECTION("ivec2") {
507
		ivec2 v2(10, 20);
508
		CHECK(sizeof(v2) == 2 * sizeof(int));
509
510
		CHECK(v2[0] == 10);
511
		CHECK(v2[1] == 20);
512
		CHECK(v2.x == 10);
513
		CHECK(v2.y == 20);
514
515
		v2.x = 100;
516
		v2.y = 200;
517
		CHECK(v2[0] == 100);
518
		CHECK(v2[1] == 200);
519
		CHECK(v2.x == 100);
520
		CHECK(v2.y == 200);
521
522
		v2[0] = 3;
523
		v2[1] = 4;
524
		CHECK(v2[0] == 3);
525
		CHECK(v2[1] == 4);
526
		CHECK(v2.x == 3);
527
		CHECK(v2.y == 4);
528
529
		//v2.z = 10;     // Ok, compile error
530
		//int i = v2.z;
531
	}
532
	SECTION("ivec3") {
533
		ivec3 v3(10, 20, 30);
534
		CHECK(sizeof(v3) == 3 * sizeof(int));
535
536
		CHECK(v3.x == 10);
537
		CHECK(v3.y == 20);
538
		CHECK(v3.z == 30);
539
540
		v3.x = 100;
541
		v3.y = 200;
542
		v3.z = 300;
543
		CHECK(v3.x == 100);
544
		CHECK(v3.y == 200);
545
		CHECK(v3.z == 300);
546
547
		//v3.w = 10;     // Ok, compile error
548
		//int i = v3.w;
549
	}
550
	SECTION("ivec4") {
551
		ivec4 v4(10, 20, 30, 40);
552
		CHECK(sizeof(v4) == 4 * sizeof(int));
553
554
		CHECK(v4.x == 10);
555
		CHECK(v4.y == 20);
556
		CHECK(v4.z == 30);
557
		CHECK(v4.w == 40);
558
559
		v4.x = 100;
560
		v4.y = 200;
561
		v4.z = 300;
562
		v4.w = 400;
563
		CHECK(v4.x == 100);
564
		CHECK(v4.y == 200);
565
		CHECK(v4.z == 300);
566
		CHECK(v4.w == 400);
567
	}
568
}
569
570
571
#if 0
572
573
// The following functions are not part of the actual test. They get compiled,
574
// but never executed. I used them to (manually) inspect the quality of the
575
// generated code. Mostly only for vec4, because the code was only optimized
576
// for that type.
577
578
void test_constr(vec4& z)
579
{
580
	z = vec4();
581
}
582
void test_constr(float x, vec4& z)
583
{
584
	z = vec4(x);
585
}
586
void test_constr(float a, float b, float c, float d, vec4& z)
587
{
588
	z = vec4(a, b, c, d);
589
}
590
591
void test_change0(float x, vec4& z)
592
{
593
	z[0] = x;
594
}
595
void test_change2(float x, vec4& z)
596
{
597
	z[2] = x;
598
}
599
600
void test_extract0(const vec4& x, float& z)
601
{
602
	z = x[0];
603
}
604
void test_extract2(const vec4& x, float& z)
605
{
606
	z = x[2];
607
}
608
609
bool test_equal(const vec4& x, const vec4& y)
610
{
611
	return x == y;
612
}
613
bool test_not_equal(const vec4& x, const vec4& y)
614
{
615
	return x != y;
616
}
617
618
void test_add(const vec4& x, const vec4& y, vec4& z)
619
{
620
	z = x + y;
621
}
622
void test_add(vec4& x, const vec4& y)
623
{
624
	x += y;
625
}
626
627
void test_negate(const vec4& x, vec4& y)
628
{
629
	y = -x;
630
}
631
632
void test_mul(const vec4& x, const vec4& y, vec4& z)
633
{
634
	z = x * y;
635
}
636
void test_mul(float x, const vec4& y, vec4& z)
637
{
638
	z = x * y;
639
}
640
641
void test_div(const vec4& x, const vec4& y, vec4& z)
642
{
643
	z = x / y;
644
}
645
void test_div(float x, const vec4& y, vec4& z)
646
{
647
	z = x / y;
648
}
649
void test_div(const vec4& x, float y, vec4& z)
650
{
651
	z = x / y;
652
}
653
654
void test_sum(const vec4& x, float& y)
655
{
656
	y = sum(x);
657
}
658
void test_sum_broadcast(const vec4& x, vec4& y)
659
{
660
	y = sum_broadcast(x);
661
}
662
663
void test_dot(const vec4& x, const vec4& y, float& z)
664
{
665
	z = dot(x, y);
666
}
667
void test_dot_broadcast(const vec4& x, const vec4& y, vec4& z)
668
{
669
	z = dot_broadcast(x, y);
670
}
671
672
void test_length2(const vec4& x, float& y)
673
{
674
	y = length2(x);
675
}
676
677
void test_length(const vec4& x, float& y)
678
{
679
	y = length(x);
680
}
681
682
void test_normalize(const vec4& x, vec4& y)
683
{
684
	y = normalize(x);
685
}
686
687
void test_recip(const vec4& x, vec4& y)
688
{
689
	y = recip(x);
690
}
691
692
693
void test_constr(vec3& z)
694
{
695
	z = vec3();
696
}
697
void test_constr(float x, vec3& z)
698
{
699
	z = vec3(x);
700
}
701
void test_constr(float a, float b, float c, vec3& z)
702
{
703
	z = vec3(a, b, c);
704
}
705
void test_constr(vec4 x, vec3& y)
706
{
707
	y = vec3(x);
708
}
709
710
void test_change0(float x, vec3& z)
711
{
712
	z[0] = x;
713
}
714
void test_change2(float x, vec3& z)
715
{
716
	z[2] = x;
717
}
718
719
void test_extract0(const vec3& x, float& z)
720
{
721
	z = x[0];
722
}
723
void test_extract2(const vec3& x, float& z)
724
{
725
	z = x[2];
726
}
727
728
bool test_equal(const vec3& x, const vec3& y)
729
{
730
	return x == y;
731
}
732
bool test_not_equal(const vec3& x, const vec3& y)
733
{
734
	return x != y;
735
}
736
737
void test_add(const vec3& x, const vec3& y, vec3& z)
738
{
739
	z = x + y;
740
}
741
void test_add(vec3& x, const vec3& y)
742
{
743
	x += y;
744
}
745
746
void test_negate(const vec3& x, vec3& y)
747
{
748
	y = -x;
749
}
750
751
void test_mul(const vec3& x, const vec3& y, vec3& z)
752
{
753
	z = x * y;
754
}
755
void test_mul(float x, const vec3& y, vec3& z)
756
{
757
	z = x * y;
758
}
759
760
void test_div(const vec3& x, const vec3& y, vec3& z)
761
{
762
	z = x / y;
763
}
764
void test_div(float x, const vec3& y, vec3& z)
765
{
766
	z = x / y;
767
}
768
void test_div(const vec3& x, float y, vec3& z)
769
{
770
	z = x / y;
771
}
772
773
void test_min(const vec3& x, const vec3& y, vec3& z)
774
{
775
	z = min(x, y);
776
}
777
778
void test_min(const vec4& x, const vec4& y, vec4& z)
779
{
780
	z = min(x, y);
781
}
782
783
void test_clamp(const vec3& x, const vec3& y, const vec3& z, vec3& w)
784
{
785
	w = clamp(x, y, z);
786
}
787
788
void test_clamp(const vec4& x, const vec4& y, const vec4& z, vec4& w)
789
{
790
	w = clamp(x, y, z);
791
}
792
793
void test_clamp(const vec3& x, float y, float z, vec3& w)
794
{
795
	w = clamp(x, y, z);
796
}
797
798
void test_clamp(const vec4& x, float y, float z, vec4& w)
799
{
800
	w = clamp(x, y, z);
801
}
802
803
void test_clamp(const vec4& x, vec4& y)
804
{
805
	y = clamp(x, 0.0f, 1.0f);
806
}
807
808
void test_sum(const vec3& x, float& y)
809
{
810
	y = sum(x);
811
}
812
813
void test_dot(const vec3& x, const vec3& y, float& z)
814
{
815
	z = dot(x, y);
816
}
817
818
void test_length2(const vec3& x, float& y)
819
{
820
	y = length2(x);
821
}
822
823
void test_length(const vec3& x, float& y)
824
{
825
	y = length(x);
826
}
827
828
void test_normalize(const vec3& x, vec3& y)
829
{
830
	y = normalize(x);
831
}
832
833
void test_round(const vec4& x, ivec4& y)
834
{
835
	y = round(x);
836
}
837
void test_trunc(const vec4& x, ivec4& y)
838
{
839
	y = trunc(x);
840
}
841
842
#endif