Browse code

Standardize OpenGL-related #includes and #defines

We use glXGetProcAddress to load glXCreateContextAttribsARB ourselves,
so GLX_GLXEXT_PROTOTYPES is not needed.

Robert Cranston authored on 27/02/2024 02:27:47
Showing 1 changed files
... ...
@@ -99,15 +99,16 @@
99 99
 #ifndef VECTORUTILS4
100 100
 #define VECTORUTILS4
101 101
 
102
-#ifdef __APPLE__
102
+#if defined(__APPLE__)
103 103
 	#define GL_SILENCE_DEPRECATION
104 104
 	#include <OpenGL/gl3.h>
105
+#elif defined(_WIN32)
106
+	#include "glew.h"
105 107
 #else
106
-	#if defined(_WIN32)
107
-		#include "glew.h"
108
-	#endif
108
+	#define GL_GLEXT_PROTOTYPES
109 109
 	#include <GL/gl.h>
110 110
 #endif
111
+
111 112
 #include <math.h>
112 113
 #include <stdio.h>
113 114
 
Browse code

Convert encoding from MacRoman to UTF-8

Swedish characters use a weird encoding. For instance, `file --mime`
just gives `charset=unknown-8bit` and `grep` just says `binary file
matches`.

Searching for them in the [Western Latin character sets comparison
table][] gives that this is the old [Mac OS Roman][] (MIME / IANA:
`macintosh`). Tooling support for this outside of Macs is very poor, as
can be seen above.

[Western Latin character sets comparison table]: https://en.wikipedia.org/wiki/Western_Latin_character_sets_(computing)#Comparison_table
[Mac OS Roman]: https://en.wikipedia.org/wiki/Mac_OS_Roman

To convert:

tmp_file="$(mktemp)"
trap 'rm "$tmp_file"' EXIT
find . -type f -exec file --mime {} + \
| while IFS=':' read file mime
do
if echo "$mime" | grep -qi 'charset=unknown-8bit'
then
iconv -f 'macintosh' -t 'utf-8' "$file" -o "$tmp_file"
mv "$tmp_file" "$file"
fi
done

Robert Cranston authored on 27/02/2024 02:27:29
Showing 1 changed files
... ...
@@ -1140,7 +1140,7 @@ mat4 ArbRotate(vec3 axis, GLfloat fi)
1140 1140
 		R.m[12] = 0.0; R.m[13] = 0.0; R.m[14] = 0.0;  R.m[15] = 1.0;
1141 1141
 	}
1142 1142
 
1143
-	Rt = Transpose(R); // Transpose = Invert -> felet ej i Transpose, och det �r en ortonormal matris
1143
+	Rt = Transpose(R); // Transpose = Invert -> felet ej i Transpose, och det är en ortonormal matris
1144 1144
 
1145 1145
 	Raxel = Rx(fi); // Rotate around x axis
1146 1146
 
Browse code

Add cpp-v5

Ingemar Ragnemalm authored on 21/02/2024 20:24:32 • Robert Cranston committed on 21/02/2024 20:24:32
Showing 1 changed files
... ...
@@ -88,6 +88,7 @@
88 88
 // 20220525: Revised perpective() to conform with the reference manual as well as GLM.
89 89
 // 20230205: Added new helper functions, uploadMat4ToShader etc.
90 90
 // Made a better #ifdef for handling multiple inclusions.
91
+// 20230227: Fixed the mat4(mat3) constructor.
91 92
 
92 93
 // You may use VectorUtils as you please. A reference to the origin is appreciated
93 94
 // but if you grab some snippets from it without reference... no problem.
... ...
@@ -253,14 +254,16 @@
253 254
 	} mat3;
254 255
 
255 256
 #ifdef __cplusplus
256
-	vec3::vec3(vec4 v) : x(v.x), y(v.y), z(v.z) {}
257
-	mat4::mat4(mat3 x)
258
-	{
259
-		m[0] = x.m[0]; m[1] = x.m[1]; m[2] = x.m[2]; m[3] = 0;
260
-		m[4] = x.m[3]; m[5] = x.m[4]; m[6] = x.m[5]; m[7] = 0;
261
-		m[8] = x.m[6]; m[9] = x.m[7]; m[10] = x.m[8]; m[11] = 0;
262
-		m[12] = x.m[0]; m[13] = x.m[0]; m[14] = x.m[0]; m[15] = 1;
263
-	}
257
+// This needed to be compiled only once - moved to implementation.
258
+// This most likely must be done with several more!
259
+//	vec3::vec3(vec4 v) : x(v.x), y(v.y), z(v.z) {}
260
+//	mat4::mat4(mat3 x)
261
+//	{
262
+//		m[0] = x.m[0]; m[1] = x.m[1]; m[2] = x.m[2]; m[3] = 0;
263
+//		m[4] = x.m[3]; m[5] = x.m[4]; m[6] = x.m[5]; m[7] = 0;
264
+//		m[8] = x.m[6]; m[9] = x.m[7]; m[10] = x.m[8]; m[11] = 0;
265
+//		m[12] = x.m[0]; m[13] = x.m[0]; m[14] = x.m[0]; m[15] = 1;
266
+//	}
264 267
 #endif
265 268
 
266 269
 //#ifdef __cplusplus
... ...
@@ -375,7 +378,7 @@
375 378
 #ifdef __cplusplus
376 379
 // Some C++ operator overloads
377 380
 // Non-member C++ operators!
378
-// New version 2021-05-2x: Constructiors for vec3 etc replaced in order to avoid
381
+// New version 2021-05-2x: Constructors for vec3 etc replaced in order to avoid
379 382
 // problems with some C++ compilers.
380 383
 
381 384
 // --- vec3 operations ---
... ...
@@ -1656,6 +1659,20 @@ mat4 lookAt(vec3 p, vec3 l, vec3 u)
1656 1659
 	return lookAtv(p, l, u);
1657 1660
 }
1658 1661
 
1662
+
1663
+#ifdef __cplusplus
1664
+	vec3::vec3(vec4 v) : x(v.x), y(v.y), z(v.z) {}
1665
+	// Was wrong, fixed 2023-02-27
1666
+	mat4::mat4(mat3 x)
1667
+	{
1668
+		m[0]  = x.m[0]; m[1]  = x.m[1]; m[2] =  x.m[2]; m[3]  = 0;
1669
+		m[4]  = x.m[3]; m[5]  = x.m[4]; m[6] =  x.m[5]; m[7]  = 0;
1670
+		m[8]  = x.m[6]; m[9]  = x.m[7]; m[10] = x.m[8]; m[11] = 0;
1671
+		m[12] = 0;      m[13] = 0;      m[14] = 0;      m[15] = 1;
1672
+	}
1673
+#endif
1674
+
1675
+
1659 1676
 #endif
1660 1677
 #endif
1661 1678
 #endif
Browse code

Add cpp-v3

Ingemar Ragnemalm authored on 21/02/2024 20:24:30 • Robert Cranston committed on 21/02/2024 20:24:30
Showing 1 changed files
1 1
old mode 100755
2 2
new mode 100644
... ...
@@ -74,7 +74,6 @@
74 74
 // 180314: Added some #defines for moving closer to GLSL (dot, cross...).
75 75
 // 2021-05-15: Constructors for vec3 etc replaced in order to avoid
76 76
 // problems with some C++ compilers.
77
-// 2022-11-10: Corrected an ifdef that could cause problems.
78 77
 
79 78
 // 2022-05-05: Created VectorUtils4, now only a header file!
80 79
 // You must define MAIN in only one file (typically the main
... ...
@@ -86,14 +85,15 @@
86 85
 // - You must #define MAIN in the main program
87 86
 // This means that VectorUtils can still be used from C and thereby many other languages,
88 87
 // while taking more advantage of C++ features when using C++.
89
-// 20220525: Revised perpective() to conform with the reference manual as well as GLM. (But it went wrong, why?)
90
-// 2022-08-29: Renamed Transpose to transpose to conform better with GLSL. Corrected perspective.
88
+// 20220525: Revised perpective() to conform with the reference manual as well as GLM.
89
+// 20230205: Added new helper functions, uploadMat4ToShader etc.
90
+// Made a better #ifdef for handling multiple inclusions.
91 91
 
92 92
 // You may use VectorUtils as you please. A reference to the origin is appreciated
93 93
 // but if you grab some snippets from it without reference... no problem.
94 94
 
95
-// VectorUtils3 header
96
-// See source for more information
95
+// VectorUtils4 interface part
96
+// See implementation part for more information
97 97
 
98 98
 #ifndef VECTORUTILS4
99 99
 #define VECTORUTILS4
... ...
@@ -115,11 +115,6 @@
115 115
 #define M_PI           3.14159265358979323846
116 116
 #endif
117 117
 
118
-// Really old type names
119
-#define Vector3f Point3D
120
-#define Matrix3f Matrix3D
121
-#define Matrix4f Matrix4D
122
-
123 118
 // GLSL-style
124 119
 // These are already changed, here I define the intermediate type names that I use in some demos.
125 120
 #define Point3D vec3
... ...
@@ -136,10 +131,11 @@
136 131
 // without knowing about the constructors, while the C++ code happily used them.
137 132
 // However, we do not need them; you can initialize with SetVec* instead of
138 133
 // vec*() and it will work.
139
-// Note 2022: These are now back (and more), which is possible when doing this as a header only unit.
140
-
134
+// Note 2022: These are now back (and more), which is possible when doing this as a header only unit
135
+// so it works with both C and C++ and still allows the constructors.
136
+	
141 137
 	typedef struct vec4 vec4;
142
-
138
+	
143 139
 	// vec3 is very useful
144 140
 	typedef struct vec3
145 141
 	{
... ...
@@ -158,7 +154,7 @@
158 154
 			vec3(vec4 v);
159 155
 		#endif
160 156
 	} vec3, *vec3Ptr;
161
-
157
+	
162 158
 	// vec4 is not as useful. Can be a color with alpha, or a quaternion, but IMHO you
163 159
 	// rarely need homogenous coordinate vectors on the CPU.
164 160
 	typedef struct vec4
... ...
@@ -189,13 +185,13 @@
189 185
 		{GLfloat x; GLfloat s;};
190 186
 		union
191 187
 		{GLfloat y; GLfloat t;};
192
-
188
+		
193 189
 		#ifdef __cplusplus
194 190
             vec2() {}
195 191
 			vec2(GLfloat x2, GLfloat y2) : x(x2), y(y2) {}
196 192
 		#endif
197 193
 	} vec2, *vec2Ptr;
198
-
194
+	
199 195
 	typedef struct mat3 mat3;
200 196
 	typedef struct mat4
201 197
 	{
... ...
@@ -211,7 +207,7 @@
211 207
 			}
212 208
 			mat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
213 209
 				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
214
-				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
210
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11, 
215 211
 				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15)
216 212
 			{
217 213
 				m[0] = p0; m[1] = p1; m[2] = p2; m[3] = p3;
... ...
@@ -280,7 +276,7 @@
280 276
 	mat3 SetMat3(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7, GLfloat p8);
281 277
 	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
282 278
 				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
283
-				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
279
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11, 
284 280
 				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
285 281
 				);
286 282
 // Basic vector operations on vec3's. (vec4 not included since I never need them.)
... ...
@@ -327,7 +323,7 @@
327 323
 
328 324
 // GLU replacement functions
329 325
 	mat4 lookAtv(vec3 p, vec3 l, vec3 v);
330
-	mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz,
326
+	mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz, 
331 327
 			GLfloat lx, GLfloat ly, GLfloat lz,
332 328
 			GLfloat vx, GLfloat vy, GLfloat vz);
333 329
 	mat4 perspective(float fovyInDegrees, float aspectRatio,
... ...
@@ -354,15 +350,13 @@
354 350
 
355 351
 /* Utility functions for easier uploads to shaders with error messages. */
356 352
 // NEW as prototype 2022, added to VU 2023
357
-/*
358
-	void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m);
359
-	void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i);
360
-	void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f);
361
-	void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength);
362
-	void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v);
363
-	void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength);
353
+	void uploadMat4ToShader(GLuint shader, const char *nameInShader, mat4 m);
354
+	void uploadUniformIntToShader(GLuint shader, const char *nameInShader, GLint i);
355
+	void uploadUniformFloatToShader(GLuint shader, const char *nameInShader, GLfloat f);
356
+	void uploadUniformFloatArrayToShader(GLuint shader, const char *nameInShader, GLfloat *f, int arrayLength);
357
+	void uploadUniformVec3ToShader(GLuint shader, const char *nameInShader, vec3 v);
358
+	void uploadUniformVec3ArrayToShader(GLuint shader, const char *nameInShader, vec3 *a, int arrayLength);
364 359
 	void bindTextureToTextureUnit(GLuint tex, int unit);
365
-*/
366 360
 
367 361
 #ifdef __cplusplus
368 362
 // Convenient overloads for C++, closer to GLSL
... ...
@@ -554,13 +548,15 @@ vec3 operator*(const mat3 &a, const vec3 &b)
554 548
 }
555 549
 
556 550
 #endif
557
-//#endif
551
+#endif
558 552
 
559 553
 // ********** implementation section ************
560 554
 
561 555
 #ifdef MAIN
562
-//#ifndef VECTOR_UTILS_IMPLEMENTATION
563
-//#define VECTOR_UTILS_IMPLEMENTATION
556
+
557
+// Make sure this is included once
558
+#ifndef VECTORUTILS4_MAIN
559
+#define VECTORUTILS4_MAIN
564 560
 
565 561
 // VS doesn't define NAN properly
566 562
 #ifdef _WIN32
... ...
@@ -575,7 +571,7 @@ char transposed = 0;
575 571
 	vec3 SetVector(GLfloat x, GLfloat y, GLfloat z)
576 572
 	{
577 573
 		vec3 v;
578
-
574
+		
579 575
 		v.x = x;
580 576
 		v.y = y;
581 577
 		v.z = z;
... ...
@@ -586,7 +582,7 @@ char transposed = 0;
586 582
 	vec2 SetVec2(GLfloat x, GLfloat y)
587 583
 	{
588 584
 		vec2 v;
589
-
585
+		
590 586
 		v.x = x;
591 587
 		v.y = y;
592 588
 		return v;
... ...
@@ -595,7 +591,7 @@ char transposed = 0;
595 591
 	vec3 SetVec3(GLfloat x, GLfloat y, GLfloat z)
596 592
 	{
597 593
 		vec3 v;
598
-
594
+		
599 595
 		v.x = x;
600 596
 		v.y = y;
601 597
 		v.z = z;
... ...
@@ -605,7 +601,7 @@ char transposed = 0;
605 601
 	vec4 SetVec4(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
606 602
 	{
607 603
 		vec4 v;
608
-
604
+		
609 605
 		v.x = x;
610 606
 		v.y = y;
611 607
 		v.z = z;
... ...
@@ -632,7 +628,7 @@ char transposed = 0;
632 628
 // Like above; Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
633 629
 	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
634 630
 				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
635
-				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
631
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11, 
636 632
 				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
637 633
 				)
638 634
 	{
... ...
@@ -664,17 +660,17 @@ char transposed = 0;
664 660
 	vec3 VectorSub(vec3 a, vec3 b)
665 661
 	{
666 662
 		vec3 result;
667
-
663
+		
668 664
 		result.x = a.x - b.x;
669 665
 		result.y = a.y - b.y;
670 666
 		result.z = a.z - b.z;
671 667
 		return result;
672 668
 	}
673
-
669
+	
674 670
 	vec3 VectorAdd(vec3 a, vec3 b)
675 671
 	{
676 672
 		vec3 result;
677
-
673
+		
678 674
 		result.x = a.x + b.x;
679 675
 		result.y = a.y + b.y;
680 676
 		result.z = a.z + b.z;
... ...
@@ -688,7 +684,7 @@ char transposed = 0;
688 684
 		result.x = a.y*b.z - a.z*b.y;
689 685
 		result.y = a.z*b.x - a.x*b.z;
690 686
 		result.z = a.x*b.y - a.y*b.x;
691
-
687
+		
692 688
 		return result;
693 689
 	}
694 690
 
... ...
@@ -700,11 +696,11 @@ char transposed = 0;
700 696
 	vec3 ScalarMult(vec3 a, GLfloat s)
701 697
 	{
702 698
 		vec3 result;
703
-
699
+		
704 700
 		result.x = a.x * s;
705 701
 		result.y = a.y * s;
706 702
 		result.z = a.z * s;
707
-
703
+		
708 704
 		return result;
709 705
 	}
710 706
 
... ...
@@ -734,7 +730,7 @@ char transposed = 0;
734 730
 
735 731
 		n = cross(VectorSub(a, b), VectorSub(a, c));
736 732
 		n = ScalarMult(n, 1/Norm(n));
737
-
733
+		
738 734
 		return n;
739 735
 	}
740 736
 
... ...
@@ -936,7 +932,7 @@ char transposed = 0;
936 932
 	vec3 MultMat3Vec3(mat3 a, vec3 b) // result = a * b
937 933
 	{
938 934
 		vec3 r;
939
-
935
+		
940 936
 		if (!transposed)
941 937
 		{
942 938
 			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z;
... ...
@@ -949,7 +945,7 @@ char transposed = 0;
949 945
 			r.y = a.m[1]*b.x + a.m[4]*b.y + a.m[7]*b.z;
950 946
 			r.z = a.m[2]*b.x + a.m[5]*b.y + a.m[8]*b.z;
951 947
 		}
952
-
948
+		
953 949
 		return r;
954 950
 	}
955 951
 
... ...
@@ -1061,12 +1057,12 @@ char transposed = 0;
1061 1057
 //	mat4 TransposeRotation(mat4 m)
1062 1058
 //	{
1063 1059
 //		mat4 a;
1064
-//
1060
+//		
1065 1061
 //		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[12];
1066 1062
 //		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[13];
1067 1063
 //		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[14];
1068 1064
 //		a.m[3] = m.m[3]; a.m[7] = m.m[7]; a.m[11] = m.m[11];    a.m[15] = m.m[15];
1069
-//
1065
+//		
1070 1066
 //		return a;
1071 1067
 //	}
1072 1068
 
... ...
@@ -1074,12 +1070,12 @@ char transposed = 0;
1074 1070
 	mat4 transpose(mat4 m)
1075 1071
 	{
1076 1072
 		mat4 a;
1077
-
1073
+		
1078 1074
 		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[3];
1079 1075
 		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[7];
1080 1076
 		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[11];
1081 1077
 		a.m[3] = m.m[12]; a.m[7] = m.m[13]; a.m[11] = m.m[14];    a.m[15] = m.m[15];
1082
-
1078
+		
1083 1079
 		return a;
1084 1080
 	}
1085 1081
 
... ...
@@ -1087,11 +1083,11 @@ char transposed = 0;
1087 1083
 	mat3 TransposeMat3(mat3 m)
1088 1084
 	{
1089 1085
 		mat3 a;
1090
-
1086
+		
1091 1087
 		a.m[0] = m.m[0]; a.m[3] = m.m[1]; a.m[6] = m.m[2];
1092 1088
 		a.m[1] = m.m[3]; a.m[4] = m.m[4]; a.m[7] = m.m[5];
1093 1089
 		a.m[2] = m.m[6]; a.m[5] = m.m[7]; a.m[8] = m.m[8];
1094
-
1090
+		
1095 1091
 		return a;
1096 1092
 	}
1097 1093
 
... ...
@@ -1141,13 +1137,13 @@ mat4 ArbRotate(vec3 axis, GLfloat fi)
1141 1137
 		R.m[12] = 0.0; R.m[13] = 0.0; R.m[14] = 0.0;  R.m[15] = 1.0;
1142 1138
 	}
1143 1139
 
1144
-	Rt = Transpose(R); // Transpose = Invert -> felet ej i Transpose, och det \8Ar en ortonormal matris
1140
+	Rt = Transpose(R); // Transpose = Invert -> felet ej i Transpose, och det �r en ortonormal matris
1145 1141
 
1146 1142
 	Raxel = Rx(fi); // Rotate around x axis
1147 1143
 
1148 1144
 	// m := Rt * Rx * R
1149 1145
 	m = Mult(Mult(Rt, Raxel), R);
1150
-
1146
+	
1151 1147
 	return m;
1152 1148
 }
1153 1149
 
... ...
@@ -1156,7 +1152,7 @@ mat4 ArbRotate(vec3 axis, GLfloat fi)
1156 1152
 mat4 CrossMatrix(vec3 a) // Matrix for cross product
1157 1153
 {
1158 1154
 	mat4 m;
1159
-
1155
+	
1160 1156
 	if (transposed)
1161 1157
 	{
1162 1158
 		m.m[0] =    0; m.m[4] =-a.z; m.m[8] = a.y; m.m[12] = 0.0;
... ...
@@ -1175,18 +1171,18 @@ mat4 CrossMatrix(vec3 a) // Matrix for cross product
1175 1171
 		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
1176 1172
 		// not be generally used, but is fine for matrix differentials
1177 1173
 	}
1178
-
1174
+	
1179 1175
 	return m;
1180 1176
 }
1181 1177
 
1182 1178
 mat4 MatrixAdd(mat4 a, mat4 b)
1183 1179
 {
1184 1180
 	mat4 dest;
1185
-
1181
+	
1186 1182
 	int i;
1187 1183
 	for (i = 0; i < 16; i++)
1188 1184
 		dest.m[i] = a.m[i] + b.m[i];
1189
-
1185
+	
1190 1186
 	return dest;
1191 1187
 }
1192 1188
 
... ...
@@ -1224,27 +1220,31 @@ mat4 lookAtv(vec3 p, vec3 l, vec3 v)
1224 1220
 	return m;
1225 1221
 }
1226 1222
 
1227
-mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz,
1223
+mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz, 
1228 1224
 			GLfloat lx, GLfloat ly, GLfloat lz,
1229 1225
 			GLfloat vx, GLfloat vy, GLfloat vz)
1230 1226
 {
1231 1227
 	vec3 p, l, v;
1232
-
1228
+	
1233 1229
 	p = SetVector(px, py, pz);
1234 1230
 	l = SetVector(lx, ly, lz);
1235 1231
 	v = SetVector(vx, vy, vz);
1236
-
1232
+	
1237 1233
 	return lookAtv(p, l, v);
1238 1234
 }
1239 1235
 
1240 1236
 // From http://www.opengl.org/wiki/GluPerspective_code
1241 1237
 // Changed names and parameter order to conform with VU style
1242 1238
 // Rewritten 120913 because it was all wrong...
1243
-// Rewritten again 2022 to a more compact form.
1239
+
1240
+// Creates a projection matrix like gluPerspective or glFrustum.
1241
+// Upload to your shader as usual.
1242
+// Error fixed 20220525: 180, not 360!
1243
+// Also made it conform to the reference manual.
1244 1244
 mat4 perspective(float fovyInDegrees, float aspectRatio,
1245 1245
                       float znear, float zfar)
1246 1246
 {
1247
-	float f = 1/tan(fovyInDegrees * M_PI / 360.0);
1247
+	float f = 1/tan(fovyInDegrees / 2);
1248 1248
 	mat4 m = SetMat4(f/aspectRatio, 0, 0, 0,
1249 1249
 					0, f, 0, 0,
1250 1250
 					0, 0, (zfar+znear)/(znear-zfar), 2*zfar*znear/(znear-zfar),
... ...
@@ -1259,7 +1259,7 @@ mat4 frustum(float left, float right, float bottom, float top,
1259 1259
 {
1260 1260
     float temp, temp2, temp3, temp4;
1261 1261
     mat4 matrix;
1262
-
1262
+    
1263 1263
     temp = 2.0f * znear;
1264 1264
     temp2 = right - left;
1265 1265
     temp3 = top - bottom;
... ...
@@ -1280,10 +1280,10 @@ mat4 frustum(float left, float right, float bottom, float top,
1280 1280
     matrix.m[13] = 0.0;
1281 1281
     matrix.m[14] = (-temp * zfar) / temp4; // D = -2fn / f-n
1282 1282
     matrix.m[15] = 0.0;
1283
-
1283
+    
1284 1284
     if (!transposed)
1285 1285
     	matrix = Transpose(matrix);
1286
-
1286
+    
1287 1287
     return matrix;
1288 1288
 }
1289 1289
 
... ...
@@ -1320,7 +1320,7 @@ mat3 InvertMat3(mat3 in)
1320 1320
 	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
1321 1321
 	mat3 out, nanout;
1322 1322
 	float DET;
1323
-
1323
+	
1324 1324
 	// Copying to internal variables both clarify the code and
1325 1325
 	// buffers data so the output may be identical to the input!
1326 1326
 	a11 = in.m[0];
... ...
@@ -1352,7 +1352,7 @@ mat3 InvertMat3(mat3 in)
1352 1352
 								NAN, NAN, NAN);
1353 1353
 		out = nanout;
1354 1354
 	}
1355
-
1355
+	
1356 1356
 	return out;
1357 1357
 }
1358 1358
 
... ...
@@ -1364,7 +1364,7 @@ mat3 InverseTranspose(mat4 in)
1364 1364
 	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
1365 1365
 	mat3 out, nanout;
1366 1366
 	float DET;
1367
-
1367
+	
1368 1368
 	// Copying to internal variables
1369 1369
 	a11 = in.m[0];
1370 1370
 	a12 = in.m[1];
... ...
@@ -1404,7 +1404,7 @@ mat3 InverseTranspose(mat4 in)
1404 1404
 mat3 mat4tomat3(mat4 m)
1405 1405
 {
1406 1406
 	mat3 result;
1407
-
1407
+	
1408 1408
 	result.m[0] = m.m[0];
1409 1409
 	result.m[1] = m.m[1];
1410 1410
 	result.m[2] = m.m[2];
... ...
@@ -1420,7 +1420,7 @@ mat3 mat4tomat3(mat4 m)
1420 1420
 mat4 mat3tomat4(mat3 m)
1421 1421
 {
1422 1422
 	mat4 result;
1423
-
1423
+	
1424 1424
 	result.m[0] = m.m[0];
1425 1425
 	result.m[1] = m.m[1];
1426 1426
 	result.m[2] = m.m[2];
... ...
@@ -1467,7 +1467,7 @@ vec4 vec3tovec4(vec3 v)
1467 1467
 mat4 InvertMat4(mat4 a)
1468 1468
 {
1469 1469
    mat4 b;
1470
-
1470
+     
1471 1471
    float c=a.m[0],d=a.m[1],e=a.m[2],g=a.m[3],
1472 1472
 	f=a.m[4],h=a.m[5],i=a.m[6],j=a.m[7],
1473 1473
 	k=a.m[8],l=a.m[9],o=a.m[10],m=a.m[11],
... ...
@@ -1533,7 +1533,7 @@ void printMat3(mat3 m)
1533 1533
 	printf(" ---------------------------------------------------------------\n");
1534 1534
 }
1535 1535
 
1536
-void printVec3(vec3 in)
1536
+void printVec3(vec3 in) 
1537 1537
 {
1538 1538
 	printf("(%f, %f, %f)\n", in.x, in.y, in.z);
1539 1539
 }
... ...
@@ -1558,7 +1558,7 @@ static void ReportError(const char *caller, const char *name)
1558 1558
 	}
1559 1559
 }
1560 1560
 
1561
-void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m)
1561
+void uploadMat4ToShader(GLuint shader, const char *nameInShader, mat4 m)
1562 1562
 {
1563 1563
 	if (nameInShader == NULL) return;
1564 1564
 	glUseProgram(shader);
... ...
@@ -1569,7 +1569,7 @@ void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m)
1569 1569
 		ReportError("uploadMat4ToShader", nameInShader);
1570 1570
 }
1571 1571
 
1572
-void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i)
1572
+void uploadUniformIntToShader(GLuint shader, const char *nameInShader, GLint i)
1573 1573
 {
1574 1574
 	if (nameInShader == NULL) return;
1575 1575
 	glUseProgram(shader);
... ...
@@ -1580,7 +1580,7 @@ void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i)
1580 1580
 		ReportError("uploadUniformIntToShader", nameInShader);
1581 1581
 }
1582 1582
 
1583
-void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f)
1583
+void uploadUniformFloatToShader(GLuint shader, const char *nameInShader, GLfloat f)
1584 1584
 {
1585 1585
 	if (nameInShader == NULL) return;
1586 1586
 	glUseProgram(shader);
... ...
@@ -1591,7 +1591,7 @@ void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f)
1591 1591
 		ReportError("uploadUniformFloatToShader", nameInShader);
1592 1592
 }
1593 1593
 
1594
-void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength)
1594
+void uploadUniformFloatArrayToShader(GLuint shader, const char *nameInShader, GLfloat *f, int arrayLength)
1595 1595
 {
1596 1596
 	if (nameInShader == NULL) return;
1597 1597
 	glUseProgram(shader);
... ...
@@ -1602,7 +1602,7 @@ void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat
1602 1602
 		ReportError("uploadUniformFloatToShader", nameInShader);
1603 1603
 }
1604 1604
 
1605
-void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v)
1605
+void uploadUniformVec3ToShader(GLuint shader, const char *nameInShader, vec3 v)
1606 1606
 {
1607 1607
 	if (nameInShader == NULL) return;
1608 1608
 	glUseProgram(shader);
... ...
@@ -1613,7 +1613,7 @@ void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v)
1613 1613
 		ReportError("uploadUniformVec3ToShader", nameInShader);
1614 1614
 }
1615 1615
 
1616
-void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength)
1616
+void uploadUniformVec3ArrayToShader(GLuint shader, const char *nameInShader, vec3 *a, int arrayLength)
1617 1617
 {
1618 1618
 	if (nameInShader == NULL) return;
1619 1619
 	glUseProgram(shader);
... ...
@@ -1658,5 +1658,4 @@ mat4 lookAt(vec3 p, vec3 l, vec3 u)
1658 1658
 
1659 1659
 #endif
1660 1660
 #endif
1661
-
1662 1661
 #endif
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
... ...
@@ -73,7 +73,7 @@
73 73
 // 170331: Added stdio.h for printMat4 and printVec3
74 74
 // 180314: Added some #defines for moving closer to GLSL (dot, cross...).
75 75
 // 2021-05-15: Constructors for vec3 etc replaced in order to avoid
76
-// problems with some C++ compilers.
76
+// problems with some C++ compilers.
77 77
 // 2022-11-10: Corrected an ifdef that could cause problems.
78 78
 
79 79
 // 2022-05-05: Created VectorUtils4, now only a header file!
... ...
@@ -352,6 +352,18 @@
352 352
 	void printMat4(mat4 m);
353 353
 	void printVec3(vec3 in);
354 354
 
355
+/* Utility functions for easier uploads to shaders with error messages. */
356
+// NEW as prototype 2022, added to VU 2023
357
+/*
358
+	void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m);
359
+	void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i);
360
+	void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f);
361
+	void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength);
362
+	void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v);
363
+	void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength);
364
+	void bindTextureToTextureUnit(GLuint tex, int unit);
365
+*/
366
+
355 367
 #ifdef __cplusplus
356 368
 // Convenient overloads for C++, closer to GLSL
357 369
 	mat3 inverse(mat3 m);
... ...
@@ -547,7 +559,7 @@ vec3 operator*(const mat3 &a, const vec3 &b)
547 559
 // ********** implementation section ************
548 560
 
549 561
 #ifdef MAIN
550
-//#ifndef VECTOR_UTILS_IMPLEMENTATION
562
+//#ifndef VECTOR_UTILS_IMPLEMENTATION
551 563
 //#define VECTOR_UTILS_IMPLEMENTATION
552 564
 
553 565
 // VS doesn't define NAN properly
... ...
@@ -1526,6 +1538,98 @@ void printVec3(vec3 in)
1526 1538
 	printf("(%f, %f, %f)\n", in.x, in.y, in.z);
1527 1539
 }
1528 1540
 
1541
+/* Utility functions for easier uploads to shaders with error messages. */
1542
+// NEW as prototype 2022, added to VU 2023
1543
+
1544
+#define NUM_ERRORS 8
1545
+
1546
+static void ReportError(const char *caller, const char *name)
1547
+{
1548
+	static unsigned int draw_error_counter = 0; 
1549
+	if(draw_error_counter < NUM_ERRORS)
1550
+	{
1551
+		fprintf(stderr, "%s warning: '%s' not found in shader!\n", caller, name);
1552
+		draw_error_counter++;
1553
+	}
1554
+	else if(draw_error_counter == NUM_ERRORS)
1555
+	{
1556
+		fprintf(stderr, "%s: Number of errors bigger than %i. No more vill be printed.\n", caller, NUM_ERRORS);
1557
+		draw_error_counter++;
1558
+	}
1559
+}
1560
+
1561
+void uploadMat4ToShader(GLuint shader, char *nameInShader, mat4 m)
1562
+{
1563
+	if (nameInShader == NULL) return;
1564
+	glUseProgram(shader);
1565
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1566
+	if (loc >= 0)
1567
+		glUniformMatrix4fv(loc, 1, GL_TRUE, m.m);
1568
+	else
1569
+		ReportError("uploadMat4ToShader", nameInShader);
1570
+}
1571
+
1572
+void uploadUniformIntToShader(GLuint shader, char *nameInShader, GLint i)
1573
+{
1574
+	if (nameInShader == NULL) return;
1575
+	glUseProgram(shader);
1576
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1577
+	if (loc >= 0)
1578
+		glUniform1i(loc, i);
1579
+	else
1580
+		ReportError("uploadUniformIntToShader", nameInShader);
1581
+}
1582
+
1583
+void uploadUniformFloatToShader(GLuint shader, char *nameInShader, GLfloat f)
1584
+{
1585
+	if (nameInShader == NULL) return;
1586
+	glUseProgram(shader);
1587
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1588
+	if (loc >= 0)
1589
+		glUniform1f(loc, f);
1590
+	else
1591
+		ReportError("uploadUniformFloatToShader", nameInShader);
1592
+}
1593
+
1594
+void uploadUniformFloatArrayToShader(GLuint shader, char *nameInShader, GLfloat *f, int arrayLength)
1595
+{
1596
+	if (nameInShader == NULL) return;
1597
+	glUseProgram(shader);
1598
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1599
+	if (loc >= 0)
1600
+		glUniform1fv(loc, arrayLength, f);
1601
+	else
1602
+		ReportError("uploadUniformFloatToShader", nameInShader);
1603
+}
1604
+
1605
+void uploadUniformVec3ToShader(GLuint shader, char *nameInShader, vec3 v)
1606
+{
1607
+	if (nameInShader == NULL) return;
1608
+	glUseProgram(shader);
1609
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1610
+	if (loc >= 0)
1611
+		glUniform3f(loc, v.x, v.y, v.z);
1612
+	else
1613
+		ReportError("uploadUniformVec3ToShader", nameInShader);
1614
+}
1615
+
1616
+void uploadUniformVec3ArrayToShader(GLuint shader, char *nameInShader, vec3 *a, int arrayLength)
1617
+{
1618
+	if (nameInShader == NULL) return;
1619
+	glUseProgram(shader);
1620
+	GLint loc = glGetUniformLocation(shader, nameInShader);
1621
+	if (loc >= 0)
1622
+		glUniform3fv(loc, arrayLength, (GLfloat *)a);
1623
+	else
1624
+		ReportError("uploadUniformVec3ArrayToShader", nameInShader);
1625
+}
1626
+
1627
+void bindTextureToTextureUnit(GLuint tex, int unit)
1628
+{
1629
+	glActiveTexture(GL_TEXTURE0 + unit);
1630
+	glBindTexture(GL_TEXTURE_2D, tex);
1631
+}
1632
+
1529 1633
 #ifdef __cplusplus
1530 1634
 mat3 inverse(mat3 m)
1531 1635
 {
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,1558 @@
1
+// VectorUtils4, header only version!
2
+// You must define MAIN in only one file (typically the main
3
+// program) in order to only complile the implementation section once!
4
+// The #define must be BEFORE the "include of this file!
5
+
6
+// VectorUtils
7
+// Vector and matrix manipulation library for OpenGL, a package of the most essential functions.
8
+// This is intended as a mini version of GLM.
9
+// Includes:
10
+// - Basic vector operations: Add, subtract, scale, dot product, cross product.
11
+// - Basic matrix operations: Multiply matrix to matrix, matric to vector, transpose.
12
+// - Creation of transformation matrixces: Translation, scaling, rotation.
13
+// - A few more special operations: Orthonormalizaton of a matrix, CrossMatrix,
14
+// - Replacements of some GLU functions: lookAt, frustum, perspective.
15
+// - Inverse and inverse transpose for creating normal matrices.
16
+// Supports both C and C++. The C interface makes it accessible from most languages if desired.
17
+
18
+// A note on completeness:
19
+// All operations may not be 100% symmetrical over all types, and some GLSL types are
20
+// missing (like vec2). These will be added if proven important. There are already
21
+// some calls of minor importance (mat3 * mat3, mat3 * vec3) included only for
22
+// symmetry. I don't want the code to grow a lot for such reasons, I want it to be
23
+// compact and to the point.
24
+
25
+// Current open design questions:
26
+// Naming conventions: Lower case or capitalized? (Frustum/frustum)
27
+// Prefix for function calls? (The cost would be more typing and making the code harder to read.)
28
+// Add vector operations for vec4? Other *essential* symmetry issues?
29
+// Names for functions when supporting both vec3 and vec4, mat3 and mat4? (vec3Add, vec4Add?)
30
+
31
+
32
+// History:
33
+
34
+// VectorUtils is a small (but growing) math unit by Ingemar Ragnemalm.
35
+// It originated as "geom3d" by Andrew Meggs, but that unit is no more
36
+// than inspiration today. The original VectorUtils(1) was based on it,
37
+// while VectorUtils2 was a rewrite primarily to get rid of the over-use
38
+// of arrays in the original.
39
+
40
+// New version 120201:
41
+// Defaults to matrices "by the book". Can also be configured to the flipped
42
+// column-wise matrices that old OpenGL required (and we all hated).
43
+// This is freshly implemented, limited testing, so there can be bugs.
44
+// But it seems to work just fine on my tests with translation, rotations
45
+// and matrix multiplications.
46
+
47
+// 1208??: Added lookAt, perspective, frustum
48
+// Also made Transpose do what it should. TransposeRotation is the old function.
49
+// 120913: Fixed perspective. Never trust other's code...
50
+// 120925: Transposing in CrossMatrix
51
+// 121119: Fixed one more glitch in perspective.
52
+
53
+// 130227 First draft to a version 3.
54
+// C++ operators if accessed from C++
55
+// Vectors by value when possible. Return values on the stack.
56
+// (Why was this not the case in VectorUtils2? Beause I tried to stay compatible
57
+// with an old C compiler. Older C code generally prefers all non-scalar data by
58
+// reference. But I'd like to move away from that now.)
59
+// Types conform with GLSL as much as possible (vec3, mat4)
60
+// Added some operations for mat3 and vec4, but most of them are more for
61
+// completeness than usefulness; I find vec3's and mat4's to be what I use
62
+// most of the time.
63
+// Also added InvertMat3 and InversTranspose to support creation of normal matrices.
64
+// Marked some calls for removal: CopyVector, TransposeRotation, CopyMatrix.
65
+// 130308: Added InvertMat4 and some more vec3/vec4 operators (+= etc)
66
+// 130922: Fixed a vital bug in CrossMatrix.
67
+// 130924: Fixed a bug in mat3tomat4.
68
+// 131014: Added TransposeMat3 (although I doubt its importance)
69
+// 140213: Corrected mat3tomat4. (Were did the correction in 130924 go?)
70
+// 151210: Added printMat4 and printVec3.
71
+// 160302: Added empty constuctors for vec3 and vec4.
72
+// 170221: Uses _WIN32 instead of WIN32
73
+// 170331: Added stdio.h for printMat4 and printVec3
74
+// 180314: Added some #defines for moving closer to GLSL (dot, cross...).
75
+// 2021-05-15: Constructors for vec3 etc replaced in order to avoid
76
+// problems with some C++ compilers.
77
+// 2022-11-10: Corrected an ifdef that could cause problems.
78
+
79
+// 2022-05-05: Created VectorUtils4, now only a header file!
80
+// You must define MAIN in only one file (typically the main
81
+// program) in order to only complile the implementation section once!
82
+// This means:
83
+// + Only ONE file
84
+// + I can now safely re-introduce the constructors again!
85
+// + I can move closer to GLM and GLSL syntax
86
+// - You must #define MAIN in the main program
87
+// This means that VectorUtils can still be used from C and thereby many other languages,
88
+// while taking more advantage of C++ features when using C++.
89
+// 20220525: Revised perpective() to conform with the reference manual as well as GLM. (But it went wrong, why?)
90
+// 2022-08-29: Renamed Transpose to transpose to conform better with GLSL. Corrected perspective.
91
+
92
+// You may use VectorUtils as you please. A reference to the origin is appreciated
93
+// but if you grab some snippets from it without reference... no problem.
94
+
95
+// VectorUtils3 header
96
+// See source for more information
97
+
98
+#ifndef VECTORUTILS4
99
+#define VECTORUTILS4
100
+
101
+#ifdef __APPLE__
102
+	#define GL_SILENCE_DEPRECATION
103
+	#include <OpenGL/gl3.h>
104
+#else
105
+	#if defined(_WIN32)
106
+		#include "glew.h"
107
+	#endif
108
+	#include <GL/gl.h>
109
+#endif
110
+#include <math.h>
111
+#include <stdio.h>
112
+
113
+
114
+#ifndef M_PI
115
+#define M_PI           3.14159265358979323846
116
+#endif
117
+
118
+// Really old type names
119
+#define Vector3f Point3D
120
+#define Matrix3f Matrix3D
121
+#define Matrix4f Matrix4D
122
+
123
+// GLSL-style
124
+// These are already changed, here I define the intermediate type names that I use in some demos.
125
+#define Point3D vec3
126
+#define Matrix3D mat3
127
+#define Matrix4D mat4
128
+#define DotProduct dot
129
+#define CrossProduct cross
130
+#define Normalize normalize
131
+#define Transpose transpose
132
+// Furthermore, SplitVector should be revised to conform with reflect()
133
+
134
+// Note 210515: I have removed the constructors from my structs below in order to please
135
+// some compilers. They did work but the compilers were upset about C using these
136
+// without knowing about the constructors, while the C++ code happily used them.
137
+// However, we do not need them; you can initialize with SetVec* instead of
138
+// vec*() and it will work.
139
+// Note 2022: These are now back (and more), which is possible when doing this as a header only unit.
140
+
141
+	typedef struct vec4 vec4;
142
+
143
+	// vec3 is very useful
144
+	typedef struct vec3
145
+	{
146
+//		GLfloat x, y, z;
147
+		union
148
+		{GLfloat x; GLfloat r;};
149
+		union
150
+		{GLfloat y; GLfloat g;};
151
+		union
152
+		{GLfloat z; GLfloat b;};
153
+		#ifdef __cplusplus
154
+            vec3() {}
155
+			vec3(GLfloat x2, GLfloat y2, GLfloat z2) : x(x2), y(y2), z(z2) {}
156
+			vec3(GLfloat x2) : x(x2), y(x2), z(x2) {}
157
+//			vec3(vec4 v) : x(v.x), y(v.y), z(v.z) {}
158
+			vec3(vec4 v);
159
+		#endif
160
+	} vec3, *vec3Ptr;
161
+
162
+	// vec4 is not as useful. Can be a color with alpha, or a quaternion, but IMHO you
163
+	// rarely need homogenous coordinate vectors on the CPU.
164
+	typedef struct vec4
165
+	{
166
+//		GLfloat x, y, z, w; // w or h
167
+		union
168
+		{GLfloat x; GLfloat r;};
169
+		union
170
+		{GLfloat y; GLfloat g;};
171
+		union
172
+		{GLfloat z; GLfloat b;};
173
+		union
174
+		{GLfloat h; GLfloat w; GLfloat a;};
175
+		#ifdef __cplusplus
176
+            vec4() {}
177
+			vec4(GLfloat x2, GLfloat y2, GLfloat z2, GLfloat w2) : x(x2), y(y2), z(z2), w(w2) {}
178
+			vec4(GLfloat xyz, GLfloat w2) : x(xyz), y(xyz), z(xyz), w(w2) {}
179
+			vec4(vec3 v, GLfloat w2) : x(v.x), y(v.y), z(v.z), w(w2) {}
180
+			vec4(vec3 v) : x(v.x), y(v.y), z(v.z), w(1) {}
181
+		#endif
182
+	} vec4, *vec4Ptr;
183
+
184
+// vec2 is mostly used for texture cordinates, so I havn't bothered defining any operations for it
185
+	typedef struct vec2
186
+	{
187
+//		GLfloat x, y;
188
+		union
189
+		{GLfloat x; GLfloat s;};
190
+		union
191
+		{GLfloat y; GLfloat t;};
192
+
193
+		#ifdef __cplusplus
194
+            vec2() {}
195
+			vec2(GLfloat x2, GLfloat y2) : x(x2), y(y2) {}
196
+		#endif
197
+	} vec2, *vec2Ptr;
198
+
199
+	typedef struct mat3 mat3;
200
+	typedef struct mat4
201
+	{
202
+		GLfloat m[16];
203
+		#ifdef __cplusplus
204
+            mat4() {}
205
+			mat4(GLfloat x2)
206
+			{
207
+				m[0] = x2; m[1] = 0; m[2] = 0; m[3] = 0;
208
+				m[4] = 0; m[5] = x2; m[6] = 0; m[7] = 0;
209
+				m[8] = 0; m[9] = 0; m[10] = x2; m[11] = 0;
210
+				m[12] = 0; m[13] = 0; m[14] = 0; m[15] = x2;
211
+			}
212
+			mat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
213
+				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
214
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
215
+				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15)
216
+			{
217
+				m[0] = p0; m[1] = p1; m[2] = p2; m[3] = p3;
218
+				m[4] = p4; m[5] = p5; m[6] = p6; m[7] = p7;
219
+				m[8] = p8; m[9] = p9; m[10] = p10; m[11] = p11;
220
+				m[12] = p12; m[13] = p13; m[14] = p14; m[15] = p15;
221
+			}
222
+			mat4(mat3 x);
223
+		#endif
224
+	} mat4;
225
+	typedef struct mat3
226
+	{
227
+		GLfloat m[9];
228
+		#ifdef __cplusplus
229
+            mat3() {}
230
+			mat3(GLfloat x2)
231
+			{
232
+				m[0] = x2; m[1] = 0; m[2] = 0;
233
+				m[3] = 0; m[4] = x2; m[5] = 0;
234
+				m[6] = 0; m[7] = 0; m[8] = x2;
235
+			}
236
+			mat3(GLfloat p0, GLfloat p1, GLfloat p2,
237
+				GLfloat p3, GLfloat p4, GLfloat p5,
238
+				GLfloat p6, GLfloat p7, GLfloat p8)
239
+			{
240
+				m[0] = p0; m[1] = p1; m[2] = p2;
241
+				m[3] = p3; m[4] = p4; m[5] = p5;
242
+				m[6] = p6; m[7] = p7; m[8] = p8;
243
+			}
244
+			mat3(mat4 x)
245
+			{
246
+				m[0] = x.m[0]; m[1] = x.m[1]; m[2] = x.m[2];
247
+				m[3] = x.m[4]; m[4] = x.m[5]; m[5] = x.m[6];
248
+				m[6] = x.m[8]; m[7] = x.m[9]; m[8] = x.m[10];
249
+			}
250
+			mat3(vec3 x1, vec3 x2, vec3 x3)
251
+			{
252
+				m[0] = x1.x; m[1] = x1.y; m[2] = x1.z;
253
+				m[3] = x2.x; m[4] = x2.y; m[5] = x2.z;
254
+				m[6] = x3.x; m[7] = x3.y; m[8] = x3.z;
255
+			}
256
+		#endif
257
+	} mat3;
258
+
259
+#ifdef __cplusplus
260
+	vec3::vec3(vec4 v) : x(v.x), y(v.y), z(v.z) {}
261
+	mat4::mat4(mat3 x)
262
+	{
263
+		m[0] = x.m[0]; m[1] = x.m[1]; m[2] = x.m[2]; m[3] = 0;
264
+		m[4] = x.m[3]; m[5] = x.m[4]; m[6] = x.m[5]; m[7] = 0;
265
+		m[8] = x.m[6]; m[9] = x.m[7]; m[10] = x.m[8]; m[11] = 0;
266
+		m[12] = x.m[0]; m[13] = x.m[0]; m[14] = x.m[0]; m[15] = 1;
267
+	}
268
+#endif
269
+
270
+//#ifdef __cplusplus
271
+//extern "C" {
272
+//#endif
273
+
274
+// New better name for SetVector and replacements for constructors
275
+	vec2 SetVec2(GLfloat x, GLfloat y);
276
+	vec3 SetVec3(GLfloat x, GLfloat y, GLfloat z);
277
+	vec4 SetVec4(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
278
+
279
+	vec3 SetVector(GLfloat x, GLfloat y, GLfloat z);
280
+	mat3 SetMat3(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7, GLfloat p8);
281
+	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
282
+				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
283
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
284
+				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
285
+				);
286
+// Basic vector operations on vec3's. (vec4 not included since I never need them.)
287
+// Note: C++ users can also use operator overloading, defined below.
288
+	vec3 VectorSub(vec3 a, vec3 b);
289
+	vec3 VectorAdd(vec3 a, vec3 b);
290
+	vec3 cross(vec3 a, vec3 b);
291
+	GLfloat dot(vec3 a, vec3 b);
292
+	vec3 ScalarMult(vec3 a, GLfloat s);
293
+	GLfloat Norm(vec3 a);
294
+	vec3 normalize(vec3 a);
295
+	vec3 CalcNormalVector(vec3 a, vec3 b, vec3 c);
296
+	void SplitVector(vec3 v, vec3 n, vec3 *vn, vec3 *vp);
297
+
298
+// Matrix operations primarily on 4x4 matrixes!
299
+// Row-wise by default but can be configured to column-wise (see SetTransposed)
300
+
301
+	mat4 IdentityMatrix();
302
+	mat4 Rx(GLfloat a);
303
+	mat4 Ry(GLfloat a);
304
+	mat4 Rz(GLfloat a);
305
+	mat4 T(GLfloat tx, GLfloat ty, GLfloat tz);
306
+	mat4 S(GLfloat sx, GLfloat sy, GLfloat sz);
307
+	mat4 Mult(mat4 a, mat4 b); // dest = a * b - rename to MultMat4 considered but I don't like to make the name of the most common operation longer
308
+	// but for symmetry, MultMat4 is made a synonym:
309
+	#define MultMat4 Mult
310
+
311
+	vec3 MultVec3(mat4 a, vec3 b); // result = a * b
312
+	vec4 MultVec4(mat4 a, vec4 b);
313
+
314
+// Mat3 operations (new)
315
+	mat3 MultMat3(mat3 a, mat3 b); // m = a * b
316
+	vec3 MultMat3Vec3(mat3 a, vec3 b); // result = a * b
317
+
318
+	void OrthoNormalizeMatrix(mat4 *R);
319
+	mat4 transpose(mat4 m);
320
+	mat3 TransposeMat3(mat3 m);
321
+	mat4 ArbRotate(vec3 axis, GLfloat fi);
322
+	mat4 CrossMatrix(vec3 a);
323
+	mat4 MatrixAdd(mat4 a, mat4 b);
324
+
325
+// Configure, i.e. if you want matrices to be column-wise
326
+	void SetTransposed(char t);
327
+
328
+// GLU replacement functions
329
+	mat4 lookAtv(vec3 p, vec3 l, vec3 v);
330
+	mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz,
331
+			GLfloat lx, GLfloat ly, GLfloat lz,
332
+			GLfloat vx, GLfloat vy, GLfloat vz);
333
+	mat4 perspective(float fovyInDegrees, float aspectRatio,
334
+                      float znear, float zfar);
335
+	mat4 frustum(float left, float right, float bottom, float top,
336
+                  float znear, float zfar);
337
+	mat4 ortho(GLfloat left, GLfloat right, GLfloat bottom,
338
+			GLfloat top, GLfloat near, GLfloat far);
339
+
340
+// For creating a normal matrix
341
+	mat3 InvertMat3(mat3 in);
342
+	mat3 InverseTranspose(mat4 in);
343
+	mat4 InvertMat4(mat4 a);
344
+
345
+// Simple conversions
346
+	mat3 mat4tomat3(mat4 m);
347
+	mat4 mat3tomat4(mat3 m);
348
+	vec3 vec4tovec3(vec4 v);
349
+	vec4 vec3tovec4(vec3 v);
350
+
351
+// Convenient printing calls
352
+	void printMat4(mat4 m);
353
+	void printVec3(vec3 in);
354
+
355
+#ifdef __cplusplus
356
+// Convenient overloads for C++, closer to GLSL
357
+	mat3 inverse(mat3 m);
358
+	mat4 inverse(mat4 m);
359
+	mat3 transpose(mat3 m);
360
+	mat4 S(GLfloat s);
361
+	mat4 S(vec3 s);
362
+	mat4 lookAt(vec3 p, vec3 l, vec3 u);
363
+#endif
364
+
365
+//#ifdef __cplusplus
366
+//}
367
+//#endif
368
+
369
+#ifdef __cplusplus
370
+// Some C++ operator overloads
371
+// Non-member C++ operators!
372
+// New version 2021-05-2x: Constructiors for vec3 etc replaced in order to avoid
373
+// problems with some C++ compilers.
374
+
375
+// --- vec3 operations ---
376
+inline
377
+vec3 operator+(const vec3 &a, const vec3 &b) // vec3+vec3
378
+{
379
+	return SetVector(a.x+b.x, a.y+b.y, a.z+b.z);
380
+}
381
+
382
+inline
383
+vec3 operator-(const vec3 &a, const vec3 &b) // vec3-vec3
384
+{
385
+	return SetVector(a.x-b.x, a.y-b.y, a.z-b.z);
386
+}
387
+
388
+inline
389
+vec3 operator-(const vec3 &a)
390
+{
391
+		return SetVector(-a.x, -a.y, -a.z);
392
+}
393
+
394
+	// Questionable, not like GLSL
395
+inline
396
+float operator*(const vec3 &a, const vec3 &b) // vec3 dot vec3
397
+{
398
+	return (a.x*b.x+ a.y*b.y+ a.z*b.z);
399
+}
400
+
401
+inline
402
+vec3 operator*(const vec3 &b, double a) // vec3 * scalar
403
+{
404
+	return SetVector(a*b.x, a*b.y, a*b.z);
405
+}
406
+
407
+inline
408
+vec3 operator*(double a, const vec3 &b) // scalar * vec3
409
+{
410
+	return SetVector(a*b.x, a*b.y, a*b.z);
411
+}
412
+
413
+inline
414
+vec3 operator/(const vec3 &b, double a) // vec3 / scalar
415
+{
416
+	return SetVector(b.x/a, b.y/a, b.z/a);
417
+}
418
+
419
+inline
420
+void operator+=(vec3 &a, const vec3 &b) // vec3+=vec3
421
+{
422
+	a = a + b;
423
+}
424
+
425
+inline
426
+void operator-=(vec3 &a, const vec3 &b) // vec3-=vec3
427
+{
428
+	a = a - b;
429
+}
430
+
431
+inline
432
+void operator*=(vec3 &a, const float &b) // vec3*=scalar
433
+{
434
+	a = a * b;
435
+}
436
+
437
+inline
438
+void operator/=(vec3 &a, const float &b) // vec3/=scalar
439
+{
440
+	a = a / b;
441
+}
442
+
443
+// --- vec4 operations ---
444
+
445
+inline
446
+vec4 operator+(const vec4 &a, const vec4 &b) // vec4+vec4
447
+{
448
+	return SetVec4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
449
+}
450
+
451
+inline
452
+vec4 operator-(const vec4 &a, const vec4 &b) // vec4-vec4
453
+{
454
+	return SetVec4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
455
+}
456
+
457
+	// Questionable, not like GLSL
458
+inline
459
+float operator*(const vec4 &a, const vec4 &b) // vec4 dot vec4
460
+{
461
+	return (a.x*b.x+ a.y*b.y+ a.z*b.z+ a.w*b.w);
462
+}
463
+
464
+inline
465
+vec4 operator*(const vec4 &b, double a) // vec4 * scalar
466
+{
467
+	return SetVec4(a*b.x, a*b.y, a*b.z, a*b.w);
468
+}
469
+
470
+inline
471
+vec4 operator*(double a, const vec4 &b) // scalar * vec4
472
+{
473
+	return SetVec4(a*b.x, a*b.y, a*b.z, a*b.w);
474
+}
475
+
476
+inline
477
+vec4 operator/(const vec4 &b, double a) // vec4 / scalar
478
+{
479
+	return SetVec4(b.x/a, b.y/a, b.z/a, b.w/a);
480
+}
481
+
482
+
483
+inline
484
+void operator+=(vec4 &a, const vec4 &b) // vec4+=vec4
485
+{
486
+	a = a + b;
487
+}
488
+
489
+inline
490
+void operator-=(vec4 &a, const vec4 &b) // vec4-=vec4
491
+{
492
+	a = a - b;
493
+}
494
+
495
+inline
496
+void operator*=(vec4 &a, const float &b) // vec4 *= scalar
497
+{
498
+	a = a * b;
499
+}
500
+
501
+inline
502
+void operator/=(vec4 &a, const float &b) // vec4 /= scalar
503
+{
504
+	a = a / b;
505
+}
506
+
507
+// --- Matrix multiplication ---
508
+
509
+// mat4 * mat4
510
+inline
511
+mat4 operator*(const mat4 &a, const mat4 &b)
512
+{
513
+	return (Mult(a, b));
514
+}
515
+
516
+// mat3 * mat3
517
+inline
518
+mat3 operator*(const mat3 &a, const mat3 &b)
519
+{
520
+	return (MultMat3(a, b));
521
+}
522
+
523
+// mat4 * vec3
524
+inline
525
+vec3 operator*(const mat4 &a, const vec3 &b)
526
+{
527
+	return MultVec3(a, b); // result = a * b
528
+}
529
+
530
+// mat4 * vec4
531
+inline
532
+vec4 operator*(const mat4 &a, const vec4 &b)
533
+{
534
+	return MultVec4(a, b); // result = a * b
535
+}
536
+
537
+// mat3 * vec3
538
+inline
539
+vec3 operator*(const mat3 &a, const vec3 &b)
540
+{
541
+	return MultMat3Vec3(a, b); // result = a * b
542
+}
543
+
544
+#endif
545
+//#endif
546
+
547
+// ********** implementation section ************
548
+
549
+#ifdef MAIN
550
+//#ifndef VECTOR_UTILS_IMPLEMENTATION
551
+//#define VECTOR_UTILS_IMPLEMENTATION
552
+
553
+// VS doesn't define NAN properly
554
+#ifdef _WIN32
555
+    #ifndef NAN
556
+        static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
557
+        #define NAN (*(const float *) __nan)
558
+    #endif
559
+#endif
560
+
561
+char transposed = 0;
562
+
563
+	vec3 SetVector(GLfloat x, GLfloat y, GLfloat z)
564
+	{
565
+		vec3 v;
566
+
567
+		v.x = x;
568
+		v.y = y;
569
+		v.z = z;
570
+		return v;
571
+	}
572
+
573
+// New better name
574
+	vec2 SetVec2(GLfloat x, GLfloat y)
575
+	{
576
+		vec2 v;
577
+
578
+		v.x = x;
579
+		v.y = y;
580
+		return v;
581
+	}
582
+
583
+	vec3 SetVec3(GLfloat x, GLfloat y, GLfloat z)
584
+	{
585
+		vec3 v;
586
+
587
+		v.x = x;
588
+		v.y = y;
589
+		v.z = z;
590
+		return v;
591
+	}
592
+
593
+	vec4 SetVec4(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
594
+	{
595
+		vec4 v;
596
+
597
+		v.x = x;
598
+		v.y = y;
599
+		v.z = z;
600
+		v.w = w;
601
+		return v;
602
+	}
603
+
604
+// Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
605
+	mat3 SetMat3(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3, GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7, GLfloat p8)
606
+	{
607
+		mat3 m;
608
+		m.m[0] = p0;
609
+		m.m[1] = p1;
610
+		m.m[2] = p2;
611
+		m.m[3] = p3;
612
+		m.m[4] = p4;
613
+		m.m[5] = p5;
614
+		m.m[6] = p6;
615
+		m.m[7] = p7;
616
+		m.m[8] = p8;
617
+		return m;
618
+	}
619
+
620
+// Like above; Modern C doesn't need this, but Visual Studio insists on old-fashioned C and needs this.
621
+	mat4 SetMat4(GLfloat p0, GLfloat p1, GLfloat p2, GLfloat p3,
622
+				GLfloat p4, GLfloat p5, GLfloat p6, GLfloat p7,
623
+				GLfloat p8, GLfloat p9, GLfloat p10, GLfloat p11,
624
+				GLfloat p12, GLfloat p13, GLfloat p14, GLfloat p15
625
+				)
626
+	{
627
+		mat4 m;
628
+		m.m[0] = p0;
629
+		m.m[1] = p1;
630
+		m.m[2] = p2;
631
+		m.m[3] = p3;
632
+		m.m[4] = p4;
633
+		m.m[5] = p5;
634
+		m.m[6] = p6;
635
+		m.m[7] = p7;
636
+		m.m[8] = p8;
637
+		m.m[9] = p9;
638
+		m.m[10] = p10;
639
+		m.m[11] = p11;
640
+		m.m[12] = p12;
641
+		m.m[13] = p13;
642
+		m.m[14] = p14;
643
+		m.m[15] = p15;
644
+		return m;
645
+	}
646
+
647
+
648
+	// vec3 operations
649
+	// vec4 operations can easily be added but I havn't seen much need for them.
650
+	// Some are defined as C++ operators though.
651
+
652
+	vec3 VectorSub(vec3 a, vec3 b)
653
+	{
654
+		vec3 result;
655
+
656
+		result.x = a.x - b.x;
657
+		result.y = a.y - b.y;
658
+		result.z = a.z - b.z;
659
+		return result;
660
+	}
661
+
662
+	vec3 VectorAdd(vec3 a, vec3 b)
663
+	{
664
+		vec3 result;
665
+
666
+		result.x = a.x + b.x;
667
+		result.y = a.y + b.y;
668
+		result.z = a.z + b.z;
669
+		return result;
670
+	}
671
+
672
+	vec3 cross(vec3 a, vec3 b)
673
+	{
674
+		vec3 result;
675
+
676
+		result.x = a.y*b.z - a.z*b.y;
677
+		result.y = a.z*b.x - a.x*b.z;
678
+		result.z = a.x*b.y - a.y*b.x;
679
+
680
+		return result;
681
+	}
682
+
683
+	GLfloat dot(vec3 a, vec3 b)
684
+	{
685
+		return a.x * b.x + a.y * b.y + a.z * b.z;
686
+	}
687
+
688
+	vec3 ScalarMult(vec3 a, GLfloat s)
689
+	{
690
+		vec3 result;
691
+
692
+		result.x = a.x * s;
693
+		result.y = a.y * s;
694
+		result.z = a.z * s;
695
+
696
+		return result;
697
+	}
698
+
699
+	GLfloat Norm(vec3 a)
700
+	{
701
+		GLfloat result;
702
+
703
+		result = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
704
+		return result;
705
+	}
706
+
707
+	vec3 normalize(vec3 a)
708
+	{
709
+		GLfloat norm;
710
+		vec3 result;
711
+
712
+		norm = (GLfloat)sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
713
+		result.x = a.x / norm;
714
+		result.y = a.y / norm;
715
+		result.z = a.z / norm;
716
+		return result;
717
+	}
718
+
719
+	vec3 CalcNormalVector(vec3 a, vec3 b, vec3 c)
720
+	{
721
+		vec3 n;
722
+
723
+		n = cross(VectorSub(a, b), VectorSub(a, c));
724
+		n = ScalarMult(n, 1/Norm(n));
725
+
726
+		return n;
727
+	}
728
+
729
+// Splits v into vn (parallell to n) and vp (perpendicular). Does not demand n to be normalized.
730
+	void SplitVector(vec3 v, vec3 n, vec3 *vn, vec3 *vp)
731
+	{
732
+		GLfloat nlen;
733
+		GLfloat nlen2;
734
+
735
+		nlen = DotProduct(v, n);
736
+		nlen2 = n.x*n.x+n.y*n.y+n.z*n.z; // Squared length
737
+		if (nlen2 == 0)
738
+		{
739
+			*vp = v;
740
+			*vn = SetVector(0, 0, 0);
741
+		}
742
+		else
743
+		{
744
+			*vn = ScalarMult(n, nlen/nlen2);
745
+			*vp = VectorSub(v, *vn);
746
+		}
747
+	}
748
+
749
+// Matrix operations primarily on 4x4 matrixes!
750
+// Row-wise by default but can be configured to column-wise (see SetTransposed)
751
+
752
+	mat4 IdentityMatrix()
753
+	{
754
+		mat4 m;
755
+		int i;
756
+
757
+		for (i = 0; i <= 15; i++)
758
+			m.m[i] = 0;
759
+		for (i = 0; i <= 3; i++)
760
+			m.m[i * 5] = 1; // 0,5,10,15
761
+		return m;
762
+	}
763
+
764
+	mat4 Rx(GLfloat a)
765
+	{
766
+		mat4 m;
767
+		m = IdentityMatrix();
768
+		m.m[5] = (GLfloat)cos(a);
769
+		if (transposed)
770
+			m.m[9] = (GLfloat)-sin(a);
771
+		else
772
+			m.m[9] = (GLfloat)sin(a);
773
+		m.m[6] = -m.m[9]; //sin(a);
774
+		m.m[10] = m.m[5]; //cos(a);
775
+		return m;
776
+	}
777
+
778
+	mat4 Ry(GLfloat a)
779
+	{
780
+		mat4 m;
781
+		m = IdentityMatrix();
782
+		m.m[0] = (GLfloat)cos(a);
783
+		if (transposed)
784
+			m.m[8] = (GLfloat)sin(a); // Was flipped
785
+		else
786
+			m.m[8] = (GLfloat)-sin(a);
787
+		m.m[2] = -m.m[8]; //sin(a);
788
+		m.m[10] = m.m[0]; //cos(a);
789
+		return m;
790
+	}
791
+
792
+	mat4 Rz(GLfloat a)
793
+	{
794
+		mat4 m;
795
+		m = IdentityMatrix();
796
+		m.m[0] = (GLfloat)cos(a);
797
+		if (transposed)
798
+			m.m[4] = (GLfloat)-sin(a);
799
+		else
800
+			m.m[4] = (GLfloat)sin(a);
801
+		m.m[1] = -m.m[4]; //sin(a);
802
+		m.m[5] = m.m[0]; //cos(a);
803
+		return m;
804
+	}
805
+
806
+	mat4 T(GLfloat tx, GLfloat ty, GLfloat tz)
807
+	{
808
+		mat4 m;
809
+		m = IdentityMatrix();
810
+		if (transposed)
811
+		{
812
+			m.m[12] = tx;
813
+			m.m[13] = ty;
814
+			m.m[14] = tz;
815
+		}
816
+		else
817
+		{
818
+			m.m[3] = tx;
819
+			m.m[7] = ty;
820
+			m.m[11] = tz;
821
+		}
822
+		return m;
823
+	}
824
+
825
+	mat4 S(GLfloat sx, GLfloat sy, GLfloat sz)
826
+	{
827
+		mat4 m;
828
+		m = IdentityMatrix();
829
+		m.m[0] = sx;
830
+		m.m[5] = sy;
831
+		m.m[10] = sz;
832
+		return m;
833
+	}
834
+
835
+	mat4 Mult(mat4 a, mat4 b) // m = a * b
836
+	{
837
+		mat4 m;
838
+
839
+		int x, y;
840
+		for (x = 0; x <= 3; x++)
841
+			for (y = 0; y <= 3; y++)
842
+				if (transposed)
843
+					m.m[x*4 + y] =	a.m[y+4*0] * b.m[0+4*x] +
844
+								a.m[y+4*1] * b.m[1+4*x] +
845
+								a.m[y+4*2] * b.m[2+4*x] +
846
+								a.m[y+4*3] * b.m[3+4*x];
847
+				else
848
+					m.m[y*4 + x] =	a.m[y*4+0] * b.m[0*4+x] +
849
+								a.m[y*4+1] * b.m[1*4+x] +
850
+								a.m[y*4+2] * b.m[2*4+x] +
851
+								a.m[y*4+3] * b.m[3*4+x];
852
+
853
+		return m;
854
+	}
855
+
856
+//	mat4 Mult(mat4 a, mat4 b) // m = a * b
857
+//	{
858
+//		mat4 m;
859
+
860
+//		if (transposed)
861
+//		{
862
+//			a = transpose(a);
863
+//			b = transpose(b);
864
+//		}
865
+
866
+//		int x, y;
867
+//		for (x = 0; x <= 3; x++)
868
+//			for (y = 0; y <= 3; y++)
869
+//					m.m[y*4 + x] =	a.m[y*4+0] * b.m[0*4+x] +
870
+//								a.m[y*4+1] * b.m[1*4+x] +
871
+//								a.m[y*4+2] * b.m[2*4+x] +
872
+//								a.m[y*4+3] * b.m[3*4+x];
873
+
874
+//		if (transposed)
875
+//			m = transpose(m);
876
+
877
+//		return m;
878
+//	}
879
+
880
+
881
+	// Ej testad!
882
+	mat3 MultMat3(mat3 a, mat3 b) // m = a * b
883
+	{
884
+		mat3 m;
885
+
886
+		int x, y;
887
+		for (x = 0; x <= 2; x++)
888
+			for (y = 0; y <= 2; y++)
889
+				if (transposed)
890
+					m.m[x*3 + y] =	a.m[y+3*0] * b.m[0+3*x] +
891
+								a.m[y+3*1] * b.m[1+3*x] +
892
+								a.m[y+3*2] * b.m[2+3*x];
893
+				else
894
+					m.m[y*3 + x] =	a.m[y*3+0] * b.m[0*3+x] +
895
+								a.m[y*3+1] * b.m[1*3+x] +
896
+								a.m[y*3+2] * b.m[2*3+x];
897
+
898
+		return m;
899
+	}
900
+
901
+	// mat4 * vec3
902
+	// The missing homogenous coordinate is implicitly set to 1.
903
+	vec3 MultVec3(mat4 a, vec3 b) // result = a * b
904
+	{
905
+		vec3 r;
906
+
907
+		if (!transposed)
908
+		{
909
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3];
910
+			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7];
911
+			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11];
912
+		}
913
+		else
914
+		{
915
+			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12];
916
+			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13];
917
+			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14];
918
+		}
919
+
920
+		return r;
921
+	}
922
+
923
+	// mat3 * vec3
924
+	vec3 MultMat3Vec3(mat3 a, vec3 b) // result = a * b
925
+	{
926
+		vec3 r;
927
+
928
+		if (!transposed)
929
+		{
930
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z;
931
+			r.y = a.m[3]*b.x + a.m[4]*b.y + a.m[5]*b.z;
932
+			r.z = a.m[6]*b.x + a.m[7]*b.y + a.m[8]*b.z;
933
+		}
934
+		else
935
+		{
936
+			r.x = a.m[0]*b.x + a.m[3]*b.y + a.m[6]*b.z;
937
+			r.y = a.m[1]*b.x + a.m[4]*b.y + a.m[7]*b.z;
938
+			r.z = a.m[2]*b.x + a.m[5]*b.y + a.m[8]*b.z;
939
+		}
940
+
941
+		return r;
942
+	}
943
+
944
+	// mat4 * vec4
945
+	vec4 MultVec4(mat4 a, vec4 b) // result = a * b
946
+	{
947
+		vec4 r;
948
+
949
+		if (!transposed)
950
+		{
951
+			r.x = a.m[0]*b.x + a.m[1]*b.y + a.m[2]*b.z + a.m[3]*b.w;
952
+			r.y = a.m[4]*b.x + a.m[5]*b.y + a.m[6]*b.z + a.m[7]*b.w;
953
+			r.z = a.m[8]*b.x + a.m[9]*b.y + a.m[10]*b.z + a.m[11]*b.w;
954
+			r.w = a.m[12]*b.x + a.m[13]*b.y + a.m[14]*b.z + a.m[15]*b.w;
955
+		}
956
+		else
957
+		{
958
+			r.x = a.m[0]*b.x + a.m[4]*b.y + a.m[8]*b.z + a.m[12]*b.w;
959
+			r.y = a.m[1]*b.x + a.m[5]*b.y + a.m[9]*b.z + a.m[13]*b.w;
960
+			r.z = a.m[2]*b.x + a.m[6]*b.y + a.m[10]*b.z + a.m[14]*b.w;
961
+			r.w = a.m[3]*b.x + a.m[7]*b.y + a.m[11]*b.z + a.m[15]*b.w;
962
+		}
963
+
964
+		return r;
965
+	}
966
+
967
+
968
+// Unnecessary
969
+// Will probably be removed
970
+//	void CopyMatrix(GLfloat *src, GLfloat *dest)
971
+//	{
972
+//		int i;
973
+//		for (i = 0; i <= 15; i++)
974
+//			dest[i] = src[i];
975
+//	}
976
+
977
+
978
+// Added for lab 3 (TSBK03)
979
+
980
+	// Orthonormalization of Matrix4D. Assumes rotation only, translation/projection ignored
981
+	void OrthoNormalizeMatrix(mat4 *R)
982
+	{
983
+		vec3 x, y, z;
984
+
985
+		if (transposed)
986
+		{
987
+			x = SetVector(R->m[0], R->m[1], R->m[2]);
988
+			y = SetVector(R->m[4], R->m[5], R->m[6]);
989
+//		SetVector(R[8], R[9], R[10], &z);
990
+			// Kryssa fram ur varandra
991
+			// Normera
992
+			z = CrossProduct(x, y);
993
+			z = Normalize(z);
994
+			x = Normalize(x);
995
+			y = CrossProduct(z, x);
996
+			R->m[0] = x.x;
997
+			R->m[1] = x.y;
998
+			R->m[2] = x.z;
999
+			R->m[4] = y.x;
1000
+			R->m[5] = y.y;
1001
+			R->m[6] = y.z;
1002
+			R->m[8] = z.x;
1003
+			R->m[9] = z.y;
1004
+			R->m[10] = z.z;
1005
+
1006
+			R->m[3] = 0.0;
1007
+			R->m[7] = 0.0;
1008
+			R->m[11] = 0.0;
1009
+			R->m[12] = 0.0;
1010
+			R->m[13] = 0.0;
1011
+			R->m[14] = 0.0;
1012
+			R->m[15] = 1.0;
1013
+		}
1014
+		else
1015
+		{
1016
+		// NOT TESTED
1017
+			x = SetVector(R->m[0], R->m[4], R->m[8]);
1018
+			y = SetVector(R->m[1], R->m[5], R->m[9]);
1019
+//		SetVector(R[2], R[6], R[10], &z);
1020
+			// Kryssa fram ur varandra
1021
+			// Normera
1022
+			z = CrossProduct(x, y);
1023
+			z = Normalize(z);
1024
+			x = Normalize(x);
1025
+			y = CrossProduct(z, x);
1026
+			R->m[0] = x.x;
1027
+			R->m[4] = x.y;
1028
+			R->m[8] = x.z;
1029
+			R->m[1] = y.x;
1030
+			R->m[5] = y.y;
1031
+			R->m[9] = y.z;
1032
+			R->m[2] = z.x;
1033
+			R->m[6] = z.y;
1034
+			R->m[10] = z.z;
1035
+
1036
+			R->m[3] = 0.0;
1037
+			R->m[7] = 0.0;
1038
+			R->m[11] = 0.0;
1039
+			R->m[12] = 0.0;
1040
+			R->m[13] = 0.0;
1041
+			R->m[14] = 0.0;
1042
+			R->m[15] = 1.0;
1043
+		}
1044
+	}
1045
+
1046
+
1047
+// Commented out since I plan to remove it if I can't see a good reason to keep it.
1048
+//	// Only transposes rotation part.
1049
+//	mat4 TransposeRotation(mat4 m)
1050
+//	{
1051
+//		mat4 a;
1052
+//
1053
+//		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[12];
1054
+//		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[13];
1055
+//		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[14];
1056
+//		a.m[3] = m.m[3]; a.m[7] = m.m[7]; a.m[11] = m.m[11];    a.m[15] = m.m[15];
1057
+//
1058
+//		return a;
1059
+//	}
1060
+
1061
+	// Complete transpose!
1062
+	mat4 transpose(mat4 m)
1063
+	{
1064
+		mat4 a;
1065
+
1066
+		a.m[0] = m.m[0]; a.m[4] = m.m[1]; a.m[8] = m.m[2];      a.m[12] = m.m[3];
1067
+		a.m[1] = m.m[4]; a.m[5] = m.m[5]; a.m[9] = m.m[6];      a.m[13] = m.m[7];
1068
+		a.m[2] = m.m[8]; a.m[6] = m.m[9]; a.m[10] = m.m[10];    a.m[14] = m.m[11];
1069
+		a.m[3] = m.m[12]; a.m[7] = m.m[13]; a.m[11] = m.m[14];    a.m[15] = m.m[15];
1070
+
1071
+		return a;
1072
+	}
1073
+
1074
+	// Complete transpose!
1075
+	mat3 TransposeMat3(mat3 m)
1076
+	{
1077
+		mat3 a;
1078
+
1079
+		a.m[0] = m.m[0]; a.m[3] = m.m[1]; a.m[6] = m.m[2];
1080
+		a.m[1] = m.m[3]; a.m[4] = m.m[4]; a.m[7] = m.m[5];
1081
+		a.m[2] = m.m[6]; a.m[5] = m.m[7]; a.m[8] = m.m[8];
1082
+
1083
+		return a;
1084
+	}
1085
+
1086
+// Rotation around arbitrary axis (rotation only)
1087
+mat4 ArbRotate(vec3 axis, GLfloat fi)
1088
+{
1089
+	vec3 x, y, z;
1090
+	mat4 R, Rt, Raxel, m;
1091
+
1092
+// Check if parallel to Z
1093
+	if (axis.x < 0.0000001) // Below some small value
1094
+	if (axis.x > -0.0000001)
1095
+	if (axis.y < 0.0000001)
1096
+	if (axis.y > -0.0000001)
1097
+	{
1098
+		if (axis.z > 0)
1099
+		{
1100
+			m = Rz(fi);
1101
+			return m;
1102
+		}
1103
+		else
1104
+		{
1105
+			m = Rz(-fi);
1106
+			return m;
1107
+		}
1108
+	}
1109
+
1110
+	x = Normalize(axis);
1111
+	z = SetVector(0,0,1); // Temp z
1112
+	y = Normalize(CrossProduct(z, x)); // y' = z^ x x'
1113
+	z = CrossProduct(x, y); // z' = x x y
1114
+
1115
+	if (transposed)
1116
+	{
1117
+		R.m[0] = x.x; R.m[4] = x.y; R.m[8] = x.z;  R.m[12] = 0.0;
1118
+		R.m[1] = y.x; R.m[5] = y.y; R.m[9] = y.z;  R.m[13] = 0.0;
1119
+		R.m[2] = z.x; R.m[6] = z.y; R.m[10] = z.z;  R.m[14] = 0.0;
1120
+
1121
+		R.m[3] = 0.0; R.m[7] = 0.0; R.m[11] = 0.0;  R.m[15] = 1.0;
1122
+	}
1123
+	else
1124
+	{
1125
+		R.m[0] = x.x; R.m[1] = x.y; R.m[2] = x.z;  R.m[3] = 0.0;
1126
+		R.m[4] = y.x; R.m[5] = y.y; R.m[6] = y.z;  R.m[7] = 0.0;
1127
+		R.m[8] = z.x; R.m[9] = z.y; R.m[10] = z.z;  R.m[11] = 0.0;
1128
+
1129
+		R.m[12] = 0.0; R.m[13] = 0.0; R.m[14] = 0.0;  R.m[15] = 1.0;
1130
+	}
1131
+
1132
+	Rt = Transpose(R); // Transpose = Invert -> felet ej i Transpose, och det \8Ar en ortonormal matris
1133
+
1134
+	Raxel = Rx(fi); // Rotate around x axis
1135
+
1136
+	// m := Rt * Rx * R
1137
+	m = Mult(Mult(Rt, Raxel), R);
1138
+
1139
+	return m;
1140
+}
1141
+
1142
+
1143
+// Not tested much
1144
+mat4 CrossMatrix(vec3 a) // Matrix for cross product
1145
+{
1146
+	mat4 m;
1147
+
1148
+	if (transposed)
1149
+	{
1150
+		m.m[0] =    0; m.m[4] =-a.z; m.m[8] = a.y; m.m[12] = 0.0;
1151
+		m.m[1] = a.z; m.m[5] =    0; m.m[9] =-a.x; m.m[13] = 0.0;
1152
+		m.m[2] =-a.y; m.m[6] = a.x; m.m[10]=    0; m.m[14] = 0.0;
1153
+		m.m[3] =  0.0; m.m[7] =  0.0; m.m[11]=  0.0; m.m[15] = 0.0;
1154
+		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
1155
+		// not be generally used, but is fine for matrix differentials
1156
+	}
1157
+	else
1158
+	{
1159
+		m.m[0] =    0; m.m[1] =-a.z; m.m[2] = a.y; m.m[3] = 0.0;
1160
+		m.m[4] = a.z; m.m[5] =    0; m.m[6] =-a.x; m.m[7] = 0.0;
1161
+		m.m[8] =-a.y; m.m[9] = a.x; m.m[10]=    0; m.m[11] = 0.0;
1162
+		m.m[12] =  0.0; m.m[13] =  0.0; m.m[14]=  0.0; m.m[15] = 0.0;
1163
+		// NOTE! 0.0 in the homogous coordinate. Thus, the matrix can
1164
+		// not be generally used, but is fine for matrix differentials
1165
+	}
1166
+
1167
+	return m;
1168
+}
1169
+
1170
+mat4 MatrixAdd(mat4 a, mat4 b)
1171
+{
1172
+	mat4 dest;
1173
+
1174
+	int i;
1175
+	for (i = 0; i < 16; i++)
1176
+		dest.m[i] = a.m[i] + b.m[i];
1177
+
1178
+	return dest;
1179
+}
1180
+
1181
+// 0 = row-wise defined matrices
1182
+// 1 = column-wise
1183
+void SetTransposed(char t)
1184
+{
1185
+	transposed = t;
1186
+}
1187
+
1188
+
1189
+// Build standard matrices
1190
+
1191
+mat4 lookAtv(vec3 p, vec3 l, vec3 v)
1192
+{
1193
+	vec3 n, u;
1194
+	mat4 rot, trans;
1195
+
1196
+	n = Normalize(VectorSub(p, l));
1197
+	u = Normalize(CrossProduct(v, n));
1198
+	v = CrossProduct(n, u);
1199
+
1200
+	if (transposed)
1201
+	rot = SetMat4(u.x, v.x, n.x, 0,
1202
+                  u.y, v.y, n.y, 0,
1203
+                  u.z, v.z, n.z, 0,
1204
+                  0,   0,   0,   1);
1205
+	else
1206
+	rot = SetMat4(u.x, u.y, u.z, 0,
1207
+                  v.x, v.y, v.z, 0,
1208
+                  n.x, n.y, n.z, 0,
1209
+                  0,   0,   0,   1);
1210
+	trans = T(-p.x, -p.y, -p.z);
1211
+	mat4 m = Mult(rot, trans);
1212
+	return m;
1213
+}
1214
+
1215
+mat4 lookAt(GLfloat px, GLfloat py, GLfloat pz,
1216
+			GLfloat lx, GLfloat ly, GLfloat lz,
1217
+			GLfloat vx, GLfloat vy, GLfloat vz)
1218
+{
1219
+	vec3 p, l, v;
1220
+
1221
+	p = SetVector(px, py, pz);
1222
+	l = SetVector(lx, ly, lz);
1223
+	v = SetVector(vx, vy, vz);
1224
+
1225
+	return lookAtv(p, l, v);
1226
+}
1227
+
1228
+// From http://www.opengl.org/wiki/GluPerspective_code
1229
+// Changed names and parameter order to conform with VU style
1230
+// Rewritten 120913 because it was all wrong...
1231
+// Rewritten again 2022 to a more compact form.
1232
+mat4 perspective(float fovyInDegrees, float aspectRatio,
1233
+                      float znear, float zfar)
1234
+{
1235
+	float f = 1/tan(fovyInDegrees * M_PI / 360.0);
1236
+	mat4 m = SetMat4(f/aspectRatio, 0, 0, 0,
1237
+					0, f, 0, 0,
1238
+					0, 0, (zfar+znear)/(znear-zfar), 2*zfar*znear/(znear-zfar),
1239
+					0, 0, -1, 0);
1240
+	if (transposed)
1241
+		m = transpose(m);
1242
+	return m;
1243
+}
1244
+
1245
+mat4 frustum(float left, float right, float bottom, float top,
1246
+                  float znear, float zfar)
1247
+{
1248
+    float temp, temp2, temp3, temp4;
1249
+    mat4 matrix;
1250
+
1251
+    temp = 2.0f * znear;
1252
+    temp2 = right - left;
1253
+    temp3 = top - bottom;
1254
+    temp4 = zfar - znear;
1255
+    matrix.m[0] = temp / temp2; // 2*near/(right-left)
1256
+    matrix.m[1] = 0.0;
1257
+    matrix.m[2] = 0.0;
1258
+    matrix.m[3] = 0.0;
1259
+    matrix.m[4] = 0.0;
1260
+    matrix.m[5] = temp / temp3; // 2*near/(top - bottom)
1261
+    matrix.m[6] = 0.0;
1262
+    matrix.m[7] = 0.0;
1263
+    matrix.m[8] = (right + left) / temp2; // A = r+l / r-l
1264
+    matrix.m[9] = (top + bottom) / temp3; // B = t+b / t-b
1265
+    matrix.m[10] = (-zfar - znear) / temp4; // C = -(f+n) / f-n
1266
+    matrix.m[11] = -1.0;
1267
+    matrix.m[12] = 0.0;
1268
+    matrix.m[13] = 0.0;
1269
+    matrix.m[14] = (-temp * zfar) / temp4; // D = -2fn / f-n
1270
+    matrix.m[15] = 0.0;
1271
+
1272
+    if (!transposed)
1273
+    	matrix = Transpose(matrix);
1274
+
1275
+    return matrix;
1276
+}
1277
+
1278
+// Not tested!
1279
+mat4 ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
1280
+{
1281
+        float a = 2.0f / (right - left);
1282
+        float b = 2.0f / (top - bottom);
1283
+        float c = -2.0f / (far - near);
1284
+
1285
+        float tx = - (right + left)/(right - left);
1286
+        float ty = - (top + bottom)/(top - bottom);
1287
+        float tz = - (far + near)/(far - near);
1288
+
1289
+        mat4 o = SetMat4(
1290
+            a, 0, 0, tx,
1291
+            0, b, 0, ty,
1292
+            0, 0, c, tz,
1293
+            0, 0, 0, 1);
1294
+
1295
+        if (transposed)
1296
+   			o = Transpose(o);
1297
+
1298
+        return o;
1299
+}
1300
+
1301
+// The code below is based on code from:
1302
+// http://www.dr-lex.be/random/matrix_inv.html
1303
+
1304
+// Inverts mat3 (row-wise matrix)
1305
+// (For a more general inverse, try a gaussian elimination.)
1306
+mat3 InvertMat3(mat3 in)
1307
+{
1308
+	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
1309
+	mat3 out, nanout;
1310
+	float DET;
1311
+
1312
+	// Copying to internal variables both clarify the code and
1313
+	// buffers data so the output may be identical to the input!
1314
+	a11 = in.m[0];
1315
+	a12 = in.m[1];
1316
+	a13 = in.m[2];
1317
+	a21 = in.m[3];
1318
+	a22 = in.m[4];
1319
+	a23 = in.m[5];
1320
+	a31 = in.m[6];
1321
+	a32 = in.m[7];
1322
+	a33 = in.m[8];
1323
+	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
1324
+	if (DET != 0)
1325
+	{
1326
+		out.m[0] = (a33*a22-a32*a23)/DET;
1327
+		out.m[1] = -(a33*a12-a32*a13)/DET;
1328
+		out.m[2] = (a23*a12-a22*a13)/DET;
1329
+		out.m[3] = -(a33*a21-a31*a23)/DET;
1330
+		out.m[4] = (a33*a11-a31*a13)/DET;
1331
+		out.m[5] = -(a23*a11-a21*a13)/DET;
1332
+		out.m[6] = (a32*a21-a31*a22)/DET;
1333
+		out.m[7] = -(a32*a11-a31*a12)/DET;
1334
+		out.m[8] = (a22*a11-a21*a12)/DET;
1335
+	}
1336
+	else
1337
+	{
1338
+		nanout = SetMat3(NAN, NAN, NAN,
1339
+								NAN, NAN, NAN,
1340
+								NAN, NAN, NAN);
1341
+		out = nanout;
1342
+	}
1343
+
1344
+	return out;
1345
+}
1346
+
1347
+// For making a normal matrix from a model-to-view matrix
1348
+// Takes a mat4 in, ignores 4th row/column (should just be translations),
1349
+// inverts as mat3 (row-wise matrix) and returns the transpose
1350
+mat3 InverseTranspose(mat4 in)
1351
+{
1352
+	float a11, a12, a13, a21, a22, a23, a31, a32, a33;
1353
+	mat3 out, nanout;
1354
+	float DET;
1355
+
1356
+	// Copying to internal variables
1357
+	a11 = in.m[0];
1358
+	a12 = in.m[1];
1359
+	a13 = in.m[2];
1360
+	a21 = in.m[4];
1361
+	a22 = in.m[5];
1362
+	a23 = in.m[6];
1363
+	a31 = in.m[8];
1364
+	a32 = in.m[9];
1365
+	a33 = in.m[10];
1366
+	DET = a11*(a33*a22-a32*a23)-a21*(a33*a12-a32*a13)+a31*(a23*a12-a22*a13);
1367
+	if (DET != 0)
1368
+	{
1369
+		out.m[0] = (a33*a22-a32*a23)/DET;
1370
+		out.m[3] = -(a33*a12-a32*a13)/DET;
1371
+		out.m[6] = (a23*a12-a22*a13)/DET;
1372
+		out.m[1] = -(a33*a21-a31*a23)/DET;
1373
+		out.m[4] = (a33*a11-a31*a13)/DET;
1374
+		out.m[7] = -(a23*a11-a21*a13)/DET;
1375
+		out.m[2] = (a32*a21-a31*a22)/DET;
1376
+		out.m[5] = -(a32*a11-a31*a12)/DET;
1377
+		out.m[8] = (a22*a11-a21*a12)/DET;
1378
+	}
1379
+	else
1380
+	{
1381
+		nanout = SetMat3(NAN, NAN, NAN,
1382
+								NAN, NAN, NAN,
1383
+								NAN, NAN, NAN);
1384
+		out = nanout;
1385
+	}
1386
+
1387
+	return out;
1388
+}
1389
+
1390
+
1391
+// Simple conversions
1392
+mat3 mat4tomat3(mat4 m)
1393
+{
1394
+	mat3 result;
1395
+
1396
+	result.m[0] = m.m[0];
1397
+	result.m[1] = m.m[1];
1398
+	result.m[2] = m.m[2];
1399
+	result.m[3] = m.m[4];
1400
+	result.m[4] = m.m[5];
1401
+	result.m[5] = m.m[6];
1402
+	result.m[6] = m.m[8];
1403
+	result.m[7] = m.m[9];
1404
+	result.m[8] = m.m[10];
1405
+	return result;
1406
+}
1407
+
1408
+mat4 mat3tomat4(mat3 m)
1409
+{
1410
+	mat4 result;
1411
+
1412
+	result.m[0] = m.m[0];
1413
+	result.m[1] = m.m[1];
1414
+	result.m[2] = m.m[2];
1415
+	result.m[3] = 0;
1416
+	result.m[4] = m.m[3];
1417
+	result.m[5] = m.m[4];
1418
+	result.m[6] = m.m[5];
1419
+	result.m[7] = 0;
1420
+	result.m[8] = m.m[6];
1421
+	result.m[9] = m.m[7];
1422
+	result.m[10] = m.m[8];
1423
+	result.m[11] = 0;
1424
+
1425
+	result.m[12] = 0;
1426
+	result.m[13] = 0;
1427
+	result.m[14] = 0;
1428
+	result.m[15] = 1;
1429
+	return result;
1430
+}
1431
+
1432
+vec3 vec4tovec3(vec4 v)
1433
+{
1434
+	vec3 result;
1435
+	result.x = v.x;
1436
+	result.y = v.y;
1437
+	result.z = v.z;
1438
+	return result;
1439
+}
1440
+
1441
+vec4 vec3tovec4(vec3 v)
1442
+{
1443
+	vec4 result;
1444
+	result.x = v.x;
1445
+	result.y = v.y;
1446
+	result.z = v.z;
1447
+	result.w = 1;
1448
+	return result;
1449
+}
1450
+
1451
+
1452
+// Stol... I mean adapted from glMatrix (WebGL math unit). Almost no
1453
+// changes despite changing language! But I just might replace it with
1454
+// a gaussian elimination some time.
1455
+mat4 InvertMat4(mat4 a)
1456
+{
1457
+   mat4 b;
1458
+
1459
+   float c=a.m[0],d=a.m[1],e=a.m[2],g=a.m[3],
1460
+	f=a.m[4],h=a.m[5],i=a.m[6],j=a.m[7],
1461
+	k=a.m[8],l=a.m[9],o=a.m[10],m=a.m[11],
1462
+	n=a.m[12],p=a.m[13],r=a.m[14],s=a.m[15],
1463
+	A=c*h-d*f,
1464
+	B=c*i-e*f,
1465
+	t=c*j-g*f,
1466
+	u=d*i-e*h,
1467
+	v=d*j-g*h,
1468
+	w=e*j-g*i,
1469
+	x=k*p-l*n,
1470
+	y=k*r-o*n,
1471
+	z=k*s-m*n,
1472
+	C=l*r-o*p,
1473
+	D=l*s-m*p,
1474
+	E=o*s-m*r,
1475
+	q=1/(A*E-B*D+t*C+u*z-v*y+w*x);
1476
+	b.m[0]=(h*E-i*D+j*C)*q;
1477
+	b.m[1]=(-d*E+e*D-g*C)*q;
1478
+	b.m[2]=(p*w-r*v+s*u)*q;
1479
+	b.m[3]=(-l*w+o*v-m*u)*q;
1480
+	b.m[4]=(-f*E+i*z-j*y)*q;
1481
+	b.m[5]=(c*E-e*z+g*y)*q;
1482
+	b.m[6]=(-n*w+r*t-s*B)*q;
1483
+	b.m[7]=(k*w-o*t+m*B)*q;
1484
+	b.m[8]=(f*D-h*z+j*x)*q;
1485
+	b.m[9]=(-c*D+d*z-g*x)*q;
1486
+	b.m[10]=(n*v-p*t+s*A)*q;
1487
+	b.m[11]=(-k*v+l*t-m*A)*q;
1488
+	b.m[12]=(-f*C+h*y-i*x)*q;
1489
+	b.m[13]=(c*C-d*y+e*x)*q;
1490
+	b.m[14]=(-n*u+p*B-r*A)*q;
1491
+	b.m[15]=(k*u-l*B+o*A)*q;
1492
+	return b;
1493
+};
1494
+
1495
+
1496
+// Two convenient printing functions suggested by Christian Luckey 2015.
1497
+// Added printMat3 2019.
1498
+void printMat4(mat4 m)
1499
+{
1500
+	unsigned int i;
1501
+	printf(" ---------------------------------------------------------------\n");
1502
+	for (i = 0; i < 4; i++)
1503
+	{
1504
+		int n = i * 4;
1505
+		printf("| %11.5f\t| %11.5f\t| %11.5f\t| %11.5f\t|\n",
1506
+			m.m[n], m.m[n+1], m.m[n+2], m.m[n+3]);
1507
+	}
1508
+	printf(" ---------------------------------------------------------------\n");
1509
+}
1510
+
1511
+void printMat3(mat3 m)
1512
+{
1513
+	unsigned int i;
1514
+	printf(" ---------------------------------------------------------------\n");
1515
+	for (i = 0; i < 3; i++)
1516
+	{
1517
+		int n = i * 3;
1518
+		printf("| %11.5f\t| %11.5f\t| %11.5f\t| \n",
1519
+			m.m[n], m.m[n+1], m.m[n+2]);
1520
+	}
1521
+	printf(" ---------------------------------------------------------------\n");
1522
+}
1523
+
1524
+void printVec3(vec3 in)
1525
+{
1526
+	printf("(%f, %f, %f)\n", in.x, in.y, in.z);
1527
+}
1528
+
1529
+#ifdef __cplusplus
1530
+mat3 inverse(mat3 m)
1531
+{
1532
+	return InvertMat3(m);
1533
+}
1534
+mat4 inverse(mat4 m)
1535
+{
1536
+	return InvertMat4(m);
1537
+}
1538
+mat3 transpose(mat3 m)
1539
+{
1540
+	return TransposeMat3(m);
1541
+}
1542
+mat4 S(GLfloat s)
1543
+{
1544
+	return S(s, s, s);
1545
+}
1546
+mat4 S(vec3 s)
1547
+{
1548
+	return S(s.x, s.y, s.z);
1549
+}
1550
+mat4 lookAt(vec3 p, vec3 l, vec3 u)
1551
+{
1552
+	return lookAtv(p, l, u);
1553
+}
1554
+
1555
+#endif
1556
+#endif
1557
+
1558
+#endif