Add items

master
Elias Fleckenstein 2022-04-19 23:30:07 +02:00
parent 32781feeff
commit dde805203b
No known key found for this signature in database
GPG Key ID: 06927A5199D6C9B2
63 changed files with 1695 additions and 241 deletions

2
deps/protogen vendored

@ -1 +1 @@
Subproject commit 45b691209c95e5a758536a32564c329683550dca
Subproject commit 97963be1d8fbc53dce1b116f1d62340dee83383c

BIN
meshes/axe.gox Normal file

Binary file not shown.

39
meshes/axe.txt Normal file
View File

@ -0,0 +1,39 @@
# Goxel 0.10.6
# One line per voxel
# X Y Z RRGGBB
0 -1 9 a5a5a5
0 -1 10 a0a0a0
0 0 0 503612
0 0 1 503612
0 0 2 584120
0 0 3 43351e
0 0 4 503612
0 0 5 503612
0 0 6 4a3312
0 0 7 5c421a
0 3 7 a0a0a0
0 4 7 9e9e9e
0 0 8 5a380e
0 2 8 9e9e9e
0 3 8 a1a1a1
0 4 8 a1a1a1
0 0 9 a1a1a1
1 0 9 a0a0a0
0 1 9 9e9e9e
0 2 9 9e9e9e
0 3 9 a1a1a1
0 4 9 9e9e9e
0 0 10 989898
1 0 10 a0a0a0
0 1 10 a0a0a0
0 2 10 9e9e9e
0 3 10 9e9e9e
0 4 10 9e9e9e
0 0 11 5c421a
0 2 11 a0a0a0
0 3 11 9e9e9e
0 4 11 a1a1a1
0 3 12 9e9e9e
0 4 12 9e9e9e
-1 0 9 a0a0a0
-1 0 10 a0a0a0

BIN
meshes/pickaxe.gox Normal file

Binary file not shown.

31
meshes/pickaxe.txt Normal file
View File

@ -0,0 +1,31 @@
# Goxel 0.10.6
# One line per voxel
# X Y Z RRGGBB
0 -4 7 a0a0a0
0 -4 8 a0a0a0
0 -3 8 999999
0 -3 9 a0a0a0
0 -2 9 a0a0a0
0 -1 9 8b8b8b
0 -2 10 a0a0a0
0 -1 10 a9a9a9
0 0 0 503612
0 0 1 503612
0 0 2 584120
0 0 3 43351e
0 0 4 503612
0 0 5 503612
0 0 6 4a3312
0 0 7 5c421a
0 4 7 999999
0 0 8 5a380e
0 3 8 999999
0 4 8 a0a0a0
0 0 9 a0a0a0
0 1 9 a9a9a9
0 2 9 a0a0a0
0 3 9 a0a0a0
0 0 10 a9a9a9
0 1 10 8b8b8b
0 2 10 a0a0a0
0 0 11 a0a0a0

BIN
meshes/unknown.gox Normal file

Binary file not shown.

732
meshes/unknown.txt Normal file
View File

@ -0,0 +1,732 @@
# Goxel 0.10.6
# One line per voxel
# X Y Z RRGGBB
0 0 0 920088
1 0 0 920088
2 0 0 920088
3 0 0 920088
4 0 0 920088
5 0 0 920088
6 0 0 920088
7 0 0 920088
8 0 0 920088
0 1 0 920088
1 1 0 c400bc
2 1 0 c400bc
3 1 0 c400bc
4 1 0 c400bc
5 1 0 c400bc
6 1 0 c400bc
7 1 0 c400bc
8 1 0 920088
0 2 0 920088
1 2 0 c400bc
2 2 0 c400bc
3 2 0 cdd300
4 2 0 cdd300
5 2 0 cdd300
6 2 0 c400bc
7 2 0 c400bc
8 2 0 920088
0 3 0 920088
1 3 0 c400bc
2 3 0 cdd300
3 3 0 c400bc
4 3 0 c400bc
5 3 0 c400bc
6 3 0 cdd300
7 3 0 c400bc
8 3 0 920088
0 4 0 920088
1 4 0 c400bc
2 4 0 c400bc
3 4 0 c400bc
4 4 0 cdd300
5 4 0 cdd300
6 4 0 c400bc
7 4 0 c400bc
8 4 0 920088
0 5 0 920088
1 5 0 c400bc
2 5 0 c400bc
3 5 0 c400bc
4 5 0 c400bc
5 5 0 c400bc
6 5 0 c400bc
7 5 0 c400bc
8 5 0 920088
0 6 0 920088
1 6 0 c400bc
2 6 0 c400bc
3 6 0 c400bc
4 6 0 cdd300
5 6 0 c400bc
6 6 0 c400bc
7 6 0 c400bc
8 6 0 920088
0 7 0 920088
1 7 0 c400bc
2 7 0 c400bc
3 7 0 c400bc
4 7 0 c400bc
5 7 0 c400bc
6 7 0 c400bc
7 7 0 c400bc
8 7 0 920088
0 8 0 920088
1 8 0 920088
2 8 0 920088
3 8 0 920088
4 8 0 920088
5 8 0 920088
6 8 0 920088
7 8 0 920088
8 8 0 920088
0 0 1 920088
1 0 1 c400bc
2 0 1 c400bc
3 0 1 c400bc
4 0 1 c400bc
5 0 1 c400bc
6 0 1 c400bc
7 0 1 c400bc
8 0 1 920088
0 1 1 c400bc
1 1 1 ffffff
2 1 1 ffffff
3 1 1 ffffff
4 1 1 ffffff
5 1 1 ffffff
6 1 1 ffffff
7 1 1 ffffff
8 1 1 c400bc
0 2 1 c400bc
1 2 1 ffffff
2 2 1 ffffff
3 2 1 ffffff
4 2 1 ffffff
5 2 1 ffffff
6 2 1 ffffff
7 2 1 ffffff
8 2 1 c400bc
0 3 1 c400bc
1 3 1 ffffff
2 3 1 ffffff
3 3 1 ffffff
4 3 1 ffffff
5 3 1 ffffff
6 3 1 ffffff
7 3 1 ffffff
8 3 1 c400bc
0 4 1 c400bc
1 4 1 ffffff
2 4 1 ffffff
3 4 1 ffffff
4 4 1 ffffff
5 4 1 ffffff
6 4 1 ffffff
7 4 1 ffffff
8 4 1 c400bc
0 5 1 c400bc
1 5 1 ffffff
2 5 1 ffffff
3 5 1 ffffff
4 5 1 ffffff
5 5 1 ffffff
6 5 1 ffffff
7 5 1 ffffff
8 5 1 c400bc
0 6 1 c400bc
1 6 1 ffffff
2 6 1 ffffff
3 6 1 ffffff
4 6 1 ffffff
5 6 1 ffffff
6 6 1 ffffff
7 6 1 ffffff
8 6 1 c400bc
0 7 1 c400bc
1 7 1 ffffff
2 7 1 ffffff
3 7 1 ffffff
4 7 1 ffffff
5 7 1 ffffff
6 7 1 ffffff
7 7 1 ffffff
8 7 1 c400bc
0 8 1 920088
1 8 1 c400bc
2 8 1 c400bc
3 8 1 c400bc
4 8 1 c400bc
5 8 1 c400bc
6 8 1 c400bc
7 8 1 c400bc
8 8 1 920088
0 0 2 920088
1 0 2 c400bc
2 0 2 c400bc
3 0 2 c400bc
4 0 2 cdd300
5 0 2 c400bc
6 0 2 c400bc
7 0 2 c400bc
8 0 2 920088
0 1 2 c400bc
1 1 2 ffffff
2 1 2 ffffff
3 1 2 ffffff
4 1 2 ffffff
5 1 2 ffffff
6 1 2 ffffff
7 1 2 ffffff
8 1 2 c400bc
0 2 2 c400bc
1 2 2 ffffff
2 2 2 ffffff
3 2 2 ffffff
4 2 2 ffffff
5 2 2 ffffff
6 2 2 ffffff
7 2 2 ffffff
8 2 2 c400bc
0 3 2 c400bc
1 3 2 ffffff
2 3 2 ffffff
3 3 2 ffffff
4 3 2 ffffff
5 3 2 ffffff
6 3 2 ffffff
7 3 2 ffffff
8 3 2 c400bc
0 4 2 cdd300
1 4 2 ffffff
2 4 2 ffffff
3 4 2 ffffff
4 4 2 ffffff
5 4 2 ffffff
6 4 2 ffffff
7 4 2 ffffff
8 4 2 cdd300
0 5 2 c400bc
1 5 2 ffffff
2 5 2 ffffff
3 5 2 ffffff
4 5 2 ffffff
5 5 2 ffffff
6 5 2 ffffff
7 5 2 ffffff
8 5 2 c400bc
0 6 2 c400bc
1 6 2 ffffff
2 6 2 ffffff
3 6 2 ffffff
4 6 2 ffffff
5 6 2 ffffff
6 6 2 ffffff
7 6 2 ffffff
8 6 2 c400bc
0 7 2 c400bc
1 7 2 ffffff
2 7 2 ffffff
3 7 2 ffffff
4 7 2 ffffff
5 7 2 ffffff
6 7 2 ffffff
7 7 2 ffffff
8 7 2 c400bc
0 8 2 920088
1 8 2 c400bc
2 8 2 c400bc
3 8 2 c400bc
4 8 2 cdd300
5 8 2 c400bc
6 8 2 c400bc
7 8 2 c400bc
8 8 2 920088
0 0 3 920088
1 0 3 c400bc
2 0 3 c400bc
3 0 3 c400bc
4 0 3 c400bc
5 0 3 c400bc
6 0 3 c400bc
7 0 3 c400bc
8 0 3 920088
0 1 3 c400bc
1 1 3 ffffff
2 1 3 c400bc
3 1 3 c400bc
4 1 3 ffffff
5 1 3 ffffff
6 1 3 ffffff
7 1 3 ffffff
8 1 3 c400bc
0 2 3 c400bc
1 2 3 c400bc
2 2 3 c400bc
3 2 3 ffffff
4 2 3 ffffff
5 2 3 ffffff
6 2 3 ffffff
7 2 3 ffffff
8 2 3 c400bc
0 3 3 c400bc
1 3 3 ffffff
2 3 3 ffffff
3 3 3 ffffff
4 3 3 ffffff
5 3 3 ffffff
6 3 3 ffffff
7 3 3 ffffff
8 3 3 c400bc
0 4 3 c400bc
1 4 3 ffffff
2 4 3 ffffff
3 4 3 ffffff
4 4 3 ffffff
5 4 3 ffffff
6 4 3 ffffff
7 4 3 ffffff
8 4 3 c400bc
0 5 3 c400bc
1 5 3 ffffff
2 5 3 ffffff
3 5 3 ffffff
4 5 3 ffffff
5 5 3 ffffff
6 5 3 ffffff
7 5 3 ffffff
8 5 3 c400bc
0 6 3 c400bc
1 6 3 ffffff
2 6 3 ffffff
3 6 3 ffffff
4 6 3 ffffff
5 6 3 ffffff
6 6 3 ffffff
7 6 3 ffffff
8 6 3 c400bc
0 7 3 c400bc
1 7 3 ffffff
2 7 3 ffffff
3 7 3 ffffff
4 7 3 ffffff
5 7 3 ffffff
6 7 3 ffffff
7 7 3 ffffff
8 7 3 c400bc
0 8 3 920088
1 8 3 c400bc
2 8 3 c400bc
3 8 3 c400bc
4 8 3 c400bc
5 8 3 c400bc
6 8 3 c400bc
7 8 3 c400bc
8 8 3 920088
0 0 4 920088
1 0 4 c400bc
2 0 4 c400bc
3 0 4 c400bc
4 0 4 cdd300
5 0 4 cdd300
6 0 4 c400bc
7 0 4 c400bc
8 0 4 920088
0 1 4 c400bc
1 1 4 c400bc
2 1 4 c400bc
3 1 4 ffffff
4 1 4 ffffff
5 1 4 ffffff
6 1 4 ffffff
7 1 4 ffffff
8 1 4 c400bc
0 2 4 c400bc
1 2 4 c400bc
2 2 4 ffffff
3 2 4 ffffff
4 2 4 ffffff
5 2 4 ffffff
6 2 4 ffffff
7 2 4 ffffff
8 2 4 c400bc
0 3 4 cdd300
1 3 4 ffffff
2 3 4 ffffff
3 3 4 ffffff
4 3 4 ffffff
5 3 4 ffffff
6 3 4 ffffff
7 3 4 ffffff
8 3 4 c400bc
0 4 4 cdd300
1 4 4 ffffff
2 4 4 ffffff
3 4 4 ffffff
4 4 4 ffffff
5 4 4 ffffff
6 4 4 ffffff
7 4 4 ffffff
8 4 4 cdd300
0 5 4 c400bc
1 5 4 ffffff
2 5 4 ffffff
3 5 4 ffffff
4 5 4 ffffff
5 5 4 ffffff
6 5 4 ffffff
7 5 4 ffffff
8 5 4 cdd300
0 6 4 c400bc
1 6 4 ffffff
2 6 4 ffffff
3 6 4 ffffff
4 6 4 ffffff
5 6 4 ffffff
6 6 4 ffffff
7 6 4 ffffff
8 6 4 c400bc
0 7 4 c400bc
1 7 4 ffffff
2 7 4 ffffff
3 7 4 ffffff
4 7 4 ffffff
5 7 4 ffffff
6 7 4 ffffff
7 7 4 ffffff
8 7 4 c400bc
0 8 4 920088
1 8 4 c400bc
2 8 4 c400bc
3 8 4 cdd300
4 8 4 cdd300
5 8 4 c400bc
6 8 4 c400bc
7 8 4 c400bc
8 8 4 920088
0 0 5 920088
1 0 5 c400bc
2 0 5 cdd300
3 0 5 c400bc
4 0 5 c400bc
5 0 5 c400bc
6 0 5 cdd300
7 0 5 c400bc
8 0 5 920088
0 1 5 c400bc
1 1 5 c400bc
2 1 5 ffffff
3 1 5 ffffff
4 1 5 ffffff
5 1 5 ffffff
6 1 5 ffffff
7 1 5 ffffff
8 1 5 c400bc
0 2 5 cdd300
1 2 5 ffffff
2 2 5 ffffff
3 2 5 ffffff
4 2 5 ffffff
5 2 5 ffffff
6 2 5 ffffff
7 2 5 ffffff
8 2 5 cdd300
0 3 5 c400bc
1 3 5 ffffff
2 3 5 ffffff
3 3 5 ffffff
4 3 5 ffffff
5 3 5 ffffff
6 3 5 ffffff
7 3 5 ffffff
8 3 5 c400bc
0 4 5 c400bc
1 4 5 ffffff
2 4 5 ffffff
3 4 5 ffffff
4 4 5 ffffff
5 4 5 ffffff
6 4 5 ffffff
7 4 5 ffffff
8 4 5 c400bc
0 5 5 c400bc
1 5 5 ffffff
2 5 5 ffffff
3 5 5 ffffff
4 5 5 ffffff
5 5 5 ffffff
6 5 5 ffffff
7 5 5 ffffff
8 5 5 c400bc
0 6 5 cdd300
1 6 5 ffffff
2 6 5 ffffff
3 6 5 ffffff
4 6 5 ffffff
5 6 5 ffffff
6 6 5 ffffff
7 6 5 ffffff
8 6 5 cdd300
0 7 5 c400bc
1 7 5 ffffff
2 7 5 ffffff
3 7 5 ffffff
4 7 5 ffffff
5 7 5 ffffff
6 7 5 ffffff
7 7 5 ffffff
8 7 5 c400bc
0 8 5 920088
1 8 5 c400bc
2 8 5 cdd300
3 8 5 c400bc
4 8 5 c400bc
5 8 5 c400bc
6 8 5 cdd300
7 8 5 c400bc
8 8 5 920088
0 0 6 920088
1 0 6 c400bc
2 0 6 c400bc
3 0 6 cdd300
4 0 6 cdd300
5 0 6 cdd300
6 0 6 c400bc
7 0 6 c400bc
8 0 6 920088
0 1 6 c400bc
1 1 6 c400bc
2 1 6 c400bc
3 1 6 c400bc
4 1 6 ffffff
5 1 6 ffffff
6 1 6 c400bc
7 1 6 c400bc
8 1 6 c400bc
0 2 6 c400bc
1 2 6 c400bc
2 2 6 ffffff
3 2 6 ffffff
4 2 6 ffffff
5 2 6 ffffff
6 2 6 ffffff
7 2 6 ffffff
8 2 6 c400bc
0 3 6 cdd300
1 3 6 ffffff
2 3 6 ffffff
3 3 6 ffffff
4 3 6 ffffff
5 3 6 ffffff
6 3 6 ffffff
7 3 6 ffffff
8 3 6 cdd300
0 4 6 cdd300
1 4 6 ffffff
2 4 6 ffffff
3 4 6 ffffff
4 4 6 ffffff
5 4 6 ffffff
6 4 6 ffffff
7 4 6 ffffff
8 4 6 cdd300
0 5 6 cdd300
1 5 6 ffffff
2 5 6 ffffff
3 5 6 ffffff
4 5 6 ffffff
5 5 6 ffffff
6 5 6 ffffff
7 5 6 ffffff
8 5 6 cdd300
0 6 6 c400bc
1 6 6 ffffff
2 6 6 ffffff
3 6 6 ffffff
4 6 6 ffffff
5 6 6 ffffff
6 6 6 ffffff
7 6 6 ffffff
8 6 6 c400bc
0 7 6 c400bc
1 7 6 ffffff
2 7 6 ffffff
3 7 6 ffffff
4 7 6 ffffff
5 7 6 ffffff
6 7 6 ffffff
7 7 6 ffffff
8 7 6 c400bc
0 8 6 920088
1 8 6 c400bc
2 8 6 c400bc
3 8 6 cdd300
4 8 6 cdd300
5 8 6 cdd300
6 8 6 c400bc
7 8 6 c400bc
8 8 6 920088
0 0 7 920088
1 0 7 c400bc
2 0 7 c400bc
3 0 7 c400bc
4 0 7 c400bc
5 0 7 c400bc
6 0 7 c400bc
7 0 7 c400bc
8 0 7 920088
0 1 7 c400bc
1 1 7 ffffff
2 1 7 c400bc
3 1 7 ffffff
4 1 7 ffffff
5 1 7 ffffff
6 1 7 ffffff
7 1 7 c400bc
8 1 7 c400bc
0 2 7 c400bc
1 2 7 c400bc
2 2 7 c400bc
3 2 7 c400bc
4 2 7 ffffff
5 2 7 c400bc
6 2 7 c400bc
7 2 7 c400bc
8 2 7 c400bc
0 3 7 c400bc
1 3 7 c400bc
2 3 7 ffffff
3 3 7 ffffff
4 3 7 c400bc
5 3 7 c400bc
6 3 7 c400bc
7 3 7 ffffff
8 3 7 c400bc
0 4 7 c400bc
1 4 7 ffffff
2 4 7 ffffff
3 4 7 ffffff
4 4 7 ffffff
5 4 7 ffffff
6 4 7 ffffff
7 4 7 ffffff
8 4 7 c400bc
0 5 7 c400bc
1 5 7 ffffff
2 5 7 ffffff
3 5 7 ffffff
4 5 7 ffffff
5 5 7 ffffff
6 5 7 ffffff
7 5 7 ffffff
8 5 7 c400bc
0 6 7 c400bc
1 6 7 ffffff
2 6 7 ffffff
3 6 7 ffffff
4 6 7 ffffff
5 6 7 ffffff
6 6 7 ffffff
7 6 7 ffffff
8 6 7 c400bc
0 7 7 c400bc
1 7 7 ffffff
2 7 7 ffffff
3 7 7 ffffff
4 7 7 ffffff
5 7 7 ffffff
6 7 7 ffffff
7 7 7 ffffff
8 7 7 c400bc
0 8 7 920088
1 8 7 c400bc
2 8 7 c400bc
3 8 7 c400bc
4 8 7 c400bc
5 8 7 c400bc
6 8 7 c400bc
7 8 7 c400bc
8 8 7 920088
0 0 8 920088
1 0 8 920088
2 0 8 920088
3 0 8 920088
4 0 8 920088
5 0 8 920088
6 0 8 920088
7 0 8 920088
8 0 8 920088
0 1 8 920088
1 1 8 c400bc
2 1 8 c400bc
3 1 8 c400bc
4 1 8 c400bc
5 1 8 c400bc
6 1 8 c400bc
7 1 8 c400bc
8 1 8 920088
0 2 8 920088
1 2 8 c400bc
2 2 8 c400bc
3 2 8 c400bc
4 2 8 cdd300
5 2 8 c400bc
6 2 8 c400bc
7 2 8 c400bc
8 2 8 920088
0 3 8 920088
1 3 8 c400bc
2 3 8 c400bc
3 3 8 c400bc
4 3 8 c400bc
5 3 8 c400bc
6 3 8 c400bc
7 3 8 c400bc
8 3 8 920088
0 4 8 920088
1 4 8 c400bc
2 4 8 c400bc
3 4 8 c400bc
4 4 8 cdd300
5 4 8 cdd300
6 4 8 c400bc
7 4 8 c400bc
8 4 8 920088
0 5 8 920088
1 5 8 c400bc
2 5 8 cdd300
3 5 8 c400bc
4 5 8 c400bc
5 5 8 c400bc
6 5 8 cdd300
7 5 8 c400bc
8 5 8 920088
0 6 8 920088
1 6 8 c400bc
2 6 8 c400bc
3 6 8 cdd300
4 6 8 cdd300
5 6 8 cdd300
6 6 8 c400bc
7 6 8 c400bc
8 6 8 920088
0 7 8 920088
1 7 8 c400bc
2 7 8 c400bc
3 7 8 c400bc
4 7 8 c400bc
5 7 8 c400bc
6 7 8 c400bc
7 7 8 c400bc
8 7 8 920088
0 8 8 920088
1 8 8 920088
2 8 8 920088
3 8 8 920088
4 8 8 920088
5 8 8 920088
6 8 8 920088
7 8 8 920088
8 8 8 920088

View File

@ -1,19 +1,15 @@
name player scale 1 1.8 1
name nametag pos 0 1.1 0
name neck pos 0 0.75 0 scale 0.45 0.25 0.45
name head pos 0 +0.5 0 cube head
name eyes pos 0 0 +0.5
name body scale 0.48 0.75 0.225
name upper pos 0 1.0 0 scale 1 0.5 1
name chest pos 0 -0.5 0 cube chest
name shoulders scale 0.5 1 1
name left pos -1.5 0 0
name arm pos 0 -0.5 0 cube arm
name right pos +1.5 0 0
name arm pos 0 -0.5 0 cube arm
name lower pos 0 0.5 0 scale 1 0.5 1
name hips scale 0.5 1 1
name left pos -0.5 0 0
name leg pos 0 -0.5 0 cube leg
name right pos +0.5 0 0
name leg pos 0 -0.5 0 cube leg
name nametag pos 0 2 0
name neck pos 0 1.35 0
name head pos 0 0.225 0 scale 0.45 0.45 0.45 cube head
name eyes pos 0 0 +0.5
name chest pos 0 1.0125 0 scale 0.48 0.675 0.225 cube chest
name arm_left pos -0.36 1.35 0 scale -1 1 1 clockwise
pos 0 -0.3375 0 scale 0.24 0.675 0.225 cube arm
name hand pos 0 -0.585 0 scale 0.0625 0.0625 0.0625 rot 90 0 0
name arm_right pos +0.36 1.35 0
pos 0 -0.3375 0 scale 0.24 0.675 0.225 cube arm
name hand pos 0 -0.585 0 scale 0.0625 0.0625 0.0625 rot 90 0 0
name leg_left pos -0.12 0.675 0 scale -1 1 1 clockwise
pos 0 -0.3375 0 scale 0.24 0.675 0.225 cube leg
name leg_right pos +0.12 0.675 0
pos 0 -0.3375 0 scale 0.24 0.675 0.225 cube leg

View File

@ -1,5 +1,4 @@
in vec3 fragmentPosition;
in vec3 fragmentNormal;
in vec3 fragmentTextureCoordinates;
in float fragmentLight;

View File

@ -2,7 +2,6 @@ layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
out vec3 fragmentPosition;
out vec3 fragmentNormal;
out vec3 fragmentTextureCoordinates;
out float fragmentLight;
@ -18,9 +17,9 @@ void main()
gl_Position = VP * worldSpace;
fragmentPosition = worldSpace.xyz;
fragmentNormal = vertexNormal;
fragmentTextureCoordinates = vertexPosition;
float diffuseLight = 0.3 * daylight * clamp(dot(normalize(fragmentNormal), normalize(lightDir)), 0.0, 1.0);
fragmentLight = ambientLight + diffuseLight;
mat3 normalMatrix = transpose(inverse(mat3(model)));
vec3 normal = normalize(normalMatrix * vertexNormal);
fragmentLight = ambientLight + 0.3 * daylight * clamp(dot(normal, normalize(lightDir)), 0.0, 1.0);
}

16
shaders/3d/item/fragment.glsl Executable file
View File

@ -0,0 +1,16 @@
in vec3 fragmentPosition;
in vec3 fragmentColor;
out vec4 outColor;
uniform vec3 fogColor;
uniform vec3 cameraPos;
void main()
{
outColor = vec4(fragmentColor, 1.0);
outColor.rgb = mix(outColor.rgb, fogColor, clamp(length(fragmentPosition - cameraPos) / VIEW_DISTANCE, 0.0, 1.0));
if (outColor.a == 0.0)
discard;
}

25
shaders/3d/item/vertex.glsl Executable file
View File

@ -0,0 +1,25 @@
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec3 vertexColor;
out vec3 fragmentPosition;
out vec3 fragmentColor;
uniform mat4 model;
uniform mat4 VP;
uniform float daylight;
uniform float ambientLight;
uniform vec3 lightDir;
void main()
{
vec4 worldSpace = model * vec4(vertexPosition, 1.0);
gl_Position = VP * worldSpace;
fragmentPosition = worldSpace.xyz;
fragmentColor = vertexColor;
mat3 normalMatrix = transpose(inverse(mat3(model)));
vec3 normal = normalize(normalMatrix * vertexNormal);
fragmentColor *= ambientLight + 0.3 * daylight * clamp(dot(normal, normalize(lightDir)), 0.0, 1.0);
}

View File

@ -1,5 +1,4 @@
in vec3 fragmentPosition;
in vec3 fragmentNormal;
in vec2 fragmentTextureCoordinates;
in float fragmentTextureIndex;
in vec3 fragmentColor;

View File

@ -5,7 +5,6 @@ layout(location = 3) in float vertexTextureIndex;
layout(location = 4) in vec3 vertexColor;
out vec3 fragmentPosition;
out vec3 fragmentNormal;
out vec2 fragmentTextureCoordinates;
out float fragmentTextureIndex;
out vec3 fragmentColor;
@ -22,13 +21,9 @@ void main()
gl_Position = VP * worldSpace;
fragmentPosition = worldSpace.xyz;
fragmentNormal = vertexNormal;
fragmentTextureCoordinates = vertexTextureCoordinates;
fragmentTextureIndex = vertexTextureIndex;
fragmentColor = vertexColor;
float diffuseLight = 0.3 * daylight * clamp(dot(normalize(fragmentNormal), normalize(lightDir)), 0.0, 1.0);
float light = ambientLight + diffuseLight;
fragmentColor *= light;
fragmentColor *= ambientLight + 0.3 * daylight * clamp(dot(normalize(vertexNormal), normalize(lightDir)), 0.0, 1.0);
}

View File

@ -79,6 +79,7 @@ set(COMMON_SOURCES
day.c
environment.c
interrupt.c
item.c
node.c
perlin.c
physics.c
@ -94,6 +95,8 @@ add_executable(dragonblocks
client/client_auth.c
client/client_config.c
client/client_entity.c
client/client_inventory.c
client/client_item.c
client/client_node.c
client/client_player.c
client/client_terrain.c
@ -111,6 +114,7 @@ add_executable(dragonblocks
client/mesh.c
client/model.c
client/raycast.c
client/screenshot.c
client/shader.c
client/sky.c
client/terrain_gfx.c

View File

@ -1,6 +1,5 @@
#include <math.h>
#include "client/camera.h"
#include "client/client.h"
struct Camera camera;
@ -14,6 +13,12 @@ static void camera_update()
mat4x4_look_at(camera.view, camera.eye, center, camera.up);
}
void camera_init()
{
camera_set_position((v3f32) {0.0f, 0.0f, 0.0f});
camera_set_angle(0.0f, 0.0f);
}
void camera_set_position(v3f32 pos)
{
camera.eye[0] = pos.x;

View File

@ -1,8 +1,6 @@
#ifndef _CAMERA_H_
#define _CAMERA_H_
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <linmath.h/linmath.h>
#include "types.h"
@ -16,8 +14,8 @@ extern struct Camera {
} movement_dirs;
} camera;
void camera_init();
void camera_set_position(v3f32 pos);
void camera_set_angle(f32 yaw, f32 pitch);
void camera_on_resize(int width, int height);
#endif // _CAMERA_H_

View File

@ -7,6 +7,7 @@
#include <unistd.h>
#include "client/client.h"
#include "client/client_auth.h"
#include "client/client_inventory.h"
#include "client/client_player.h"
#include "client/client_terrain.h"
#include "client/debug_menu.h"
@ -143,6 +144,7 @@ int main(int argc, char **argv)
client->on_recv_type[DRAGONNET_TYPE_ToClientEntityRemove ] = (void *) &client_entity_remove;
client->on_recv_type[DRAGONNET_TYPE_ToClientEntityUpdatePosRot ] = (void *) &client_entity_update_pos_rot;
client->on_recv_type[DRAGONNET_TYPE_ToClientEntityUpdateNametag] = (void *) &client_entity_update_nametag;
client->on_recv_type[DRAGONNET_TYPE_ToClientPlayerInventory ] = (void *) &client_inventory_update_player;
flag_ini(&finish);
flag_ini(&gfx_init);

View File

@ -94,7 +94,7 @@ static void update_nametag(ClientEntity *entity)
if (!entity->data.nametag)
entity->nametag->visible = false;
} else if (entity->data.nametag) {
entity->nametag = gui_add(NULL, (GUIElementDefinition) {
entity->nametag = gui_add(NULL, (GUIElementDef) {
.pos = {-1.0f, -1.0f},
.z_index = 0.1f,
.offset = {0, 0},
@ -233,7 +233,7 @@ void client_entity_transform(ClientEntity *entity)
model_node_transform(entity->model->root);
}
void client_entity_add(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityAdd *pkt)
void client_entity_add(__attribute__((unused)) void *peer, ToClientEntityAdd *pkt)
{
if (pkt->type >= COUNT_ENTITY)
return;
@ -264,12 +264,12 @@ void client_entity_add(__attribute__((unused)) DragonnetPeer *peer, ToClientEnti
refcount_drp(&entity->rc);
}
void client_entity_remove(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityRemove *pkt)
void client_entity_remove(__attribute__((unused)) void *peer, ToClientEntityRemove *pkt)
{
map_del(&entities, &pkt->id, &cmp_entity, &entity_drop, NULL, &refcount_obj);
}
void client_entity_update_pos_rot(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityUpdatePosRot *pkt)
void client_entity_update_pos_rot(__attribute__((unused)) void *peer, ToClientEntityUpdatePosRot *pkt)
{
ClientEntity *entity = client_entity_grab(pkt->id);
@ -291,7 +291,7 @@ void client_entity_update_pos_rot(__attribute__((unused)) DragonnetPeer *peer, T
refcount_drp(&entity->rc);
}
void client_entity_update_nametag(__attribute__((unused)) DragonnetPeer *peer, ToClientEntityUpdateNametag *pkt)
void client_entity_update_nametag(__attribute__((unused)) void *peer, ToClientEntityUpdateNametag *pkt)
{
ClientEntity *entity = client_entity_grab(pkt->id);

View File

@ -1,12 +1,12 @@
#ifndef _CLIENT_ENTITY_H_
#define _CLIENT_ENTITY_H_
#include <dragonnet/peer.h>
#include <dragonstd/refcount.h>
#include <pthread.h>
#include "client/gui.h"
#include "client/model.h"
#include "entity.h"
#include "item.h"
#include "types.h"
typedef struct {
@ -56,9 +56,9 @@ void client_entity_drop(ClientEntity *entity);
void client_entity_transform(ClientEntity *entity);
void client_entity_add(DragonnetPeer *peer, ToClientEntityAdd *pkt);
void client_entity_remove(DragonnetPeer *peer, ToClientEntityRemove *pkt);
void client_entity_update_pos_rot(DragonnetPeer *peer, ToClientEntityUpdatePosRot *pkt);
void client_entity_update_nametag(DragonnetPeer *peer, ToClientEntityUpdateNametag *pkt);
void client_entity_add(void *peer, ToClientEntityAdd *pkt);
void client_entity_remove(void *peer, ToClientEntityRemove *pkt);
void client_entity_update_pos_rot(void *peer, ToClientEntityUpdatePosRot *pkt);
void client_entity_update_nametag(void *peer, ToClientEntityUpdateNametag *pkt);
#endif // _CLIENT_ENTITY_H_

View File

@ -0,0 +1,109 @@
#include <asprintf/asprintf.h>
#include <stdio.h>
#include <stdlib.h>
#include "client/client_config.h"
#include "client/client_inventory.h"
#include "client/client_item.h"
#include "client/gl_debug.h"
#include "client/frustum.h"
#include "client/light.h"
#include "client/shader.h"
static GLuint _3d_shader_prog;
static GLint _3d_loc_VP;
static ModelShader _3d_model_shader;
static LightShader _3d_light_shader;
bool client_inventory_init()
{
char *_3d_shader_defs;
asprintf(&_3d_shader_defs, "#define VIEW_DISTANCE %lf\n", client_config.view_distance);
if (!shader_program_create(RESSOURCE_PATH "shaders/3d/item", &_3d_shader_prog, _3d_shader_defs)) {
fprintf(stderr, "[error] failed to create 3D item shader program\n");
return false;
}
free(_3d_shader_defs);
_3d_loc_VP = glGetUniformLocation(_3d_shader_prog, "VP");
_3d_model_shader.prog = _3d_shader_prog;
_3d_model_shader.loc_transform = glGetUniformLocation(_3d_shader_prog, "model"); GL_DEBUG
_3d_light_shader.prog = _3d_shader_prog;
light_shader_locate(&_3d_light_shader);
return true;
}
void client_inventory_deinit()
{
glDeleteProgram(_3d_shader_prog); GL_DEBUG
}
void client_inventory_update()
{
glProgramUniformMatrix4fv(_3d_shader_prog, _3d_loc_VP, 1, GL_FALSE, frustum[0]); GL_DEBUG
light_shader_update(&_3d_light_shader);
}
static void wield_init(ModelNode *hand)
{
if (hand)
model_node_add_mesh(hand, &(ModelMesh) {
.mesh = NULL,
.textures = NULL,
.num_textures = 0,
.shader = &_3d_model_shader,
});
}
static void wield_update(ModelNode *hand, ModelNode *arm, ItemType item)
{
Mesh *mesh = client_item_mesh(item);
if (hand)
((ModelMesh *) hand->meshes.ptr)[0].mesh = mesh;
if (arm) {
arm->rot.x = mesh ? -M_PI / 8.0 : 0.0;
model_node_transform(arm);
}
}
void client_inventory_init_player(ClientEntity *entity)
{
ClientPlayerData *data = entity->extra;
item_stack_initialize(&data->inventory.left);
item_stack_initialize(&data->inventory.right);
wield_init(data->bones.hand_left);
wield_init(data->bones.hand_right);
}
void client_inventory_deinit_player(ClientEntity *entity)
{
ClientPlayerData *data = entity->extra;
item_stack_destroy(&data->inventory.left);
item_stack_destroy(&data->inventory.right);
}
void client_inventory_update_player(__attribute__((unused)) void *peer, ToClientPlayerInventory *pkt)
{
ClientEntity *entity = client_player_entity(pkt->id);
if (!entity)
return;
ClientPlayerData *data = entity->extra;
item_stack_deserialize(&data->inventory.left, &pkt->left);
item_stack_deserialize(&data->inventory.right, &pkt->right);
wield_update(data->bones.hand_left, data->bones.arm_left, data->inventory.left.type);
wield_update(data->bones.hand_right, data->bones.arm_right, data->inventory.right.type);
refcount_drp(&entity->rc);
}

View File

@ -0,0 +1,16 @@
#ifndef _CLIENT_INVENTORY_H_
#define _CLIENT_INVENTORY_H_
#include <stdbool.h>
#include "client/client_player.h"
#include "client/model.h"
bool client_inventory_init();
void client_inventory_deinit();
void client_inventory_update();
void client_inventory_init_player(ClientEntity *entity);
void client_inventory_deinit_player(ClientEntity *entity);
void client_inventory_update_player(void *peer, ToClientPlayerInventory *pkt);
#endif // _CLIENT_INVENTORY_H_

43
src/client/client_item.c Normal file
View File

@ -0,0 +1,43 @@
#include "client/client_item.h"
ClientItemDef client_item_defs[COUNT_ITEM] = {
// unknown
{
.mesh_path = RESSOURCE_PATH "meshes/unknown.txt",
.mesh = {0},
},
// none
{
.mesh_path = NULL,
.mesh = {0},
},
// pickaxe
{
.mesh_path = RESSOURCE_PATH "meshes/pickaxe.txt",
.mesh = {0},
},
// axe
{
.mesh_path = RESSOURCE_PATH "meshes/axe.txt",
.mesh = {0},
},
};
void client_item_init()
{
for (ItemType i = 0; i < COUNT_ITEM; i++)
if (client_item_defs[i].mesh_path)
mesh_load(&client_item_defs[i].mesh, client_item_defs[i].mesh_path);
}
void client_item_deinit()
{
for (ItemType i = 0; i < COUNT_ITEM; i++)
if (client_item_defs[i].mesh_path)
mesh_destroy(&client_item_defs[i].mesh);
}
Mesh *client_item_mesh(ItemType type)
{
return client_item_defs[type].mesh_path ? &client_item_defs[type].mesh : NULL;
}

18
src/client/client_item.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _CLIENT_ITEM_H_
#define _CLIENT_ITEM_H_
#include "client/mesh.h"
#include "item.h"
typedef struct {
const char *mesh_path;
Mesh mesh;
} ClientItemDef;
extern ClientItemDef client_item_defs[];
void client_item_init();
void client_item_deinit();
Mesh *client_item_mesh(ItemType type);
#endif // _CLIENT_ITEM_H_

View File

@ -38,7 +38,7 @@ static void render_color(NodeArgsRender *args)
args->vertex.color = ((ColorData *) args->node->data)->color;
}
ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
ClientNodeDef client_node_defs[NODE_UNLOADED] = {
// unknown
{
.tiles = TILES_SIMPLE(RESSOURCE_PATH "textures/unknown.png"),
@ -47,6 +47,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Unknown",
},
// air
{
@ -56,6 +57,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = false,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Air",
},
// grass
{
@ -65,6 +67,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_grass,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Grass",
},
// dirt
{
@ -74,6 +77,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Dirt",
},
// stone
{
@ -83,6 +87,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_stone,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Stone",
},
// snow
{
@ -92,6 +97,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = true,
.selection_color = {0.1f, 0.5f, 1.0f},
.name = "Snow",
},
// oak wood
{
@ -105,6 +111,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Oak Wood",
},
// oak leaves
{
@ -114,6 +121,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Oak Leaves",
},
// pine wood
{
@ -127,6 +135,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Pine Wood",
},
// pine leaves
{
@ -136,6 +145,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Pine Leaves",
},
// palm wood
{
@ -149,6 +159,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Palm Wood",
},
// palm leaves
{
@ -158,6 +169,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = &render_color,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Palm Leaves",
},
// sand
{
@ -167,6 +179,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Sand",
},
// water
{
@ -176,6 +189,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = false,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Water",
},
// lava
{
@ -185,6 +199,7 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = false,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Lava",
},
// vulcano_stone
{
@ -194,13 +209,14 @@ ClientNodeDefinition client_node_definitions[NODE_UNLOADED] = {
.render = NULL,
.pointable = true,
.selection_color = {1.0f, 1.0f, 1.0f},
.name = "Vulcano Stone",
},
};
void client_node_init()
{
for (NodeType node = NODE_UNKNOWN; node < NODE_UNLOADED; node++) {
ClientNodeDefinition *def = &client_node_definitions[node];
for (NodeType node = 0; node < NODE_UNLOADED; node++) {
ClientNodeDef *def = &client_node_defs[node];
if (def->visibility != VISIBILITY_NONE) {
Texture *textures[6];

View File

@ -30,9 +30,10 @@ typedef struct {
void (*render)(NodeArgsRender *args);
bool pointable;
v3f32 selection_color;
} ClientNodeDefinition;
char *name;
} ClientNodeDef;
extern ClientNodeDefinition client_node_definitions[];
extern ClientNodeDef client_node_defs[];
void client_node_init();
#endif // _CLIENT_NODE_H_

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include "client/camera.h"
#include "client/client.h"
#include "client/client_inventory.h"
#include "client/client_player.h"
#include "client/client_terrain.h"
#include "client/cube.h"
@ -10,16 +11,6 @@
#include "environment.h"
#include "physics.h"
typedef struct {
ModelNode *nametag;
ModelNode *neck;
ModelNode *eyes;
ModelNode *shoulder_left;
ModelNode *shoulder_right;
ModelNode *hip_left;
ModelNode *hip_right;
} PlayerModelBones;
struct ClientPlayer client_player;
static ClientEntity *player_entity;
@ -33,10 +24,10 @@ static void update_camera()
{
vec4 dst, src = {0.0f, 0.0f, 0.0f, 1.0f};
PlayerModelBones *bones = player_entity->extra;
ClientPlayerData *data = player_entity->extra;
if (bones->eyes)
mat4x4_mul_vec4(dst, bones->eyes->abs, src);
if (data->bones.eyes)
mat4x4_mul_vec4(dst, data->bones.eyes->abs, src);
else
vec4_dup(dst, src);
@ -88,21 +79,26 @@ static void on_add(ClientEntity *entity)
entity->model = model_clone(player_model);
entity->model->extra = refcount_grb(&entity->rc);
PlayerModelBones *bones = entity->extra = malloc(sizeof *bones);
*bones = (PlayerModelBones) {NULL};
model_get_bones(entity->model, (ModelBoneMapping[]) {
{"player.nametag", &bones->nametag },
{"player.neck", &bones->neck },
{"player.neck.head.eyes", &bones->eyes },
{"player.body.upper.shoulders.left", &bones->shoulder_left },
{"player.body.upper.shoulders.right", &bones->shoulder_right},
{"player.body.lower.hips.left", &bones->hip_left },
{"player.body.lower.hips.right", &bones->hip_right },
}, 7);
ClientPlayerData *data = entity->extra = malloc(sizeof *data);
data->bones = (struct ClientPlayerBones) {NULL};
entity->nametag_offset = bones->nametag ? &bones->nametag->abs : NULL;
model_get_bones(entity->model, (ModelBoneMapping[9]) {
{"nametag", &data->bones.nametag },
{"neck", &data->bones.neck },
{"neck.head.eyes", &data->bones.eyes },
{"arm_left", &data->bones.arm_left },
{"arm_right", &data->bones.arm_right },
{"arm_left.hand", &data->bones.hand_left },
{"arm_right.hand", &data->bones.hand_right},
{"leg_left", &data->bones.leg_left },
{"leg_right", &data->bones.leg_right },
}, 9);
entity->nametag_offset = data->bones.nametag ? &data->bones.nametag->abs : NULL;
entity->box_collision = (aabb3f32) {{-0.45f, 0.0f, -0.45f}, {0.45f, 1.8f, 0.45f}};
client_inventory_init_player(entity);
model_scene_add(entity->model);
client_entity_transform(entity);
}
@ -115,18 +111,19 @@ static void on_remove(ClientEntity *entity)
static void on_free(ClientEntity *entity)
{
client_inventory_init_player(entity);
free(entity->extra);
}
static void on_transform(ClientEntity *entity)
{
PlayerModelBones *bones = entity->extra;
ClientPlayerData *data = entity->extra;
entity->model->root->rot.x = entity->model->root->rot.z = 0.0f;
if (bones->neck) {
bones->neck->rot.x = entity->data.rot.x;
model_node_transform(bones->neck);
if (data->bones.neck) {
data->bones.neck->rot.x = entity->data.rot.x;
model_node_transform(data->bones.neck);
}
}
@ -174,8 +171,8 @@ static void local_on_update_nametag(ClientEntity *entity)
static void __attribute__((unused)) on_model_step(Model *model, __attribute__((unused)) f64 dtime)
{
PlayerModelBones *bones = ((ClientEntity *) model->extra)->extra;
(void) bones;
ClientPlayerData *data = ((ClientEntity *) model->extra)->extra;
(void) data; // ToDo: animations
}
static void on_model_delete(Model *model)
@ -241,7 +238,19 @@ void client_player_gfx_deinit()
model_delete(player_model);
}
ClientEntity *client_player_entity()
ClientEntity *client_player_entity(u64 id)
{
ClientEntity *entity = client_entity_grab(id);
if (entity->type == &client_entity_types[ENTITY_LOCALPLAYER]
|| entity->type == &client_entity_types[ENTITY_PLAYER])
return entity;
refcount_drp(&entity->rc);
return NULL;
}
ClientEntity *client_player_entity_local()
{
ClientEntity *entity = NULL;
@ -280,7 +289,7 @@ void client_player_update_rot(ClientEntity *entity)
// jump if possible
void client_player_jump()
{
ClientEntity *entity = client_player_entity();
ClientEntity *entity = client_player_entity_local();
if (!entity)
return;
@ -305,7 +314,7 @@ void client_player_jump()
// to be called every frame
void client_player_tick(f64 dtime)
{
ClientEntity *entity = client_player_entity();
ClientEntity *entity = client_player_entity_local();
if (!entity)
return;

View File

@ -11,13 +11,32 @@ extern struct ClientPlayer {
pthread_rwlock_t lock_movement;
} client_player;
typedef struct {
struct {
ItemStack left;
ItemStack right;
} inventory;
struct ClientPlayerBones {
ModelNode *nametag;
ModelNode *neck;
ModelNode *eyes;
ModelNode *arm_left;
ModelNode *arm_right;
ModelNode *hand_left;
ModelNode *hand_right;
ModelNode *leg_left;
ModelNode *leg_right;
} bones;
} ClientPlayerData;
void client_player_init(); // called on startup
void client_player_deinit(); // called on shutdown
void client_player_gfx_init();
void client_player_gfx_deinit();
ClientEntity *client_player_entity(); // grab and return client entity
ClientEntity *client_player_entity(u64 id); // grab and return client entity by id
ClientEntity *client_player_entity_local(); // grab and return local client entity
void client_player_jump(); // jump if possible

View File

@ -63,7 +63,7 @@ static void sync_step()
static size_t old_num_requests = 0;
v3f64 player_pos;
ClientEntity *entity = client_player_entity();
ClientEntity *entity = client_player_entity_local();
if (entity) {
pthread_rwlock_rdlock(&entity->lock_pos_rot);

View File

@ -6,12 +6,14 @@
#include <stdlib.h>
#include <pthread.h>
#include "client/client_config.h"
#include "client/client_node.h"
#include "client/client_player.h"
#include "client/client_terrain.h"
#include "client/debug_menu.h"
#include "client/game.h"
#include "client/gl_debug.h"
#include "client/gui.h"
#include "client/interact.h"
#include "client/window.h"
#include "day.h"
#include "environment.h"
@ -23,7 +25,7 @@ static bool changed_elements[COUNT_ENTRY] = {false};
static pthread_mutex_t changed_elements_mtx = PTHREAD_MUTEX_INITIALIZER;
static bool debug_menu_enabled = true;
static DebugMenuEntry last_always_visible = ENTRY_POS;
static DebugMenuEntry last_always_visible = ENTRY_POINTED;
static char *get_entry_text(DebugMenuEntry entry)
{
@ -33,6 +35,10 @@ static char *get_entry_text(DebugMenuEntry entry)
int minutes = 0;
v3f64 pos = {0.0f, 0.0f, 0.0f};
v3f32 rot = {0.0f, 0.0f, 0.0f};
char *pnt_name = NULL;
// shortcut
static struct InteractPointed *pnt = &interact_pointed;
switch (entry) {
case ENTRY_POS:
@ -40,7 +46,7 @@ static char *get_entry_text(DebugMenuEntry entry)
case ENTRY_PITCH:
case ENTRY_HUMIDITY:
case ENTRY_TEMPERATURE: {
ClientEntity *entity = client_player_entity();
ClientEntity *entity = client_player_entity_local();
if (!entity)
return strdup("");
@ -52,6 +58,13 @@ static char *get_entry_text(DebugMenuEntry entry)
break;
}
case ENTRY_POINTED:
if (!pnt->exists)
return strdup("");
pnt_name = client_node_defs[pnt->node].name;
break;
case ENTRY_FLIGHT:
case ENTRY_COLLISION:
pthread_rwlock_rdlock(&client_player.lock_movement);
@ -78,6 +91,7 @@ static char *get_entry_text(DebugMenuEntry entry)
case ENTRY_VERSION: asprintf(&str, "Dragonblocks Alpha %s", VERSION ); break;
case ENTRY_FPS: asprintf(&str, "%d FPS", game_fps ); break;
case ENTRY_POS: asprintf(&str, "(%.1f %.1f %.1f)", pos.x, pos.y, pos.z ); break;
case ENTRY_POINTED: asprintf(&str, "%s (%d, %d, %d)", pnt_name, pnt->pos.x, pnt->pos.y, pnt->pos.z ); break;
case ENTRY_YAW: asprintf(&str, "yaw = %.1f", 360.0 - rot.y / M_PI * 180.0 ); break;
case ENTRY_PITCH: asprintf(&str, "pitch = %.1f", -rot.x / M_PI * 180.0 ); break;
case ENTRY_TIME: asprintf(&str, "%02d:%02d", hours, minutes ); break;
@ -106,7 +120,7 @@ void debug_menu_init()
s32 offset = -16;
for (DebugMenuEntry i = 0; i < COUNT_ENTRY; i++) {
gui_elements[i] = gui_add(NULL, (GUIElementDefinition) {
gui_elements[i] = gui_add(NULL, (GUIElementDef) {
.pos = {0.0f, 0.0f},
.z_index = 0.1f,
.offset = {2, offset += 18},

View File

@ -5,6 +5,7 @@ typedef enum {
ENTRY_VERSION,
ENTRY_FPS,
ENTRY_POS,
ENTRY_POINTED,
ENTRY_YAW,
ENTRY_PITCH,
ENTRY_TIME,

View File

@ -1,13 +1,13 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <stb/stb_image_write.h>
#include <stdio.h>
#include <unistd.h>
#include "client/camera.h"
#include "client/client.h"
#include "client/client_entity.h"
#include "client/client_inventory.h"
#include "client/client_item.h"
#include "client/client_node.h"
#include "client/client_player.h"
#include "client/client_terrain.h"
@ -26,25 +26,7 @@
int game_fps = 0;
static void crosshair_init()
{
gui_add(NULL, (GUIElementDefinition) {
.pos = {0.5f, 0.5f},
.z_index = 0.0f,
.offset = {0, 0},
.margin = {0, 0},
.align = {0.5f, 0.5f},
.scale = {1.0f, 1.0f},
.scale_type = SCALE_IMAGE,
.affect_parent_scale = false,
.text = NULL,
.image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false),
.text_color = {0.0f, 0.0f, 0.0f, 0.0f},
.bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
});
}
static void render(f64 dtime)
void game_render(f64 dtime)
{
glEnable(GL_DEPTH_TEST); GL_DEBUG
glEnable(GL_BLEND); GL_DEBUG
@ -60,6 +42,7 @@ static void render(f64 dtime)
frustum_update();
terrain_gfx_update();
client_entity_gfx_update();
client_inventory_update();
sky_render();
model_scene_render(dtime);
@ -98,7 +81,7 @@ static void game_loop()
debug_menu_changed(ENTRY_SUN_ANGLE);
debug_menu_update();
render(dtime);
game_render(dtime);
glfwSwapBuffers(window.handle);
glfwPollEvents();
@ -126,23 +109,27 @@ bool game(Flag *gfx_init)
client_player_gfx_init();
camera_init();
if (!gui_init())
return false;
if (!interact_init())
return false;
client_item_init();
if (!client_inventory_init())
return false;
client_node_init();
client_terrain_start();
camera_set_position((v3f32) {0.0f, 0.0f, 0.0f});
camera_set_angle(0.0f, 0.0f);
if (!gui_init())
return false;
debug_menu_init();
crosshair_init();
input_init();
flag_set(gfx_init);
game_loop();
client_terrain_stop();
@ -155,70 +142,9 @@ bool game(Flag *gfx_init)
client_entity_gfx_deinit();
client_player_gfx_deinit();
interact_deinit();
client_item_deinit();
client_inventory_deinit();
return true;
}
char *game_take_screenshot()
{
// renderbuffer for depth & stencil buffer
GLuint rbo;
glGenRenderbuffers(1, &rbo); GL_DEBUG
glBindRenderbuffer(GL_RENDERBUFFER, rbo); GL_DEBUG
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window.width, window.height); GL_DEBUG
// 2 textures, one with AA, one without
GLuint txos[2];
glGenTextures(2, txos); GL_DEBUG
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, txos[0]); GL_DEBUG
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window.width, window.height, GL_TRUE); GL_DEBUG
glBindTexture(GL_TEXTURE_2D, txos[1]); GL_DEBUG
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window.width, window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); GL_DEBUG
// 2 framebuffers, one with AA, one without
GLuint fbos[2];
glGenFramebuffers(2, fbos); GL_DEBUG
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, txos[0], 0); GL_DEBUG
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); GL_DEBUG
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, txos[1], 0); GL_DEBUG
// render scene
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
render(0.0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DEBUG
// blit AA-buffer into no-AA buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); GL_DEBUG
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); GL_DEBUG
glBlitFramebuffer(0, 0, window.width, window.height, 0, 0, window.width, window.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_DEBUG
// read data
GLubyte data[window.width * window.height * 3];
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
glPixelStorei(GL_PACK_ALIGNMENT, 1); GL_DEBUG
glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, data); GL_DEBUG
// create filename
char filename[BUFSIZ];
time_t timep = time(0);
strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep));
// save screenshot
stbi_flip_vertically_on_write(true);
stbi_write_png(filename, window.width, window.height, 3, data, window.width * 3);
// delete buffers
glDeleteRenderbuffers(1, &rbo); GL_DEBUG
glDeleteTextures(2, txos); GL_DEBUG
glDeleteFramebuffers(2, fbos); GL_DEBUG
return strdup(filename);
}

View File

@ -2,10 +2,11 @@
#define _GAME_H_
#include <dragonstd/flag.h>
#include "types.h"
extern int game_fps;
bool game(Flag *gfx_init);
char *game_take_screenshot();
void game_render(f64 dtime);
#endif // _GAME_H_

View File

@ -327,7 +327,7 @@ void gui_render()
glEnable(GL_CULL_FACE); GL_DEBUG
}
GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def)
GUIElement *gui_add(GUIElement *parent, GUIElementDef def)
{
if (parent == NULL)
parent = &root_element;

View File

@ -29,10 +29,10 @@ typedef struct {
Texture *image;
v4f32 text_color;
v4f32 bg_color;
} GUIElementDefinition;
} GUIElementDef;
typedef struct GUIElement {
GUIElementDefinition def;
GUIElementDef def;
bool visible;
v2f32 pos;
v2f32 scale;
@ -47,7 +47,7 @@ bool gui_init();
void gui_deinit();
void gui_update_projection();
void gui_render();
GUIElement *gui_add(GUIElement *parent, GUIElementDefinition def);
GUIElement *gui_add(GUIElement *parent, GUIElementDef def);
void gui_text(GUIElement *element, const char *text);
void gui_transform(GUIElement *element);

View File

@ -6,9 +6,9 @@
#include "client/client.h"
#include "client/client_player.h"
#include "client/debug_menu.h"
#include "client/game.h"
#include "client/gui.h"
#include "client/input.h"
#include "client/screenshot.h"
#include "client/window.h"
#include "day.h"
@ -72,7 +72,7 @@ static bool key_listener(KeyListener *listener)
void input_init()
{
pause_menu = gui_add(NULL, (GUIElementDefinition) {
pause_menu = gui_add(NULL, (GUIElementDef) {
.pos = {0.0f, 0.0f},
.z_index = 0.5f,
.offset = {0, 0},
@ -87,7 +87,7 @@ void input_init()
.bg_color = {0.0f, 0.0f, 0.0f, 0.4f},
});
status_message = gui_add(NULL, (GUIElementDefinition) {
status_message = gui_add(NULL, (GUIElementDef) {
.pos = {0.5f, 0.25f},
.z_index = 0.1f,
.offset = {0, 0},
@ -165,7 +165,7 @@ void input_tick(f64 dtime)
debug_menu_toggle();
if (key_listener(&listener_screenshot)) {
char *screenshot_filename = game_take_screenshot();
char *screenshot_filename = screenshot();
SET_STATUS_MESSAGE("Screenshot saved to %s", screenshot_filename)
free(screenshot_filename);
}
@ -202,7 +202,7 @@ void input_cursor(double current_x, double current_y)
cursor_last_x = current_x;
cursor_last_y = current_y;
ClientEntity *entity = client_player_entity();
ClientEntity *entity = client_player_entity_local();
if (!entity)
return;

View File

@ -3,15 +3,17 @@
#include "client/camera.h"
#include "client/client_node.h"
#include "client/cube.h"
#include "client/debug_menu.h"
#include "client/frustum.h"
#include "client/gl_debug.h"
#include "client/gui.h"
#include "client/interact.h"
#include "client/mesh.h"
#include "client/raycast.h"
#include "client/shader.h"
static bool pointed;
static v3s32 node_pos;
struct InteractPointed interact_pointed;
static GLuint shader_prog;
static GLint loc_MVP;
static GLint loc_color;
@ -53,6 +55,21 @@ bool interact_init()
selection_mesh.data = vertices;
mesh_upload(&selection_mesh);
gui_add(NULL, (GUIElementDef) {
.pos = {0.5f, 0.5f},
.z_index = 0.0f,
.offset = {0, 0},
.margin = {0, 0},
.align = {0.5f, 0.5f},
.scale = {1.0f, 1.0f},
.scale_type = SCALE_IMAGE,
.affect_parent_scale = false,
.text = NULL,
.image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false),
.text_color = {0.0f, 0.0f, 0.0f, 0.0f},
.bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
});
return true;
}
@ -64,22 +81,27 @@ void interact_deinit()
void interact_tick()
{
v3s32 old_node_pos = node_pos;
NodeType node;
if ((pointed = raycast(
(v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]},
(v3f64) {camera.front[0], camera.front[1], camera.front[2]},
5, &node_pos, &node)) && !v3s32_equals(node_pos, old_node_pos)) {
mat4x4_translate(model, node_pos.x, node_pos.y, node_pos.z);
v3f32 *color = &client_node_definitions[node].selection_color;
bool old_exists = interact_pointed.exists;
v3s32 old_pointed = interact_pointed.pos;
if ((interact_pointed.exists = raycast(
(v3f64) {camera.eye [0], camera.eye [1], camera.eye [2]},
(v3f64) {camera.front[0], camera.front[1], camera.front[2]},
5, &interact_pointed.pos, &interact_pointed.node))
&& !v3s32_equals(interact_pointed.pos, old_pointed)) {
mat4x4_translate(model,
interact_pointed.pos.x, interact_pointed.pos.y, interact_pointed.pos.z);
v3f32 *color = &client_node_defs[interact_pointed.node].selection_color;
glProgramUniform3f(shader_prog, loc_color, color->x, color->y, color->z); GL_DEBUG
debug_menu_changed(ENTRY_POINTED);
}
if (old_exists && !interact_pointed.exists)
debug_menu_changed(ENTRY_POINTED);
}
void interact_render()
{
if (!pointed)
if (!interact_pointed.exists)
return;
mat4x4 mvp;

View File

@ -1,6 +1,12 @@
#ifndef _INTERACT_H_
#define _INTERACT_H_
extern struct InteractPointed {
bool exists;
v3s32 pos;
NodeType node;
} interact_pointed;
bool interact_init();
void interact_deinit();
void interact_tick();

View File

@ -1,8 +1,133 @@
#include <dragonstd/tree.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include "client/cube.h"
#include "client/gl_debug.h"
#include "client/mesh.h"
typedef struct {
v3s32 pos;
v3f32 color;
} LoadedVoxel;
typedef struct {
Tree voxels;
Array vertices;
} LoadedRenderArgs;
static v3s32 face_dir[6] = {
{+0, +0, -1},
{+0, +0, +1},
{-1, +0, +0},
{+1, +0, +0},
{+0, -1, +0},
{+0, +1, +0},
};
typedef struct {
v3f32 pos;
v3f32 normal;
v3f32 color;
} __attribute__((packed)) LoadedVertex;
static VertexLayout loaded_layout = {
.attributes = (VertexAttribute[]) {
{GL_FLOAT, 3, sizeof(v3f32)}, // position
{GL_FLOAT, 3, sizeof(v3f32)}, // normal
{GL_FLOAT, 3, sizeof(v3f32)}, // color
},
.count = 3,
.size = sizeof(LoadedVertex),
};
static int cmp_loaded_voxel(const LoadedVoxel *voxel, const v3s32 *pos)
{
return v3s32_cmp(&voxel->pos, pos);
}
static void render_loaded_voxel(LoadedVoxel *voxel, LoadedRenderArgs *args)
{
v3f32 pos = v3s32_to_f32(voxel->pos);
for (int f = 0; f < 6; f++) {
v3s32 neigh_pos = v3s32_add(voxel->pos, face_dir[f]);
if (tree_get(&args->voxels, &neigh_pos, &cmp_loaded_voxel, NULL))
continue;
for (int v = 0; v < 6; v++)
array_apd(&args->vertices, &(LoadedVertex) {
v3f32_add(cube_vertices[f][v].position, pos),
cube_vertices[f][v].normal,
voxel->color,
});
}
}
void mesh_load(Mesh *mesh, const char *path)
{
mesh->layout = &loaded_layout;
mesh->vao = mesh->vbo = 0;
mesh->data = NULL;
mesh->count = 0;
mesh->free_data = true;
LoadedRenderArgs args;
tree_ini(&args.voxels);
array_ini(&args.vertices, sizeof(LoadedVertex), 500);
FILE *file = fopen(path, "r");
if (!file) {
fprintf(stderr, "[warning] failed to open mesh %s\n", path);
return;
}
char *line = NULL;
size_t siz = 0;
ssize_t length;
int count = 0;
while ((length = getline(&line, &siz, file)) > 0) {
count++;
if (*line == '#')
continue;
LoadedVoxel *voxel = malloc(sizeof *voxel);
v3s32 color;
if (sscanf(line, "%d %d %d %2x%2x%2x",
&voxel->pos.x, &voxel->pos.z, &voxel->pos.y,
&color.x, &color.y, &color.z) != 6) {
fprintf(stderr, "[warning] syntax error in mesh %s in line %d: %s\n",
path, count, line);
free(voxel);
continue;
}
voxel->color = (v3f32) {
(f32) color.x / 0xFF,
(f32) color.y / 0xFF,
(f32) color.z / 0xFF,
};
if (!tree_add(&args.voxels, &voxel->pos, voxel, &cmp_loaded_voxel, NULL)) {
fprintf(stderr, "[warning] more than one voxel at position (%d, %d, %d) in mesh %s in line %d\n",
voxel->pos.x, voxel->pos.y, voxel->pos.z, path, count);
free(voxel);
}
}
if (line)
free(line);
fclose(file);
tree_trv(&args.voxels, &render_loaded_voxel, &args, NULL, 0);
tree_clr(&args.voxels, &free, NULL, NULL, 0);
mesh->data = args.vertices.ptr;
mesh->count = args.vertices.siz;
}
// upload data to GPU (only done once)
void mesh_upload(Mesh *mesh)
{

View File

@ -25,6 +25,7 @@ typedef struct {
bool free_data;
} Mesh;
void mesh_load(Mesh *mesh, const char *path);
void mesh_upload(Mesh *mesh);
void mesh_render(Mesh *mesh);
void mesh_destroy(Mesh *mesh);

View File

@ -55,9 +55,16 @@ static void render_node(ModelNode *node)
if (!node->visible)
return;
if (node->clockwise) {
glFrontFace(GL_CW); GL_DEBUG
}
for (size_t i = 0; i < node->meshes.siz; i++) {
ModelMesh *mesh = &((ModelMesh *) node->meshes.ptr)[i];
if (!mesh->mesh)
continue;
glUseProgram(mesh->shader->prog); GL_DEBUG
glUniformMatrix4fv(mesh->shader->loc_transform, 1, GL_FALSE, node->abs[0]); GL_DEBUG
@ -70,6 +77,10 @@ static void render_node(ModelNode *node)
}
list_itr(&node->children, &render_node, NULL, NULL);
if (node->clockwise) {
glFrontFace(GL_CCW); GL_DEBUG
}
}
static void free_node_meshes(ModelNode *node)
@ -276,11 +287,15 @@ Model *model_load(const char *path, const char *textures_path, Mesh *cube, Model
cursor += n;
else
fprintf(stderr, "[warning] invalid value for rot in model %s in line %d\n", path, count);
node->rot = v3f32_scale(node->rot, M_PI / 180.0);
} else if (strcmp(key, "scale") == 0) {
if (sscanf(cursor, "%f %f %f %n", &node->scale.x, &node->scale.y, &node->scale.z, &n) == 3)
cursor += n;
else
fprintf(stderr, "[warning] invalid value for scale in model %s in line %d\n", path, count);
} else if (strcmp(key, "clockwise") == 0) {
node->clockwise = 1;
} else if (strcmp(key, "cube") == 0) {
char texture[length + 1];
@ -372,7 +387,8 @@ ModelNode *model_node_create(ModelNode *parent)
{
ModelNode *node = malloc(sizeof *node);
node->name = NULL;
node->visible = true;
node->visible = 1;
node->clockwise = 0;
node->pos = (v3f32) {0.0f, 0.0f, 0.0f};
node->rot = (v3f32) {0.0f, 0.0f, 0.0f};
node->scale = (v3f32) {1.0f, 1.0f, 1.0f};

View File

@ -26,12 +26,13 @@ typedef struct {
typedef struct ModelNode {
char *name;
bool visible;
v3f32 pos, rot, scale;
mat4x4 abs, rel;
Array meshes;
struct ModelNode *parent;
List children;
unsigned int visible: 1;
unsigned int clockwise: 1;
} ModelNode;
typedef struct {

View File

@ -14,7 +14,7 @@ bool raycast(v3f64 pos, v3f64 dir, f64 len, v3s32 *node_pos, NodeType *node)
if (*node == NODE_UNLOADED)
return false;
if (client_node_definitions[*node].pointable)
if (client_node_defs[*node].pointable)
return true;
f64 vpos[3] = {pos.x, pos.y, pos.z};

73
src/client/screenshot.c Normal file
View File

@ -0,0 +1,73 @@
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <GL/glew.h>
#include <GL/gl.h>
#include <stb/stb_image_write.h>
#include <string.h>
#include <time.h>
#include "client/game.h"
#include "client/gl_debug.h"
#include "client/window.h"
char *screenshot()
{
// renderbuffer for depth & stencil buffer
GLuint rbo;
glGenRenderbuffers(1, &rbo); GL_DEBUG
glBindRenderbuffer(GL_RENDERBUFFER, rbo); GL_DEBUG
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window.width, window.height); GL_DEBUG
// 2 textures, one with AA, one without
GLuint txos[2];
glGenTextures(2, txos); GL_DEBUG
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, txos[0]); GL_DEBUG
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window.width, window.height, GL_TRUE); GL_DEBUG
glBindTexture(GL_TEXTURE_2D, txos[1]); GL_DEBUG
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window.width, window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); GL_DEBUG
// 2 framebuffers, one with AA, one without
GLuint fbos[2];
glGenFramebuffers(2, fbos); GL_DEBUG
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, txos[0], 0); GL_DEBUG
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); GL_DEBUG
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, txos[1], 0); GL_DEBUG
// render scene
glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
game_render(0.0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DEBUG
// blit AA-buffer into no-AA buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); GL_DEBUG
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); GL_DEBUG
glBlitFramebuffer(0, 0, window.width, window.height, 0, 0, window.width, window.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_DEBUG
// read data
GLubyte data[window.width * window.height * 3];
glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
glPixelStorei(GL_PACK_ALIGNMENT, 1); GL_DEBUG
glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, data); GL_DEBUG
// create filename
char filename[BUFSIZ];
time_t timep = time(0);
strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep));
// save screenshot
stbi_flip_vertically_on_write(true);
stbi_write_png(filename, window.width, window.height, 3, data, window.width * 3);
// delete buffers
glDeleteRenderbuffers(1, &rbo); GL_DEBUG
glDeleteTextures(2, txos); GL_DEBUG
glDeleteFramebuffers(2, fbos); GL_DEBUG
return strdup(filename);
}

6
src/client/screenshot.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _SCREENSHOT_H_
#define _SCREENSHOT_H_
char *screenshot();
#endif // _SCREENSHOT_H_

View File

@ -5,7 +5,7 @@
#include "client/gl_debug.h"
#include "client/shader.h"
static GLuint compile_shader(GLenum type, const char *path, const char *name, GLuint program, const char *definitions)
static GLuint compile_shader(GLenum type, const char *path, const char *name, GLuint program, const char *defs)
{
char full_path[strlen(path) + 1 + strlen(name) + 1 + 4 + 1];
sprintf(full_path, "%s/%s.glsl", path, name);
@ -53,13 +53,13 @@ static GLuint compile_shader(GLenum type, const char *path, const char *name, GL
const char *code_list[3] = {
version,
definitions,
defs,
code,
};
int size_list[3] = {
18,
strlen(definitions),
strlen(defs),
size,
};
@ -82,21 +82,21 @@ static GLuint compile_shader(GLenum type, const char *path, const char *name, GL
return id;
}
bool shader_program_create(const char *path, GLuint *idptr, const char *definitions)
bool shader_program_create(const char *path, GLuint *idptr, const char *defs)
{
GLuint id = glCreateProgram(); GL_DEBUG
if (!definitions)
definitions = "";
if (!defs)
defs = "";
GLuint vert, frag;
if (!(vert = compile_shader(GL_VERTEX_SHADER, path, "vertex", id, definitions))) {
if (!(vert = compile_shader(GL_VERTEX_SHADER, path, "vertex", id, defs))) {
glDeleteProgram(id); GL_DEBUG
return false;
}
if (!(frag = compile_shader(GL_FRAGMENT_SHADER, path, "fragment", id, definitions))) {
if (!(frag = compile_shader(GL_FRAGMENT_SHADER, path, "fragment", id, defs))) {
glDeleteShader(vert); GL_DEBUG
glDeleteProgram(id); GL_DEBUG
return false;

View File

@ -5,6 +5,6 @@
#include <GL/gl.h>
#include <stdbool.h>
bool shader_program_create(const char *path, GLuint *idptr, const char *definitions);
bool shader_program_create(const char *path, GLuint *idptr, const char *defs);
#endif // _SHADER_H_

View File

@ -59,7 +59,7 @@ static ModelShader model_shader;
static inline bool cull_face(NodeType self, NodeType nbr)
{
switch (client_node_definitions[self].visibility) {
switch (client_node_defs[self].visibility) {
case VISIBILITY_CLIP:
return false;
@ -69,7 +69,7 @@ static inline bool cull_face(NodeType self, NodeType nbr)
case VISIBILITY_SOLID:
return nbr == NODE_UNLOADED
|| client_node_definitions[nbr].visibility == VISIBILITY_SOLID;
|| client_node_defs[nbr].visibility == VISIBILITY_SOLID;
default: // impossible
break;
@ -85,7 +85,7 @@ static inline void render_node(ChunkRenderData *data, v3s32 offset)
args.node = &data->chunk->data[offset.x][offset.y][offset.z];
ClientNodeDefinition *def = &client_node_definitions[args.node->type];
ClientNodeDef *def = &client_node_defs[args.node->type];
if (def->visibility == VISIBILITY_NONE)
return;

View File

@ -2,6 +2,9 @@
#define _WINDOW_H_
#include <GLFW/glfw3.h>
#include <linmath.h/linmath.h>
#include <stdbool.h>
#include "types.h"
extern struct Window {
int width, height;

98
src/item.c Normal file
View File

@ -0,0 +1,98 @@
#include <stdlib.h>
#include "item.h"
void item_stack_initialize(ItemStack *stack)
{
stack->type = ITEM_NONE;
stack->count = 1;
stack->data = NULL;
if (item_defs[stack->type].create)
item_defs[stack->type].create(stack);
}
void item_stack_destroy(ItemStack *stack)
{
if (item_defs[stack->type].delete)
item_defs[stack->type].delete(stack);
if (stack->data) {
free(stack->data);
stack->data = NULL;
}
}
void item_stack_set(ItemStack *stack, ItemType type, u32 count, Blob buffer)
{
item_stack_destroy(stack);
stack->type = type;
stack->count = count;
stack->data = item_defs[stack->type].data_size > 0 ?
malloc(item_defs[stack->type].data_size) : NULL;
if (item_defs[stack->type].create)
item_defs[stack->type].create(stack);
if (item_defs[stack->type].deserialize)
item_defs[stack->type].deserialize(&buffer, stack->data);
}
void item_stack_serialize(ItemStack *stack, SerializedItemStack *serialized)
{
serialized->type = stack->type;
serialized->count = stack->count;
serialized->data = (Blob) {0, NULL};
if (item_defs[stack->type].serialize)
item_defs[stack->type].serialize(&serialized->data, stack->data);
}
void item_stack_deserialize(ItemStack *stack, SerializedItemStack *serialized)
{
ItemType type = serialized->type;
if (type >= COUNT_ITEM)
type = ITEM_UNKNOWN;
item_stack_set(stack, type, serialized->count, serialized->data);
}
ItemDef item_defs[COUNT_ITEM] = {
// unknown
{
.stackable = false,
.data_size = 0,
.create = NULL,
.delete = NULL,
.serialize = NULL,
.deserialize = NULL,
},
// none
{
.stackable = false,
.data_size = 0,
.create = NULL,
.delete = NULL,
.serialize = NULL,
.deserialize = NULL,
},
// pickaxe
{
.stackable = false,
.data_size = 0,
.create = NULL,
.delete = NULL,
.serialize = NULL,
.deserialize = NULL,
},
// axe
{
.stackable = false,
.data_size = 0,
.create = NULL,
.delete = NULL,
.serialize = NULL,
.deserialize = NULL,
},
};

40
src/item.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef _ITEM_H_
#define _ITEM_H_
#include <stdbool.h>
#include <stddef.h>
#include "types.h"
typedef enum {
ITEM_UNKNOWN,
ITEM_NONE,
ITEM_PICKAXE,
ITEM_AXE,
COUNT_ITEM,
} ItemType;
typedef struct {
ItemType type;
u32 count; // i know future me is going to thank me for making it big
void *data;
} ItemStack;
typedef struct {
bool stackable;
size_t data_size;
void (*create)(ItemStack *stack);
void (*delete)(ItemStack *stack);
void (*serialize)(Blob *buffer, void *data);
void (*deserialize)(Blob *buffer, void *data);
} ItemDef;
void item_stack_initialize(ItemStack *stack);
void item_stack_destroy(ItemStack *stack);
void item_stack_set(ItemStack *stack, ItemType type, u32 count, Blob buffer);
void item_stack_serialize(ItemStack *stack, SerializedItemStack *serialized);
void item_stack_deserialize(ItemStack *stack, SerializedItemStack *serialized);
extern ItemDef item_defs[];
#endif // _ITEM_H_

View File

@ -2,7 +2,7 @@
#include "terrain.h"
#include "types.h"
NodeDefinition node_definitions[NODE_UNLOADED] = {
NodeDef node_defs[NODE_UNLOADED] = {
// unknown
{
.solid = true,

View File

@ -5,8 +5,6 @@
#include <stddef.h>
#include "types.h"
#define NODE_DEFINITION(type) ((type) < NODE_UNLOADED ? &node_definitions[NODE_UNKNOWN] : &node_definitions[(type)]);
typedef enum {
NODE_UNKNOWN, // Used for unknown nodes received from server (caused by outdated clients)
NODE_AIR,
@ -36,8 +34,8 @@ typedef struct {
void (*delete)(struct TerrainNode *node);
void (*serialize)(Blob *buffer, void *data);
void (*deserialize)(Blob *buffer, void *data);
} NodeDefinition;
} NodeDef;
extern NodeDefinition node_definitions[];
extern NodeDef node_defs[];
#endif

View File

@ -20,7 +20,7 @@ static aabb3s32 round_box(aabb3f64 box)
static bool is_solid(Terrain *terrain, s32 x, s32 y, s32 z)
{
NodeType node = terrain_get_node(terrain, (v3s32) {x, y, z}).type;
return node == NODE_UNLOADED || node_definitions[node].solid;
return node == NODE_UNLOADED || node_defs[node].solid;
}
bool physics_ground(Terrain *terrain, bool collide, aabb3f32 box, v3f64 *pos, v3f64 *vel)

View File

@ -1,8 +1,9 @@
#define _GNU_SOURCE // don't worry, GNU extensions are only used when available
#include <dragonnet/addr.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include "interrupt.h"
#include "server/database.h"
#include "server/server.h"
@ -70,6 +71,8 @@ int main(int argc, char **argv)
server->on_recv_type[DRAGONNET_TYPE_ToServerPosRot ] = (void *) &on_ToServerPosRot;
server->on_recv_type[DRAGONNET_TYPE_ToServerRequestChunk] = (void *) &on_ToServerRequestChunk;
srand(time(0));
interrupt_init();
if (!database_init())
return EXIT_FAILURE;

View File

@ -27,32 +27,50 @@ static void send_entity_add(ServerPlayer *player, ServerPlayer *entity)
});
}
static void send_entity_remove(ServerPlayer *player, ServerPlayer *entity)
static void send_entity_remove(ServerPlayer *client, ServerPlayer *entity)
{
dragonnet_peer_send_ToClientEntityRemove(player->peer, &(ToClientEntityRemove) {
dragonnet_peer_send_ToClientEntityRemove(client->peer, &(ToClientEntityRemove) {
.id = entity->id,
});
}
static void send_entity_update_pos_rot(ServerPlayer *player, ServerPlayer *entity)
static void send_entity_update_pos_rot(ServerPlayer *client, ServerPlayer *entity)
{
if (player != entity)
dragonnet_peer_send_ToClientEntityUpdatePosRot(player->peer, &(ToClientEntityUpdatePosRot) {
if (client != entity)
dragonnet_peer_send_ToClientEntityUpdatePosRot(client->peer, &(ToClientEntityUpdatePosRot) {
.id = entity->id,
.pos = entity->pos,
.rot = entity->rot,
});
}
static void send_entity_add_existing(ServerPlayer *entity, ServerPlayer *player)
static void send_entity_add_existing(ServerPlayer *entity, ServerPlayer *client)
{
if (player != entity) {
if (client != entity) {
pthread_rwlock_rdlock(&entity->lock_pos);
send_entity_add(player, entity);
send_entity_add(client, entity);
pthread_rwlock_unlock(&entity->lock_pos);
}
}
static void send_player_inventory(ServerPlayer *client, ServerPlayer *player)
{
ToClientPlayerInventory pkt;
pkt.id = player->id;
item_stack_serialize(&player->inventory.left, &pkt.left);
item_stack_serialize(&player->inventory.right, &pkt.right);
dragonnet_peer_send_ToClientPlayerInventory(client->peer, &pkt);
}
static void send_player_inventory_existing(ServerPlayer *player, ServerPlayer *client)
{
if (client != player) {
pthread_rwlock_rdlock(&player->lock_inv);
send_player_inventory(client, player);
pthread_rwlock_unlock(&player->lock_inv);
}
}
// main thread
// called on server shutdown
static void player_drop(ServerPlayer *player)
@ -81,6 +99,10 @@ static void player_delete(ServerPlayer *player)
pthread_rwlock_destroy(&player->lock_pos);
item_stack_destroy(&player->inventory.left);
item_stack_destroy(&player->inventory.right);
pthread_rwlock_destroy(&player->lock_inv);
free(player);
}
@ -95,6 +117,9 @@ static void player_spawn(ServerPlayer *player)
database_create_player(player->name, player->pos, player->rot);
}
item_stack_set(&player->inventory.left, ITEM_NONE + rand() % (ITEM_AXE - ITEM_NONE + 1), 1, (Blob) {0, NULL});
item_stack_set(&player->inventory.right, ITEM_NONE + rand() % (ITEM_AXE - ITEM_NONE + 1), 1, (Blob) {0, NULL});
// since this is recv thread, we don't need lock_peer
dragonnet_peer_send_ToClientInfo(player->peer, &(ToClientInfo) {
.seed = seed,
@ -113,6 +138,9 @@ static void player_spawn(ServerPlayer *player)
server_player_iterate(&send_entity_add, player);
server_player_iterate(&send_entity_add_existing, player);
server_player_iterate(&send_player_inventory, player);
server_player_iterate(&send_player_inventory_existing, player);
}
// any thread
@ -170,6 +198,10 @@ void server_player_add(DragonnetPeer *peer)
player->rot = (v3f32) {0.0f, 0.0f, 0.0f};
pthread_rwlock_init(&player->lock_pos, NULL);
item_stack_initialize(&player->inventory.left);
item_stack_initialize(&player->inventory.right);
pthread_rwlock_init(&player->lock_inv, NULL);
printf("[access] connected %s\n", player->name);
peer->extra = refcount_grb(&player->rc);

View File

@ -5,6 +5,7 @@
#include <dragonstd/refcount.h>
#include <pthread.h>
#include <stdbool.h>
#include "item.h"
#include "types.h"
typedef struct {
@ -21,6 +22,12 @@ typedef struct {
v3f64 pos; // player position
v3f32 rot; // you wont guess what this is
pthread_rwlock_t lock_pos; // git commit crime
struct {
ItemStack left;
ItemStack right;
} inventory;
pthread_rwlock_t lock_inv;
} ServerPlayer;
void server_player_init();

View File

@ -263,7 +263,7 @@ static void generate_spawn_hut()
pos.y++;
}
if (node_definitions[node].solid)
if (node_defs[node].solid)
break;
server_terrain_gen_node(pos,

View File

@ -95,7 +95,7 @@ void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks)
node = NODE_SNOW;
if (generate_args.diff == 1) for (int i = 0; i < NUM_TREES; i++) {
TreeDef *def = &tree_definitions[i];
TreeDef *def = &tree_defs[i];
if (def->condition(&condition_args)
&& noise2d(condition_args.pos.x, condition_args.pos.z, 0, seed + def->offset) * 0.5 + 0.5 < def->probability

View File

@ -201,7 +201,7 @@ static void palm_tree(v3s32 pos, List *changed_chunks)
voxel_procedural_delete(proc);
}
TreeDef tree_definitions[NUM_TREES] = {
TreeDef tree_defs[NUM_TREES] = {
// oak
{
.spread = 64.0f,

View File

@ -30,6 +30,6 @@ typedef struct {
void (*generate)(v3s32 pos, List *changed_chunks);
} TreeDef;
extern TreeDef tree_definitions[];
extern TreeDef tree_defs[];
#endif // _TREES_H_

View File

@ -166,7 +166,7 @@ Blob terrain_serialize_chunk(TerrainChunk *chunk)
},
};
NodeDefinition *def = &node_definitions[node->type];
NodeDef *def = &node_defs[node->type];
if (def->serialize)
def->serialize(&node_data->data, node->data);
@ -242,7 +242,7 @@ TerrainNode terrain_node_create(NodeType type, Blob buffer)
if (type >= NODE_UNLOADED)
type = NODE_UNKNOWN;
NodeDefinition *def = &node_definitions[type];
NodeDef *def = &node_defs[type];
TerrainNode node;
node.type = type;
@ -259,7 +259,7 @@ TerrainNode terrain_node_create(NodeType type, Blob buffer)
void terrain_node_delete(TerrainNode node)
{
NodeDefinition *def = &node_definitions[node.type];
NodeDef *def = &node_defs[node.type];
if (def->delete)
def->delete(&node);

View File

@ -25,6 +25,11 @@ EntityData
v3f32 rot
String nametag
SerializedItemStack
u32 type
u32 count
Blob data
; server packets
pkt ToServerAuth
@ -83,3 +88,8 @@ pkt ToClientEntityUpdatePosRot
pkt ToClientEntityUpdateNametag
u64 id
String nametag
pkt ToClientPlayerInventory
u64 id
SerializedItemStack left
SerializedItemStack right