Browse code

Add cpp-v2

Ingemar Ragnemalm authored on 21/02/2024 20:24:29 • Robert Cranston committed on 21/02/2024 20:24:29
Showing 1 changed files
1 1
deleted file mode 100755
... ...
@@ -1,1125 +0,0 @@
1
-// VectorUtils
2
-// Vector and matrix manipulation library for OpenGL, a package of the most essential functions.
3
-// Includes:
4
-// - Basic vector operations: Add, subtract, scale, dot product, cross product.
5
-// - Basic matrix operations: Multiply matrix to matrix, matric to vector, transpose.
6
-// - Creation of transformation matrixces: Translation, scaling, rotation.
7
-// - A few more special operations: Orthonormalizaton of a matrix, CrossMatrix,
8
-// - Replacements of some GLU functions: lookAt, frustum, perspective.
9
-// - Inverse and inverse transpose for creating normal matrices.
10
-// Supports both C and C++. The C interface makes it accessible from most languages if desired.
11
-
12
-// A note on completeness:
13
-// All operations may not be 100% symmetrical over all types, and some GLSL types are
14
-// missing (like vec2). These will be added if proven important. There is already
15
-// some calls of minor importance (mat3 * mat3, mat3 * vec3) included only for
16
-// symmetry. I don't want the code to grow a lot for such reasons, I want it to be
17
-// compact and to the point.
18
-
19
-// Current open design questions:
20
-// Naming conventions: Lower case or capitalized? (Frustum/frustum)
21
-// Prefix for function calls? (The cost would be more typing and making the code harder to read.)
22
-// Add vector operations for vec4? Other *essential* symmetry issues?
23
-// Names for functions when supporting both vec3 and vec4, mat3 and mat4? (vec3Add, vec4Add?)
24
-
25
-
26
-// History:
27
-
28
-// VectorUtils is a small (but growing) math unit by Ingemar Ragnemalm.
29
-// It originated as "geom3d" by Andrew Meggs, but that unit is no more
30
-// than inspiration today. The original VectorUtils(1) was based on it,
31
-// while VectorUtils2 was a rewrite primarily to get rid of the over-use
32
-// of arrays in the original.
33
-
34
-// New version 120201:
35
-// Defaults to matrices "by the book". Can also be configured to the flipped
36
-// column-wise matrices that old OpenGL required (and we all hated).
37
-// This is freshly implemented, limited testing, so there can be bugs.
38
-// But it seems to work just fine on my tests with translation, rotations
39
-// and matrix multiplications.
40
-
41
-// 1208??: Added lookAt, perspective, frustum
42
-// Also made Transpose do what it should. TransposeRotation is the old function.
43
-// 120913: Fixed perspective. Never trust other's code...
44
-// 120925: Transposing in CrossMatrix
45
-// 121119: Fixed one more glitch in perspective.
46
-
47
-// 130227 First draft to a version 3.
48
-// C++ operators if accessed from C++
49
-// Vectors by value when possible. Return values on the stack.
50
-// (Why was this not the case in VectorUtils2? Beause I tried to stay compatible
51
-// with an old C compiler. Older C code generally prefers all non-scalar data by
52
-// reference. But I'd like to move away from that now.)
53
-// Types conform with GLSL as much as possible (vec3, mat4)
54
-// Added some operations for mat3 and vec4, but most of them are more for
55
-// completeness than usefulness; I find vec3's and mat4's to be what I use
56
-// most of the time.
57
-// Also added InvertMat3 and InversTranspose to support creation of normal matrices.
58
-// Marked some calls for removal: CopyVector, TransposeRotation, CopyMatrix.
59
-// 130308: Added InvertMat4 and some more vec3/vec4 operators (+= etc)
60
-// 130922: Fixed a vital bug in CrossMatrix.
61
-// 130924: Fixed a bug in mat3tomat4.
62
-// 131014: Added TransposeMat3 (although I doubt its importance)
63
-// 140213: Corrected mat3tomat4. (Were did the correction in 130924 go?)
64
-// 151210: Added printMat4 and printVec3.
65
-// 160302: Added empty constructors for vec3 and vec4.
66
-// 170221: Uses _WIN32 instead of WIN32
67
-// 170331: Added stdio.h for printMat4 and printVec3
68
-// 180314: Added some #defines for moving closer to GLSL (dot, cross...).
69
-// 2021-05-15: Constructiors for vec3 etc replaced in order to avoid
70
-// problems with some C++ compilers.
71
-// 2022-05-14: Corrected transposed version of lookAtv.
72
-// 2023-01-31: Added shader upload utility functions.
73
-
74
-// You may use VectorUtils as you please. A reference to the origin is appreciated
75
-// but if you grab some snippets from it without reference... no problem.
76
-
77
-
78
-#include "VectorUtils3.h"
79
-
80
-// VS doesn't define NAN properly
81
-#ifdef _WIN32
82
-    #ifndef NAN
83
-        static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
84
-        #define NAN (*(const float *) __nan)
85
-    #endif
86
-#endif
87
-
88
-char transposed = 0;
89
-
90
-	vec3 SetVector(GLfloat x, GLfloat y, GLfloat z)
91
-	{
92
-		vec3 v;
93
-		
94
-		v.x = x;
95
-		v.y = y;
96
-		v.z = z;
97
-		return v;
98
-	}
99
-
100
-// New better name
101
-	vec2 SetVec2(GLfloat x, GLfloat y)
102
-	{
103
-		vec2 v;
104
-		
105
-		v.x = x;
106
-		v.y = y;
107
-		return v;
108
-	}
109
-
110
-	vec3 SetVec3(GLfloat x, GLfloat y, GLfloat z)
111
-	{
112
-		vec3 v;
113
-		
114
-		v.x = x;
115
-		v.y = y;
116
-		v.z = z;
117
-		return v;
118
-	}
119
-
120
-	vec4 SetVec4(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
121
-	{
122
-		vec4 v;
123
-		
124
-		v.x = x;
125
-		v.y = y;
126
-		v.z = z;
127
-		v.w = w;
128
-		return v;
129
-	}
130
-
131
-// Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
132
-	mat3 SetMat3(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7, GLfloat p8)
133
-	{
134
-		mat3 m;
135
-		m.m[0] = p0;
136
-		m.m[1] = p1;
137
-		m.m[2] = p2;
138
-		m.m[3] = p3;
139
-		m.m[4] = p4;
140
-		m.m[5] = p5;
141
-		m.m[6] = p6;
142
-		m.m[7] = p7;
143
-		m.m[8] = p8;
144
-		return m;
145
-	}
146
-
147
-// Like above; Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
148
-	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
149
-				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
150
-				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11, 
151
-				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
152
-				)
153
-	{
154
-		mat4 m;
155
-		m.m[0] = p0;
156
-		m.m[1] = p1;
157
-		m.m[2] = p2;
158
-		m.m[3] = p3;
159
-		m.m[4] = p4;
160
-		m.m[5] = p5;
161
-		m.m[6] = p6;
162
-		m.m[7] = p7;
163
-		m.m[8] = p8;
164
-		m.m[9] = p9;
165
-		m.m[10] = p10;
166
-		m.m[11] = p11;
167
-		m.m[12] = p12;
168
-		m.m[13] = p13;
169
-		m.m[14] = p14;
170
-		m.m[15] = p15;
171
-		return m;
172
-	}
173
-
174
-
175
-	// vec3 operations
176
-	// vec4 operations can easily be added but I havn't seen much need for them.
177
-	// Some are defined as C++ operators though.
178
-
179
-	vec3 VectorSub(vec3 a, vec3 b)
180
-	{
181
-		vec3 result;
182
-		
183
-		result.x = a.x - b.x;
184
-		result.y = a.y - b.y;
185
-		result.z = a.z - b.z;
186
-		return result;
187
-	}
188
-	
189
-	vec3 VectorAdd(vec3 a, vec3 b)
190
-	{
191
-		vec3 result;
192
-		
193
-		result.x = a.x + b.x;
194
-		result.y = a.y + b.y;
195
-		result.z = a.z + b.z;
196
-		return result;
197
-	}
198
-
199
-	vec3 CrossProduct(vec3 a, vec3 b)
200
-	{
201
-		vec3 result;
202
-
203
-		result.x = a.y*b.z - a.z*b.y;
204
-		result.y = a.z*b.x - a.x*b.z;
205
-		result.z = a.x*b.y - a.y*b.x;
206
-		
207
-		return result;
208
-	}
209
-
210
-	GLfloat DotProduct(vec3 a, vec3 b)
211
-	{
212
-		return a.x * b.x + a.y * b.y + a.z * b.z;
213
-	}
214
-
215
-	vec3 ScalarMult(vec3 a, GLfloat s)
216
-	{
217
-		vec3 result;
218
-		
219
-		result.x = a.x * s;
220
-		result.y = a.y * s;
221
-		result.z = a.z * s;
222
-		
223
-		return result;
224
-	}
225
-
226
-	GLfloat Norm(vec3 a)
227
-	{
228
-		GLfloat result;
229
-
230
-		result = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
231
-		return result;
232
-	}
233
-
234
-	vec3 Normalize(vec3 a)
235
-	{
236
-		GLfloat norm;
237
-		vec3 result;
238
-
239
-		norm = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
240
-		result.x = a.x / norm;
241
-		result.y = a.y / norm;
242
-		result.z = a.z / norm;
243
-		return result;
244
-	}
245
-
246
-	vec3 CalcNormalVector(vec3 a, vec3 b, vec3 c)
247
-	{
248
-		vec3 n;
249
-
250
-		n = CrossProduct(VectorSub(a, b), VectorSub(a, c));
251
-		n = ScalarMult(n, 1/Norm(n));
252
-		
253
-		return n;
254
-	}
255
-
256
-// Splits v into vn (parallell to n) and vp (perpendicular). Does not demand n to be normalized.
257
-	void SplitVector(vec3 v, vec3 n, vec3 *vn, vec3 *vp)
258
-	{
259
-		GLfloat nlen;
260
-		GLfloat nlen2;
261
-
262
-		nlen = DotProduct(v, n);
263
-		nlen2 = n.x*n.x+n.y*n.y+n.z*n.z; // Squared length
264
-		if (nlen2 == 0)
265
-		{
266
-			*vp = v;
267
-			*vn = SetVector(0, 0, 0);
268
-		}
269
-		else
270
-		{
271
-			*vn = ScalarMult(n, nlen/nlen2);
272
-			*vp = VectorSub(v, *vn);
273
-		}
274
-	}
275
-
276
-// Matrix operations primarily on 4x4 matrixes!
277
-// Row-wise by default but can be configured to column-wise (see SetTransposed)
278
-
279
-	mat4 IdentityMatrix()
280
-	{
281
-		mat4 m;
282
-		int i;
283
-
284
-		for (i = 0; i <= 15; i++)
285
-			m.m[i] = 0;
286
-		for (i = 0; i <= 3; i++)
287
-			m.m[i * 5] = 1; // 0,5,10,15
288
-		return m;
289
-	}
290
-
291
-	mat4 Rx(GLfloat a)
292
-	{
293
-		mat4 m;
294
-		m = IdentityMatrix();
295
-		m.m[5] = (GLfloat)cos(a);
296
-		if (transposed)
297
-			m.m[9] = (GLfloat)-sin(a);
298
-		else
299
-			m.m[9] = (GLfloat)sin(a);
300
-		m.m[6] = -m.m[9]; //sin(a);
301
-		m.m[10] = m.m[5]; //cos(a);
302
-		return m;
303
-	}
304
-
305
-	mat4 Ry(GLfloat a)
306
-	{
307
-		mat4 m;
308
-		m = IdentityMatrix();
309
-		m.m[0] = (GLfloat)cos(a);
310
-		if (transposed)
311
-			m.m[8] = (GLfloat)sin(a); // Was flipped
312
-		else
313
-			m.m[8] = (GLfloat)-sin(a);
314
-		m.m[2] = -m.m[8]; //sin(a);
315
-		m.m[10] = m.m[0]; //cos(a);
316
-		return m;
317
-	}
318
-
319
-	mat4 Rz(GLfloat a)
320
-	{
321
-		mat4 m;
322
-		m = IdentityMatrix();
323
-		m.m[0] = (GLfloat)cos(a);
324
-		if (transposed)
325
-			m.m[4] = (GLfloat)-sin(a);
326
-		else
327
-			m.m[4] = (GLfloat)sin(a);
328
-		m.m[1] = -m.m[4]; //sin(a);
329
-		m.m[5] = m.m[0]; //cos(a);
330
-		return m;
331
-	}
332
-
333
-	mat4 T(GLfloat tx, GLfloat ty, GLfloat tz)
334
-	{
335
-		mat4 m;
336
-		m = IdentityMatrix();
337
-		if (transposed)
338
-		{
339
-			m.m[12] = tx;
340
-			m.m[13] = ty;
341
-			m.m[14] = tz;
342
-		}
343
-		else
344
-		{
345
-			m.m[3] = tx;
346
-			m.m[7] = ty;
347
-			m.m[11] = tz;
348
-		}
349
-		return m;
350
-	}
351
-
352
-	mat4 S(GLfloat sx, GLfloat sy, GLfloat sz)
353
-	{
354
-		mat4 m;
355
-		m = IdentityMatrix();
356
-		m.m[0] = sx;
357
-		m.m[5] = sy;
358
-		m.m[10] = sz;
359
-		return m;
360
-	}
361
-
362
-	mat4 Mult(mat4 a, mat4 b) // m = a * b
363
-	{
364
-		mat4 m;
365
-
366
-		int x, y;
367
-		for (x = 0; x <= 3; x++)
368
-			for (y = 0; y <= 3; y++)
369
-				if (transposed)
370
-					m.m[x*4 + y] =	a.m[y+4*0] * b.m[0+4*x] +
371
-								a.m[y+4*1] * b.m[1+4*x] +
372
-								a.m[y+4*2] * b.m[2+4*x] +
373
-								a.m[y+4*3] * b.m[3+4*x];
374
-				else
375
-					m.m[y*4 + x] =	a.m[y*4+0] * b.m[0*4+x] +
376
-								a.m[y*4+1] * b.m[1*4+x] +
377
-								a.m[y*4+2] * b.m[2*4+x] +
378
-								a.m[y*4+3] * b.m[3*4+x];
379
-
380
-		return m;
381
-	}
382
-
383
-	// Ej testad!
384
-	mat3 MultMat3(mat3 a, mat3 b) // m = a * b
385
-	{
386
-		mat3 m;
387
-
388
-		int x, y;
389
-		for (x = 0; x <= 2; x++)
390
-			for (y = 0; y <= 2; y++)
391
-				if (transposed)
392
-					m.m[x*3 + y] =	a.m[y+3*0] * b.m[0+3*x] +
393
-								a.m[y+3*1] * b.m[1+3*x] +
394
-								a.m[y+3*2] * b.m[2+3*x];
395
-				else
396
-					m.m[y*3 + x] =	a.m[y*3+0] * b.m[0*3+x] +
397
-								a.m[y*3+1] * b.m[1*3+x] +
398
-								a.m[y*3+2] * b.m[2*3+x];
399
-
400
-		return m;
401
-	}
402
-
403
-	// mat4 * vec3
404
-	// The missing homogenous coordinate is implicitly set to 1.
405
-	vec3 MultVec3(mat4 a, vec3 b) // result = a * b
406
-	{
407
-		vec3 r;
408
-
409
-		if (!transposed)
410
-		{
411
-			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3];
412
-			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7];
413
-			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11];
414
-		}
415
-		else
416
-		{
417
-			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12];
418
-			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13];
419
-			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14];
420
-		}
421
-
422
-		return r;
423
-	}
424
-
425
-	// mat3 * vec3
426
-	vec3 MultMat3Vec3(mat3 a, vec3 b) // result = a * b
427
-	{
428
-		vec3 r;
429
-		
430
-		if (!transposed)
431
-		{
432
-			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z;
433
-			r.y = a.m[3]*b.x + a.m[4]*b.y + a.m[5]*b.z;
434
-			r.z = a.m[6]*b.x + a.m[7]*b.y + a.m[8]*b.z;
435
-		}
436
-		else
437
-		{
438
-			r.x = a.m[0]*b.x + a.m[3]*b.y + a.m[6]*b.z;
439
-			r.y = a.m[1]*b.x + a.m[4]*b.y + a.m[7]*b.z;
440
-			r.z = a.m[2]*b.x + a.m[5]*b.y + a.m[8]*b.z;
441
-		}
442
-		
443
-		return r;
444
-	}
445
-
446
-	// mat4 * vec4
447
-	vec4 MultVec4(mat4 a, vec4 b) // result = a * b
448
-	{
449
-		vec4 r;
450
-
451
-		if (!transposed)
452
-		{
453
-			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3]*b.w;
454
-			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7]*b.w;
455
-			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11]*b.w;
456
-			r.w = a.m[12]*b.x + a.m[13]*b.y + a.m[14]*b.z + a.m[15]*b.w;
457
-		}
458
-		else
459
-		{
460
-			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12]*b.w;
461
-			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13]*b.w;
462
-			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14]*b.w;
463
-			r.w = a.m[3]*b.x + a.m[7]*b.y + a.m[11]*b.z + a.m[15]*b.w;
464
-		}
465
-
466
-		return r;
467
-	}
468
-
469
-
470
-// Unnecessary
471
-// Will probably be removed
472
-//	void CopyMatrix(GLfloat *src, GLfloat *dest)
473
-//	{
474
-//		int i;
475
-//		for (i = 0; i <= 15; i++)
476
-//			dest[i] = src[i];
477
-//	}
478
-
479
-
480
-// Added for lab 3 (TSBK03)
481
-
482
-	// Orthonormalization of Matrix4D. Assumes rotation only, translation/projection ignored
483
-	void OrthoNormalizeMatrix(mat4 *R)
484
-	{
485
-		vec3 x, y, z;
486
-
487
-		if (transposed)
488
-		{
489
-			x = SetVector(R->m[0], R->m[1], R->m[2]);
490
-			y = SetVector(R->m[4], R->m[5], R->m[6]);
491
-//		SetVector(R[8], R[9], R[10], &z);
492
-			// Kryssa fram ur varandra
493
-			// Normera
494
-			z = CrossProduct(x, y);
495
-			z = Normalize(z);
496
-			x = Normalize(x);
497
-			y = CrossProduct(z, x);
498
-			R->m[0] = x.x;
499
-			R->m[1] = x.y;
500
-			R->m[2] = x.z;
501
-			R->m[4] = y.x;
502
-			R->m[5] = y.y;
503
-			R->m[6] = y.z;
504
-			R->m[8] = z.x;
505
-			R->m[9] = z.y;
506
-			R->m[10] = z.z;
507
-
508
-			R->m[3] = 0.0;
509
-			R->m[7] = 0.0;
510
-			R->m[11] = 0.0;
511
-			R->m[12] = 0.0;
512
-			R->m[13] = 0.0;
513
-			R->m[14] = 0.0;
514
-			R->m[15] = 1.0;
515
-		}
516
-		else
517
-		{
518
-		// NOT TESTED
519
-			x = SetVector(R->m[0], R->m[4], R->m[8]);
520
-			y = SetVector(R->m[1], R->m[5], R->m[9]);
521
-//		SetVector(R[2], R[6], R[10], &z);
522
-			// Kryssa fram ur varandra
523
-			// Normera
524
-			z = CrossProduct(x, y);
525
-			z = Normalize(z);
526
-			x = Normalize(x);
527
-			y = CrossProduct(z, x);
528
-			R->m[0] = x.x;
529
-			R->m[4] = x.y;
530
-			R->m[8] = x.z;
531
-			R->m[1] = y.x;
532
-			R->m[5] = y.y;
533
-			R->m[9] = y.z;
534
-			R->m[2] = z.x;
535
-			R->m[6] = z.y;
536
-			R->m[10] = z.z;
537
-
538
-			R->m[3] = 0.0;
539
-			R->m[7] = 0.0;
540
-			R->m[11] = 0.0;
541
-			R->m[12] = 0.0;
542
-			R->m[13] = 0.0;
543
-			R->m[14] = 0.0;
544
-			R->m[15] = 1.0;
545
-		}
546
-	}
547
-
548
-
549
-// Commented out since I plan to remove it if I can't see a good reason to keep it.
550
-//	// Only transposes rotation part.
551
-//	mat4 TransposeRotation(mat4 m)
552
-//	{
553
-//		mat4 a;
554
-//		
555
-//		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[12];
556
-//		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[13];
557
-//		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[14];
558
-//		a.m[3] = m.m[3]; a.m[7] = m.m[7]; a.m[11] = m.m[11];    a.m[15] = m.m[15];
559
-//		
560
-//		return a;
561
-//	}
562
-
563
-	// Complete transpose!
564
-	mat4 transpose(mat4 m)
565
-	{
566
-		mat4 a;
567
-		
568
-		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[3];
569
-		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[7];
570
-		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[11];
571
-		a.m[3] = m.m[12]; a.m[7] = m.m[13]; a.m[11] = m.m[14];    a.m[15] = m.m[15];
572
-		
573
-		return a;
574
-	}
575
-
576
-	// Complete transpose!
577
-	mat3 TransposeMat3(mat3 m)
578
-	{
579
-		mat3 a;
580
-		
581
-		a.m[0] = m.m[0]; a.m[3] = m.m[1]; a.m[6] = m.m[2];
582
-		a.m[1] = m.m[3]; a.m[4] = m.m[4]; a.m[7] = m.m[5];
583
-		a.m[2] = m.m[6]; a.m[5] = m.m[7]; a.m[8] = m.m[8];
584
-		
585
-		return a;
586
-	}
587
-
588
-// Rotation around arbitrary axis (rotation only)
589
-mat4 ArbRotate(vec3 axis, GLfloat fi)
590
-{
591
-	vec3 x, y, z;
592
-	mat4 R, Rt, Raxel, m;
593
-
594
-// Check if parallel to Z
595
-	if (axis.x < 0.0000001) // Below some small value
596
-	if (axis.x > -0.0000001)
597
-	if (axis.y < 0.0000001)
598
-	if (axis.y > -0.0000001)
599
-	{
600
-		if (axis.z > 0)
601
-		{
602
-			m = Rz(fi);
603
-			return m;
604
-		}
605
-		else
606
-		{
607
-			m = Rz(-fi);
608
-			return m;
609
-		}
610
-	}
611
-
612
-	x = Normalize(axis);
613
-	z = SetVector(0,0,1); // Temp z
614
-	y = Normalize(CrossProduct(z, x)); // y' = z^ x x'
615
-	z = CrossProduct(x, y); // z' = x x y
616
-
617
-	if (transposed)
618
-	{
619
-		R.m[0] = x.x; R.m[4] = x.y; R.m[8] = x.z;  R.m[12] = 0.0;
620
-		R.m[1] = y.x; R.m[5] = y.y; R.m[9] = y.z;  R.m[13] = 0.0;
621
-		R.m[2] = z.x; R.m[6] = z.y; R.m[10] = z.z;  R.m[14] = 0.0;
622
-
623
-		R.m[3] = 0.0; R.m[7] = 0.0; R.m[11] = 0.0;  R.m[15] = 1.0;
624
-	}
625
-	else
626
-	{
627
-		R.m[0] = x.x; R.m[1] = x.y; R.m[2] = x.z;  R.m[3] = 0.0;
628
-		R.m[4] = y.x; R.m[5] = y.y; R.m[6] = y.z;  R.m[7] = 0.0;
629
-		R.m[8] = z.x; R.m[9] = z.y; R.m[10] = z.z;  R.m[11] = 0.0;
630
-
631
-		R.m[12] = 0.0; R.m[13] = 0.0; R.m[14] = 0.0;  R.m[15] = 1.0;
632
-	}
633
-
634
-	Rt = transpose(R); // Transpose = Invert -> felet ej i Transpose, och det �r en ortonormal matris
635
-
636
-	Raxel = Rx(fi); // Rotate around x axis
637
-
638
-	// m := Rt * Rx * R
639
-	m = Mult(Mult(Rt, Raxel), R);
640
-	
641
-	return m;
642
-}
643
-
644
-
645
-// Not tested much
646
-mat4 CrossMatrix(vec3 a) // Matrix for cross product
647
-{
648
-	mat4 m;
649
-	
650
-	if (transposed)
651
-	{
652
-		m.m[0] =    0; m.m[4] =-a.z; m.m[8] = a.y; m.m[12] = 0.0;
653
-		m.m[1] = a.z; m.m[5] =    0; m.m[9] =-a.x; m.m[13] = 0.0;
654
-		m.m[2] =-a.y; m.m[6] = a.x; m.m[10]=    0; m.m[14] = 0.0;
655
-		m.m[3] =  0.0; m.m[7] =  0.0; m.m[11]=  0.0; m.m[15] = 0.0;
656
-		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
657
-		// not be generally used, but is fine for matrix differentials
658
-	}
659
-	else
660
-	{
661
-		m.m[0] =    0; m.m[1] =-a.z; m.m[2] = a.y; m.m[3] = 0.0;
662
-		m.m[4] = a.z; m.m[5] =    0; m.m[6] =-a.x; m.m[7] = 0.0;
663
-		m.m[8] =-a.y; m.m[9] = a.x; m.m[10]=    0; m.m[11] = 0.0;
664
-		m.m[12] =  0.0; m.m[13] =  0.0; m.m[14]=  0.0; m.m[15] = 0.0;
665
-		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
666
-		// not be generally used, but is fine for matrix differentials
667
-	}
668
-	
669
-	return m;
670
-}
671
-
672
-mat4 MatrixAdd(mat4 a, mat4 b)
673
-{
674
-	mat4 dest;
675
-	
676
-	int i;
677
-	for (i = 0; i < 16; i++)
678
-		dest.m[i] = a.m[i] + b.m[i];
679
-	
680
-	return dest;
681
-}
682
-
683
-
684
-void SetTransposed(char t)
685
-{
686
-	transposed = t;
687
-}
688
-
689
-
690
-// Build standard matrices
691
-
692
-mat4 lookAtv(vec3 p, vec3 l, vec3 v)
693
-{
694
-	vec3 n, u;
695
-	mat4 rot, trans;
696
-
697
-	n = Normalize(VectorSub(p, l));
698
-	u = Normalize(CrossProduct(v, n));
699
-	v = CrossProduct(n, u);
700
-
701
-//	rot = {{ u.x, u.y, u.z, 0,
702
-//                      v.x, v.y, v.z, 0,
703
-//                      n.x, n.y, n.z, 0,
704
-//                      0,   0,   0,   1 }};
705
-// VS friendly version:
706
-	if (transposed)
707
-	rot = SetMat4(u.x, v.x, n.x, 0,
708
-                  u.y, v.y, n.y, 0,
709
-                  u.z, v.z, n.z, 0,
710
-                  0,   0,   0,   1);
711
-	else
712
-	rot = SetMat4(u.x, u.y, u.z, 0,
713
-                  v.x, v.y, v.z, 0,
714
-                  n.x, n.y, n.z, 0,
715
-                  0,   0,   0,   1);
716
-	trans = T(-p.x, -p.y, -p.z);
717
-	return Mult(rot, trans);
718
-}
719
-
720
-mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz, 
721
-			GLfloat lx, GLfloat ly, GLfloat lz,
722
-			GLfloat vx, GLfloat vy, GLfloat vz)
723
-{
724
-	vec3 p, l, v;
725
-	
726
-	p = SetVector(px, py, pz);
727
-	l = SetVector(lx, ly, lz);
728
-	v = SetVector(vx, vy, vz);
729
-	
730
-	return lookAtv(p, l, v);
731
-}
732
-
733
-// From http://www.opengl.org/wiki/GluPerspective_code
734
-// Changed names and parameter order to conform with VU style
735
-// Rewritten 120913 because it was all wrong...
736
-
737
-// Creates a projection matrix like gluPerspective or glFrustum.
738
-// Upload to your shader as usual.
739
-// 2022: Yet another fix. Was it correct this time?
740
-mat4 perspective(float fovyInDegrees, float aspectRatio,
741
-                      float znear, float zfar)
742
-{
743
-	float f = 1.0/tan(fovyInDegrees * M_PI / 360.0);
744
-	mat4 m = SetMat4(f/aspectRatio, 0, 0, 0,
745
-					0, f, 0, 0,
746
-					0, 0, (zfar+znear)/(znear-zfar), 2*zfar*znear/(znear-zfar),
747
-					0, 0, -1, 0);
748
-	if (transposed)
749
-		m = transpose(m);
750
-	return m;
751
-}
752
-
753
-mat4 frustum(float left, float right, float bottom, float top,
754
-                  float znear, float zfar)
755
-{
756
-    float temp, temp2, temp3, temp4;
757
-    mat4 matrix;
758
-    
759
-    temp = 2.0f * znear;
760
-    temp2 = right - left;
761
-    temp3 = top - bottom;
762
-    temp4 = zfar - znear;
763
-    matrix.m[0] = temp / temp2; // 2*near/(right-left)
764
-    matrix.m[1] = 0.0;
765
-    matrix.m[2] = 0.0;
766
-    matrix.m[3] = 0.0;
767
-    matrix.m[4] = 0.0;
768
-    matrix.m[5] = temp / temp3; // 2*near/(top - bottom)
769
-    matrix.m[6] = 0.0;
770
-    matrix.m[7] = 0.0;
771
-    matrix.m[8] = (right + left) / temp2; // A = r+l / r-l
772
-    matrix.m[9] = (top + bottom) / temp3; // B = t+b / t-b
773
-    matrix.m[10] = (-zfar - znear) / temp4; // C = -(f+n) / f-n
774
-    matrix.m[11] = -1.0;
775
-    matrix.m[12] = 0.0;
776
-    matrix.m[13] = 0.0;
777
-    matrix.m[14] = (-temp * zfar) / temp4; // D = -2fn / f-n
778
-    matrix.m[15] = 0.0;
779
-    
780
-    if (!transposed)
781
-    	matrix = transpose(matrix);
782
-    
783
-    return matrix;
784
-}
785
-
786
-// Not tested!
787
-mat4 ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
788
-{
789
-        float a = 2.0f / (right - left);
790
-        float b = 2.0f / (top - bottom);
791
-        float c = -2.0f / (far - near);
792
-
793
-        float tx = - (right + left)/(right - left);
794
-        float ty = - (top + bottom)/(top - bottom);
795
-        float tz = - (far + near)/(far - near);
796
-
797
-        mat4 o = SetMat4(
798
-            a, 0, 0, tx,
799
-            0, b, 0, ty,
800
-            0, 0, c, tz,
801
-            0, 0, 0, 1);
802
-        return o;
803
-}
804
-
805
-// The code below is based on code from:
806
-// http://www.dr-lex.be/random/matrix_inv.html
807
-
808
-// Inverts mat3 (row-wise matrix)
809
-// (For a more general inverse, try a gaussian elimination.)
810
-mat3 InvertMat3(mat3 in)
811
-{
812
-	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
813
-	mat3 out, nanout;
814
-	float DET;
815
-	
816
-	// Copying to internal variables both clarify the code and
817
-	// buffers data so the output may be identical to the input!
818
-	a11 = in.m[0];
819
-	a12 = in.m[1];
820
-	a13 = in.m[2];
821
-	a21 = in.m[3];
822
-	a22 = in.m[4];
823
-	a23 = in.m[5];
824
-	a31 = in.m[6];
825
-	a32 = in.m[7];
826
-	a33 = in.m[8];
827
-	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
828
-	if (DET != 0)
829
-	{
830
-		out.m[0] = (a33*a22-a32*a23)/DET;
831
-		out.m[1] = -(a33*a12-a32*a13)/DET;
832
-		out.m[2] = (a23*a12-a22*a13)/DET;
833
-		out.m[3] = -(a33*a21-a31*a23)/DET;
834
-		out.m[4] = (a33*a11-a31*a13)/DET;
835
-		out.m[5] = -(a23*a11-a21*a13)/DET;
836
-		out.m[6] = (a32*a21-a31*a22)/DET;
837
-		out.m[7] = -(a32*a11-a31*a12)/DET;
838
-		out.m[8] = (a22*a11-a21*a12)/DET;
839
-	}
840
-	else
841
-	{
842
-		nanout = SetMat3(NAN, NAN, NAN,
843
-								NAN, NAN, NAN,
844
-								NAN, NAN, NAN);
845
-		out = nanout;
846
-	}
847
-	
848
-	return out;
849
-}
850
-
851
-// For making a normal matrix from a model-to-view matrix
852
-// Takes a mat4 in, ignores 4th row/column (should just be translations),
853
-// inverts as mat3 (row-wise matrix) and returns the transpose
854
-mat3 InverseTranspose(mat4 in)
855
-{
856
-	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
857
-	mat3 out, nanout;
858
-	float DET;
859
-	
860
-	// Copying to internal variables
861
-	a11 = in.m[0];
862
-	a12 = in.m[1];
863
-	a13 = in.m[2];
864
-	a21 = in.m[4];
865
-	a22 = in.m[5];
866
-	a23 = in.m[6];
867
-	a31 = in.m[8];
868
-	a32 = in.m[9];
869
-	a33 = in.m[10];
870
-	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
871
-	if (DET != 0)
872
-	{
873
-		out.m[0] = (a33*a22-a32*a23)/DET;
874
-		out.m[3] = -(a33*a12-a32*a13)/DET;
875
-		out.m[6] = (a23*a12-a22*a13)/DET;
876
-		out.m[1] = -(a33*a21-a31*a23)/DET;
877
-		out.m[4] = (a33*a11-a31*a13)/DET;
878
-		out.m[7] = -(a23*a11-a21*a13)/DET;
879
-		out.m[2] = (a32*a21-a31*a22)/DET;
880
-		out.m[5] = -(a32*a11-a31*a12)/DET;
881
-		out.m[8] = (a22*a11-a21*a12)/DET;
882
-	}
883
-	else
884
-	{
885
-		nanout = SetMat3(NAN, NAN, NAN,
886
-								NAN, NAN, NAN,
887
-								NAN, NAN, NAN);
888
-		out = nanout;
889
-	}
890
-
891
-	return out;
892
-}
893
-
894
-
895
-// Simple conversions
896
-mat3 mat4tomat3(mat4 m)
897
-{
898
-	mat3 result;
899
-	
900
-	result.m[0] = m.m[0];
901
-	result.m[1] = m.m[1];
902
-	result.m[2] = m.m[2];
903
-	result.m[3] = m.m[4];
904
-	result.m[4] = m.m[5];
905
-	result.m[5] = m.m[6];
906
-	result.m[6] = m.m[8];
907
-	result.m[7] = m.m[9];
908
-	result.m[8] = m.m[10];
909
-	return result;
910
-}
911
-
912
-mat4 mat3tomat4(mat3 m)
913
-{
914
-	mat4 result;
915
-	
916
-	result.m[0] = m.m[0];
917
-	result.m[1] = m.m[1];
918
-	result.m[2] = m.m[2];
919
-	result.m[3] = 0;
920
-	result.m[4] = m.m[3];
921
-	result.m[5] = m.m[4];
922
-	result.m[6] = m.m[5];
923
-	result.m[7] = 0;
924
-	result.m[8] = m.m[6];
925
-	result.m[9] = m.m[7];
926
-	result.m[10] = m.m[8];
927
-	result.m[11] = 0;
928
-
929
-	result.m[12] = 0;
930
-	result.m[13] = 0;
931
-	result.m[14] = 0;
932
-	result.m[15] = 1;
933
-	return result;
934
-}
935
-
936
-vec3 vec4tovec3(vec4 v)
937
-{
938
-	vec3 result;
939
-	result.x = v.x;
940
-	result.y = v.y;
941
-	result.z = v.z;
942
-	return result;
943
-}
944
-
945
-vec4 vec3tovec4(vec3 v)
946
-{
947
-	vec4 result;
948
-	result.x = v.x;
949
-	result.y = v.y;
950
-	result.z = v.z;
951
-	result.w = 1;
952
-	return result;
953
-}
954
-
955
-
956
-// Stol... I mean adapted from glMatrix (WebGL math unit). Almost no
957
-// changes despite changing language! But I just might replace it with
958
-// a gaussian elimination some time.
959
-mat4 InvertMat4(mat4 a)
960
-{
961
-   mat4 b;
962
-     
963
-   float c=a.m[0],d=a.m[1],e=a.m[2],g=a.m[3],
964
-	f=a.m[4],h=a.m[5],i=a.m[6],j=a.m[7],
965
-	k=a.m[8],l=a.m[9],o=a.m[10],m=a.m[11],
966
-	n=a.m[12],p=a.m[13],r=a.m[14],s=a.m[15],
967
-	A=c*h-d*f,
968
-	B=c*i-e*f,
969
-	t=c*j-g*f,
970
-	u=d*i-e*h,
971
-	v=d*j-g*h,
972
-	w=e*j-g*i,
973
-	x=k*p-l*n,
974
-	y=k*r-o*n,
975
-	z=k*s-m*n,
976
-	C=l*r-o*p,
977
-	D=l*s-m*p,
978
-	E=o*s-m*r,
979
-	q=1/(A*E-B*D+t*C+u*z-v*y+w*x);
980
-	b.m[0]=(h*E-i*D+j*C)*q;
981
-	b.m[1]=(-d*E+e*D-g*C)*q;
982
-	b.m[2]=(p*w-r*v+s*u)*q;
983
-	b.m[3]=(-l*w+o*v-m*u)*q;
984
-	b.m[4]=(-f*E+i*z-j*y)*q;
985
-	b.m[5]=(c*E-e*z+g*y)*q;
986
-	b.m[6]=(-n*w+r*t-s*B)*q;
987
-	b.m[7]=(k*w-o*t+m*B)*q;
988
-	b.m[8]=(f*D-h*z+j*x)*q;
989
-	b.m[9]=(-c*D+d*z-g*x)*q;
990
-	b.m[10]=(n*v-p*t+s*A)*q;
991
-	b.m[11]=(-k*v+l*t-m*A)*q;
992
-	b.m[12]=(-f*C+h*y-i*x)*q;
993
-	b.m[13]=(c*C-d*y+e*x)*q;
994
-	b.m[14]=(-n*u+p*B-r*A)*q;
995
-	b.m[15]=(k*u-l*B+o*A)*q;
996
-	return b;
997
-};
998
-
999
-
1000
-// Two convenient printing functions suggested by Christian Luckey 2015.
1001
-// Added printMat3 2019.
1002
-void printMat4(mat4 m)
1003
-{
1004
-	unsigned int i;
1005
-	printf(" ---------------------------------------------------------------\n");
1006
-	for (i = 0; i < 4; i++)
1007
-	{
1008
-		int n = i * 4;
1009
-		printf("| %11.5f\t| %11.5f\t| %11.5f\t| %11.5f\t|\n",
1010
-			m.m[n], m.m[n+1], m.m[n+2], m.m[n+3]);
1011
-	}
1012
-	printf(" ---------------------------------------------------------------\n");
1013
-}
1014
-
1015
-void printMat3(mat3 m)
1016
-{
1017
-	unsigned int i;
1018
-	printf(" ---------------------------------------------------------------\n");
1019
-	for (i = 0; i < 3; i++)
1020
-	{
1021
-		int n = i * 3;
1022
-		printf("| %11.5f\t| %11.5f\t| %11.5f\t| \n",
1023
-			m.m[n], m.m[n+1], m.m[n+2]);
1024
-	}
1025
-	printf(" ---------------------------------------------------------------\n");
1026
-}
1027
-
1028
-void printVec3(vec3 in) 
1029
-{
1030
-	printf("(%f, %f, %f)\n", in.x, in.y, in.z);
1031
-}
1032
-
1033
-
1034
-
1035
-/* Utility functions for easier uploads to shaders with error messages. */
1036
-// NEW as prototype 2022, added to VU 2023
1037
-
1038
-#define NUM_ERRORS 8
1039
-
1040
-static void ReportError(const char *caller, const char *name)
1041
-{
1042
-	static unsigned int draw_error_counter = 0; 
1043
-	if(draw_error_counter < NUM_ERRORS)
1044
-	{
1045
-		fprintf(stderr, "%s warning: '%s' not found in shader!\n", caller, name);
1046
-		draw_error_counter++;
1047
-	}
1048
-	else if(draw_error_counter == NUM_ERRORS)
1049
-	{
1050
-		fprintf(stderr, "%s: Number of errors bigger than %i. No more vill be printed.\n", caller, NUM_ERRORS);
1051
-		draw_error_counter++;
1052
-	}
1053
-}
1054
-
1055
-void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m)
1056
-{
1057
-	if (nameInShader == NULL) return;
1058
-	glUseProgram(shader);
1059
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1060
-	if (loc >= 0)
1061
-		glUniformMatrix4fv(loc, 1, GL_TRUE, m.m);
1062
-	else
1063
-		ReportError("uploadMat4ToShader", nameInShader);
1064
-}
1065
-
1066
-void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i)
1067
-{
1068
-	if (nameInShader == NULL) return;
1069
-	glUseProgram(shader);
1070
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1071
-	if (loc >= 0)
1072
-		glUniform1i(loc, i);
1073
-	else
1074
-		ReportError("uploadUniformIntToShader", nameInShader);
1075
-}
1076
-
1077
-void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f)
1078
-{
1079
-	if (nameInShader == NULL) return;
1080
-	glUseProgram(shader);
1081
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1082
-	if (loc >= 0)
1083
-		glUniform1f(loc, f);
1084
-	else
1085
-		ReportError("uploadUniformFloatToShader", nameInShader);
1086
-}
1087
-
1088
-void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength)
1089
-{
1090
-	if (nameInShader == NULL) return;
1091
-	glUseProgram(shader);
1092
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1093
-	if (loc >= 0)
1094
-		glUniform1fv(loc, arrayLength, f);
1095
-	else
1096
-		ReportError("uploadUniformFloatToShader", nameInShader);
1097
-}
1098
-
1099
-void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v)
1100
-{
1101
-	if (nameInShader == NULL) return;
1102
-	glUseProgram(shader);
1103
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1104
-	if (loc >= 0)
1105
-		glUniform3f(loc, v.x, v.y, v.z);
1106
-	else
1107
-		ReportError("uploadUniformVec3ToShader", nameInShader);
1108
-}
1109
-
1110
-void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength)
1111
-{
1112
-	if (nameInShader == NULL) return;
1113
-	glUseProgram(shader);
1114
-	GLint loc = glGetUniformLocation(shader, nameInShader);
1115
-	if (loc >= 0)
1116
-		glUniform3fv(loc, arrayLength, (GLfloat *)a);
1117
-	else
1118
-		ReportError("uploadUniformVec3ArrayToShader", nameInShader);
1119
-}
1120
-
1121
-void bindTextureToTextureUnit(GLuint tex, int unit)
1122
-{
1123
-	glActiveTexture(GL_TEXTURE0 + unit);
1124
-	glBindTexture(GL_TEXTURE_2D, tex);
1125
-}
Browse code

Add cpp-v1

Ingemar Ragnemalm authored on 21/02/2024 20:24:28 • Robert Cranston committed on 21/02/2024 20:24:28
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,1125 @@
1
+// VectorUtils
2
+// Vector and matrix manipulation library for OpenGL, a package of the most essential functions.
3
+// Includes:
4
+// - Basic vector operations: Add, subtract, scale, dot product, cross product.
5
+// - Basic matrix operations: Multiply matrix to matrix, matric to vector, transpose.
6
+// - Creation of transformation matrixces: Translation, scaling, rotation.
7
+// - A few more special operations: Orthonormalizaton of a matrix, CrossMatrix,
8
+// - Replacements of some GLU functions: lookAt, frustum, perspective.
9
+// - Inverse and inverse transpose for creating normal matrices.
10
+// Supports both C and C++. The C interface makes it accessible from most languages if desired.
11
+
12
+// A note on completeness:
13
+// All operations may not be 100% symmetrical over all types, and some GLSL types are
14
+// missing (like vec2). These will be added if proven important. There is already
15
+// some calls of minor importance (mat3 * mat3, mat3 * vec3) included only for
16
+// symmetry. I don't want the code to grow a lot for such reasons, I want it to be
17
+// compact and to the point.
18
+
19
+// Current open design questions:
20
+// Naming conventions: Lower case or capitalized? (Frustum/frustum)
21
+// Prefix for function calls? (The cost would be more typing and making the code harder to read.)
22
+// Add vector operations for vec4? Other *essential* symmetry issues?
23
+// Names for functions when supporting both vec3 and vec4, mat3 and mat4? (vec3Add, vec4Add?)
24
+
25
+
26
+// History:
27
+
28
+// VectorUtils is a small (but growing) math unit by Ingemar Ragnemalm.
29
+// It originated as "geom3d" by Andrew Meggs, but that unit is no more
30
+// than inspiration today. The original VectorUtils(1) was based on it,
31
+// while VectorUtils2 was a rewrite primarily to get rid of the over-use
32
+// of arrays in the original.
33
+
34
+// New version 120201:
35
+// Defaults to matrices "by the book". Can also be configured to the flipped
36
+// column-wise matrices that old OpenGL required (and we all hated).
37
+// This is freshly implemented, limited testing, so there can be bugs.
38
+// But it seems to work just fine on my tests with translation, rotations
39
+// and matrix multiplications.
40
+
41
+// 1208??: Added lookAt, perspective, frustum
42
+// Also made Transpose do what it should. TransposeRotation is the old function.
43
+// 120913: Fixed perspective. Never trust other's code...
44
+// 120925: Transposing in CrossMatrix
45
+// 121119: Fixed one more glitch in perspective.
46
+
47
+// 130227 First draft to a version 3.
48
+// C++ operators if accessed from C++
49
+// Vectors by value when possible. Return values on the stack.
50
+// (Why was this not the case in VectorUtils2? Beause I tried to stay compatible
51
+// with an old C compiler. Older C code generally prefers all non-scalar data by
52
+// reference. But I'd like to move away from that now.)
53
+// Types conform with GLSL as much as possible (vec3, mat4)
54
+// Added some operations for mat3 and vec4, but most of them are more for
55
+// completeness than usefulness; I find vec3's and mat4's to be what I use
56
+// most of the time.
57
+// Also added InvertMat3 and InversTranspose to support creation of normal matrices.
58
+// Marked some calls for removal: CopyVector, TransposeRotation, CopyMatrix.
59
+// 130308: Added InvertMat4 and some more vec3/vec4 operators (+= etc)
60
+// 130922: Fixed a vital bug in CrossMatrix.
61
+// 130924: Fixed a bug in mat3tomat4.
62
+// 131014: Added TransposeMat3 (although I doubt its importance)
63
+// 140213: Corrected mat3tomat4. (Were did the correction in 130924 go?)
64
+// 151210: Added printMat4 and printVec3.
65
+// 160302: Added empty constructors for vec3 and vec4.
66
+// 170221: Uses _WIN32 instead of WIN32
67
+// 170331: Added stdio.h for printMat4 and printVec3
68
+// 180314: Added some #defines for moving closer to GLSL (dot, cross...).
69
+// 2021-05-15: Constructiors for vec3 etc replaced in order to avoid
70
+// problems with some C++ compilers.
71
+// 2022-05-14: Corrected transposed version of lookAtv.
72
+// 2023-01-31: Added shader upload utility functions.
73
+
74
+// You may use VectorUtils as you please. A reference to the origin is appreciated
75
+// but if you grab some snippets from it without reference... no problem.
76
+
77
+
78
+#include "VectorUtils3.h"
79
+
80
+// VS doesn't define NAN properly
81
+#ifdef _WIN32
82
+    #ifndef NAN
83
+        static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
84
+        #define NAN (*(const float *) __nan)
85
+    #endif
86
+#endif
87
+
88
+char transposed = 0;
89
+
90
+	vec3 SetVector(GLfloat x, GLfloat y, GLfloat z)
91
+	{
92
+		vec3 v;
93
+		
94
+		v.x = x;
95
+		v.y = y;
96
+		v.z = z;
97
+		return v;
98
+	}
99
+
100
+// New better name
101
+	vec2 SetVec2(GLfloat x, GLfloat y)
102
+	{
103
+		vec2 v;
104
+		
105
+		v.x = x;
106
+		v.y = y;
107
+		return v;
108
+	}
109
+
110
+	vec3 SetVec3(GLfloat x, GLfloat y, GLfloat z)
111
+	{
112
+		vec3 v;
113
+		
114
+		v.x = x;
115
+		v.y = y;
116
+		v.z = z;
117
+		return v;
118
+	}
119
+
120
+	vec4 SetVec4(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
121
+	{
122
+		vec4 v;
123
+		
124
+		v.x = x;
125
+		v.y = y;
126
+		v.z = z;
127
+		v.w = w;
128
+		return v;
129
+	}
130
+
131
+// Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
132
+	mat3 SetMat3(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7, GLfloat p8)
133
+	{
134
+		mat3 m;
135
+		m.m[0] = p0;
136
+		m.m[1] = p1;
137
+		m.m[2] = p2;
138
+		m.m[3] = p3;
139
+		m.m[4] = p4;
140
+		m.m[5] = p5;
141
+		m.m[6] = p6;
142
+		m.m[7] = p7;
143
+		m.m[8] = p8;
144
+		return m;
145
+	}
146
+
147
+// Like above; Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
148
+	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
149
+				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
150
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11, 
151
+				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
152
+				)
153
+	{
154
+		mat4 m;
155
+		m.m[0] = p0;
156
+		m.m[1] = p1;
157
+		m.m[2] = p2;
158
+		m.m[3] = p3;
159
+		m.m[4] = p4;
160
+		m.m[5] = p5;
161
+		m.m[6] = p6;
162
+		m.m[7] = p7;
163
+		m.m[8] = p8;
164
+		m.m[9] = p9;
165
+		m.m[10] = p10;
166
+		m.m[11] = p11;
167
+		m.m[12] = p12;
168
+		m.m[13] = p13;
169
+		m.m[14] = p14;
170
+		m.m[15] = p15;
171
+		return m;
172
+	}
173
+
174
+
175
+	// vec3 operations
176
+	// vec4 operations can easily be added but I havn't seen much need for them.
177
+	// Some are defined as C++ operators though.
178
+
179
+	vec3 VectorSub(vec3 a, vec3 b)
180
+	{
181
+		vec3 result;
182
+		
183
+		result.x = a.x - b.x;
184
+		result.y = a.y - b.y;
185
+		result.z = a.z - b.z;
186
+		return result;
187
+	}
188
+	
189
+	vec3 VectorAdd(vec3 a, vec3 b)
190
+	{
191
+		vec3 result;
192
+		
193
+		result.x = a.x + b.x;
194
+		result.y = a.y + b.y;
195
+		result.z = a.z + b.z;
196
+		return result;
197
+	}
198
+
199
+	vec3 CrossProduct(vec3 a, vec3 b)
200
+	{
201
+		vec3 result;
202
+
203
+		result.x = a.y*b.z - a.z*b.y;
204
+		result.y = a.z*b.x - a.x*b.z;
205
+		result.z = a.x*b.y - a.y*b.x;
206
+		
207
+		return result;
208
+	}
209
+
210
+	GLfloat DotProduct(vec3 a, vec3 b)
211
+	{
212
+		return a.x * b.x + a.y * b.y + a.z * b.z;
213
+	}
214
+
215
+	vec3 ScalarMult(vec3 a, GLfloat s)
216
+	{
217
+		vec3 result;
218
+		
219
+		result.x = a.x * s;
220
+		result.y = a.y * s;
221
+		result.z = a.z * s;
222
+		
223
+		return result;
224
+	}
225
+
226
+	GLfloat Norm(vec3 a)
227
+	{
228
+		GLfloat result;
229
+
230
+		result = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
231
+		return result;
232
+	}
233
+
234
+	vec3 Normalize(vec3 a)
235
+	{
236
+		GLfloat norm;
237
+		vec3 result;
238
+
239
+		norm = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
240
+		result.x = a.x / norm;
241
+		result.y = a.y / norm;
242
+		result.z = a.z / norm;
243
+		return result;
244
+	}
245
+
246
+	vec3 CalcNormalVector(vec3 a, vec3 b, vec3 c)
247
+	{
248
+		vec3 n;
249
+
250
+		n = CrossProduct(VectorSub(a, b), VectorSub(a, c));
251
+		n = ScalarMult(n, 1/Norm(n));
252
+		
253
+		return n;
254
+	}
255
+
256
+// Splits v into vn (parallell to n) and vp (perpendicular). Does not demand n to be normalized.
257
+	void SplitVector(vec3 v, vec3 n, vec3 *vn, vec3 *vp)
258
+	{
259
+		GLfloat nlen;
260
+		GLfloat nlen2;
261
+
262
+		nlen = DotProduct(v, n);
263
+		nlen2 = n.x*n.x+n.y*n.y+n.z*n.z; // Squared length
264
+		if (nlen2 == 0)
265
+		{
266
+			*vp = v;
267
+			*vn = SetVector(0, 0, 0);
268
+		}
269
+		else
270
+		{
271
+			*vn = ScalarMult(n, nlen/nlen2);
272
+			*vp = VectorSub(v, *vn);
273
+		}
274
+	}
275
+
276
+// Matrix operations primarily on 4x4 matrixes!
277
+// Row-wise by default but can be configured to column-wise (see SetTransposed)
278
+
279
+	mat4 IdentityMatrix()
280
+	{
281
+		mat4 m;
282
+		int i;
283
+
284
+		for (i = 0; i <= 15; i++)
285
+			m.m[i] = 0;
286
+		for (i = 0; i <= 3; i++)
287
+			m.m[i * 5] = 1; // 0,5,10,15
288
+		return m;
289
+	}
290
+
291
+	mat4 Rx(GLfloat a)
292
+	{
293
+		mat4 m;
294
+		m = IdentityMatrix();
295
+		m.m[5] = (GLfloat)cos(a);
296
+		if (transposed)
297
+			m.m[9] = (GLfloat)-sin(a);
298
+		else
299
+			m.m[9] = (GLfloat)sin(a);
300
+		m.m[6] = -m.m[9]; //sin(a);
301
+		m.m[10] = m.m[5]; //cos(a);
302
+		return m;
303
+	}
304
+
305
+	mat4 Ry(GLfloat a)
306
+	{
307
+		mat4 m;
308
+		m = IdentityMatrix();
309
+		m.m[0] = (GLfloat)cos(a);
310
+		if (transposed)
311
+			m.m[8] = (GLfloat)sin(a); // Was flipped
312
+		else
313
+			m.m[8] = (GLfloat)-sin(a);
314
+		m.m[2] = -m.m[8]; //sin(a);
315
+		m.m[10] = m.m[0]; //cos(a);
316
+		return m;
317
+	}
318
+
319
+	mat4 Rz(GLfloat a)
320
+	{
321
+		mat4 m;
322
+		m = IdentityMatrix();
323
+		m.m[0] = (GLfloat)cos(a);
324
+		if (transposed)
325
+			m.m[4] = (GLfloat)-sin(a);
326
+		else
327
+			m.m[4] = (GLfloat)sin(a);
328
+		m.m[1] = -m.m[4]; //sin(a);
329
+		m.m[5] = m.m[0]; //cos(a);
330
+		return m;
331
+	}
332
+
333
+	mat4 T(GLfloat tx, GLfloat ty, GLfloat tz)
334
+	{
335
+		mat4 m;
336
+		m = IdentityMatrix();
337
+		if (transposed)
338
+		{
339
+			m.m[12] = tx;
340
+			m.m[13] = ty;
341
+			m.m[14] = tz;
342
+		}
343
+		else
344
+		{
345
+			m.m[3] = tx;
346
+			m.m[7] = ty;
347
+			m.m[11] = tz;
348
+		}
349
+		return m;
350
+	}
351
+
352
+	mat4 S(GLfloat sx, GLfloat sy, GLfloat sz)
353
+	{
354
+		mat4 m;
355
+		m = IdentityMatrix();
356
+		m.m[0] = sx;
357
+		m.m[5] = sy;
358
+		m.m[10] = sz;
359
+		return m;
360
+	}
361
+
362
+	mat4 Mult(mat4 a, mat4 b) // m = a * b
363
+	{
364
+		mat4 m;
365
+
366
+		int x, y;
367
+		for (x = 0; x <= 3; x++)
368
+			for (y = 0; y <= 3; y++)
369
+				if (transposed)
370
+					m.m[x*4 + y] =	a.m[y+4*0] * b.m[0+4*x] +
371
+								a.m[y+4*1] * b.m[1+4*x] +
372
+								a.m[y+4*2] * b.m[2+4*x] +
373
+								a.m[y+4*3] * b.m[3+4*x];
374
+				else
375
+					m.m[y*4 + x] =	a.m[y*4+0] * b.m[0*4+x] +
376
+								a.m[y*4+1] * b.m[1*4+x] +
377
+								a.m[y*4+2] * b.m[2*4+x] +
378
+								a.m[y*4+3] * b.m[3*4+x];
379
+
380
+		return m;
381
+	}
382
+
383
+	// Ej testad!
384
+	mat3 MultMat3(mat3 a, mat3 b) // m = a * b
385
+	{
386
+		mat3 m;
387
+
388
+		int x, y;
389
+		for (x = 0; x <= 2; x++)
390
+			for (y = 0; y <= 2; y++)
391
+				if (transposed)
392
+					m.m[x*3 + y] =	a.m[y+3*0] * b.m[0+3*x] +
393
+								a.m[y+3*1] * b.m[1+3*x] +
394
+								a.m[y+3*2] * b.m[2+3*x];
395
+				else
396
+					m.m[y*3 + x] =	a.m[y*3+0] * b.m[0*3+x] +
397
+								a.m[y*3+1] * b.m[1*3+x] +
398
+								a.m[y*3+2] * b.m[2*3+x];
399
+
400
+		return m;
401
+	}
402
+
403
+	// mat4 * vec3
404
+	// The missing homogenous coordinate is implicitly set to 1.
405
+	vec3 MultVec3(mat4 a, vec3 b) // result = a * b
406
+	{
407
+		vec3 r;
408
+
409
+		if (!transposed)
410
+		{
411
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3];
412
+			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7];
413
+			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11];
414
+		}
415
+		else
416
+		{
417
+			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12];
418
+			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13];
419
+			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14];
420
+		}
421
+
422
+		return r;
423
+	}
424
+
425
+	// mat3 * vec3
426
+	vec3 MultMat3Vec3(mat3 a, vec3 b) // result = a * b
427
+	{
428
+		vec3 r;
429
+		
430
+		if (!transposed)
431
+		{
432
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z;
433
+			r.y = a.m[3]*b.x + a.m[4]*b.y + a.m[5]*b.z;
434
+			r.z = a.m[6]*b.x + a.m[7]*b.y + a.m[8]*b.z;
435
+		}
436
+		else
437
+		{
438
+			r.x = a.m[0]*b.x + a.m[3]*b.y + a.m[6]*b.z;
439
+			r.y = a.m[1]*b.x + a.m[4]*b.y + a.m[7]*b.z;
440
+			r.z = a.m[2]*b.x + a.m[5]*b.y + a.m[8]*b.z;
441
+		}
442
+		
443
+		return r;
444
+	}
445
+
446
+	// mat4 * vec4
447
+	vec4 MultVec4(mat4 a, vec4 b) // result = a * b
448
+	{
449
+		vec4 r;
450
+
451
+		if (!transposed)
452
+		{
453
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3]*b.w;
454
+			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7]*b.w;
455
+			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11]*b.w;
456
+			r.w = a.m[12]*b.x + a.m[13]*b.y + a.m[14]*b.z + a.m[15]*b.w;
457
+		}
458
+		else
459
+		{
460
+			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12]*b.w;
461
+			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13]*b.w;
462
+			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14]*b.w;
463
+			r.w = a.m[3]*b.x + a.m[7]*b.y + a.m[11]*b.z + a.m[15]*b.w;
464
+		}
465
+
466
+		return r;
467
+	}
468
+
469
+
470
+// Unnecessary
471
+// Will probably be removed
472
+//	void CopyMatrix(GLfloat *src, GLfloat *dest)
473
+//	{
474
+//		int i;
475
+//		for (i = 0; i <= 15; i++)
476
+//			dest[i] = src[i];
477
+//	}
478
+
479
+
480
+// Added for lab 3 (TSBK03)
481
+
482
+	// Orthonormalization of Matrix4D. Assumes rotation only, translation/projection ignored
483
+	void OrthoNormalizeMatrix(mat4 *R)
484
+	{
485
+		vec3 x, y, z;
486
+
487
+		if (transposed)
488
+		{
489
+			x = SetVector(R->m[0], R->m[1], R->m[2]);
490
+			y = SetVector(R->m[4], R->m[5], R->m[6]);
491
+//		SetVector(R[8], R[9], R[10], &z);
492
+			// Kryssa fram ur varandra
493
+			// Normera
494
+			z = CrossProduct(x, y);
495
+			z = Normalize(z);
496
+			x = Normalize(x);
497
+			y = CrossProduct(z, x);
498
+			R->m[0] = x.x;
499
+			R->m[1] = x.y;
500
+			R->m[2] = x.z;
501
+			R->m[4] = y.x;
502
+			R->m[5] = y.y;
503
+			R->m[6] = y.z;
504
+			R->m[8] = z.x;
505
+			R->m[9] = z.y;
506
+			R->m[10] = z.z;
507
+
508
+			R->m[3] = 0.0;
509
+			R->m[7] = 0.0;
510
+			R->m[11] = 0.0;
511
+			R->m[12] = 0.0;
512
+			R->m[13] = 0.0;
513
+			R->m[14] = 0.0;
514
+			R->m[15] = 1.0;
515
+		}
516
+		else
517
+		{
518
+		// NOT TESTED
519
+			x = SetVector(R->m[0], R->m[4], R->m[8]);
520
+			y = SetVector(R->m[1], R->m[5], R->m[9]);
521
+//		SetVector(R[2], R[6], R[10], &z);
522
+			// Kryssa fram ur varandra
523
+			// Normera
524
+			z = CrossProduct(x, y);
525
+			z = Normalize(z);
526
+			x = Normalize(x);
527
+			y = CrossProduct(z, x);
528
+			R->m[0] = x.x;
529
+			R->m[4] = x.y;
530
+			R->m[8] = x.z;
531
+			R->m[1] = y.x;
532
+			R->m[5] = y.y;
533
+			R->m[9] = y.z;
534
+			R->m[2] = z.x;
535
+			R->m[6] = z.y;
536
+			R->m[10] = z.z;
537
+
538
+			R->m[3] = 0.0;
539
+			R->m[7] = 0.0;
540
+			R->m[11] = 0.0;
541
+			R->m[12] = 0.0;
542
+			R->m[13] = 0.0;
543
+			R->m[14] = 0.0;
544
+			R->m[15] = 1.0;
545
+		}
546
+	}
547
+
548
+
549
+// Commented out since I plan to remove it if I can't see a good reason to keep it.
550
+//	// Only transposes rotation part.
551
+//	mat4 TransposeRotation(mat4 m)
552
+//	{
553
+//		mat4 a;
554
+//		
555
+//		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[12];
556
+//		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[13];
557
+//		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[14];
558
+//		a.m[3] = m.m[3]; a.m[7] = m.m[7]; a.m[11] = m.m[11];    a.m[15] = m.m[15];
559
+//		
560
+//		return a;
561
+//	}
562
+
563
+	// Complete transpose!
564
+	mat4 transpose(mat4 m)
565
+	{
566
+		mat4 a;
567
+		
568
+		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[3];
569
+		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[7];
570
+		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[11];
571
+		a.m[3] = m.m[12]; a.m[7] = m.m[13]; a.m[11] = m.m[14];    a.m[15] = m.m[15];
572
+		
573
+		return a;
574
+	}
575
+
576
+	// Complete transpose!
577
+	mat3 TransposeMat3(mat3 m)
578
+	{
579
+		mat3 a;
580
+		
581
+		a.m[0] = m.m[0]; a.m[3] = m.m[1]; a.m[6] = m.m[2];
582
+		a.m[1] = m.m[3]; a.m[4] = m.m[4]; a.m[7] = m.m[5];
583
+		a.m[2] = m.m[6]; a.m[5] = m.m[7]; a.m[8] = m.m[8];
584
+		
585
+		return a;
586
+	}
587
+
588
+// Rotation around arbitrary axis (rotation only)
589
+mat4 ArbRotate(vec3 axis, GLfloat fi)
590
+{
591
+	vec3 x, y, z;
592
+	mat4 R, Rt, Raxel, m;
593
+
594
+// Check if parallel to Z
595
+	if (axis.x < 0.0000001) // Below some small value
596
+	if (axis.x > -0.0000001)
597
+	if (axis.y < 0.0000001)
598
+	if (axis.y > -0.0000001)
599
+	{
600
+		if (axis.z > 0)
601
+		{
602
+			m = Rz(fi);
603
+			return m;
604
+		}
605
+		else
606
+		{
607
+			m = Rz(-fi);
608
+			return m;
609
+		}
610
+	}
611
+
612
+	x = Normalize(axis);
613
+	z = SetVector(0,0,1); // Temp z
614
+	y = Normalize(CrossProduct(z, x)); // y' = z^ x x'
615
+	z = CrossProduct(x, y); // z' = x x y
616
+
617
+	if (transposed)
618
+	{
619
+		R.m[0] = x.x; R.m[4] = x.y; R.m[8] = x.z;  R.m[12] = 0.0;
620
+		R.m[1] = y.x; R.m[5] = y.y; R.m[9] = y.z;  R.m[13] = 0.0;
621
+		R.m[2] = z.x; R.m[6] = z.y; R.m[10] = z.z;  R.m[14] = 0.0;
622
+
623
+		R.m[3] = 0.0; R.m[7] = 0.0; R.m[11] = 0.0;  R.m[15] = 1.0;
624
+	}
625
+	else
626
+	{
627
+		R.m[0] = x.x; R.m[1] = x.y; R.m[2] = x.z;  R.m[3] = 0.0;
628
+		R.m[4] = y.x; R.m[5] = y.y; R.m[6] = y.z;  R.m[7] = 0.0;
629
+		R.m[8] = z.x; R.m[9] = z.y; R.m[10] = z.z;  R.m[11] = 0.0;
630
+
631
+		R.m[12] = 0.0; R.m[13] = 0.0; R.m[14] = 0.0;  R.m[15] = 1.0;
632
+	}
633
+
634
+	Rt = transpose(R); // Transpose = Invert -> felet ej i Transpose, och det �r en ortonormal matris
635
+
636
+	Raxel = Rx(fi); // Rotate around x axis
637
+
638
+	// m := Rt * Rx * R
639
+	m = Mult(Mult(Rt, Raxel), R);
640
+	
641
+	return m;
642
+}
643
+
644
+
645
+// Not tested much
646
+mat4 CrossMatrix(vec3 a) // Matrix for cross product
647
+{
648
+	mat4 m;
649
+	
650
+	if (transposed)
651
+	{
652
+		m.m[0] =    0; m.m[4] =-a.z; m.m[8] = a.y; m.m[12] = 0.0;
653
+		m.m[1] = a.z; m.m[5] =    0; m.m[9] =-a.x; m.m[13] = 0.0;
654
+		m.m[2] =-a.y; m.m[6] = a.x; m.m[10]=    0; m.m[14] = 0.0;
655
+		m.m[3] =  0.0; m.m[7] =  0.0; m.m[11]=  0.0; m.m[15] = 0.0;
656
+		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
657
+		// not be generally used, but is fine for matrix differentials
658
+	}
659
+	else
660
+	{
661
+		m.m[0] =    0; m.m[1] =-a.z; m.m[2] = a.y; m.m[3] = 0.0;
662
+		m.m[4] = a.z; m.m[5] =    0; m.m[6] =-a.x; m.m[7] = 0.0;
663
+		m.m[8] =-a.y; m.m[9] = a.x; m.m[10]=    0; m.m[11] = 0.0;
664
+		m.m[12] =  0.0; m.m[13] =  0.0; m.m[14]=  0.0; m.m[15] = 0.0;
665
+		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
666
+		// not be generally used, but is fine for matrix differentials
667
+	}
668
+	
669
+	return m;
670
+}
671
+
672
+mat4 MatrixAdd(mat4 a, mat4 b)
673
+{
674
+	mat4 dest;
675
+	
676
+	int i;
677
+	for (i = 0; i < 16; i++)
678
+		dest.m[i] = a.m[i] + b.m[i];
679
+	
680
+	return dest;
681
+}
682
+
683
+
684
+void SetTransposed(char t)
685
+{
686
+	transposed = t;
687
+}
688
+
689
+
690
+// Build standard matrices
691
+
692
+mat4 lookAtv(vec3 p, vec3 l, vec3 v)
693
+{
694
+	vec3 n, u;
695
+	mat4 rot, trans;
696
+
697
+	n = Normalize(VectorSub(p, l));
698
+	u = Normalize(CrossProduct(v, n));
699
+	v = CrossProduct(n, u);
700
+
701
+//	rot = {{ u.x, u.y, u.z, 0,
702
+//                      v.x, v.y, v.z, 0,
703
+//                      n.x, n.y, n.z, 0,
704
+//                      0,   0,   0,   1 }};
705
+// VS friendly version:
706
+	if (transposed)
707
+	rot = SetMat4(u.x, v.x, n.x, 0,
708
+                  u.y, v.y, n.y, 0,
709
+                  u.z, v.z, n.z, 0,
710
+                  0,   0,   0,   1);
711
+	else
712
+	rot = SetMat4(u.x, u.y, u.z, 0,
713
+                  v.x, v.y, v.z, 0,
714
+                  n.x, n.y, n.z, 0,
715
+                  0,   0,   0,   1);
716
+	trans = T(-p.x, -p.y, -p.z);
717
+	return Mult(rot, trans);
718
+}
719
+
720
+mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz, 
721
+			GLfloat lx, GLfloat ly, GLfloat lz,
722
+			GLfloat vx, GLfloat vy, GLfloat vz)
723
+{
724
+	vec3 p, l, v;
725
+	
726
+	p = SetVector(px, py, pz);
727
+	l = SetVector(lx, ly, lz);
728
+	v = SetVector(vx, vy, vz);
729
+	
730
+	return lookAtv(p, l, v);
731
+}
732
+
733
+// From http://www.opengl.org/wiki/GluPerspective_code
734
+// Changed names and parameter order to conform with VU style
735
+// Rewritten 120913 because it was all wrong...
736
+
737
+// Creates a projection matrix like gluPerspective or glFrustum.
738
+// Upload to your shader as usual.
739
+// 2022: Yet another fix. Was it correct this time?
740
+mat4 perspective(float fovyInDegrees, float aspectRatio,
741
+                      float znear, float zfar)
742
+{
743
+	float f = 1.0/tan(fovyInDegrees * M_PI / 360.0);
744
+	mat4 m = SetMat4(f/aspectRatio, 0, 0, 0,
745
+					0, f, 0, 0,
746
+					0, 0, (zfar+znear)/(znear-zfar), 2*zfar*znear/(znear-zfar),
747
+					0, 0, -1, 0);
748
+	if (transposed)
749
+		m = transpose(m);
750
+	return m;
751
+}
752
+
753
+mat4 frustum(float left, float right, float bottom, float top,
754
+                  float znear, float zfar)
755
+{
756
+    float temp, temp2, temp3, temp4;
757
+    mat4 matrix;
758
+    
759
+    temp = 2.0f * znear;
760
+    temp2 = right - left;
761
+    temp3 = top - bottom;
762
+    temp4 = zfar - znear;
763
+    matrix.m[0] = temp / temp2; // 2*near/(right-left)
764
+    matrix.m[1] = 0.0;
765
+    matrix.m[2] = 0.0;
766
+    matrix.m[3] = 0.0;
767
+    matrix.m[4] = 0.0;
768
+    matrix.m[5] = temp / temp3; // 2*near/(top - bottom)
769
+    matrix.m[6] = 0.0;
770
+    matrix.m[7] = 0.0;
771
+    matrix.m[8] = (right + left) / temp2; // A = r+l / r-l
772
+    matrix.m[9] = (top + bottom) / temp3; // B = t+b / t-b
773
+    matrix.m[10] = (-zfar - znear) / temp4; // C = -(f+n) / f-n
774
+    matrix.m[11] = -1.0;
775
+    matrix.m[12] = 0.0;
776
+    matrix.m[13] = 0.0;
777
+    matrix.m[14] = (-temp * zfar) / temp4; // D = -2fn / f-n
778
+    matrix.m[15] = 0.0;
779
+    
780
+    if (!transposed)
781
+    	matrix = transpose(matrix);
782
+    
783
+    return matrix;
784
+}
785
+
786
+// Not tested!
787
+mat4 ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
788
+{
789
+        float a = 2.0f / (right - left);
790
+        float b = 2.0f / (top - bottom);
791
+        float c = -2.0f / (far - near);
792
+
793
+        float tx = - (right + left)/(right - left);
794
+        float ty = - (top + bottom)/(top - bottom);
795
+        float tz = - (far + near)/(far - near);
796
+
797
+        mat4 o = SetMat4(
798
+            a, 0, 0, tx,
799
+            0, b, 0, ty,
800
+            0, 0, c, tz,
801
+            0, 0, 0, 1);
802
+        return o;
803
+}
804
+
805
+// The code below is based on code from:
806
+// http://www.dr-lex.be/random/matrix_inv.html
807
+
808
+// Inverts mat3 (row-wise matrix)
809
+// (For a more general inverse, try a gaussian elimination.)
810
+mat3 InvertMat3(mat3 in)
811
+{
812
+	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
813
+	mat3 out, nanout;
814
+	float DET;
815
+	
816
+	// Copying to internal variables both clarify the code and
817
+	// buffers data so the output may be identical to the input!
818
+	a11 = in.m[0];
819
+	a12 = in.m[1];
820
+	a13 = in.m[2];
821
+	a21 = in.m[3];
822
+	a22 = in.m[4];
823
+	a23 = in.m[5];
824
+	a31 = in.m[6];
825
+	a32 = in.m[7];
826
+	a33 = in.m[8];
827
+	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
828
+	if (DET != 0)
829
+	{
830
+		out.m[0] = (a33*a22-a32*a23)/DET;
831
+		out.m[1] = -(a33*a12-a32*a13)/DET;
832
+		out.m[2] = (a23*a12-a22*a13)/DET;
833
+		out.m[3] = -(a33*a21-a31*a23)/DET;
834
+		out.m[4] = (a33*a11-a31*a13)/DET;
835
+		out.m[5] = -(a23*a11-a21*a13)/DET;
836
+		out.m[6] = (a32*a21-a31*a22)/DET;
837
+		out.m[7] = -(a32*a11-a31*a12)/DET;
838
+		out.m[8] = (a22*a11-a21*a12)/DET;
839
+	}
840
+	else
841
+	{
842
+		nanout = SetMat3(NAN, NAN, NAN,
843
+								NAN, NAN, NAN,
844
+								NAN, NAN, NAN);
845
+		out = nanout;
846
+	}
847
+	
848
+	return out;
849
+}
850
+
851
+// For making a normal matrix from a model-to-view matrix
852
+// Takes a mat4 in, ignores 4th row/column (should just be translations),
853
+// inverts as mat3 (row-wise matrix) and returns the transpose
854
+mat3 InverseTranspose(mat4 in)
855
+{
856
+	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
857
+	mat3 out, nanout;
858
+	float DET;
859
+	
860
+	// Copying to internal variables
861
+	a11 = in.m[0];
862
+	a12 = in.m[1];
863
+	a13 = in.m[2];
864
+	a21 = in.m[4];
865
+	a22 = in.m[5];
866
+	a23 = in.m[6];
867
+	a31 = in.m[8];
868
+	a32 = in.m[9];
869
+	a33 = in.m[10];
870
+	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
871
+	if (DET != 0)
872
+	{
873
+		out.m[0] = (a33*a22-a32*a23)/DET;
874
+		out.m[3] = -(a33*a12-a32*a13)/DET;
875
+		out.m[6] = (a23*a12-a22*a13)/DET;
876
+		out.m[1] = -(a33*a21-a31*a23)/DET;
877
+		out.m[4] = (a33*a11-a31*a13)/DET;
878
+		out.m[7] = -(a23*a11-a21*a13)/DET;
879
+		out.m[2] = (a32*a21-a31*a22)/DET;
880
+		out.m[5] = -(a32*a11-a31*a12)/DET;
881
+		out.m[8] = (a22*a11-a21*a12)/DET;
882
+	}
883
+	else
884
+	{
885
+		nanout = SetMat3(NAN, NAN, NAN,
886
+								NAN, NAN, NAN,
887
+								NAN, NAN, NAN);
888
+		out = nanout;
889
+	}
890
+
891
+	return out;
892
+}
893
+
894
+
895
+// Simple conversions
896
+mat3 mat4tomat3(mat4 m)
897
+{
898
+	mat3 result;
899
+	
900
+	result.m[0] = m.m[0];
901
+	result.m[1] = m.m[1];
902
+	result.m[2] = m.m[2];
903
+	result.m[3] = m.m[4];
904
+	result.m[4] = m.m[5];
905
+	result.m[5] = m.m[6];
906
+	result.m[6] = m.m[8];
907
+	result.m[7] = m.m[9];
908
+	result.m[8] = m.m[10];
909
+	return result;
910
+}
911
+
912
+mat4 mat3tomat4(mat3 m)
913
+{
914
+	mat4 result;
915
+	
916
+	result.m[0] = m.m[0];
917
+	result.m[1] = m.m[1];
918
+	result.m[2] = m.m[2];
919
+	result.m[3] = 0;
920
+	result.m[4] = m.m[3];
921
+	result.m[5] = m.m[4];
922
+	result.m[6] = m.m[5];
923
+	result.m[7] = 0;
924
+	result.m[8] = m.m[6];
925
+	result.m[9] = m.m[7];
926
+	result.m[10] = m.m[8];
927
+	result.m[11] = 0;
928
+
929
+	result.m[12] = 0;
930
+	result.m[13] = 0;
931
+	result.m[14] = 0;
932
+	result.m[15] = 1;
933
+	return result;
934
+}
935
+
936
+vec3 vec4tovec3(vec4 v)
937
+{
938
+	vec3 result;
939
+	result.x = v.x;
940
+	result.y = v.y;
941
+	result.z = v.z;
942
+	return result;
943
+}
944
+
945
+vec4 vec3tovec4(vec3 v)
946
+{
947
+	vec4 result;
948
+	result.x = v.x;
949
+	result.y = v.y;
950
+	result.z = v.z;
951
+	result.w = 1;
952
+	return result;
953
+}
954
+
955
+
956
+// Stol... I mean adapted from glMatrix (WebGL math unit). Almost no
957
+// changes despite changing language! But I just might replace it with
958
+// a gaussian elimination some time.
959
+mat4 InvertMat4(mat4 a)
960
+{
961
+   mat4 b;
962
+     
963
+   float c=a.m[0],d=a.m[1],e=a.m[2],g=a.m[3],
964
+	f=a.m[4],h=a.m[5],i=a.m[6],j=a.m[7],
965
+	k=a.m[8],l=a.m[9],o=a.m[10],m=a.m[11],
966
+	n=a.m[12],p=a.m[13],r=a.m[14],s=a.m[15],
967
+	A=c*h-d*f,
968
+	B=c*i-e*f,
969
+	t=c*j-g*f,
970
+	u=d*i-e*h,
971
+	v=d*j-g*h,
972
+	w=e*j-g*i,
973
+	x=k*p-l*n,
974
+	y=k*r-o*n,
975
+	z=k*s-m*n,
976
+	C=l*r-o*p,
977
+	D=l*s-m*p,
978
+	E=o*s-m*r,
979
+	q=1/(A*E-B*D+t*C+u*z-v*y+w*x);
980
+	b.m[0]=(h*E-i*D+j*C)*q;
981
+	b.m[1]=(-d*E+e*D-g*C)*q;
982
+	b.m[2]=(p*w-r*v+s*u)*q;
983
+	b.m[3]=(-l*w+o*v-m*u)*q;
984
+	b.m[4]=(-f*E+i*z-j*y)*q;
985
+	b.m[5]=(c*E-e*z+g*y)*q;
986
+	b.m[6]=(-n*w+r*t-s*B)*q;
987
+	b.m[7]=(k*w-o*t+m*B)*q;
988
+	b.m[8]=(f*D-h*z+j*x)*q;
989
+	b.m[9]=(-c*D+d*z-g*x)*q;
990
+	b.m[10]=(n*v-p*t+s*A)*q;
991
+	b.m[11]=(-k*v+l*t-m*A)*q;
992
+	b.m[12]=(-f*C+h*y-i*x)*q;
993
+	b.m[13]=(c*C-d*y+e*x)*q;
994
+	b.m[14]=(-n*u+p*B-r*A)*q;
995
+	b.m[15]=(k*u-l*B+o*A)*q;
996
+	return b;
997
+};
998
+
999
+
1000
+// Two convenient printing functions suggested by Christian Luckey 2015.
1001
+// Added printMat3 2019.
1002
+void printMat4(mat4 m)
1003
+{
1004
+	unsigned int i;
1005
+	printf(" ---------------------------------------------------------------\n");
1006
+	for (i = 0; i < 4; i++)
1007
+	{
1008
+		int n = i * 4;
1009
+		printf("| %11.5f\t| %11.5f\t| %11.5f\t| %11.5f\t|\n",
1010
+			m.m[n], m.m[n+1], m.m[n+2], m.m[n+3]);
1011
+	}
1012
+	printf(" ---------------------------------------------------------------\n");
1013
+}
1014
+
1015
+void printMat3(mat3 m)
1016
+{
1017
+	unsigned int i;
1018
+	printf(" ---------------------------------------------------------------\n");
1019
+	for (i = 0; i < 3; i++)
1020
+	{
1021
+		int n = i * 3;
1022
+		printf("| %11.5f\t| %11.5f\t| %11.5f\t| \n",
1023
+			m.m[n], m.m[n+1], m.m[n+2]);
1024
+	}
1025
+	printf(" ---------------------------------------------------------------\n");
1026
+}
1027
+
1028
+void printVec3(vec3 in) 
1029
+{
1030
+	printf("(%f, %f, %f)\n", in.x, in.y, in.z);
1031
+}
1032
+
1033
+
1034
+
1035
+/* Utility functions for easier uploads to shaders with error messages. */
1036
+// NEW as prototype 2022, added to VU 2023
1037
+
1038
+#define NUM_ERRORS 8
1039
+
1040
+static void ReportError(const char *caller, const char *name)
1041
+{
1042
+	static unsigned int draw_error_counter = 0; 
1043
+	if(draw_error_counter < NUM_ERRORS)
1044
+	{
1045
+		fprintf(stderr, "%s warning: '%s' not found in shader!\n", caller, name);
1046
+		draw_error_counter++;
1047
+	}
1048
+	else if(draw_error_counter == NUM_ERRORS)
1049
+	{
1050
+		fprintf(stderr, "%s: Number of errors bigger than %i. No more vill be printed.\n", caller, NUM_ERRORS);
1051
+		draw_error_counter++;
1052
+	}
1053
+}
1054
+
1055
+void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m)
1056
+{
1057
+	if (nameInShader == NULL) return;
1058
+	glUseProgram(shader);
1059
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1060
+	if (loc >= 0)
1061
+		glUniformMatrix4fv(loc, 1, GL_TRUE, m.m);
1062
+	else
1063
+		ReportError("uploadMat4ToShader", nameInShader);
1064
+}
1065
+
1066
+void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i)
1067
+{
1068
+	if (nameInShader == NULL) return;
1069
+	glUseProgram(shader);
1070
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1071
+	if (loc >= 0)
1072
+		glUniform1i(loc, i);
1073
+	else
1074
+		ReportError("uploadUniformIntToShader", nameInShader);
1075
+}
1076
+
1077
+void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f)
1078
+{
1079
+	if (nameInShader == NULL) return;
1080
+	glUseProgram(shader);
1081
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1082
+	if (loc >= 0)
1083
+		glUniform1f(loc, f);
1084
+	else
1085
+		ReportError("uploadUniformFloatToShader", nameInShader);
1086
+}
1087
+
1088
+void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength)
1089
+{
1090
+	if (nameInShader == NULL) return;
1091
+	glUseProgram(shader);
1092
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1093
+	if (loc >= 0)
1094
+		glUniform1fv(loc, arrayLength, f);
1095
+	else
1096
+		ReportError("uploadUniformFloatToShader", nameInShader);
1097
+}
1098
+
1099
+void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v)
1100
+{
1101
+	if (nameInShader == NULL) return;
1102
+	glUseProgram(shader);
1103
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1104
+	if (loc >= 0)
1105
+		glUniform3f(loc, v.x, v.y, v.z);
1106
+	else
1107
+		ReportError("uploadUniformVec3ToShader", nameInShader);
1108
+}
1109
+
1110
+void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength)
1111
+{
1112
+	if (nameInShader == NULL) return;
1113
+	glUseProgram(shader);
1114
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1115
+	if (loc >= 0)
1116
+		glUniform3fv(loc, arrayLength, (GLfloat *)a);
1117
+	else
1118
+		ReportError("uploadUniformVec3ArrayToShader", nameInShader);
1119
+}
1120
+
1121
+void bindTextureToTextureUnit(GLuint tex, int unit)
1122
+{
1123
+	glActiveTexture(GL_TEXTURE0 + unit);
1124
+	glBindTexture(GL_TEXTURE_2D, tex);
1125
+}