Compare commits
	
		
			119 Commits
		
	
	
		
			f024d51d85
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4526c514e9 | |||
| bf3a3ea02b | |||
| 669064e4a7 | |||
| 2ffd44f1a5 | |||
| 11dee52090 | |||
| 53e535774d | |||
| 2f086fe548 | |||
| db42dd3d9e | |||
| b0cebb67f8 | |||
| bca5dafabf | |||
| 0aacccdf67 | |||
| 7a17d129a1 | |||
| 7f2c4cdd0a | |||
| 56fbde696f | |||
| 88e9d3550a | |||
| 66ca20ee5b | |||
| ef0c29de02 | |||
| 87f6b2b87a | |||
| 390ab7c3b4 | |||
| 72ab9f6aa2 | |||
| 15a471f911 | |||
| ab8343e749 | |||
| 09e9f611f8 | |||
| fb1b8457d6 | |||
| ab71bbc438 | |||
| 95895750e8 | |||
| 98323da649 | |||
| c739864489 | |||
| f45e30620f | |||
| dcbda91730 | |||
| 80f20a06cd | |||
| c12c212843 | |||
| 1223e55db1 | |||
| 351b7e9d42 | |||
| b57ec11598 | |||
| d750c49f71 | |||
| cf8c681474 | |||
| 84fbb711e1 | |||
| 8c74706fdc | |||
| d851509321 | |||
| e87f780dae | |||
| 8726c833d4 | |||
| da495d9e43 | |||
| 18e9964d33 | |||
| 95d474c956 | |||
| 41c30256b7 | |||
| 4b178de784 | |||
| bb6b0e3e5d | |||
| 97622d0bf7 | |||
| 319bad9659 | |||
| 57dcf6457c | |||
| 7671f688a3 | |||
| f9851967d8 | |||
| 5dac82ffb7 | |||
| 185f44252f | |||
| cee57282cb | |||
| cdf521f184 | |||
| cab1b538e6 | |||
| afa9bc7468 | |||
| 8ccc424b06 | |||
| 62aa2fbc3b | |||
| 22edc89593 | |||
| 1f5f01d73f | |||
| 798100f138 | |||
| aa9c443997 | |||
| 535ead0337 | |||
| 6f5c094f49 | |||
| 996597684b | |||
| 4f58fc4803 | |||
| c91f1b9e9b | |||
| 3ceafe5899 | |||
| 5eeb7d6819 | |||
| ed43a0f286 | |||
| bf1aa69cf5 | |||
| 8b8855d648 | |||
| 0b9a37a9cd | |||
| 2bea7218db | |||
| afc10fb79a | |||
| 86138f838c | |||
| ddfeba238d | |||
| 29749c834a | |||
| 760d9b6b9c | |||
| ec98a033eb | |||
| caa8c416a9 | |||
| 690eb3d317 | |||
| 6239be219a | |||
| be7b577a0e | |||
| 2e39780272 | |||
| 1adac24148 | |||
| 50b8c6dd0a | |||
| 3bbab3f624 | |||
| a3f0be461b | |||
| fdce10a85c | |||
| f77fa5694b | |||
| 3e414881d9 | |||
| 4fa553db47 | |||
| 711b9d8558 | |||
| 2f126f95ff | |||
| 4143fd7b05 | |||
| 643da4e58d | |||
| d323c0ae14 | |||
| e01c1397bc | |||
| 46ca6bfa10 | |||
| 91c4721c46 | |||
| 3a852cbab0 | |||
| 5b55092ba2 | |||
| b4210da399 | |||
| 34d0d17b76 | |||
| fee04607a7 | |||
| b6e7b9c213 | |||
| e472b221c0 | |||
| fa2857b5d3 | |||
| ba88c5b27c | |||
| 1ad2ca1a47 | |||
| b111058f31 | |||
| 26c1f17a86 | |||
| 29c53de86e | |||
| 1ab8c964bf | |||
| 677627d8c9 | 
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,7 @@
 | 
			
		||||
.cache
 | 
			
		||||
compile_commands.json
 | 
			
		||||
tiny
 | 
			
		||||
/tiny
 | 
			
		||||
*.pam
 | 
			
		||||
resources/*.png
 | 
			
		||||
.venv
 | 
			
		||||
*.py
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
# tinyrenderer
 | 
			
		||||
 | 
			
		||||
Following along the [tinyrenderer](https://github.com/ssloy/tinyrenderer/wiki) lessons
 | 
			
		||||
 | 
			
		||||
### Result so far
 | 
			
		||||

 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								compile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								compile
									
									
									
									
									
								
							@@ -3,9 +3,11 @@
 | 
			
		||||
CC=clang
 | 
			
		||||
WAPP_INCLUDE="$(find intern/wapp/src -type d | xargs -I{} echo -n "-I{} ")"
 | 
			
		||||
WAPP_SRC="$(find intern/wapp/src -type f -name "*.c" | xargs -I{} echo -n "{} ")"
 | 
			
		||||
CFLAGS="-g -Isrc $WAPP_INCLUDE"
 | 
			
		||||
TINYRENDER_INCLUDE="$(find src -type d | xargs -I{} echo -n "-I{} ")"
 | 
			
		||||
TINYRENDER_SRC="$(find src -type f -name "*.c" | xargs -I{} echo -n "{} ")"
 | 
			
		||||
CFLAGS="-g $TINYRENDER_INCLUDE $WAPP_INCLUDE"
 | 
			
		||||
LIBS="-lm"
 | 
			
		||||
SRC="src/*.c $WAPP_SRC"
 | 
			
		||||
SRC="$TINYRENDER_SRC $WAPP_SRC"
 | 
			
		||||
OUT=tiny
 | 
			
		||||
 | 
			
		||||
(set -x ; $CC $CFLAGS $LIBS $SRC -o $OUT)
 | 
			
		||||
 
 | 
			
		||||
 Submodule intern/wapp updated: 8ed372d938...b8f6e5f187
									
								
							
							
								
								
									
										
											BIN
										
									
								
								output.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								output.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 652 KiB  | 
							
								
								
									
										44
									
								
								resources/cube.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								resources/cube.obj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
# Blender 4.2.0
 | 
			
		||||
# www.blender.org
 | 
			
		||||
o Cube
 | 
			
		||||
v 0.500000 0.500000 -0.500000
 | 
			
		||||
v 0.500000 -0.500000 -0.500000
 | 
			
		||||
v 0.500000 0.500000 0.500000
 | 
			
		||||
v 0.500000 -0.500000 0.500000
 | 
			
		||||
v -0.500000 0.500000 -0.500000
 | 
			
		||||
v -0.500000 -0.500000 -0.500000
 | 
			
		||||
v -0.500000 0.500000 0.500000
 | 
			
		||||
v -0.500000 -0.500000 0.500000
 | 
			
		||||
vn -0.0000 1.0000 -0.0000
 | 
			
		||||
vn -0.0000 -0.0000 1.0000
 | 
			
		||||
vn -1.0000 -0.0000 -0.0000
 | 
			
		||||
vn -0.0000 -1.0000 -0.0000
 | 
			
		||||
vn 1.0000 -0.0000 -0.0000
 | 
			
		||||
vn -0.0000 -0.0000 -1.0000
 | 
			
		||||
vt 0.875000 0.500000
 | 
			
		||||
vt 0.625000 0.750000
 | 
			
		||||
vt 0.625000 0.500000
 | 
			
		||||
vt 0.375000 1.000000
 | 
			
		||||
vt 0.375000 0.750000
 | 
			
		||||
vt 0.625000 0.000000
 | 
			
		||||
vt 0.375000 0.250000
 | 
			
		||||
vt 0.375000 0.000000
 | 
			
		||||
vt 0.375000 0.500000
 | 
			
		||||
vt 0.125000 0.750000
 | 
			
		||||
vt 0.125000 0.500000
 | 
			
		||||
vt 0.625000 0.250000
 | 
			
		||||
vt 0.875000 0.750000
 | 
			
		||||
vt 0.625000 1.000000
 | 
			
		||||
s 0
 | 
			
		||||
f 5/1/1 3/2/1 1/3/1
 | 
			
		||||
f 3/2/2 8/4/2 4/5/2
 | 
			
		||||
f 7/6/3 6/7/3 8/8/3
 | 
			
		||||
f 2/9/4 8/10/4 6/11/4
 | 
			
		||||
f 1/3/5 4/5/5 2/9/5
 | 
			
		||||
f 5/12/6 2/9/6 6/7/6
 | 
			
		||||
f 5/1/1 7/13/1 3/2/1
 | 
			
		||||
f 3/2/2 7/14/2 8/4/2
 | 
			
		||||
f 7/6/3 5/12/3 6/7/3
 | 
			
		||||
f 2/9/4 4/5/4 8/10/4
 | 
			
		||||
f 1/3/5 3/2/5 4/5/5
 | 
			
		||||
f 5/12/6 1/3/6 2/9/6
 | 
			
		||||
							
								
								
									
										13334
									
								
								resources/diablo3_pose.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13334
									
								
								resources/diablo3_pose.obj
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								resources/diablo3_pose_diffuse.pnm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/diablo3_pose_diffuse.pnm
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										108
									
								
								resources/diablo3_pose_tangent.pnm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								resources/diablo3_pose_tangent.pnm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										78
									
								
								resources/grid.pnm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								resources/grid.pnm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										172
									
								
								resources/half_sphere.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								resources/half_sphere.obj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
# Blender 4.2.0
 | 
			
		||||
# www.blender.org
 | 
			
		||||
o Sphere
 | 
			
		||||
v 0.382683 0.923880 0.000000
 | 
			
		||||
v 0.707107 0.707107 0.000000
 | 
			
		||||
v 0.923879 0.382683 0.000000
 | 
			
		||||
v 1.000000 0.000000 0.000000
 | 
			
		||||
v 0.923879 -0.382683 0.000000
 | 
			
		||||
v 0.707107 -0.707107 0.000000
 | 
			
		||||
v 0.382683 -0.923880 0.000000
 | 
			
		||||
v 0.270598 0.923880 0.270598
 | 
			
		||||
v 0.500000 0.707107 0.500000
 | 
			
		||||
v 0.653281 0.382683 0.653281
 | 
			
		||||
v 0.707107 0.000000 0.707107
 | 
			
		||||
v 0.653281 -0.382683 0.653281
 | 
			
		||||
v 0.500000 -0.707107 0.500000
 | 
			
		||||
v 0.270598 -0.923880 0.270598
 | 
			
		||||
v 0.000000 0.923880 0.382683
 | 
			
		||||
v 0.000000 0.707107 0.707107
 | 
			
		||||
v 0.000000 0.382683 0.923879
 | 
			
		||||
v 0.000000 0.000000 1.000000
 | 
			
		||||
v 0.000000 -0.382683 0.923879
 | 
			
		||||
v 0.000000 -0.707107 0.707107
 | 
			
		||||
v 0.000000 -0.923880 0.382683
 | 
			
		||||
v -0.270598 0.923880 0.270598
 | 
			
		||||
v -0.500000 0.707107 0.500000
 | 
			
		||||
v -0.653281 0.382683 0.653281
 | 
			
		||||
v -0.707107 0.000000 0.707107
 | 
			
		||||
v -0.653281 -0.382683 0.653281
 | 
			
		||||
v -0.500000 -0.707107 0.500000
 | 
			
		||||
v -0.270598 -0.923880 0.270598
 | 
			
		||||
v -0.382683 0.923880 0.000000
 | 
			
		||||
v -0.707107 0.707107 0.000000
 | 
			
		||||
v -0.923879 0.382683 0.000000
 | 
			
		||||
v -1.000000 0.000000 0.000000
 | 
			
		||||
v -0.923879 -0.382683 0.000000
 | 
			
		||||
v -0.707107 -0.707107 0.000000
 | 
			
		||||
v -0.382683 -0.923880 0.000000
 | 
			
		||||
v 0.000000 -1.000000 0.000000
 | 
			
		||||
v 0.000000 1.000000 0.000000
 | 
			
		||||
vn 0.5414 -0.8103 0.2243
 | 
			
		||||
vn 0.9087 -0.1807 0.3764
 | 
			
		||||
vn 0.7862 0.5253 0.3256
 | 
			
		||||
vn 0.1945 0.9776 0.0805
 | 
			
		||||
vn 0.1945 -0.9776 0.0805
 | 
			
		||||
vn 0.7862 -0.5253 0.3256
 | 
			
		||||
vn 0.9087 0.1807 0.3764
 | 
			
		||||
vn 0.5414 0.8103 0.2243
 | 
			
		||||
vn 0.0805 0.9776 0.1945
 | 
			
		||||
vn 0.0805 -0.9776 0.1945
 | 
			
		||||
vn 0.3256 -0.5253 0.7862
 | 
			
		||||
vn 0.3764 0.1807 0.9087
 | 
			
		||||
vn 0.2243 0.8103 0.5414
 | 
			
		||||
vn 0.2243 -0.8103 0.5414
 | 
			
		||||
vn 0.3764 -0.1807 0.9087
 | 
			
		||||
vn 0.3256 0.5253 0.7862
 | 
			
		||||
vn -0.3256 -0.5253 0.7862
 | 
			
		||||
vn -0.3764 0.1807 0.9087
 | 
			
		||||
vn -0.2243 0.8103 0.5414
 | 
			
		||||
vn -0.2243 -0.8103 0.5414
 | 
			
		||||
vn -0.3764 -0.1807 0.9087
 | 
			
		||||
vn -0.3256 0.5253 0.7862
 | 
			
		||||
vn -0.0805 0.9776 0.1945
 | 
			
		||||
vn -0.0805 -0.9776 0.1945
 | 
			
		||||
vn -0.5414 -0.8103 0.2243
 | 
			
		||||
vn -0.9087 -0.1807 0.3764
 | 
			
		||||
vn -0.7862 0.5253 0.3256
 | 
			
		||||
vn -0.1945 0.9776 0.0805
 | 
			
		||||
vn -0.1945 -0.9776 0.0805
 | 
			
		||||
vn -0.7862 -0.5253 0.3256
 | 
			
		||||
vn -0.9087 0.1807 0.3764
 | 
			
		||||
vn -0.5414 0.8103 0.2243
 | 
			
		||||
vt 0.500000 0.250000
 | 
			
		||||
vt 0.375000 0.125000
 | 
			
		||||
vt 0.500000 0.125000
 | 
			
		||||
vt 0.500000 0.375000
 | 
			
		||||
vt 0.375000 0.500000
 | 
			
		||||
vt 0.375000 0.375000
 | 
			
		||||
vt 0.500000 0.625000
 | 
			
		||||
vt 0.375000 0.750000
 | 
			
		||||
vt 0.375000 0.625000
 | 
			
		||||
vt 0.500000 0.875000
 | 
			
		||||
vt 0.437500 1.000000
 | 
			
		||||
vt 0.375000 0.875000
 | 
			
		||||
vt 0.437500 0.000000
 | 
			
		||||
vt 0.375000 0.250000
 | 
			
		||||
vt 0.500000 0.500000
 | 
			
		||||
vt 0.500000 0.750000
 | 
			
		||||
vt 0.312500 1.000000
 | 
			
		||||
vt 0.250000 0.875000
 | 
			
		||||
vt 0.312500 0.000000
 | 
			
		||||
vt 0.250000 0.125000
 | 
			
		||||
vt 0.250000 0.250000
 | 
			
		||||
vt 0.250000 0.500000
 | 
			
		||||
vt 0.250000 0.750000
 | 
			
		||||
vt 0.250000 0.375000
 | 
			
		||||
vt 0.250000 0.625000
 | 
			
		||||
vt 0.125000 0.250000
 | 
			
		||||
vt 0.125000 0.625000
 | 
			
		||||
vt 0.125000 0.500000
 | 
			
		||||
vt 0.125000 0.750000
 | 
			
		||||
vt 0.125000 0.125000
 | 
			
		||||
vt 0.125000 0.375000
 | 
			
		||||
vt 0.187500 1.000000
 | 
			
		||||
vt 0.125000 0.875000
 | 
			
		||||
vt 0.187500 0.000000
 | 
			
		||||
vt 0.000000 0.125000
 | 
			
		||||
vt 0.000000 0.500000
 | 
			
		||||
vt 0.000000 0.375000
 | 
			
		||||
vt 0.000000 0.625000
 | 
			
		||||
vt 0.062500 1.000000
 | 
			
		||||
vt 0.000000 0.875000
 | 
			
		||||
vt 0.062500 0.000000
 | 
			
		||||
vt 0.000000 0.250000
 | 
			
		||||
vt 0.000000 0.750000
 | 
			
		||||
s 0
 | 
			
		||||
f 6/1/1 14/2/1 7/3/1
 | 
			
		||||
f 5/4/2 11/5/2 12/6/2
 | 
			
		||||
f 3/7/3 9/8/3 10/9/3
 | 
			
		||||
f 1/10/4 37/11/4 8/12/4
 | 
			
		||||
f 36/13/5 7/3/5 14/2/5
 | 
			
		||||
f 5/4/6 13/14/6 6/1/6
 | 
			
		||||
f 3/7/7 11/5/7 4/15/7
 | 
			
		||||
f 1/10/8 9/8/8 2/16/8
 | 
			
		||||
f 8/12/9 37/17/9 15/18/9
 | 
			
		||||
f 36/19/10 14/2/10 21/20/10
 | 
			
		||||
f 12/6/11 20/21/11 13/14/11
 | 
			
		||||
f 10/9/12 18/22/12 11/5/12
 | 
			
		||||
f 8/12/13 16/23/13 9/8/13
 | 
			
		||||
f 13/14/14 21/20/14 14/2/14
 | 
			
		||||
f 12/6/15 18/22/15 19/24/15
 | 
			
		||||
f 9/8/16 17/25/16 10/9/16
 | 
			
		||||
f 19/24/17 27/26/17 20/21/17
 | 
			
		||||
f 18/22/18 24/27/18 25/28/18
 | 
			
		||||
f 15/18/19 23/29/19 16/23/19
 | 
			
		||||
f 20/21/20 28/30/20 21/20/20
 | 
			
		||||
f 18/22/21 26/31/21 19/24/21
 | 
			
		||||
f 16/23/22 24/27/22 17/25/22
 | 
			
		||||
f 15/18/23 37/32/23 22/33/23
 | 
			
		||||
f 36/34/24 21/20/24 28/30/24
 | 
			
		||||
f 27/26/25 35/35/25 28/30/25
 | 
			
		||||
f 26/31/26 32/36/26 33/37/26
 | 
			
		||||
f 23/29/27 31/38/27 24/27/27
 | 
			
		||||
f 22/33/28 37/39/28 29/40/28
 | 
			
		||||
f 36/41/29 28/30/29 35/35/29
 | 
			
		||||
f 26/31/30 34/42/30 27/26/30
 | 
			
		||||
f 24/27/31 32/36/31 25/28/31
 | 
			
		||||
f 22/33/32 30/43/32 23/29/32
 | 
			
		||||
f 6/1/1 13/14/1 14/2/1
 | 
			
		||||
f 5/4/2 4/15/2 11/5/2
 | 
			
		||||
f 3/7/3 2/16/3 9/8/3
 | 
			
		||||
f 5/4/6 12/6/6 13/14/6
 | 
			
		||||
f 3/7/7 10/9/7 11/5/7
 | 
			
		||||
f 1/10/8 8/12/8 9/8/8
 | 
			
		||||
f 12/6/11 19/24/11 20/21/11
 | 
			
		||||
f 10/9/12 17/25/12 18/22/12
 | 
			
		||||
f 8/12/13 15/18/13 16/23/13
 | 
			
		||||
f 13/14/14 20/21/14 21/20/14
 | 
			
		||||
f 12/6/15 11/5/15 18/22/15
 | 
			
		||||
f 9/8/16 16/23/16 17/25/16
 | 
			
		||||
f 19/24/17 26/31/17 27/26/17
 | 
			
		||||
f 18/22/18 17/25/18 24/27/18
 | 
			
		||||
f 15/18/19 22/33/19 23/29/19
 | 
			
		||||
f 20/21/20 27/26/20 28/30/20
 | 
			
		||||
f 18/22/21 25/28/21 26/31/21
 | 
			
		||||
f 16/23/22 23/29/22 24/27/22
 | 
			
		||||
f 27/26/25 34/42/25 35/35/25
 | 
			
		||||
f 26/31/26 25/28/26 32/36/26
 | 
			
		||||
f 23/29/27 30/43/27 31/38/27
 | 
			
		||||
f 26/31/30 33/37/30 34/42/30
 | 
			
		||||
f 24/27/31 31/38/31 32/36/31
 | 
			
		||||
f 22/33/32 29/40/32 30/43/32
 | 
			
		||||
							
								
								
									
										31134
									
								
								resources/head.obj
									
									
									
									
									
								
							
							
						
						
									
										31134
									
								
								resources/head.obj
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										38
									
								
								resources/head_diffuse.pnm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								resources/head_diffuse.pnm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										66
									
								
								resources/head_tangent.pnm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								resources/head_tangent.pnm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										269
									
								
								resources/icosphere.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								resources/icosphere.obj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,269 @@
 | 
			
		||||
# Blender 4.2.0
 | 
			
		||||
# www.blender.org
 | 
			
		||||
o Icosphere
 | 
			
		||||
v 0.000000 -1.000000 0.000000
 | 
			
		||||
v 0.723607 -0.447220 0.525725
 | 
			
		||||
v -0.276388 -0.447220 0.850649
 | 
			
		||||
v -0.894426 -0.447216 0.000000
 | 
			
		||||
v -0.276388 -0.447220 -0.850649
 | 
			
		||||
v 0.723607 -0.447220 -0.525725
 | 
			
		||||
v 0.276388 0.447220 0.850649
 | 
			
		||||
v -0.723607 0.447220 0.525725
 | 
			
		||||
v -0.723607 0.447220 -0.525725
 | 
			
		||||
v 0.276388 0.447220 -0.850649
 | 
			
		||||
v 0.894426 0.447216 0.000000
 | 
			
		||||
v 0.000000 1.000000 0.000000
 | 
			
		||||
v -0.162456 -0.850654 0.499995
 | 
			
		||||
v 0.425323 -0.850654 0.309011
 | 
			
		||||
v 0.262869 -0.525738 0.809012
 | 
			
		||||
v 0.850648 -0.525736 0.000000
 | 
			
		||||
v 0.425323 -0.850654 -0.309011
 | 
			
		||||
v -0.525730 -0.850652 0.000000
 | 
			
		||||
v -0.688189 -0.525736 0.499997
 | 
			
		||||
v -0.162456 -0.850654 -0.499995
 | 
			
		||||
v -0.688189 -0.525736 -0.499997
 | 
			
		||||
v 0.262869 -0.525738 -0.809012
 | 
			
		||||
v 0.951058 0.000000 0.309013
 | 
			
		||||
v 0.951058 0.000000 -0.309013
 | 
			
		||||
v 0.000000 0.000000 1.000000
 | 
			
		||||
v 0.587786 0.000000 0.809017
 | 
			
		||||
v -0.951058 0.000000 0.309013
 | 
			
		||||
v -0.587786 0.000000 0.809017
 | 
			
		||||
v -0.587786 0.000000 -0.809017
 | 
			
		||||
v -0.951058 0.000000 -0.309013
 | 
			
		||||
v 0.587786 0.000000 -0.809017
 | 
			
		||||
v 0.000000 0.000000 -1.000000
 | 
			
		||||
v 0.688189 0.525736 0.499997
 | 
			
		||||
v -0.262869 0.525738 0.809012
 | 
			
		||||
v -0.850648 0.525736 0.000000
 | 
			
		||||
v -0.262869 0.525738 -0.809012
 | 
			
		||||
v 0.688189 0.525736 -0.499997
 | 
			
		||||
v 0.162456 0.850654 0.499995
 | 
			
		||||
v 0.525730 0.850652 0.000000
 | 
			
		||||
v -0.425323 0.850654 0.309011
 | 
			
		||||
v -0.425323 0.850654 -0.309011
 | 
			
		||||
v 0.162456 0.850654 -0.499995
 | 
			
		||||
vn 0.1024 -0.9435 0.3151
 | 
			
		||||
vn 0.7002 -0.6617 0.2680
 | 
			
		||||
vn -0.2680 -0.9435 0.1947
 | 
			
		||||
vn -0.2680 -0.9435 -0.1947
 | 
			
		||||
vn 0.1024 -0.9435 -0.3151
 | 
			
		||||
vn 0.9050 -0.3304 0.2680
 | 
			
		||||
vn 0.0247 -0.3304 0.9435
 | 
			
		||||
vn -0.8897 -0.3304 0.3151
 | 
			
		||||
vn -0.5746 -0.3304 -0.7488
 | 
			
		||||
vn 0.5346 -0.3304 -0.7779
 | 
			
		||||
vn 0.8026 -0.1256 0.5831
 | 
			
		||||
vn -0.3066 -0.1256 0.9435
 | 
			
		||||
vn -0.9921 -0.1256 -0.0000
 | 
			
		||||
vn -0.3066 -0.1256 -0.9435
 | 
			
		||||
vn 0.8026 -0.1256 -0.5831
 | 
			
		||||
vn 0.4089 0.6617 0.6284
 | 
			
		||||
vn -0.4713 0.6617 0.5831
 | 
			
		||||
vn -0.7002 0.6617 -0.2680
 | 
			
		||||
vn 0.0385 0.6617 -0.7488
 | 
			
		||||
vn 0.7240 0.6617 -0.1947
 | 
			
		||||
vn 0.2680 0.9435 -0.1947
 | 
			
		||||
vn 0.4911 0.7947 -0.3568
 | 
			
		||||
vn 0.4089 0.6617 -0.6284
 | 
			
		||||
vn -0.1024 0.9435 -0.3151
 | 
			
		||||
vn -0.1876 0.7947 -0.5773
 | 
			
		||||
vn -0.4713 0.6617 -0.5831
 | 
			
		||||
vn -0.3313 0.9435 -0.0000
 | 
			
		||||
vn -0.6071 0.7947 -0.0000
 | 
			
		||||
vn -0.7002 0.6617 0.2680
 | 
			
		||||
vn -0.1024 0.9435 0.3151
 | 
			
		||||
vn -0.1876 0.7947 0.5773
 | 
			
		||||
vn 0.0385 0.6617 0.7488
 | 
			
		||||
vn 0.2680 0.9435 0.1947
 | 
			
		||||
vn 0.4911 0.7947 0.3568
 | 
			
		||||
vn 0.7240 0.6617 0.1947
 | 
			
		||||
vn 0.8897 0.3304 -0.3151
 | 
			
		||||
vn 0.7947 0.1876 -0.5773
 | 
			
		||||
vn 0.5746 0.3304 -0.7488
 | 
			
		||||
vn -0.0247 0.3304 -0.9435
 | 
			
		||||
vn -0.3035 0.1876 -0.9342
 | 
			
		||||
vn -0.5346 0.3304 -0.7779
 | 
			
		||||
vn -0.9050 0.3304 -0.2680
 | 
			
		||||
vn -0.9822 0.1876 -0.0000
 | 
			
		||||
vn -0.9050 0.3304 0.2680
 | 
			
		||||
vn -0.5346 0.3304 0.7779
 | 
			
		||||
vn -0.3035 0.1876 0.9342
 | 
			
		||||
vn -0.0247 0.3304 0.9435
 | 
			
		||||
vn 0.5746 0.3304 0.7488
 | 
			
		||||
vn 0.7947 0.1876 0.5773
 | 
			
		||||
vn 0.8897 0.3304 0.3151
 | 
			
		||||
vn 0.3066 0.1256 -0.9435
 | 
			
		||||
vn 0.3035 -0.1876 -0.9342
 | 
			
		||||
vn 0.0247 -0.3304 -0.9435
 | 
			
		||||
vn -0.8026 0.1256 -0.5831
 | 
			
		||||
vn -0.7947 -0.1876 -0.5773
 | 
			
		||||
vn -0.8897 -0.3304 -0.3151
 | 
			
		||||
vn -0.8026 0.1256 0.5831
 | 
			
		||||
vn -0.7947 -0.1876 0.5773
 | 
			
		||||
vn -0.5746 -0.3304 0.7488
 | 
			
		||||
vn 0.3066 0.1256 0.9435
 | 
			
		||||
vn 0.3035 -0.1876 0.9342
 | 
			
		||||
vn 0.5346 -0.3304 0.7779
 | 
			
		||||
vn 0.9921 0.1256 -0.0000
 | 
			
		||||
vn 0.9822 -0.1876 -0.0000
 | 
			
		||||
vn 0.9050 -0.3304 -0.2680
 | 
			
		||||
vn 0.4713 -0.6617 -0.5831
 | 
			
		||||
vn 0.1876 -0.7947 -0.5773
 | 
			
		||||
vn -0.0385 -0.6617 -0.7488
 | 
			
		||||
vn -0.4089 -0.6617 -0.6284
 | 
			
		||||
vn -0.4911 -0.7947 -0.3568
 | 
			
		||||
vn -0.7240 -0.6617 -0.1947
 | 
			
		||||
vn -0.7240 -0.6617 0.1947
 | 
			
		||||
vn -0.4911 -0.7947 0.3568
 | 
			
		||||
vn -0.4089 -0.6617 0.6284
 | 
			
		||||
vn 0.7002 -0.6617 -0.2680
 | 
			
		||||
vn 0.6071 -0.7947 -0.0000
 | 
			
		||||
vn 0.3313 -0.9435 -0.0000
 | 
			
		||||
vn -0.0385 -0.6617 0.7488
 | 
			
		||||
vn 0.1876 -0.7947 0.5773
 | 
			
		||||
vn 0.4713 -0.6617 0.5831
 | 
			
		||||
vt 0.181819 0.000000
 | 
			
		||||
vt 0.227273 0.078731
 | 
			
		||||
vt 0.136365 0.078731
 | 
			
		||||
vt 0.272728 0.157461
 | 
			
		||||
vt 0.318182 0.078731
 | 
			
		||||
vt 0.363637 0.157461
 | 
			
		||||
vt 0.909091 0.000000
 | 
			
		||||
vt 0.954545 0.078731
 | 
			
		||||
vt 0.863636 0.078731
 | 
			
		||||
vt 0.727273 0.000000
 | 
			
		||||
vt 0.772727 0.078731
 | 
			
		||||
vt 0.681818 0.078731
 | 
			
		||||
vt 0.545455 0.000000
 | 
			
		||||
vt 0.590909 0.078731
 | 
			
		||||
vt 0.500000 0.078731
 | 
			
		||||
vt 0.318182 0.236191
 | 
			
		||||
vt 0.090910 0.157461
 | 
			
		||||
vt 0.181819 0.157461
 | 
			
		||||
vt 0.136365 0.236191
 | 
			
		||||
vt 0.818182 0.157461
 | 
			
		||||
vt 0.909091 0.157461
 | 
			
		||||
vt 0.863636 0.236191
 | 
			
		||||
vt 0.636364 0.157461
 | 
			
		||||
vt 0.727273 0.157461
 | 
			
		||||
vt 0.681818 0.236191
 | 
			
		||||
vt 0.454546 0.157461
 | 
			
		||||
vt 0.545455 0.157461
 | 
			
		||||
vt 0.500000 0.236191
 | 
			
		||||
vt 0.227273 0.236191
 | 
			
		||||
vt 0.045455 0.236191
 | 
			
		||||
vt 0.772727 0.236191
 | 
			
		||||
vt 0.590909 0.236191
 | 
			
		||||
vt 0.409092 0.236191
 | 
			
		||||
vt 0.181819 0.314921
 | 
			
		||||
vt 0.272728 0.314921
 | 
			
		||||
vt 0.227273 0.393651
 | 
			
		||||
vt 0.000000 0.314921
 | 
			
		||||
vt 0.090910 0.314921
 | 
			
		||||
vt 0.045455 0.393651
 | 
			
		||||
vt 0.727273 0.314921
 | 
			
		||||
vt 0.818182 0.314921
 | 
			
		||||
vt 0.772727 0.393651
 | 
			
		||||
vt 0.545455 0.314921
 | 
			
		||||
vt 0.636364 0.314921
 | 
			
		||||
vt 0.590909 0.393651
 | 
			
		||||
vt 0.363637 0.314921
 | 
			
		||||
vt 0.454546 0.314921
 | 
			
		||||
vt 0.409092 0.393651
 | 
			
		||||
vt 0.500000 0.393651
 | 
			
		||||
vt 0.454546 0.472382
 | 
			
		||||
vt 0.681818 0.393651
 | 
			
		||||
vt 0.636364 0.472382
 | 
			
		||||
vt 0.863636 0.393651
 | 
			
		||||
vt 0.818182 0.472382
 | 
			
		||||
vt 0.909091 0.314921
 | 
			
		||||
vt 0.136365 0.393651
 | 
			
		||||
vt 0.090910 0.472382
 | 
			
		||||
vt 0.318182 0.393651
 | 
			
		||||
vt 0.272728 0.472382
 | 
			
		||||
vt 0.954545 0.236191
 | 
			
		||||
vt 1.000000 0.157461
 | 
			
		||||
vt 0.409092 0.078731
 | 
			
		||||
vt 0.363637 0.000000
 | 
			
		||||
s 0
 | 
			
		||||
f 1/1/1 14/2/1 13/3/1
 | 
			
		||||
f 2/4/2 14/5/2 16/6/2
 | 
			
		||||
f 1/7/3 13/8/3 18/9/3
 | 
			
		||||
f 1/10/4 18/11/4 20/12/4
 | 
			
		||||
f 1/13/5 20/14/5 17/15/5
 | 
			
		||||
f 2/4/6 16/6/6 23/16/6
 | 
			
		||||
f 3/17/7 15/18/7 25/19/7
 | 
			
		||||
f 4/20/8 19/21/8 27/22/8
 | 
			
		||||
f 5/23/9 21/24/9 29/25/9
 | 
			
		||||
f 6/26/10 22/27/10 31/28/10
 | 
			
		||||
f 2/4/11 23/16/11 26/29/11
 | 
			
		||||
f 3/17/12 25/19/12 28/30/12
 | 
			
		||||
f 4/20/13 27/22/13 30/31/13
 | 
			
		||||
f 5/23/14 29/25/14 32/32/14
 | 
			
		||||
f 6/26/15 31/28/15 24/33/15
 | 
			
		||||
f 7/34/16 33/35/16 38/36/16
 | 
			
		||||
f 8/37/17 34/38/17 40/39/17
 | 
			
		||||
f 9/40/18 35/41/18 41/42/18
 | 
			
		||||
f 10/43/19 36/44/19 42/45/19
 | 
			
		||||
f 11/46/20 37/47/20 39/48/20
 | 
			
		||||
f 39/48/21 42/49/21 12/50/21
 | 
			
		||||
f 39/48/22 37/47/22 42/49/22
 | 
			
		||||
f 37/47/23 10/43/23 42/49/23
 | 
			
		||||
f 42/45/24 41/51/24 12/52/24
 | 
			
		||||
f 42/45/25 36/44/25 41/51/25
 | 
			
		||||
f 36/44/26 9/40/26 41/51/26
 | 
			
		||||
f 41/42/27 40/53/27 12/54/27
 | 
			
		||||
f 41/42/28 35/41/28 40/53/28
 | 
			
		||||
f 35/41/29 8/55/29 40/53/29
 | 
			
		||||
f 40/39/30 38/56/30 12/57/30
 | 
			
		||||
f 40/39/31 34/38/31 38/56/31
 | 
			
		||||
f 34/38/32 7/34/32 38/56/32
 | 
			
		||||
f 38/36/33 39/58/33 12/59/33
 | 
			
		||||
f 38/36/34 33/35/34 39/58/34
 | 
			
		||||
f 33/35/35 11/46/35 39/58/35
 | 
			
		||||
f 24/33/36 37/47/36 11/46/36
 | 
			
		||||
f 24/33/37 31/28/37 37/47/37
 | 
			
		||||
f 31/28/38 10/43/38 37/47/38
 | 
			
		||||
f 32/32/39 36/44/39 10/43/39
 | 
			
		||||
f 32/32/40 29/25/40 36/44/40
 | 
			
		||||
f 29/25/41 9/40/41 36/44/41
 | 
			
		||||
f 30/31/42 35/41/42 9/40/42
 | 
			
		||||
f 30/31/43 27/22/43 35/41/43
 | 
			
		||||
f 27/22/44 8/55/44 35/41/44
 | 
			
		||||
f 28/30/45 34/38/45 8/37/45
 | 
			
		||||
f 28/30/46 25/19/46 34/38/46
 | 
			
		||||
f 25/19/47 7/34/47 34/38/47
 | 
			
		||||
f 26/29/48 33/35/48 7/34/48
 | 
			
		||||
f 26/29/49 23/16/49 33/35/49
 | 
			
		||||
f 23/16/50 11/46/50 33/35/50
 | 
			
		||||
f 31/28/51 32/32/51 10/43/51
 | 
			
		||||
f 31/28/52 22/27/52 32/32/52
 | 
			
		||||
f 22/27/53 5/23/53 32/32/53
 | 
			
		||||
f 29/25/54 30/31/54 9/40/54
 | 
			
		||||
f 29/25/55 21/24/55 30/31/55
 | 
			
		||||
f 21/24/56 4/20/56 30/31/56
 | 
			
		||||
f 27/22/57 28/60/57 8/55/57
 | 
			
		||||
f 27/22/58 19/21/58 28/60/58
 | 
			
		||||
f 19/21/59 3/61/59 28/60/59
 | 
			
		||||
f 25/19/60 26/29/60 7/34/60
 | 
			
		||||
f 25/19/61 15/18/61 26/29/61
 | 
			
		||||
f 15/18/62 2/4/62 26/29/62
 | 
			
		||||
f 23/16/63 24/33/63 11/46/63
 | 
			
		||||
f 23/16/64 16/6/64 24/33/64
 | 
			
		||||
f 16/6/65 6/26/65 24/33/65
 | 
			
		||||
f 17/15/66 22/27/66 6/26/66
 | 
			
		||||
f 17/15/67 20/14/67 22/27/67
 | 
			
		||||
f 20/14/68 5/23/68 22/27/68
 | 
			
		||||
f 20/12/69 21/24/69 5/23/69
 | 
			
		||||
f 20/12/70 18/11/70 21/24/70
 | 
			
		||||
f 18/11/71 4/20/71 21/24/71
 | 
			
		||||
f 18/9/72 19/21/72 4/20/72
 | 
			
		||||
f 18/9/73 13/8/73 19/21/73
 | 
			
		||||
f 13/8/74 3/61/74 19/21/74
 | 
			
		||||
f 16/6/75 17/62/75 6/26/75
 | 
			
		||||
f 16/6/76 14/5/76 17/62/76
 | 
			
		||||
f 14/5/77 1/63/77 17/62/77
 | 
			
		||||
f 13/3/78 15/18/78 3/17/78
 | 
			
		||||
f 13/3/79 14/2/79 15/18/79
 | 
			
		||||
f 14/2/80 2/4/80 15/18/80
 | 
			
		||||
							
								
								
									
										15
									
								
								resources/polygon.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								resources/polygon.obj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# Blender 4.2.0
 | 
			
		||||
# www.blender.org
 | 
			
		||||
o Sphere
 | 
			
		||||
v 0.707107 0.000000 0.707107
 | 
			
		||||
v 0.653281 -0.382683 0.653281
 | 
			
		||||
v 0.000000 0.000000 1.000000
 | 
			
		||||
v 0.000000 -0.382683 0.923879
 | 
			
		||||
vn 0.3764 -0.1807 0.9087
 | 
			
		||||
vt 0.375000 0.375000
 | 
			
		||||
vt 0.250000 0.500000
 | 
			
		||||
vt 0.250000 0.375000
 | 
			
		||||
vt 0.375000 0.500000
 | 
			
		||||
s 0
 | 
			
		||||
f 2/1/1 3/2/1 4/3/1
 | 
			
		||||
f 2/1/1 1/4/1 3/2/1
 | 
			
		||||
							
								
								
									
										7
									
								
								src/constants.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/constants.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#ifndef CONSTANTS_H
 | 
			
		||||
#define CONSTANTS_H
 | 
			
		||||
 | 
			
		||||
#define DEPTH_MAX 255
 | 
			
		||||
#define TRIANGLE_VERTICES 3
 | 
			
		||||
 | 
			
		||||
#endif // CONSTANTS_H
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
 | 
			
		||||
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y, u64 base_size);
 | 
			
		||||
 | 
			
		||||
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
 | 
			
		||||
  if (!arena || !buffer || buffer->width == 0 || buffer->height == 0) {
 | 
			
		||||
@@ -21,13 +21,22 @@ bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
 | 
			
		||||
  u64 idx = calculate_pixel_index(buffer, x, y, base_size);
 | 
			
		||||
  i64 idx = calculate_pixel_index(buffer, x, y, base_size);
 | 
			
		||||
  if (idx == -1) {
 | 
			
		||||
    idx = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ((u8 *)(buffer->buf)) + idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
 | 
			
		||||
  u64 idx = calculate_pixel_index(buffer, x, y, base_size);
 | 
			
		||||
  i64 idx = calculate_pixel_index(buffer, x, y, base_size);
 | 
			
		||||
  if (idx == -1) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _clear_buffer(Buffer *buffer, void *value, u64 base_size) {
 | 
			
		||||
@@ -74,7 +83,11 @@ void save_image(const Image *img, const char *filename) {
 | 
			
		||||
  write_p7_image(img->width, img->height, (u8 *)(img->buf), filename);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal u64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
 | 
			
		||||
internal i64 calculate_pixel_index(Buffer *buffer, u64 x, u64 y,
 | 
			
		||||
                                   u64 base_size) {
 | 
			
		||||
  if (x < 0 || y < 0 || x >= buffer->width || y >= buffer->height) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (y * buffer->width + x) * base_size;
 | 
			
		||||
}
 | 
			
		||||
@@ -6,12 +6,14 @@
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define BUF_TYPE(TYPE, NAME)                                                   \
 | 
			
		||||
  typedef struct {                                                             \
 | 
			
		||||
  typedef struct NAME {                                                        \
 | 
			
		||||
    u64 width;                                                                 \
 | 
			
		||||
    u64 height;                                                                \
 | 
			
		||||
    TYPE *buf;                                                                 \
 | 
			
		||||
  } NAME
 | 
			
		||||
 | 
			
		||||
#define BUF_SIZE(BUF) sizeof(*((BUF)->buf))
 | 
			
		||||
 | 
			
		||||
typedef struct colour Colour;
 | 
			
		||||
struct colour {
 | 
			
		||||
  u8 r;
 | 
			
		||||
@@ -24,14 +26,10 @@ BUF_TYPE(void, Buffer);
 | 
			
		||||
BUF_TYPE(Colour, Image);
 | 
			
		||||
BUF_TYPE(f32, Depth);
 | 
			
		||||
 | 
			
		||||
#define init_buffer(ARENA, BUF)                                                \
 | 
			
		||||
  _init_buffer(ARENA, (Buffer *)BUF, sizeof(*((BUF)->buf)))
 | 
			
		||||
#define get_pixel(TYPE, BUF, X, Y)                                             \
 | 
			
		||||
  (*((TYPE *)(_get_pixel((Buffer *)BUF, X, Y, sizeof(*((BUF)->buf))))))
 | 
			
		||||
#define set_pixel(BUF, X, Y, VAL_PTR)                                          \
 | 
			
		||||
  _set_pixel((Buffer *)BUF, X, Y, VAL_PTR, sizeof(*((BUF)->buf)))
 | 
			
		||||
#define clear_buffer(BUF, VAL_PTR)                                             \
 | 
			
		||||
  _clear_buffer((Buffer *)BUF, VAL_PTR, sizeof(*((BUF)->buf)))
 | 
			
		||||
#define init_buffer(ARENA, BUF)       (_init_buffer(ARENA, (Buffer *)BUF, BUF_SIZE(BUF)))
 | 
			
		||||
#define get_pixel(TYPE, BUF, X, Y)    (*((TYPE *)(_get_pixel((Buffer *)BUF, X, Y, BUF_SIZE(BUF)))))
 | 
			
		||||
#define set_pixel(BUF, X, Y, VAL_PTR) (_set_pixel((Buffer *)BUF, X, Y, VAL_PTR, BUF_SIZE(BUF)))
 | 
			
		||||
#define clear_buffer(BUF, VAL_PTR)    (_clear_buffer((Buffer *)BUF, VAL_PTR, BUF_SIZE(BUF)))
 | 
			
		||||
 | 
			
		||||
bool _init_buffer(Arena *arena, Buffer *buffer, u64 base_size);
 | 
			
		||||
u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size);
 | 
			
		||||
							
								
								
									
										48
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/main.c
									
									
									
									
									
								
							@@ -1,46 +1,6 @@
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "mem_utils.h"
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "tiny.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  TINY_EXIT_SUCCESS,
 | 
			
		||||
  TINY_EXIT_ARENA_INIT_FAILED,
 | 
			
		||||
  TINY_EXIT_RENDER_INIT_FAILED,
 | 
			
		||||
  TINY_EXIT_MODEL_LOAD_FAILED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(void) {
 | 
			
		||||
  Arena *arena = NULL;
 | 
			
		||||
  if (!wapp_mem_arena_init(&arena, 10ul * 1024ul * 1024ul * 1024ul,
 | 
			
		||||
                           WAPP_MEM_ALLOC_RESERVE, false)) {
 | 
			
		||||
    return TINY_EXIT_ARENA_INIT_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  srand(time(NULL));
 | 
			
		||||
 | 
			
		||||
  Colour bg = {.r = 42, .g = 45, .b = 52, .a = 255};
 | 
			
		||||
  Colour teal = {.r = 14, .g = 156, .b = 208, .a = 255};
 | 
			
		||||
  Colour orange = {.r = 242, .g = 100, .b = 48, .a = 255};
 | 
			
		||||
  Render render;
 | 
			
		||||
  if (!init_render(arena, &render, 1200, 1200)) {
 | 
			
		||||
    return TINY_EXIT_RENDER_INIT_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Model model = load_obj_file(arena, "resources/head.obj");
 | 
			
		||||
  if (IS_NULL_MODEL(model)) {
 | 
			
		||||
    return TINY_EXIT_MODEL_LOAD_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clear_buffer(&(render.img), &bg);
 | 
			
		||||
  render_model(&model, &render, teal, RENDER_TYPE_SHADED, COLOUR_TYPE_FIXED);
 | 
			
		||||
  save_image(&(render.img), "result.pam");
 | 
			
		||||
 | 
			
		||||
  wapp_mem_arena_destroy(&arena);
 | 
			
		||||
 | 
			
		||||
  return TINY_EXIT_SUCCESS;
 | 
			
		||||
i32 main(i32 argc, char *argv[]) {
 | 
			
		||||
  return tiny_main(argc, argv);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								src/model/obj.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/model/obj.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "pam.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
Model load_obj_file(Arena *arena, const char *filename, const char *diffuse, const char *tangent) {
 | 
			
		||||
  if (!arena) {
 | 
			
		||||
    return INVALID_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FILE *fp = fopen(filename, "r");
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    return INVALID_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Model model = (Model){
 | 
			
		||||
      .vertices            = list_create(V3f, arena),
 | 
			
		||||
      .normals             = list_create(V3f, arena),
 | 
			
		||||
      .texture_coordinates = list_create(V2f, arena),
 | 
			
		||||
      .triangles           = list_create(Triangle, arena),
 | 
			
		||||
  };
 | 
			
		||||
  if (!(model.vertices) || !(model.normals) || !(model.texture_coordinates) || !(model.triangles)) {
 | 
			
		||||
    return INVALID_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char line[8192];
 | 
			
		||||
  char identifier[8];
 | 
			
		||||
  V3f vertex;
 | 
			
		||||
  V3f normal;
 | 
			
		||||
  V2f coord;
 | 
			
		||||
  Triangle triangle;
 | 
			
		||||
  f32 vx, vy, vz;
 | 
			
		||||
  f32 nx, ny, nz;
 | 
			
		||||
  f32 u, v;
 | 
			
		||||
  u64 fp0, fp1, fp2;
 | 
			
		||||
  u64 vn0, vn1, vn2;
 | 
			
		||||
  u64 tx0, tx1, tx2;
 | 
			
		||||
  while (fgets(line, 8191, fp) != NULL) {
 | 
			
		||||
    sscanf(line, "%s", identifier);
 | 
			
		||||
    if (strncmp(identifier, "v", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%f %f %f", &vx, &vy, &vz);
 | 
			
		||||
      vertex.x = vx;
 | 
			
		||||
      vertex.y = vy;
 | 
			
		||||
      vertex.z = vz;
 | 
			
		||||
      list_append(V3f, arena, model.vertices, vertex);
 | 
			
		||||
    } else if (strncmp(identifier, "vn", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%f %f %f", &nx, &ny, &nz);
 | 
			
		||||
      normal.x = nx;
 | 
			
		||||
      normal.y = ny;
 | 
			
		||||
      normal.z = nz;
 | 
			
		||||
      list_append(V3f, arena, model.normals, normal);
 | 
			
		||||
    } else if (strncmp(identifier, "vt", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%f %f", &u, &v);
 | 
			
		||||
      coord.u = u;
 | 
			
		||||
      coord.v = 1.0f - v;
 | 
			
		||||
      list_append(V2f, arena, model.texture_coordinates, coord);
 | 
			
		||||
    } else if (strncmp(identifier, "f", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%lu/%lu/%lu %lu/%lu/%lu %lu/%lu/%lu",
 | 
			
		||||
             &fp0, &tx0, &vn0,
 | 
			
		||||
             &fp1, &tx1, &vn1,
 | 
			
		||||
             &fp2, &tx2, &vn2);
 | 
			
		||||
      // OBJ indices start from 1
 | 
			
		||||
      triangle.p0  = fp0 - 1;
 | 
			
		||||
      triangle.p1  = fp1 - 1;
 | 
			
		||||
      triangle.p2  = fp2 - 1;
 | 
			
		||||
      triangle.tx0 = tx0 - 1;
 | 
			
		||||
      triangle.tx1 = tx1 - 1;
 | 
			
		||||
      triangle.tx2 = tx2 - 1;
 | 
			
		||||
      triangle.n0  = vn0 - 1;
 | 
			
		||||
      triangle.n1  = vn1 - 1;
 | 
			
		||||
      triangle.n2  = vn2 - 1;
 | 
			
		||||
      list_append(Triangle, arena, model.triangles, triangle);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (diffuse) {
 | 
			
		||||
    model.texture = load_p6_image(arena, diffuse);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tangent) {
 | 
			
		||||
    model.normal = load_p6_image(arena, tangent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return model;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								src/model/obj.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/model/obj.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
#ifndef OBJ_H
 | 
			
		||||
#define OBJ_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "constants.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
#define INVALID_MODEL ((Model){0})
 | 
			
		||||
#define IS_INVALID_MODEL(m) (m.vertices == NULL || m.triangles == NULL)
 | 
			
		||||
 | 
			
		||||
typedef struct triangle Triangle;
 | 
			
		||||
struct triangle {
 | 
			
		||||
  union {
 | 
			
		||||
    u64 positions[TRIANGLE_VERTICES];
 | 
			
		||||
    struct {
 | 
			
		||||
      u64 p0;
 | 
			
		||||
      u64 p1;
 | 
			
		||||
      u64 p2;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
  union {
 | 
			
		||||
    u64 normals[TRIANGLE_VERTICES];
 | 
			
		||||
    struct {
 | 
			
		||||
      u64 n0;
 | 
			
		||||
      u64 n1;
 | 
			
		||||
      u64 n2;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
  union {
 | 
			
		||||
    u64 coordinates[TRIANGLE_VERTICES];
 | 
			
		||||
    struct {
 | 
			
		||||
      u64 tx0;
 | 
			
		||||
      u64 tx1;
 | 
			
		||||
      u64 tx2;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
MAKE_LIST_TYPE(Triangle);
 | 
			
		||||
 | 
			
		||||
typedef struct point_light PointLight;
 | 
			
		||||
struct point_light {
 | 
			
		||||
  V3f diffuse_intensity;
 | 
			
		||||
  V3f specular_intensity;
 | 
			
		||||
  V3f position;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct model Model;
 | 
			
		||||
struct model {
 | 
			
		||||
  LIST_TYPE(V3f)      *vertices;
 | 
			
		||||
  LIST_TYPE(V3f)      *normals;
 | 
			
		||||
  LIST_TYPE(V2f)      *texture_coordinates;
 | 
			
		||||
  LIST_TYPE(Triangle) *triangles;
 | 
			
		||||
  Image               *texture;
 | 
			
		||||
  Image               *normal;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Model load_obj_file(Arena *arena, const char *filename, const char *diffuse, const char *tangent);
 | 
			
		||||
 | 
			
		||||
#endif // OBJ_H
 | 
			
		||||
							
								
								
									
										172
									
								
								src/model/render.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								src/model/render.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
#include "render.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "constants.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
Render g_render_passes[COUNT_RENDER_PASS] = {0};
 | 
			
		||||
 | 
			
		||||
typedef struct triangle_bbox TriangleBBox;
 | 
			
		||||
struct triangle_bbox {
 | 
			
		||||
  u64 x0;
 | 
			
		||||
  u64 y0;
 | 
			
		||||
  u64 x1;
 | 
			
		||||
  u64 y1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
internal void         render_triangle(const Triangle *triangle, const Model *model, ShaderID shader,
 | 
			
		||||
                                      Render *render, RenderType render_type, Colour colour);
 | 
			
		||||
internal void         fill_triangle(Render *render, ShaderID shader, VertexData vertices[TRIANGLE_VERTICES],
 | 
			
		||||
                                    Colour colour, const Model *model, RenderType type);
 | 
			
		||||
internal TriangleBBox get_triangle_bbox(const Image *img, V2f vertices[TRIANGLE_VERTICES]);
 | 
			
		||||
internal V3f          get_barycentric_coords(V2f a, V2f b, V2f c, V2f p);
 | 
			
		||||
internal V2f          get_viewport_vertex(const V3f *vertex, const Image *img);
 | 
			
		||||
 | 
			
		||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
 | 
			
		||||
  render->img = (Image){.width = width, .height = height};
 | 
			
		||||
  if (!init_buffer(arena, &(render->img))) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render->depth = (Depth){.width = width, .height = height};
 | 
			
		||||
  if (!init_buffer(arena, &(render->depth))) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  f32 inf = -INFINITY;
 | 
			
		||||
  clear_buffer(&(render->depth), &inf);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_model(const Model *model, Render *render, ShaderID shader, RenderType render_type, Colour colour) {
 | 
			
		||||
  Triangle triangle;
 | 
			
		||||
  for (u64 i = 0; i < model->triangles->count; ++i) {
 | 
			
		||||
    triangle = list_get(model->triangles, i);
 | 
			
		||||
    render_triangle(&triangle, model, shader, render, render_type, colour);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void render_triangle(const Triangle *triangle, const Model *model, ShaderID shader,
 | 
			
		||||
                              Render *render, RenderType render_type, Colour colour) {
 | 
			
		||||
  Image *img = &(render->img);
 | 
			
		||||
  VertexData vertices[TRIANGLE_VERTICES];
 | 
			
		||||
  for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
 | 
			
		||||
    vertices[i].position = list_get(model->vertices, triangle->positions[i]);
 | 
			
		||||
    vertices[i].normal   = list_get(model->normals, triangle->normals[i]);
 | 
			
		||||
    vertices[i].uv       = list_get(model->texture_coordinates, triangle->coordinates[i]);
 | 
			
		||||
 | 
			
		||||
    vertices[i]          = run_vertex_shader(shader, &vertices[i], i, model);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (render_type == RENDER_TYPE_WIREFRAME) {
 | 
			
		||||
    // V3f v0, v1;
 | 
			
		||||
    // u64 x0, y0, x1, y1;
 | 
			
		||||
    // for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
 | 
			
		||||
    //   v0 = vertices[i];
 | 
			
		||||
    //   v1 = vertices[(i + 1) % TRIANGLE_VERTICES];
 | 
			
		||||
    //
 | 
			
		||||
    //   draw_line(img, (u64)v0.x, (u64)v0.y, (u64)v1.x, (u64)v1.y, colour);
 | 
			
		||||
    // }
 | 
			
		||||
  } else if (render_type == RENDER_TYPE_FILLED || render_type == RENDER_TYPE_SHADED) {
 | 
			
		||||
    fill_triangle(render, shader, vertices, colour, model, render_type);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void fill_triangle(Render *render, ShaderID shader, VertexData vertices[TRIANGLE_VERTICES],
 | 
			
		||||
                            Colour colour, const Model *model, RenderType type) {
 | 
			
		||||
  Image   *img   = &(render->img);
 | 
			
		||||
  Depth   *depth = &(render->depth);
 | 
			
		||||
 | 
			
		||||
  V2f vp_verts[TRIANGLE_VERTICES] = {0};
 | 
			
		||||
  for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
 | 
			
		||||
    vp_verts[i] = get_viewport_vertex(&vertices[i].position, img);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TriangleBBox bbox = get_triangle_bbox(img, vp_verts);
 | 
			
		||||
 | 
			
		||||
  V2f            point;
 | 
			
		||||
  V3f            coords;
 | 
			
		||||
  f32            z;
 | 
			
		||||
  f32            zbuf;
 | 
			
		||||
  V4f            shader_colour;
 | 
			
		||||
  Colour         output_colour;
 | 
			
		||||
  FragmentResult result;
 | 
			
		||||
 | 
			
		||||
  f32 intensity = 1.0f;
 | 
			
		||||
 | 
			
		||||
  for (u64 y = bbox.y0; y <= bbox.y1; ++y) {
 | 
			
		||||
    for (u64 x = bbox.x0; x <= bbox.x1; ++x) {
 | 
			
		||||
      point = (V2f){x, y};
 | 
			
		||||
      coords = get_barycentric_coords(vp_verts[0], vp_verts[1], vp_verts[2], point);
 | 
			
		||||
      if (coords.x < 0.0f || coords.y < 0.0f || coords.z < 0.0f) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      z    = 0.0f;
 | 
			
		||||
      z    += vertices[0].position.z * coords.x +
 | 
			
		||||
              vertices[1].position.z * coords.y +
 | 
			
		||||
              vertices[2].position.z * coords.z;
 | 
			
		||||
      zbuf = get_pixel(f32, &(render->depth), x, y);
 | 
			
		||||
 | 
			
		||||
      if (z <= zbuf) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      shader_colour = (V4f){.r = colour.r, .g = colour.g, .b = colour.b, .a = colour.a};
 | 
			
		||||
      result        = run_fragment_shader(shader, &coords, &shader_colour, model);
 | 
			
		||||
      if (DISCARD_FRAGMENT(result)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      output_colour = (Colour){
 | 
			
		||||
          .r = clamp(result.colour.r, 0, UINT8_MAX),
 | 
			
		||||
          .g = clamp(result.colour.g, 0, UINT8_MAX),
 | 
			
		||||
          .b = clamp(result.colour.b, 0, UINT8_MAX),
 | 
			
		||||
          .a = clamp(result.colour.a, 0, UINT8_MAX),
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      set_pixel(depth, x, y, &z);
 | 
			
		||||
      set_pixel(img, x, y, &output_colour);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal TriangleBBox get_triangle_bbox(const Image *img, V2f vertices[TRIANGLE_VERTICES]) {
 | 
			
		||||
  f32 x0 = min(vertices[0].x, min(vertices[1].x, vertices[2].x));
 | 
			
		||||
  f32 x1 = max(vertices[0].x, max(vertices[1].x, vertices[2].x));
 | 
			
		||||
  f32 y0 = min(vertices[0].y, min(vertices[1].y, vertices[2].y));
 | 
			
		||||
  f32 y1 = max(vertices[0].y, max(vertices[1].y, vertices[2].y));
 | 
			
		||||
 | 
			
		||||
  return (TriangleBBox){
 | 
			
		||||
      .x0 = x0,
 | 
			
		||||
      .y0 = y0,
 | 
			
		||||
      .x1 = x1,
 | 
			
		||||
      .y1 = y1,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal V3f get_barycentric_coords(V2f a, V2f b, V2f c, V2f p) {
 | 
			
		||||
  V3f x_vec = V3(V3f, f32, c.x, b.x, a.x, a.x, a.x, p.x);
 | 
			
		||||
  V3f y_vec = V3(V3f, f32, c.y, b.y, a.y, a.y, a.y, p.y);
 | 
			
		||||
 | 
			
		||||
  V3f u = cross_product(x_vec, y_vec);
 | 
			
		||||
  if (fabsf(u.z) < 1e-2) {
 | 
			
		||||
    return (V3f){-1.0f, 1.0f, 1.0f};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (V3f){1.0f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal V2f get_viewport_vertex(const V3f *vertex, const Image *img) {
 | 
			
		||||
  V3f output = *vertex;
 | 
			
		||||
  output.x = clamp(output.x, 0.0f, img->width);
 | 
			
		||||
  output.y = clamp(output.y, 0.0f, img->height);
 | 
			
		||||
 | 
			
		||||
  return (V2f){output.x, output.y};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								src/model/render.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/model/render.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
#ifndef RENDER_H
 | 
			
		||||
#define RENDER_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  RENDER_TYPE_WIREFRAME,
 | 
			
		||||
  RENDER_TYPE_FILLED,
 | 
			
		||||
  RENDER_TYPE_SHADED,
 | 
			
		||||
 | 
			
		||||
  COUNT_RENDER_TYPE,
 | 
			
		||||
} RenderType;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  PROJECTION_TYPE_ORTHOGRAPHIC,
 | 
			
		||||
  PROJECTION_TYPE_PERSPECTIVE,
 | 
			
		||||
 | 
			
		||||
  COUNT_PROJECTION_TYPE,
 | 
			
		||||
} ProjectionType;
 | 
			
		||||
 | 
			
		||||
typedef struct render Render;
 | 
			
		||||
struct render {
 | 
			
		||||
  Image img;
 | 
			
		||||
  Depth depth;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum render_pass {
 | 
			
		||||
  RENDER_PASS_SHADOW,
 | 
			
		||||
  RENDER_PASS_MAIN,
 | 
			
		||||
 | 
			
		||||
  COUNT_RENDER_PASS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern Render g_render_passes[COUNT_RENDER_PASS];
 | 
			
		||||
 | 
			
		||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height);
 | 
			
		||||
void render_model(const Model *model, Render *render, ShaderID shader, RenderType render_type, Colour colour);
 | 
			
		||||
 | 
			
		||||
#endif // RENDER_H
 | 
			
		||||
							
								
								
									
										297
									
								
								src/obj.c
									
									
									
									
									
								
							
							
						
						
									
										297
									
								
								src/obj.c
									
									
									
									
									
								
							@@ -1,297 +0,0 @@
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define TRIANGLE_VERTICES 3
 | 
			
		||||
 | 
			
		||||
#define V2(T, ELEM_T, X0, Y0, X1, Y1)                                          \
 | 
			
		||||
  ((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
 | 
			
		||||
#define V3(T, ELEM_T, X0, Y0, Z0, X1, Y1, Z1)                                  \
 | 
			
		||||
  ((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0,                       \
 | 
			
		||||
       (ELEM_T)Z1 - (ELEM_T)Z0})
 | 
			
		||||
#define dot_v2(V1, V2) ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y)
 | 
			
		||||
#define dot_v3(V1, V2)                                                         \
 | 
			
		||||
  ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z)
 | 
			
		||||
#define normalise_v3(V)                                                        \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    f32 magnitude = sqrtf(dot_v3(V, V));                                       \
 | 
			
		||||
    V.x /= magnitude;                                                          \
 | 
			
		||||
    V.y /= magnitude;                                                          \
 | 
			
		||||
    V.z /= magnitude;                                                          \
 | 
			
		||||
  } while (0);
 | 
			
		||||
#define cross_product(V1, V2)                                                  \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .x = V1.y * V2.z - V1.z * V2.y,                                          \
 | 
			
		||||
      .y = V1.z * V2.x - V1.x * V2.z,                                          \
 | 
			
		||||
      .z = V1.x * V2.y - V1.y * V2.x,                                          \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
typedef struct triangle_bbox TriangleBBox;
 | 
			
		||||
struct triangle_bbox {
 | 
			
		||||
  u64 x0;
 | 
			
		||||
  u64 y0;
 | 
			
		||||
  u64 x1;
 | 
			
		||||
  u64 y1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct i64x2 V2i;
 | 
			
		||||
struct i64x2 {
 | 
			
		||||
  i64 x;
 | 
			
		||||
  i64 y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct f32x3 V3f;
 | 
			
		||||
struct f32x3 {
 | 
			
		||||
  f32 x;
 | 
			
		||||
  f32 y;
 | 
			
		||||
  f32 z;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct u64x3 V3u;
 | 
			
		||||
struct u64x3 {
 | 
			
		||||
  u64 x;
 | 
			
		||||
  u64 y;
 | 
			
		||||
  u64 z;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct f32_3x3 M3x3f;
 | 
			
		||||
struct f32_3x3 {
 | 
			
		||||
  V3f row0;
 | 
			
		||||
  V3f row1;
 | 
			
		||||
  V3f row2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
internal void render_triangle(const Triangle *triangle, const Model *model,
 | 
			
		||||
                              Render *render, Colour colour, RenderType type);
 | 
			
		||||
internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
 | 
			
		||||
                            Colour colour);
 | 
			
		||||
internal TriangleBBox get_triangle_bbox(const Image *img,
 | 
			
		||||
                                        Vertex vertices[TRIANGLE_VERTICES]);
 | 
			
		||||
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
 | 
			
		||||
                                    const V2i *ab, const V2i *ac,
 | 
			
		||||
                                    const V2i *ap);
 | 
			
		||||
internal void get_image_coordinates(const Vertex *vertex, const Image *img,
 | 
			
		||||
                                    u64 *x, u64 *y);
 | 
			
		||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max);
 | 
			
		||||
 | 
			
		||||
V3f g_light_dir = {0.0f, 0.0f, -1.0f};
 | 
			
		||||
 | 
			
		||||
Model load_obj_file(Arena *arena, const char *filename) {
 | 
			
		||||
  if (!arena) {
 | 
			
		||||
    return NULL_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FILE *fp = fopen(filename, "r");
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    return NULL_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Model model = (Model){
 | 
			
		||||
      .vertices = list_create(Vertex, arena),
 | 
			
		||||
      .triangles = list_create(Triangle, arena),
 | 
			
		||||
  };
 | 
			
		||||
  if (!(model.vertices) || !(model.triangles)) {
 | 
			
		||||
    return NULL_MODEL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char line[8192];
 | 
			
		||||
  char identifier[8];
 | 
			
		||||
  Vertex vertex;
 | 
			
		||||
  Triangle triangle;
 | 
			
		||||
  f32 vx, vy, vz;
 | 
			
		||||
  u64 fp0, fp1, fp2;
 | 
			
		||||
  u64 ign_0_1, ign_0_2;
 | 
			
		||||
  u64 ign_1_1, ign_1_2;
 | 
			
		||||
  u64 ign_2_1, ign_2_2;
 | 
			
		||||
  while (fgets(line, 8191, fp) != NULL) {
 | 
			
		||||
    sscanf(line, "%s", identifier);
 | 
			
		||||
    if (strncmp(identifier, "v", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%f %f %f", &vx, &vy, &vz);
 | 
			
		||||
      vertex.x = vx;
 | 
			
		||||
      vertex.y = vy;
 | 
			
		||||
      vertex.z = vz;
 | 
			
		||||
      list_append(Vertex, arena, model.vertices, vertex);
 | 
			
		||||
    } else if (strncmp(identifier, "f", 8) == 0) {
 | 
			
		||||
      sscanf(line + 2, "%lu/%lu/%lu %lu/%lu/%lu %lu/%lu/%lu", &fp0, &ign_0_1,
 | 
			
		||||
             &ign_0_2, &fp1, &ign_1_1, &ign_1_2, &fp2, &ign_2_1, &ign_2_2);
 | 
			
		||||
      // OBJ indices start from 1
 | 
			
		||||
      triangle.p0 = fp0 - 1;
 | 
			
		||||
      triangle.p1 = fp1 - 1;
 | 
			
		||||
      triangle.p2 = fp2 - 1;
 | 
			
		||||
      list_append(Triangle, arena, model.triangles, triangle);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return model;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
 | 
			
		||||
  render->img = (Image){.width = width, .height = height};
 | 
			
		||||
  if (!init_buffer(arena, &(render->img))) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render->depth = (Depth){.width = width, .height = height};
 | 
			
		||||
  if (!init_buffer(arena, &(render->depth))) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  f32 inf = -1.0f * INFINITY;
 | 
			
		||||
  clear_buffer(&(render->depth), &inf);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_model(const Model *model, Render *render, Colour colour,
 | 
			
		||||
                  RenderType type, ColourType colour_type) {
 | 
			
		||||
  Triangle triangle;
 | 
			
		||||
 | 
			
		||||
  for (u64 i = 0; i < model->triangles->count; ++i) {
 | 
			
		||||
    triangle = list_get(model->triangles, i);
 | 
			
		||||
    if (colour_type == COLOUR_TYPE_RANDOM) {
 | 
			
		||||
      colour = (Colour){.r = rand() % UINT8_MAX,
 | 
			
		||||
                        .g = rand() % UINT8_MAX,
 | 
			
		||||
                        .b = rand() % UINT8_MAX,
 | 
			
		||||
                        .a = 255};
 | 
			
		||||
    }
 | 
			
		||||
    render_triangle(&triangle, model, render, colour, type);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void render_triangle(const Triangle *triangle, const Model *model,
 | 
			
		||||
                              Render *render, Colour colour, RenderType type) {
 | 
			
		||||
  Image *img = &(render->img);
 | 
			
		||||
  Vertex vertices[TRIANGLE_VERTICES] = {
 | 
			
		||||
      list_get(model->vertices, triangle->p0),
 | 
			
		||||
      list_get(model->vertices, triangle->p1),
 | 
			
		||||
      list_get(model->vertices, triangle->p2),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (type == RENDER_TYPE_WIREFRAME) {
 | 
			
		||||
    Vertex v0, v1;
 | 
			
		||||
    u64 x0, y0, x1, y1;
 | 
			
		||||
    for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) {
 | 
			
		||||
      v0 = vertices[i];
 | 
			
		||||
      v1 = vertices[(i + 1) % TRIANGLE_VERTICES];
 | 
			
		||||
 | 
			
		||||
      get_image_coordinates(&v0, img, &x0, &y0);
 | 
			
		||||
      get_image_coordinates(&v1, img, &x1, &y1);
 | 
			
		||||
 | 
			
		||||
      draw_line(img, x0, y0, x1, y1, colour);
 | 
			
		||||
    }
 | 
			
		||||
  } else if (type == RENDER_TYPE_FILLED || type == RENDER_TYPE_SHADED) {
 | 
			
		||||
    f32 intensity = 1.0f;
 | 
			
		||||
 | 
			
		||||
    if (type == RENDER_TYPE_SHADED) {
 | 
			
		||||
      V3f ab = V3(V3f, f32, vertices[0].x, vertices[0].y, vertices[0].z,
 | 
			
		||||
                  vertices[1].x, vertices[1].y, vertices[1].z);
 | 
			
		||||
      V3f ac = V3(V3f, f32, vertices[0].x, vertices[0].y, vertices[0].z,
 | 
			
		||||
                  vertices[2].x, vertices[2].y, vertices[2].z);
 | 
			
		||||
 | 
			
		||||
      V3f normal = cross_product(ac, ab);
 | 
			
		||||
      normalise_v3(normal);
 | 
			
		||||
 | 
			
		||||
      intensity = dot_v3(normal, g_light_dir);
 | 
			
		||||
 | 
			
		||||
      colour.r *= intensity;
 | 
			
		||||
      colour.g *= intensity;
 | 
			
		||||
      colour.b *= intensity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (intensity > 0.0f) {
 | 
			
		||||
      fill_triangle(render, vertices, colour);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
 | 
			
		||||
                            Colour colour) {
 | 
			
		||||
  Image *img = &(render->img);
 | 
			
		||||
  Depth *depth = &(render->depth);
 | 
			
		||||
  TriangleBBox bbox = get_triangle_bbox(img, vertices);
 | 
			
		||||
 | 
			
		||||
  u64 v0x, v0y, v1x, v1y, v2x, v2y;
 | 
			
		||||
  get_image_coordinates(&(vertices[0]), img, &v0x, &v0y);
 | 
			
		||||
  get_image_coordinates(&(vertices[1]), img, &v1x, &v1y);
 | 
			
		||||
  get_image_coordinates(&(vertices[2]), img, &v2x, &v2y);
 | 
			
		||||
 | 
			
		||||
  V2i ab = V2(V2i, i64, v0x, v0y, v1x, v1y);
 | 
			
		||||
  V2i ac = V2(V2i, i64, v0x, v0y, v2x, v2y);
 | 
			
		||||
  f32 d00 = dot_v2(ab, ab);
 | 
			
		||||
  f32 d01 = dot_v2(ab, ac);
 | 
			
		||||
  f32 d11 = dot_v2(ac, ac);
 | 
			
		||||
  f32 denom = (f32)d00 * (f32)d11 - (f32)d01 * (f32)d01;
 | 
			
		||||
  V2i ap;
 | 
			
		||||
  V3f coords;
 | 
			
		||||
  f32 z;
 | 
			
		||||
  f32 zbuf;
 | 
			
		||||
 | 
			
		||||
  for (u64 y = bbox.y0; y < bbox.y1; ++y) {
 | 
			
		||||
    for (u64 x = bbox.x0; x < bbox.x1; ++x) {
 | 
			
		||||
      ap = V2(V2i, i64, v0x, v0y, x, y);
 | 
			
		||||
      coords = get_barycentric_coords(d00, d01, d11, denom, &ab, &ac, &ap);
 | 
			
		||||
      if (coords.x < 0.0f || coords.y < 0.0f || coords.z < 0.0f) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      z = 0.0f;
 | 
			
		||||
      z += vertices[0].z * coords.x + vertices[1].z * coords.y +
 | 
			
		||||
           vertices[2].z * coords.z;
 | 
			
		||||
      zbuf = get_pixel(f32, &(render->depth), x, y);
 | 
			
		||||
 | 
			
		||||
      if (z > zbuf) {
 | 
			
		||||
        set_pixel(depth, x, y, &z);
 | 
			
		||||
        set_pixel(img, x, y, &colour);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal TriangleBBox get_triangle_bbox(const Image *img,
 | 
			
		||||
                                        Vertex vertices[TRIANGLE_VERTICES]) {
 | 
			
		||||
  f32 x0 = min(vertices[0].x, min(vertices[1].x, vertices[2].x));
 | 
			
		||||
  f32 x1 = max(vertices[0].x, max(vertices[1].x, vertices[2].x));
 | 
			
		||||
  // NOTE (Abdelrahman): Because y is flipped, we use max for the minimum and
 | 
			
		||||
  // min for the maximum
 | 
			
		||||
  f32 y0 = max(vertices[0].y, max(vertices[1].y, vertices[2].y));
 | 
			
		||||
  f32 y1 = min(vertices[0].y, min(vertices[1].y, vertices[2].y));
 | 
			
		||||
 | 
			
		||||
  return (TriangleBBox){
 | 
			
		||||
      .x0 = ndc_to_image_coordinate(x0, img->width),
 | 
			
		||||
      .y0 = ndc_to_image_coordinate(0.0f - y0, img->height),
 | 
			
		||||
      .x1 = ndc_to_image_coordinate(x1, img->width),
 | 
			
		||||
      .y1 = ndc_to_image_coordinate(0.0f - y1, img->height),
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
 | 
			
		||||
                                    const V2i *ab, const V2i *ac,
 | 
			
		||||
                                    const V2i *ap) {
 | 
			
		||||
  f32 d20 = dot_v2((*ap), (*ab));
 | 
			
		||||
  f32 d21 = dot_v2((*ap), (*ac));
 | 
			
		||||
 | 
			
		||||
  f32 v = (d11 * d20 - d01 * d21) / denom;
 | 
			
		||||
  f32 w = (d00 * d21 - d01 * d20) / denom;
 | 
			
		||||
  f32 u = 1.0f - v - w;
 | 
			
		||||
 | 
			
		||||
  return (V3f){v, w, u};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal void get_image_coordinates(const Vertex *vertex, const Image *img,
 | 
			
		||||
                                    u64 *x, u64 *y) {
 | 
			
		||||
  *x = ndc_to_image_coordinate(vertex->x, img->width);
 | 
			
		||||
  *y = ndc_to_image_coordinate(0.0f - vertex->y, img->height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal u64 ndc_to_image_coordinate(f32 value, u64 max) {
 | 
			
		||||
  f32 result = (value + 1.0f) * max * 0.5f;
 | 
			
		||||
  return clamp((u64)result, 0, max);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								src/obj.h
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								src/obj.h
									
									
									
									
									
								
							@@ -1,61 +0,0 @@
 | 
			
		||||
#ifndef OBJ_H
 | 
			
		||||
#define OBJ_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
 | 
			
		||||
#define NULL_MODEL ((Model){0})
 | 
			
		||||
#define IS_NULL_MODEL(m) (m.vertices == NULL || m.triangles == NULL)
 | 
			
		||||
 | 
			
		||||
typedef struct vertex Vertex;
 | 
			
		||||
struct vertex {
 | 
			
		||||
  f32 x;
 | 
			
		||||
  f32 y;
 | 
			
		||||
  f32 z;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct triangle Triangle;
 | 
			
		||||
struct triangle {
 | 
			
		||||
  u64 p0;
 | 
			
		||||
  u64 p1;
 | 
			
		||||
  u64 p2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  RENDER_TYPE_WIREFRAME,
 | 
			
		||||
  RENDER_TYPE_FILLED,
 | 
			
		||||
  RENDER_TYPE_SHADED,
 | 
			
		||||
 | 
			
		||||
  COUNT_RENDER_TYPES,
 | 
			
		||||
} RenderType;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  COLOUR_TYPE_FIXED,
 | 
			
		||||
  COLOUR_TYPE_RANDOM,
 | 
			
		||||
 | 
			
		||||
  COUNT_COLOUR_TYPE,
 | 
			
		||||
} ColourType;
 | 
			
		||||
 | 
			
		||||
MAKE_LIST_TYPE(Vertex);
 | 
			
		||||
MAKE_LIST_TYPE(Triangle);
 | 
			
		||||
 | 
			
		||||
typedef struct model Model;
 | 
			
		||||
struct model {
 | 
			
		||||
  LIST_TYPE(Vertex) * vertices;
 | 
			
		||||
  LIST_TYPE(Triangle) * triangles;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct render Render;
 | 
			
		||||
struct render {
 | 
			
		||||
  Image img;
 | 
			
		||||
  Depth depth;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Model load_obj_file(Arena *arena, const char *filename);
 | 
			
		||||
bool init_render(Arena *arena, Render *render, u64 width, u64 height);
 | 
			
		||||
void render_model(const Model *model, Render *render, Colour colour,
 | 
			
		||||
                  RenderType type, ColourType colour_type);
 | 
			
		||||
 | 
			
		||||
#endif // OBJ_H
 | 
			
		||||
							
								
								
									
										30
									
								
								src/pam.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/pam.c
									
									
									
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
#include "pam.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
void write_p7_image(u64 width, u64 height, u8 *buf, const char *outfile) {
 | 
			
		||||
  FILE *fp = fopen(outfile, "wb");
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    fprintf(stderr, "Couldn't open file: %s\n", outfile);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char header[4096] = {0};
 | 
			
		||||
  snprintf(header, 4095,
 | 
			
		||||
           "P7\n"
 | 
			
		||||
           "WIDTH %lu\n"
 | 
			
		||||
           "HEIGHT %lu\n"
 | 
			
		||||
           "DEPTH 4\n"
 | 
			
		||||
           "MAXVAL 255\n"
 | 
			
		||||
           "TUPLTYPE RGB_ALPHA\n"
 | 
			
		||||
           "ENDHDR\n",
 | 
			
		||||
           width, height);
 | 
			
		||||
 | 
			
		||||
  u64 hdr_size = strlen(header);
 | 
			
		||||
  u64 buf_size = width * height * 4;
 | 
			
		||||
 | 
			
		||||
  fwrite(header, hdr_size, 1, fp);
 | 
			
		||||
  fwrite(buf, buf_size, 1, fp);
 | 
			
		||||
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										88
									
								
								src/pam/pam.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/pam/pam.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
#include "pam.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
void write_p7_image(u64 width, u64 height, u8 *buf, const char *outfile) {
 | 
			
		||||
  FILE *fp = fopen(outfile, "wb");
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    fprintf(stderr, "Couldn't open file: %s\n", outfile);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char header[4096] = {0};
 | 
			
		||||
  snprintf(header, 4095,
 | 
			
		||||
           "P7\n"
 | 
			
		||||
           "WIDTH %lu\n"
 | 
			
		||||
           "HEIGHT %lu\n"
 | 
			
		||||
           "DEPTH 4\n"
 | 
			
		||||
           "MAXVAL 255\n"
 | 
			
		||||
           "TUPLTYPE RGB_ALPHA\n"
 | 
			
		||||
           "ENDHDR\n",
 | 
			
		||||
           width, height);
 | 
			
		||||
 | 
			
		||||
  u64 hdr_size = strlen(header);
 | 
			
		||||
  u64 buf_size = width * height * 4;
 | 
			
		||||
 | 
			
		||||
  fwrite(header, hdr_size, 1, fp);
 | 
			
		||||
  fwrite(buf, buf_size, 1, fp);
 | 
			
		||||
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Image *load_p6_image(Arena *arena, const char *filename) {
 | 
			
		||||
  Image *output = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!arena || !filename) {
 | 
			
		||||
    goto RETURN_VALUE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FILE *fp = fopen(filename, "rb");
 | 
			
		||||
  if (!fp) {
 | 
			
		||||
    goto RETURN_VALUE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char type[4] = {0};
 | 
			
		||||
  fread(type, 3, 1, fp);
 | 
			
		||||
  if (strncmp(type, "P6\n", 4) != 0) {
 | 
			
		||||
    goto CLOSE_FILE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 w, h;
 | 
			
		||||
  fscanf(fp, "%lu %lu\n", &w, &h);
 | 
			
		||||
 | 
			
		||||
  u64 max;
 | 
			
		||||
  fscanf(fp, "%lu\n", &max);
 | 
			
		||||
  if (max > UINT8_MAX) {
 | 
			
		||||
    goto CLOSE_FILE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  output = wapp_mem_arena_alloc(arena, sizeof(Image));
 | 
			
		||||
  if (!output) {
 | 
			
		||||
    goto CLOSE_FILE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  output->width = w;
 | 
			
		||||
  output->height = h;
 | 
			
		||||
  if (!init_buffer(arena, output)) {
 | 
			
		||||
    goto CLOSE_FILE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Colour colour = {0};
 | 
			
		||||
  for (u64 y = 0; y < h; ++y) {
 | 
			
		||||
    for (u64 x = 0; x < w; ++x) {
 | 
			
		||||
      fread(&colour, 3, 1, fp);
 | 
			
		||||
      colour.a = 255;
 | 
			
		||||
      set_pixel(output, x, y, &colour);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
CLOSE_FILE:
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
 | 
			
		||||
RETURN_VALUE:
 | 
			
		||||
  return output;
 | 
			
		||||
}
 | 
			
		||||
@@ -2,7 +2,9 @@
 | 
			
		||||
#define PAM_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
 | 
			
		||||
void write_p7_image(u64 width, u64 height, u8 *buf, const char *outfile);
 | 
			
		||||
Image *load_p6_image(Arena *arena, const char *filename);
 | 
			
		||||
 | 
			
		||||
#endif // PAM_H
 | 
			
		||||
							
								
								
									
										135
									
								
								src/shader/main_shader.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/shader/main_shader.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
#include "main_shader.h"
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "render.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
VertexData general_shader_vertex(void *shader, const VertexData *vert, u8 index, const Model *model) {
 | 
			
		||||
  Shader *shdr = (Shader *)shader;
 | 
			
		||||
 | 
			
		||||
  V4f vh = V3_to_V4(vert->position);
 | 
			
		||||
  vh.y   = 0.0 - vh.y;
 | 
			
		||||
  vh     = mat4x4_mul_vec4(shdr->final, vh);
 | 
			
		||||
 | 
			
		||||
  shdr->vertices[index].position = project_vec4(vh);
 | 
			
		||||
  shdr->vertices[index].uv       = vert->uv;
 | 
			
		||||
 | 
			
		||||
  V4f hnorm                    = V3_to_V4(vert->normal);
 | 
			
		||||
  hnorm                        = mat4x4_mul_vec4(shdr->proj_mv_inv_t, hnorm);
 | 
			
		||||
  shdr->vertices[index].normal = project_vec4(hnorm);
 | 
			
		||||
  normalise_v3(shdr->vertices[index].normal);
 | 
			
		||||
 | 
			
		||||
  return shdr->vertices[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FragmentResult diffuse_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                       const Model *model) {
 | 
			
		||||
  Shader *shdr = (Shader *)shader;
 | 
			
		||||
 | 
			
		||||
  M3x3f pos_mat    = {.rows = {shdr->vertices[0].position, shdr->vertices[1].position, shdr->vertices[2].position}};
 | 
			
		||||
  pos_mat          = mat3x3_transpose(pos_mat);
 | 
			
		||||
  M3x3f normal_mat = {.rows = {shdr->vertices[0].normal, shdr->vertices[1].normal, shdr->vertices[2].normal}};
 | 
			
		||||
  normal_mat       = mat3x3_transpose(normal_mat);
 | 
			
		||||
  M3x2f uvs        = {shdr->vertices[0].uv, shdr->vertices[1].uv, shdr->vertices[2].uv};
 | 
			
		||||
  M2x3f uv_mat     = mat3x2_transpose(uvs);
 | 
			
		||||
 | 
			
		||||
  V3f position = mat3x3_mul_vec3(pos_mat, (*barycentric));
 | 
			
		||||
  V3f normal   = mat3x3_mul_vec3(normal_mat, (*barycentric));
 | 
			
		||||
  V2f uv       = mat2x3_mul_vec3(uv_mat, (*barycentric));
 | 
			
		||||
 | 
			
		||||
  V4f shadow_position_h = V3_to_V4(position);
 | 
			
		||||
  shadow_position_h     = mat4x4_mul_vec4(shdr->shadow_matrix, shadow_position_h);
 | 
			
		||||
  V3f shadow_position   = project_vec4(shadow_position_h);
 | 
			
		||||
 | 
			
		||||
  // Calculate shadow
 | 
			
		||||
  const Render *shadow_pass = &(g_render_passes[RENDER_PASS_SHADOW]);
 | 
			
		||||
  f32 shadow_z              = get_pixel(f32, &(shadow_pass->depth), shadow_position.x, shadow_position.y);
 | 
			
		||||
  f32 shadow                = 0.3f + 0.7f * (shadow_z < shadow_position.z + 10.0f);
 | 
			
		||||
 | 
			
		||||
#pragma region darboux_frame_tangent_normals
 | 
			
		||||
  /**
 | 
			
		||||
   * Based on the following section of the tinyrenderer tutorial
 | 
			
		||||
   * https://github.com/ssloy/tinyrenderer/wiki/Lesson-6bis:-tangent-space-normal-mapping#starting-point-phong-shading
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (model->normal) {
 | 
			
		||||
    u64 nm_x = uv.u * model->normal->width;
 | 
			
		||||
    u64 nm_y = uv.v * model->normal->height;
 | 
			
		||||
 | 
			
		||||
    Colour pixel   = get_pixel(Colour, model->normal, nm_x, nm_y);
 | 
			
		||||
    V3f    tangent = (V3f){
 | 
			
		||||
        .x = pixel.r / 255.f * 2.f - 1.f,
 | 
			
		||||
        .y = pixel.g / 255.f * 2.f - 1.f,
 | 
			
		||||
        .z = pixel.b / 255.f * 2.f - 1.f,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    V3f p0p1 = sub_v3(shdr->vertices[1].position, shdr->vertices[0].position);
 | 
			
		||||
    V3f p0p2 = sub_v3(shdr->vertices[2].position, shdr->vertices[0].position);
 | 
			
		||||
 | 
			
		||||
    M3x3f A     = {.rows = {p0p1, p0p2, normal}};
 | 
			
		||||
    M3x3f A_inv = mat3x3_inv(A);
 | 
			
		||||
 | 
			
		||||
    V2f uv0 = shdr->vertices[0].uv;
 | 
			
		||||
    V2f uv1 = shdr->vertices[1].uv;
 | 
			
		||||
    V2f uv2 = shdr->vertices[2].uv;
 | 
			
		||||
 | 
			
		||||
    V3f u_vec = {uv1.u - uv0.u, uv2.u - uv0.u, 0};
 | 
			
		||||
    V3f v_vec = {uv1.v - uv0.v, uv2.v - uv0.v, 0};
 | 
			
		||||
 | 
			
		||||
    V3f i = mat3x3_mul_vec3(A_inv, u_vec);
 | 
			
		||||
    normalise_v3(i);
 | 
			
		||||
    V3f j = mat3x3_mul_vec3(A_inv, v_vec);
 | 
			
		||||
    normalise_v3(j);
 | 
			
		||||
 | 
			
		||||
    M3x3f B = {.rows = {i, j, normal}};
 | 
			
		||||
    B = mat3x3_transpose(B);
 | 
			
		||||
 | 
			
		||||
    normal = mat3x3_mul_vec3(B, tangent);
 | 
			
		||||
    normalise_v3(normal);
 | 
			
		||||
  }
 | 
			
		||||
#pragma endregion darboux_frame_tangent_normals
 | 
			
		||||
 | 
			
		||||
  V4f output;
 | 
			
		||||
  if (model->texture) {
 | 
			
		||||
    u64    tx_x = uv.u * model->texture->width;
 | 
			
		||||
    u64    tx_y = uv.v * model->texture->height;
 | 
			
		||||
    Colour tx   = get_pixel(Colour, model->texture, tx_x, tx_y);
 | 
			
		||||
    output      = (V4f){.r = tx.r, .g = tx.g, .b = tx.b, .a = tx.a};
 | 
			
		||||
  } else {
 | 
			
		||||
    output = *colour;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  f32 intensity = max(0.001f, dot_v3(normal, shdr->light_dir));
 | 
			
		||||
  f32 r         = clamp(intensity + shdr->ambient.r, 0.0f, 1.0f);
 | 
			
		||||
  f32 g         = clamp(intensity + shdr->ambient.g, 0.0f, 1.0f);
 | 
			
		||||
  f32 b         = clamp(intensity + shdr->ambient.b, 0.0f, 1.0f);
 | 
			
		||||
 | 
			
		||||
  output.r *= r * shadow;
 | 
			
		||||
  output.g *= g * shadow;
 | 
			
		||||
  output.b *= b * shadow;
 | 
			
		||||
 | 
			
		||||
  return (FragmentResult){.colour = output};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FragmentResult albedo_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                      const Model *model) {
 | 
			
		||||
  Shader *shdr = (Shader *)shader;
 | 
			
		||||
 | 
			
		||||
  M3x2f uvs    = {shdr->vertices[0].uv, shdr->vertices[1].uv, shdr->vertices[2].uv};
 | 
			
		||||
  M2x3f uv_mat = mat3x2_transpose(uvs);
 | 
			
		||||
  V2f   uv     = mat2x3_mul_vec3(uv_mat, (*barycentric));
 | 
			
		||||
 | 
			
		||||
  V4f output;
 | 
			
		||||
  if (model->texture) {
 | 
			
		||||
    u64    tx_x = uv.u * model->texture->width;
 | 
			
		||||
    u64    tx_y = uv.v * model->texture->height;
 | 
			
		||||
    Colour tx   = get_pixel(Colour, model->texture, tx_x, tx_y);
 | 
			
		||||
    output      = (V4f){.r = tx.r, .g = tx.g, .b = tx.b, .a = tx.a};
 | 
			
		||||
  } else {
 | 
			
		||||
    output = *colour;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (FragmentResult){.colour = output};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/shader/main_shader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/shader/main_shader.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
#ifndef MAIN_SHADER_H
 | 
			
		||||
#define MAIN_SHADER_H
 | 
			
		||||
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
typedef struct shader Shader;
 | 
			
		||||
struct shader {
 | 
			
		||||
  #include "shader_base.inc"
 | 
			
		||||
  M4x4f shadow_matrix;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
VertexData     general_shader_vertex(void *shader, const VertexData *vert, u8 index, const Model *model);
 | 
			
		||||
FragmentResult diffuse_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                       const Model *model);
 | 
			
		||||
FragmentResult albedo_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                      const Model *model);
 | 
			
		||||
#endif // !MAIN_SHADER_H
 | 
			
		||||
							
								
								
									
										58
									
								
								src/shader/shader.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/shader/shader.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_SHADER_COUNT 2048
 | 
			
		||||
 | 
			
		||||
typedef struct shader_repo ShaderRepo;
 | 
			
		||||
struct shader_repo {
 | 
			
		||||
  void           *shaders[MAX_SHADER_COUNT];
 | 
			
		||||
  VertexShader   *vertex_funcs[MAX_SHADER_COUNT];
 | 
			
		||||
  FragmentShader *fragment_funcs[MAX_SHADER_COUNT];
 | 
			
		||||
  u64            count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
internal ShaderRepo g_repository = {0};
 | 
			
		||||
 | 
			
		||||
ShaderID register_shader(void *shader, VertexShader *vertex, FragmentShader *fragment) {
 | 
			
		||||
  if (g_repository.count + 1 >= MAX_SHADER_COUNT) {
 | 
			
		||||
    return INVALID_SHADER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ++(g_repository.count);
 | 
			
		||||
  g_repository.shaders[g_repository.count]        = shader;
 | 
			
		||||
  g_repository.vertex_funcs[g_repository.count]   = vertex;
 | 
			
		||||
  g_repository.fragment_funcs[g_repository.count] = fragment;
 | 
			
		||||
 | 
			
		||||
  return (ShaderID){g_repository.count};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VertexData run_vertex_shader(ShaderID shader, const VertexData *vert, u8 index, const Model *model) {
 | 
			
		||||
  if (IS_INVALID_SHADER(shader) || shader.id > g_repository.count || !vert || !model) {
 | 
			
		||||
    return (VertexData){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void *shader_obj          = g_repository.shaders[shader.id];
 | 
			
		||||
  VertexShader *vertex_func = g_repository.vertex_funcs[shader.id];
 | 
			
		||||
 | 
			
		||||
  if (!shader_obj || !vertex_func) {
 | 
			
		||||
    return (VertexData){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return vertex_func(shader_obj, vert, index, model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FragmentResult run_fragment_shader(ShaderID shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                   const Model *model) {
 | 
			
		||||
  if (IS_INVALID_SHADER(shader) || shader.id > g_repository.count || !colour) {
 | 
			
		||||
    return DISCARDED_FRAGMENT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void *shader_obj              = g_repository.shaders[shader.id];
 | 
			
		||||
  FragmentShader *fragment_func = g_repository.fragment_funcs[shader.id];
 | 
			
		||||
 | 
			
		||||
  if (!shader_obj || !fragment_func) {
 | 
			
		||||
    return DISCARDED_FRAGMENT;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return fragment_func(shader_obj, barycentric, colour, model);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								src/shader/shader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/shader/shader.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
#ifndef SHADER_H
 | 
			
		||||
#define SHADER_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
typedef struct shader_id ShaderID;
 | 
			
		||||
struct shader_id {
 | 
			
		||||
  u64 id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct vertex_data VertexData;
 | 
			
		||||
struct vertex_data {
 | 
			
		||||
  V3f position;
 | 
			
		||||
  V3f normal;
 | 
			
		||||
  V2f uv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct fragment_result FragmentResult;
 | 
			
		||||
struct fragment_result {
 | 
			
		||||
  V4f  colour;
 | 
			
		||||
  bool discard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define INVALID_SHADER           ((ShaderID){0})
 | 
			
		||||
#define IS_INVALID_SHADER(ID)    (ID.id == 0)
 | 
			
		||||
#define DISCARDED_FRAGMENT       ((FragmentResult){.discard = true})
 | 
			
		||||
#define DISCARD_FRAGMENT(RESULT) (RESULT.discard)
 | 
			
		||||
 | 
			
		||||
typedef VertexData(VertexShader)(void *shader, const VertexData *vert, u8 index, const Model *model);
 | 
			
		||||
typedef FragmentResult(FragmentShader)(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                       const Model *model);
 | 
			
		||||
 | 
			
		||||
ShaderID register_shader(void *shader, VertexShader *vertex, FragmentShader *fragment);
 | 
			
		||||
VertexData run_vertex_shader(ShaderID shader, const VertexData *vert, u8 index, const Model *model);
 | 
			
		||||
FragmentResult run_fragment_shader(ShaderID shader, const V3f *barycentric, const V4f *colour, const Model *model);
 | 
			
		||||
 | 
			
		||||
#endif // SHADER_H
 | 
			
		||||
							
								
								
									
										8
									
								
								src/shader/shader_base.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/shader/shader_base.inc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
V3f light_dir;
 | 
			
		||||
V3f ambient;
 | 
			
		||||
M4x4f proj_mv;
 | 
			
		||||
M4x4f proj_mv_inv_t;
 | 
			
		||||
M4x4f viewport;
 | 
			
		||||
M4x4f final;
 | 
			
		||||
M4x4f final_inv;
 | 
			
		||||
VertexData vertices[TRIANGLE_VERTICES];
 | 
			
		||||
							
								
								
									
										86
									
								
								src/shader/shaders.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/shader/shaders.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
#include "shaders.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "shadow_shader.h"
 | 
			
		||||
#include "main_shader.h"
 | 
			
		||||
#include "render.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
ShaderID depth                = {0};
 | 
			
		||||
ShaderID perspective_diffuse  = {0};
 | 
			
		||||
ShaderID perspective_albedo   = {0};
 | 
			
		||||
ShaderID orthographic_diffuse = {0};
 | 
			
		||||
ShaderID orthographic_albedo  = {0};
 | 
			
		||||
 | 
			
		||||
internal ShadowShader depth_shader = {0};
 | 
			
		||||
internal Shader       perspective  = {0};
 | 
			
		||||
internal Shader       orthographic = {0};
 | 
			
		||||
 | 
			
		||||
internal V3f g_ambient_light = {0.1f, 0.1f, 0.1f};
 | 
			
		||||
internal V3f g_eye           = {0.2f, -0.1f, 0.5f};
 | 
			
		||||
internal V3f g_target        = {0};
 | 
			
		||||
internal V3f g_up            = {0.0f, 1.0f, 0.0f};
 | 
			
		||||
internal V3f g_light_dir     = {1.0f, -1.0f, 1.0f};
 | 
			
		||||
 | 
			
		||||
internal M4x4f get_projection_matrix(ProjectionType projection_type);
 | 
			
		||||
 | 
			
		||||
void load_shaders(M4x4f vp) {
 | 
			
		||||
  // Set up depth shader matrices
 | 
			
		||||
  M4x4f depth_model_view = lookat(g_light_dir, g_target, g_up);
 | 
			
		||||
  M4x4f depth_projection = projection(0.0f);
 | 
			
		||||
 | 
			
		||||
  // Set up depth shader
 | 
			
		||||
  depth_shader.proj_mv       = mat4x4_mul(depth_projection, depth_model_view);
 | 
			
		||||
  depth_shader.proj_mv_inv_t = mat4x4_inv(mat4x4_transpose(depth_shader.proj_mv));
 | 
			
		||||
  depth_shader.viewport      = vp;
 | 
			
		||||
  depth_shader.final         = mat4x4_mul(depth_shader.viewport, depth_shader.proj_mv);
 | 
			
		||||
  depth_shader.light_dir     = mat3x3_mul_vec3(depth_shader.proj_mv, g_light_dir);
 | 
			
		||||
  normalise_v3(depth_shader.light_dir);
 | 
			
		||||
 | 
			
		||||
  // Set up main shader matrices
 | 
			
		||||
  M4x4f model_view              = lookat(g_eye, g_target, g_up);
 | 
			
		||||
  M4x4f orthographic_projection = get_projection_matrix(PROJECTION_TYPE_ORTHOGRAPHIC);
 | 
			
		||||
  M4x4f perspective_projection  = get_projection_matrix(PROJECTION_TYPE_PERSPECTIVE);
 | 
			
		||||
 | 
			
		||||
  // Set up perspective shader
 | 
			
		||||
  perspective.proj_mv       = mat4x4_mul(perspective_projection, model_view);
 | 
			
		||||
  perspective.proj_mv_inv_t = mat4x4_inv(mat4x4_transpose(perspective.proj_mv));
 | 
			
		||||
  perspective.viewport      = vp;
 | 
			
		||||
  perspective.final         = mat4x4_mul(perspective.viewport, perspective.proj_mv);
 | 
			
		||||
  perspective.final_inv     = mat4x4_inv(perspective.final);
 | 
			
		||||
  perspective.ambient       = g_ambient_light;
 | 
			
		||||
  perspective.light_dir     = mat3x3_mul_vec3(perspective.proj_mv, g_light_dir);
 | 
			
		||||
  normalise_v3(perspective.light_dir);
 | 
			
		||||
  perspective.shadow_matrix = mat4x4_mul(depth_shader.final, perspective.final_inv);
 | 
			
		||||
 | 
			
		||||
  // Set up orthographic shader
 | 
			
		||||
  orthographic.proj_mv       = mat4x4_mul(orthographic_projection, model_view);
 | 
			
		||||
  orthographic.proj_mv_inv_t = mat4x4_inv(mat4x4_transpose(orthographic.proj_mv));
 | 
			
		||||
  orthographic.viewport      = vp;
 | 
			
		||||
  orthographic.final         = mat4x4_mul(orthographic.viewport, orthographic.proj_mv);
 | 
			
		||||
  orthographic.final_inv     = mat4x4_inv(perspective.final);
 | 
			
		||||
  orthographic.shadow_matrix = mat4x4_mul(depth_shader.final, orthographic.final_inv);
 | 
			
		||||
  orthographic.light_dir     = mat3x3_mul_vec3(orthographic.proj_mv, g_light_dir);
 | 
			
		||||
  normalise_v3(orthographic.light_dir);
 | 
			
		||||
  orthographic.ambient       = g_ambient_light;
 | 
			
		||||
 | 
			
		||||
  // Register shaders
 | 
			
		||||
  depth                = register_shader(&depth_shader, shadow_shader_vertex,  shadow_shader_fragment);
 | 
			
		||||
  perspective_diffuse  = register_shader(&perspective,  general_shader_vertex, diffuse_shader_fragment);
 | 
			
		||||
  perspective_albedo   = register_shader(&perspective,  general_shader_vertex, albedo_shader_fragment);
 | 
			
		||||
  orthographic_diffuse = register_shader(&orthographic, general_shader_vertex, diffuse_shader_fragment);
 | 
			
		||||
  orthographic_albedo  = register_shader(&orthographic, general_shader_vertex, albedo_shader_fragment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal M4x4f get_projection_matrix(ProjectionType projection_type) {
 | 
			
		||||
  if (projection_type == PROJECTION_TYPE_PERSPECTIVE) {
 | 
			
		||||
    V3f cam = V3(V3f, f32, g_target.x, g_target.y, g_target.z, g_eye.x, g_eye.y, g_eye.z);
 | 
			
		||||
    normalise_v3(cam);
 | 
			
		||||
 | 
			
		||||
    f32 coeff = -1.0f / magnitude_v3(cam) * 0.5f;
 | 
			
		||||
 | 
			
		||||
    return projection(coeff);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return mat4x4_identity;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								src/shader/shaders.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/shader/shaders.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef SHADERS_H
 | 
			
		||||
#define SHADERS_H
 | 
			
		||||
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
 | 
			
		||||
extern ShaderID depth;
 | 
			
		||||
extern ShaderID perspective_diffuse;
 | 
			
		||||
extern ShaderID perspective_albedo;
 | 
			
		||||
extern ShaderID orthographic_diffuse;
 | 
			
		||||
extern ShaderID orthographic_albedo;
 | 
			
		||||
 | 
			
		||||
void load_shaders(M4x4f vp);
 | 
			
		||||
 | 
			
		||||
#endif // SHADERS_H
 | 
			
		||||
							
								
								
									
										30
									
								
								src/shader/shadow_shader.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/shader/shadow_shader.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
#include "shadow_shader.h"
 | 
			
		||||
#include "constants.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
VertexData shadow_shader_vertex(void *shader, const VertexData *vert, u8 index, const Model *model) {
 | 
			
		||||
  ShadowShader *shdr = (ShadowShader *)shader;
 | 
			
		||||
 | 
			
		||||
  V4f vh = V3_to_V4(vert->position);
 | 
			
		||||
  vh.y   = 0.0 - vh.y;
 | 
			
		||||
  vh     = mat4x4_mul_vec4(shdr->final, vh);
 | 
			
		||||
 | 
			
		||||
  shdr->vertices[index].position = project_vec4(vh);
 | 
			
		||||
 | 
			
		||||
  return shdr->vertices[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FragmentResult shadow_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                     const Model *model) {
 | 
			
		||||
  ShadowShader *shdr = (ShadowShader *)shader;
 | 
			
		||||
 | 
			
		||||
  M3x3f pos_mat = {.rows = {shdr->vertices[0].position, shdr->vertices[1].position, shdr->vertices[2].position}};
 | 
			
		||||
  pos_mat       = mat3x3_transpose(pos_mat);
 | 
			
		||||
  V3f position  = mat3x3_mul_vec3(pos_mat, (*barycentric));
 | 
			
		||||
 | 
			
		||||
  f32 channel = clamp(position.z + DEPTH_MAX, 0.0f, DEPTH_MAX);
 | 
			
		||||
  V4f output = {.r = channel, .g = channel, .b = channel, .a = 255};
 | 
			
		||||
 | 
			
		||||
  return (FragmentResult){.colour = output};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								src/shader/shadow_shader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/shader/shadow_shader.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#ifndef SHADOW_SHADER_H
 | 
			
		||||
#define SHADOW_SHADER_H
 | 
			
		||||
 | 
			
		||||
#include "constants.h"
 | 
			
		||||
#include "shader.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
 | 
			
		||||
typedef struct shadow_shader ShadowShader;
 | 
			
		||||
struct shadow_shader {
 | 
			
		||||
  #include "shader_base.inc"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
VertexData     shadow_shader_vertex(void *shader, const VertexData *vert, u8 index, const Model *model);
 | 
			
		||||
FragmentResult shadow_shader_fragment(void *shader, const V3f *barycentric, const V4f *colour,
 | 
			
		||||
                                      const Model *model);
 | 
			
		||||
 | 
			
		||||
#endif // !SHADOW_SHADER_H
 | 
			
		||||
							
								
								
									
										97
									
								
								src/str/str.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/str/str.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
#include "str.h"
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define CAPACITY_SCALAR 4
 | 
			
		||||
 | 
			
		||||
Str8 str8(Arena *arena, char *str) {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return (Str8){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 length = strlen(str);
 | 
			
		||||
  Str8 output = {
 | 
			
		||||
      .str      = str,
 | 
			
		||||
      .length   = length,
 | 
			
		||||
      .capacity = length,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (arena) {
 | 
			
		||||
    output.capacity *= CAPACITY_SCALAR;
 | 
			
		||||
 | 
			
		||||
    output.str = wapp_mem_arena_alloc(arena, output.capacity);
 | 
			
		||||
    if (!output.str) {
 | 
			
		||||
      return (Str8){0};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    strncpy(output.str, str, output.length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Str8 str8_copy(Arena *arena, const Str8 *str) {
 | 
			
		||||
  if (!arena) {
 | 
			
		||||
    return str8_lit(str->str);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char *tmp = wapp_mem_arena_alloc(arena, str->capacity);
 | 
			
		||||
  if (!tmp) {
 | 
			
		||||
    return str8_lit(str->str);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  strncpy(tmp, str->str, str->length);
 | 
			
		||||
 | 
			
		||||
  return (Str8){
 | 
			
		||||
      .str      = tmp,
 | 
			
		||||
      .length   = str->length,
 | 
			
		||||
      .capacity = str->capacity,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
i32 str8_concat(Arena *arena, Str8 *dst, char *src) {
 | 
			
		||||
  if (!src || !dst) {
 | 
			
		||||
    return STR_OP_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 src_length = strlen(src);
 | 
			
		||||
  if (src_length + dst->length > dst->capacity) {
 | 
			
		||||
    if (!arena) {
 | 
			
		||||
      return STR_OP_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u64 capacity = dst->capacity * CAPACITY_SCALAR + src_length;
 | 
			
		||||
    char *str = wapp_mem_arena_alloc(arena, capacity);
 | 
			
		||||
    if (!str) {
 | 
			
		||||
      return STR_OP_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    strncpy(str, dst->str, dst->length);
 | 
			
		||||
    strncpy(str + dst->length, src, src_length);
 | 
			
		||||
 | 
			
		||||
    dst->str      = str;
 | 
			
		||||
    dst->length   = dst->length + src_length;
 | 
			
		||||
    dst->capacity = capacity;
 | 
			
		||||
 | 
			
		||||
    return STR_OP_SUCEEDED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  strncpy(dst->str + dst->length, src, src_length);
 | 
			
		||||
  return STR_OP_SUCEEDED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Str8 str8_substr(Arena *arena, const Str8 *str, u64 start, u64 count) {
 | 
			
		||||
  if (start > str->length || start + count > str->length) {
 | 
			
		||||
    return (Str8){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Str8 tmp = {
 | 
			
		||||
      .str      = str->str + start,
 | 
			
		||||
      .length   = count,
 | 
			
		||||
      .capacity = count,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return str8_copy(arena, &tmp);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								src/str/str.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/str/str.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
#ifndef STR_H
 | 
			
		||||
#define STR_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  STR_OP_SUCEEDED,
 | 
			
		||||
  STR_OP_FAILED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct str8 Str8;
 | 
			
		||||
struct str8 {
 | 
			
		||||
  char *str;
 | 
			
		||||
  u64  length;
 | 
			
		||||
  u64  capacity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define str8_lit(STR) (str8(NULL, STR))
 | 
			
		||||
 | 
			
		||||
Str8 str8(Arena *arena, char *str);
 | 
			
		||||
Str8 str8_copy(Arena *arena, const Str8 *str);
 | 
			
		||||
i32  str8_concat(Arena *arena, Str8 *dst, char *src);
 | 
			
		||||
Str8 str8_substr(Arena *arena, const Str8 *str, u64 start, u64 count);
 | 
			
		||||
 | 
			
		||||
#endif // !STR_H
 | 
			
		||||
							
								
								
									
										116
									
								
								src/tiny/tiny.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/tiny/tiny.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
#include "img.h"
 | 
			
		||||
#include "mem_arena.h"
 | 
			
		||||
#include "misc_utils.h"
 | 
			
		||||
#include "obj.h"
 | 
			
		||||
#include "render.h"
 | 
			
		||||
#include "shaders.h"
 | 
			
		||||
#include "str.h"
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#define IMAGE_DIMENSION 1200
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  TINY_EXIT_SUCCESS,
 | 
			
		||||
  TINY_EXIT_MISSING_ARGS,
 | 
			
		||||
  TINY_EXIT_OBJ_NOT_EXIST,
 | 
			
		||||
  TINY_EXIT_ARENA_INIT_FAILED,
 | 
			
		||||
  TINY_EXIT_RENDER_INIT_FAILED,
 | 
			
		||||
  TINY_EXIT_MODEL_LOAD_FAILED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct tiny_args TinyArgs;
 | 
			
		||||
struct tiny_args {
 | 
			
		||||
  Str8 obj;
 | 
			
		||||
  Str8 diffuse;
 | 
			
		||||
  Str8 tangent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
internal TinyArgs parse_args(Arena *arena, int argc, char *argv[]);
 | 
			
		||||
internal i32      tinyrenderer(Arena *arena, TinyArgs args);
 | 
			
		||||
internal bool     file_exists(const Str8 *path);
 | 
			
		||||
 | 
			
		||||
i32 tiny_main(i32 argc, char *argv[]) {
 | 
			
		||||
  Arena *arena = NULL;
 | 
			
		||||
  if (!wapp_mem_arena_init(&arena, GB(10))) {
 | 
			
		||||
    return TINY_EXIT_ARENA_INIT_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TinyArgs args   = parse_args(arena, argc, argv);
 | 
			
		||||
  i32      output = tinyrenderer(arena, args);
 | 
			
		||||
 | 
			
		||||
  wapp_mem_arena_destroy(&arena);
 | 
			
		||||
 | 
			
		||||
  return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal TinyArgs parse_args(Arena *arena, int argc, char *argv[]) {
 | 
			
		||||
  if (argc < 2) {
 | 
			
		||||
    exit(TINY_EXIT_MISSING_ARGS);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TinyArgs args = {
 | 
			
		||||
      .obj = str8_lit(argv[1]),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (!file_exists(&args.obj)) {
 | 
			
		||||
    exit(TINY_EXIT_OBJ_NOT_EXIST);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  u64 substr_end = args.obj.length - 4;
 | 
			
		||||
 | 
			
		||||
  args.diffuse = str8_substr(arena, &args.obj, 0, substr_end);
 | 
			
		||||
  str8_concat(arena, &args.diffuse, "_diffuse.pnm");
 | 
			
		||||
  if (!file_exists(&args.diffuse)) {
 | 
			
		||||
    args.diffuse = (Str8){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  args.tangent = str8_substr(arena, &args.obj, 0, substr_end);
 | 
			
		||||
  str8_concat(arena, &args.tangent, "_tangent.pnm");
 | 
			
		||||
  if (!file_exists(&args.tangent)) {
 | 
			
		||||
    args.tangent = (Str8){0};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return args;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal i32 tinyrenderer(Arena *arena, TinyArgs args) {
 | 
			
		||||
  Colour bg          = {.r = 42, .g = 45,  .b = 52,  .a = 255};
 | 
			
		||||
  Colour main_colour = {.r = 14, .g = 156, .b = 208, .a = 255};
 | 
			
		||||
 | 
			
		||||
  Render *shadowbuffer = &(g_render_passes[RENDER_PASS_SHADOW]);
 | 
			
		||||
  Render *framebuffer  = &(g_render_passes[RENDER_PASS_MAIN]);
 | 
			
		||||
  if (!init_render(arena, shadowbuffer, IMAGE_DIMENSION, IMAGE_DIMENSION) ||
 | 
			
		||||
      !init_render(arena, framebuffer,  IMAGE_DIMENSION, IMAGE_DIMENSION)) {
 | 
			
		||||
    return TINY_EXIT_RENDER_INIT_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const char *diffuse = args.diffuse.length > 0 ? args.diffuse.str : NULL;
 | 
			
		||||
  const char *tangent = args.tangent.length > 0 ? args.tangent.str : NULL;
 | 
			
		||||
 | 
			
		||||
  Model obj = load_obj_file(arena, args.obj.str, diffuse, tangent);
 | 
			
		||||
  if (IS_INVALID_MODEL(obj)) {
 | 
			
		||||
    return TINY_EXIT_MODEL_LOAD_FAILED;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  load_shaders(viewport(0, 0, IMAGE_DIMENSION, IMAGE_DIMENSION));
 | 
			
		||||
 | 
			
		||||
  clear_buffer(&(framebuffer->img), &bg);
 | 
			
		||||
 | 
			
		||||
  render_model(&obj, shadowbuffer, depth,               RENDER_TYPE_SHADED, main_colour);
 | 
			
		||||
  render_model(&obj, framebuffer,  perspective_diffuse, RENDER_TYPE_SHADED, main_colour);
 | 
			
		||||
 | 
			
		||||
  save_image(&(framebuffer->img), "result.pam");
 | 
			
		||||
 | 
			
		||||
  return TINY_EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
internal bool file_exists(const Str8 *path) {
 | 
			
		||||
  struct stat st;
 | 
			
		||||
  return stat(path->str, &st) == 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/tiny/tiny.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/tiny/tiny.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef TINY_H
 | 
			
		||||
#define TINY_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
 | 
			
		||||
i32 tiny_main(i32 argc, char *argv[]);
 | 
			
		||||
 | 
			
		||||
#endif // !TINY_H
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
#define UTILS_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
 | 
			
		||||
#define swap(T, v0, v1)                                                        \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    T tmp = v0;                                                                \
 | 
			
		||||
							
								
								
									
										165
									
								
								src/vec/vec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/vec/vec.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
#include "vec.h"
 | 
			
		||||
#include "constants.h"
 | 
			
		||||
 | 
			
		||||
M4x4f lookat(V3f eye, V3f target, V3f up) {
 | 
			
		||||
  V3f z = V3(V3f, f32, target.x, target.y, target.z, eye.x, eye.y, eye.z);
 | 
			
		||||
  normalise_v3(z);
 | 
			
		||||
  V3f x = cross_product(up, z);
 | 
			
		||||
  normalise_v3(x);
 | 
			
		||||
  V3f y = cross_product(z, x);
 | 
			
		||||
  normalise_v3(y);
 | 
			
		||||
 | 
			
		||||
  M4x4f rotation = mat4x4_identity;
 | 
			
		||||
  rotation.row0.x = x.x;
 | 
			
		||||
  rotation.row0.y = x.y;
 | 
			
		||||
  rotation.row0.z = x.z;
 | 
			
		||||
  rotation.row1.x = y.x;
 | 
			
		||||
  rotation.row1.y = y.y;
 | 
			
		||||
  rotation.row1.z = y.z;
 | 
			
		||||
  rotation.row2.x = z.x;
 | 
			
		||||
  rotation.row2.y = z.y;
 | 
			
		||||
  rotation.row2.z = z.z;
 | 
			
		||||
 | 
			
		||||
  M4x4f translation = mat4x4_identity;
 | 
			
		||||
  translation.row0.w = -(eye.x);
 | 
			
		||||
  translation.row1.w = -(eye.y);
 | 
			
		||||
  translation.row2.w = -(eye.z);
 | 
			
		||||
 | 
			
		||||
  return mat4x4_mul(rotation, translation);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
M4x4f projection(f32 coeff) {
 | 
			
		||||
  return (M4x4f){
 | 
			
		||||
    .row0 = {1.0f, 0.0f,  0.0f, 0.0f},
 | 
			
		||||
    .row1 = {0.0f, 1.0f,  0.0f, 0.0f},
 | 
			
		||||
    .row2 = {0.0f, 0.0f,  1.0f, 0.0f},
 | 
			
		||||
    .row3 = {0.0f, 0.0f, coeff, 1.0f},
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
M4x4f viewport(f32 x, f32 y, u64 w, u64 h) {
 | 
			
		||||
  M4x4f output = mat4x4_identity;
 | 
			
		||||
 | 
			
		||||
  f32 half_width = (f32)w * 0.5f;
 | 
			
		||||
  f32 half_height = (f32)h * 0.5f;
 | 
			
		||||
  f32 half_depth = (f32)DEPTH_MAX * 0.5f;
 | 
			
		||||
 | 
			
		||||
  output.row0.x = half_width;
 | 
			
		||||
  output.row0.w = x + half_width;
 | 
			
		||||
  output.row1.y = half_height;
 | 
			
		||||
  output.row1.w = y + half_height;
 | 
			
		||||
  output.row2.z = output.row2.w = half_depth;
 | 
			
		||||
 | 
			
		||||
  return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
M3x3f mat3x3_inv(M3x3f matrix) {
 | 
			
		||||
  M3x3f dest = {0};
 | 
			
		||||
  float det;
 | 
			
		||||
 | 
			
		||||
  float a = matrix.rows[0].elements[0], b = matrix.rows[0].elements[1],
 | 
			
		||||
        c = matrix.rows[0].elements[2], d = matrix.rows[1].elements[0],
 | 
			
		||||
        e = matrix.rows[1].elements[1], f = matrix.rows[1].elements[2],
 | 
			
		||||
        g = matrix.rows[2].elements[0], h = matrix.rows[2].elements[1],
 | 
			
		||||
        i = matrix.rows[2].elements[2];
 | 
			
		||||
 | 
			
		||||
  dest.rows[0].elements[0] = e * i - f * h;
 | 
			
		||||
  dest.rows[0].elements[1] = -(b * i - h * c);
 | 
			
		||||
  dest.rows[0].elements[2] = b * f - e * c;
 | 
			
		||||
  dest.rows[1].elements[0] = -(d * i - g * f);
 | 
			
		||||
  dest.rows[1].elements[1] = a * i - c * g;
 | 
			
		||||
  dest.rows[1].elements[2] = -(a * f - d * c);
 | 
			
		||||
  dest.rows[2].elements[0] = d * h - g * e;
 | 
			
		||||
  dest.rows[2].elements[1] = -(a * h - g * b);
 | 
			
		||||
  dest.rows[2].elements[2] = a * e - b * d;
 | 
			
		||||
 | 
			
		||||
  det = 1.0f / (a * dest.rows[0].elements[0] + b * dest.rows[1].elements[0] +
 | 
			
		||||
                c * dest.rows[2].elements[0]);
 | 
			
		||||
 | 
			
		||||
  dest.rows[0].elements[0] *= det;
 | 
			
		||||
  dest.rows[0].elements[1] *= det;
 | 
			
		||||
  dest.rows[0].elements[2] *= det;
 | 
			
		||||
  dest.rows[1].elements[0] *= det;
 | 
			
		||||
  dest.rows[1].elements[1] *= det;
 | 
			
		||||
  dest.rows[1].elements[2] *= det;
 | 
			
		||||
  dest.rows[2].elements[0] *= det;
 | 
			
		||||
  dest.rows[2].elements[1] *= det;
 | 
			
		||||
  dest.rows[2].elements[2] *= det;
 | 
			
		||||
 | 
			
		||||
  return dest;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
M4x4f mat4x4_inv(M4x4f matrix) {
 | 
			
		||||
  f32 mat[4][4] = mat4x4_to_array(matrix);
 | 
			
		||||
  f32 dest[4][4] = {0};
 | 
			
		||||
 | 
			
		||||
  f32 t[6];
 | 
			
		||||
  f32 det;
 | 
			
		||||
  f32 a = mat[0][0], b = mat[0][1], c = mat[0][2], d = mat[0][3], e = mat[1][0],
 | 
			
		||||
      f = mat[1][1], g = mat[1][2], h = mat[1][3], i = mat[2][0], j = mat[2][1],
 | 
			
		||||
      k = mat[2][2], l = mat[2][3], m = mat[3][0], n = mat[3][1], o = mat[3][2],
 | 
			
		||||
      p = mat[3][3];
 | 
			
		||||
 | 
			
		||||
  t[0] = k * p - o * l;
 | 
			
		||||
  t[1] = j * p - n * l;
 | 
			
		||||
  t[2] = j * o - n * k;
 | 
			
		||||
  t[3] = i * p - m * l;
 | 
			
		||||
  t[4] = i * o - m * k;
 | 
			
		||||
  t[5] = i * n - m * j;
 | 
			
		||||
 | 
			
		||||
  dest[0][0] = f * t[0] - g * t[1] + h * t[2];
 | 
			
		||||
  dest[1][0] = -(e * t[0] - g * t[3] + h * t[4]);
 | 
			
		||||
  dest[2][0] = e * t[1] - f * t[3] + h * t[5];
 | 
			
		||||
  dest[3][0] = -(e * t[2] - f * t[4] + g * t[5]);
 | 
			
		||||
 | 
			
		||||
  dest[0][1] = -(b * t[0] - c * t[1] + d * t[2]);
 | 
			
		||||
  dest[1][1] = a * t[0] - c * t[3] + d * t[4];
 | 
			
		||||
  dest[2][1] = -(a * t[1] - b * t[3] + d * t[5]);
 | 
			
		||||
  dest[3][1] = a * t[2] - b * t[4] + c * t[5];
 | 
			
		||||
 | 
			
		||||
  t[0] = g * p - o * h;
 | 
			
		||||
  t[1] = f * p - n * h;
 | 
			
		||||
  t[2] = f * o - n * g;
 | 
			
		||||
  t[3] = e * p - m * h;
 | 
			
		||||
  t[4] = e * o - m * g;
 | 
			
		||||
  t[5] = e * n - m * f;
 | 
			
		||||
 | 
			
		||||
  dest[0][2] = b * t[0] - c * t[1] + d * t[2];
 | 
			
		||||
  dest[1][2] = -(a * t[0] - c * t[3] + d * t[4]);
 | 
			
		||||
  dest[2][2] = a * t[1] - b * t[3] + d * t[5];
 | 
			
		||||
  dest[3][2] = -(a * t[2] - b * t[4] + c * t[5]);
 | 
			
		||||
 | 
			
		||||
  t[0] = g * l - k * h;
 | 
			
		||||
  t[1] = f * l - j * h;
 | 
			
		||||
  t[2] = f * k - j * g;
 | 
			
		||||
  t[3] = e * l - i * h;
 | 
			
		||||
  t[4] = e * k - i * g;
 | 
			
		||||
  t[5] = e * j - i * f;
 | 
			
		||||
 | 
			
		||||
  dest[0][3] = -(b * t[0] - c * t[1] + d * t[2]);
 | 
			
		||||
  dest[1][3] = a * t[0] - c * t[3] + d * t[4];
 | 
			
		||||
  dest[2][3] = -(a * t[1] - b * t[3] + d * t[5]);
 | 
			
		||||
  dest[3][3] = a * t[2] - b * t[4] + c * t[5];
 | 
			
		||||
 | 
			
		||||
  det = 1.0f /
 | 
			
		||||
        (a * dest[0][0] + b * dest[1][0] + c * dest[2][0] + d * dest[3][0]);
 | 
			
		||||
 | 
			
		||||
  dest[0][0] *= det;
 | 
			
		||||
  dest[0][1] *= det;
 | 
			
		||||
  dest[0][2] *= det;
 | 
			
		||||
  dest[0][3] *= det;
 | 
			
		||||
  dest[1][0] *= det;
 | 
			
		||||
  dest[1][1] *= det;
 | 
			
		||||
  dest[1][2] *= det;
 | 
			
		||||
  dest[1][3] *= det;
 | 
			
		||||
  dest[2][0] *= det;
 | 
			
		||||
  dest[2][1] *= det;
 | 
			
		||||
  dest[2][2] *= det;
 | 
			
		||||
  dest[2][3] *= det;
 | 
			
		||||
  dest[3][0] *= det;
 | 
			
		||||
  dest[3][1] *= det;
 | 
			
		||||
  dest[3][2] *= det;
 | 
			
		||||
  dest[3][3] *= det;
 | 
			
		||||
 | 
			
		||||
  return array_to_mat4x4(dest);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										340
									
								
								src/vec/vec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								src/vec/vec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,340 @@
 | 
			
		||||
#ifndef VEC_H
 | 
			
		||||
#define VEC_H
 | 
			
		||||
 | 
			
		||||
#include "aliases.h"
 | 
			
		||||
#include "typed_list.h"
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
typedef struct i64x2 V2i;
 | 
			
		||||
struct i64x2 {
 | 
			
		||||
  i64 x;
 | 
			
		||||
  i64 y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct u64x2 V2u;
 | 
			
		||||
struct u64x2 {
 | 
			
		||||
  u64 x;
 | 
			
		||||
  u64 y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32x2 V2f;
 | 
			
		||||
union f32x2 {
 | 
			
		||||
  f32 elements[2];
 | 
			
		||||
  struct {
 | 
			
		||||
    union {
 | 
			
		||||
      f32 x;
 | 
			
		||||
      f32 u;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 y;
 | 
			
		||||
      f32 v;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32x3 V3f;
 | 
			
		||||
union f32x3 {
 | 
			
		||||
  f32 elements[3];
 | 
			
		||||
  struct {
 | 
			
		||||
    union {
 | 
			
		||||
      f32 x;
 | 
			
		||||
      f32 r;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 y;
 | 
			
		||||
      f32 g;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 z;
 | 
			
		||||
      f32 b;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32x4 V4f;
 | 
			
		||||
union f32x4 {
 | 
			
		||||
  f32 elements[4];
 | 
			
		||||
  struct {
 | 
			
		||||
    union {
 | 
			
		||||
      f32 x;
 | 
			
		||||
      f32 r;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 y;
 | 
			
		||||
      f32 g;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 z;
 | 
			
		||||
      f32 b;
 | 
			
		||||
    };
 | 
			
		||||
    union {
 | 
			
		||||
      f32 w;
 | 
			
		||||
      f32 a;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct u64x3 V3u;
 | 
			
		||||
struct u64x3 {
 | 
			
		||||
  u64 x;
 | 
			
		||||
  u64 y;
 | 
			
		||||
  u64 z;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32_3x2 M3x2f;
 | 
			
		||||
union f32_3x2 {
 | 
			
		||||
  V2f rows[3];
 | 
			
		||||
  struct {
 | 
			
		||||
    V2f row0;
 | 
			
		||||
    V2f row1;
 | 
			
		||||
    V2f row2;
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32_2x3 M2x3f;
 | 
			
		||||
union f32_2x3 {
 | 
			
		||||
  V3f rows[2];
 | 
			
		||||
  struct {
 | 
			
		||||
    V3f row0;
 | 
			
		||||
    V3f row1;
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32_3x3 M3x3f;
 | 
			
		||||
union f32_3x3 {
 | 
			
		||||
  V3f rows[3];
 | 
			
		||||
  struct {
 | 
			
		||||
    V3f row0;
 | 
			
		||||
    V3f row1;
 | 
			
		||||
    V3f row2;
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef union f32_4x4 M4x4f;
 | 
			
		||||
union f32_4x4 {
 | 
			
		||||
  V4f rows[4];
 | 
			
		||||
  struct {
 | 
			
		||||
    V4f row0;
 | 
			
		||||
    V4f row1;
 | 
			
		||||
    V4f row2;
 | 
			
		||||
    V4f row3;
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
MAKE_LIST_TYPE(V3f);
 | 
			
		||||
MAKE_LIST_TYPE(V2f);
 | 
			
		||||
 | 
			
		||||
#define V2(T, ELEM_T, X0, Y0, X1, Y1)                                          \
 | 
			
		||||
  ((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0})
 | 
			
		||||
 | 
			
		||||
#define V3(T, ELEM_T, X0, Y0, Z0, X1, Y1, Z1)                                  \
 | 
			
		||||
  ((T){(ELEM_T)X1 - (ELEM_T)X0, (ELEM_T)Y1 - (ELEM_T)Y0,                       \
 | 
			
		||||
       (ELEM_T)Z1 - (ELEM_T)Z0})
 | 
			
		||||
 | 
			
		||||
#define V3_to_V4(V3) ((V4f){.x = V3.x, .y = V3.y, .z = V3.z, .w = 1.0f})
 | 
			
		||||
 | 
			
		||||
#define dot_v2(V1, V2) ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y)
 | 
			
		||||
 | 
			
		||||
#define add_v2(V1, V2)                                                         \
 | 
			
		||||
  ((V2f){                                                                      \
 | 
			
		||||
      .x = V1.x + V2.x,                                                        \
 | 
			
		||||
      .y = V1.y + V2.y,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define sub_v2(V1, V2)                                                         \
 | 
			
		||||
  ((V2f){                                                                      \
 | 
			
		||||
      .x = V1.x - V2.x,                                                        \
 | 
			
		||||
      .y = V1.y - V2.y,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mul_v2(V1, V2)                                                         \
 | 
			
		||||
  ((V2f){                                                                      \
 | 
			
		||||
      .x = V1.x * V2.x,                                                        \
 | 
			
		||||
      .y = V1.y * V2.y,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define num_mul_v2(V, N) ((V2f){.x = (N) * V.x, .y = (N) * V.y})
 | 
			
		||||
 | 
			
		||||
#define magnitude_v2(V) (sqrtf(dot_v2(V, V)))
 | 
			
		||||
 | 
			
		||||
#define normalise_v2(V)                                                        \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    f32 magnitude = magnitude_v2(V);                                           \
 | 
			
		||||
    V.x /= magnitude;                                                          \
 | 
			
		||||
    V.y /= magnitude;                                                          \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define dot_v3(V1, V2)                                                         \
 | 
			
		||||
  ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z)
 | 
			
		||||
 | 
			
		||||
#define add_v3(V1, V2)                                                         \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .x = V1.x + V2.x,                                                        \
 | 
			
		||||
      .y = V1.y + V2.y,                                                        \
 | 
			
		||||
      .z = V1.z + V2.z,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define sub_v3(V1, V2)                                                         \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .x = V1.x - V2.x,                                                        \
 | 
			
		||||
      .y = V1.y - V2.y,                                                        \
 | 
			
		||||
      .z = V1.z - V2.z,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mul_v3(V1, V2)                                                         \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .x = V1.x * V2.x,                                                        \
 | 
			
		||||
      .y = V1.y * V2.y,                                                        \
 | 
			
		||||
      .z = V1.z * V2.z,                                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define num_mul_v3(V, N) ((V3f){.x = (N) * V.x, .y = (N) * V.y, .z = (N) * V.z})
 | 
			
		||||
 | 
			
		||||
#define num_div_v3(V, N) ((V3f){.x = V.x / (N), .y = V.y / (N), .z = V.z / (N)})
 | 
			
		||||
 | 
			
		||||
#define magnitude_v3(V) (sqrtf(dot_v3(V, V)))
 | 
			
		||||
 | 
			
		||||
#define normalise_v3(V)                                                        \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    f32 magnitude = magnitude_v3(V);                                           \
 | 
			
		||||
    V.x /= magnitude;                                                          \
 | 
			
		||||
    V.y /= magnitude;                                                          \
 | 
			
		||||
    V.z /= magnitude;                                                          \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define cross_product(V1, V2)                                                  \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .x = V1.y * V2.z - V1.z * V2.y,                                          \
 | 
			
		||||
      .y = V1.z * V2.x - V1.x * V2.z,                                          \
 | 
			
		||||
      .z = V1.x * V2.y - V1.y * V2.x,                                          \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat3x2_transpose(MAT)                                                  \
 | 
			
		||||
  ((M2x3f){                                                                    \
 | 
			
		||||
      .row0 = {.x = MAT.row0.x, .y = MAT.row1.x, .z = MAT.row2.x},             \
 | 
			
		||||
      .row1 = {.x = MAT.row0.y, .y = MAT.row1.y, .z = MAT.row2.y},             \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat2x3_mul_vec3(MAT, V)                                                \
 | 
			
		||||
  ((V2f){                                                                      \
 | 
			
		||||
      .elements[0] = dot_v3(MAT.rows[0], V),                                   \
 | 
			
		||||
      .elements[1] = dot_v3(MAT.rows[1], V),                                   \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat3x3_transpose(MAT)                                                  \
 | 
			
		||||
  ((M3x3f){                                                                    \
 | 
			
		||||
      .row0 = {.x = MAT.row0.x, .y = MAT.row1.x, .z = MAT.row2.x},             \
 | 
			
		||||
      .row1 = {.x = MAT.row0.y, .y = MAT.row1.y, .z = MAT.row2.y},             \
 | 
			
		||||
      .row2 = {.x = MAT.row0.z, .y = MAT.row1.z, .z = MAT.row2.z},             \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat3x3_mul_vec3(MAT, V)                                                \
 | 
			
		||||
  ((V3f){                                                                      \
 | 
			
		||||
      .elements[0] = dot_v3(MAT.rows[0], V),                                   \
 | 
			
		||||
      .elements[1] = dot_v3(MAT.rows[1], V),                                   \
 | 
			
		||||
      .elements[2] = dot_v3(MAT.rows[2], V),                                   \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat4x4_identity                                                        \
 | 
			
		||||
  ((M4x4f){                                                                    \
 | 
			
		||||
      .row0 = {1.0f, 0.0f, 0.0f, 0.0f},                                        \
 | 
			
		||||
      .row1 = {0.0f, 1.0f, 0.0f, 0.0f},                                        \
 | 
			
		||||
      .row2 = {0.0f, 0.0f, 1.0f, 0.0f},                                        \
 | 
			
		||||
      .row3 = {0.0f, 0.0f, 0.0f, 1.0f},                                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat4x4_to_array(MAT)                                                   \
 | 
			
		||||
  ((f32[4][4]){                                                                \
 | 
			
		||||
      {MAT.row0.x, MAT.row0.y, MAT.row0.z, MAT.row0.w},                        \
 | 
			
		||||
      {MAT.row1.x, MAT.row1.y, MAT.row1.z, MAT.row1.w},                        \
 | 
			
		||||
      {MAT.row2.x, MAT.row2.y, MAT.row2.z, MAT.row2.w},                        \
 | 
			
		||||
      {MAT.row3.x, MAT.row3.y, MAT.row3.z, MAT.row3.w},                        \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define array_to_mat4x4(arr)                                                   \
 | 
			
		||||
  ((M4x4f){                                                                    \
 | 
			
		||||
      .row0 = {arr[0][0], arr[0][1], arr[0][2], arr[0][3]},                    \
 | 
			
		||||
      .row1 = {arr[1][0], arr[1][1], arr[1][2], arr[1][3]},                    \
 | 
			
		||||
      .row2 = {arr[2][0], arr[2][1], arr[2][2], arr[2][3]},                    \
 | 
			
		||||
      .row3 = {arr[3][0], arr[3][1], arr[3][2], arr[3][3]},                    \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat4x4_transpose(MAT)                                                  \
 | 
			
		||||
  ((M4x4f){                                                                    \
 | 
			
		||||
      .row0 = {.x = MAT.row0.x,                                                \
 | 
			
		||||
               .y = MAT.row1.x,                                                \
 | 
			
		||||
               .z = MAT.row2.x,                                                \
 | 
			
		||||
               .w = MAT.row3.x},                                               \
 | 
			
		||||
      .row1 = {.x = MAT.row0.y,                                                \
 | 
			
		||||
               .y = MAT.row1.y,                                                \
 | 
			
		||||
               .z = MAT.row2.y,                                                \
 | 
			
		||||
               .w = MAT.row3.y},                                               \
 | 
			
		||||
      .row2 = {.x = MAT.row0.z,                                                \
 | 
			
		||||
               .y = MAT.row1.z,                                                \
 | 
			
		||||
               .z = MAT.row2.z,                                                \
 | 
			
		||||
               .w = MAT.row3.z},                                               \
 | 
			
		||||
      .row3 = {.x = MAT.row0.w,                                                \
 | 
			
		||||
               .y = MAT.row1.w,                                                \
 | 
			
		||||
               .z = MAT.row2.w,                                                \
 | 
			
		||||
               .w = MAT.row3.w},                                               \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat4x4_mul(MAT1, MAT2)                                                 \
 | 
			
		||||
  ((M4x4f){                                                                    \
 | 
			
		||||
      .row0.x = MAT1.row0.x * MAT2.row0.x + MAT1.row0.y * MAT2.row1.x +        \
 | 
			
		||||
                MAT1.row0.z * MAT2.row2.x + MAT1.row0.w * MAT2.row3.x,         \
 | 
			
		||||
      .row0.y = MAT1.row0.x * MAT2.row0.y + MAT1.row0.y * MAT2.row1.y +        \
 | 
			
		||||
                MAT1.row0.z * MAT2.row2.y + MAT1.row0.w * MAT2.row3.y,         \
 | 
			
		||||
      .row0.z = MAT1.row0.x * MAT2.row0.z + MAT1.row0.y * MAT2.row1.z +        \
 | 
			
		||||
                MAT1.row0.z * MAT2.row2.z + MAT1.row0.w * MAT2.row3.z,         \
 | 
			
		||||
      .row0.w = MAT1.row0.x * MAT2.row0.w + MAT1.row0.y * MAT2.row1.w +        \
 | 
			
		||||
                MAT1.row0.z * MAT2.row2.w + MAT1.row0.w * MAT2.row3.w,         \
 | 
			
		||||
      .row1.x = MAT1.row1.x * MAT2.row0.x + MAT1.row1.y * MAT2.row1.x +        \
 | 
			
		||||
                MAT1.row1.z * MAT2.row2.x + MAT1.row1.w * MAT2.row3.x,         \
 | 
			
		||||
      .row1.y = MAT1.row1.x * MAT2.row0.y + MAT1.row1.y * MAT2.row1.y +        \
 | 
			
		||||
                MAT1.row1.z * MAT2.row2.y + MAT1.row1.w * MAT2.row3.y,         \
 | 
			
		||||
      .row1.z = MAT1.row1.x * MAT2.row0.z + MAT1.row1.y * MAT2.row1.z +        \
 | 
			
		||||
                MAT1.row1.z * MAT2.row2.z + MAT1.row1.w * MAT2.row3.z,         \
 | 
			
		||||
      .row1.w = MAT1.row1.x * MAT2.row0.w + MAT1.row1.y * MAT2.row1.w +        \
 | 
			
		||||
                MAT1.row1.z * MAT2.row2.w + MAT1.row1.w * MAT2.row3.w,         \
 | 
			
		||||
      .row2.x = MAT1.row2.x * MAT2.row0.x + MAT1.row2.y * MAT2.row1.x +        \
 | 
			
		||||
                MAT1.row2.z * MAT2.row2.x + MAT1.row2.w * MAT2.row3.x,         \
 | 
			
		||||
      .row2.y = MAT1.row2.x * MAT2.row0.y + MAT1.row2.y * MAT2.row1.y +        \
 | 
			
		||||
                MAT1.row2.z * MAT2.row2.y + MAT1.row2.w * MAT2.row3.y,         \
 | 
			
		||||
      .row2.z = MAT1.row2.x * MAT2.row0.z + MAT1.row2.y * MAT2.row1.z +        \
 | 
			
		||||
                MAT1.row2.z * MAT2.row2.z + MAT1.row2.w * MAT2.row3.z,         \
 | 
			
		||||
      .row2.w = MAT1.row2.x * MAT2.row0.w + MAT1.row2.y * MAT2.row1.w +        \
 | 
			
		||||
                MAT1.row2.z * MAT2.row2.w + MAT1.row2.w * MAT2.row3.w,         \
 | 
			
		||||
      .row3.x = MAT1.row3.x * MAT2.row0.x + MAT1.row3.y * MAT2.row1.x +        \
 | 
			
		||||
                MAT1.row3.z * MAT2.row2.x + MAT1.row3.w * MAT2.row3.x,         \
 | 
			
		||||
      .row3.y = MAT1.row3.x * MAT2.row0.y + MAT1.row3.y * MAT2.row1.y +        \
 | 
			
		||||
                MAT1.row3.z * MAT2.row2.y + MAT1.row3.w * MAT2.row3.y,         \
 | 
			
		||||
      .row3.z = MAT1.row3.x * MAT2.row0.z + MAT1.row3.y * MAT2.row1.z +        \
 | 
			
		||||
                MAT1.row3.z * MAT2.row2.z + MAT1.row3.w * MAT2.row3.z,         \
 | 
			
		||||
      .row3.w = MAT1.row3.x * MAT2.row0.w + MAT1.row3.y * MAT2.row1.w +        \
 | 
			
		||||
                MAT1.row3.z * MAT2.row2.w + MAT1.row3.w * MAT2.row3.w,         \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define mat4x4_mul_vec4(MAT, V)                                                \
 | 
			
		||||
  ((V4f){                                                                      \
 | 
			
		||||
      .x = MAT.row0.x * V.x + MAT.row0.y * V.y + MAT.row0.z * V.z +            \
 | 
			
		||||
           MAT.row0.w * V.w,                                                   \
 | 
			
		||||
      .y = MAT.row1.x * V.x + MAT.row1.y * V.y + MAT.row1.z * V.z +            \
 | 
			
		||||
           MAT.row1.w * V.w,                                                   \
 | 
			
		||||
      .z = MAT.row2.x * V.x + MAT.row2.y * V.y + MAT.row2.z * V.z +            \
 | 
			
		||||
           MAT.row2.w * V.w,                                                   \
 | 
			
		||||
      .w = MAT.row3.x * V.x + MAT.row3.y * V.y + MAT.row3.z * V.z +            \
 | 
			
		||||
           MAT.row3.w * V.w,                                                   \
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
#define project_vec4(V) ((V3f){.x = V.x / V.w, .y = V.y / V.w, .z = V.z / V.w})
 | 
			
		||||
 | 
			
		||||
#define mat_access(MAT, i, j) (MAT.rows[i].elements[j])
 | 
			
		||||
 | 
			
		||||
M4x4f lookat(V3f eye, V3f target, V3f up);
 | 
			
		||||
M4x4f projection(f32 coeff);
 | 
			
		||||
M4x4f viewport(f32 x, f32 y, u64 w, u64 h);
 | 
			
		||||
M3x3f mat3x3_inv(M3x3f matrix);
 | 
			
		||||
M4x4f mat4x4_inv(M4x4f matrix);
 | 
			
		||||
 | 
			
		||||
#endif // VEC_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user