Initial Commit

This commit is contained in:
2026-02-12 11:46:06 +03:00
commit b044c8d1a5
3973 changed files with 1599881 additions and 0 deletions

24
CMakeLists.txt Normal file
View File

@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
project(engine C CXX)
if(APPLE)
enable_language(OBJC)
endif()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
if (MSVC)
# Always generate PDBs
add_compile_options(/Zi)
add_link_options(/DEBUG)
add_compile_options(/W3) # Warning level
endif()
add_subdirectory(thirdparty)
add_subdirectory(src)

View File

@@ -0,0 +1,22 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/wood1.jpg
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/walls_and_floor.png

214
data/levels/test/scene.obj Normal file
View File

@@ -0,0 +1,214 @@
# Blender 4.0.2
# www.blender.org
mtllib scene.mtl
o Plane
v -3.872431 0.000000 -3.872431
v -3.872431 0.000000 3.872431
v 3.872431 0.000000 3.872431
v 3.872431 0.000000 -3.872431
v -3.872431 3.000000 -3.872431
v -3.872431 3.000000 3.872431
v 3.872431 3.000000 3.872431
v 3.872431 3.000000 -3.872431
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vt 0.688091 0.518615
vt 0.218399 0.988307
vt 0.218399 0.518615
vt 0.008503 0.062780
vt 0.715890 0.336789
vt 0.715890 0.062780
vt 0.008503 0.336789
vt 0.688091 0.988307
s 0
usemtl Material.002
f 3/1/1 1/2/1 2/3/1
f 2/4/2 7/5/2 3/6/2
f 4/6/3 5/7/3 1/4/3
f 3/4/4 8/5/4 4/6/4
f 1/6/5 6/7/5 2/4/5
f 3/1/1 4/8/1 1/2/1
f 2/4/2 6/7/2 7/5/2
f 4/6/3 8/5/3 5/7/3
f 3/4/4 7/7/4 8/5/4
f 1/6/5 5/5/5 6/7/5
o Cube
v -1.000000 1.084691 1.000000
v -1.000000 0.915309 1.000000
v -1.000000 1.084691 -1.000000
v -1.000000 0.915309 -1.000000
v 1.000000 1.084691 1.000000
v 1.000000 0.915309 1.000000
v 1.000000 1.084691 -1.000000
v 1.000000 0.915309 -1.000000
v 0.723372 -0.019617 -0.721264
v 0.667966 0.931702 -0.665858
v 0.723372 -0.019617 -0.826672
v 0.667966 0.931702 -0.882078
v 0.828780 -0.019617 -0.721264
v 0.884186 0.931702 -0.665858
v 0.828780 -0.019617 -0.826672
v 0.884186 0.931702 -0.882078
v 0.723372 -0.019617 0.881694
v 0.667966 0.931702 0.937100
v 0.723372 -0.019617 0.776286
v 0.667966 0.931702 0.720881
v 0.828780 -0.019617 0.881694
v 0.884186 0.931702 0.937100
v 0.828780 -0.019617 0.776286
v 0.884186 0.931702 0.720881
v -0.766023 -0.019617 0.881694
v -0.821429 0.931702 0.937100
v -0.766023 -0.019617 0.776286
v -0.821429 0.931702 0.720881
v -0.660615 -0.019617 0.881694
v -0.605209 0.931702 0.937100
v -0.660615 -0.019617 0.776286
v -0.605209 0.931702 0.720881
v -0.766023 -0.019617 -0.715648
v -0.821429 0.931702 -0.660242
v -0.766023 -0.019617 -0.821056
v -0.821429 0.931702 -0.876462
v -0.660615 -0.019617 -0.715648
v -0.605209 0.931702 -0.660242
v -0.660615 -0.019617 -0.821056
v -0.605209 0.931702 -0.876462
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 -0.9983
vn 0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 0.9983
vt -0.936570 1.015405
vt 2.004606 1.264496
vt -0.936570 1.264496
vt -1.007504 1.015405
vt 1.933672 1.264496
vt -1.007504 1.264496
vt 2.004606 1.015405
vt 1.933672 1.015405
vt 1.933672 2.004606
vt -1.007504 -0.936570
vt -1.007504 2.004606
vt 1.933672 -0.936570
vt 1.513221 1.039511
vt 1.749712 -0.359487
vt 1.594700 -0.359487
vt 1.526866 -0.359487
vt 1.763357 1.039511
vt 1.681878 -0.359487
vt 1.831191 1.039511
vt 1.445387 1.039511
vt 1.681878 1.749712
vt 1.526866 1.594700
vt 1.526866 1.749712
vt 1.445387 1.831191
vt 1.763357 1.513221
vt 1.763357 1.831191
vt -0.844071 1.039511
vt -0.607580 -0.359487
vt -0.762591 -0.359487
vt -0.526101 1.039511
vt 1.681878 -0.607580
vt 1.526866 -0.762591
vt 1.526866 -0.607580
vt 1.445387 -0.526101
vt 1.763357 -0.844071
vt 1.763357 -0.526101
vt -0.663420 -0.359487
vt -0.426929 1.039511
vt -0.508408 -0.359487
vt -0.508408 -0.607580
vt -0.663420 -0.762591
vt -0.663420 -0.607580
vt -0.744899 -0.526101
vt -0.426929 -0.844071
vt -0.426929 -0.526101
vt 1.504962 1.039511
vt 1.741453 -0.359487
vt 1.586442 -0.359487
vt 1.822933 1.039511
vt -0.744899 1.039511
vt -0.508408 1.741453
vt -0.663420 1.586442
vt -0.663420 1.741453
vt -0.744899 1.822933
vt -0.426929 1.504962
vt -0.426929 1.822933
vt 1.681878 1.594700
vt 1.445387 1.513221
vt 1.681878 -0.762591
vt 1.445387 -0.844071
vt -0.508408 -0.762591
vt -0.744899 -0.844071
vt -0.508408 1.586442
vt -0.744899 1.504962
s 0
usemtl Material.001
f 10/9/6 11/10/6 9/11/6
f 12/12/7 15/13/7 11/14/7
f 16/15/8 13/11/8 15/10/8
f 14/16/9 9/14/9 13/13/9
f 15/17/10 9/18/10 11/19/10
f 12/19/11 14/20/11 16/17/11
f 18/21/12 19/22/12 17/23/12
f 19/24/13 24/25/13 23/26/13
f 24/27/14 21/23/14 23/22/14
f 21/26/15 18/28/15 17/24/15
f 23/29/10 17/30/10 19/31/10
f 20/32/11 22/33/11 24/34/11
f 26/35/12 27/36/12 25/37/12
f 27/24/13 32/25/13 31/26/13
f 32/38/14 29/37/14 31/36/14
f 30/25/15 25/24/15 29/26/15
f 31/39/10 25/40/10 27/41/10
f 28/42/11 30/43/11 32/44/11
f 34/35/12 35/36/12 33/37/12
f 35/45/13 40/46/13 39/47/13
f 40/38/14 37/37/14 39/36/14
f 38/46/15 33/45/15 37/47/15
f 39/48/10 33/49/10 35/50/10
f 36/51/11 38/52/11 40/53/11
f 42/54/12 43/55/12 41/56/12
f 43/45/13 48/46/13 47/47/13
f 48/57/14 45/56/14 47/55/14
f 45/47/15 42/58/15 41/45/15
f 47/59/10 41/60/10 43/61/10
f 44/62/11 46/63/11 48/64/11
f 10/9/6 12/15/6 11/10/6
f 12/12/7 16/16/7 15/13/7
f 16/15/8 14/9/8 13/11/8
f 14/16/9 10/12/9 9/14/9
f 15/17/10 13/20/10 9/18/10
f 12/19/11 10/18/11 14/20/11
f 18/21/12 20/27/12 19/22/12
f 19/24/13 20/28/13 24/25/13
f 24/27/14 22/21/14 21/23/14
f 21/26/15 22/25/15 18/28/15
f 23/29/10 21/65/10 17/30/10
f 20/32/11 18/66/11 22/33/11
f 26/35/12 28/38/12 27/36/12
f 27/24/13 28/28/13 32/25/13
f 32/38/14 30/35/14 29/37/14
f 30/25/15 26/28/15 25/24/15
f 31/39/10 29/67/10 25/40/10
f 28/42/11 26/68/11 30/43/11
f 34/35/12 36/38/12 35/36/12
f 35/45/13 36/58/13 40/46/13
f 40/38/14 38/35/14 37/37/14
f 38/46/15 34/58/15 33/45/15
f 39/48/10 37/69/10 33/49/10
f 36/51/11 34/70/11 38/52/11
f 42/54/12 44/57/12 43/55/12
f 43/45/13 44/58/13 48/46/13
f 48/57/14 46/54/14 45/56/14
f 45/47/15 46/46/15 42/58/15
f 47/59/10 45/71/10 41/60/10
f 44/62/11 42/72/11 46/63/11

10
data/levels/test/test.xml Normal file
View File

@@ -0,0 +1,10 @@
<LevelDescription>
<SceneFile filename="scene.obj"/>
<Skybox name="skybox/sky_01.dae"/>
</LevelDescription>
<Entities>
<Entity classname="TempPlayer">
<IsDisableled value="false" />
</Entity>
</Entities>

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/figures_color.png

View File

@@ -0,0 +1,36 @@
# Blender 4.0.2
# www.blender.org
mtllib figure_box.mtl
o Cube
v -0.150000 -0.150000 0.150000
v -0.150000 0.150000 0.150000
v -0.150000 -0.150000 -0.150000
v -0.150000 0.150000 -0.150000
v 0.150000 -0.150000 0.150000
v 0.150000 0.150000 0.150000
v 0.150000 -0.150000 -0.150000
v 0.150000 0.150000 -0.150000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.256265 0.989829
vt 0.392173 0.853921
vt 0.256265 0.853921
vt 0.392173 0.989829
s 0
usemtl Material.002
f 2/1/1 3/2/1 1/3/1
f 4/1/2 7/2/2 3/3/2
f 8/4/3 5/3/3 7/2/3
f 6/4/4 1/3/4 5/2/4
f 7/4/5 1/3/5 3/1/5
f 4/1/6 6/2/6 8/4/6
f 2/1/1 4/4/1 3/2/1
f 4/1/2 8/4/2 7/2/2
f 8/4/3 6/1/3 5/3/3
f 6/4/4 2/1/4 1/3/4
f 7/4/5 5/2/5 1/3/5
f 4/1/6 2/3/6 6/2/6

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/figures_color.png

176
data/models/figure_cone.obj Normal file
View File

@@ -0,0 +1,176 @@
# Blender 4.0.2
# www.blender.org
mtllib figure_cone.mtl
o Cone
v 0.000000 -0.200000 -0.200000
v 0.039018 -0.200000 -0.196157
v 0.076537 -0.200000 -0.184776
v 0.111114 -0.200000 -0.166294
v 0.141421 -0.200000 -0.141421
v 0.166294 -0.200000 -0.111114
v 0.184776 -0.200000 -0.076537
v 0.196157 -0.200000 -0.039018
v 0.200000 -0.200000 0.000000
v 0.196157 -0.200000 0.039018
v 0.184776 -0.200000 0.076537
v 0.166294 -0.200000 0.111114
v 0.141421 -0.200000 0.141421
v 0.111114 -0.200000 0.166294
v 0.076537 -0.200000 0.184776
v 0.039018 -0.200000 0.196157
v 0.000000 -0.200000 0.200000
v -0.039018 -0.200000 0.196157
v -0.076537 -0.200000 0.184776
v -0.111114 -0.200000 0.166294
v -0.141421 -0.200000 0.141421
v -0.166294 -0.200000 0.111114
v -0.184776 -0.200000 0.076537
v -0.196157 -0.200000 0.039018
v -0.200000 -0.200000 0.000000
v -0.196157 -0.200000 -0.039018
v -0.184776 -0.200000 -0.076537
v -0.166294 -0.200000 -0.111114
v -0.141421 -0.200000 -0.141421
v -0.111114 -0.200000 -0.166294
v -0.076537 -0.200000 -0.184776
v -0.039018 -0.200000 -0.196157
v 0.000000 0.200000 0.000000
vn -0.0000 -0.5033 -0.8641
vn -0.0000 1.0000 -0.0000
vn 0.1686 -0.5033 -0.8475
vn 0.3307 -0.5033 -0.7983
vn 0.4801 -0.5033 -0.7185
vn 0.6110 -0.5033 -0.6110
vn 0.7185 -0.5033 -0.4801
vn 0.7983 -0.5033 -0.3307
vn 0.8475 -0.5033 -0.1686
vn 0.8641 -0.5033 -0.0000
vn 0.8475 -0.5033 0.1686
vn 0.7983 -0.5033 0.3307
vn 0.7185 -0.5033 0.4801
vn 0.6110 -0.5033 0.6110
vn 0.4801 -0.5033 0.7185
vn 0.3307 -0.5033 0.7983
vn 0.1686 -0.5033 0.8475
vn -0.0000 -0.5033 0.8641
vn -0.1686 -0.5033 0.8475
vn -0.3307 -0.5033 0.7983
vn -0.4801 -0.5033 0.7185
vn -0.6110 -0.5033 0.6110
vn -0.7185 -0.5033 0.4801
vn -0.7983 -0.5033 0.3307
vn -0.8475 -0.5033 0.1686
vn -0.8641 -0.5033 -0.0000
vn -0.8475 -0.5033 -0.1686
vn -0.7983 -0.5033 -0.3307
vn -0.7185 -0.5033 -0.4801
vn -0.6110 -0.5033 -0.6110
vn -0.4801 -0.5033 -0.7185
vn -0.3307 -0.5033 -0.7983
vn -0.1686 -0.5033 -0.8475
vt 0.699342 0.426213
vt 0.699342 0.580691
vt 0.714410 0.426213
vt 0.728900 0.426213
vt 0.742253 0.426213
vt 0.753958 0.426213
vt 0.684273 0.426213
vt 0.669784 0.426213
vt 0.656430 0.426213
vt 0.644726 0.426213
vt 0.714410 0.400391
vt 0.623587 0.461077
vt 0.684273 0.551900
vt 0.699342 0.553384
vt 0.714410 0.551900
vt 0.728900 0.547505
vt 0.742253 0.540367
vt 0.753958 0.530762
vt 0.763564 0.519057
vt 0.770701 0.505704
vt 0.775096 0.491214
vt 0.776581 0.476145
vt 0.775096 0.461077
vt 0.770701 0.446587
vt 0.763564 0.433234
vt 0.753958 0.421529
vt 0.742253 0.411924
vt 0.728900 0.404786
vt 0.699342 0.398907
vt 0.684273 0.400391
vt 0.669784 0.404786
vt 0.656430 0.411924
vt 0.644726 0.421529
vt 0.635120 0.433234
vt 0.627982 0.446587
vt 0.622103 0.476145
vt 0.623587 0.491214
vt 0.627982 0.505704
vt 0.635120 0.519057
vt 0.644726 0.530762
vt 0.656430 0.540367
vt 0.669784 0.547505
s 1
usemtl Material.001
f 1/1/1 33/2/2 2/3/3
f 2/3/3 33/2/2 3/4/4
f 3/4/4 33/2/2 4/5/5
f 4/5/5 33/2/2 5/6/6
f 5/6/6 33/2/2 6/5/7
f 6/5/7 33/2/2 7/4/8
f 7/4/8 33/2/2 8/3/9
f 8/3/9 33/2/2 9/1/10
f 9/1/10 33/2/2 10/7/11
f 10/7/11 33/2/2 11/8/12
f 11/8/12 33/2/2 12/9/13
f 12/9/13 33/2/2 13/10/14
f 13/6/14 33/2/2 14/5/15
f 14/5/15 33/2/2 15/4/16
f 15/4/16 33/2/2 16/3/17
f 16/3/17 33/2/2 17/1/18
f 17/1/18 33/2/2 18/7/19
f 18/7/19 33/2/2 19/8/20
f 19/8/20 33/2/2 20/9/21
f 20/9/21 33/2/2 21/10/22
f 21/10/22 33/2/2 22/9/23
f 22/9/23 33/2/2 23/8/24
f 23/8/24 33/2/2 24/7/25
f 24/7/25 33/2/2 25/1/26
f 25/1/26 33/2/2 26/3/27
f 26/3/27 33/2/2 27/4/28
f 27/4/28 33/2/2 28/5/29
f 28/5/29 33/2/2 29/6/30
f 29/10/30 33/2/2 30/9/31
f 30/9/31 33/2/2 31/8/32
f 16/11/17 24/12/25 32/13/33
f 31/8/32 33/2/2 32/7/33
f 32/7/33 33/2/2 1/1/1
f 32/13/33 1/14/1 2/15/3
f 2/15/3 3/16/4 4/17/5
f 4/17/5 5/18/6 6/19/7
f 6/19/7 7/20/8 8/21/9
f 8/21/9 9/22/10 10/23/11
f 10/23/11 11/24/12 12/25/13
f 12/25/13 13/26/14 14/27/15
f 14/27/15 15/28/16 16/11/17
f 16/11/17 17/29/18 18/30/19
f 18/30/19 19/31/20 20/32/21
f 20/32/21 21/33/22 22/34/23
f 22/34/23 23/35/24 24/12/25
f 24/12/25 25/36/26 26/37/27
f 26/37/27 27/38/28 28/39/29
f 28/39/29 29/40/30 30/41/31
f 30/41/31 31/42/32 32/13/33
f 32/13/33 2/15/3 4/17/5
f 4/17/5 6/19/7 8/21/9
f 8/21/9 10/23/11 12/25/13
f 12/25/13 14/27/15 16/11/17
f 16/11/17 18/30/19 20/32/21
f 20/32/21 22/34/23 24/12/25
f 24/12/25 26/37/27 28/39/29
f 28/39/29 30/41/31 32/13/33
f 32/13/33 4/17/5 8/21/9
f 8/21/9 12/25/13 16/11/17
f 16/11/17 20/32/21 24/12/25
f 24/12/25 28/39/29 32/13/33
f 32/13/33 8/21/9 16/11/17

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.004
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/figures_color.png

View File

@@ -0,0 +1,100 @@
# Blender 4.0.2
# www.blender.org
mtllib figure_cyliner.mtl
o Cylinder
v 0.000000 -0.150000 -0.100000
v 0.000000 0.150000 -0.100000
v 0.070711 -0.150000 -0.070711
v 0.070711 0.150000 -0.070711
v 0.100000 -0.150000 0.000000
v 0.100000 0.150000 0.000000
v 0.070711 -0.150000 0.070711
v 0.070711 0.150000 0.070711
v 0.000000 -0.150000 0.100000
v 0.000000 0.150000 0.100000
v -0.070711 -0.150000 0.070711
v -0.070711 0.150000 0.070711
v -0.100000 -0.150000 0.000000
v -0.100000 0.150000 0.000000
v -0.070711 -0.150000 -0.070711
v -0.070711 0.150000 -0.070711
vn -0.0000 0.6303 -0.7764
vn 0.5490 -0.6303 -0.5490
vn -0.0000 -0.6303 -0.7764
vn 0.5490 0.6303 -0.5490
vn 0.7764 -0.6303 -0.0000
vn 0.7764 0.6303 -0.0000
vn 0.5490 -0.6303 0.5490
vn 0.5490 0.6303 0.5490
vn -0.0000 -0.6303 0.7764
vn -0.0000 0.6303 0.7764
vn -0.5490 -0.6303 0.5490
vn -0.5490 0.6303 0.5490
vn -0.7764 -0.6303 -0.0000
vn -0.7764 0.6303 -0.0000
vn -0.5490 -0.6303 -0.5490
vn -0.5490 0.6303 -0.5490
vt 0.185036 0.967496
vt 0.162401 0.876954
vt 0.185036 0.876954
vt 0.162401 0.967496
vt 0.139765 0.876954
vt 0.139765 0.967496
vt 0.117130 0.876954
vt 0.117130 0.967496
vt 0.094494 0.876954
vt 0.094494 0.967496
vt 0.071859 0.876954
vt 0.071859 0.967496
vt 0.049223 0.876954
vt 0.005763 0.831683
vt 0.049223 0.788223
vt 0.092684 0.831683
vt 0.049223 0.967496
vt 0.026588 0.876954
vt 0.026588 0.967496
vt 0.003953 0.876954
vt 0.170496 0.800952
vt 0.109034 0.800952
vt 0.109034 0.862414
vt 0.079954 0.862414
vt 0.049223 0.875143
vt 0.018493 0.862414
vt 0.018493 0.800952
vt 0.079954 0.800952
vt 0.003953 0.967496
vt 0.139765 0.875143
vt 0.170496 0.862414
vt 0.183225 0.831683
vt 0.139765 0.788223
vt 0.096305 0.831683
s 1
usemtl Material.004
f 2/1/1 3/2/2 1/3/3
f 4/4/4 5/5/5 3/2/2
f 6/6/6 7/7/7 5/5/5
f 8/8/8 9/9/9 7/7/7
f 10/10/10 11/11/11 9/9/9
f 12/12/12 13/13/13 11/11/11
f 14/14/14 10/15/10 6/16/6
f 14/17/14 15/18/15 13/13/13
f 16/19/16 1/20/3 15/18/15
f 7/21/7 11/22/11 15/23/15
f 2/1/1 4/4/4 3/2/2
f 4/4/4 6/6/6 5/5/5
f 6/6/6 8/8/8 7/7/7
f 8/8/8 10/10/10 9/9/9
f 10/10/10 12/12/12 11/11/11
f 12/12/12 14/17/14 13/13/13
f 6/16/6 4/24/4 2/25/1
f 2/25/1 16/26/16 14/14/14
f 14/14/14 12/27/12 10/15/10
f 10/15/10 8/28/8 6/16/6
f 6/16/6 2/25/1 14/14/14
f 14/17/14 16/19/16 15/18/15
f 16/19/16 2/29/1 1/20/3
f 15/23/15 1/30/3 3/31/2
f 3/31/2 5/32/5 7/21/7
f 7/21/7 9/33/9 11/22/11
f 11/22/11 13/34/13 15/23/15
f 15/23/15 3/31/2 7/21/7

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.003
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/figures_color.png

View File

@@ -0,0 +1,743 @@
# Blender 4.0.2
# www.blender.org
mtllib figure_sphere.mtl
o Sphere
v 0.000000 -0.289778 -0.077646
v -0.000000 -0.259808 -0.150000
v 0.000000 -0.212132 -0.212132
v -0.000000 -0.150000 -0.259808
v 0.000000 -0.077646 -0.289778
v -0.000000 0.000000 -0.300000
v 0.000000 0.077646 -0.289778
v -0.000000 0.150000 -0.259808
v 0.000000 0.212132 -0.212132
v -0.000000 0.259808 -0.150000
v 0.000000 0.289778 -0.077646
v 0.000000 0.300000 0.000000
v -0.036084 -0.289778 -0.068752
v -0.069708 -0.259808 -0.132818
v -0.098583 -0.212132 -0.187834
v -0.120739 -0.150000 -0.230048
v -0.134666 -0.077646 -0.256585
v -0.139417 0.000000 -0.265637
v -0.134666 0.077646 -0.256585
v -0.120739 0.150000 -0.230048
v -0.098583 0.212132 -0.187834
v -0.069708 0.259808 -0.132818
v -0.036084 0.289778 -0.068752
v -0.063901 -0.289778 -0.044108
v -0.123448 -0.259808 -0.085210
v -0.174581 -0.212132 -0.120505
v -0.213818 -0.150000 -0.147588
v -0.238482 -0.077646 -0.164613
v -0.246895 0.000000 -0.170419
v -0.238482 0.077646 -0.164613
v -0.213818 0.150000 -0.147588
v -0.174581 0.212132 -0.120505
v -0.123448 0.259808 -0.085210
v -0.063901 0.289778 -0.044108
v -0.077080 -0.289778 -0.009359
v -0.148906 -0.259808 -0.018080
v -0.210585 -0.212132 -0.025570
v -0.257913 -0.150000 -0.031316
v -0.287665 -0.077646 -0.034929
v -0.297813 0.000000 -0.036161
v -0.287665 0.077646 -0.034929
v -0.257913 0.150000 -0.031316
v -0.210585 0.212132 -0.025570
v -0.148906 0.259808 -0.018080
v -0.077080 0.289778 -0.009359
v -0.072600 -0.289778 0.027534
v -0.140252 -0.259808 0.053191
v -0.198347 -0.212132 0.075223
v -0.242924 -0.150000 0.092129
v -0.270947 -0.077646 0.102757
v -0.280505 0.000000 0.106381
v -0.270947 0.077646 0.102757
v -0.242924 0.150000 0.092129
v -0.198347 0.212132 0.075223
v -0.140252 0.259808 0.053191
v -0.072600 0.289778 0.027534
v 0.000000 -0.300000 0.000000
v -0.051489 -0.289778 0.058119
v -0.099468 -0.259808 0.112277
v -0.140670 -0.212132 0.158783
v -0.172284 -0.150000 0.194469
v -0.192158 -0.077646 0.216902
v -0.198937 0.000000 0.224553
v -0.192158 0.077646 0.216902
v -0.172284 0.150000 0.194469
v -0.140670 0.212132 0.158783
v -0.099468 0.259808 0.112277
v -0.051489 0.289778 0.058119
v -0.018582 -0.289778 0.075389
v -0.035897 -0.259808 0.145641
v -0.050767 -0.212132 0.205968
v -0.062176 -0.150000 0.252258
v -0.069348 -0.077646 0.281357
v -0.071795 0.000000 0.291283
v -0.069348 0.077646 0.281357
v -0.062176 0.150000 0.252258
v -0.050767 0.212132 0.205968
v -0.035897 0.259808 0.145641
v -0.018582 0.289778 0.075389
v 0.018582 -0.289778 0.075389
v 0.035897 -0.259808 0.145641
v 0.050767 -0.212132 0.205968
v 0.062176 -0.150000 0.252258
v 0.069348 -0.077646 0.281357
v 0.071795 0.000000 0.291283
v 0.069348 0.077646 0.281357
v 0.062176 0.150000 0.252258
v 0.050767 0.212132 0.205968
v 0.035897 0.259808 0.145641
v 0.018582 0.289778 0.075389
v 0.051489 -0.289778 0.058119
v 0.099468 -0.259808 0.112277
v 0.140670 -0.212132 0.158783
v 0.172284 -0.150000 0.194469
v 0.192158 -0.077646 0.216902
v 0.198937 0.000000 0.224553
v 0.192158 0.077646 0.216902
v 0.172284 0.150000 0.194469
v 0.140670 0.212132 0.158783
v 0.099468 0.259808 0.112277
v 0.051489 0.289778 0.058119
v 0.072600 -0.289778 0.027534
v 0.140252 -0.259808 0.053191
v 0.198347 -0.212132 0.075223
v 0.242924 -0.150000 0.092129
v 0.270947 -0.077646 0.102757
v 0.280505 0.000000 0.106381
v 0.270947 0.077646 0.102757
v 0.242924 0.150000 0.092129
v 0.198347 0.212132 0.075223
v 0.140252 0.259808 0.053191
v 0.072600 0.289778 0.027534
v 0.077080 -0.289778 -0.009359
v 0.148906 -0.259808 -0.018081
v 0.210585 -0.212132 -0.025570
v 0.257913 -0.150000 -0.031316
v 0.287665 -0.077646 -0.034929
v 0.297813 0.000000 -0.036161
v 0.287665 0.077646 -0.034929
v 0.257913 0.150000 -0.031316
v 0.210585 0.212132 -0.025570
v 0.148906 0.259808 -0.018081
v 0.077080 0.289778 -0.009359
v 0.063901 -0.289778 -0.044108
v 0.123448 -0.259808 -0.085210
v 0.174581 -0.212132 -0.120505
v 0.213817 -0.150000 -0.147588
v 0.238482 -0.077646 -0.164613
v 0.246895 0.000000 -0.170419
v 0.238482 0.077646 -0.164613
v 0.213817 0.150000 -0.147588
v 0.174581 0.212132 -0.120505
v 0.123448 0.259808 -0.085210
v 0.063901 0.289778 -0.044108
v 0.036084 -0.289778 -0.068752
v 0.069708 -0.259808 -0.132818
v 0.098583 -0.212132 -0.187834
v 0.120739 -0.150000 -0.230048
v 0.134666 -0.077646 -0.256585
v 0.139417 0.000000 -0.265637
v 0.134666 0.077646 -0.256585
v 0.120739 0.150000 -0.230048
v 0.098583 0.212132 -0.187834
v 0.069708 0.259808 -0.132818
v 0.036084 0.289778 -0.068752
vn -0.1289 0.9608 -0.2456
vn -0.0000 0.8574 -0.5147
vn -0.2392 0.8574 -0.4558
vn -0.0000 -1.0000 -0.0000
vn -0.1289 -0.9608 -0.2456
vn -0.0000 -0.9608 -0.2773
vn -0.4495 0.2540 -0.8564
vn -0.0000 0.4916 -0.8708
vn -0.0000 0.2540 -0.9672
vn -0.4495 -0.2540 -0.8564
vn -0.0000 -0.4916 -0.8708
vn -0.4047 -0.4916 -0.7711
vn -0.0000 1.0000 -0.0000
vn -0.0000 0.9608 -0.2773
vn -0.2392 -0.8574 -0.4558
vn -0.3331 0.6973 -0.6347
vn -0.4047 0.4916 -0.7711
vn -0.4647 -0.0000 -0.8855
vn -0.0000 -0.2540 -0.9672
vn -0.3331 -0.6973 -0.6347
vn -0.0000 -0.8574 -0.5147
vn -0.0000 0.6973 -0.7168
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -0.6973 -0.7168
vn -0.5899 -0.6973 -0.4072
vn -0.4236 -0.8574 -0.2924
vn -0.4236 0.8574 -0.2924
vn -0.5899 0.6973 -0.4072
vn -0.7960 0.2540 -0.5494
vn -0.8230 -0.0000 -0.5681
vn -0.2283 0.9608 -0.1575
vn -0.2283 -0.9608 -0.1575
vn -0.7960 -0.2540 -0.5494
vn -0.7167 -0.4916 -0.4947
vn -0.7167 0.4916 -0.4947
vn -0.2753 0.9608 -0.0334
vn -0.2753 -0.9608 -0.0334
vn -0.7116 0.6973 -0.0864
vn -0.8645 0.4916 -0.1050
vn -0.9602 -0.2540 -0.1166
vn -0.7116 -0.6973 -0.0864
vn -0.5110 -0.8574 -0.0620
vn -0.9602 0.2540 -0.1166
vn -0.9927 -0.0000 -0.1205
vn -0.5110 0.8574 -0.0620
vn -0.8645 -0.4916 -0.1050
vn -0.6702 -0.6973 0.2542
vn -0.2593 0.9608 0.0983
vn -0.4813 0.8574 0.1825
vn -0.2593 -0.9608 0.0983
vn -0.9044 0.2540 0.3430
vn -0.9044 -0.2540 0.3430
vn -0.8143 -0.4916 0.3088
vn -0.4813 -0.8574 0.1825
vn -0.6702 0.6973 0.2542
vn -0.8143 0.4916 0.3088
vn -0.9350 -0.0000 0.3546
vn -0.4753 -0.6973 0.5366
vn -0.3413 -0.8574 0.3853
vn -0.4753 0.6973 0.5366
vn -0.6414 0.2540 0.7240
vn -0.6631 -0.0000 0.7485
vn -0.1839 0.9608 0.2076
vn -0.3413 0.8574 0.3853
vn -0.1839 -0.9608 0.2076
vn -0.6414 -0.2540 0.7240
vn -0.5775 -0.4916 0.6518
vn -0.5775 0.4916 0.6518
vn -0.2315 -0.2540 0.9391
vn -0.2084 -0.4916 0.8455
vn -0.0664 0.9608 0.2693
vn -0.1232 -0.8574 0.4998
vn -0.0664 -0.9608 0.2693
vn -0.1715 0.6973 0.6960
vn -0.2084 0.4916 0.8455
vn -0.1715 -0.6973 0.6960
vn -0.2315 0.2540 0.9391
vn -0.2393 -0.0000 0.9709
vn -0.1232 0.8574 0.4998
vn 0.1715 -0.6973 0.6960
vn 0.0664 0.9608 0.2693
vn 0.1232 0.8574 0.4998
vn 0.0664 -0.9608 0.2693
vn 0.2315 0.2540 0.9391
vn 0.2315 -0.2540 0.9391
vn 0.2084 -0.4916 0.8455
vn 0.1232 -0.8574 0.4998
vn 0.1715 0.6973 0.6960
vn 0.2084 0.4916 0.8455
vn 0.2393 -0.0000 0.9709
vn 0.6414 -0.2540 0.7240
vn 0.4753 -0.6973 0.5366
vn 0.3413 -0.8574 0.3853
vn 0.4753 0.6973 0.5366
vn 0.6631 -0.0000 0.7485
vn 0.1839 0.9608 0.2076
vn 0.3413 0.8574 0.3853
vn 0.1839 -0.9608 0.2076
vn 0.6414 0.2540 0.7240
vn 0.5775 -0.4916 0.6518
vn 0.5775 0.4916 0.6518
vn 0.9044 -0.2540 0.3430
vn 0.8143 -0.4916 0.3088
vn 0.2593 0.9608 0.0983
vn 0.4813 -0.8574 0.1825
vn 0.2593 -0.9608 0.0983
vn 0.6702 0.6973 0.2542
vn 0.8143 0.4916 0.3088
vn 0.9350 -0.0000 0.3546
vn 0.6702 -0.6973 0.2542
vn 0.4813 0.8574 0.1825
vn 0.9044 0.2540 0.3430
vn 0.9602 0.2540 -0.1166
vn 0.9927 -0.0000 -0.1205
vn 0.8645 -0.4916 -0.1050
vn 0.7116 -0.6973 -0.0864
vn 0.2753 0.9608 -0.0334
vn 0.5110 0.8574 -0.0620
vn 0.2753 -0.9608 -0.0334
vn 0.9602 -0.2540 -0.1166
vn 0.7116 0.6973 -0.0864
vn 0.8645 0.4916 -0.1050
vn 0.5110 -0.8574 -0.0620
vn 0.7960 -0.2540 -0.5494
vn 0.5899 -0.6973 -0.4072
vn 0.4236 -0.8574 -0.2924
vn 0.5899 0.6973 -0.4072
vn 0.7960 0.2540 -0.5494
vn 0.8230 -0.0000 -0.5681
vn 0.7167 -0.4916 -0.4947
vn 0.4236 0.8574 -0.2924
vn 0.2283 -0.9608 -0.1575
vn 0.2283 0.9608 -0.1575
vn 0.7167 0.4916 -0.4947
vn 0.4495 0.2540 -0.8564
vn 0.4495 -0.2540 -0.8564
vn 0.4047 -0.4916 -0.7711
vn 0.1289 0.9608 -0.2456
vn 0.2392 -0.8574 -0.4558
vn 0.1289 -0.9608 -0.2456
vn 0.3331 0.6973 -0.6347
vn 0.4047 0.4916 -0.7711
vn 0.4647 -0.0000 -0.8855
vn 0.2392 0.8574 -0.4558
vn 0.3331 -0.6973 -0.6347
vt 0.837228 0.961554
vt 0.818152 0.953589
vt 0.829851 0.946558
vt 0.956579 0.806236
vt 0.988195 0.806360
vt 0.981177 0.812973
vt 0.820781 0.898041
vt 0.808717 0.922444
vt 0.805971 0.906283
vt 0.816422 0.865259
vt 0.798452 0.857592
vt 0.813660 0.849018
vt 0.854940 0.973173
vt 0.829810 0.966877
vt 0.802361 0.818082
vt 0.777899 0.812973
vt 0.784917 0.806360
vt 0.825811 0.930651
vt 0.823036 0.914413
vt 0.818672 0.881632
vt 0.801176 0.873759
vt 0.809651 0.833102
vt 0.789195 0.826391
vt 0.812355 0.938343
vt 0.803570 0.890022
vt 0.794864 0.841677
vt 0.827190 0.825330
vt 0.819547 0.809678
vt 0.840939 0.941665
vt 0.838658 0.925098
vt 0.835594 0.891717
vt 0.834206 0.875002
vt 0.844894 0.957954
vt 0.994127 0.798752
vt 0.832636 0.858318
vt 0.830563 0.841716
vt 0.790849 0.798752
vt 0.837006 0.908427
vt 0.852694 0.956319
vt 0.786665 0.790762
vt 0.851319 0.922492
vt 0.850942 0.905567
vt 0.849890 0.854788
vt 0.848407 0.820965
vt 0.845725 0.804128
vt 0.850611 0.888640
vt 0.850278 0.871713
vt 0.851829 0.939412
vt 0.989943 0.790762
vt 0.849353 0.837868
vt 0.870933 0.822226
vt 0.860525 0.956766
vt 0.862688 0.940030
vt 0.917641 0.794139
vt 0.865700 0.889493
vt 0.867451 0.855778
vt 0.868732 0.838958
vt 0.876704 0.805837
vt 0.863955 0.923209
vt 0.864889 0.906357
vt 0.866513 0.872630
vt 0.890608 0.828398
vt 0.898432 0.813146
vt 0.876666 0.927145
vt 0.880629 0.894085
vt 0.882375 0.877505
vt 0.868280 0.959261
vt 0.873633 0.943454
vt 0.921324 0.802091
vt 0.884303 0.860963
vt 0.886777 0.844537
vt 0.878821 0.910651
vt 0.900057 0.868810
vt 0.902875 0.852642
vt 0.875856 0.963633
vt 0.913432 0.821735
vt 0.927886 0.809329
vt 0.889699 0.933734
vt 0.892882 0.917669
vt 0.906788 0.836786
vt 0.895395 0.901417
vt 0.897683 0.885101
vt 0.884908 0.949336
vt 0.920840 0.845112
vt 0.883119 0.969590
vt 0.897123 0.957058
vt 0.935119 0.815389
vt 0.910345 0.909972
vt 0.915041 0.877386
vt 0.917592 0.861150
vt 0.925760 0.829560
vt 0.903647 0.941989
vt 0.907529 0.926133
vt 0.912730 0.893690
vt 0.929805 0.884864
vt 0.933915 0.851861
vt 0.937076 0.835601
vt 0.919621 0.950438
vt 0.928006 0.901420
vt 0.889756 0.976756
vt 0.911829 0.965641
vt 0.942676 0.819888
vt 0.926026 0.917938
vt 0.931676 0.868323
vt 0.923500 0.934337
vt 0.944718 0.889698
vt 0.945610 0.872850
vt 0.893929 0.984677
vt 0.948034 0.839221
vt 0.950422 0.822528
vt 0.939016 0.956868
vt 0.941403 0.940175
vt 0.943827 0.906546
vt 0.946637 0.856016
vt 0.932865 0.973161
vt 0.942800 0.923380
vt 0.960340 0.924707
vt 0.960051 0.907776
vt 0.959556 0.873910
vt 0.959274 0.856978
vt 0.825215 0.989174
vt 0.963474 0.975437
vt 0.958251 0.823128
vt 0.959802 0.890843
vt 0.961450 0.958555
vt 0.960742 0.941636
vt 0.958895 0.840049
vt 0.771554 0.888040
vt 0.756773 0.907776
vt 0.756524 0.890843
vt 0.768652 0.854609
vt 0.755617 0.840049
vt 0.766501 0.838002
vt 0.779620 0.954549
vt 0.760196 0.975437
vt 0.758172 0.958555
vt 0.774372 0.921485
vt 0.772875 0.904776
vt 0.770215 0.871307
vt 0.755996 0.856978
vt 0.787148 0.970287
vt 0.966057 0.821644
vt 0.757464 0.941636
vt 0.757063 0.924707
vt 0.756278 0.873910
vt 0.817064 0.981240
vt 0.754973 0.823128
vt 0.762779 0.821644
vt 0.776361 0.938117
vt 0.790669 0.914735
vt 0.786380 0.881914
vt 0.784176 0.865519
vt 0.822838 0.973577
vt 0.777565 0.833289
vt 0.770459 0.818180
vt 0.797418 0.946930
vt 0.793409 0.930995
vt 0.788450 0.898343
vt 0.804803 0.961961
vt 0.781476 0.849249
vt 0.973737 0.818180
s 1
usemtl Material.003
f 23/1/1 10/2/2 22/3/3
f 57/4/4 13/5/5 1/6/6
f 19/7/7 8/8/8 7/9/9
f 17/10/10 4/11/11 16/12/12
f 23/1/1 12/13/13 11/14/14
f 14/15/15 1/16/6 13/17/5
f 21/18/16 8/8/8 20/19/17
f 18/20/18 5/21/19 17/10/10
f 15/22/20 2/23/21 14/15/15
f 21/18/16 10/2/2 9/24/22
f 19/7/7 6/25/23 18/20/18
f 15/22/20 4/11/11 3/26/24
f 26/27/25 14/15/15 25/28/26
f 33/29/27 21/18/16 32/30/28
f 30/31/29 18/20/18 29/32/30
f 26/27/25 16/12/12 15/22/20
f 34/33/31 22/3/3 33/29/27
f 57/4/4 24/34/32 13/5/5
f 30/31/29 20/19/17 19/7/7
f 28/35/33 16/12/12 27/36/34
f 34/33/31 12/13/13 23/1/1
f 25/28/26 13/17/5 24/37/32
f 32/30/28 20/19/17 31/38/35
f 29/32/30 17/10/10 28/35/33
f 45/39/36 12/13/13 34/33/31
f 35/40/37 25/28/26 24/37/32
f 43/41/38 31/38/35 42/42/39
f 39/43/40 29/32/30 28/35/33
f 37/44/41 25/28/26 36/45/42
f 43/41/38 33/29/27 32/30/28
f 41/46/43 29/32/30 40/47/44
f 37/44/41 27/36/34 26/27/25
f 45/39/36 33/29/27 44/48/45
f 57/4/4 35/49/37 24/34/32
f 41/46/43 31/38/35 30/31/29
f 39/43/40 27/36/34 38/50/46
f 48/51/47 38/50/46 37/44/41
f 56/52/48 44/48/45 55/53/49
f 57/4/4 46/54/50 35/49/37
f 52/55/51 42/42/39 41/46/43
f 50/56/52 38/50/46 49/57/53
f 56/52/48 12/13/13 45/39/36
f 47/58/54 35/40/37 46/54/50
f 54/59/55 42/42/39 53/60/56
f 50/56/52 40/47/44 39/43/40
f 48/51/47 36/45/42 47/58/54
f 54/59/55 44/48/45 43/41/38
f 52/55/51 40/47/44 51/61/57
f 60/62/58 47/58/54 59/63/59
f 66/64/60 55/53/49 54/59/55
f 64/65/61 51/61/57 63/66/62
f 60/62/58 49/57/53 48/51/47
f 68/67/63 55/53/49 67/68/64
f 57/4/4 58/69/65 46/54/50
f 64/65/61 53/60/56 52/55/51
f 62/70/66 49/57/53 61/71/67
f 68/67/63 12/13/13 56/52/48
f 59/63/59 46/54/50 58/69/65
f 66/64/60 53/60/56 65/72/68
f 62/70/66 51/61/57 50/56/52
f 73/73/69 61/71/67 72/74/70
f 79/75/71 12/13/13 68/67/63
f 70/76/72 58/69/65 69/77/73
f 77/78/74 65/72/68 76/79/75
f 73/73/69 63/66/62 62/70/66
f 71/80/76 59/63/59 70/76/72
f 77/78/74 67/68/64 66/64/60
f 75/81/77 63/66/62 74/82/78
f 71/80/76 61/71/67 60/62/58
f 79/75/71 67/68/64 78/83/79
f 57/4/4 69/77/73 58/69/65
f 75/81/77 65/72/68 64/65/61
f 82/84/80 72/74/70 71/80/76
f 90/85/81 78/83/79 89/86/82
f 57/4/4 80/87/83 69/77/73
f 86/88/84 76/79/75 75/81/77
f 84/89/85 72/74/70 83/90/86
f 90/85/81 12/13/13 79/75/71
f 81/91/87 69/77/73 80/87/83
f 88/92/88 76/79/75 87/93/89
f 84/89/85 74/82/78 73/73/69
f 82/84/80 70/76/72 81/91/87
f 89/86/82 77/78/74 88/92/88
f 86/88/84 74/82/78 85/94/90
f 95/95/91 85/94/90 84/89/85
f 93/96/92 81/91/87 92/97/93
f 99/98/94 89/86/82 88/92/88
f 96/99/95 86/88/84 85/94/90
f 93/96/92 83/90/86 82/84/80
f 101/100/96 89/86/82 100/101/97
f 57/4/4 91/102/98 80/87/83
f 97/103/99 87/93/89 86/88/84
f 95/95/91 83/90/86 94/104/100
f 101/100/96 12/13/13 90/85/81
f 91/102/98 81/91/87 80/87/83
f 99/98/94 87/93/89 98/105/101
f 106/106/102 94/104/100 105/107/103
f 112/108/104 12/13/13 101/100/96
f 103/109/105 91/102/98 102/110/106
f 110/111/107 98/105/101 109/112/108
f 107/113/109 95/95/91 106/106/102
f 104/114/110 92/97/93 103/109/105
f 111/115/111 99/98/94 110/111/107
f 108/116/112 96/99/95 107/113/109
f 104/114/110 94/104/100 93/96/92
f 112/108/104 100/101/97 111/115/111
f 57/4/4 102/110/106 91/102/98
f 108/116/112 98/105/101 97/103/99
f 119/117/113 107/113/109 118/118/114
f 116/119/115 104/114/110 115/120/116
f 123/121/117 111/115/111 122/122/118
f 57/4/4 113/123/119 102/110/106
f 119/117/113 109/112/108 108/116/112
f 117/124/120 105/107/103 116/119/115
f 123/121/117 12/13/13 112/108/104
f 113/123/119 103/109/105 102/110/106
f 121/125/121 109/112/108 120/126/122
f 117/124/120 107/113/109 106/106/102
f 114/127/123 104/114/110 103/109/105
f 122/122/118 110/111/107 121/125/121
f 128/128/124 118/129/114 117/130/120
f 126/131/125 114/132/123 125/133/126
f 132/134/127 122/135/118 121/136/121
f 130/137/128 118/129/114 129/138/129
f 127/139/130 115/140/116 126/131/125
f 133/141/131 123/121/117 122/135/118
f 57/4/4 124/142/132 113/123/119
f 130/137/128 120/143/122 119/144/113
f 128/128/124 116/145/115 127/139/130
f 134/146/133 12/13/13 123/121/117
f 125/133/126 113/147/119 124/148/132
f 132/134/127 120/143/122 131/149/134
f 141/150/135 131/149/134 130/137/128
f 139/151/136 127/139/130 138/152/137
f 145/153/138 12/13/13 134/146/133
f 136/154/139 124/148/132 135/155/140
f 143/156/141 131/149/134 142/157/142
f 140/158/143 128/128/124 139/151/136
f 136/154/139 126/131/125 125/133/126
f 144/159/144 132/134/127 143/156/141
f 141/150/135 129/138/129 140/158/143
f 138/152/137 126/131/125 137/160/145
f 144/159/144 134/146/133 133/141/131
f 57/4/4 135/161/140 124/142/132
f 2/23/21 137/160/145 136/154/139
f 10/2/2 143/156/141 9/24/22
f 6/25/23 141/150/135 140/158/143
f 3/26/24 138/152/137 137/160/145
f 11/14/14 144/159/144 10/2/2
f 57/4/4 1/6/6 135/161/140
f 7/9/9 142/157/142 141/150/135
f 5/21/19 138/152/137 4/11/11
f 11/14/14 12/13/13 145/153/138
f 1/16/6 136/154/139 135/155/140
f 9/24/22 142/157/142 8/8/8
f 5/21/19 140/158/143 139/151/136
f 23/1/1 11/14/14 10/2/2
f 19/7/7 20/19/17 8/8/8
f 17/10/10 5/21/19 4/11/11
f 14/15/15 2/23/21 1/16/6
f 21/18/16 9/24/22 8/8/8
f 18/20/18 6/25/23 5/21/19
f 15/22/20 3/26/24 2/23/21
f 21/18/16 22/3/3 10/2/2
f 19/7/7 7/9/9 6/25/23
f 15/22/20 16/12/12 4/11/11
f 26/27/25 15/22/20 14/15/15
f 33/29/27 22/3/3 21/18/16
f 30/31/29 19/7/7 18/20/18
f 26/27/25 27/36/34 16/12/12
f 34/33/31 23/1/1 22/3/3
f 30/31/29 31/38/35 20/19/17
f 28/35/33 17/10/10 16/12/12
f 25/28/26 14/15/15 13/17/5
f 32/30/28 21/18/16 20/19/17
f 29/32/30 18/20/18 17/10/10
f 35/40/37 36/45/42 25/28/26
f 43/41/38 32/30/28 31/38/35
f 39/43/40 40/47/44 29/32/30
f 37/44/41 26/27/25 25/28/26
f 43/41/38 44/48/45 33/29/27
f 41/46/43 30/31/29 29/32/30
f 37/44/41 38/50/46 27/36/34
f 45/39/36 34/33/31 33/29/27
f 41/46/43 42/42/39 31/38/35
f 39/43/40 28/35/33 27/36/34
f 48/51/47 49/57/53 38/50/46
f 56/52/48 45/39/36 44/48/45
f 52/55/51 53/60/56 42/42/39
f 50/56/52 39/43/40 38/50/46
f 47/58/54 36/45/42 35/40/37
f 54/59/55 43/41/38 42/42/39
f 50/56/52 51/61/57 40/47/44
f 48/51/47 37/44/41 36/45/42
f 54/59/55 55/53/49 44/48/45
f 52/55/51 41/46/43 40/47/44
f 60/62/58 48/51/47 47/58/54
f 66/64/60 67/68/64 55/53/49
f 64/65/61 52/55/51 51/61/57
f 60/62/58 61/71/67 49/57/53
f 68/67/63 56/52/48 55/53/49
f 64/65/61 65/72/68 53/60/56
f 62/70/66 50/56/52 49/57/53
f 59/63/59 47/58/54 46/54/50
f 66/64/60 54/59/55 53/60/56
f 62/70/66 63/66/62 51/61/57
f 73/73/69 62/70/66 61/71/67
f 70/76/72 59/63/59 58/69/65
f 77/78/74 66/64/60 65/72/68
f 73/73/69 74/82/78 63/66/62
f 71/80/76 60/62/58 59/63/59
f 77/78/74 78/83/79 67/68/64
f 75/81/77 64/65/61 63/66/62
f 71/80/76 72/74/70 61/71/67
f 79/75/71 68/67/63 67/68/64
f 75/81/77 76/79/75 65/72/68
f 82/84/80 83/90/86 72/74/70
f 90/85/81 79/75/71 78/83/79
f 86/88/84 87/93/89 76/79/75
f 84/89/85 73/73/69 72/74/70
f 81/91/87 70/76/72 69/77/73
f 88/92/88 77/78/74 76/79/75
f 84/89/85 85/94/90 74/82/78
f 82/84/80 71/80/76 70/76/72
f 89/86/82 78/83/79 77/78/74
f 86/88/84 75/81/77 74/82/78
f 95/95/91 96/99/95 85/94/90
f 93/96/92 82/84/80 81/91/87
f 99/98/94 100/101/97 89/86/82
f 96/99/95 97/103/99 86/88/84
f 93/96/92 94/104/100 83/90/86
f 101/100/96 90/85/81 89/86/82
f 97/103/99 98/105/101 87/93/89
f 95/95/91 84/89/85 83/90/86
f 91/102/98 92/97/93 81/91/87
f 99/98/94 88/92/88 87/93/89
f 106/106/102 95/95/91 94/104/100
f 103/109/105 92/97/93 91/102/98
f 110/111/107 99/98/94 98/105/101
f 107/113/109 96/99/95 95/95/91
f 104/114/110 93/96/92 92/97/93
f 111/115/111 100/101/97 99/98/94
f 108/116/112 97/103/99 96/99/95
f 104/114/110 105/107/103 94/104/100
f 112/108/104 101/100/96 100/101/97
f 108/116/112 109/112/108 98/105/101
f 119/117/113 108/116/112 107/113/109
f 116/119/115 105/107/103 104/114/110
f 123/121/117 112/108/104 111/115/111
f 119/117/113 120/126/122 109/112/108
f 117/124/120 106/106/102 105/107/103
f 113/123/119 114/127/123 103/109/105
f 121/125/121 110/111/107 109/112/108
f 117/124/120 118/118/114 107/113/109
f 114/127/123 115/120/116 104/114/110
f 122/122/118 111/115/111 110/111/107
f 128/128/124 129/138/129 118/129/114
f 126/131/125 115/140/116 114/132/123
f 132/134/127 133/141/131 122/135/118
f 130/137/128 119/144/113 118/129/114
f 127/139/130 116/145/115 115/140/116
f 133/141/131 134/146/133 123/121/117
f 130/137/128 131/149/134 120/143/122
f 128/128/124 117/130/120 116/145/115
f 125/133/126 114/132/123 113/147/119
f 132/134/127 121/136/121 120/143/122
f 141/150/135 142/157/142 131/149/134
f 139/151/136 128/128/124 127/139/130
f 136/154/139 125/133/126 124/148/132
f 143/156/141 132/134/127 131/149/134
f 140/158/143 129/138/129 128/128/124
f 136/154/139 137/160/145 126/131/125
f 144/159/144 133/141/131 132/134/127
f 141/150/135 130/137/128 129/138/129
f 138/152/137 127/139/130 126/131/125
f 144/159/144 145/153/138 134/146/133
f 2/23/21 3/26/24 137/160/145
f 10/2/2 144/159/144 143/156/141
f 6/25/23 7/9/9 141/150/135
f 3/26/24 4/11/11 138/152/137
f 11/14/14 145/153/138 144/159/144
f 7/9/9 8/8/8 142/157/142
f 5/21/19 139/151/136 138/152/137
f 1/16/6 2/23/21 136/154/139
f 9/24/22 143/156/141 142/157/142
f 5/21/19 6/25/23 140/158/143

BIN
data/models/scene.blend Normal file

Binary file not shown.

22
data/models/scene.mtl Normal file
View File

@@ -0,0 +1,22 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/wood1.jpg
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/walls_and_floor.png

214
data/models/scene.obj Normal file
View File

@@ -0,0 +1,214 @@
# Blender 4.0.2
# www.blender.org
mtllib scene.mtl
o Plane
v -3.872431 0.000000 -3.872431
v -3.872431 0.000000 3.872431
v 3.872431 0.000000 3.872431
v 3.872431 0.000000 -3.872431
v -3.872431 3.000000 -3.872431
v -3.872431 3.000000 3.872431
v 3.872431 3.000000 3.872431
v 3.872431 3.000000 -3.872431
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vt 0.688091 0.518615
vt 0.218399 0.988307
vt 0.218399 0.518615
vt 0.008503 0.062780
vt 0.715890 0.336789
vt 0.715890 0.062780
vt 0.008503 0.336789
vt 0.688091 0.988307
s 0
usemtl Material.002
f 3/1/1 1/2/1 2/3/1
f 2/4/2 7/5/2 3/6/2
f 4/6/3 5/7/3 1/4/3
f 3/4/4 8/5/4 4/6/4
f 1/6/5 6/7/5 2/4/5
f 3/1/1 4/8/1 1/2/1
f 2/4/2 6/7/2 7/5/2
f 4/6/3 8/5/3 5/7/3
f 3/4/4 7/7/4 8/5/4
f 1/6/5 5/5/5 6/7/5
o Cube
v -1.000000 1.084691 1.000000
v -1.000000 0.915309 1.000000
v -1.000000 1.084691 -1.000000
v -1.000000 0.915309 -1.000000
v 1.000000 1.084691 1.000000
v 1.000000 0.915309 1.000000
v 1.000000 1.084691 -1.000000
v 1.000000 0.915309 -1.000000
v 0.723372 -0.019617 -0.721264
v 0.667966 0.931702 -0.665858
v 0.723372 -0.019617 -0.826672
v 0.667966 0.931702 -0.882078
v 0.828780 -0.019617 -0.721264
v 0.884186 0.931702 -0.665858
v 0.828780 -0.019617 -0.826672
v 0.884186 0.931702 -0.882078
v 0.723372 -0.019617 0.881694
v 0.667966 0.931702 0.937100
v 0.723372 -0.019617 0.776286
v 0.667966 0.931702 0.720881
v 0.828780 -0.019617 0.881694
v 0.884186 0.931702 0.937100
v 0.828780 -0.019617 0.776286
v 0.884186 0.931702 0.720881
v -0.766023 -0.019617 0.881694
v -0.821429 0.931702 0.937100
v -0.766023 -0.019617 0.776286
v -0.821429 0.931702 0.720881
v -0.660615 -0.019617 0.881694
v -0.605209 0.931702 0.937100
v -0.660615 -0.019617 0.776286
v -0.605209 0.931702 0.720881
v -0.766023 -0.019617 -0.715648
v -0.821429 0.931702 -0.660242
v -0.766023 -0.019617 -0.821056
v -0.821429 0.931702 -0.876462
v -0.660615 -0.019617 -0.715648
v -0.605209 0.931702 -0.660242
v -0.660615 -0.019617 -0.821056
v -0.605209 0.931702 -0.876462
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vn -0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 -0.9983
vn 0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 0.9983
vt -0.936570 1.015405
vt 2.004606 1.264496
vt -0.936570 1.264496
vt -1.007504 1.015405
vt 1.933672 1.264496
vt -1.007504 1.264496
vt 2.004606 1.015405
vt 1.933672 1.015405
vt 1.933672 2.004606
vt -1.007504 -0.936570
vt -1.007504 2.004606
vt 1.933672 -0.936570
vt 1.513221 1.039511
vt 1.749712 -0.359487
vt 1.594700 -0.359487
vt 1.526866 -0.359487
vt 1.763357 1.039511
vt 1.681878 -0.359487
vt 1.831191 1.039511
vt 1.445387 1.039511
vt 1.681878 1.749712
vt 1.526866 1.594700
vt 1.526866 1.749712
vt 1.445387 1.831191
vt 1.763357 1.513221
vt 1.763357 1.831191
vt -0.844071 1.039511
vt -0.607580 -0.359487
vt -0.762591 -0.359487
vt -0.526101 1.039511
vt 1.681878 -0.607580
vt 1.526866 -0.762591
vt 1.526866 -0.607580
vt 1.445387 -0.526101
vt 1.763357 -0.844071
vt 1.763357 -0.526101
vt -0.663420 -0.359487
vt -0.426929 1.039511
vt -0.508408 -0.359487
vt -0.508408 -0.607580
vt -0.663420 -0.762591
vt -0.663420 -0.607580
vt -0.744899 -0.526101
vt -0.426929 -0.844071
vt -0.426929 -0.526101
vt 1.504962 1.039511
vt 1.741453 -0.359487
vt 1.586442 -0.359487
vt 1.822933 1.039511
vt -0.744899 1.039511
vt -0.508408 1.741453
vt -0.663420 1.586442
vt -0.663420 1.741453
vt -0.744899 1.822933
vt -0.426929 1.504962
vt -0.426929 1.822933
vt 1.681878 1.594700
vt 1.445387 1.513221
vt 1.681878 -0.762591
vt 1.445387 -0.844071
vt -0.508408 -0.762591
vt -0.744899 -0.844071
vt -0.508408 1.586442
vt -0.744899 1.504962
s 0
usemtl Material.001
f 10/9/6 11/10/6 9/11/6
f 12/12/7 15/13/7 11/14/7
f 16/15/8 13/11/8 15/10/8
f 14/16/9 9/14/9 13/13/9
f 15/17/10 9/18/10 11/19/10
f 12/19/11 14/20/11 16/17/11
f 18/21/12 19/22/12 17/23/12
f 19/24/13 24/25/13 23/26/13
f 24/27/14 21/23/14 23/22/14
f 21/26/15 18/28/15 17/24/15
f 23/29/10 17/30/10 19/31/10
f 20/32/11 22/33/11 24/34/11
f 26/35/12 27/36/12 25/37/12
f 27/24/13 32/25/13 31/26/13
f 32/38/14 29/37/14 31/36/14
f 30/25/15 25/24/15 29/26/15
f 31/39/10 25/40/10 27/41/10
f 28/42/11 30/43/11 32/44/11
f 34/35/12 35/36/12 33/37/12
f 35/45/13 40/46/13 39/47/13
f 40/38/14 37/37/14 39/36/14
f 38/46/15 33/45/15 37/47/15
f 39/48/10 33/49/10 35/50/10
f 36/51/11 38/52/11 40/53/11
f 42/54/12 43/55/12 41/56/12
f 43/45/13 48/46/13 47/47/13
f 48/57/14 45/56/14 47/55/14
f 45/47/15 42/58/15 41/45/15
f 47/59/10 41/60/10 43/61/10
f 44/62/11 46/63/11 48/64/11
f 10/9/6 12/15/6 11/10/6
f 12/12/7 16/16/7 15/13/7
f 16/15/8 14/9/8 13/11/8
f 14/16/9 10/12/9 9/14/9
f 15/17/10 13/20/10 9/18/10
f 12/19/11 10/18/11 14/20/11
f 18/21/12 20/27/12 19/22/12
f 19/24/13 20/28/13 24/25/13
f 24/27/14 22/21/14 21/23/14
f 21/26/15 22/25/15 18/28/15
f 23/29/10 21/65/10 17/30/10
f 20/32/11 18/66/11 22/33/11
f 26/35/12 28/38/12 27/36/12
f 27/24/13 28/28/13 32/25/13
f 32/38/14 30/35/14 29/37/14
f 30/25/15 26/28/15 25/24/15
f 31/39/10 29/67/10 25/40/10
f 28/42/11 26/68/11 30/43/11
f 34/35/12 36/38/12 35/36/12
f 35/45/13 36/58/13 40/46/13
f 40/38/14 38/35/14 37/37/14
f 38/46/15 34/58/15 33/45/15
f 39/48/10 37/69/10 33/49/10
f 36/51/11 34/70/11 38/52/11
f 42/54/12 44/57/12 43/55/12
f 43/45/13 44/58/13 48/46/13
f 48/57/14 46/54/14 45/56/14
f 45/47/15 46/46/15 42/58/15
f 47/59/10 45/71/10 41/60/10
f 44/62/11 42/72/11 46/63/11

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'scene.blend'
# www.blender.org
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/wood1.jpg

180
data/models/scene_table.obj Normal file
View File

@@ -0,0 +1,180 @@
# Blender 4.0.2
# www.blender.org
mtllib scene_table.mtl
o Cube
v -1.000000 1.084691 1.000000
v -1.000000 0.915309 1.000000
v -1.000000 1.084691 -1.000000
v -1.000000 0.915309 -1.000000
v 1.000000 1.084691 1.000000
v 1.000000 0.915309 1.000000
v 1.000000 1.084691 -1.000000
v 1.000000 0.915309 -1.000000
v 0.723372 -0.019617 -0.721264
v 0.667966 0.931702 -0.665858
v 0.723372 -0.019617 -0.826672
v 0.667966 0.931702 -0.882078
v 0.828780 -0.019617 -0.721264
v 0.884186 0.931702 -0.665858
v 0.828780 -0.019617 -0.826672
v 0.884186 0.931702 -0.882078
v 0.723372 -0.019617 0.881694
v 0.667966 0.931702 0.937100
v 0.723372 -0.019617 0.776286
v 0.667966 0.931702 0.720881
v 0.828780 -0.019617 0.881694
v 0.884186 0.931702 0.937100
v 0.828780 -0.019617 0.776286
v 0.884186 0.931702 0.720881
v -0.766023 -0.019617 0.881694
v -0.821429 0.931702 0.937100
v -0.766023 -0.019617 0.776286
v -0.821429 0.931702 0.720881
v -0.660615 -0.019617 0.881694
v -0.605209 0.931702 0.937100
v -0.660615 -0.019617 0.776286
v -0.605209 0.931702 0.720881
v -0.766023 -0.019617 -0.715648
v -0.821429 0.931702 -0.660242
v -0.766023 -0.019617 -0.821056
v -0.821429 0.931702 -0.876462
v -0.660615 -0.019617 -0.715648
v -0.605209 0.931702 -0.660242
v -0.660615 -0.019617 -0.821056
v -0.605209 0.931702 -0.876462
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn -0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 -0.9983
vn 0.9983 -0.0581 -0.0000
vn -0.0000 -0.0581 0.9983
vt 2.004606 1.264496
vt -0.936570 1.015405
vt -0.936570 1.264496
vt 1.933672 1.264496
vt -1.007504 1.015405
vt -1.007504 1.264496
vt 2.004606 1.015405
vt 1.933672 1.015405
vt -1.007504 -0.936570
vt 1.933672 2.004606
vt -1.007504 2.004606
vt 1.933672 -0.936570
vt 1.513221 1.039511
vt 1.749712 -0.359487
vt 1.594700 -0.359487
vt 1.526866 -0.359487
vt 1.763357 1.039511
vt 1.681878 -0.359487
vt 1.831191 1.039511
vt 1.445387 1.039511
vt 1.681878 1.749712
vt 1.526866 1.594700
vt 1.526866 1.749712
vt 1.445387 1.831191
vt 1.763357 1.513221
vt 1.763357 1.831191
vt -0.844071 1.039511
vt -0.607580 -0.359487
vt -0.762591 -0.359487
vt -0.526101 1.039511
vt 1.681878 -0.607580
vt 1.526866 -0.762591
vt 1.526866 -0.607580
vt 1.445387 -0.526101
vt 1.763357 -0.844071
vt 1.763357 -0.526101
vt -0.663420 -0.359487
vt -0.426929 1.039511
vt -0.508408 -0.359487
vt -0.508408 -0.607580
vt -0.663420 -0.762591
vt -0.663420 -0.607580
vt -0.744899 -0.526101
vt -0.426929 -0.844071
vt -0.426929 -0.526101
vt 1.504962 1.039511
vt 1.741453 -0.359487
vt 1.586442 -0.359487
vt 1.822933 1.039511
vt -0.744899 1.039511
vt -0.508408 1.741453
vt -0.663420 1.586442
vt -0.663420 1.741453
vt -0.744899 1.822933
vt -0.426929 1.504962
vt -0.426929 1.822933
vt 1.681878 1.594700
vt 1.445387 1.513221
vt 1.681878 -0.762591
vt 1.445387 -0.844071
vt -0.508408 -0.762591
vt -0.744899 -0.844071
vt -0.508408 1.586442
vt -0.744899 1.504962
s 0
usemtl Material.001
f 3/1/1 2/2/1 1/3/1
f 7/4/2 4/5/2 3/6/2
f 5/3/3 8/7/3 7/1/3
f 1/6/4 6/8/4 5/4/4
f 1/9/5 7/10/5 3/11/5
f 6/12/6 4/11/6 8/10/6
f 10/13/7 11/14/7 9/15/7
f 11/16/8 16/17/8 15/18/8
f 16/19/9 13/15/9 15/14/9
f 13/18/10 10/20/10 9/16/10
f 15/21/6 9/22/6 11/23/6
f 12/24/5 14/25/5 16/26/5
f 18/27/7 19/28/7 17/29/7
f 19/16/8 24/17/8 23/18/8
f 24/30/9 21/29/9 23/28/9
f 22/17/10 17/16/10 21/18/10
f 23/31/6 17/32/6 19/33/6
f 20/34/5 22/35/5 24/36/5
f 26/27/7 27/28/7 25/29/7
f 27/37/8 32/38/8 31/39/8
f 32/30/9 29/29/9 31/28/9
f 30/38/10 25/37/10 29/39/10
f 31/40/6 25/41/6 27/42/6
f 28/43/5 30/44/5 32/45/5
f 34/46/7 35/47/7 33/48/7
f 35/37/8 40/38/8 39/39/8
f 40/49/9 37/48/9 39/47/9
f 37/39/10 34/50/10 33/37/10
f 39/51/6 33/52/6 35/53/6
f 36/54/5 38/55/5 40/56/5
f 3/1/1 4/7/1 2/2/1
f 7/4/2 8/8/2 4/5/2
f 5/3/3 6/2/3 8/7/3
f 1/6/4 2/5/4 6/8/4
f 1/9/5 5/12/5 7/10/5
f 6/12/6 2/9/6 4/11/6
f 10/13/7 12/19/7 11/14/7
f 11/16/8 12/20/8 16/17/8
f 16/19/9 14/13/9 13/15/9
f 13/18/10 14/17/10 10/20/10
f 15/21/6 13/57/6 9/22/6
f 12/24/5 10/58/5 14/25/5
f 18/27/7 20/30/7 19/28/7
f 19/16/8 20/20/8 24/17/8
f 24/30/9 22/27/9 21/29/9
f 22/17/10 18/20/10 17/16/10
f 23/31/6 21/59/6 17/32/6
f 20/34/5 18/60/5 22/35/5
f 26/27/7 28/30/7 27/28/7
f 27/37/8 28/50/8 32/38/8
f 32/30/9 30/27/9 29/29/9
f 30/38/10 26/50/10 25/37/10
f 31/40/6 29/61/6 25/41/6
f 28/43/5 26/62/5 30/44/5
f 34/46/7 36/49/7 35/47/7
f 35/37/8 36/50/8 40/38/8
f 40/49/9 38/46/9 37/48/9
f 37/39/10 38/38/10 34/50/10
f 39/51/6 37/63/6 33/52/6
f 36/54/5 34/64/5 38/55/5

View File

@@ -0,0 +1,12 @@
# Blender 4.0.2 MTL File: 'scene.blend'
# www.blender.org
newmtl Material.002
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd data/textures/scene/walls_and_floor_light.png

View File

@@ -0,0 +1,37 @@
# Blender 4.0.2
# www.blender.org
mtllib scene_walls.mtl
o Plane
v -3.872431 0.000000 -3.872431
v -3.872431 0.000000 3.872431
v 3.872431 0.000000 3.872431
v 3.872431 0.000000 -3.872431
v -3.872431 3.000000 -3.872431
v -3.872431 3.000000 3.872431
v 3.872431 3.000000 3.872431
v 3.872431 3.000000 -3.872431
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vt 0.688091 0.518615
vt 0.218399 0.988307
vt 0.218399 0.518615
vt 0.008503 0.062780
vt 0.715890 0.336789
vt 0.715890 0.062780
vt 0.008503 0.336789
vt 0.688091 0.988307
s 0
usemtl Material.002
f 3/1/1 1/2/1 2/3/1
f 2/4/2 7/5/2 3/6/2
f 4/6/3 5/7/3 1/4/3
f 3/4/4 8/5/4 4/6/4
f 1/6/5 6/7/5 2/4/5
f 3/1/1 4/8/1 1/2/1
f 2/4/2 6/7/2 7/5/2
f 4/6/3 8/5/3 5/7/3
f 3/4/4 7/7/4 8/5/4
f 1/6/5 5/5/5 6/7/5

13
data/models/test.mtl Normal file
View File

@@ -0,0 +1,13 @@
# Blender 4.0.2 MTL File: 'None'
# www.blender.org
newmtl Material.001
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd content/textures/test/diamond-inlay-tile1_albedo.png
map_Kn content/textures/test/diamond-inlay-tile1_normal-ogl.png

53
data/models/test.obj Normal file
View File

@@ -0,0 +1,53 @@
# Blender 4.0.2
# www.blender.org
mtllib test.mtl
o Plane
v -5.000000 0.000000 5.000000
v 5.000000 0.000000 5.000000
v -5.000000 0.000000 -5.000000
v 5.000000 0.000000 -5.000000
v 2.368457 0.000000 -3.631543
v 2.368457 0.000000 -2.368457
v 3.631543 0.000000 -2.368457
v 3.631543 0.000000 -3.631543
v 2.368457 4.000000 -3.631543
v 2.368457 4.000000 -2.368457
v 3.631543 4.000000 -2.368457
v 3.631543 4.000000 -3.631543
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
vn -0.0000 -0.0000 1.0000
vt 1.642477 0.813162
vt 1.245911 2.069025
vt 1.245911 0.813162
vt 1.245911 1.242810
vt -1.067532 2.069025
vt -1.067532 -1.070632
vt 2.072125 -1.070632
vt 1.642477 1.242810
vt 2.072125 2.069025
vt 1.642477 1.639376
vt 1.245911 1.639376
vt 1.642477 2.069025
s 0
usemtl Material.001
f 8/1/1 11/2/1 7/3/1
f 6/4/2 3/5/2 1/6/2
f 6/4/2 2/7/2 7/8/2
f 7/8/2 4/9/2 8/10/2
f 5/11/2 4/9/2 3/5/2
f 11/8/2 9/11/2 10/4/2
f 6/3/3 9/12/3 5/1/3
f 5/3/4 12/12/4 8/1/4
f 7/1/5 10/2/5 6/3/5
f 8/1/1 12/12/1 11/2/1
f 6/4/2 5/11/2 3/5/2
f 6/4/2 1/6/2 2/7/2
f 7/8/2 2/7/2 4/9/2
f 5/11/2 8/10/2 4/9/2
f 11/8/2 12/10/2 9/11/2
f 6/3/3 10/2/3 9/12/3
f 5/3/4 9/2/4 12/12/4
f 7/1/5 11/12/5 10/2/5

View File

@@ -0,0 +1,8 @@
-- Game initialization script
-- глобальная таблица сущностей
g_entity_table = {
-- Lua class -- CPP class -- Description
{ "actor_player", "ActorBase", "Player actor entity" }
}

View File

@@ -0,0 +1,13 @@
-- Game object
game_object = {
}
function game_object:on_init()
end
function game_object:on_shutdown()
end
function game_object:on_update(dt)
end

View File

@@ -0,0 +1,8 @@
#version 120
varying vec3 v_color;
void main()
{
gl_FragColor = vec4(v_color, 1.0);
}

View File

@@ -0,0 +1,15 @@
#version 120
attribute vec3 a_position;
attribute vec3 a_color;
varying vec3 v_color;
uniform mat4 u_modelViewProjection;
void main()
{
gl_Position = u_modelViewProjection * vec4(a_position, 1.0f);
v_color = a_color;
}

View File

@@ -0,0 +1,17 @@
#version 120
varying vec3 v_position;
varying vec3 v_normal;
varying vec2 v_texcoord;
varying vec3 v_finalColor;
uniform sampler2D u_albedoTexture;
uniform vec4 u_customColor;
void main() {
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
//gl_FragColor = u_customColor * vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
gl_FragColor = vec4(v_finalColor, 1.0) * texture2D(u_albedoTexture, v_texcoord);
//gl_FragColor = vec4( v_normal, 1.0 );
//gl_FragColor = texture2D(u_albedoTexture, v_texcoord);
}

View File

@@ -0,0 +1,46 @@
#version 120
attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;
varying vec3 v_position;
varying vec3 v_normal;
varying vec2 v_texcoord;
varying vec3 v_finalColor;
uniform mat4 u_modelMatrix;
uniform mat4 u_viewMatrix;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewProjection;
vec3 CalcOmniLight()
{
vec3 lightPos = vec3(0.1, 2.1, 0.1);
float d = distance(lightPos, v_position);
vec3 L = normalize(lightPos-v_position);
vec3 N = normalize(v_normal);
vec3 col = vec3( max(0, dot(N, L) / d) );
col = col * 0.8 + 0.2;
return col;
}
vec3 CalcDirLight()
{
vec3 lightPos = vec3(5.0, 10.0, 1.0);
//lightPos = -lightPos;
vec3 L = normalize(lightPos);
vec3 N = normalize(v_normal);
vec3 col = vec3( max(0, dot(N, L)) );
col = col * 0.8 + 0.2;
return col;
}
void main() {
v_position = vec3( u_modelMatrix * vec4(a_position, 1.0) );
v_normal = vec3( mat3(u_modelMatrix) * a_normal );
v_texcoord = a_texcoord;
v_finalColor = CalcDirLight();
gl_Position = u_modelViewProjection * vec4(a_position, 1);
}

7
data/shaders/test.ps Normal file
View File

@@ -0,0 +1,7 @@
#version 130
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}

11
data/shaders/test.vs Normal file
View File

@@ -0,0 +1,11 @@
#version 130
attribute vec2 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main() {
v_color = a_color;
gl_Position = vec4(a_position.xy,0,1);
}

10
data/shaders/ui_base.ps Normal file
View File

@@ -0,0 +1,10 @@
#version 120
uniform sampler2D u_albedoTexture;
varying vec2 v_texcoord;
varying vec4 v_color;
void main() {
gl_FragColor = v_color * texture2D(u_albedoTexture, v_texcoord.st);
}

16
data/shaders/ui_base.vs Normal file
View File

@@ -0,0 +1,16 @@
#version 120
uniform mat4 u_projectionMatrix;
attribute vec2 a_position;
attribute vec2 a_texcoord;
attribute vec4 a_color;
varying vec2 v_texcoord;
varying vec4 v_color;
void main() {
v_texcoord = a_texcoord;
v_color = a_color;
gl_Position = u_projectionMatrix * vec4(a_position.xy, 0, 1);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
data/textures/notex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

View File

@@ -0,0 +1,2 @@
https://opengameart.org/content/wood-texture-tiles

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

25
engine.log Normal file
View File

@@ -0,0 +1,25 @@
'engine' build 1592, Feb 12 2026
NVIDIA Corporation
GeForce GTX 750 Ti/PCIe/SSE2
OpenGL ver. 3.2.0 NVIDIA 457.85
Context created with OpenGL version 3.2
...found GL_ARB_debug_output
loaded notex
created shader from file data/shaders/debug_draw.vs
created shader from file data/shaders/debug_draw.ps
Initializing entity manager ...
total registered 2 entities
actor_player
ActorBase
Player actor entity
Loading OBJ file data/levels/test/scene.obj...
Loading MTL file data/levels/test/scene.mtl...
loaded wood1
loaded walls_and_floor
Loaded Model 'data/levels/test/scene.obj'
created shader from file data/shaders/lit_generic.vs
created shader from file data/shaders/lit_generic.ps
--- unfreed textures ---
data/textures/notex.png
data/textures/scene/wood1.jpg
data/textures/scene/walls_and_floor.png

63
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,63 @@
file(GLOB ENGINE_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/engine/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/engine/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/engine/*.inl"
)
source_group("engine" FILES ${ENGINE_SRC})
file(GLOB ENGINE_PHYSICS_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/engine/physics/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/engine/physics/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/engine/physics/*.inl"
)
source_group("engine/physics" FILES ${ENGINE_PHYSICS_SRC})
file(GLOB RENDER_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/render/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/render/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/render/*.inl"
)
source_group("render" FILES ${RENDER_SRC})
file(GLOB SOUND_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/sound/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/sound/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/sound/*.inl"
)
source_group("sound" FILES ${SOUND_SRC})
file(GLOB GAME_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/game/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/game/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/game/*.inl"
)
source_group("game" FILES ${GAME_SRC})
add_executable(engine WIN32
${ENGINE_SRC}
${ENGINE_PHYSICS_SRC}
${RENDER_SRC}
${SOUND_SRC}
${GAME_SRC}
)
target_include_directories(engine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/engine"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/engine/physics"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/game"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/render"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/sound"
)
#target_precompile_headers(engine PRIVATE "pch.h")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/glm")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/stb")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/openal")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/SDL2-2.26.5")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/miniaudio-0.11.24")
target_include_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/")
target_link_directories(engine PRIVATE "${CMAKE_SOURCE_DIR}/thirdparty/openal")
target_link_libraries(engine SDL3::SDL3 pugixml luaplus glad bullet)

View File

@@ -0,0 +1,30 @@
#include "boundingbox.h"
void BoundingBox::SetIdentity()
{
m_min = glm::vec3(-0.1f);
m_max = glm::vec3(0.1f);
}
BoundingBox& BoundingBox::TransformAABB(const glm::mat4& modelMatrix)
{
// transform to center/extents box representation
glm::vec3 center = (m_max + m_min) * glm::vec3(0.5);
glm::vec3 extents = m_max - center;
// transform center
glm::vec3 t_center = glm::vec3(modelMatrix * glm::vec4(center, 1.0));
// transform extents (take maximum)
glm::mat3 abs_mat = glm::mat3(abs(glm::vec3(modelMatrix[0])), abs(glm::vec3(modelMatrix[1])), abs(glm::vec3(modelMatrix[2])));
glm::vec3 t_extents = abs_mat * extents;
// transform to min/max box representation
glm::vec3 tmin = t_center - t_extents;
glm::vec3 tmax = t_center + t_extents;
m_min = tmin;
m_max = tmax;
return *this;
}

41
src/engine/boundingbox.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef BOUNDINGBOX_H
#define BOUNDINGBOX_H
#include <glm/glm.hpp>
class BoundingBox
{
public:
glm::vec3 m_min;
glm::vec3 m_max;
public:
void SetIdentity();
BoundingBox& TransformAABB(const glm::mat4& modelMatrix);
//! Returns a bool whether the given point is inside the bounding volume.
bool Contains(const glm::vec3& pPoint) const
{
return m_min.x <= pPoint.x && m_min.y <= pPoint.y && m_min.z <= pPoint.z &&
m_max.x >= pPoint.x && m_max.y >= pPoint.y && m_max.z >= pPoint.z;
}
bool Contains(const BoundingBox& pBox) const
{
return Contains(pBox.m_min) && Contains(pBox.m_max);
}
glm::vec3 GetCenter() const
{
return m_min + (m_max - m_min) * 0.5f;
}
float GetExtend() const
{
return glm::length((m_max - m_min)) * 0.5f;
}
};
#endif

92
src/engine/camera.cpp Normal file
View File

@@ -0,0 +1,92 @@
#include "camera.h"
Camera::Camera()
{
m_projectionType = PERSPECTIVE;
m_position = glm::vec3(0.0f);
m_direction = glm::vec3(0.0f, 0.0f, 1.0f);
m_front = glm::vec3(0.0f, 0.0f, 0.0f);
m_right = glm::vec3(0.0f, 0.0f, 0.0f);
m_up = glm::vec3(0.0f, 1.0f, 0.0f);
m_fov = 70.0f;
m_yaw = 0.0f;
m_pitch = 0.0f;
}
Camera::~Camera()
{
}
void Camera::SetYawPitch(float yaw, float pitch)
{
m_yaw = yaw;
m_pitch = pitch;
m_direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
m_direction.y = sin(glm::radians(pitch));
m_direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
m_front = glm::normalize(m_direction);
m_right = glm::normalize(glm::cross(m_front, m_up));
}
glm::quat Camera::GetOrientation()
{
const glm::quat rotQuatY = glm::angleAxis(glm::radians(-GetYaw()), glm::vec3(0, 1, 0));
const glm::quat rotQuatX = glm::angleAxis(glm::radians(GetPitch()), GetRight());
return rotQuatX * rotQuatY;
}
glm::mat4 Camera::GetProjectionMatrix(const Viewport& viewport) const
{
glm::mat4 proj = glm::mat4(1.0f);
if (m_projectionType == ORTHOGONAL)
{
proj = glm::ortho(0.0f, (float)viewport.width, 0.0f, (float)viewport.height, 0.1f, 1000.0f);
}
else // if (m_projectionType == PERSPECTIVE): Control return in all path's
{
float aspectRatio = (float)viewport.width / (float)viewport.height;
proj = glm::perspective(glm::radians(m_fov), aspectRatio, 0.01f, 100.0f);
}
return proj;
}
glm::mat4 Camera::GetViewMatrix() const
{
glm::mat4 view = glm::mat4(1.0f);
view = glm::lookAt(m_position, m_position + m_front, m_up);
return view;
}
glm::mat4 Camera::GetTranslationMatrix() const
{
glm::mat4 t = glm::mat4(1.0f);
t = glm::translate(t, m_position);
t = glm::rotate(t, m_direction.x, glm::vec3(1.0f, 0.0f, 0.0f));
t = glm::rotate(t, m_direction.y, glm::vec3(0.0f, 1.0f, 0.0f));
t = glm::rotate(t, m_direction.z, glm::vec3(0.0f, 0.0f, 1.0f));
return t;
}
Frustum& Camera::GetFrustum()
{
return m_frustum;
}
//////////////////////////////////////////////////////////////////////////
// Camera Manager
CameraManager g_cameraManager;
void CameraManager::SetActiveCamera(Camera* p_camera)
{
m_activeCamera = p_camera;
}
Camera* CameraManager::GetActiveCamera() const
{
return m_activeCamera;
}

232
src/engine/camera.h Normal file
View File

@@ -0,0 +1,232 @@
#ifndef CAMERA_H
#define CAMERA_H
#include "boundingbox.h"
#include "render_shared.h"
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/norm.hpp>
enum CameraProjection_t
{
ORTHOGONAL,
PERSPECTIVE,
};
enum FrustumSide_t
{
FRUSTUM_TOP,
FRUSTUM_BOTTOM,
FRUSTUM_RIGHT,
FRUSTUM_LEFT,
FRUSTUM_FAR,
FRUSTUM_NEAR,
FRUSTUM_MAX
};
enum Halfspace_t
{
HALFSPACE_NEGATIVE = -1,
HALFSPACE_ONPLANE = 0,
HALFSPACE_POSITIVE = 1
};
struct Plane
{
glm::vec3 normal;
float distance;
Plane() : normal(0.0f, 1.0f, 0.0f), distance(0.0f)
{
}
inline void Normalize();
inline float ClassifyPoint(const glm::vec3& point) const;
};
inline void Plane::Normalize()
{
// calculate vector magnitude
float mag = glm::length(normal);
// divide plane normal and distance
normal /= mag;
distance /= mag;
}
inline float Plane::ClassifyPoint(const glm::vec3& point) const
{
return glm::dot(normal, point) + distance;
}
struct Sphere
{
glm::vec3 center;
float radius;
Sphere() : center(0.0f), radius(0.0f)
{
}
};
class Frustum
{
public:
Plane m_planes[FRUSTUM_MAX];
public:
inline void Build(const glm::mat4& a_ViewProj);
inline bool CullBoundingBox(const BoundingBox& a_Bounds);
inline bool CullSphere(const Sphere& a_Sphere);
};
inline void Frustum::Build(const glm::mat4& a_ViewProj)
{
// left
m_planes[FRUSTUM_LEFT].normal.x = a_ViewProj[3][0] + a_ViewProj[0][0];
m_planes[FRUSTUM_LEFT].normal.y = a_ViewProj[3][1] + a_ViewProj[0][1];
m_planes[FRUSTUM_LEFT].normal.z = a_ViewProj[3][2] + a_ViewProj[0][2];
m_planes[FRUSTUM_LEFT].distance = a_ViewProj[3][3] + a_ViewProj[0][3];
m_planes[FRUSTUM_LEFT].Normalize();
// right
m_planes[FRUSTUM_RIGHT].normal.x = a_ViewProj[3][0] - a_ViewProj[0][0];
m_planes[FRUSTUM_RIGHT].normal.y = a_ViewProj[3][1] - a_ViewProj[0][1];
m_planes[FRUSTUM_RIGHT].normal.z = a_ViewProj[3][2] - a_ViewProj[0][2];
m_planes[FRUSTUM_RIGHT].distance = a_ViewProj[3][3] - a_ViewProj[0][3];
m_planes[FRUSTUM_RIGHT].Normalize();
// bottom
m_planes[FRUSTUM_BOTTOM].normal.x = a_ViewProj[3][0] + a_ViewProj[1][0];
m_planes[FRUSTUM_BOTTOM].normal.y = a_ViewProj[3][1] + a_ViewProj[1][1];
m_planes[FRUSTUM_BOTTOM].normal.z = a_ViewProj[3][2] + a_ViewProj[1][2];
m_planes[FRUSTUM_BOTTOM].distance = a_ViewProj[3][3] + a_ViewProj[1][3];
m_planes[FRUSTUM_BOTTOM].Normalize();
// top
m_planes[FRUSTUM_TOP].normal.x = a_ViewProj[3][0] - a_ViewProj[1][0];
m_planes[FRUSTUM_TOP].normal.y = a_ViewProj[3][1] - a_ViewProj[1][1];
m_planes[FRUSTUM_TOP].normal.z = a_ViewProj[3][2] - a_ViewProj[1][2];
m_planes[FRUSTUM_TOP].distance = a_ViewProj[3][3] - a_ViewProj[1][3];
m_planes[FRUSTUM_TOP].Normalize();
// near
m_planes[FRUSTUM_NEAR].normal.x = a_ViewProj[3][0] + a_ViewProj[2][0];
m_planes[FRUSTUM_NEAR].normal.y = a_ViewProj[3][1] + a_ViewProj[2][1];
m_planes[FRUSTUM_NEAR].normal.z = a_ViewProj[3][2] + a_ViewProj[2][2];
m_planes[FRUSTUM_NEAR].distance = a_ViewProj[3][3] + a_ViewProj[2][3];
m_planes[FRUSTUM_NEAR].Normalize();
// far
m_planes[FRUSTUM_FAR].normal.x = a_ViewProj[3][0] - a_ViewProj[2][0];
m_planes[FRUSTUM_FAR].normal.y = a_ViewProj[3][1] - a_ViewProj[2][1];
m_planes[FRUSTUM_FAR].normal.z = a_ViewProj[3][2] - a_ViewProj[2][2];
m_planes[FRUSTUM_FAR].distance = a_ViewProj[3][3] - a_ViewProj[2][3];
m_planes[FRUSTUM_FAR].Normalize();
}
inline bool Frustum::CullBoundingBox(const BoundingBox& a_Bounds)
{
glm::vec3 center = a_Bounds.GetCenter();
glm::vec3 magnitude = (a_Bounds.m_max - a_Bounds.m_min) * 0.5f;
for (int i = 0; i < FRUSTUM_MAX; i++)
{
const Plane& plane = m_planes[i];
float dist = plane.ClassifyPoint(center);
dist += fabsf(plane.normal.z) * magnitude.z;
dist += fabsf(plane.normal.y) * magnitude.y;
dist += fabsf(plane.normal.x) * magnitude.x;
if (dist < 0.0f)
return true;
}
return false;
}
inline bool Frustum::CullSphere(const Sphere& a_Sphere)
{
return m_planes[FRUSTUM_LEFT].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius &&
m_planes[FRUSTUM_RIGHT].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius &&
m_planes[FRUSTUM_TOP].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius &&
m_planes[FRUSTUM_BOTTOM].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius &&
m_planes[FRUSTUM_NEAR].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius &&
m_planes[FRUSTUM_FAR].ClassifyPoint(a_Sphere.center) >= -a_Sphere.radius;
}
class Camera
{
public:
Camera();
~Camera();
inline void LookAt(const glm::vec3& direction) { m_direction = direction /*- m_position*/; }
inline void SetProjection(CameraProjection_t projection) { m_projectionType = projection; }
inline CameraProjection_t GetProjection() const { return m_projectionType; }
// In degrees
inline void SetFOV(float fov) { m_fov = fov; }
inline float GetFOV() const { return m_fov; }
inline void SetPosition(const glm::vec3& position) { m_position = position; }
inline const glm::vec3& GetPosition() const { return m_position; }
void SetYawPitch(float yaw, float pitch);
inline const glm::vec3& GetDirection() const { return m_direction; }
inline const glm::vec3& GetFront() const { return m_front; }
inline const glm::vec3& GetRight() const { return m_right; }
inline const glm::vec3& GetUp() const { return m_up; }
inline float GetYaw() { return m_yaw; }
inline float GetPitch() { return m_pitch; }
glm::quat GetOrientation();
// FIXME: Control zNear/zFar in perspective projection
glm::mat4 GetProjectionMatrix(const Viewport& viewport) const;
glm::mat4 GetViewMatrix() const;
glm::mat4 GetTranslationMatrix() const;
Frustum& GetFrustum();
private:
Frustum m_frustum;
CameraProjection_t m_projectionType;
glm::vec3 m_position;
glm::vec3 m_direction;
glm::vec3 m_front;
glm::vec3 m_right;
glm::vec3 m_up;
float m_yaw;
float m_pitch;
float m_fov;
};
//////////////////////////////////////////////////////////////////////////
// Camera Manager
class CameraManager
{
public:
void SetActiveCamera(Camera* p_camera);
Camera* GetActiveCamera() const;
private:
Camera* m_activeCamera;
};
extern CameraManager g_cameraManager;
#endif // !CAMERA_H

121
src/engine/core.cpp Normal file
View File

@@ -0,0 +1,121 @@
#include <stdio.h>
#include <string.h>
#include "core.h"
#include "log.h"
#include <SDL3/SDL.h>
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
void error_backend(const char* txt)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Engine Error", txt, nullptr);
}
void warning_backend(const char* txt)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning!", txt, nullptr);
}
//static void initializeConsole() {
// AllocConsole();
// freopen("CONOUT$", "w", stdout);
//}
int Core::ms_argc;
char** Core::ms_argv;
void Core::Init(int argc, char* argv[])
{
ms_argc = argc;
ms_argv = argv;
// initialize timer
//getSystemTimer()->init();
#ifdef WIN32
//initializeConsole();
#endif
Logger::Open();
}
void Core::Shutdown()
{
Logger::Close();
// shutdown timer
//getSystemTimer()->shutdown();
}
void Core::Frame()
{
//getSystemTimer()->update();
}
void Core::Error(const char* msg, ...)
{
static char buf[2048 * 2];
va_list args;
va_start(args, msg);
vsnprintf(buf, sizeof(buf), msg, args);
va_end(args);
Logger::Msg("ERROR! %s", buf);
error_backend(buf);
// __debugbreak();
#ifdef WIN32
ExitProcess(1);
#endif // WIN32
}
void Core::Warning(const char* msg, ...)
{
static char buf[2048 * 2];
va_list args;
va_start(args, msg);
vsnprintf(buf, sizeof(buf), msg, args);
va_end(args);
Logger::Msg("Warning! %s", buf);
warning_backend(buf);
}
bool Core::HasOption(const char* name)
{
for (int i = 0; i < ms_argc; i++) {
if (ms_argv[i]) {
if (strcmp(ms_argv[i], name) == 0)
return true;
}
}
return false;
}
const char* Core::GetOptionParameter(const char* name)
{
for (int i = 0; i < ms_argc; i++) {
if (ms_argv[i]) {
if (strcmp(ms_argv[i], name) == 0) {
if (!ms_argv[i + 1]) {
Core::Error("Commandline option %s doesn't have parameter!", name);
} else {
return ms_argv[i + 1];
}
}
}
}
return nullptr;
}

25
src/engine/core.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef CORE_H
#define CORE_H
#define SDL_ASSERT_LEVEL 3
#include <SDL3/SDL.h>
class Core
{
private:
static int ms_argc;
static char** ms_argv;
public:
static void Init(int argc, char* argv[]);
static void Shutdown();
static void Frame();
static void Error(const char* fmt, ...);
static void Warning(const char* fmt, ...);
static bool HasOption(const char* name);
static const char* GetOptionParameter(const char* name);
};
#endif // !CORE_H

308
src/engine/engine.cpp Normal file
View File

@@ -0,0 +1,308 @@
#include <SDL3/SDL_main.h>
#include "ifilesystem.h"
#include "core.h"
#include "log.h"
#include "engine.h"
#include "entitymanager.h"
#include "world.h"
#include "camera.h"
#include "inputmanager.h"
// renderer
#include "render.h"
#include "renderdevice.h"
// game
#include "game.h"
static bool s_bCoreProfile = true;
void ParseCommandLine()
{
if (Core::HasOption("-help") || Core::HasOption("-?")) {
const char* help =
"Commandline arguments list:\n\n"
"\n-? or -help - open this help.\n"
"\n-map - load level after engine start.\n"
"\n-disablecoreprofile - disable OpenGL core profile.\n";
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Commandline help",
help,
nullptr);
exit(0);
}
else if (Core::HasOption("-disablecoreprofile")) {
s_bCoreProfile = false;
}
}
Engine::Engine()
{
}
Engine::~Engine()
{
}
void Engine::Init()
{
ParseCommandLine();
if (SDL_Init(SDL_INIT_VIDEO) != true) {
Core::Error("Failed to initialize SDL3. Error code: %s", SDL_GetError());
}
// Enable core profile for compability for new hardware
if (s_bCoreProfile)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#ifdef _DEBUG
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif // _DEBUG
}
// Create render window
m_window = SDL_CreateWindow("Engine", 1280, 720, SDL_WINDOW_OPENGL);
if (!m_window) {
Core::Error("Failed to create window. Error code: %s", SDL_GetError());
}
// Initialize renderer
g_pRender = new Render();
g_pRender->Init(m_window);
// Initialize engine
g_entityManager->Init();
// Initialize game
g_game->Init();
if (Core::HasOption("-map")) {
const char* levelname = Core::GetOptionParameter("-map");
NewGame(levelname);
}
}
void Engine::Shutdown()
{
if (g_world) {
delete g_world;
g_world = nullptr;
}
g_game->Shutdown();
g_entityManager->Shutdown();
if (g_pRender) {
g_pRender->Shutdown();
delete g_pRender;
g_pRender = nullptr;
}
if (m_window) {
SDL_DestroyWindow(m_window);
m_window = nullptr;
}
}
void Engine::Run()
{
m_run = true;
while (m_run) {
Frame_SDL();
Core::Frame();
Frame();
}
}
void Engine::Frame_SDL()
{
// clear input system
g_inputManager.Frame();
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) {
m_run = false;
}
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE) {
m_run = false;
}
// keyboard action
if (event.key.key < kMaxKeyboardKeys) {
if (event.type == SDL_EVENT_KEY_DOWN) {
g_inputManager.OnKeyboardAction(event.key.key, true);
}
else if (event.type == SDL_EVENT_KEY_UP) {
g_inputManager.OnKeyboardAction(event.key.key, false);
}
}
// mouse action
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
g_inputManager.OnMouseAction(GetMouseButtonsFromSDL(event.button.button), true);
}
else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) {
g_inputManager.OnMouseAction(GetMouseButtonsFromSDL(event.button.button), false);
}
// mouse pos action
if (event.type == SDL_EVENT_MOUSE_MOTION) {
g_inputManager.OnMouseMoveAction(event.motion.xrel, event.motion.yrel);
}
}
}
void Engine::Frame()
{
// *** updating
// Get current ticks
static Uint64 frequency = SDL_GetPerformanceFrequency();
static Uint64 oldTime = 0;
Uint64 currentTime = SDL_GetPerformanceCounter();
if (currentTime <= oldTime)
currentTime = oldTime + 1;
float dt = oldTime > 0 ? (float)((double)(currentTime - oldTime) / frequency) : (float)(1.0f / 60.0f);
// update entities
if (g_world)
g_world->Update(dt);
// *** rendering
RenderFrame();
// save old time
oldTime = currentTime;
}
void Engine::RenderFrame()
{
// *** start rendering
int windowSizeX = 0, windowSizeY = 0;
SDL_GetWindowSize(m_window, &windowSizeX, &windowSizeY);
// initialize matrices
Camera* camera = g_cameraManager.GetActiveCamera();
if (camera)
{
Viewport vp = { 0,0,windowSizeX,windowSizeY };
g_pRender->SetProjectionMatrix(camera->GetProjectionMatrix(vp));
g_pRender->SetViewMatrix(camera->GetViewMatrix());
}
// install viewport
g_pRenderDevice->SetViewport(0, 0, windowSizeX, windowSizeY);
g_pRenderDevice->Clear(TST_COLOR | TST_DEPTH, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0xffffffff);
g_pRender->RenderScene();
g_pRender->Present();
}
static bool Server_validateMap(const char* mapname)
{
char buffer[kMaxPathLength];
snprintf(buffer, kMaxPathLength, "data/levels/%s/%s.xml", mapname, mapname);
if (!GetFileSystem()->IsExist(buffer)) {
Logger::Msg("Server::ValidateMap: map %s is not exist", mapname);
return false;
}
return true;
}
void Engine::NewGame(const char* mapname)
{
if (!Server_validateMap(mapname)) {
Logger::Msg("Engine::NewGame: map %s doesnt exist", mapname);
return;
}
// create entity container
Disconnect();
g_world = new World();
g_pRender->LoadSceneXML(mapname);
// after initializing client scene and collision system - we initialize the server game
g_game->InitForNewMap(mapname);
}
void Engine::Disconnect()
{
g_cameraManager.SetActiveCamera(nullptr);
if (g_world) {
delete g_world;
g_world = nullptr;
}
}
SDL_Window* Engine::GetWindow()
{
return m_window;
}
Engine g_engine;
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
HANDLE g_executionLockerMutex;
void initializeExecutionLockerMutex()
{
g_executionLockerMutex = OpenMutexA(READ_CONTROL, FALSE, "engine_execution_locker_mutex");
if (!g_executionLockerMutex) {
g_executionLockerMutex = CreateMutexA(NULL, FALSE, "engine_execution_locker_mutex");
} else {
MessageBoxA(NULL, "Failed to open second instance of application.", "Error", MB_OK | MB_ICONERROR);
ExitProcess(1);
}
}
#endif // WIN32
int main(int argc, char* argv[])
{
#ifdef WIN32
initializeExecutionLockerMutex();
#endif // WIN32
Core::Init(argc, argv);
g_engine.Init();
g_engine.Run();
g_engine.Shutdown();
Core::Shutdown();
return 0;
}
Engine* GetEngine()
{
return &g_engine;
}

36
src/engine/engine.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef ENGINE_H
#define ENGINE_H
#include <SDL3/SDL.h>
class Engine
{
public:
Engine();
~Engine();
void Init();
void Shutdown();
void Run();
void Frame_SDL();
void Frame();
void RenderFrame();
void NewGame(const char* mapname);
void Disconnect();
SDL_Window* GetWindow();
private:
SDL_Window* m_window = nullptr;
bool m_run = true;
};
Engine* GetEngine();
#endif

View File

@@ -0,0 +1,64 @@
#include "core.h"
#include "log.h"
#include "entitymanager.h"
static EntityManager s_entityManager;
EntityManager* g_entityManager = &s_entityManager;
void EntityManager::Init()
{
Logger::Msg("Initializing entity manager ...");
RegisterEntities();
}
void EntityManager::Shutdown()
{
}
void EntityManager::RegisterEntities()
{
SDL_assert(EntityRegistrator::ms_entityRegistrators);
for (EntityRegistrator* entityReg = EntityRegistrator::ms_entityRegistrators;
entityReg != nullptr;
entityReg = entityReg->m_nextEntityRegistrator)
{
m_entityRegistrationInfo.push_back(entityReg->m_entityRegInfo);
}
Logger::Msg("total registered %i entities", m_entityRegistrationInfo.size());
}
void EntityManager::Update(float dt)
{
//for (std::vector<IEntityBase*>::iterator it = m_entities.begin();
// it != m_entities.end();
// ++it)
//{
// IEntityBase* entity = (*it);
// if (entity) {
// entity->Update(dt);
// }
//}
}
IEntityBase* EntityManager::CreateEntity(const char* classname)
{
for (std::vector<EntityRegistrationInfo>::iterator it = m_entityRegistrationInfo.begin();
it != m_entityRegistrationInfo.end();
++it)
{
EntityRegistrationInfo& info = (*it);
if (strcmp(info.m_entityName, classname) == 0) {
IEntityBase* entity = info.m_createEntityFunc();
entity->SetClassname(info.m_entityName);
//m_entities.push_back(entity);
return entity;
}
}
Core::Error("EntityManager::CreateEntity: can't create entity with unknown '%s' class name!", classname);
return nullptr;
}

View File

@@ -0,0 +1,31 @@
#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H
#include <vector>
#include "ientity.h"
#include "entityregistrator.h"
class IEntityBase;
class EntityManager
{
public:
void Init();
void Shutdown();
void Update(float dt);
IEntityBase* CreateEntity(const char* classname);
private:
void RegisterEntities();
private:
std::vector<EntityRegistrationInfo> m_entityRegistrationInfo;
// std::vector<IEntityBase*> m_entities;
};
extern EntityManager* g_entityManager;
#endif // !ENTITYMANAGER_H

View File

@@ -0,0 +1,10 @@
#include "engine/entityregistrator.h"
EntityRegistrator* EntityRegistrator::ms_entityRegistrators;
EntityRegistrator::EntityRegistrator(EntityRegistrationInfo& regInfo) :
m_entityRegInfo(regInfo)
{
m_nextEntityRegistrator = ms_entityRegistrators;
ms_entityRegistrators = this;
}

View File

@@ -0,0 +1,30 @@
#ifndef ENTITYREGISTRATOR_H
#define ENTITYREGISTRATOR_H
class IEntityBase;
struct EntityRegistrationInfo
{
IEntityBase* (*m_createEntityFunc)();
const char* m_entityName;
};
template <typename T>
IEntityBase* createEntityTemplated()
{
return new T();
}
class EntityRegistrator
{
public:
EntityRegistrator(EntityRegistrationInfo& regInfo);
public:
EntityRegistrationInfo m_entityRegInfo;
EntityRegistrator* m_nextEntityRegistrator;
static EntityRegistrator* ms_entityRegistrators;
};
#endif // !ENTITYREGISTRATOR_H

121
src/engine/filesystem.cpp Normal file
View File

@@ -0,0 +1,121 @@
#include "filesystem.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <io.h>
FileSystem::FileSystem()
{
m_iOpenedFiles = 0;
memset(m_Files, 0, sizeof(m_Files));
}
FileSystem::~FileSystem()
{
}
void FileSystem::Init()
{
}
void FileSystem::Shutdown()
{
// find already opened file
for (int i = 0; i < MAX_OPENED_FILES; i++)
{
if (m_Files[i].m_pFile)
{
fclose(m_Files[i].m_pFile);
m_Files[i].m_pFile = nullptr;
}
}
}
FileHandle_t FileSystem::OpenFile(const char* pFilename, const char* pMode)
{
int iHandle;
// find already opened file
for (int i = 0; i < MAX_OPENED_FILES; i++)
{
if (m_Files[i].m_pFile && strcmp(m_Files[i].m_szFilename, pFilename) == 0)
return i;
}
if (!IsExist(pFilename) && pMode[0] == 'r')
{
printf("FileSystem::OpenFile: '%s' is not exist\n", pFilename);
return -1;
}
// Find free handle
for (int i = 0; i < MAX_OPENED_FILES; i++)
{
if (m_Files[i].m_pFile == NULL)
{
iHandle = i;
break;
}
}
m_Files[iHandle].m_pFile = fopen(pFilename, pMode);
assert(m_Files[iHandle].m_pFile);
m_iOpenedFiles++;
return iHandle;
}
void FileSystem::CloseFile(FileHandle_t hFile)
{
assert(hFile <= MAX_OPENED_FILES);
fclose(m_Files[hFile].m_pFile);
m_Files[hFile].m_pFile = NULL;
m_iOpenedFiles--;
}
size_t FileSystem::GetFileLength(FileHandle_t hFile)
{
assert(hFile <= MAX_OPENED_FILES);
assert(m_Files[hFile].m_pFile);
size_t size;
fseek(m_Files[hFile].m_pFile, 0, SEEK_END);
size = (size_t)ftell(m_Files[hFile].m_pFile);
fseek(m_Files[hFile].m_pFile, 0, SEEK_SET);
return size;
}
void FileSystem::ReadFile(FileHandle_t hFile, void* pData, size_t uiSize)
{
assert(hFile <= MAX_OPENED_FILES);
assert(m_Files[hFile].m_pFile);
fread(pData, uiSize, 1, m_Files[hFile].m_pFile);
}
void FileSystem::WriteFile(FileHandle_t hFile, void* pData, size_t uiSize)
{
assert(hFile <= MAX_OPENED_FILES);
assert(m_Files[hFile].m_pFile);
fwrite(pData, uiSize, 1, m_Files[hFile].m_pFile);
}
bool FileSystem::IsExist(const char* pFilename)
{
return _access(pFilename, /*F_OK*/ 0) == 0;
}
extern "C" __declspec(dllexport) IFileSystem* GetFileSystem()
{
static FileSystem fileSystem;
return &fileSystem;
}

46
src/engine/filesystem.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <stdio.h>
#include "ifilesystem.h"
#define MAX_OPENED_FILES 16
#define MAX_FNAME 260
struct FileHandleImpl
{
char m_szFilename[MAX_FNAME];
FILE* m_pFile;
};
class FileSystem : public IFileSystem
{
public:
FileSystem(void);
~FileSystem(void);
void Init();
void Shutdown();
FileHandle_t OpenFile(const char* pFilename, const char* pMode);
void CloseFile(FileHandle_t hFile);
// File API
size_t GetFileLength(FileHandle_t hFile);
void ReadFile(FileHandle_t hFile, void* pData, size_t uiSize);
void WriteFile(FileHandle_t hFile, void* pData, size_t uiSize);
bool IsExist(const char* pFilename);
private:
FileHandleImpl m_Files[MAX_OPENED_FILES];
int m_iOpenedFiles;
};
#endif // !FILESYSTEM_H

38
src/engine/ientity.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "ientity.h"
#include <glm/gtx/quaternion.hpp>
IEntityBase::IEntityBase() :
m_worldTM(1.0f),
m_position(0.0f),
m_rotation(0.0f),
m_scale(1.0f),
m_classname(nullptr)
{
}
IEntityBase::~IEntityBase()
{
}
void IEntityBase::Update(float dt)
{
}
void IEntityBase::Render()
{
}
const glm::mat4& IEntityBase::GetWorldTransform()
{
return m_worldTM;
}
void IEntityBase::UpdateTransform()
{
glm::vec3 radiansRotation = glm::vec3(glm::radians(m_rotation.x), glm::radians(m_rotation.y), glm::radians(m_rotation.z));
glm::mat4 rotation = glm::toMat4(glm::quat(radiansRotation));
m_worldTM = glm::mat4(1.0f);
m_worldTM = glm::translate(m_worldTM, m_position) * rotation * glm::scale(m_worldTM, m_scale);
}

46
src/engine/ientity.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef IENTITY_H
#define IENTITY_H
#include "boundingbox.h"
class IEntityBase
{
public:
IEntityBase();
virtual ~IEntityBase();
virtual void Update(float dt);
virtual void Render();
const char* GetClassname() { return m_classname; }
void SetClassname(const char* classname) { m_classname = classname; }
const BoundingBox& GetBoundingBox() { return m_boundingBox; }
const glm::mat4& GetWorldTransform();
void UpdateTransform();
protected:
glm::vec3 m_position;
glm::vec3 m_rotation;
glm::vec3 m_scale;
glm::mat4 m_worldTM;
BoundingBox m_boundingBox;
const char* m_classname;
};
// registration
#include "engine/entityregistrator.h"
#define REGISTER_ENTITY(CLASSNAME) \
static EntityRegistrationInfo s_##CLASSNAME##RegisterInfo = { &createEntityTemplated<CLASSNAME>, #CLASSNAME }; \
static EntityRegistrator s_##CLASSNAME##Registrator(s_##CLASSNAME##RegisterInfo)
#define REGISTER_ENTITY_EX(CLASSNAME, NAME) \
static EntityRegistrationInfo s_##CLASSNAME##RegisterInfo = { &createEntityTemplated<CLASSNAME>, NAME }; \
static EntityRegistrator s_##CLASSNAME##Registrator(s_##CLASSNAME##RegisterInfo)
#endif // !ENTITYBASE_H

32
src/engine/ifilesystem.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef IFILESYSTEM_H
#define IFILESYSTEM_H
// Constants
static const int kInvalidFileHandleValue = -1;
static const int kMaxPathLength = 260;
// File handle type
typedef int FileHandle_t;
// The file system interface.
class IFileSystem
{
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual FileHandle_t OpenFile( const char* pFilename, const char* pMode ) = 0;
virtual void CloseFile( FileHandle_t hFile ) = 0;
// File API
virtual size_t GetFileLength( FileHandle_t hFile ) = 0;
virtual void ReadFile( FileHandle_t hFile, void* pData, size_t uiSize ) = 0;
virtual void WriteFile( FileHandle_t hFile, void* pData, size_t uiSize ) = 0;
virtual bool IsExist( const char* pFilename ) = 0;
};
extern "C" __declspec(dllexport) IFileSystem* GetFileSystem();
#endif // !FILESYSTEM_H

View File

@@ -0,0 +1,68 @@
#include <SDL3/SDL.h>
#include "engine/inputmanager.h"
#include "engine/engine.h"
InputManager g_inputManager;
void InputManager::OnKeyboardAction(uint32_t key, bool action)
{
if (key >= kMaxKeyboardKeys)
return;
m_keyboard.m_keys[key] = action;
}
void InputManager::OnMouseAction(uint32_t key, bool action)
{
assert(key <= kMaxMouseKeys);
m_mouse.m_keys[key] = action;
}
void InputManager::OnMouseMoveAction(float x, float y)
{
m_deltaMousePos.x = x - m_mousePos.x;
m_deltaMousePos.y = y - m_mousePos.y;
if (m_relativeMouseMode) {
m_mousePos.x += x;
m_mousePos.y += y;
} else {
m_mousePos.x = x;
m_mousePos.y = y;
}
}
void InputManager::SetRelativeMouseMode(bool relativeMode)
{
if (m_relativeMouseMode != relativeMode) {
SDL_SetWindowRelativeMouseMode(GetEngine()->GetWindow(), relativeMode);
m_relativeMouseMode = relativeMode;
}
}
void InputManager::Frame()
{
m_deltaMousePos.x = 0;
m_deltaMousePos.y = 0;
m_mousePos.x = 0;
m_mousePos.y = 0;
}
EMouseButtons GetMouseButtonsFromSDL(uint8_t button)
{
EMouseButtons mousebutton = EMouseButton_None;
if (button == SDL_BUTTON_LEFT)
mousebutton = EMouseButton_Left;
else if (button == SDL_BUTTON_MIDDLE)
mousebutton = EMouseButton_Middle;
else if (button == SDL_BUTTON_RIGHT)
mousebutton = EMouseButton_Right;
else if (button == SDL_BUTTON_X1)
mousebutton = EMouseButton_1;
else if (button == SDL_BUTTON_X2)
mousebutton = EMouseButton_2;
return mousebutton;
}

66
src/engine/inputmanager.h Normal file
View File

@@ -0,0 +1,66 @@
#ifndef INPUTMANAGER_H
#define INPUTMANAGER_H
#include <stdint.h>
#include <glm/glm.hpp>
const int kMaxKeyboardKeys = 460;
const int kMaxMouseKeys = 5;
enum EMouseButtons
{
EMouseButton_None,
EMouseButton_Left,
EMouseButton_Middle,
EMouseButton_Right,
EMouseButton_1,
EMouseButton_2,
};
template <int KEYCOUNT>
class InputLayout
{
public:
bool IsKeyDown(uint32_t key)
{
assert(key <= KEYCOUNT);
return m_keys[key];
}
bool m_keys[KEYCOUNT];
};
class InputManager
{
public:
void OnKeyboardAction(uint32_t key, bool action);
void OnMouseAction(uint32_t key, bool action);
void OnMouseMoveAction(float x, float y);
InputLayout<kMaxKeyboardKeys>& GetKeyboard() { return m_keyboard; }
glm::vec2& GetMousePos() { return m_mousePos; }
glm::vec2& GetMouseDeltaPos() { return m_deltaMousePos; }
void SetRelativeMouseMode(bool relativeMode);
void Frame();
private:
InputLayout<kMaxKeyboardKeys> m_keyboard;
InputLayout<kMaxMouseKeys> m_mouse;
glm::vec2 m_mousePos;
glm::vec2 m_deltaMousePos;
bool m_relativeMouseMode = false;
};
extern InputManager g_inputManager;
EMouseButtons GetMouseButtonsFromSDL(uint8_t button);
#endif // !INPUTMANAGER_H

143
src/engine/log.cpp Normal file
View File

@@ -0,0 +1,143 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <SDL3/SDL.h>
#include "engine/log.h"
static char* g_month[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
static int g_day_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int build_id;
FILE* g_logFile;
void CalculateBuildNumber()
{
static int start_day = 3;
static int start_month = 10;
static int start_year = 2021;
// Calculating build
int build = 0, mnum = 0, dnum, ynum, mcnt;
char mon[4];
char buf[128];
strcpy(buf, __DATE__);
sscanf(buf, "%s %d %d", mon, &dnum, &ynum);
for (int i = 0; i < 12; i++) {
#ifdef WIN32
if (stricmp(g_month[i], mon) == 0) {
#else
if (strcasecmp(g_month[i], mon) == 0) {
#endif // WIN32
mnum = i;
break;
}
}
build_id = (ynum - start_year) * 365 + dnum - start_day;
for (int i = 0; i < mnum; ++i)
build_id += g_day_in_month[i];
for (int i = 0; i < start_month - 1; ++i)
build_id -= g_day_in_month[i];
}
void Logger::Open()
{
CalculateBuildNumber();
#if 0//def WIN32
char UserName[256];
DWORD dwUserName = 256;
if (!GetUserNameA(UserName, &dwUserName))
strcpy(UserName, "unnamed");
char logfilename[256];
sprintf(logfilename, "engine_%s.log", UserName);
#else
char logfilename[256];
sprintf(logfilename, "engine.log");
#endif
g_logFile = fopen(logfilename, "w");
Msg("'%s' build %d, %s", "engine", build_id, __DATE__);
}
void Logger::Close()
{
if (g_logFile) {
fclose(g_logFile);
g_logFile = nullptr;
}
}
void Logger::Msg(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
MsgArg(fmt, args);
va_end(args);
}
void Logger::MsgArg(const char* fmt, va_list args)
{
char buffer[2048];
int len = vsnprintf(buffer, sizeof(buffer), fmt, args);
assert(len >= 0);
assert(len < 2048);
SDL_assert_always(len >= 0);
SDL_assert_always(len < 2048);
//if (len >= sizeof(buffer))
// len = sizeof(buffer) - 1;
//if (buffer[len] != '\n' && len < sizeof(buffer) - 1)
//{
// buffer[len++] = '\n';
// buffer[len] = '\0';
//}
len = strlen(buffer);
if (buffer[len - 1] != '\n')
{
buffer[len++] = '\n';
buffer[len] = '\0';
}
//time_t t = time(0);
//struct tm* ti = localtime(&t);
//char timestr[256];
//sprintf(timestr, "%s", asctime(ti));
//timestr[strlen(timestr) - 1] = '\0';
//sprintf(buffer2, "[%s] %s", timestr, buffer);
if (g_logFile)
{
fwrite(buffer, sizeof(char), len, g_logFile);
fflush(g_logFile);
}
#ifdef WIN32
//OutputDebugStringA(buffer);
fwrite(buffer, sizeof(char), len, stdout);
#else
fwrite(buffer, sizeof(char), len, stdout);
#endif
}
void Msg(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
Logger::MsgArg(fmt, args);
va_end(args);
}

18
src/engine/log.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef LOG_H
#define LOG_H
#include <stdarg.h>
class Logger
{
public:
static void Open();
static void Close();
static void Msg(const char* fmt, ...);
static void MsgArg(const char* fmt, va_list args);
};
void Msg(const char* fmt, ...);
#endif // !LOG_H

View File

@@ -0,0 +1,13 @@
#include "physics/bullet_private.h"
glm::vec3 btVectorToGlm(const btVector3& vec)
{
return glm::vec3(vec.x(), vec.y(), vec.z());
}
btVector3 glmVectorToBt(const glm::vec3& vec)
{
return btVector3(vec.x, vec.y, vec.z);
}

View File

@@ -0,0 +1,19 @@
#ifndef BULLET_PRIVATE_H
#define BULLET_PRIVATE_H
#include <glm/glm.hpp>
// Bullet includes
#include "btBulletCollisionCommon.h"
#include "btBulletDynamicsCommon.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletDynamics/Character/btKinematicCharacterController.h"
const int kCollisionFilterAllMask = btBroadphaseProxy::DefaultFilter | btBroadphaseProxy::StaticFilter | btBroadphaseProxy::KinematicFilter | btBroadphaseProxy::DebrisFilter;
glm::vec3 btVectorToGlm(const btVector3& vec);
btVector3 glmVectorToBt(const glm::vec3& vec);
#endif

View File

@@ -0,0 +1,40 @@
#include <glm/glm.hpp>
#include "engine/physics/physicsdebugdraw.h"
#include "render/render_shared.h"
#include "render/debugrender.h"
void PhysicsDebugDraw::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
{
glm::vec3 btFrom = glm::vec3(from.x(), from.y(), from.z());
glm::vec3 btTo = glm::vec3(to.x(), to.y(), to.z());
glm::vec3 btColor = glm::vec3(color.x(), color.y(), color.z());
g_pDebugRender->DrawLine(btFrom, btTo, btColor);
}
void PhysicsDebugDraw::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
{
btVector3 to = PointOnB + normalOnB * 1;//distance;
const btVector3& from = PointOnB;
drawLine(from, to, color);
}
void PhysicsDebugDraw::reportErrorWarning(const char* warningString)
{
}
void PhysicsDebugDraw::draw3dText(const btVector3& location, const char* textString)
{
}
void PhysicsDebugDraw::setDebugMode(int debugMode)
{
m_debugMode = debugMode;
}
int PhysicsDebugDraw::getDebugMode() const
{
return m_debugMode;
}

View File

@@ -0,0 +1,25 @@
#ifndef PHYSICSDEBUGDRAW_H
#define PHYSICSDEBUGDRAW_H
#include "LinearMath/btIDebugDraw.h"
class PhysicsDebugDraw : public btIDebugDraw
{
public:
void Init();
void Shutdown();
// btIDebugDraw inherit
void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
void reportErrorWarning(const char* warningString) override;
void draw3dText(const btVector3& location, const char* textString) override;
void setDebugMode(int debugMode) override;
int getDebugMode() const override;
private:
int m_debugMode;
};
#endif

View File

@@ -0,0 +1,180 @@
#include "engine/core.h"
#include "engine/engine.h"
#include "engine/camera.h"
#include "engine/physics/physicsworld.h"
#include "engine/physics/physicsdebugdraw.h"
#include "engine/physics/rigidbody.h"
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
#include <BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h>
#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
static void InternalTickCallback(btDynamicsWorld* world, btScalar timeStep)
{
SDL_assert(world);
SDL_assert(world->getWorldUserInfo());
static_cast<PhysicsWorld*>(world->getWorldUserInfo())->InternalTick();
}
PhysicsWorld::PhysicsWorld()
{
m_debugDraw = false;
m_collisionConfiguration = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_overlappingPairCache = new btDbvtBroadphase();
m_solver = new btSequentialImpulseConstraintSolver();
m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_overlappingPairCache, m_solver, m_collisionConfiguration);
m_btGhostPairCallback = new btGhostPairCallback();
m_world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(m_btGhostPairCallback);
m_world->setInternalTickCallback(InternalTickCallback, this);
m_world->setDebugDrawer(&m_physicsDebugDraw);
m_accumulatedTime = 0.0f;
m_stepTime = (1.0f / 30.0f); // 30 fps
// set the standart gravity
//m_world->setGravity(btVector3(0, 0, 0));
//getWorld()->setGravity(btVector3(0.0, -15.0, 0.0));
}
PhysicsWorld::~PhysicsWorld()
{
m_world->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(nullptr);
// delete ghost pair callback
delete m_btGhostPairCallback;
// delete dynamics world
delete m_world;
// delete solver
delete m_solver;
// delete broadphase
delete m_overlappingPairCache;
// delete dispatcher
delete m_dispatcher;
// delete collision configuration
delete m_collisionConfiguration;
}
void PhysicsWorld::AddRigidBody(RigidBody* body)
{
SDL_assert(body->GetSDKBody() && "RigidBody is not properly initialized");
m_world->addRigidBody(body->GetSDKBody());
m_rigidbodies.push_back(body);
}
void PhysicsWorld::RemoveRigidBody(RigidBody* body)
{
SDL_assert(body->GetSDKBody() && "RigidBody is not properly initialized");
m_world->removeRigidBody(body->GetSDKBody());
auto it = std::find(m_rigidbodies.begin(), m_rigidbodies.end(), body);
if (it != m_rigidbodies.end())
m_rigidbodies.erase(it);
}
const std::vector<RigidBody*>& PhysicsWorld::GetRigidBodies()
{
return m_rigidbodies;
}
void PhysicsWorld::Step(float delta)
{
// m_world->stepSimulation(delta);
// m_world->stepSimulation(delta, 12, m_stepTime);
#if 1
if (delta < 0.01f)
{
m_accumulatedTime += delta;
if (m_accumulatedTime > m_stepTime)
{
m_world->stepSimulation(m_stepTime);
m_accumulatedTime -= m_stepTime;
}
}
else
{
m_world->stepSimulation(delta);
}
#endif
//m_debugDraw = true;
if (m_debugDraw)
{
//DebugDrawTriggers();
int debugDrawMode = 0;
debugDrawMode |= btIDebugDraw::DBG_DrawAabb;
debugDrawMode |= btIDebugDraw::DBG_DrawWireframe;
// debugDrawMode |= btIDebugDraw::DBG_DrawContactPoints;
m_physicsDebugDraw.setDebugMode(debugDrawMode);
m_world->debugDrawWorld();
}
/*if (m_world)
m_world->stepSimulation(1 / 60.0f);
int debugDrawMode = 0;
debugDrawMode |= btIDebugDraw::DBG_DrawAabb;
debugDrawMode |= btIDebugDraw::DBG_DrawWireframe;
debugDrawMode |= btIDebugDraw::DBG_DrawContactPoints;
m_physicsDebugDraw.setDebugMode(debugDrawMode);
m_world->debugDrawWorld();*/
}
void PhysicsWorld::ToggleDebugDraw()
{
m_debugDraw = !m_debugDraw;
}
void PhysicsWorld::InternalTick()
{
int numManifolds = m_world->getDispatcher()->getNumManifolds();
for (int i = 0; i < numManifolds; i++)
{
btPersistentManifold* contactManifold = m_world->getDispatcher()->getManifoldByIndexInternal(i);
btCollisionObject* obA = const_cast<btCollisionObject*>(contactManifold->getBody0());
btCollisionObject* obB = const_cast<btCollisionObject*>(contactManifold->getBody1());
int numContacts = contactManifold->getNumContacts();
for (int j = 0; j < numContacts; j++)
{
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance() < 0.f)
{
const btVector3& ptA = pt.getPositionWorldOnA();
const btVector3& ptB = pt.getPositionWorldOnB();
const btVector3& normalOnB = pt.m_normalWorldOnB;
RigidBody* rbA = static_cast<RigidBody*>(obA->getUserPointer());
RigidBody* rbB = static_cast<RigidBody*>(obB->getUserPointer());
if (!rbA || !rbB)
continue;
SDL_assert(rbA);
SDL_assert(rbB);
/*if (TriggerComponent* trigger = rbA->GetEntity()->GetComponent<TriggerComponent>())
{
trigger->OnCollide(rbA, rbB);
}
else if (TriggerComponent* trigger = rbB->GetEntity()->GetComponent<TriggerComponent>())
{
trigger->OnCollide(rbB, rbA);
}*/
}
}
}
}

View File

@@ -0,0 +1,51 @@
#ifndef PHYSICSWORLD_H
#define PHYSICSWORLD_H
#include "engine/physics/bullet_private.h"
#include "engine/physics/physicsdebugdraw.h"
#include <vector>
class RigidBody;
class PhysicsWorld
{
public:
PhysicsWorld();
~PhysicsWorld();
void AddRigidBody(RigidBody* body);
void RemoveRigidBody(RigidBody* body);
const std::vector<RigidBody*>& GetRigidBodies();
void Step(float delta);
btDynamicsWorld* GetWorld() { return m_world; }
float GetFixedTimeStep() { return m_stepTime; }
void ToggleDebugDraw();
void InternalTick();
private:
btDefaultCollisionConfiguration* m_collisionConfiguration;
btCollisionDispatcher* m_dispatcher;
btBroadphaseInterface* m_overlappingPairCache;
btSequentialImpulseConstraintSolver* m_solver;
btDiscreteDynamicsWorld* m_world;
btGhostPairCallback* m_btGhostPairCallback;
PhysicsDebugDraw m_physicsDebugDraw;
std::vector<RigidBody*> m_rigidbodies;
float m_accumulatedTime;
float m_stepTime;
bool m_debugDraw;
};
#endif // !PHYSICSWORLD_H

View File

@@ -0,0 +1,301 @@
#include "engine/core.h"
#include "engine/log.h"
#include "engine/physics/rigidbody.h"
#include "engine/physics/physicsworld.h"
#include <glm/glm.hpp>
RigidBody::RigidBody()
{
m_rigidBody = nullptr;
m_compoundShape = nullptr;
m_physicsWorld = nullptr;
m_mass = 0.0f;
m_isEnable = false;
m_static = false;
m_isKinematic = false;
m_isTrigger = false;
m_inWorld = false;
m_disableBodyOrientUpdate = false;
}
RigidBody::~RigidBody()
{
DestroyBody();
m_physicsWorld = nullptr;
m_compoundShape = nullptr;
m_rigidBody = nullptr;
}
//
//void RigidBody::LoadXML(tinyxml2::XMLElement& element)
//{
// Component::LoadXML(element);
//
// tinyxml2::XMLElement* massElement = element.FirstChildElement("Mass");
// if (massElement)
// massElement->QueryFloatAttribute("value", &m_mass);
//
// tinyxml2::XMLElement* staticElement = element.FirstChildElement("Static");
// if (staticElement)
// staticElement->QueryBoolAttribute("value", &m_static);
//
// tinyxml2::XMLElement* triggerElement = element.FirstChildElement("Trigger");
// if (triggerElement)
// triggerElement->QueryBoolAttribute("value", &m_isTrigger);
//
// tinyxml2::XMLElement* kinematicElement = element.FirstChildElement("Kinematic");
// if (kinematicElement)
// kinematicElement->QueryBoolAttribute("value", &m_isKinematic);
//
// bool changeFilterUsableHack = false;
// bool bolvanHack = false;
// bool obstacleHack = false;
//
// tinyxml2::XMLElement* filterElement = element.FirstChildElement("Filter");
// if (filterElement)
// {
// const char* filterValue = nullptr;
// filterElement->QueryStringAttribute("value", &filterValue);
// if (filterValue)
// {
// if (strcmp(filterValue, "PhysicsFilter_Usable") == 0)
// {
// changeFilterUsableHack = true;
// }
// if (strcmp(filterValue, "PhysicsFilter_Bolvan") == 0)
// {
// bolvanHack = true;
// }
// if (strcmp(filterValue, "PhysicsFilter_Obstacle") == 0)
// {
// obstacleHack = true;
// }
// }
// }
//
// CreateBody();
// UpdateBodyTranslationDirty();
//
// if (changeFilterUsableHack)
// {
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = PhysicsFilter_Usable;
// }
// else if (m_isTrigger)
// {
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = PhysicsFilter_Triggers;
// }
//
// // HACKHACKHACK: bolvan body never sleep
// if (bolvanHack)
// {
// m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
//
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = PhysicsFilter_NPC;
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterMask = kCollisionFilterAllMask;
// }
//
// if (obstacleHack)
// {
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = PhysicsFilter_Obstacle;
// m_rigidBody->getBroadphaseProxy()->m_collisionFilterMask = PhysicsFilter_Obstacle | PhysicsFilter_Player;
// m_rigidBody->setCustomDebugColor(btVector3(173 / 255, 216 / 255, 230 / 255));
// }
//}
//
//void RigidBody::SaveXML(tinyxml2::XMLElement& element)
//{
// Component::SaveXML(element);
//
// tinyxml2::XMLElement* enableElement = element.InsertNewChildElement("Enable");
// enableElement->SetAttribute("value", m_isEnable);
//
// tinyxml2::XMLElement* massElement = element.InsertNewChildElement("Mass");
// massElement->SetAttribute("value", m_mass);
//
// tinyxml2::XMLElement* staticElement = element.InsertNewChildElement("Static");
// staticElement->SetAttribute("value", m_static);
//
// tinyxml2::XMLElement* kinematicElement = element.InsertNewChildElement("Kinematic");
// kinematicElement->SetAttribute("value", m_isKinematic);
//
// tinyxml2::XMLElement* triggerElement = element.InsertNewChildElement("Trigger");
// triggerElement->SetAttribute("value", m_isTrigger);
//}
//void RigidBody::UpdateEntityTranslationDirty()
//{
// btTransform trans = m_rigidBody->getWorldTransform();
// GetEntity()->SetPosition(btVectorToGlm(trans.getOrigin()));
//
// // calculate rotation
//
// if (!m_disableBodyOrientUpdate)
// {
// btQuaternion quaternion;
// trans.getBasis().getRotation(quaternion);
// GetEntity()->SetRotation(glm::quat(quaternion.getW(), quaternion.getX(), quaternion.getY(), quaternion.getZ()));
// }
//
// // calculate rotation based on euler angles
// //float roll, pitch, yaw;
// //trans.getRotation().getEulerZYX(yaw, pitch, roll);
// //GetEntity()->SetEulerRotation(glm::vec3(roll, pitch, yaw));
//}
//
//void RigidBody::UpdateBodyTranslationDirty()
//{
// if (!m_rigidBody)
// return;
//
// btTransform trans;
// trans.setIdentity();
//
// // origin
// trans.setOrigin(glmVectorToBt(GetEntity()->GetPosition()));
//
// // rotation
// glm::quat entityRot = GetEntity()->GetRotation();
// btQuaternion bodyRot;
// bodyRot.setX(entityRot.x);
// bodyRot.setY(entityRot.y);
// bodyRot.setZ(entityRot.z);
// bodyRot.setW(entityRot.w);
// trans.setRotation(bodyRot);
//
// // set transformation to body
// m_rigidBody->setWorldTransform(trans);
//}
#if 0
void RigidBody::getWorldTransform(btTransform& worldTrans) const
{
//throw std::logic_error("The method or operation is not implemented.");
}
void RigidBody::setWorldTransform(const btTransform& worldTrans)
{
//throw std::logic_error("The method or operation is not implemented.");
UpdateBodyTranslationDirty();
}
#endif
void RigidBody::CreateBody()
{
SDL_assert(m_physicsWorld);
if (m_rigidBody)
return;
m_compoundShape = new btCompoundShape();
btVector3 localInertia(0.0f, 0.0f, 0.0f);
btRigidBody::btRigidBodyConstructionInfo rigidBodyCInfo(m_mass, nullptr, m_compoundShape, localInertia);
m_rigidBody = new btRigidBody(rigidBodyCInfo);
m_rigidBody->setUserPointer(this);
UpdateBodyProperties();
m_physicsWorld->AddRigidBody(this);
m_inWorld = m_rigidBody->isInWorld();
}
void RigidBody::DestroyBody()
{
if (m_physicsWorld)
{
m_physicsWorld->RemoveRigidBody(this);
}
else
{
Logger::Msg("RigidBody::DestroyBody: Can't remove body. Physics world is already destroyed.");
//Logger::Msg("Entity=0x%p", GetEntity());
}
// remove user pointer from this component
m_rigidBody->setUserPointer(nullptr);
delete m_rigidBody;
m_rigidBody = nullptr;
delete m_compoundShape;
m_compoundShape = nullptr;
}
void RigidBody::UpdateBodyProperties()
{
int bodyCollisionFlags = m_rigidBody->getCollisionFlags();
if (m_static)
bodyCollisionFlags |= btRigidBody::CF_STATIC_OBJECT;
else
bodyCollisionFlags &= ~btRigidBody::CF_STATIC_OBJECT;
if (m_isKinematic)
bodyCollisionFlags |= btRigidBody::CF_KINEMATIC_OBJECT;
else
bodyCollisionFlags &= ~btRigidBody::CF_KINEMATIC_OBJECT;
if (m_isTrigger)
bodyCollisionFlags |= btRigidBody::CF_NO_CONTACT_RESPONSE;
else
bodyCollisionFlags &= ~btRigidBody::CF_NO_CONTACT_RESPONSE;
m_rigidBody->setCollisionFlags(bodyCollisionFlags);
// trigger custom color
if (m_isTrigger)
m_rigidBody->setCustomDebugColor(btVector3(1.0f, 0.5f, 0.0f));
// HACKHACKHACK: kinematic body never sleep
if (m_isKinematic)
m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
}
void RigidBody::DisableBodyOrientUpdate()
{
m_disableBodyOrientUpdate = true;
}
void RigidBody::DisableBody()
{
m_rigidBody->setActivationState(DISABLE_SIMULATION);
}
void RigidBody::DisableCollide()
{
m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
}
void RigidBody::EnableCollide()
{
m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() & ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
}
void RigidBody::AttachShape(ShapeComponent* shape)
{
//shape->InitializeShape();
}
void RigidBody::DettachShape(ShapeComponent* shape)
{
//m_compoundShape->removeChildShape(shape->getSdkShape());
}
void RigidBody::ApplyImpulse(const glm::vec3& impulse)
{
m_rigidBody->applyCentralImpulse(glmVectorToBt(impulse));
}
void RigidBody::SetLinearVelocity(const glm::vec3& velocity)
{
m_rigidBody->setLinearVelocity(glmVectorToBt(velocity));
}
glm::vec3 RigidBody::GetLinearVelocity()
{
return btVectorToGlm(m_rigidBody->getLinearVelocity());
}

View File

@@ -0,0 +1,84 @@
#ifndef RIGIDBODYCOMPONENT_H
#define RIGIDBODYCOMPONENT_H
#include "engine/physics/bullet_private.h"
class PhysicsManager;
class PhysicsWorld;
class ShapeComponent;
enum PhysicsFilter
{
PhysicsFilter_None = 1 << 6,
PhysicsFilter_Player = 1 << 7,
PhysicsFilter_Triggers = 1 << 8,
PhysicsFilter_Usable = 1 << 9,
PhysicsFilter_NPC = 1 << 9,
PhysicsFilter_Obstacle = 1 << 9,
};
const int kPhysicsFilter_AllAux = PhysicsFilter_Player | PhysicsFilter_Triggers | PhysicsFilter_Usable;
//! Rigid body
class RigidBody
{
public:
RigidBody();
~RigidBody();
void UpdateEntityTranslationDirty();
void UpdateBodyTranslationDirty();
// Setter's and getter's
const float GetMass() { return m_mass; }
void SetMass(float value) { m_mass = value; }
const bool IsStatic() { return m_static; }
btRigidBody* GetSDKBody() { return m_rigidBody; }
btCompoundShape* GetCompoundShape() { return m_compoundShape; }
PhysicsWorld* GetPhysicsWorld() { return m_physicsWorld; }
//void getWorldTransform(btTransform& worldTrans) const override;
//void setWorldTransform(const btTransform& worldTrans) override;
void DisableBodyOrientUpdate();
void DisableBody();
void DisableCollide();
void EnableCollide();
void AttachShape(ShapeComponent* shape);
void DettachShape(ShapeComponent* shape);
void ApplyImpulse(const glm::vec3& impulse);
void SetLinearVelocity(const glm::vec3& velocity);
glm::vec3 GetLinearVelocity();
private:
void CreateBody();
void DestroyBody();
void UpdateBodyProperties();
private:
btRigidBody* m_rigidBody;
btCompoundShape* m_compoundShape;
PhysicsWorld* m_physicsWorld;
// Body mass
float m_mass;
bool m_isEnable;
bool m_static;
bool m_isKinematic;
bool m_isTrigger;
bool m_inWorld;
// engine properties
bool m_disableBodyOrientUpdate;
};
#endif // !RIGIDBODYCOMPONENT_H

176
src/engine/world.cpp Normal file
View File

@@ -0,0 +1,176 @@
#include <stdlib.h>
#include <string.h>
#include "core.h"
#include "log.h"
#include "ientity.h"
#include "entitymanager.h"
#include "world.h"
#include "camera.h"
// World
World::World()
{
m_isUpdating = false;
}
World::~World()
{
DestroyWorld();
}
void World::DestroyWorld()
{
for (int i = 0; i < m_entities.size(); ++i)
{
delete m_entities[i];
m_entities[i] = 0;
}
m_entities.clear();
}
void World::Update(float dt)
{
// Run destroyer
UpdateDestroyList();
m_isUpdating = true;
// Update entities
for (int i = 0; i < m_entities.size(); i++)
{
m_entities[i]->Update(dt);
}
for (int i = 0; i < m_entities.size(); i++)
{
m_entities[i]->UpdateTransform();
}
m_isUpdating = false;
}
void World::Render()
{
Camera* camera = g_cameraManager.GetActiveCamera();
if (!camera)
return;
Frustum& frustum = camera->GetFrustum();
// Render entities
for (int i = 0; i < m_entities.size(); i++)
{
if (frustum.CullBoundingBox(m_entities[i]->GetBoundingBox()))
continue;
m_entities[i]->Render();
}
}
void World::UpdateDestroyList()
{
// Update deleting list
if (!m_entitiesToDelete.empty())
{
for (int i = 0; i < m_entitiesToDelete.size(); i++)
{
DeleteEntity(FindEntityId(m_entitiesToDelete[i]));
}
m_entitiesToDelete.clear();
}
}
void World::AddEntity(IEntityBase* pEntity)
{
m_entities.push_back(pEntity);
}
IEntityBase* World::CreateEntity(const char* classname)
{
IEntityBase* entity = nullptr;
if (classname != nullptr)
{
// Get entity factory.
entity = g_entityManager->CreateEntity(classname);
}
if (entity == nullptr)
{
Core::Warning("World::CreateEntity: Can't create entity with unknown %s classname.", classname);
return nullptr;
}
m_entities.push_back(entity);
//entity->Spawn();
return entity;
}
void World::DeleteEntity(int index)
{
if (m_isUpdating)
{
Msg("World::DeleteEntity: illegal call in world update!");
SDL_assert_always(0);
return;
}
if (0 > index || index >= GetNumEntities())
{
Msg("World::DeleteEntity: invalid entity index %d", index);
SDL_assert_always(0);
return;
}
delete m_entities[index];
m_entities.erase(m_entities.begin() + index);
}
int World::GetNumEntities()
{
return (int)m_entities.size();
}
IEntityBase* World::GetEntity(int index)
{
return m_entities[index];
}
int World::FindEntityId(IEntityBase* pEntity)
{
for (int i = 0; i < GetNumEntities(); i++)
{
if (m_entities[i] == pEntity)
return i;
}
return -1;
}
IEntityBase* World::FindEntityByClassName(const char* pClassname)
{
for (int i = 0; i < GetNumEntities(); i++)
{
if (strcmp(m_entities[i]->GetClassname(), pClassname) == 0)
return m_entities[i];
}
return nullptr;
}
void World::MarkEntityToDelete(IEntityBase* pEntity)
{
m_entitiesToDelete.push_back(pEntity);
}
void World::MarkEntityToDeleteId(int index)
{
MarkEntityToDelete(GetEntity(index));
}
World* g_world = nullptr;

44
src/engine/world.h Normal file
View File

@@ -0,0 +1,44 @@
#ifndef WORLD_H
#define WORLD_H
#include <vector>
class IEntityBase;
class World
{
public:
World();
~World();
void DestroyWorld();
void Update(float dt);
void Render();
void AddEntity(IEntityBase* pEntity);
IEntityBase* CreateEntity(const char* pClassname);
void DeleteEntity(int index);
int GetNumEntities();
IEntityBase* GetEntity(int index);
int FindEntityId(IEntityBase* pEntity);
IEntityBase* FindEntityByClassName(const char* pClassname);
void MarkEntityToDelete(IEntityBase* pEntity);
void MarkEntityToDeleteId(int index);
private:
void UpdateDestroyList();
private:
std::vector<IEntityBase*> m_entities;
std::vector<IEntityBase*> m_entitiesToDelete;
bool m_isUpdating;
};
extern World* g_world;
#endif // !WORLD_H

172
src/game/game.cpp Normal file
View File

@@ -0,0 +1,172 @@
#include "ifilesystem.h"
#include "core.h"
#include "log.h"
#include "game.h"
#include "game_lua_help.h"
#include "ientity.h"
#include "entitymanager.h"
#include "world.h"
#include <pugixml.hpp>
static Game s_game;
Game* g_game = &s_game;
void consoleMsg(const char* msg)
{
Logger::Msg("%s", msg);
}
void engineError(const char* msg)
{
Core::Error("%s", msg);
}
void engineWarning(const char* msg)
{
Core::Warning("%s", msg);
}
LuaPlus::LuaObject engineCreateEntity(const char* classname)
{
LuaPlus::LuaObject entityObject;
entityObject.AssignNewTable(GetLuaState());
//GameObject* entity = (GameObject*)g_entityManager->createEntity(classname);
//entity->init_from_lua(entityObject);
//entity->init();
return entityObject;
}
void engineAddEntityToWorld(LuaPlus::LuaObject& object)
{
LuaPlus::LuaObject cppclass = object["__cpp_entity"];
// todo
}
void registerEngine()
{
using namespace LuaPlus;
// register engine functions
LuaObject engineTable = GetLuaState().GetGlobals().CreateTable("engine");
engineTable.RegisterDirect("error", &engineError);
engineTable.RegisterDirect("warning", &engineWarning);
engineTable.RegisterDirect("create_entity", &engineCreateEntity);
engineTable.RegisterDirect("add_entity_to_world", &engineAddEntityToWorld);
LuaObject consoleTable = GetLuaState().GetGlobals().CreateTable("console");
consoleTable.RegisterDirect("print", &consoleMsg);
}
void registerClasses()
{
using namespace LuaPlus;
// base thing
GetLuaState().GetGlobals().RegisterDirect("load_script", &luaLoadScript);
registerEngine();
}
void initializeEntityPrototypesFromLua()
{
using namespace LuaPlus;
LuaObject entitiesTable = GetLuaState().GetGlobal("g_entity_table");
for (LuaTableIterator it(entitiesTable); it; it.Next()) {
LuaObject entityTable = it.GetValue();
assert(entityTable.IsTable());
for (LuaTableIterator it2(entityTable); it2; it2.Next()) {
Logger::Msg("%s", it2.GetValue().ToString());
}
}
}
void initializeEntitiesTable()
{
using namespace LuaPlus;
LuaObject entitiesTable = GetLuaState().GetGlobal("g_entity_table");
if (entitiesTable.IsNil()) {
Core::Error("initializeEntitiesTable: failed initialize the entity table! g_entity_table is nil");
}
if (!entitiesTable.IsTable()) {
Core::Error("initializeEntitiesTable: failed initialize the entity table! g_entity_table is not a table");
}
initializeEntityPrototypesFromLua();
}
void initializeLua()
{
using namespace LuaPlus;
// register base classes
registerClasses();
// load game base script
luaLoadScript("game_init.lua");
}
void Game::Init()
{
initializeLua();
initializeEntitiesTable();
}
void Game::InitForNewMap(const char* mapname)
{
LoadLevelXML(mapname);
}
void Game::LoadLevelXML(const char* mapname)
{
// Load XML file of the level
char buffer[kMaxPathLength];
snprintf(buffer, kMaxPathLength, "data/levels/%s/%s.xml", mapname, mapname);
FileHandle_t file = GetFileSystem()->OpenFile(buffer, "rb");
SDL_assert_always(file != kInvalidFileHandleValue);
size_t length = GetFileSystem()->GetFileLength(file);
char* filedata = new char[length + 1];
GetFileSystem()->ReadFile(file, filedata, length);
filedata[length] = '\0';
GetFileSystem()->CloseFile(file);
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer(filedata, length);
delete[] filedata;
if (!result) {
Core::Error("Game::LoadLevelXML: Error while reading level description file '%s'\nError: %s:%i",
buffer, result.description(), result.offset);
}
for (pugi::xml_node entity : doc.child("Entities").children("Entity")) {
pugi::xml_attribute entityname = entity.attribute("name");
pugi::xml_attribute classname = entity.attribute("classname");
if (classname.empty()) {
if (!entityname.empty()) {
Core::Error(" Game::LoadLevelXML: Classname is not specified for entity '%s'", entityname.as_string());
}
else {
Core::Error(" Game::LoadLevelXML: Classname is not specified for entity");
}
}
IEntityBase* entity = g_entityManager->CreateEntity(classname.as_string());
g_world->AddEntity(entity);
}
}
void Game::Shutdown()
{
}

18
src/game/game.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef GAME_H
#define GAME_H
class Game
{
public:
void Init();
void InitForNewMap(const char* mapname);
void LoadLevelXML(const char* mapname);
void Shutdown();
};
extern Game* g_game;
#endif

View File

@@ -0,0 +1,91 @@
#include <string>
#include "core.h"
#include "game_lua_help.h"
class LuaStateWrapper
{
public:
LuaStateWrapper()
{
m_luaState = LuaPlus::LuaState::Create();
m_luaState->OpenLibs();
}
~LuaStateWrapper()
{
LuaPlus::LuaState::Destroy(m_luaState);
}
LuaPlus::LuaState& operator()()
{
return *m_luaState;
}
private:
LuaPlus::LuaState* m_luaState;
};
LuaPlus::LuaState& GetLuaState()
{
static LuaStateWrapper instance;
return instance();
}
void luaError(int errorcode)
{
LuaPlus::LuaState* state = &GetLuaState();
LuaPlus::LuaStackObject stackObj(state, -1);
const char* errorStr = stackObj.GetString();
if (errorStr) {
GetLuaState().SetTop(0);
}
else {
errorStr = "Unknown lua error";
}
Core::Error(errorStr);
}
void luaError(int errorcode, const char* filename)
{
LuaPlus::LuaState* state = &GetLuaState();
LuaPlus::LuaStackObject stackObj(state, -1);
std::string errorStr = stackObj.GetString();
if (!errorStr.empty()) {
GetLuaState().SetTop(0);
}
else {
errorStr = "Unknown lua error";
}
Core::Error(errorStr.c_str());
}
void luaLoadScript(const char* filename)
{
char buffer[260];
snprintf(buffer, sizeof(buffer), "data/scripts/%s", filename);
int result = 0;
result = GetLuaState().DoFile(buffer);
if (result != 0) {
luaError(result, buffer);
}
}
void luaDoString(const char* str)
{
int result = 0;
result = GetLuaState().DoString(str);
if (result != 0) {
luaError(result);
}
}
glm::mat4 getMatrixFromLua(LuaPlus::LuaObject& matrix)
{
glm::mat4 return_matrix = glm::identity<glm::mat4>();
return return_matrix;
}

17
src/game/game_lua_help.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef GAME_LUA_HELP_H
#define GAME_LUA_HELP_H
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <LuaPlus.h>
LuaPlus::LuaState& GetLuaState();
void luaLoadScript(const char* filename);
void luaDoString(const char* str);
glm::mat4 getMatrixFromLua(LuaPlus::LuaObject& matrix);
#endif

122
src/game/game_object.cpp Normal file
View File

@@ -0,0 +1,122 @@
#include "inputmanager.h"
#include "game_object.h"
#include <SDL3/SDL.h>
REGISTER_ENTITY(Entity);
Entity::Entity() :
m_model(nullptr)
{
}
Entity::~Entity()
{
}
void Entity::Render()
{
if (m_model)
m_model->Draw(GetWorldTransform());
}
void Entity::LoadModel(const char* filename)
{
m_model = g_pModelSystem->LoadModel(filename);
}
REGISTER_ENTITY(TempPlayer);
TempPlayer::TempPlayer()
{
}
TempPlayer::~TempPlayer()
{
}
void TempPlayer::Update(float dt)
{
g_cameraManager.SetActiveCamera(&m_camera);
UpdateCameraLook();
UpdateCameraMovement(dt);
}
void TempPlayer::UpdateCameraMovement(float dt)
{
// calculate player movement
float speed = 19.0f * dt;
uint32_t movementDir = GenMovementDir();
if (movementDir & EMovementDir_Forward)
m_position += speed * m_camera.GetFront();
if (movementDir & EMovementDir_Backward)
m_position -= speed * m_camera.GetFront();
if (movementDir & EMovementDir_Left)
m_position -= glm::normalize(glm::cross(m_camera.GetFront(), m_camera.GetUp())) * speed;
if (movementDir & EMovementDir_Right)
m_position += glm::normalize(glm::cross(m_camera.GetFront(), m_camera.GetUp())) * speed;
// set position back to camera for calculation view matrix
m_camera.SetPosition(m_position);
}
void TempPlayer::UpdateCameraLook()
{
g_inputManager.SetRelativeMouseMode(true);
glm::ivec2 mousePos = g_inputManager.GetMousePos();
// calculate yaw and pitch
static float yaw = 0.0f, pitch = 0.0f;
int deltaX = mousePos.x;
int deltaY = mousePos.y;
float sensitivity = 0.15f;
yaw += deltaX * sensitivity;
pitch -= deltaY * sensitivity;
if (pitch > 89.0f) pitch = 89.0f;
if (pitch < -89.0f) pitch = -89.0f;
m_camera.SetYawPitch(yaw, pitch);
}
uint32_t TempPlayer::GenMovementDir()
{
uint32_t movementDir = EMovementDir_None;
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_W)) {
movementDir |= EMovementDir_Forward;
}
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_S)) {
movementDir |= EMovementDir_Backward;
}
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_A)) {
movementDir |= EMovementDir_Left;
}
if (g_inputManager.GetKeyboard().IsKeyDown(SDLK_D)) {
movementDir |= EMovementDir_Right;
}
return movementDir;
}
Weapon::Weapon()
{
}
Weapon::~Weapon()
{
}
void Weapon::Update(float dt)
{
}

60
src/game/game_object.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef GAME_OBJECT_H
#define GAME_OBJECT_H
#include "engine/ientity.h"
#include "engine/camera.h"
#include "render/modelsystem.h"
enum EMovmentDir
{
EMovementDir_None = 1 << 0,
EMovementDir_Forward = 1 << 1,
EMovementDir_Backward = 1 << 2,
EMovementDir_Left = 1 << 3,
EMovementDir_Right = 1 << 4
};
class Entity : public IEntityBase
{
public:
Entity();
virtual ~Entity();
virtual void Render();
virtual void LoadModel(const char* filename);
protected:
Model* m_model;
};
class TempPlayer : public Entity
{
public:
TempPlayer();
~TempPlayer();
virtual void Update(float dt);
void UpdateCameraMovement(float dt);
void UpdateCameraLook();
private:
uint32_t GenMovementDir();
private:
Camera m_camera;
};
class Weapon : public Entity
{
public:
Weapon();
~Weapon();
virtual void Update(float dt);
};
#endif // !GAME_OBJECT_H

120
src/render/debugrender.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include "debugrender.h"
#include "render_shared.h"
#include "render.h"
#include "renderdevice.h"
#include "gpu_buffer.h"
#include "shadersystem.h"
#include "glad/glad.h"
struct DebugVertex
{
glm::vec3 position;
glm::vec3 color;
};
static InputLayoutDesc_t g_debugRenderLayout[] =
{
{ VERTEXATTR_VEC3, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC3, SHADERSEMANTIC_COLOR }
};
bool g_drawDebug = true;
DebugRender* g_pDebugRender;
DebugRender::DebugRender()
{
m_verticesBuffer = nullptr;
m_shader = nullptr;
}
DebugRender::~DebugRender()
{
m_verticesBuffer = nullptr;
m_shader = nullptr;
}
void DebugRender::Initialize()
{
//float points[12];
//m_verticesBuffer = g_pRenderDevice->CreateVertexBuffer(points, sizeof(points), true);
m_verticesBuffer = g_pRenderDevice->CreateVertexBuffer(NULL, kMaxDebugVBSize, true);
m_shader = g_pShaderSystem->CreateShader("debug_draw",
"data/shaders/debug_draw.vs",
"data/shaders/debug_draw.ps",
g_debugRenderLayout,
sizeof(g_debugRenderLayout) / sizeof(g_debugRenderLayout[0]));
}
void DebugRender::Shutdown()
{
if (m_verticesBuffer) {
delete m_verticesBuffer;
m_verticesBuffer = nullptr;
}
}
void DebugRender::DrawLine(const glm::vec3& from, const glm::vec3& to, const glm::vec3& color)
{
if (!g_drawDebug)
return;
Line line;
line.from = from;
line.color0 = color;
line.to = to;
line.color1 = color;
m_lines.push_back(line);
}
void DebugRender::RenderFrame()
{
if (!g_drawDebug)
return;
// draw lines
DrawLinesInternal();
// and clear them
m_lines.clear();
}
void DebugRender::DrawAxis(const glm::vec3& vec)
{
const float length = 0.2f;
DrawLine(vec, glm::vec3(vec.x + length, vec.y, vec.z), glm::vec3(1.0f, 0.0, 0.0f));
DrawLine(vec, glm::vec3(vec.x, vec.y + length, vec.z), glm::vec3(0.0f, 1.0f, 0.0f));
DrawLine(vec, glm::vec3(vec.x, vec.y, vec.z + length), glm::vec3(0.0f, 0.0f, 1.0f));
}
void DebugRender::DrawLinesInternal()
{
if (m_lines.empty())
return;
g_pRenderDevice->SetDepthTest(true);
g_pRenderDevice->SetDepthWrite(true);
g_pRenderDevice->SetVerticesBuffer(m_verticesBuffer);
m_verticesBuffer->UpdateBuffer(m_lines.data(), m_lines.size() * sizeof(Line));
// Bind our shader
g_pShaderSystem->SetShader(m_shader);
// #TODO: Fix stupid bug, when we get very far from wireframe and lines can start cliping
glm::mat4 proj = g_pRender->GetProjectionMatrix();
glm::mat4 view = g_pRender->GetViewMatrix();
proj[2][3] -= 0.0001f;
glm::mat4 mv = glm::mat4(1.0f);
mv = proj * view;
g_pShaderSystem->SetUniformMatrix(m_shader, UNIFORM_MVP_MATRIX, &mv[0]);
// draw stuff
g_pRenderDevice->DrawArrays(PT_LINES, 0, m_lines.size() * 2);
}

52
src/render/debugrender.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef DEBUGRENDER_H
#define DEBUGRENDER_H
#include <vector>
#include "render_shared.h"
const int kMaxDebugVBSize = 1024 * 1024 * 2;
class GPUBuffer;
class Shader;
class DebugRender
{
public:
DebugRender();
~DebugRender();
void Initialize();
void Shutdown();
void DrawAxis(const glm::vec3& vec);
void DrawLine(const glm::vec3& from, const glm::vec3& to, const glm::vec3& color);
void RenderFrame();
private:
void DrawLinesInternal();
private:
// Primitives
struct Line
{
glm::vec3 from;
glm::vec3 color0;
glm::vec3 to;
glm::vec3 color1;
};
std::vector<Line> m_lines;
private:
GPUBuffer* m_verticesBuffer;
Shader* m_shader;
};
extern DebugRender* g_pDebugRender;
extern bool g_drawDebug;
#endif // !DEBUGRENDER_H

215
src/render/gl_shared.cpp Normal file
View File

@@ -0,0 +1,215 @@
#include "gl_shared.h"
#include "log.h"
const char *GL_ErrorString( int err )
{
switch( err )
{
#ifdef GL_STACK_OVERFLOW
case GL_STACK_OVERFLOW:
return "GL_STACK_OVERFLOW";
#endif // GL_STACK_OVERFLOW
#ifdef GL_STACK_UNDERFLOW
case GL_STACK_UNDERFLOW:
return "GL_STACK_UNDERFLOW";
#endif // GL_STACK_UNDERFLOW
case GL_INVALID_ENUM:
return "GL_INVALID_ENUM";
case GL_INVALID_VALUE:
return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION:
return "GL_INVALID_OPERATION";
case GL_OUT_OF_MEMORY:
return "GL_OUT_OF_MEMORY";
default:
return "UNKNOWN ERROR";
}
}
void GL_CheckError()
{
GLenum err;
if ( (err = glGetError()) != GL_NO_ERROR )
Msg( "OpenGL Error: %s", GL_ErrorString( err ) );// Msg("OpenGL Error: %s [%s]\n", GL_ErrorString(err), GL_TargetToString(tex->target));
}
void GL_CheckErrorEx( const char* filename, int line )
{
GLenum err;
if ( (err = glGetError()) != GL_NO_ERROR )
Msg( "OpenGL Error: %s at %s:%i", GL_ErrorString( err ), filename, line );// Msg("OpenGL Error: %s [%s]\n", GL_ErrorString(err), GL_TargetToString(tex->target));
}
void GL_CheckErrorFunction(const char* expression, const char* filename, int line)
{
GLenum err;
if ( (err = glGetError()) != GL_NO_ERROR )
Msg( "OpenGL Error: %s (%s) at %s:%i", expression, GL_ErrorString( err ), filename, line );// Msg("OpenGL Error: %s [%s]\n", GL_ErrorString(err), GL_TargetToString(tex->target));
}
// Conversion functions
#include "render_shared.h"
uint32_t GetGLInternalPF(PixelFormat pf)
{
switch (pf)
{
case PF_UNKNOWN:
return 0;
case PF_R8G8B8:
case PF_R8G8B8F:
return GL_RGB;
case PF_R8G8B8A8:
case PF_R8G8B8A8F:
return GL_RGBA;
}
return 0;
}
uint32_t GetGLTypePF(PixelFormat pf)
{
switch (pf)
{
case PF_UNKNOWN:
return 0;
case PF_R8G8B8:
case PF_R8G8B8A8:
return GL_UNSIGNED_BYTE;
case PF_R8G8B8F:
case PF_R8G8B8A8F:
return GL_FLOAT;
}
return 0;
}
uint32_t GetGLBlendFactor(BlendFactor factor)
{
switch (factor)
{
case BF_ZERO:
return GL_ZERO;
case BF_ONE:
return GL_ONE;
case BF_SRC_COLOR:
return GL_SRC_COLOR;
case BF_ONE_MINUS_SRC_COLOR:
return GL_ONE_MINUS_SRC_COLOR;
case BF_DST_COLOR:
return GL_DST_COLOR;
case BF_ONE_MINUS_DST_COLOR:
return GL_ONE_MINUS_DST_COLOR;
case BF_SRC_ALPHA:
return GL_SRC_ALPHA;
case BF_ONE_MINUS_SRC_ALPHA:
return GL_ONE_MINUS_SRC_ALPHA;
case BF_DST_ALPHA:
return GL_DST_ALPHA;
case BF_ONE_MINUS_DST_ALPHA:
return GL_ONE_MINUS_DST_ALPHA;
case BF_CONSTANT_COLOR:
return GL_CONSTANT_COLOR;
case BF_ONE_MINUS_CONSTANT_COLOR:
return GL_ONE_MINUS_CONSTANT_COLOR;
case BF_CONSTANT_ALPHA:
return GL_CONSTANT_ALPHA;
case BF_ONE_MINUS_CONSTANT_ALPHA:
return GL_ONE_MINUS_CONSTANT_ALPHA;
default:
break;
}
return 0;
}
uint32_t GetGLEquation(BlendEquation equation)
{
switch (equation)
{
case BE_FUNC_ADD:
return GL_FUNC_ADD;
case BE_FUNC_SUBTRACT:
return GL_FUNC_SUBTRACT;
case BE_FUNC_REVERSE_SUBTRACT:
return GL_FUNC_REVERSE_SUBTRACT;
case BE_MIN:
return GL_MIN;
case BE_MAX:
return GL_MAX;
default:
break;
}
return 0;
}
uint32_t GetGLDepthFunc(DepthFunc func)
{
switch (func)
{
case DF_NEVER:
return GL_NEVER;
case DF_LESS:
return GL_LESS;
case DF_EQUAL:
return GL_EQUAL;
case DF_LEQUAL:
return GL_LEQUAL;
case DF_GREATER:
return GL_GREATER;
case DF_NOTEQUAL:
return GL_NOTEQUAL;
case DF_GEQUAL:
return GL_GEQUAL;
case DF_ALWAYS:
return GL_ALWAYS;
default:
break;
}
SDL_assert(0 && "Should be never here");
return 0;
}
int getGlWrap(TextureWrap wrap)
{
int param = 0;
if (wrap == TextureWrap_Repeat)
param = GL_REPEAT;
else if (wrap == TextureWrap_MirroredRepeat)
param = GL_MIRRORED_REPEAT;
else if (wrap == TextureWrap_ClampToEdge)
param = GL_CLAMP_TO_EDGE;
else if (wrap == TextureWrap_ClampToBorder)
param = GL_CLAMP_TO_BORDER;
return param;
}
int getGlTexFilter(TextureFilter filter)
{
int param = 0;
if (filter == TextureFilter_Linear)
param = GL_LINEAR;
else if (filter == TextureFilter_Nearest)
param = GL_NEAREST;
else if (filter == TextureFilter_LinearMipmapLinear)
param = GL_LINEAR_MIPMAP_LINEAR;
else if (filter == TextureFilter_LinearMipmapNearest)
param = GL_LINEAR_MIPMAP_NEAREST;
else if (filter == TextureFilter_NearestMipmapLinear)
param = GL_NEAREST_MIPMAP_LINEAR;
else if (filter == TextureFilter_NearestMipmapNearest)
param = GL_NEAREST_MIPMAP_NEAREST;
return param;
}

18
src/render/gl_shared.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef GL_SHARED_H
#define GL_SHARED_H
#include <SDL3/SDL.h>
#include <glad/glad.h>
void GL_CheckError();
void GL_CheckErrorEx(const char* filename, int line);
void GL_CheckErrorFunction(const char* expression, const char* filename, int line);
#define GL_CHECK_ERROR() \
GL_CheckErrorEx(__FILE__, __LINE__)
#define GL_CHECK_FUNC_ERROR(expr) \
expr; \
GL_CheckErrorFunction(#expr, __FILE__, __LINE__)
#endif // !GL_SHARED_H

103
src/render/gpu_buffer.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include "log.h"
#include "gl_shared.h"
#include "render_shared.h"
#include "gpu_buffer.h"
GLenum BufferTypeToTarget(BufferType type)
{
switch (type)
{
case BT_VERTEX:
return GL_ARRAY_BUFFER;
case BT_INDEX:
return GL_ELEMENT_ARRAY_BUFFER;
default:
break;
};
SDL_assert(0 && "Unknowed buffer type");
return 0;
}
GPUBuffer::GPUBuffer(BufferType type, void* data, size_t size, bool isStream /*= false*/)
{
m_type = type;
m_target = BufferTypeToTarget(m_type);
m_isStream = isStream;
m_size = size;
glGenBuffers(1, &m_buffer);
glBindBuffer(m_target, m_buffer);
glBufferData(m_target, size, data, isStream ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
GL_CHECK_ERROR();
glBindBuffer(m_target, 0);
}
GPUBuffer::~GPUBuffer()
{
glDeleteBuffers(1, &m_buffer);
}
void GPUBuffer::Bind()
{
glBindBuffer(m_target, m_buffer);
}
void* GPUBuffer::MapBuffer(BufferAccess access)
{
GLenum accessGl = 0;
switch (access)
{
case BA_READ_ONLY:
accessGl = GL_READ_ONLY;
break;
case BA_WRITE_ONLY:
accessGl = GL_WRITE_ONLY;
break;
case BA_READ_WRITE:
accessGl = GL_READ_WRITE;
break;
}
Bind();
void* ptr = glMapBuffer(m_target, accessGl);
GL_CHECK_ERROR();
return ptr;
}
void GPUBuffer::UnmapBuffer()
{
Bind();
glUnmapBuffer(m_target);
}
void GPUBuffer::UpdateBuffer(void* data, size_t size)
{
SDL_assert(m_isStream && "Trying to update static buffer.");
// Clear GL errors
glGetError();
// Bind buffer
Bind();
glBufferData(m_target, size, data, GL_DYNAMIC_DRAW);
GL_CHECK_ERROR();
GLenum error = glGetError();
if (error == GL_OUT_OF_MEMORY)
{
Msg("GPUBuffer::UpdateData: Out of memory. Couldn't allocate buffer with %u size", (unsigned)size);
return;
}
m_size = size;
}

32
src/render/gpu_buffer.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef GPU_BUFFER_H
#define GPU_BUFFER_H
#include "render_shared.h"
class RenderDevice;
class GPUBuffer
{
friend class RenderDevice;
public:
~GPUBuffer();
void Bind();
void* MapBuffer(BufferAccess access);
void UnmapBuffer();
void UpdateBuffer(void* data, size_t size);
private:
GPUBuffer(BufferType type, void* data, size_t size, bool isStream = false);
BufferType m_type;
uint32_t m_target;
uint32_t m_buffer;
size_t m_size;
bool m_isStream;
};
#endif // !GPU_BUFFER_H

404
src/render/modelsystem.cpp Normal file
View File

@@ -0,0 +1,404 @@
#include <assert.h>
#include <vector>
#include <string>
#include "ifilesystem.h"
#include "log.h"
#include "render.h"
#include "gpu_buffer.h"
#include "shader.h"
#include "shadersystem.h"
#include "renderdevice.h"
#include "modelsystem.h"
#include "texturesmanager.h"
ModelSystem* g_pModelSystem = nullptr;
static InputLayoutDesc_t g_staticVertexLayout[] = {
{ VERTEXATTR_VEC3, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC3, SHADERSEMANTIC_NORMAL },
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD },
};
static InputLayoutDesc_t g_skinnedVertexLayout[] = {
{ VERTEXATTR_VEC3, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC3, SHADERSEMANTIC_NORMAL },
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD }
};
Shader* g_litShader = nullptr;
std::string getFileNameWithoutExtension(const std::string& filename)
{
size_t lastindex = filename.find_last_of(".");
if (lastindex != std::string::npos) {
return filename.substr(0, lastindex);
}
return filename;
}
ModelSystem::ModelSystem()
{
}
ModelSystem::~ModelSystem()
{
}
void ModelSystem::Shutdown()
{
for (int i = 0; i < m_models.size(); i++)
{
if (m_models[i].model)
{
delete m_models[i].model;
m_models[i].model = nullptr;
}
}
m_models.clear();
}
Model* ModelSystem::LoadModel(const char* filename)
{
auto it = std::find_if(m_models.begin(), m_models.end(), [=](const ModelEntry& entry) { return strcmp(entry.filename, filename) == 0; });
if (it != m_models.end())
{
return it->model;
}
if (!GetFileSystem()->IsExist(filename))
{
Msg("ModelSystem::LoadModel: File '%s' not exist.", filename);
return nullptr;
}
Model* model = new Model();
if (strstr(filename, ".obj"))
{
model->LoadObj(filename);
}
else
{
// Find file extension
size_t stringLength = strlen(filename);
for (int i = stringLength; i > 0; --i)
{
if (filename[i] == '.')
{
stringLength = i;
break;
}
}
const char* fileExtension = &filename[stringLength];
Msg("ModelSystem::LoadModel: Unknowed file format '%s'", filename, fileExtension);
return nullptr;
}
ModelEntry entry = {};
strcpy(entry.filename, filename);
entry.model = model;
m_models.push_back(entry);
Msg("Loaded Model '%s'", filename);
return model;
}
Model::Model()
{
m_data.vb = nullptr;
m_data.ib = nullptr;
m_AlbedoTexture = nullptr;
//m_boundingBox.min = glm::vec3(0.0f);
//m_boundingBox.max = glm::vec3(0.0f);
}
Model::~Model()
{
m_AlbedoTexture = nullptr;
if (m_data.vb)
{
delete m_data.vb;
m_data.vb = nullptr;
}
}
void Model::LoadObj(const char* filename)
{
Msg("Loading OBJ file %s...", filename);
std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
std::vector<glm::vec3> out_vertices;
std::vector<glm::vec2> out_uvs;
std::vector<glm::vec3> out_normals;
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if (strcmp(lineHeader, "v") == 0) {
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9) {
Msg("Model::LoadObj: File can't be read by our simple parser :-( Try exporting with other options");
fclose(file);
return;
}
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
normalIndices.push_back(normalIndex[0]);
normalIndices.push_back(normalIndex[1]);
normalIndices.push_back(normalIndex[2]);
}
else {
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
// For each vertex of each triangle
for (unsigned int i = 0; i < vertexIndices.size(); i++) {
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
// Put the attributes in buffers
out_vertices.push_back(vertex);
out_uvs.push_back(uv);
out_normals.push_back(normal);
}
fclose(file);
// Combine in to the one array
std::vector<StaticMeshVertex> vertices;
for (unsigned int i = 0; i < vertexIndices.size(); i++)
{
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
StaticMeshVertex vtx = {};
vtx.position = vertex;
vtx.normal = normal;
vtx.texcoord = uv;
vertices.push_back(vtx);
//m_boundingBox.min = glm::min(m_boundingBox.min, vertex);
//m_boundingBox.max = glm::max(m_boundingBox.max, vertex);
}
m_Vertices = vertices;
m_data.vb = g_pRenderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
m_data.vbcount = vertices.size();
std::string mtlfilename = getFileNameWithoutExtension(filename);
mtlfilename += ".mtl";
LoadMtl(mtlfilename.c_str());
}
void Model::LoadMtl(const char* filename)
{
Msg("Loading MTL file %s...", filename);
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
if (strcmp(lineHeader, "map_Kd") == 0) {
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
const char* textureFilename = stupidBuffer + 1;
m_AlbedoTexture = g_pTexturesManager->LoadTexture2D(textureFilename, true);
}
//if (strcmp(lineHeader, "v") == 0) {
// glm::vec3 vertex;
// fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
// temp_vertices.push_back(vertex);
//}
//else {
// // Probably a comment, eat up the rest of the line
// char stupidBuffer[1000];
// fgets(stupidBuffer, 1000, file);
//}
}
fclose(file);
}
void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
{
if (!g_litShader)
{
g_litShader = g_pShaderSystem->CreateShader("lit_generic", "data/shaders/lit_generic.vs", "data/shaders/lit_generic.ps",
g_staticVertexLayout, sizeof(g_staticVertexLayout) / sizeof(g_staticVertexLayout[0]));
}
glFrontFace(GL_CCW);
glDepthFunc(GL_LESS);
g_pRenderDevice->SetCullFace(true);
g_pRenderDevice->SetDepthTest(true);
g_pRenderDevice->SetDepthWrite(true);
if (isTransparent)
{
// Enable blending
g_pRenderDevice->SetBlending(true);
g_pRenderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f);
g_pShaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
else
{
g_pRenderDevice->SetBlending(false);
//glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f);
//g_pShaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
g_pRenderDevice->SetVerticesBuffer(m_data.vb);
g_pShaderSystem->SetShader(g_litShader);
g_pShaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &model[0]);
//static float test = 0.0f;
//test += g_systemTimer->GetDelta() * 6.0f;
//glm::mat4 model = glm::mat4(1.0f);
//int32_t x = 0, y = 0;
//g_inputSystem->GetMousePosition(&x, &y);
//
//glm::mat4 model = glm::mat4(1.0f);
//model = glm::rotate(model, test, glm::vec3(0.0f, 1.0f, 0.0f));
//
//float realY = (float)g_renderView.height - (float)y - 1;
//
//glm::vec4 viewport = glm::vec4(0.0f, 0.0f, (float)g_renderView.width, (float)g_renderView.height);
//glm::vec3 pos = glm::unProject(
// glm::vec3((float)x, realY, 0.0f),
// model,
// g_renderView.proj,
// viewport);
//
//pos *= 50.0f;
//
//model = glm::translate(model, pos);
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_pRender->GetProjectionMatrix() * g_pRender->GetViewMatrix() * model;
g_pShaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_pTexturesManager->SetTexture(0, m_AlbedoTexture);
g_pShaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_pRenderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
#if 0
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_renderView.proj * g_renderView.view * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_pTexturesManager->SetTexture(0, m_AlbedoTexture);
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
BoundingBox bbox = m_boundingBox;
TransformBoundingBox(bbox, model);
g_pDebugRender->DrawBoundingBox(bbox, glm::vec3(1.0f));
#endif
}
void ReleaseModelData(ModelData_t& data)
{
if (data.ib)
{
delete data.ib;
data.ib = nullptr;
}
if (data.vb)
{
delete data.vb;
data.vb = nullptr;
}
}

70
src/render/modelsystem.h Normal file
View File

@@ -0,0 +1,70 @@
#ifndef MODELMANAGER_H
#define MODELMANAGER_H
#include <vector>
#include "render_shared.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class GPUBuffer;
class Texture2D;
struct ModelData_t
{
GPUBuffer* vb;
GPUBuffer* ib;
uint32_t vbcount;
uint32_t ibcount;
};
void ReleaseModelData(ModelData_t& data);
class Render;
class Model
{
friend class Render;
public:
Model();
~Model();
void LoadObj(const char* filename);
void LoadMtl(const char* filename);
void Draw(const glm::mat4& model, bool isTransparent = false);
//BoundingBox GetBoundingBox() { return m_boundingBox; }
private:
std::vector<StaticMeshVertex> m_Vertices;
ModelData_t m_data;
//BoundingBox m_boundingBox;
Texture2D* m_AlbedoTexture;
};
class ModelSystem
{
public:
ModelSystem();
~ModelSystem();
void Shutdown();
Model* LoadModel(const char* filename);
private:
struct ModelEntry
{
char filename[260];
Model* model;
};
std::vector< ModelEntry > m_models;
};
extern ModelSystem* g_pModelSystem;
#endif // !MODELMANAGER_H

266
src/render/render.cpp Normal file
View File

@@ -0,0 +1,266 @@
#include "core.h"
#include "log.h"
#include "render.h"
#include "renderdevice.h"
#include "texturesmanager.h"
#include "shadersystem.h"
#include "modelsystem.h"
#include "debugrender.h"
#include "ifilesystem.h"
#include <pugixml.hpp>
static GLuint g_VAO = 0;
// TEMP
glm::vec3 g_viewOrigin;
glm::vec3 g_viewOrient;
#ifdef GL_DEBUG_OUTPUT
#define GL_DEBUG_OUTPUT 0x92E0
#endif // GL_DEBUG_OUTPUT
#ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
#endif // !GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
#ifndef GL_DEBUG_TYPE_ERROR_ARB
#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
#endif // !GL_DEBUG_TYPE_ERROR_ARB
#ifndef GL_ARB_debug_output
#define GL_ARB_debug_output 1
typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled);
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf);
PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void* userParam);
PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
typedef GLuint(APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog);
PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
#endif
void APIENTRY GL_DebugOutput(GLenum source,
GLenum type,
unsigned int id,
GLenum severity,
GLsizei length,
const char* message,
const void* userParam)
{
// Nvidia spam too much about filenameBuffer mapping
if (type == 0x8251)
return;
Msg("OpenGL: %stype = 0x%x, severity = 0x%x, message = %s\n",
(type == GL_DEBUG_TYPE_ERROR_ARB ? "** GL ERROR ** " : ""),
type, severity, message);
if (type == GL_DEBUG_TYPE_ERROR_ARB)
{
bool debug = true;
}
}
Render* g_pRender = nullptr;
Render::Render() :
m_pWindow(nullptr),
m_pGLContext(nullptr),
m_pStretchedPicVBuf(nullptr),
m_sceneModel(nullptr),
m_bUsingVAO(false)
{
m_ViewMatrix = glm::identity<glm::mat4>();
m_ProjectionMatrix = glm::identity<glm::mat4>();
}
Render::~Render()
{
}
void Render::Init(SDL_Window* pWindow)
{
m_pWindow = pWindow;
SDL_assert(m_pWindow);
// Create OpenGL context
m_pGLContext = SDL_GL_CreateContext(m_pWindow);
SDL_GL_MakeCurrent(m_pWindow, m_pGLContext);
gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress);
if (GLVersion.major == 0 || GLVersion.minor == 0)
{
Core::Error("Failed to load OpenGL");
}
// Core profile probably, should use VAO
if (GLVersion.major >= 3 && GLVersion.minor >= 1)
m_bUsingVAO = true;
Msg("%s", (const char*)glGetString(GL_VENDOR));
Msg("%s", (const char*)glGetString(GL_RENDERER));
Msg("OpenGL ver. %s", (const char*)glGetString(GL_VERSION));
Msg("Context created with OpenGL version %d.%d", GLVersion.major, GLVersion.minor);
// Reset OpenGL error stack
glGetError();
// Load extension
glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
// Enable debug output
if (glDebugMessageCallbackARB)
{
Msg("...found GL_ARB_debug_output");
//glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageCallbackARB(GL_DebugOutput, NULL);
}
// Create render device
g_pRenderDevice = new RenderDevice();
// Create texture manager
g_pTexturesManager = new TexturesManager();
g_pTexturesManager->Init();
// Create shader system
g_pShaderSystem = new ShaderSystem();
g_pShaderSystem->Init();
// Create model system
g_pModelSystem = new ModelSystem();
// Create debug render
g_pDebugRender = new DebugRender();
g_pDebugRender->Initialize();
// Create stretched picture filenameBuffer
m_pStretchedPicVBuf = g_pRenderDevice->CreateVertexBuffer(nullptr, MAX_STRETCH_VX, true);
// Core profile require Vertex Array Object to render
if (m_bUsingVAO)
{
// Create global vertex array
glGenVertexArrays(1, &g_VAO);
glBindVertexArray(g_VAO);
}
}
void Render::Shutdown()
{
if (m_bUsingVAO)
{
glBindVertexArray(0);
glDeleteVertexArrays(1, &g_VAO);
}
delete m_pStretchedPicVBuf;
m_pStretchedPicVBuf = nullptr;
g_pDebugRender->Shutdown();
delete g_pDebugRender;
g_pDebugRender = nullptr;
g_pModelSystem->Shutdown();
delete g_pModelSystem;
g_pModelSystem = nullptr;
g_pShaderSystem->Shutdown();
delete g_pShaderSystem;
g_pShaderSystem = nullptr;
g_pTexturesManager->Shutdown();
delete g_pTexturesManager;
g_pTexturesManager = nullptr;
delete g_pRenderDevice;
g_pRenderDevice = nullptr;
// Destroy OpenGL context
SDL_GL_MakeCurrent(nullptr, nullptr);
SDL_GL_DestroyContext(m_pGLContext);
m_pGLContext = nullptr;
}
void Render::RenderScene()
{
if (m_sceneModel) {
static glm::mat4 s_identity = glm::mat4(1.0f);
m_sceneModel->Draw(s_identity);
}
g_pDebugRender->RenderFrame();
}
void Render::Present(bool vsync)
{
SDL_GL_SwapWindow(m_pWindow);
}
void Render::ResetStates()
{
g_pRenderDevice->SetDepthTest(true);
g_pRenderDevice->SetDepthWrite(true);
g_pRenderDevice->SetStencilTest(false);
g_pRenderDevice->SetScissorTest(false);
g_pRenderDevice->SetCullFace(false);
g_pRenderDevice->SetBlending(false);
}
void Render::SetViewMatrix(const glm::mat4& matView)
{
m_ViewMatrix = matView;
}
void Render::SetProjectionMatrix(const glm::mat4& matProjection)
{
m_ProjectionMatrix = matProjection;
}
void Render::LoadSceneXML(const char* filename)
{
char filenameBuffer[kMaxPathLength];
snprintf(filenameBuffer, kMaxPathLength, "data/levels/%s/%s.xml", filename, filename);
FileHandle_t file = GetFileSystem()->OpenFile(filenameBuffer, "rb");
SDL_assert_always(file != kInvalidFileHandleValue);
size_t length = GetFileSystem()->GetFileLength(file);
char* filedata = new char[length + 1];
GetFileSystem()->ReadFile(file, filedata, length);
filedata[length] = '\0';
GetFileSystem()->CloseFile(file);
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer(filedata, length);
delete[] filedata;
if (!result) {
Core::Error("Render::LoadSceneXML: Error while reading level description file '%s'\nError: %s:%i",
filenameBuffer, result.description(), result.offset);
}
pugi::xml_node root = doc.document_element();
const char* scenefilename = root.child("SceneFile").attribute("filename").value();
sprintf(filenameBuffer, "data/levels/%s/%s", filename, scenefilename);
if (!GetFileSystem()->IsExist(filenameBuffer)) {
Core::Error("SceneManager::LoadScene: scene file '%s' doesnt exist", scenefilename);
}
m_sceneFilename = filenameBuffer;
m_sceneModel = g_pModelSystem->LoadModel(m_sceneFilename.c_str());
}
//IRender* GetRender()
//{
// return g_pRender;
//}

58
src/render/render.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef RENDER_H
#define RENDER_H
#include "gl_shared.h"
#include "render_shared.h"
#include <string>
class GPUBuffer;
class Model;
class Render
{
public:
Render();
~Render();
void Init(SDL_Window* pWindow);
void Shutdown();
void RenderScene();
void Present(bool vsync = false);
void ResetStates();
void SetViewMatrix(const glm::mat4& matView);
void SetProjectionMatrix(const glm::mat4& matProjection);
inline const glm::mat4& GetViewMatrix() { return m_ViewMatrix; }
inline const glm::mat4& GetProjectionMatrix() { return m_ProjectionMatrix; }
void LoadSceneXML(const char* filename);
private:
glm::mat4 m_ViewMatrix;
glm::mat4 m_ProjectionMatrix;
SDL_Window* m_pWindow;
SDL_GLContext m_pGLContext;
GPUBuffer* m_pStretchedPicVBuf;
std::string m_sceneFilename;
std::string m_sceneName;
Model* m_sceneModel;
bool m_bUsingVAO;
};
extern Render* g_pRender;
// TEMP
extern glm::vec3 g_viewOrigin;
extern glm::vec3 g_viewOrient;
#endif // !RENDER_H

240
src/render/render_shared.h Normal file
View File

@@ -0,0 +1,240 @@
// Shared header for render subsystem
#ifndef RENDER_SHARED_H
#define RENDER_SHARED_H
#include <stdint.h>
#include <glm/glm.hpp>
typedef uint32_t index_t;
enum BufferType
{
BT_VERTEX,
BT_INDEX,
BT_MAX
};
enum BufferAccess
{
BA_READ_ONLY,
BA_WRITE_ONLY,
BA_READ_WRITE,
BA_MAX
};
// texture format
enum PixelFormat
{
PF_UNKNOWN,
PF_R8G8B8,
PF_R8G8B8A8,
PF_R8G8B8F,
PF_R8G8B8A8F,
// Depth formats
PF_DEPTH32F
};
// Blending functions
enum BlendFactor
{
BF_ZERO,
BF_ONE,
BF_SRC_COLOR,
BF_ONE_MINUS_SRC_COLOR,
BF_DST_COLOR,
BF_ONE_MINUS_DST_COLOR,
BF_SRC_ALPHA,
BF_ONE_MINUS_SRC_ALPHA,
BF_DST_ALPHA,
BF_ONE_MINUS_DST_ALPHA,
BF_CONSTANT_COLOR,
BF_ONE_MINUS_CONSTANT_COLOR,
BF_CONSTANT_ALPHA,
BF_ONE_MINUS_CONSTANT_ALPHA
};
enum BlendEquation
{
BE_FUNC_ADD,
BE_FUNC_SUBTRACT,
BE_FUNC_REVERSE_SUBTRACT,
BE_MIN,
BE_MAX
};
enum DepthFunc
{
DF_NEVER, // Never passes.
DF_LESS, // Passes if the incoming depth value is less than the stored depth value.
DF_EQUAL, // Passes if the incoming depth value is equal to the stored depth value.
DF_LEQUAL, // Passes if the incoming depth value is less than or equal to the stored depth value.
DF_GREATER, // Passes if the incoming depth value is greater than the stored depth value.
DF_NOTEQUAL, // Passes if the incoming depth value is not equal to the stored depth value.
DF_GEQUAL, // Passes if the incoming depth value is greater than or equal to the stored depth value.
DF_ALWAYS, // Always passes.
DF_MAX
};
enum TextureWrap
{
TextureWrap_Repeat,
TextureWrap_MirroredRepeat,
TextureWrap_ClampToEdge,
TextureWrap_ClampToBorder
};
enum TextureFilter
{
TextureFilter_Nearest,
TextureFilter_Linear,
TextureFilter_NearestMipmapNearest,
TextureFilter_LinearMipmapNearest,
TextureFilter_NearestMipmapLinear,
TextureFilter_LinearMipmapLinear
};
enum TextureSurfaceType
{
TST_COLOR = 1 << 0,
TST_DEPTH = 1 << 1,
TST_STENCIL = 1 << 2,
};
enum PrimitiveType
{
PT_POINTS,
PT_LINES,
PT_TRIANGLES
};
// pixel format convertion
uint32_t GetGLPF(PixelFormat pf);
uint32_t GetGLInternalPF(PixelFormat pf);
uint32_t GetGLTypePF(PixelFormat pf);
// Wrapping and Filter convertion
int getGlWrap(TextureWrap wrap);
int getGlTexFilter(TextureFilter filter);
uint32_t GetGLDepthFunc(DepthFunc func);
// Blending factor convertion
uint32_t GetGLBlendFactor(BlendFactor factor);
// Blending equation convertion
uint32_t GetGLEquation(BlendEquation equation);
struct Viewport
{
int x;
int y;
int width;
int height;
};
// Base structure for render view (view and projection matrices, viewport settings)
struct View
{
//glm::mat4 view;
//glm::mat4 proj;
int x, y;
int width, height;
float fov;
bool ortho;
};
// Stretched picture vertex
struct StretchedVertex
{
glm::vec3 position;
glm::vec2 texcoord;
glm::vec4 color;
};
#define MAX_STRETCH_VX 12 * sizeof(StretchedVertex)
const int SHADERUNIFORM_MAX_COUNT = 16;
const int INPUT_LAYOUT_MAX_COUNT = 8;
enum VertexAttribute_t {
VERTEXATTR_VEC2,
VERTEXATTR_VEC3,
VERTEXATTR_VEC4,
VERTEXATTR_UINT,
VERTEXATTR_MAX
};
enum ShaderSemantic_t {
SHADERSEMANTIC_POSITION,
SHADERSEMANTIC_COLOR,
SHADERSEMANTIC_TEXCOORD,
SHADERSEMANTIC_TEXCOORD0,
SHADERSEMANTIC_TEXCOORD1,
SHADERSEMANTIC_NORMAL,
SHADERSEMANTIC_TANGENT,
SHADERSEMANTIC_BITANGENT,
SHADERSEMANTIC_BONEIDS,
SHADERSEMANTIC_WEIGHTS,
SHADERSEMANTIC_MAX
};
enum ShaderUniformType_t {
SHADERUNIFORM_FLOAT,
SHADERUNIFORM_VEC2,
SHADERUNIFORM_VEC3,
SHADERUNIFORM_VEC4,
SHADERUNIFORM_MAT4,
SHADERUNIFORM_MAX
};
enum ShaderUniform_t
{
UNIFORM_MODEL_MATRIX,
UNIFORM_VIEW_MATRIX,
UNIFORM_PROJ_MATRIX,
UNIFORM_MVP_MATRIX,
UNIFORM_CUSTOM_COLOR,
UNIFORM_SUN_DIRECTION,
UNIFORM_SUN_COLOR,
UNIFORM_SUN_AMBIENT,
UNIFORM_MAX,
};
enum ShaderSamplers_t
{
SAMPLER_ALBEDO,
SAMPLER_NORMAL,
SAMPLER_LIGHTMAP,
SAMPLER_MAX
};
struct InputLayoutDesc_t {
VertexAttribute_t attribute;
ShaderSemantic_t semantic;
};
struct ShaderUniformDesc_t {
ShaderUniformType_t type;
const char* name;
size_t size;
};
struct StaticMeshVertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 texcoord;
};
#endif

162
src/render/renderdevice.cpp Normal file
View File

@@ -0,0 +1,162 @@
#include <assert.h>
#include <stdio.h>
// OpenGL
#include "gl_shared.h"
#include "gpu_buffer.h"
#include "renderdevice.h"
static GLenum g_glPrimitiveMode[PT_TRIANGLES + 1] = {
GL_POINTS,
GL_LINES,
GL_TRIANGLES
};
// The render device instance.
RenderDevice* g_pRenderDevice = nullptr;
RenderDevice::RenderDevice()
{
m_activeVB = nullptr;
m_activeIB = nullptr;
m_blending = false;
m_activeReadRT = nullptr;
m_activeWriteRT = nullptr;
}
RenderDevice::~RenderDevice()
{
}
GPUBuffer* RenderDevice::CreateVertexBuffer(void* data, size_t size, bool isStream)
{
return new GPUBuffer(BT_VERTEX, data, size, isStream);
}
GPUBuffer* RenderDevice::CreateIndexBuffer(void* data, size_t size, bool isStream)
{
return new GPUBuffer(BT_INDEX, data, size, isStream);
}
void RenderDevice::SetVerticesBuffer(GPUBuffer* buffer)
{
if (buffer) {
if (m_activeVB != buffer) {
m_activeVB = buffer;
m_activeVB->Bind();
}
} else { // unbind buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void RenderDevice::SetIndicesBuffer(GPUBuffer* buffer)
{
if (buffer) {
if (m_activeIB != buffer) {
m_activeIB = buffer;
m_activeIB->Bind();
}
} else { // unbind buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
void RenderDevice::SetDepthTest(bool enable)
{
enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
}
void RenderDevice::SetDepthWrite(bool enable)
{
glDepthMask(enable ? GL_TRUE : GL_FALSE);
}
void RenderDevice::SetStencilTest(bool enable)
{
enable ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST);
}
void RenderDevice::SetScissorTest(bool enable)
{
enable ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
}
void RenderDevice::SetCullFace(bool enable)
{
enable ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
}
void RenderDevice::SetBlending(bool value)
{
if (m_blending != value) {
m_blending = value;
value ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
}
}
void RenderDevice::SetBlendingFunction(BlendFactor srcFactor, BlendFactor destFactor)
{
// Switch state if one of two blending factors was changed
if (srcFactor != m_srcBlendFactor || destFactor != m_destBlendFactor)
{
m_srcBlendFactor = srcFactor;
m_destBlendFactor = destFactor;
// push to gl state
glBlendFunc(GetGLBlendFactor(srcFactor), GetGLBlendFactor(destFactor));
}
}
void RenderDevice::SetBlendFuncSeparate(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha)
{
glBlendFuncSeparate(GetGLBlendFactor(srcRGB), GetGLBlendFactor(dstRGB),
GetGLBlendFactor(srcAlpha), GetGLBlendFactor(dstAlpha));
}
void RenderDevice::SetBlendEquation(BlendEquation equation)
{
glBlendEquation(GetGLEquation(equation));
}
void RenderDevice::SetViewport(int x, int y, int w, int h)
{
glViewport(x, y, w, h);
}
void RenderDevice::Clear(uint32_t surfaces, float r, float g, float b, float a, float z, uint32_t stencil)
{
GLenum flags = 0;
if (surfaces & TST_COLOR)
{
flags |= GL_COLOR_BUFFER_BIT;
glClearColor(r, g, b, a);
}
if (surfaces & TST_DEPTH)
{
flags |= GL_DEPTH_BUFFER_BIT;
glClearDepth(z);
}
if (surfaces & TST_STENCIL)
{
flags |= GL_STENCIL_BUFFER_BIT;
glClearStencil((GLint)stencil);
}
glClear(flags);
}
void RenderDevice::DrawArrays(PrimitiveType primType, uint32_t startOf, size_t verticesCount)
{
glDrawArrays(g_glPrimitiveMode[primType], startOf, GLsizei(verticesCount));
}
void RenderDevice::DrawElements(PrimitiveType primType, size_t elementsCount, bool is16bitIndices)
{
glDrawElements(g_glPrimitiveMode[primType], GLsizei(elementsCount), is16bitIndices ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, NULL);
}

Some files were not shown because too many files have changed in this diff Show More