first commit

This commit is contained in:
Kirill Yurkin 2024-06-10 12:48:14 +03:00
commit d54c9805b3
1398 changed files with 739400 additions and 0 deletions

View File

@ -0,0 +1,15 @@
game_object = {
{ PROPERTY_STRING, "name", "Name of the object." } ,
{ PROPERTY_STRING_NOT_EDITABLE, "classname", "Clasname." },
{ PROPERTY_VEC3, "position", "World position." },
{ PROPERTY_VEC3, "rotation", "World rotation." },
{ PROPERTY_VEC3, "scale", "World scale." },
}
editor_entities = {
{ game_object, "game_object" },
}

View File

@ -0,0 +1,24 @@
BeginEntity test_entity
ClassName Player
Position 0.0 0.0 0.0
Rotation 0.0 0.0 0.0
EndEntity
# Water
BeginEntity water_test
ClassName GameObject
Tag Water
Position 0.0 -0.1 0.0
Rotation 0.0 0.0 0.0
Visual content/test/water_test.obj
EndEntity
#############
# Enemies ...
BeginEntity test_enemy
ClassName GameObject
Position -2.70 0.00 3.28
Rotation 0.0 0.0 0.0
Visual content/test/ship.obj
EndEntity

View File

@ -0,0 +1,10 @@
#version 330 core
in vec3 v_color;
out vec4 fragColor;
void main()
{
fragColor = vec4(v_color, 1.0);
}

View File

@ -0,0 +1,15 @@
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec3 v_color;
uniform mat4 u_modelViewProjection;
void main()
{
gl_Position = u_modelViewProjection * vec4(position, 1.0f);
v_color = color;
}

View File

@ -0,0 +1,15 @@
#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_normal, 1.0 );
}

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);
}

View File

@ -0,0 +1,15 @@
#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_normal, 1.0 );
}

View File

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

View File

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

11
content/shaders/ui_tex.ps Normal file
View File

@ -0,0 +1,11 @@
#version 120
varying vec2 v_texcoord;
varying vec4 v_color;
uniform sampler2D u_texture;
void main() {
vec4 tex = texture2D( u_texture, v_texcoord );
gl_FragColor = v_color * tex;
}

BIN
content/test/ship.blend Normal file

Binary file not shown.

BIN
content/test/ship.blend1 Normal file

Binary file not shown.

13
content/test/ship.mtl Normal file
View File

@ -0,0 +1,13 @@
# Blender 4.0.2 MTL File: 'ship.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 content/test/uvgrid.png
map_Kd content/test/tetrad.png

478
content/test/ship.obj Normal file
View File

@ -0,0 +1,478 @@
# Blender 4.0.2
# www.blender.org
mtllib ship.mtl
o ship
v -0.206022 0.561873 -0.011206
v -0.119716 0.560522 0.008077
v -0.004751 0.563370 -0.023105
v 0.055282 0.559558 -0.007712
v 0.145744 0.561427 0.010017
v 0.213930 0.562807 -0.008303
v -0.161451 0.562805 0.002926
v 0.003766 0.534670 -0.026896
v -0.203839 0.511860 -0.018421
v -0.162010 0.485302 -0.011563
v 0.213836 0.478134 -0.020207
v -0.045692 0.468001 -0.022078
v 0.082312 0.521381 -0.023491
v 0.044539 0.402209 -0.003451
v -0.205619 0.398058 0.004964
v -0.169031 0.381641 0.021240
v -0.068870 0.339942 0.010303
v 0.009781 0.363531 -0.014819
v 0.096103 0.397493 0.019756
v 0.217964 0.399421 0.006125
v -0.204553 0.325254 0.003283
v -0.156494 0.281751 0.003940
v 0.020743 0.317356 -0.021851
v 0.129477 0.339985 0.026030
v 0.220711 0.306984 0.005506
v -0.076777 0.258270 -0.021832
v -0.029258 0.288322 -0.010229
v 0.066269 0.241267 -0.016551
v 0.146799 0.185187 -0.011010
v -0.154116 0.185233 -0.016433
v -0.031760 0.211335 -0.023012
v 0.004891 0.201931 -0.031796
v 0.212805 0.190185 -0.016808
v -0.204504 0.199190 -0.017579
v -0.095264 0.184441 -0.020341
v 0.046662 0.144795 -0.003573
v -0.204608 0.144531 -0.017393
v -0.156809 0.146968 0.008014
v -0.079562 0.145971 -0.007068
v -0.036451 0.146321 0.007217
v 0.004779 0.135828 -0.015514
v 0.172277 0.145146 0.007740
v 0.214538 0.144846 0.002540
v -0.167417 0.048338 0.229981
v -0.169698 0.120416 0.169698
v -0.176530 0.046931 -0.176530
v 0.176530 0.046931 0.176530
v 0.169698 0.120416 0.169698
v 0.167417 0.048338 -0.229981
v 0.149213 0.119405 -0.270229
v 0.146055 0.120416 0.270657
v -0.149213 0.119405 0.270229
v -0.146055 0.120416 -0.270657
v -0.149420 0.054673 -0.264796
v 0.149420 0.054673 0.264796
v -0.002886 0.116702 0.423249
v 0.000000 0.120416 -0.416631
v 0.000000 0.046931 -0.416631
v -0.169698 0.120416 -0.169698
v 0.169698 0.120416 -0.169698
v 0.137782 0.120416 -0.244473
v 0.134751 0.120416 0.249709
v -0.134751 0.120416 -0.249709
v -0.137782 0.120416 0.244473
v 0.000000 0.116627 0.384384
v 0.000000 0.116627 -0.384384
v 0.148794 0.101470 -0.232115
v -0.148794 0.101470 0.232115
v 0.154047 0.101470 0.222255
v -0.154047 0.101470 -0.222255
v -0.066114 -0.165458 -0.222948
v -0.068212 -0.165409 0.217791
v 0.068212 -0.165409 -0.217791
v 0.066114 -0.165458 0.222948
v -0.003313 -0.164842 0.347649
v 0.003313 -0.164842 -0.347649
v -0.008288 0.574476 -0.002763
v -0.008288 0.091646 0.002763
v 0.008288 0.091646 -0.002763
v 0.008288 0.574476 0.002763
v -0.299244 0.509855 -0.002763
v 0.299244 0.509855 0.002763
v 0.299244 0.526432 -0.002763
v -0.299244 0.526432 0.002763
v -0.299244 0.185914 -0.002763
v 0.299244 0.185914 0.002763
v 0.299244 0.202490 -0.002763
v -0.299244 0.202490 0.002763
vn 0.2960 0.1490 -0.9435
vn 0.1042 0.2427 -0.9645
vn 0.2031 0.0498 -0.9779
vn 0.1526 0.4199 -0.8946
vn 0.0654 0.1817 -0.9812
vn 0.0049 0.0973 -0.9952
vn 0.0234 -0.0659 -0.9976
vn 0.2961 -0.1736 -0.9392
vn 0.4145 -0.2013 -0.8875
vn 0.0536 0.0203 -0.9984
vn 0.1127 -0.0811 -0.9903
vn 0.2245 0.1521 -0.9625
vn -0.0913 0.1252 -0.9879
vn -0.1088 -0.0643 -0.9920
vn -0.1416 -0.1919 -0.9711
vn 0.0753 0.0706 -0.9947
vn 0.2214 -0.2971 -0.9288
vn -0.1656 0.1289 -0.9777
vn 0.1741 0.0710 -0.9822
vn 0.0013 0.1961 -0.9806
vn 0.0693 0.1131 -0.9912
vn -0.2896 0.0434 -0.9562
vn -0.0926 0.1833 -0.9787
vn 0.0158 -0.1219 -0.9924
vn -0.0801 -0.1775 -0.9809
vn -0.0108 -0.0845 -0.9964
vn -0.0855 -0.0924 -0.9920
vn 0.1983 -0.2123 -0.9569
vn 0.1618 -0.5128 -0.8431
vn 0.0552 -0.1308 -0.9899
vn 0.0491 -0.3777 -0.9246
vn -0.1157 -0.2374 -0.9645
vn -0.0945 -0.1010 -0.9904
vn -0.0217 -0.4108 -0.9115
vn -0.1150 -0.3936 -0.9121
vn 0.5507 -0.3000 -0.7789
vn 0.9705 0.1358 -0.1991
vn -0.0000 1.0000 -0.0000
vn -0.9705 0.1358 0.1991
vn -0.5507 -0.3000 0.7789
vn -0.8038 -0.3896 -0.4495
vn -0.7124 0.0428 0.7004
vn 0.8641 -0.3331 0.3774
vn 0.7157 -0.0256 0.6979
vn 0.7124 0.0428 -0.7004
vn -0.8641 -0.3331 -0.3774
vn -0.0031 0.9954 -0.0960
vn 0.0031 0.9954 0.0960
vn 0.8860 -0.2683 -0.3782
vn -0.8860 -0.2683 0.3782
vn 0.8038 -0.3896 0.4495
vn 0.0708 0.9051 -0.4193
vn -0.0546 0.1148 -0.9919
vn -0.1125 0.7364 -0.6671
vn 0.0035 0.3344 -0.9424
vn 0.0104 -0.1386 -0.9903
vn 0.0321 0.0517 -0.9981
vn 0.2213 -0.2523 -0.9420
vn -0.0870 -0.3704 -0.9248
vn -0.9957 0.0926 -0.0000
vn 0.9957 0.0926 -0.0000
vn 0.0183 0.9998 -0.0099
vn -0.1072 0.9874 0.1160
vn 0.9732 0.0295 0.2279
vn -0.9732 0.0295 -0.2279
vn 0.8866 -0.1307 -0.4437
vn -0.0183 0.9998 0.0099
vn -0.7069 -0.0000 -0.7073
vn -0.6844 0.7291 0.0079
vn 0.8713 -0.3871 0.3016
vn 0.7004 -0.0000 -0.7138
vn 0.6683 -0.1939 0.7182
vn 0.0190 0.9998 -0.0005
vn 0.0450 0.9988 -0.0192
vn -0.0450 0.9988 0.0192
vn 0.6844 0.7291 -0.0079
vn 0.6820 0.2827 0.6745
vn -0.6820 0.2827 -0.6745
vn -0.0004 -1.0000 -0.0001
vn 0.8876 -0.4605 0.0042
vn -0.0005 -1.0000 0.0046
vn 0.0005 -1.0000 -0.0046
vn -0.6993 -0.2313 -0.6764
vn -0.8876 -0.4605 -0.0042
vn -0.8713 -0.3871 -0.3016
vn -0.8472 -0.3191 0.4248
vn -0.3162 0.0109 -0.9486
vn 0.3162 0.0109 0.9486
vn -0.0088 -0.3162 -0.9486
vn -0.0088 0.3162 0.9486
vn -0.9997 -0.0129 0.0225
vn 0.9997 -0.0129 -0.0225
vn 0.1159 0.9865 0.1159
vn 0.0085 0.9993 -0.0354
vn 0.9524 0.1148 0.2824
vn -0.9524 0.1148 -0.2824
vn 0.7382 -0.3193 -0.5943
vn -0.0291 0.9996 -0.0041
vn -0.7132 -0.0259 -0.7005
vn -0.7710 0.6369 -0.0000
vn -0.0085 0.9993 0.0354
vn 0.7710 0.6369 -0.0000
vn 0.0004 -1.0000 0.0001
vn 0.9064 -0.4219 -0.0218
vn -0.9064 -0.4219 0.0218
vn -0.7124 -0.1810 0.6780
vn 0.3162 -0.0109 -0.9486
vn -0.3162 -0.0109 0.9486
vn 0.0088 0.3162 -0.9486
vn 0.0088 -0.3162 0.9486
vt 0.249493 0.888699
vt 0.300679 0.888352
vt 0.252663 0.828817
vt 0.564031 0.887391
vt 0.604969 0.823879
vt 0.501539 0.840125
vt 0.305402 0.774472
vt 0.250800 0.691603
vt 0.555279 0.692751
vt 0.502804 0.650588
vt 0.298686 0.672311
vt 0.250764 0.604810
vt 0.468563 0.568169
vt 0.443762 0.782837
vt 0.758306 0.691625
vt 0.655221 0.628090
vt 0.614851 0.694249
vt 0.762260 0.582675
vt 0.587125 0.509568
vt 0.309337 0.543049
vt 0.251234 0.453628
vt 0.408695 0.616702
vt 0.402239 0.524216
vt 0.642557 0.450784
vt 0.379100 0.438470
vt 0.502499 0.456641
vt 0.452134 0.468589
vt 0.553067 0.388907
vt 0.308797 0.392191
vt 0.302135 0.439353
vt 0.401258 0.389574
vt 0.502475 0.377401
vt 0.752623 0.441086
vt 0.703496 0.388274
vt 0.754208 0.388223
vt 0.768893 0.270715
vt 0.754316 0.015814
vt 0.813716 0.356142
vt 0.706982 0.358905
vt 0.293085 0.698783
vt 0.338306 0.791985
vt 0.325015 0.816889
vt 0.221363 0.270715
vt 0.176540 0.356142
vt 0.283275 0.358905
vt 0.235941 0.015814
vt 0.810847 0.270715
vt 0.916090 0.015814
vt 0.762219 0.015814
vt 0.700395 0.291473
vt 0.655175 0.198272
vt 0.668466 0.173368
vt 0.496740 0.354358
vt 0.591654 0.336168
vt 0.591654 0.358905
vt 0.690585 0.358905
vt 0.757323 0.336168
vt 0.791985 0.358905
vt 0.599616 0.358905
vt 0.496740 0.354447
vt 0.599616 0.270715
vt 0.401827 0.336168
vt 0.401827 0.358905
vt 0.299672 0.358905
vt 0.232934 0.336168
vt 0.198272 0.358905
vt 0.669690 0.232934
vt 0.329763 0.221671
vt 0.496740 0.033828
vt 0.323790 0.757323
vt 0.663718 0.768586
vt 0.496740 0.956429
vt 0.203684 0.358905
vt 0.221671 0.336168
vt 0.786573 0.358905
vt 0.768586 0.336168
vt 0.179409 0.270715
vt 0.074167 0.015814
vt 0.228038 0.015814
vt 0.353089 0.887169
vt 0.491410 0.889914
vt 0.671747 0.882793
vt 0.753450 0.889732
vt 0.751248 0.782506
vt 0.521490 0.588413
vt 0.251190 0.387845
vt 0.452996 0.389993
vt 0.706982 0.270715
vt 0.283275 0.270715
vt 0.673508 0.811023
vt 0.496740 0.995128
vt 0.173368 0.358905
vt 0.816889 0.358905
vt 0.995128 0.270715
vt 0.496740 0.270715
vt 0.393864 0.358905
vt 0.496740 0.358905
vt 0.599616 0.356142
vt -0.004872 0.270715
vt 0.319973 0.179234
vt 0.496740 -0.004872
vt 0.700395 0.698783
vt 0.659826 0.786573
vt 0.293085 0.291473
vt 0.333655 0.203684
vt 0.424218 0.235941
vt 0.569262 0.754316
vt 0.572861 0.228038
vt 0.500066 0.074167
vt 0.420620 0.762219
vt 0.493415 0.916090
vt 0.486794 0.324378
vt 0.491813 0.903823
vt 0.498444 0.324378
vt 0.506687 0.324378
vt 0.498444 0.903823
vt 0.491813 0.324378
vt 0.855863 0.826272
vt 0.137617 0.846165
vt 0.855863 0.846165
vt 0.137617 0.826272
vt 0.855863 0.437509
vt 0.137617 0.457403
vt 0.855863 0.457402
vt 0.137617 0.437509
vt 0.393864 0.270715
vt 0.486794 0.903823
vt 0.506687 0.903823
s 1
usemtl Material.001
f 1/1/1 7/2/2 9/3/3
f 4/4/4 13/5/5 8/6/6
f 10/7/7 15/8/8 9/3/3
f 14/9/9 18/10/10 13/5/5
f 15/8/8 16/11/11 21/12/12
f 18/10/10 27/13/13 12/14/14
f 20/15/15 24/16/16 19/17/17
f 20/15/15 25/18/18 24/16/16
f 24/16/16 28/19/19 19/17/17
f 21/12/12 22/20/20 34/21/21
f 17/22/22 26/23/23 22/20/20
f 17/22/22 27/13/13 26/23/23
f 25/18/18 29/24/24 24/16/16
f 22/20/20 26/23/23 35/25/25
f 27/13/13 28/19/19 32/26/26
f 31/27/27 35/25/25 26/23/23
f 28/19/19 29/24/24 36/28/28
f 35/25/25 38/29/29 30/30/30
f 35/25/25 39/31/31 38/29/29
f 32/26/26 36/28/28 41/32/32
f 33/33/33 42/34/34 29/24/24
f 33/33/33 43/35/35 42/34/34
s 0
f 49/36/36 73/37/36 50/38/36
f 49/36/37 50/38/37 60/39/37
f 59/40/38 63/41/38 53/42/38
f 44/43/39 52/44/39 45/45/39
f 44/43/40 72/46/40 52/44/40
f 54/47/41 76/48/41 71/49/41
f 48/50/38 62/51/38 51/52/38
f 66/53/42 67/54/42 61/55/42
f 59/56/43 70/57/43 63/58/43
f 51/59/44 56/60/44 55/61/44
f 65/53/45 68/62/45 64/63/45
f 48/64/46 69/65/46 62/66/46
f 69/67/47 68/68/47 65/69/47
f 70/70/48 67/71/48 66/72/48
f 64/73/49 68/74/49 45/64/49
f 61/75/50 67/76/50 60/56/50
f 55/77/51 75/78/51 74/79/51
s 1
f 2/80/52 8/6/6 7/2/2
f 2/80/52 3/81/53 8/6/6
f 3/81/53 4/4/4 8/6/6
f 4/4/4 5/82/54 13/5/5
f 5/82/54 6/83/55 13/5/5
f 9/3/3 7/2/2 10/7/7
f 16/11/11 12/14/14 17/22/22
f 8/6/6 13/5/5 12/14/14
f 13/5/5 6/83/55 11/84/56
f 13/5/5 11/84/56 14/9/9
f 10/7/7 16/11/11 15/8/8
f 23/85/57 19/17/17 28/19/19
f 13/5/5 18/10/10 12/14/14
f 14/9/9 11/84/56 19/17/17
f 11/84/56 20/15/15 19/17/17
f 17/22/22 12/14/14 27/13/13
f 21/12/12 16/11/11 22/20/20
f 16/11/11 17/22/22 22/20/20
f 18/10/10 23/85/57 27/13/13
f 18/10/10 14/9/9 23/85/57
f 37/86/58 30/30/30 38/29/29
f 23/85/57 28/19/19 27/13/13
f 24/16/16 29/24/24 28/19/19
f 22/20/20 30/30/30 34/21/21
f 22/20/20 35/25/25 30/30/30
f 26/23/23 27/13/13 31/27/27
f 27/13/13 32/26/26 31/27/27
f 29/24/24 25/18/18 33/33/33
f 32/26/26 28/19/19 36/28/28
f 39/31/31 31/27/27 40/87/59
f 40/87/59 32/26/26 41/32/32
s 0
f 46/88/60 45/45/60 59/39/60
s 1
f 29/24/24 42/34/34 36/28/28
s 0
f 47/89/61 60/39/61 48/45/61
f 66/72/62 53/42/62 63/41/62
f 66/72/63 50/90/63 57/91/63
f 55/77/64 48/45/64 51/92/64
f 54/47/65 59/39/65 53/93/65
f 58/94/66 73/37/66 76/48/66
f 65/69/67 51/52/67 62/51/67
s 1
f 7/2/2 12/14/14 10/7/7
s 0
f 58/95/68 53/96/68 57/97/68
f 69/65/69 60/56/69 67/76/69
f 47/89/70 55/77/70 74/79/70
f 50/98/71 58/95/71 57/97/71
f 55/77/72 56/99/72 75/78/72
f 65/69/73 52/100/73 56/101/73
f 60/102/74 50/90/74 61/103/74
f 45/104/75 52/100/75 64/105/75
f 69/67/38 70/70/38 68/68/38
f 70/57/76 45/64/76 68/74/76
f 63/63/77 70/62/77 66/53/77
f 62/55/78 69/54/78 65/53/78
f 72/106/79 73/107/79 74/108/79
f 73/37/80 47/89/80 74/79/80
f 74/108/81 75/109/81 72/106/81
f 71/110/82 76/111/82 73/107/82
f 54/47/83 58/94/83 76/48/83
f 72/46/84 46/88/84 71/49/84
f 46/88/85 54/47/85 71/49/85
f 75/78/86 52/44/86 72/46/86
f 78/112/87 80/113/87 79/114/87
f 79/115/88 77/116/88 78/117/88
f 82/118/89 84/119/89 83/120/89
f 83/120/90 81/121/90 82/118/90
f 86/122/89 88/123/89 87/124/89
f 87/124/90 85/125/90 86/122/90
s 1
f 16/11/11 10/7/7 12/14/14
f 23/85/57 14/9/9 19/17/17
f 37/86/58 34/21/21 30/30/30
f 39/31/31 35/25/25 31/27/27
f 40/87/59 31/27/27 32/26/26
s 0
f 46/88/91 44/43/91 45/45/91
f 47/89/92 49/36/92 60/39/92
f 66/72/93 57/91/93 53/42/93
f 66/72/94 61/103/94 50/90/94
f 55/77/95 47/89/95 48/45/95
f 54/47/96 46/88/96 59/39/96
f 58/94/97 50/38/97 73/37/97
f 65/69/98 56/101/98 51/52/98
s 1
f 7/2/2 8/6/6 12/14/14
s 0
f 58/95/99 54/126/99 53/96/99
f 69/65/100 48/64/100 60/56/100
f 65/69/101 64/105/101 52/100/101
f 69/67/38 67/71/38 70/70/38
f 70/57/102 59/56/102 45/64/102
f 72/106/103 71/110/103 73/107/103
f 73/37/104 49/36/104 47/89/104
f 72/46/105 44/43/105 46/88/105
f 75/78/106 56/99/106 52/44/106
f 78/112/107 77/127/107 80/113/107
f 79/115/108 80/128/108 77/116/108
f 82/118/109 81/121/109 84/119/109
f 83/120/110 84/119/110 81/121/110
f 86/122/109 85/125/109 88/123/109
f 87/124/110 88/123/110 85/125/110

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
# Blender 3.6.7 MTL File: 'None'
# www.blender.org
newmtl Material.001
Ns 360.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd content/test/uvgrid.png

View File

@ -0,0 +1,222 @@
# Blender 3.6.7
# www.blender.org
mtllib ship_weapon.mtl
o Circle
v -0.001998 0.003339 -0.279058
v -0.060548 0.003339 -0.273291
v -0.116848 0.003339 -0.256213
v -0.168735 0.003339 -0.228479
v -0.214213 0.003339 -0.191155
v -0.251537 0.003339 -0.145676
v -0.279271 0.003339 -0.093790
v -0.296349 0.003339 -0.037490
v -0.302116 0.003339 0.021060
v -0.296349 0.003339 0.079610
v -0.279271 0.003339 0.135910
v -0.251537 0.003339 0.187796
v -0.214213 0.003339 0.233275
v -0.168735 0.003339 0.270599
v -0.116848 0.003339 0.298332
v -0.060548 0.003339 0.315411
v -0.001998 0.003339 0.321178
v 0.056552 0.003339 0.315411
v 0.112852 0.003339 0.298332
v 0.164738 0.003339 0.270599
v 0.210217 0.003339 0.233275
v 0.247541 0.003339 0.187796
v 0.275274 0.003339 0.135910
v 0.292353 0.003339 0.079610
v 0.298119 0.003339 0.021060
v 0.292353 0.003339 -0.037490
v 0.275274 0.003339 -0.093790
v 0.247541 0.003339 -0.145676
v 0.210217 0.003339 -0.191155
v 0.164738 0.003339 -0.228479
v 0.112852 0.003339 -0.256213
v 0.056552 0.003339 -0.273291
v -0.005752 0.003339 -0.035452
v -0.058510 0.003339 0.024814
v 0.001756 0.003339 0.077572
v 0.046705 0.003339 0.017645
v 0.001756 0.088887 -0.035452
v -0.050701 0.088887 0.017645
v -0.005752 0.088887 0.077572
v 0.054514 0.088887 0.024814
v -0.032392 0.125403 0.093038
v -0.032392 0.240710 0.093038
v -0.032392 0.125403 -0.346358
v -0.032392 0.240710 -0.346358
v 0.051930 0.125403 0.093038
v 0.051930 0.240710 0.093038
v 0.051930 0.125403 -0.346358
v 0.051930 0.240710 -0.346358
v -0.023528 0.055092 0.045175
v -0.023528 0.170399 0.045175
v -0.023528 0.055092 -0.002624
v -0.023528 0.170399 -0.002624
v 0.023972 0.055092 0.045175
v 0.023972 0.170399 0.045175
v 0.023972 0.055092 -0.002624
v 0.023972 0.170399 -0.002624
vn 0.7940 -0.1224 0.5955
vn -0.0000 1.0000 -0.0000
vn -0.6576 -0.0577 0.7512
vn 0.7100 -0.0623 -0.7014
vn -0.7523 0.0135 -0.6586
vn -0.7940 0.1224 0.5955
vn 0.7523 -0.0135 -0.6586
vn -0.7100 0.0623 -0.7014
vn 0.6576 0.0577 0.7512
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
vt 0.480149 0.438877
vt 0.469410 0.567032
vt 0.390375 0.438877
vt 0.492575 0.559691
vt 0.410487 0.915985
vt 0.326147 0.890401
vt 0.248419 0.848854
vt 0.413540 0.469410
vt 0.124377 0.724813
vt 0.082831 0.647084
vt 0.057246 0.562744
vt 0.048608 0.475033
vt 0.057246 0.387323
vt 0.082831 0.302983
vt 0.124377 0.225254
vt 0.503821 0.390375
vt 0.248419 0.101213
vt 0.326147 0.059666
vt 0.410487 0.034082
vt 0.498198 0.025443
vt 0.670249 0.059666
vt 0.747977 0.101213
vt 0.571158 0.480149
vt 0.872019 0.225254
vt 0.913566 0.302983
vt 0.939150 0.387323
vt 0.947789 0.475033
vt 0.913566 0.647084
vt 0.872019 0.724813
vt 0.747977 0.848854
vt 0.670249 0.890401
vt 0.585909 0.915985
vt 0.498198 0.924624
vt 0.503821 0.438877
vt 0.492575 0.567032
vt 0.413540 0.438877
vt 0.559691 0.438877
vt 0.559691 0.567032
vt 0.469410 0.438877
vt 0.480149 0.567032
vt 0.180290 0.792942
vt 0.180290 0.157125
vt 0.816107 0.157125
vt 0.585909 0.034082
vt 0.939150 0.562744
vt 0.816107 0.792942
vt 0.582856 0.469410
vt 0.425239 0.480149
vt 0.492575 0.390375
vt 0.390375 0.567032
vt 0.582856 0.567032
vt 0.367207 0.794470
vt 1.025443 0.621735
vt 0.367207 0.621735
vt 0.452666 0.794470
vt 0.578985 0.621735
vt 0.452666 0.621735
vt 1.025443 0.794470
vt 0.578985 0.794470
vt 0.578985 1.025443
vt 0.452666 0.367207
vt 0.452666 1.025443
vt 0.578985 0.367207
vt 0.438908 0.689140
vt 0.510512 0.516405
vt 0.438908 0.516405
vt 0.465945 0.689140
vt 0.537102 0.516405
vt 0.465945 0.516405
vt 0.510512 0.689140
vt 0.537102 0.689140
vt 0.537102 0.510512
vt 0.465945 0.438908
vt 0.465945 0.510512
vt 0.537102 0.438908
vt 0.503821 0.559691
s 0
usemtl Material.001
f 36/1/1 40/2/1 35/3/1
f 33/4/2 2/5/2 3/6/2
f 33/4/2 3/6/2 4/7/2
f 34/8/2 6/9/2 7/10/2
f 34/8/2 8/11/2 9/12/2
f 34/8/2 10/13/2 11/14/2
f 34/8/2 11/14/2 12/15/2
f 35/16/2 14/17/2 15/18/2
f 35/16/2 16/19/2 17/20/2
f 35/16/2 19/21/2 20/22/2
f 36/23/2 22/24/2 23/25/2
f 36/23/2 24/26/2 25/27/2
f 36/23/2 27/28/2 28/29/2
f 33/4/2 30/30/2 31/31/2
f 33/4/2 32/32/2 1/33/2
f 35/34/3 39/35/3 34/36/3
f 33/37/4 37/38/4 36/1/4
f 34/39/5 38/40/5 33/37/5
f 33/4/2 1/33/2 2/5/2
f 33/4/2 4/7/2 5/41/2
f 13/42/2 35/16/2 34/8/2
f 34/8/2 7/10/2 8/11/2
f 34/8/2 9/12/2 10/13/2
f 34/8/2 12/15/2 13/42/2
f 22/24/2 35/16/2 21/43/2
f 35/16/2 15/18/2 16/19/2
f 35/16/2 17/20/2 18/44/2
f 35/16/2 18/44/2 19/21/2
f 35/16/2 20/22/2 21/43/2
f 26/45/2 36/23/2 25/27/2
f 36/23/2 23/25/2 24/26/2
f 29/46/2 33/4/2 36/23/2
f 36/23/2 26/45/2 27/28/2
f 36/23/2 28/29/2 29/46/2
f 33/4/2 31/31/2 32/32/2
f 40/47/2 38/48/2 39/49/2
f 34/39/6 39/50/6 38/40/6
f 36/1/7 37/38/7 40/2/7
f 5/41/2 34/8/2 33/4/2
f 33/37/8 38/40/8 37/38/8
f 35/34/9 40/51/9 39/35/9
f 42/52/10 43/53/10 41/54/10
f 44/55/11 47/56/11 43/57/11
f 48/58/12 45/54/12 47/53/12
f 46/59/13 41/57/13 45/56/13
f 47/60/14 41/61/14 43/62/14
f 44/62/2 46/63/2 48/60/2
f 50/64/10 51/65/10 49/66/10
f 52/67/11 55/68/11 51/69/11
f 56/70/12 53/66/12 55/65/12
f 54/71/13 49/69/13 53/68/13
f 55/72/14 49/73/14 51/74/14
f 52/74/2 54/75/2 56/72/2
f 13/42/2 14/17/2 35/16/2
f 22/24/2 36/23/2 35/16/2
f 29/46/2 30/30/2 33/4/2
f 40/47/2 37/76/2 38/48/2
f 5/41/2 6/9/2 34/8/2
f 42/52/10 44/58/10 43/53/10
f 44/55/11 48/59/11 47/56/11
f 48/58/12 46/52/12 45/54/12
f 46/59/13 42/55/13 41/57/13
f 47/60/14 45/63/14 41/61/14
f 44/62/2 42/61/2 46/63/2
f 50/64/10 52/70/10 51/65/10
f 52/67/11 56/71/11 55/68/11
f 56/70/12 54/64/12 53/66/12
f 54/71/13 50/67/13 49/69/13
f 55/72/14 53/75/14 49/73/14
f 52/74/2 50/73/2 54/75/2

13
content/test/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
content/test/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
content/test/tetrad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
content/test/uvgrid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@ -0,0 +1,12 @@
# Blender 3.6.7 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/env/env_water.png

1097
content/test/water_test.obj Normal file

File diff suppressed because it is too large Load Diff

BIN
content/textures/env/env_water.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

1
gen_vs2022.bat Normal file
View File

@ -0,0 +1 @@
tools\premake5.exe vs2022

158
premake5.lua Normal file
View File

@ -0,0 +1,158 @@
solution "game"
configurations {
"Debug",
"Release"
}
platforms {
"x32",
"x64",
}
language "C++"
location "build"
targetdir "bin"
characterset "MBCS"
rtti "Off"
filter "x64"
targetdir "bin_x64"
filter "windows"
defines { "_WIN32", "WIN32", "WINDOWS" }
filter "Debug"
defines { "DEBUG", "_DEBUG" }
targetsuffix "_d"
flags { "Symbols" }
filter "Release"
defines { "NDEBUG" }
flags { "Symbols", "OptimizeSpeed", "No64BitChecks" }
--filter {}
PROJ_DIR = path.getabsolute(".")
LIB_DIR = path.getabsolute("thirdparty")
STB_DIR = path.join(LIB_DIR, "stb")
MINIAUDIO_DIR = path.join(LIB_DIR, "miniaudio")
GLAD_DIR = path.join(LIB_DIR, "glad")
GLM_DIR = path.join(LIB_DIR, "glm")
MINILUA_DIR = path.join(LIB_DIR, "minilua")
ODE_DIR = path.join(LIB_DIR, "ode-0.16.5")
-- Open Dynamics Engine
project "ode"
kind "StaticLib"
defines { "dIDEDOUBLE", "CCD_IDEDOUBLE", "_OU_FEATURE_SET=_OU_FEATURE_SET_TLS" }
filter { "Release*" }
defines { "NDEBUG", "dNODEBUG" }
flags { "OptimizeSpeed", "NoFramePointer" }
-- disable Visual Studio security warnings
filter { "vs*" }
defines { "_CRT_SECURE_NO_DEPRECATE", "_SCL_SECURE_NO_WARNINGS" }
-- enable M_* macros from math.h
filter { "vs*" }
defines { "_USE_MATH_DEFINES" }
filter {}
includedirs {
path.join(ODE_DIR, "OPCODE"),
path.join(ODE_DIR, "include"),
path.join(ODE_DIR, "build"),
path.join(ODE_DIR, "ou/include"),
path.join(ODE_DIR, "ou/src"),
path.join(ODE_DIR, "ode/src"),
path.join(ODE_DIR, "ode/src/joints"),
}
files {
-- ode sources
path.join(ODE_DIR, "include/ode/*.h"),
path.join(ODE_DIR, "ode/src/joints/*.h"),
path.join(ODE_DIR, "ode/src/joints/*.cpp"),
path.join(ODE_DIR, "ode/src/*.h"),
path.join(ODE_DIR, "ode/src/*.c"),
path.join(ODE_DIR, "ode/src/*.cpp"),
-- ou library
path.join(ODE_DIR, "ou/include/**.h"),
path.join(ODE_DIR, "ou/src/**.h"),
path.join(ODE_DIR, "ou/src/**.cpp"),
-- OPCODE
path.join(ODE_DIR, "OPCODE/*.h"),
path.join(ODE_DIR, "OPCODE/*.cpp"),
path.join(ODE_DIR, "OPCODE/Ice/*.h"),
path.join(ODE_DIR, "OPCODE/Ice/*.cpp")
}
excludes {
path.join(ODE_DIR, "ode/src/collision_std.cpp"),
path.join(ODE_DIR, "ode/src/collision_libccd.cpp"),
path.join(ODE_DIR, "ode/src/collision_libccd.h")
}
-- Game
project "game"
kind "ConsoleApp"
includedirs {
path.join(PROJ_DIR, "src"),
path.join(PROJ_DIR, "src/engine"),
LIB_DIR,
STB_DIR,
MINIAUDIO_DIR,
GLM_DIR,
MINILUA_DIR,
path.join(ODE_DIR, "include"),
path.join(ODE_DIR, "build"),
path.join(GLAD_DIR, "include")
}
files {
-- GLAD
path.join(GLAD_DIR, "src/*.c"),
-----------------------------------------
-- Engine
path.join(PROJ_DIR, "src/engine/utils/*.cpp"),
path.join(PROJ_DIR, "src/engine/utils/*.h"),
path.join(PROJ_DIR, "src/engine/filesystem/*.cpp"),
path.join(PROJ_DIR, "src/engine/filesystem/*.h"),
path.join(PROJ_DIR, "src/engine/input/*.cpp"),
path.join(PROJ_DIR, "src/engine/input/*.h"),
path.join(PROJ_DIR, "src/engine/render/*.cpp"),
path.join(PROJ_DIR, "src/engine/render/*.h"),
path.join(PROJ_DIR, "src/engine/sound/*.cpp"),
path.join(PROJ_DIR, "src/engine/sound/*.h"),
path.join(PROJ_DIR, "src/engine/physics/*.cpp"),
path.join(PROJ_DIR, "src/engine/physics/*.h"),
-----------------------------------------
-- Game
path.join(PROJ_DIR, "src/game/*.c"),
path.join(PROJ_DIR, "src/game/*.cpp"),
path.join(PROJ_DIR, "src/game/*.h"),
-----------------------------------------
-- Main
path.join(PROJ_DIR, "src/main/*.cpp"),
path.join(PROJ_DIR, "src/main/*.h"),
}
links { "ode" }

View File

@ -0,0 +1,57 @@
#include <assert.h>
#include "filesystem/file.h"
static const char* s_stdioOpeningMode[] = { "rb", "wb" };
static int s_stdioSeekDir[] = { SEEK_SET, SEEK_CUR, SEEK_END };
File::File(const char* path, FileAccess access)
{
m_filehandle = fopen(path, s_stdioOpeningMode[(int)access]);
assert(m_filehandle && "Unable to open file");
}
File::~File()
{
if (m_filehandle)
{
fclose(m_filehandle);
m_filehandle = nullptr;
}
}
void File::seek(SeekDir seekdir, long offset)
{
fseek(m_filehandle, offset, s_stdioSeekDir[(int)seekdir]);
}
long File::tell()
{
return ftell(m_filehandle);
}
bool File::eof()
{
return feof(m_filehandle);
}
size_t File::read(void* buffer, size_t size)
{
return fread(buffer, 1, size, m_filehandle);
}
size_t File::write(void const* buffer, size_t size)
{
return fwrite(buffer, size, 1, m_filehandle);
}
void File::readStringBuffer(char* buffer, size_t bufferSize)
{
seek(SeekDir::End, 0);
size_t length = tell();
seek(SeekDir::Begin, 0);
assert(length <= bufferSize);
read(buffer, length);
buffer[length] = '\0';
}

View File

@ -0,0 +1,28 @@
#ifndef FILE_H
#define FILE_H
#include "filesystem/filecommon.h"
class File
{
public:
File(const char* path, FileAccess access);
~File();
FILE* getHandle() { return m_filehandle; }
void seek(SeekDir seekdir, long offset);
long tell();
bool eof();
size_t read(void* buffer, size_t size);
size_t write(void const* buffer, size_t size);
// helpers
void readStringBuffer(char* buffer, size_t bufferSize);
private:
FILE* m_filehandle;
};
#endif

View File

@ -0,0 +1,21 @@
#ifndef FILECOMMON_H
#define FILECOMMON_H
#include <stdio.h>
static const int kMaxPathLength = 260;
enum class FileAccess
{
Read,
Write
};
enum class SeekDir
{
Begin,
Current,
End
};
#endif // !FILECOMMON_H

View File

@ -0,0 +1,316 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include "filesystem/stream.h"
#include "filesystem/filemanager.h"
void RecursiveSearch(const std::string& path, std::vector<std::string>& files);
void osResolvePath(char* path);
FileManager* g_fileManager;
FileManager::FileManager()
{
static char currentDirectory[kMaxPathLength];
GetCurrentDirectoryA(kMaxPathLength, currentDirectory);
strcat(currentDirectory, "/");
osResolvePath(currentDirectory);
m_defaultPath = currentDirectory;
}
FileManager::~FileManager()
{
}
void FileManager::SetDefaultPath(const char* path)
{
m_defaultPath = path;
}
bool FileManager::FileExist(const char* filename)
{
#if defined(WIN32) || defined(_WIN32)
char pathBuffer[kMaxPathLength];
if (!strstr(filename, m_defaultPath))
sprintf(pathBuffer, "%s%s", m_defaultPath, filename);
else
strcpy(pathBuffer, filename);
osResolvePath(pathBuffer);
DWORD dwAttrib = GetFileAttributes(pathBuffer);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
#else
FILE* file;
if ((file = fopen(filename, "r")) != NULL)
{
fclose(file);
return true;
}
else
return false;
#endif
}
File* FileManager::OpenFile(const char* path, FileAccess access)
{
char pathBuffer[kMaxPathLength];
if (!strstr(path, m_defaultPath))
sprintf(pathBuffer, "%s%s", m_defaultPath, path);
else
strcpy(pathBuffer, path);
osResolvePath(pathBuffer);
return new File(pathBuffer, access);
}
void FileManager::CloseFile(File*& file)
{
if (file)
{
delete file;
file = nullptr;
}
}
StreamBase* FileManager::OpenStream(const char* fname, FileAccess access)
{
char pathBuffer[kMaxPathLength];
if (!strstr(fname, m_defaultPath))
sprintf(pathBuffer, "%s%s", m_defaultPath, fname);
else
strcpy(pathBuffer, fname);
osResolvePath(pathBuffer);
if (!g_fileManager->FileExist( pathBuffer ))
return nullptr;
File* file = new File(pathBuffer, access);
return createFileStream(file);
}
#if _WIN32
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <time.h>
void GetFileListFromFolder(const char* path, const char* findingPattern, std::vector<std::string>& filesList)
{
struct _finddata_t c_file;
intptr_t hFile;
char pathfind[kMaxPathLength];
sprintf(pathfind, "%s/%s", path, findingPattern);
osResolvePath(pathfind);
if ((hFile = _findfirst(pathfind, &c_file)) != -1L) {
do {
char buffer[kMaxPathLength];
sprintf(buffer, "%s/%s", path, c_file.name);
filesList.push_back(buffer);
} while (_findnext(hFile, &c_file) == 0);
_findclose(hFile);
}
}
void osResolvePath(char* path)
{
assert(path);
size_t length = strlen(path);
for (int i = 0; i < (int)length; i++) {
if (path[i] == '/')
path[i] = '\\';
}
}
bool osDirectoryIsExist(const char* path)
{
DWORD ftyp = GetFileAttributesA(path);
if (ftyp == INVALID_FILE_ATTRIBUTES)
return false;
if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
return true;
return false;
}
void osCreateDirectory(const char* path)
{
CreateDirectoryA(path, NULL);
}
void RecursiveSearch(const std::string& path, std::vector<std::string>& files)
{
struct _finddata_t c_file;
intptr_t hFile;
std::string bufferPath;
bufferPath += path;
bufferPath += "/";
bufferPath += "*.*";
if ((hFile = _findfirst(bufferPath.c_str(), &c_file)) != -1L)
{
do {
if (strcmp(c_file.name, ".") == 0 ||
strcmp(c_file.name, "..") == 0 ||
strcmp(c_file.name, ".git") == 0 ||
strcmp(c_file.name, ".gitignore") == 0 ||
strcmp(c_file.name, ".gitignore") == 0 ||
strcmp(c_file.name, ".vs") == 0)
continue;
if (c_file.attrib & _A_SUBDIR)
{
std::string nextPath;
nextPath += path;
nextPath += "/";
nextPath += c_file.name;
RecursiveSearch(nextPath, files);
}
else
{
std::string filepath;
filepath += path;
filepath += "/";
filepath += c_file.name;
files.push_back(filepath);
}
} while (_findnext(hFile, &c_file) == 0);
_findclose(hFile);
}
}
#else
#include <dirent.h>
bool match(const char* pattern, const char* str, int p = 0, int c = 0)
{
if (pattern[p] == '\0')
{
return str[c] == '\0';
}
else if (pattern[p] == '*')
{
for (; str[c] != '\0'; c++)
{
if (match(pattern, str, p + 1, c))
return true;
}
return match(pattern, str, p + 1, c);
}
else if (pattern[p] != '?' && pattern[p] != str[c])
{
return false;
}
else
{
return match(pattern, str, p + 1, c + 1);
}
}
void GetFileListFromFolder(const char* path, const char* findingPattern, std::vector<std::string>& filesList)
{
DIR* dir;
dirent* ent;
if ((dir = opendir(path)) != NULL)
{
while ((ent = readdir(dir)) != NULL)
{
if (match(findingPattern, ent->d_name))
{
char buffer[kMaxPathLength];
snprintf(buffer, kMaxPathLength, "%s/%s", path, ent->d_name);
filesList.push_back(buffer);
}
}
closedir(dir);
}
}
#endif
namespace fs
{
std::string getFileExtension(const std::string& filename)
{
size_t whereIsDot = filename.find_last_of('.');
if (whereIsDot != std::string::npos) {
return filename.substr(whereIsDot);
}
return std::string();
}
std::string getFilePath(const std::string& filename)
{
size_t lastindex = filename.find_last_of("/");
if (lastindex == std::string::npos) {
lastindex = filename.find_last_of("\\");
}
if (lastindex != std::string::npos) {
return filename.substr(0, lastindex);
}
return std::string();
}
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;
}
std::string getFilenameWithoutPath(const std::string& filename)
{
size_t whereIsSlash = filename.find_last_of('/');
if (whereIsSlash == std::string::npos) {
whereIsSlash = filename.find_last_of('\\');
}
if (whereIsSlash == std::string::npos) {
return filename;
}
std::string string = filename.substr(whereIsSlash + 1);
return string;
}
std::string getFilenameWithoutPathAndExtension(const std::string& filename)
{
size_t whereIsDot = filename.find_last_of('.');
size_t whereIsSlash = filename.find_last_of('/');
if (whereIsSlash == std::string::npos) {
whereIsSlash = filename.find_last_of('\\');
}
if (whereIsDot == std::string::npos && whereIsSlash == std::string::npos) {
return filename;
}
std::string string = filename.substr(whereIsSlash + 1);
whereIsDot = string.find_last_of('.');
string = string.substr(0, whereIsDot);
return string;
}
}

View File

@ -0,0 +1,51 @@
#ifndef FILEMANAGER_H
#define FILEMANAGER_H
#include <string>
#include <vector>
#include "filesystem/file.h"
class StreamBase;
class FileManager
{
public:
FileManager();
~FileManager();
void SetDefaultPath(const char* path);
const char* GetDefaultPath() { return m_defaultPath; }
bool FileExist(const char* filename);
File* OpenFile(const char* path, FileAccess access);
void CloseFile(File*& file);
StreamBase* OpenStream(const char* fname, FileAccess access);
private:
const char* m_defaultPath;
};
extern FileManager* g_fileManager;
void GetFileListFromFolder(const char* path, const char* findingPattern, std::vector<std::string>& filesList);
void osResolvePath(char* path);
bool osDirectoryIsExist(const char* path);
void osCreateDirectory(const char* path);
// Filename helper
namespace fs
{
std::string getFileExtension(const std::string& filename);
std::string getFilePath(const std::string& filename);
std::string getFileNameWithoutExtension(const std::string& filename);
std::string getFilenameWithoutPath(const std::string& filename);
std::string getFilenameWithoutPathAndExtension(const std::string& filename);
};
#endif // !FILEMANAGER_H

View File

@ -0,0 +1,61 @@
#include <assert.h>
#include "filesystem/stream.h"
#include "filesystem/filemanager.h"
class FileStream : public StreamBase
{
public:
FileStream(File* file);
~FileStream();
size_t readBuffer(void* buffer, size_t size);
size_t writeBuffer(void* buffer, size_t size);
void seek(SeekDir way, long offset);
size_t tell();
bool eof();
private:
File* m_file;
};
FileStream::FileStream(File* file)
{
assert(file && "Cannot open file stream with nullptr file handle.");
m_file = file;
}
FileStream::~FileStream()
{
if (m_file)
g_fileManager->CloseFile(m_file);
}
size_t FileStream::readBuffer(void* buffer, size_t size)
{
return m_file->read(buffer, size);
}
size_t FileStream::writeBuffer(void* buffer, size_t size)
{
return m_file->write(buffer, size);
}
void FileStream::seek(SeekDir way, long offset)
{
m_file->seek(way, offset);
}
size_t FileStream::tell()
{
return m_file->tell();
}
bool FileStream::eof()
{
return m_file->eof();;
}
StreamBase* createFileStream(File* file)
{
return new FileStream(file);
}

View File

@ -0,0 +1,21 @@
#ifndef STREAM_H
#define STREAM_H
#include "filesystem/filecommon.h"
class StreamBase
{
public:
virtual ~StreamBase() {}
virtual size_t readBuffer(void* buffer, size_t size) = 0;
virtual size_t writeBuffer(void* buffer, size_t size) = 0;
virtual void seek(SeekDir way, long offset) = 0;
virtual size_t tell() = 0;
virtual bool eof() = 0;
};
class File;
StreamBase* createFileStream(File* file);
#endif // !STREAM_H

View File

@ -0,0 +1,182 @@
#include <assert.h>
#include <memory.h>
#include "utils/logger.h"
#include "utils/maths.h"
#include "input/input_system.h"
const int kMaxKeyboardKeys = 460;
const int kMaxMouseButtons = mouseButton_LastNamed + 1; //5;
const float kKeyThreshold = 0.2f;
IInputSystem* g_inputSystem = nullptr;
class InputSystem : public IInputSystem
{
public:
InputSystem();
~InputSystem();
void Init();
void Shutdown();
void Update();
size_t GetMaxScancode() const;
size_t GetMaxMouseButton() const;
char TranslateScancode(scanCode_t scancode) const;
void OnKeyDown(scanCode_t scancode);
void OnKeyUp(scanCode_t scancode);
void OnMouseKeyDown(mouseButton_t mousebutton);
void OnMouseKeyUp(mouseButton_t mousebutton);
void OnMouseMove(int32_t x, int32_t y);
void OnMouseWheel(int32_t x, int32_t y);
bool IsKeyPressed(scanCode_t scancode) const;
bool IsMouseButtonPressed(mouseButton_t mousebutton) const;
void GetMousePosition(int32_t* x, int32_t* y) const;
void GetMouseWheelPosition(int32_t* x, int32_t* y) const;
const char* ActionToString(Action action) const;
void BindKey(Action action, scanCode_t scancode);
bool IsActionActive(Action action) const;
void UnBindKey(Action action);
void UnBindAll();
private:
bool m_keyboardKeys[kMaxKeyboardKeys];
bool m_mouseButtons[kMaxMouseButtons];
Point2 m_mousePosition;
};
InputSystem::InputSystem()
{
memset( m_keyboardKeys, 0, sizeof( m_keyboardKeys ) );
memset( m_mouseButtons, 0, sizeof( m_mouseButtons ) );
memset( &m_mousePosition, 0, sizeof( m_mousePosition ) );
}
InputSystem::~InputSystem()
{
}
void InputSystem::Init()
{
// Nothing to do
}
void InputSystem::Shutdown()
{
// Nothing to do
}
void InputSystem::Update()
{
// TODO: Reset all pressed keys ...
}
size_t InputSystem::GetMaxScancode() const
{
return kMaxKeyboardKeys;
}
size_t InputSystem::GetMaxMouseButton() const
{
return kMaxMouseButtons;
}
char InputSystem::TranslateScancode(scanCode_t scancode) const
{
assert(0 && "Not implemented");
return 0;
}
void InputSystem::OnKeyDown(scanCode_t scancode)
{
assert(scancode <= kMaxKeyboardKeys);
m_keyboardKeys[scancode] = true;
}
void InputSystem::OnKeyUp(scanCode_t scancode)
{
assert(scancode <= kMaxKeyboardKeys);
m_keyboardKeys[scancode] = false;
}
void InputSystem::OnMouseKeyDown(mouseButton_t mousebutton)
{
assert(mousebutton <= kMaxMouseButtons);
m_mouseButtons[mousebutton] = true;
}
void InputSystem::OnMouseKeyUp(mouseButton_t mousebutton)
{
assert(mousebutton <= kMaxMouseButtons);
m_mouseButtons[mousebutton] = false;
}
void InputSystem::OnMouseMove(int32_t x, int32_t y)
{
m_mousePosition.x = (int)x;
m_mousePosition.y = (int)y;
}
void InputSystem::OnMouseWheel(int32_t x, int32_t y)
{
}
bool InputSystem::IsKeyPressed(scanCode_t scancode) const
{
assert(scancode <= KEY_MAX);
return m_keyboardKeys[scancode];
}
bool InputSystem::IsMouseButtonPressed(mouseButton_t mousebutton) const
{
assert(mousebutton <= kMaxMouseButtons);
return m_mouseButtons[mousebutton];
}
void InputSystem::GetMousePosition(int32_t* x, int32_t* y) const
{
if (x) *x = (int32_t)m_mousePosition.x;
if (y) *y = (int32_t)m_mousePosition.y;
}
void InputSystem::GetMouseWheelPosition(int32_t* x, int32_t* y) const
{
}
const char* InputSystem::ActionToString(Action action) const
{
return nullptr;
}
void InputSystem::BindKey(Action action, scanCode_t scancode)
{
}
bool InputSystem::IsActionActive(Action action) const
{
return false;
}
void InputSystem::UnBindKey(Action action)
{
}
void InputSystem::UnBindAll()
{
}
IInputSystem* CreateInputSystem(void* wndHandle)
{
return new InputSystem();
}
void DestroyInputSystem(IInputSystem* pInstance)
{
InputSystem* pInput = (InputSystem*)pInstance;
delete pInput;
}

View File

@ -0,0 +1,198 @@
#ifndef INPUT_SYSTEM_H
#define INPUT_SYSTEM_H
#include <stddef.h>
#include <stdint.h>
enum KeyboardKeys
{
KEY_UNKNOWN = 0,
KEY_SPACE = 32,
KEY_APOSTROPHE = 39, /* ' */
KEY_COMMA = 44, /* , */
KEY_MINUS = 45, /* - */
KEY_PERIOD = 46, /* . */
KEY_SLASH = 47, /* / */
KEY_0 = 48,
KEY_1 = 49,
KEY_2 = 50,
KEY_3 = 51,
KEY_4 = 52,
KEY_5 = 53,
KEY_6 = 54,
KEY_7 = 55,
KEY_8 = 56,
KEY_9 = 57,
KEY_SEMICOLON = 59, /* ; */
KEY_EQUAL = 61, /* = */
KEY_A = 65,
KEY_B = 66,
KEY_C = 67,
KEY_D = 68,
KEY_E = 69,
KEY_F = 70,
KEY_G = 71,
KEY_H = 72,
KEY_I = 73,
KEY_J = 74,
KEY_K = 75,
KEY_L = 76,
KEY_M = 77,
KEY_N = 78,
KEY_O = 79,
KEY_P = 80,
KEY_Q = 81,
KEY_R = 82,
KEY_S = 83,
KEY_T = 84,
KEY_U = 85,
KEY_V = 86,
KEY_W = 87,
KEY_X = 88,
KEY_Y = 89,
KEY_Z = 90,
KEY_LEFT_BRACKET = 91, /* [ */
KEY_BACKSLASH = 92, /* \ */
KEY_RIGHT_BRACKET = 93, /* ] */
KEY_GRAVE_ACCENT = 96, /* ` */
KEY_WORLD_1 = 161, /* non-US #1 */
KEY_WORLD_2 = 162, /* non-US #2 */
KEY_ESCAPE = 256,
KEY_ENTER = 257,
KEY_TAB = 258,
KEY_BACKSPACE = 259,
KEY_INSERT = 260,
KEY_DELETE = 261,
KEY_RIGHT = 262,
KEY_LEFT = 263,
KEY_DOWN = 264,
KEY_UP = 265,
KEY_PAGE_UP = 266,
KEY_PAGE_DOWN = 267,
KEY_HOME = 268,
KEY_END = 269,
KEY_CAPS_LOCK = 280,
KEY_SCROLL_LOCK = 281,
KEY_NUM_LOCK = 282,
KEY_PRINT_SCREEN = 283,
KEY_PAUSE = 284,
KEY_F1 = 290,
KEY_F2 = 291,
KEY_F3 = 292,
KEY_F4 = 293,
KEY_F5 = 294,
KEY_F6 = 295,
KEY_F7 = 296,
KEY_F8 = 297,
KEY_F9 = 298,
KEY_F10 = 299,
KEY_F11 = 300,
KEY_F12 = 301,
KEY_F13 = 302,
KEY_F14 = 303,
KEY_F15 = 304,
KEY_F16 = 305,
KEY_F17 = 306,
KEY_F18 = 307,
KEY_F19 = 308,
KEY_F20 = 309,
KEY_F21 = 310,
KEY_F22 = 311,
KEY_F23 = 312,
KEY_F24 = 313,
KEY_F25 = 314,
KEY_KP_0 = 320,
KEY_KP_1 = 321,
KEY_KP_2 = 322,
KEY_KP_3 = 323,
KEY_KP_4 = 324,
KEY_KP_5 = 325,
KEY_KP_6 = 326,
KEY_KP_7 = 327,
KEY_KP_8 = 328,
KEY_KP_9 = 329,
KEY_KP_DECIMAL = 330,
KEY_KP_DIVIDE = 331,
KEY_KP_MULTIPLY = 332,
KEY_KP_SUBTRACT = 333,
KEY_KP_ADD = 334,
KEY_KP_ENTER = 335,
KEY_KP_EQUAL = 336,
KEY_LEFT_SHIFT = 340,
KEY_LEFT_CONTROL = 341,
KEY_LEFT_ALT = 342,
KEY_LEFT_SUPER = 343,
KEY_RIGHT_SHIFT = 344,
KEY_RIGHT_CONTROL = 345,
KEY_RIGHT_ALT = 346,
KEY_RIGHT_SUPER = 347,
KEY_MENU = 348,
KEY_MAX
};
typedef KeyboardKeys scanCode_t;
typedef uint8_t mouseButton_t;
enum mouseButton_
{
mouseButton_Left = 1,
mouseButton_Middle ,
mouseButton_Right ,
mouseButton_LastNamed = mouseButton_Right
};
#define GetNamelessMouseButtonIndex(buttonNum) mouseButton_t(mouseButton_LastNamed + buttonNum)
enum Action_
{
Action_Forward,
Action_Backward,
Action_Left,
Action_Right,
Action_Fire,
Action_Use,
Action_Max
};
typedef uint32_t Action;
class IInputSystem
{
public:
virtual ~IInputSystem() {}
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual void Update() = 0;
virtual size_t GetMaxScancode () const = 0;
virtual size_t GetMaxMouseButton() const = 0;
virtual char TranslateScancode(scanCode_t scancode) const = 0;
virtual void OnKeyDown (scanCode_t scancode) = 0;
virtual void OnKeyUp (scanCode_t scancode) = 0;
virtual void OnMouseKeyDown (mouseButton_t mousebutton) = 0;
virtual void OnMouseKeyUp (mouseButton_t mousebutton) = 0;
virtual void OnMouseMove (int32_t x, int32_t y) = 0;
virtual void OnMouseWheel (int32_t x, int32_t y) = 0;
virtual bool IsKeyPressed (scanCode_t scancode) const = 0;
virtual bool IsMouseButtonPressed (mouseButton_t mousebutton) const = 0;
virtual void GetMousePosition (int32_t* x, int32_t* y) const = 0;
virtual void GetMouseWheelPosition (int32_t* x, int32_t* y) const = 0;
virtual const char* ActionToString (Action action) const = 0;
virtual void BindKey (Action action, scanCode_t scancode) = 0;
virtual bool IsActionActive (Action action) const = 0;
virtual void UnBindKey (Action action) = 0;
virtual void UnBindAll () = 0;
};
extern IInputSystem* g_inputSystem;
IInputSystem* CreateInputSystem(void* wndHandle);
void DestroyInputSystem(IInputSystem* pInstance);
#endif // !INPUT_SYSTEM_H

View File

@ -0,0 +1,158 @@
#include "utils/maths.h"
#include "physics_object.h"
#include "physics_world.h"
#include "physics_render.h"
#include "game/game_object.h"
#include <ode/collision_trimesh.h>
#include <vector>
PhysicsObject::PhysicsObject() :
m_pCollisionShape(nullptr), m_pRigidBody(nullptr), m_pTriMesh(nullptr),
m_pEntity(nullptr),
m_Friction(0.5f), m_Gravity(0.0f), m_LinearVelocity(0.0f)
{
}
PhysicsObject::~PhysicsObject()
{
}
void PhysicsObject::CreateTriMesh(const Vec3* vertices, const int verticesCount, const uint32_t* indices, const int indicesCount)
{
m_pRigidBody = dBodyCreate(g_PhysicsWorld->GetWorld());
dBodySetPosition(m_pRigidBody, 0, 0, 0);
dMass m;
dMassSetBox(&m, 1, 10.0f, 10.0f, 10.0f);
dBodySetMass(m_pRigidBody, &m);
// create triangle mesh
m_pTriMesh = dGeomTriMeshDataCreate();
// collect data
std::vector<dReal> odevertices;
int j = 0;
for (int i = 0; i < verticesCount; i++)
{
if (j > 2)
j = 0;
if (j == 0)
odevertices.push_back(vertices[i].x);
if (j == 1)
odevertices.push_back(vertices[i].x);
if (j == 2)
odevertices.push_back(vertices[i].x);
j++;
}
dGeomTriMeshDataBuildSimple(m_pTriMesh, odevertices.data(), odevertices.size(), (const dTriIndex*)indices, indicesCount);
m_pCollisionShape = dCreateTriMesh(g_PhysicsWorld->GetSpace(), m_pTriMesh, NULL, NULL, NULL);
dGeomSetBody(m_pCollisionShape, m_pRigidBody);
}
void PhysicsObject::CreatePlayer()
{
m_pRigidBody = dBodyCreate(g_PhysicsWorld->GetWorld());
dBodySetPosition(m_pRigidBody, 0, 0, 0);
dBodySetKinematic(m_pRigidBody);
dBodySetAutoDisableFlag(m_pRigidBody, 0); // disable body sleeping
dMass m;
dMassSetBox(&m, 1, 10.0f, 10.0f, 10.0f);
dBodySetMass(m_pRigidBody, &m);
m_pCollisionShape = dCreateBox(g_PhysicsWorld->GetSpace(), 0.5f, 0.5f, 0.5f);
dGeomSetBody(m_pCollisionShape, m_pRigidBody);
}
void PhysicsObject::CreateSimpleBox()
{
m_pRigidBody = dBodyCreate(g_PhysicsWorld->GetWorld());
dBodySetPosition(m_pRigidBody, 0, 0, 0);
dMass m;
dMassSetBox(&m, 1, 10.0f, 10.0f, 10.0f);
dBodySetMass(m_pRigidBody, &m);
m_pCollisionShape = dCreateBox(g_PhysicsWorld->GetSpace(), 0.5f, 0.5f, 0.5f);
dGeomSetBody(m_pCollisionShape, m_pRigidBody);
}
void PhysicsObject::CreateSimpleBox_Kinematic()
{
m_pRigidBody = dBodyCreate(g_PhysicsWorld->GetWorld());
dBodySetPosition(m_pRigidBody, 0, 0, 0);
dBodySetKinematic(m_pRigidBody);
dMass m;
dMassSetBox(&m, 1, 10.0f, 10.0f, 10.0f);
dBodySetMass(m_pRigidBody, &m);
m_pCollisionShape = dCreateBox(g_PhysicsWorld->GetSpace(), 0.5f, 0.5f, 0.5f);
dGeomSetBody(m_pCollisionShape, m_pRigidBody);
}
void PhysicsObject::Destroy()
{
g_PhysicsWorld->RemoveObject(this);
dGeomTriMeshDataDestroy(m_pTriMesh);
dGeomDestroy(m_pCollisionShape);
dBodyDestroy(m_pRigidBody);
}
void PhysicsObject::SyncWithEntity()
{
if (!m_pEntity)
return;
Vec3 position = m_pEntity->m_position;
dBodySetPosition(m_pRigidBody, position.x, position.y, position.z);
}
void PhysicsObject::SyncEntity()
{
if (!m_pEntity)
return;
const dReal* pPos = dBodyGetPosition(m_pRigidBody);
m_pEntity->m_position.x = pPos[0];
m_pEntity->m_position.y = pPos[1];
m_pEntity->m_position.z = pPos[2];
}
float PhysicsObject::GetFriction() const
{
return m_Friction;
}
void PhysicsObject::SetFriction(float friction)
{
m_Friction = friction;
}
void PhysicsObject::SetLinearVelocity(const Vec3& vel)
{
m_LinearVelocity = vel;
dBodySetLinearVel(m_pRigidBody, vel.x, vel.y, vel.z);
}
Vec3 PhysicsObject::GetLinearVelocity() const
{
const dReal* vel = dBodyGetLinearVel(m_pRigidBody);
return Vec3( vel[0], vel[1], vel[2] );
}
void PhysicsObject::SetGravity(const Vec3& gravityVector)
{
m_Gravity = gravityVector;
}
Vec3 PhysicsObject::GetGravity()
{
return m_Gravity;
}

View File

@ -0,0 +1,54 @@
#ifndef PHYSICS_OBJECT_H
#define PHYSICS_OBJECT_H
#include "physics/physics_world.h"
class GameObject;
class PhysicsObject
{
public:
PhysicsObject();
~PhysicsObject();
void CreateTriMesh(const Vec3* vertices, const int verticesCount, const uint32_t* indices, const int indicesCount);
void CreatePlayer();
void CreateSimpleBox();
void CreateSimpleBox_Kinematic();
void Destroy();
inline dGeomID GetShape() { return (m_pCollisionShape); }
inline dGeomID const GetShape() const { return (m_pCollisionShape); }
inline dBodyID GetBody() { return (m_pRigidBody); }
inline dBodyID const GetBody() const { return (m_pRigidBody); }
inline void SetEntity(GameObject* pEntity) { m_pEntity = pEntity; }
inline GameObject* GetEntity() { return (m_pEntity); }
inline GameObject const* GetEntity() const { return (m_pEntity); }
void SyncWithEntity ();
void SyncEntity ();
float GetFriction () const;
void SetFriction (float friction);
void SetLinearVelocity (const Vec3& vel);
Vec3 GetLinearVelocity () const;
void SetGravity (const Vec3& gravityVector);
Vec3 GetGravity ();
private:
GameObject* m_pEntity;
dTriMeshDataID m_pTriMesh;
dGeomID m_pCollisionShape;
dBodyID m_pRigidBody;
float m_Friction;
Vec3 m_Gravity;
Vec3 m_LinearVelocity;
};
#endif // !PHYSICS_OBJECT_H

View File

@ -0,0 +1 @@
#include "render/debugrender.h"

View File

@ -0,0 +1,5 @@
#ifndef PHYSICSDEBUGDRAW_H
#define PHYSICSDEBUGDRAW_H
#endif

View File

@ -0,0 +1,171 @@
#include <assert.h>
#include "utils/maths.h"
#include "render/debugrender.h"
#include "physics_world.h"
#include "physics_render.h"
#include "physics_object.h"
#include "game/game_object.h"
#include <ode/collision_trimesh.h>
static void odeNearCollisionCallback(void* _this, dGeomID id1, dGeomID id2)
{
PhysicsWorld* physWorld = (PhysicsWorld*)_this;
return physWorld->NearCollisionCallback(id1, id2);
}
PhysicsWorld* g_PhysicsWorld = nullptr;
PhysicsWorld::PhysicsWorld()
{
m_dynamicsWorld = nullptr;
m_space = nullptr;
}
PhysicsWorld::~PhysicsWorld()
{
}
void PhysicsWorld::Create()
{
m_dynamicsWorld = dWorldCreate();
m_space = dHashSpaceCreate(0);
}
void PhysicsWorld::Destroy()
{
dSpaceDestroy(m_space);
dWorldDestroy(m_dynamicsWorld);
}
void PhysicsWorld::Update(float deltaTime)
{
dSpaceCollide(m_space, this, &odeNearCollisionCallback);
dWorldQuickStep(m_dynamicsWorld, 1);
//dWorldStep(m_dynamicsWorld, 0.05);
//dWorldQuickStep(m_dynamicsWorld, stepSize);
}
void PhysicsWorld::DebugDraw()
{
for (int i = 0; i < m_objects.size(); i++)
{
PhysicsObject* obj = m_objects[i];
if (dGeomID geom = obj->GetShape())
{
int type = dGeomGetClass(geom);
switch(type)
{
//case dSphereClass:
//case dBoxClass:
//case dTriMeshClass:
//{
// //float rad = dGeomSphereGetRadius(geom);
// //GLUquadric* q = gluNewQuadric();
// //gluSphere(q, rad, 8, 8); break;
//}
case dBoxClass:
{
}
break;
case dTriMeshClass:
{
// not supported yet
}
break;
case dSphereClass:
{
float rad = dGeomSphereGetRadius(geom);
glm::mat4 m = obj->GetEntity()->GetModelMatrix();
m = glm::scale(m, glm::vec3(RadtoDeg(rad)));
g_debugRender->DrawEllipse(m, Vec3(0.5f, 0.5f, 1.0f));
}
break;
default:
printf(" UNKNOWN OBJECT CLASS!\n");
break;
}
}
}
}
dWorldID PhysicsWorld::GetWorld()
{
return m_dynamicsWorld;
}
dSpaceID PhysicsWorld::GetSpace()
{
return m_space;
}
void PhysicsWorld::AddObject(PhysicsObject* object)
{
std::vector<PhysicsObject*>::iterator it = std::find(
m_objects.begin(),
m_objects.end(),
object
);
assert(it == m_objects.end());
m_objects.push_back(object);
}
void PhysicsWorld::RemoveObject(PhysicsObject* object)
{
std::vector<PhysicsObject*>::iterator it = std::find(
m_objects.begin(),
m_objects.end(),
object
);
assert(it != m_objects.end());
m_objects.erase(it);
}
void PhysicsWorld::SetGravity(const Vec3& gravityVector)
{
dWorldSetGravity(m_dynamicsWorld, gravityVector.x, gravityVector.y, gravityVector.z);
}
Vec3 PhysicsWorld::GetGravity()
{
dVector3 g;
dWorldGetGravity(m_dynamicsWorld, g);
return Vec3(g[0], g[1], g[2]);
}
void PhysicsWorld::NearCollisionCallback(dGeomID id1, dGeomID id2)
{
}
void PhysicsInit()
{
dInitODE2(0);
g_PhysicsWorld = new PhysicsWorld();
g_PhysicsWorld->Create();
}
void PhysicsShutdown()
{
if (g_PhysicsWorld)
{
g_PhysicsWorld->Destroy();
delete g_PhysicsWorld;
g_PhysicsWorld = nullptr;
}
dCloseODE();
}

View File

@ -0,0 +1,46 @@
#ifndef PHYSICS_WORLD_H
#define PHYSICS_WORLD_H
#include <vector>
#define dDOUBLE
#include <ode/ode.h>
class PhysicsObject;
class PhysicsWorld
{
public:
PhysicsWorld();
~PhysicsWorld();
void Create();
void Destroy();
void Update(float deltaTime);
void DebugDraw();
dWorldID GetWorld();
dSpaceID GetSpace();
void AddObject(PhysicsObject* object);
void RemoveObject(PhysicsObject* object);
void SetGravity(const Vec3& gravityVector);
Vec3 GetGravity();
void NearCollisionCallback(dGeomID id1, dGeomID id2);
private:
std::vector<PhysicsObject*> m_objects;
dWorldID m_dynamicsWorld;
dSpaceID m_space;
};
extern PhysicsWorld* g_PhysicsWorld;
void PhysicsInit();
void PhysicsShutdown();
#endif // !PHYSICS_WORLD_H

52
src/engine/render/color.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef _COLOR_H_
#define _COLOR_H_
#pragma once
//#define MAKE_ARGB(a,r,g,b) \
// ((uint32_t)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
//#define MAKE_RGBA(r,g,b,a) MAKE_ARGB(a,r,g,b)
//#define MAKE_XRGB(r,g,b) MAKE_ARGB(0xff,r,g,b)
//
//#define GET_A(argb) (((argb&0xff000000)>>24)&0xff)
//#define GET_R(argb) (((argb&0x00ff0000)>>16)&0xff)
//#define GET_G(argb) (((argb&0x0000ff00)>>8)&0xff)
//#define GET_B(argb) ((argb&0x000000ff)&0xff)
//#define GET_COLOR(argb) \
// (Color({\
// GET_A(argb),\
// GET_R(argb),\
// GET_G(argb),\
// GET_B(argb)\
// }))
//
//namespace BasicColor
//{
// enum EBasicColor
// {
// eWhite = MAKE_XRGB(255, 255, 255),
// eBlack = MAKE_XRGB(0, 0, 0),
// eRed = MAKE_XRGB(255, 0, 0),
// eGreen = MAKE_XRGB(0, 255, 0),
// eBlue = MAKE_XRGB(0, 0, 255),
// eYellow = MAKE_XRGB(255, 255, 0),
// eCyan = MAKE_XRGB(0, 255, 255),
// eMagenta = MAKE_XRGB(255, 0, 255)
// };
//};
struct Color
{
union
{
struct
{
uint8_t a;
uint8_t r;
uint8_t g;
uint8_t b;
};
uint32_t argb;
};
};
#endif

View File

@ -0,0 +1,341 @@
#include "render/debugrender.h"
#include "render/render_shared.h"
#include "render/render.h"
#include "render/renderdevice.h"
#include "render/vertexbuffer.h"
#include "render/shadersystem.h"
#include "glad/glad.h"
struct DebugVertex
{
Vec3 position;
Vec3 color;
};
static InputLayoutDesc_t g_debugRenderLayout[] =
{
{ VERTEXATTR_VEC3, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC3, SHADERSEMANTIC_COLOR }
};
const int kEllipseVertexBufferSize = 114;
const int kEllipseIndexBufferSize = 672;
void FillVertexBuffer( VertexBuffer* _pVertexBuffer, const Vec3& _Color )
{
static Vec3 previousColor = Vec3(0.0f, 0.0f, 0.0f);
if (previousColor.x == _Color.x &&
previousColor.y == _Color.y &&
previousColor.z == _Color.z)
return;
float vertices[] =
{
0.0000f,0.0000f,1.0000f, 0.0000f,0.3827f,0.9239f, -0.1464f,0.3536f,0.9239f,
-0.2706f,0.2706f,0.9239f, -0.3536f,0.1464f,0.9239f, -0.3827f,0.0000f,0.9239f,
-0.3536f,-0.1464f,0.9239f, -0.2706f,-0.2706f,0.9239f, -0.1464f,-0.3536f,0.9239f,
0.0000f,-0.3827f,0.9239f, 0.1464f,-0.3536f,0.9239f, 0.2706f,-0.2706f,0.9239f,
0.3536f,-0.1464f,0.9239f, 0.3827f,0.0000f,0.9239f, 0.3536f,0.1464f,0.9239f,
0.2706f,0.2706f,0.9239f, 0.1464f,0.3536f,0.9239f, 0.0000f,0.7071f,0.7071f,
-0.2706f,0.6533f,0.7071f, -0.5000f,0.5000f,0.7071f, -0.6533f,0.2706f,0.7071f,
-0.7071f,0.0000f,0.7071f, -0.6533f,-0.2706f,0.7071f, -0.5000f,-0.5000f,0.7071f,
-0.2706f,-0.6533f,0.7071f, 0.0000f,-0.7071f,0.7071f, 0.2706f,-0.6533f,0.7071f,
0.5000f,-0.5000f,0.7071f, 0.6533f,-0.2706f,0.7071f, 0.7071f,0.0000f,0.7071f,
0.6533f,0.2706f,0.7071f, 0.5000f,0.5000f,0.7071f, 0.2706f,0.6533f,0.7071f,
0.0000f,0.9239f,0.3827f, -0.3536f,0.8536f,0.3827f, -0.6533f,0.6533f,0.3827f,
-0.8536f,0.3536f,0.3827f, -0.9239f,0.0000f,0.3827f, -0.8536f,-0.3536f,0.3827f,
-0.6533f,-0.6533f,0.3827f, -0.3536f,-0.8536f,0.3827f, 0.0000f,-0.9239f,0.3827f,
0.3536f,-0.8536f,0.3827f, 0.6533f,-0.6533f,0.3827f, 0.8536f,-0.3536f,0.3827f,
0.9239f,0.0000f,0.3827f, 0.8536f,0.3536f,0.3827f, 0.6533f,0.6533f,0.3827f,
0.3536f,0.8536f,0.3827f, 0.0000f,1.0000f,0.0000f, -0.3827f,0.9239f,0.0000f,
-0.7071f,0.7071f,0.0000f, -0.9239f,0.3827f,0.0000f, -1.0000f,0.0000f,0.0000f,
-0.9239f,-0.3827f,0.0000f, -0.7071f,-0.7071f,0.0000f, -0.3827f,-0.9239f,0.0000f,
0.0000f,-1.0000f,0.0000f, 0.3827f,-0.9239f,0.0000f, 0.7071f,-0.7071f,0.0000f,
0.9239f,-0.3827f,0.0000f, 1.0000f,0.0000f,0.0000f, 0.9239f,0.3827f,0.0000f,
0.7071f,0.7071f,0.0000f, 0.3827f,0.9239f,0.0000f, 0.0000f,0.9239f,-0.3827f,
-0.3536f,0.8536f,-0.3827f, -0.6533f,0.6533f,-0.3827f, -0.8536f,0.3536f,-0.3827f,
-0.9239f,0.0000f,-0.3827f, -0.8536f,-0.3536f,-0.3827f, -0.6533f,-0.6533f,-0.3827f,
-0.3536f,-0.8536f,-0.3827f, 0.0000f,-0.9239f,-0.3827f, 0.3536f,-0.8536f,-0.3827f,
0.6533f,-0.6533f,-0.3827f, 0.8536f,-0.3536f,-0.3827f, 0.9239f,0.0000f,-0.3827f,
0.8536f,0.3536f,-0.3827f, 0.6533f,0.6533f,-0.3827f, 0.3536f,0.8536f,-0.3827f,
0.0000f,0.7071f,-0.7071f, -0.2706f,0.6533f,-0.7071f, -0.5000f,0.5000f,-0.7071f,
-0.6533f,0.2706f,-0.7071f, -0.7071f,0.0000f,-0.7071f, -0.6533f,-0.2706f,-0.7071f,
-0.5000f,-0.5000f,-0.7071f, -0.2706f,-0.6533f,-0.7071f, 0.0000f,-0.7071f,-0.7071f,
0.2706f,-0.6533f,-0.7071f, 0.5000f,-0.5000f,-0.7071f, 0.6533f,-0.2706f,-0.7071f,
0.7071f,0.0000f,-0.7071f, 0.6533f,0.2706f,-0.7071f, 0.5000f,0.5000f,-0.7071f,
0.2706f,0.6533f,-0.7071f, 0.0000f,0.3827f,-0.9239f, -0.1464f,0.3536f,-0.9239f,
-0.2706f,0.2706f,-0.9239f, -0.3536f,0.1464f,-0.9239f, -0.3827f,0.0000f,-0.9239f,
-0.3536f,-0.1464f,-0.9239f, -0.2706f,-0.2706f,-0.9239f, -0.1464f,-0.3536f,-0.9239f,
0.0000f,-0.3827f,-0.9239f, 0.1464f,-0.3536f,-0.9239f, 0.2706f,-0.2706f,-0.9239f,
0.3536f,-0.1464f,-0.9239f, 0.3827f,0.0000f,-0.9239f, 0.3536f,0.1464f,-0.9239f,
0.2706f,0.2706f,-0.9239f, 0.1464f,0.3536f,-0.9239f, 0.0000f,0.0000f,-1.0000f
};
const int vcnt = sizeof(vertices) / (sizeof(float) * 3);
DebugVertex verts[vcnt];
for (int i = 0; i < vcnt; i++) {
int k = i * 3;
verts[i].position.x = vertices[k];
verts[i].position.y = vertices[k + 1];
verts[i].position.z = vertices[k + 2];
verts[i].color = _Color;
}
DebugVertex* pAGPMemory = ( DebugVertex* )_pVertexBuffer->MapBuffer( BufferAccess::WRITE_ONLY );
memcpy( pAGPMemory, verts, sizeof( verts ) );
_pVertexBuffer->UnmapBuffer();
previousColor = _Color;
}
IndexBuffer* CreateEllipseIndexBuffer()
{
uint16_t faces[224 * 3] =
{
0,1,2, 0,2,3, 0,3,4, 0,4,5, 0,5,6, 0,6,7, 0,7,8, 0,8,9, 0,9,10,
0,10,11, 0,11,12, 0,12,13, 0,13,14, 0,14,15, 0,15,16, 0,16,1, 1,17,18, 1,18,2,
2,18,19, 2,19,3, 3,19,20, 3,20,4, 4,20,21, 4,21,5, 5,21,22, 5,22,6, 6,22,23,
6,23,7, 7,23,24, 7,24,8, 8,24,25, 8,25,9, 9,25,26, 9,26,10, 10,26,27, 10,27,11,
11,27,28, 11,28,12, 12,28,29, 12,29,13, 13,29,30, 13,30,14, 14,30,31, 14,31,15, 15,31,32,
15,32,16, 16,32,17, 16,17,1, 17,33,34, 17,34,18, 18,34,35, 18,35,19, 19,35,36, 19,36,20,
20,36,37, 20,37,21, 21,37,38, 21,38,22, 22,38,39, 22,39,23, 23,39,40, 23,40,24, 24,40,41,
24,41,25, 25,41,42, 25,42,26, 26,42,43, 26,43,27, 27,43,44, 27,44,28, 28,44,45, 28,45,29,
29,45,46, 29,46,30, 30,46,47, 30,47,31, 31,47,48, 31,48,32, 32,48,33, 32,33,17, 33,49,50,
33,50,34, 34,50,51, 34,51,35, 35,51,52, 35,52,36, 36,52,53, 36,53,37, 37,53,54, 37,54,38,
38,54,55, 38,55,39, 39,55,56, 39,56,40, 40,56,57, 40,57,41, 41,57,58, 41,58,42, 42,58,59,
42,59,43, 43,59,60, 43,60,44, 44,60,61, 44,61,45, 45,61,62, 45,62,46, 46,62,63, 46,63,47,
47,63,64, 47,64,48, 48,64,49, 48,49,33, 49,65,66, 49,66,50, 50,66,67, 50,67,51, 51,67,68,
51,68,52, 52,68,69, 52,69,53, 53,69,70, 53,70,54, 54,70,71, 54,71,55, 55,71,72, 55,72,56,
56,72,73, 56,73,57, 57,73,74, 57,74,58, 58,74,75, 58,75,59, 59,75,76, 59,76,60, 60,76,77,
60,77,61, 61,77,78, 61,78,62, 62,78,79, 62,79,63, 63,79,80, 63,80,64, 64,80,65, 64,65,49,
65,81,82, 65,82,66, 66,82,83, 66,83,67, 67,83,84, 67,84,68, 68,84,85, 68,85,69, 69,85,86,
69,86,70, 70,86,87, 70,87,71, 71,87,88, 71,88,72, 72,88,89, 72,89,73, 73,89,90, 73,90,74,
74,90,91, 74,91,75, 75,91,92, 75,92,76, 76,92,93, 76,93,77, 77,93,94, 77,94,78, 78,94,95,
78,95,79, 79,95,96, 79,96,80, 80,96,81, 80,81,65, 81,97,98, 81,98,82, 82,98,99, 82,99,83,
83,99,100, 83,100,84, 84,100,101, 84,101,85, 85,101,102, 85,102,86, 86,102,103, 86,103,87, 87,103,104,
87,104,88, 88,104,105, 88,105,89, 89,105,106, 89,106,90, 90,106,107, 90,107,91, 91,107,108, 91,108,92,
92,108,109, 92,109,93, 93,109,110, 93,110,94, 94,110,111, 94,111,95, 95,111,112, 95,112,96, 96,112,97,
96,97,81, 113,98,97, 113,99,98, 113,100,99, 113,101,100, 113,102,101, 113,103,102, 113,104,103, 113,105,104,
113,106,105, 113,107,106, 113,108,107, 113,109,108, 113,110,109, 113,111,110, 113,112,111, 113,97,112
};
return g_renderDevice->CreateIndexBuffer(faces, sizeof(faces));
}
bool g_drawDebug = false;
DebugRender* g_debugRender;
DebugRender::DebugRender()
{
m_verticesBuffer = nullptr;
m_ellipseVertexBuffer = nullptr;
m_ellipseIndexBuffer = nullptr;
m_shader = nullptr;
}
DebugRender::~DebugRender()
{
m_verticesBuffer = nullptr;
m_shader = nullptr;
}
void DebugRender::Initialize()
{
float points[12];
m_verticesBuffer = g_renderDevice->CreateVertexBuffer(points, sizeof(points), true);
m_ellipseVertexBuffer = g_renderDevice->CreateVertexBuffer(nullptr, kEllipseVertexBufferSize * sizeof(DebugVertex), true);
m_ellipseIndexBuffer = CreateEllipseIndexBuffer();
m_shader = g_shaderSystem->CreateShader("debug_draw",
"content/shaders/debug_draw.vs",
"content/shaders/debug_draw.ps",
g_debugRenderLayout,
sizeof(g_debugRenderLayout) / sizeof(g_debugRenderLayout[0]));
m_shader->m_stride = sizeof(DebugVertex);
glGenVertexArrays(1, &m_vao);
}
void DebugRender::Shutdown()
{
glDeleteVertexArrays(1, &m_vao);
if (m_ellipseIndexBuffer) {
delete m_ellipseIndexBuffer;
m_ellipseIndexBuffer = nullptr;
}
if (m_ellipseVertexBuffer) {
delete m_ellipseVertexBuffer;
m_ellipseVertexBuffer = nullptr;
}
if (m_verticesBuffer) {
delete m_verticesBuffer;
m_verticesBuffer = nullptr;
}
}
void DebugRender::DrawLine(const Vec3& from, const Vec3& to, const 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::DrawBoundingBox(const BoundingBox& box, const glm::vec3& color)
{
glm::vec3 from = glm::vec3(box.min.x, box.min.y, box.min.z);
glm::vec3 to = glm::vec3(box.max.x, box.max.y, box.max.z);
glm::vec3 halfExtents = (to - from) * 0.5f;
glm::vec3 center = (to + from) * 0.5f;
int i, j;
glm::vec3 edgecoord(1.f, 1.f, 1.f), pa, pb;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 3; j++)
{
pa = glm::vec3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
edgecoord[2] * halfExtents[2]);
pa += center;
int othercoord = j % 3;
edgecoord[othercoord] *= -1.f;
pb = glm::vec3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
edgecoord[2] * halfExtents[2]);
pb += center;
DrawLine(Vec3(pa.x, pa.y, pa.z), Vec3(pb.x, pb.y, pb.z) , Vec3(color.x, color.y, color.z) );
}
edgecoord = glm::vec3(-1.f, -1.f, -1.f);
if (i < 3)
edgecoord[i] *= -1.f;
}
}
void DebugRender::DrawEllipse(const glm::mat4& trans, const Vec3& color)
{
EllipseDrawCmd drawCmd = {};
drawCmd.trans = trans;
drawCmd.color = color;
m_ellipseDrawCmd.push_back(drawCmd);
}
void DebugRender::RenderFrame()
{
if (!g_drawDebug)
return;
BeginDraw();
// draw lines
DrawLinesInternal();
// and clear them
m_lines.clear();
// Draw cmds
DrawCmds();
// and clear them
m_ellipseDrawCmd.clear();
EndDraw();
}
void DebugRender::DrawAxis(const Vec3& vec)
{
const float length = 0.2f;
DrawLine(vec, Vec3(vec.x + length, vec.y, vec.z), Vec3(1.0f, 0.0, 0.0f));
DrawLine(vec, Vec3(vec.x, vec.y + length, vec.z), Vec3(0.0f, 0.0f, 1.0f));
DrawLine(vec, Vec3(vec.x, vec.y, vec.z + length), Vec3(0.0f, 1.0f, 0.0f));
}
void DebugRender::BeginDraw()
{
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (int*)&m_savedVao);
glBindVertexArray(m_vao);
}
void DebugRender::EndDraw()
{
glBindVertexArray(m_savedVao);
}
void DebugRender::DrawLinesInternal()
{
if (m_lines.empty())
return;
g_renderDevice->SetDepthTest(true);
g_renderDevice->SetDepthWrite(true);
g_renderDevice->SetVerticesBuffer(m_verticesBuffer);
m_verticesBuffer->UpdateBuffer(m_lines.data(), m_lines.size() * sizeof(Line));
// Bind our shader
g_shaderSystem->SetShader(m_shader);
// #TODO: Fix stupid bug, when we get very far from wireframe and lines can start cliping
View view = g_renderView;
view.proj[2][3] -= 0.0001f;
glm::mat4 mv = glm::identity<glm::mat4>();
mv = view.proj * view.view;
g_shaderSystem->SetUniformMatrix(m_shader, UNIFORM_MVP_MATRIX, &mv[0]);
// draw stuff
g_renderDevice->DrawArrays(PT_LINES, 0, m_lines.size() * 2);
}
void DebugRender::DrawCmds()
{
if (m_ellipseDrawCmd.empty())
return;
g_renderDevice->SetDepthTest(true);
g_renderDevice->SetDepthWrite(true);
g_renderDevice->SetVerticesBuffer(m_ellipseVertexBuffer);
g_renderDevice->SetIndicesBuffer(m_ellipseIndexBuffer);
// Bind our shader
g_shaderSystem->SetShader(m_shader);
for (int i = 0; i < m_ellipseDrawCmd.size(); i++)
{
const EllipseDrawCmd& cmd = m_ellipseDrawCmd[i];
FillVertexBuffer(m_ellipseVertexBuffer, cmd.color);
// #TODO: Fix stupid bug, when we get very far from wireframe and lines can start cliping
View view = g_renderView;
view.proj[2][3] -= 0.0001f;
glm::mat4 mv = glm::identity<glm::mat4>();
mv = view.proj * view.view * cmd.trans;
g_shaderSystem->SetUniformMatrix(m_shader, UNIFORM_MVP_MATRIX, &mv[0]);
// draw stuff
g_renderDevice->DrawElements( PT_LINES, 672, true );
}
}

View File

@ -0,0 +1,68 @@
#ifndef DEBUGRENDER_H
#define DEBUGRENDER_H
#include <vector>
#include <utils/maths.h>
class VertexBuffer;
class IndexBuffer;
class Shader;
class DebugRender
{
public:
DebugRender();
~DebugRender();
void Initialize();
void Shutdown();
void DrawAxis(const Vec3& vec);
void DrawLine(const Vec3& from, const Vec3& to, const Vec3& color);
void DrawBoundingBox(const BoundingBox& box, const glm::vec3& color);
void DrawEllipse(const glm::mat4& trans, const Vec3& color);
void RenderFrame();
private:
void BeginDraw();
void EndDraw();
void DrawLinesInternal();
void DrawCmds();
private:
// Primitives
struct Line
{
Vec3 from;
Vec3 color0;
Vec3 to;
Vec3 color1;
};
struct EllipseDrawCmd
{
glm::mat4 trans;
Vec3 color;
};
std::vector<Line> m_lines;
std::vector<EllipseDrawCmd> m_ellipseDrawCmd;
private:
VertexBuffer* m_verticesBuffer;
VertexBuffer* m_ellipseVertexBuffer;
IndexBuffer* m_ellipseIndexBuffer;
Shader* m_shader;
unsigned int m_vao;
unsigned int m_savedVao;
};
extern DebugRender* g_debugRender;
extern bool g_drawDebug;
#endif // !DEBUGRENDER_H

View File

@ -0,0 +1,76 @@
#include "utils/logger.h"
#include "render/font.h"
#include "render/shader.h"
#include "render/vertexbuffer.h"
#include "render/indexbuffer.h"
#include "render/renderdevice.h"
#include "render/shadersystem.h"
#include "render/ui.h"
#include "render/texture2d.h"
#include "render/texturesmanager.h"
#include <stb_easy_font.h>
struct FontGlobals {
VertexBuffer* vb;
IndexBuffer* ib;
Shader* shader;
UIVertex* vertices = nullptr;
uint16_t* indices = nullptr;
uint16_t count = 0;
uint16_t position = 0;
uint16_t Indexposition = 0;
uint16_t currentIdx = 0;
} g_font;
void fontInit()
{
// Create vertex and index buffer
// same as ui
g_font.vb = g_renderDevice->CreateVertexBuffer( nullptr, MAX_UI_VERTICES, true );
// Create shader
InputLayoutDesc_t inputLayout[] =
{
{ VERTEXATTR_VEC2, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD },
{ VERTEXATTR_VEC4, SHADERSEMANTIC_COLOR },
};
g_font.shader = g_shaderSystem->CreateShader("ui_base", "content/shaders/ui_base.vs", "content/shaders/ui_base.ps", inputLayout, sizeof(inputLayout) / sizeof(inputLayout[0]));
g_font.shader->m_stride = sizeof( UIVertex );
}
void fontShutdown()
{
delete g_font.ib;
delete g_font.vb;
}
inline unsigned char toByteColor(const Vec4& color)
{
}
void fontDrawString(const char* text, float x, float y, float w, float h, const Vec4& color)
{
// lock buffers
UIVertex* vertices = (UIVertex*)g_font.vb->MapBuffer(BufferAccess::WRITE_ONLY);
//int num_quads = stb_easy_font_print(x, y, (char*)text, , buffer, sizeof(buffer));
//static char buffer[99999]; // ~500 chars
//int num_quads;
//num_quads = stb_easy_font_print(x, y, (char*)text, NULL, buffer, sizeof(buffer));
//glColor3f(r, g, b);
//glEnableClientState(GL_VERTEX_ARRAY);
//glVertexPointer(2, GL_FLOAT, 16, buffer);
//glDrawArrays(GL_QUADS, 0, num_quads * 4);
//glDisableClientState(GL_VERTEX_ARRAY);
}

10
src/engine/render/font.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef FONT_H
#define FONT_H
#include <utils/maths.h>
void fontInit();
void fontShutdown();
void fontDrawString(const char* text, float x, float y, float w, float h, const Vec4& color);
#endif // !FONT_H

View File

@ -0,0 +1,44 @@
#include "utils/logger.h"
#include "render/gl_shared.h"
const char *GL_ErrorString( int err )
{
switch( err )
{
case GL_STACK_OVERFLOW:
return "GL_STACK_OVERFLOW";
case GL_STACK_UNDERFLOW:
return "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));
}

View File

@ -0,0 +1,17 @@
#ifndef GL_SHARED_H
#define GL_SHARED_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

View File

@ -0,0 +1,56 @@
#include "render/indexbuffer.h"
#include "render/gl_shared.h"
IndexBuffer::IndexBuffer(void* data, size_t size, bool isStream /*= false*/)
{
glGenBuffers(1, &m_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, isStream ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//if (isStream) {
// Logger::msg("created dynamic index stream ...");
//}
}
IndexBuffer::~IndexBuffer()
{
glDeleteBuffers(1, &m_buffer);
}
void IndexBuffer::Bind()
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer);
}
void* IndexBuffer::MapBuffer(BufferAccess access)
{
GLenum accessGl = 0;
switch (access)
{
case BufferAccess::READ_ONLY:
accessGl = GL_READ_ONLY;
break;
case BufferAccess::WRITE_ONLY:
accessGl = GL_WRITE_ONLY;
break;
case BufferAccess::READ_WRITE:
accessGl = GL_READ_WRITE;
break;
}
Bind();
void* ptr = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, accessGl);
//check_for_opengl_error();
return ptr;
}
void IndexBuffer::UnmapBuffer()
{
Bind();
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}

View File

@ -0,0 +1,26 @@
#ifndef INDEXOBJECT_H
#define INDEXOBJECT_H
#include <stdint.h>
#include "render/render_shared.h"
class RenderDevice;
class IndexBuffer
{
friend class RenderDevice;
public:
~IndexBuffer();
void* MapBuffer(BufferAccess access);
void UnmapBuffer();
void Bind();
private:
IndexBuffer(void* data, size_t size, bool isStream = false);
uint32_t m_buffer;
};
#endif // !INDEXOBJECT_H

View File

@ -0,0 +1,373 @@
#include <assert.h>
#include <vector>
#include <string>
#include <utils/logger.h>
#include <utils/maths.h>
#include <utils/timer.h>
#include <filesystem/filemanager.h>
#include <input/input_system.h>
#include <render/vertexbuffer.h>
#include <render/indexbuffer.h>
#include <render/renderdevice.h>
#include <render/modelmanager.h>
#include <render/shader.h>
#include <render/shadersystem.h>
#include <render/texturesmanager.h>
#include <render/texture2d.h>
#include <render/debugrender.h>
ModelManager* g_modelManager = 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;
ModelManager::ModelManager()
{
}
ModelManager::~ModelManager()
{
}
VertexBuffer* ModelManager::CreateVertexBuffer( void* data, int size )
{
// create vertex buffer
VertexBuffer* vb = g_renderDevice->CreateVertexBuffer( data, size );
return vb;
}
IndexBuffer* ModelManager::CreateIndexBuffer( void* data, int size )
{
// create index buffer
IndexBuffer* ib = g_renderDevice->CreateIndexBuffer( data, size );
return ib;
}
Model* ModelManager::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 (!g_fileManager->FileExist(filename))
{
Logger::logPrint("ModelManager::LoadModel: File '%s' not exist.", filename);
return nullptr;
}
Model* model = new Model();
if (strstr(filename, ".obj"))
{
model->LoadObj(filename);
}
else
{
Logger::logPrint("ModelManager::LoadModel(%s): Unknowed file format '%s'",
filename, fs::getFileExtension(filename).c_str());
return nullptr;
}
ModelEntry entry = {};
strcpy(entry.filename, filename);
entry.model = model;
m_models.push_back(entry);
Logger::logPrint("ModelManager::LoadModel: Loaded '%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_data.vb = g_modelManager->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
m_data.vbcount = vertices.size();
std::string mtlfilename = fs::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_texturesManager->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::LoadIQM( const char* filename )
{
}
void Model::Draw( const glm::mat4& model, bool isTransparent /*= false*/ )
{
if (!g_litShader)
{
g_litShader = g_shaderSystem->CreateShader("lit_generic", "content/shaders/lit_generic.vs", "content/shaders/lit_generic.ps",
g_staticVertexLayout, sizeof(g_staticVertexLayout) / sizeof(g_staticVertexLayout[0]));
g_litShader->m_stride = sizeof(StaticMeshVertex);
}
g_renderDevice->SetDepthTest(true);
g_renderDevice->SetDepthWrite(true);
if (isTransparent)
{
// Enable blending
g_renderDevice->SetBlending(true);
g_renderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f);
g_shaderSystem->SetUniformFloat4( g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr( color ) );
}
else
{
g_renderDevice->SetBlending(false);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f);
g_shaderSystem->SetUniformFloat4( g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr( color ) );
}
g_renderDevice->SetVerticesBuffer(m_data.vb);
g_shaderSystem->SetShader(g_litShader);
g_shaderSystem->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_renderView.proj * g_renderView.view * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_texturesManager->SetTexture( 0, m_AlbedoTexture );
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
}
void ReleaseModelData(ModelData_t& data)
{
if (data.ib)
{
delete data.ib;
data.ib = nullptr;
}
if (data.vb)
{
delete data.vb;
data.vb = nullptr;
}
}

View File

@ -0,0 +1,75 @@
#ifndef MODELMANAGER_H
#define MODELMANAGER_H
#include <vector>
#include <utils/maths.h>
class VertexBuffer;
class IndexBuffer;
class Texture2D;
struct StaticMeshVertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 texcoord;
};
struct ModelData_t
{
VertexBuffer* vb;
IndexBuffer* ib;
uint32_t vbcount;
uint32_t ibcount;
};
void ReleaseModelData(ModelData_t& data);
class Model
{
public:
Model();
~Model();
void LoadObj( const char* filename );
void LoadMtl( const char* filename );
void LoadIQM( const char* filename );
void Draw( const glm::mat4& model, bool isTransparent = false );
BoundingBox GetBoundingBox() { return m_boundingBox; }
private:
ModelData_t m_data;
BoundingBox m_boundingBox;
Texture2D* m_AlbedoTexture;
};
class ModelManager
{
public:
ModelManager();
~ModelManager();
// Buffer creation
VertexBuffer* CreateVertexBuffer( void* data, int size );
IndexBuffer* CreateIndexBuffer( void* data, int size );
Model* LoadModel(const char* filename);
private:
struct ModelEntry
{
char filename[260];
Model* model;
};
std::vector< ModelEntry > m_models;
};
extern ModelManager* g_modelManager;
#endif // !MODELMANAGER_H

View File

@ -0,0 +1,396 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <assert.h>
#include <glad/glad.h>
#include <GL/wglext.h>
#include <utils/logger.h>
#include <utils/win32_keys.h>
#include <render/render.h>
#include <render/renderdevice.h>
#include <render/texturesmanager.h>
#include <render/shadersystem.h>
#include <render/modelmanager.h>
#include <render/ui.h>
#include <render/debugrender.h>
#include <game/game_app.h>
#pragma comment(lib, "OpenGL32.lib")
View g_renderView;
Render* g_render = NULL;
HDC g_hDC = NULL;
HGLRC g_openglContext = NULL;
GLuint g_vao = 0;
void CreateOpenGL( HWND hWnd )
{
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, // Number of bits for the depthbuffer
8, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
g_hDC = GetDC( hWnd );
int pixelFormat = ChoosePixelFormat( g_hDC, &pfd );
SetPixelFormat( g_hDC, pixelFormat, &pfd );
HGLRC tempContext = wglCreateContext( g_hDC );
wglMakeCurrent( g_hDC, tempContext );
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
assert(wglCreateContextAttribsARB);
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_FLAGS_ARB, 0,
0
};
g_openglContext = wglCreateContextAttribsARB( g_hDC, 0, attribs );
wglMakeCurrent( NULL, NULL );
wglDeleteContext( tempContext );
wglMakeCurrent( g_hDC, g_openglContext );
}
Render::Render() : m_window(nullptr)
{
}
Render::~Render()
{
}
void Render::Init()
{
Msg("Initializing renderer ...");
m_window = WND_CreateWindow(0, 0, 1280, 720, "Game");
CreateOpenGL( (HWND)m_window );
gladLoadGL();
int width = 0, height = 0;
WND_GetWindowSize(m_window, &width, &height);
g_renderView.width = width;
g_renderView.height = height;
// Create render device
g_renderDevice = new RenderDevice();
// Create texture manager
g_texturesManager = new TexturesManager();
g_texturesManager->Init();
// Create shader system
g_shaderSystem = new ShaderSystem();
g_shaderSystem->Init();
// Create model manager
g_modelManager = new ModelManager();
// Create debug render
g_debugRender = new DebugRender();
g_debugRender->Initialize();
g_drawDebug = true;
// Create UI System
uiInit();
// Create global vertex array
glGenVertexArrays(1, &g_vao);
glBindVertexArray(g_vao);
}
void Render::Shutdown()
{
glBindVertexArray(0);
glDeleteVertexArrays(1, &g_vao);
uiShutdown();
g_debugRender->Shutdown();
delete g_debugRender;
g_debugRender = nullptr;
delete g_modelManager;
g_modelManager = nullptr;
g_shaderSystem->Shutdown();
delete g_shaderSystem;
g_shaderSystem = nullptr;
g_texturesManager->Shutdown();
delete g_texturesManager;
g_texturesManager = nullptr;
delete g_renderDevice;
g_renderDevice = nullptr;
}
void Render::BeginFrame()
{
BuildRenderView();
int width = 0, height = 0;
WND_GetWindowSize(m_window, &width, &height);
glViewport( 0, 0, width, height );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
g_renderDevice->SetBackfaceCull(true);
}
void Render::EndFrame()
{
// Flush debug render
g_debugRender->RenderFrame();
SwapBuffers( g_hDC );
}
void Render::DrawFrame()
{
}
void* Render::GetRenderWindow()
{
return m_window;
}
void Render::BuildRenderView()
{
if (g_renderView.fov <= 0.0f)
{
Msg("Render::BuildRenderView: FOV is zero!");
g_renderView.fov = 0.1f;//70.0f;
}
int width = 0, height = 0;
WND_GetWindowSize(m_window, &width, &height);
if (width < 1) width = 1;
if (height < 1) height = 1;
float aspect = (float)width / (float)height;
g_renderView.proj = glm::perspectiveFov(glm::radians(g_renderView.fov), (float)width, (float)height, 0.1f, 1000.0f);
ShowCursor(FALSE);
}
// Windowing
static int s_should_wrap_mouse = FALSE;
static bool s_wndclass_registered = FALSE;
static const char* s_wndclass_name = "DumbWindowClass";
int g_mousex = 0;
int g_mousey = 0;
RECT g_rect = { 0, 0, 0, 0 };
// Should be implemented by library user.
void WND_Callback_Keyboard(void* window, KeyboardKeys key, int nativeKey, int action)
{
if (action)
g_inputSystem->OnKeyDown(key);
else
g_inputSystem->OnKeyUp(key);
}
mouseButton_t GetMouseButton(UINT mouseButton)
{
switch (mouseButton)
{
case MK_LBUTTON:
return mouseButton_Left;
case MK_MBUTTON:
return mouseButton_Middle;
case MK_RBUTTON:
return mouseButton_Right;
default:
break;
}
// #TODO: nameless buttons ???
return GetNamelessMouseButtonIndex(1);
}
LRESULT CALLBACK WND_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
WND_Callback_Keyboard(hwnd, GetKeyFromWin32((Win32Keys::Keys)wParam), (int)wParam, PRESSED);
break;
case WM_KEYUP:
WND_Callback_Keyboard(hwnd, GetKeyFromWin32((Win32Keys::Keys)wParam), (int)wParam, UNPRESSED);
break;
case WM_LBUTTONDOWN:
g_inputSystem->OnMouseKeyDown(mouseButton_Left);
break;
case WM_RBUTTONDOWN:
g_inputSystem->OnMouseKeyDown(mouseButton_Right);
break;
case WM_LBUTTONUP:
g_inputSystem->OnMouseKeyUp(mouseButton_Left);
break;
case WM_RBUTTONUP:
g_inputSystem->OnMouseKeyUp(mouseButton_Right);
break;
case WM_MOUSEHOVER:
ShowCursor(FALSE);
break;
case WM_MOUSELEAVE:
ShowCursor(TRUE);
break;
case WM_MOUSEMOVE:
{
if (s_should_wrap_mouse)
{
GetClientRect(hwnd, &g_rect); // Get window dimension
g_rect.right -= 12; // right offset
g_rect.left += 12; // left offset
g_mousex = LOWORD(lParam); // Get mouse X pos
g_mousey = HIWORD(lParam); // Get mouse Y pos
if (g_mousex >= g_rect.right)
{
SetCursorPos(g_rect.left, g_mousey);
}
else if (g_mousex <= g_rect.left)
{
SetCursorPos(g_rect.right, g_mousey);
}
g_inputSystem->OnMouseMove(g_mousex, g_mousey);
}
else
{
g_mousex = LOWORD(lParam); // Get mouse X pos
g_mousey = HIWORD(lParam); // Get mouse Y pos
g_inputSystem->OnMouseMove(g_mousex, g_mousey);
}
}
break;
default:
break;
}
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
void* WND_CreateWindow(int x, int y, int width, int height, const char* title)
{
if (!s_wndclass_registered)
{
WNDCLASSA wc;
memset(&wc, 0, sizeof(wc));
// wc.hIcon = LoadIconA(GetModuleHandleA(0), MAKEINTRESOURCEA(IDI_ICON1));
wc.lpfnWndProc = WND_WindowProc;
wc.hInstance = GetModuleHandleA(0);
wc.lpszClassName = s_wndclass_name;
RegisterClassA(&wc);
s_wndclass_registered = TRUE;
}
// Window Style
DWORD dwWindowStyle = WS_OVERLAPPEDWINDOW ^ (WS_THICKFRAME | WS_MAXIMIZEBOX);
// Rect
RECT rc = { 0, 0, width, height };
AdjustWindowRect(&rc, dwWindowStyle, FALSE);
HWND hWnd = CreateWindowA(s_wndclass_name, title, dwWindowStyle,
x, y, (rc.right - rc.left), (rc.bottom - rc.top),
NULL, NULL, GetModuleHandleA(0), NULL);
assert(hWnd != INVALID_HANDLE_VALUE);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
return hWnd;
}
void WND_DestroyWindow(void* window)
{
DestroyWindow((HWND)window);
}
void WND_GetWindowSize(void* window, int* x, int* y)
{
RECT rc;
memset(&rc, 0, sizeof(rc));
GetClientRect((HWND)window, &rc);
*x = (rc.right - rc.left);
*y = (rc.bottom - rc.top);
}
bool WND_GetWindowGrab(void* window)
{
return GetFocus() == (HWND)window;
}
void HELPER_GetWindowPos(HWND hWnd, int* x, int* y)
{
RECT rect = { NULL };
if (GetWindowRect(hWnd, &rect))
{
*x = rect.left;
*y = rect.top;
}
}
void WND_SetWindowSize(void* window, int x, int y)
{
int posX = 0, posY = 0;
HELPER_GetWindowPos((HWND)window, &posX, &posY);
MoveWindow((HWND)window, posX, posY, x, y, TRUE);
UpdateWindow((HWND)window);
}
void WND_SetRelativeMouseMode(int value)
{
s_should_wrap_mouse = value;
}

View File

@ -0,0 +1,45 @@
#ifndef RENDER_H
#define RENDER_H
// Render windowing management
enum KEY_ACTION
{
UNPRESSED,
PRESSED,
HOLDING
};
void* WND_CreateWindow(int x, int y, int width, int height, const char* title);
void WND_DestroyWindow(void* window);
void WND_GetWindowSize(void* window, int* x, int* y);
bool WND_GetWindowGrab(void* window);
void WND_SetWindowSize(void* window, int x, int y);
void WND_SetRelativeMouseMode(int value);
class Render
{
public:
Render();
~Render();
void Init();
void Shutdown();
void BeginFrame();
void EndFrame();
void DrawFrame();
void* GetRenderWindow();
private:
void BuildRenderView();
private:
void* m_window;
};
extern Render* g_render;
#endif // !RENDER_H

View File

@ -0,0 +1,84 @@
// Shared header for render stuff
#ifndef RENDER_SHARED_H
#define RENDER_SHARED_H
#include <stdint.h>
#include "utils/maths.h"
#include "render/color.h"
enum class BufferAccess
{
READ_ONLY,
WRITE_ONLY,
READ_WRITE
};
// texture format
enum PixelFormat
{
PF_UNKNOWN,
PF_R8G8B8,
PF_R8G8B8A8,
PF_R8G8B8F,
PF_R8G8B8A8F,
// Depth formats
PF_DEPTH32F
};
// pixel format convertion
uint32_t getGLPF(PixelFormat pf);
uint32_t getGLInternalPF(PixelFormat pf);
uint32_t getGLTypePF(PixelFormat pf);
// 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
};
// Blending factor convertion
uint32_t GetGLBlendFactor(BlendFactor factor);
// 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;
};
// Global instance of render view
extern View g_renderView;
// Stretched picture vertex
struct StretchedVertex
{
Vec3 position;
Vec2 texcoord;
};
#define MAX_STRETCH_VX 12 * sizeof(StretchedVertex)
// debugging stuff
void check_for_opengl_error();
#endif

View File

@ -0,0 +1,202 @@
#include <assert.h>
#include <stdio.h>
// OpenGL
#include "render/gl_shared.h"
// VERTEX AND INDEX OBJECTS
#include "render/vertexbuffer.h"
#include "render/indexbuffer.h"
#include "render/rendertarget.h"
#include "render/renderdevice.h"
RenderDevice* g_renderDevice = nullptr;
RenderDevice::RenderDevice()
{
m_activeVB = nullptr;
m_activeIB = nullptr;
m_blending = false;
m_activeReadRT = nullptr;
m_activeWriteRT = nullptr;
m_backfaceCull = false;
}
RenderDevice::~RenderDevice()
{
}
VertexBuffer* RenderDevice::CreateVertexBuffer(void* data, size_t size, bool isStream)
{
return new VertexBuffer(data, size, isStream);
}
IndexBuffer* RenderDevice::CreateIndexBuffer(void* data, size_t size, bool isStream)
{
return new IndexBuffer(data, size, isStream);
}
void RenderDevice::SetVerticesBuffer(VertexBuffer* buffer)
{
if (buffer) {
if (m_activeVB != buffer) {
m_activeVB = buffer;
m_activeVB->Bind();
}
} else { // unbind buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void RenderDevice::SetIndicesBuffer(IndexBuffer* 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::setVertexFormat(VertexFormat* format)
//{
// assert(format);
//
// if (format->count() == 0) {
// Core::error("RenderDevice::setVertexFormat: failed to set empty vertex format");
// }
//
// size_t appliedOffset = 0;
// for (VertexAttribute* it = format->begin(); it != format->end(); ++it) {
//
// GLenum data_type = get_gl_vertex_attribute_type(it->m_type);
// GLuint data_size = GLuint(get_vertex_attribute_size(it->m_type));
//
// if (appliedOffset > 0)
// glVertexAttribPointer(
// GLuint(it->m_offset),
// GLint(it->m_size),
// data_type,
// GL_FALSE,
// GLsizei(format->size() * data_size),
// (void*)(appliedOffset * sizeof(float))
// );
// else
// glVertexAttribPointer(
// GLuint(it->m_offset),
// GLint(it->m_size),
// data_type,
// GL_FALSE,
// GLsizei(format->size() * data_size),
// (void*)0
// );
//
// glEnableVertexAttribArray(GLuint(it->m_offset));
//
// appliedOffset += it->m_size;
// }
//}
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::SetReadRenderTarget(RenderTarget* renderTarget)
{
if (renderTarget) {
if (m_activeReadRT != renderTarget) {
m_activeReadRT = renderTarget;
glBindFramebuffer(GL_READ_FRAMEBUFFER, renderTarget->m_framebuffer);
}
}
else { // set default rt
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
}
void RenderDevice::SetWriteRenderTarget(RenderTarget* renderTarget)
{
if (renderTarget) {
if (m_activeWriteRT != renderTarget) {
m_activeWriteRT = renderTarget;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderTarget->m_framebuffer);
}
}
else { // set default rt
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
}
void RenderDevice::SetBackfaceCull(bool value)
{
if (m_backfaceCull != value) {
m_backfaceCull = value;
value ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
}
}
void RenderDevice::SetViewport(int x, int y, int w, int h)
{
glViewport(x, y, w, h);
}
void RenderDevice::BlitRenderTarget(int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, TextureSurfaceType surfaceType)
{
GLbitfield mask = 0;
if (surfaceType & TST_COLOR)
mask |= GL_COLOR_BUFFER_BIT;
if (surfaceType & TST_DEPTH)
mask |= GL_DEPTH_BUFFER_BIT;
if (surfaceType & TST_STENCIL)
mask |= GL_STENCIL_BUFFER_BIT;
glBlitFramebuffer(srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, mask, GL_LINEAR);
}
static GLenum g_glPrimitiveMode[PT_TRIANGLES + 1] = {
GL_POINTS,
GL_LINES,
GL_TRIANGLES
};
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);
}

View File

@ -0,0 +1,78 @@
#ifndef RENDERDEVICE_H
#define RENDERDEVICE_H
#include <stdint.h>
#include "render/render_shared.h"
class VertexBuffer;
class IndexBuffer;
class VertexFormat;
class RenderTarget;
enum TextureSurfaceType
{
TST_COLOR = 1 << 0,
TST_DEPTH = 1 << 1,
TST_STENCIL = 1 << 2,
};
enum PrimitiveType
{
PT_POINTS,
PT_LINES,
PT_TRIANGLES
};
class RenderDevice
{
public:
RenderDevice();
~RenderDevice();
VertexBuffer* CreateVertexBuffer(void* data, size_t size, bool isStream = false);
IndexBuffer* CreateIndexBuffer(void* data, size_t size, bool isStream = false);
void SetVerticesBuffer(VertexBuffer* buffer);
void SetIndicesBuffer(IndexBuffer* buffer);
void SetDepthTest(bool enable);
void SetDepthWrite(bool enable);
//void setVertexFormat(VertexFormat* format);
void SetBlending(bool value);
void SetBlendingFunction(BlendFactor srcFactor, BlendFactor destFactor);
void SetReadRenderTarget(RenderTarget* renderTarget);
void SetWriteRenderTarget(RenderTarget* renderTarget);
void SetBackfaceCull(bool value);
void SetViewport(int x, int y, int w, int h);
// glBlitFramebuffer
void BlitRenderTarget(int srcX, int srcY, int srcWidth, int srcHeight,
int destX, int destY, int destWidth, int destHeight,
TextureSurfaceType surfaceType);
// drawing
void DrawArrays(PrimitiveType primType, uint32_t startOf, size_t verticesCount);
void DrawElements(PrimitiveType primType, size_t elementsCount, bool is16bitIndices);
private:
VertexBuffer* m_activeVB;
IndexBuffer* m_activeIB;
RenderTarget* m_activeReadRT;
RenderTarget* m_activeWriteRT;
bool m_blending;
BlendFactor m_srcBlendFactor;
BlendFactor m_destBlendFactor;
bool m_backfaceCull;
};
extern RenderDevice* g_renderDevice;
#endif // !RENDERDEVICE_H

View File

@ -0,0 +1,63 @@
#include <assert.h>
#include "render/rendertarget.h"
#include "render/texturesmanager.h"
#include "render/texture2d.h"
#include "glad/glad.h"
void RenderTarget::setDefaultFramebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
RenderTarget::RenderTarget()
{
m_framebuffer = -1;
}
RenderTarget::~RenderTarget()
{
m_framebuffer = -1;
}
void RenderTarget::create(const char* name /*= nullptr*/)
{
assert(g_texturesManager);
////////////////////////
// Create FBO
// generate frame buffer
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
}
void RenderTarget::destroy()
{
GLint drawFboId;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &drawFboId);
if (drawFboId == (GLint)m_framebuffer)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &m_framebuffer);
}
void RenderTarget::finialize()
{
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
assert(0 && "RenderTarget::finialize: failed to finialize framebuffer. Framebuffer is not complete");
}
}
void RenderTarget::attachColorTexture(int slot, Texture2D* texture)
{
assert(texture && "Failed to assing nullptr texture");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + slot, GL_TEXTURE_2D, texture->GetHandle(), 0);
}
void RenderTarget::attachDepthTexture(Texture2D* texture)
{
assert(texture && "Failed to assing nullptr texture");
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture->GetHandle(), 0);
}

View File

@ -0,0 +1,33 @@
#ifndef RENDERTARGET_H
#define RENDERTARGET_H
#include <stdint.h>
class Texture2D;
class RenderDevice;
class RenderTarget
{
friend class RenderDevice;
public:
// #TODO: Little hack
static void setDefaultFramebuffer();
public:
RenderTarget();
~RenderTarget();
void create(const char* name = nullptr);
void destroy();
void finialize();
void attachColorTexture(int slot, Texture2D* texture);
void attachDepthTexture(Texture2D* texture);
private:
uint32_t m_framebuffer;
};
#endif

View File

@ -0,0 +1,92 @@
#include <assert.h>
#include "utils/logger.h"
#include "render/shader.h"
#include "filesystem/filemanager.h"
#include "filesystem/stream.h"
GLuint CreateShader(GLenum shaderType, const char* filename)
{
StreamBase* stream = g_fileManager->OpenStream( filename, FileAccess::Read );
if ( !stream )
{
Msg( "CreateShader: failed to open file %s", filename );
assert( 0 );
}
stream->seek( SeekDir::End, 0 );
size_t length = stream->tell();
stream->seek( SeekDir::Begin, 0 );
std::string content;
content.resize( length + 1 );
stream->readBuffer( (void*)content.data(), length );
content[length] = '\0';
const char* contentCStr = content.c_str();
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &contentCStr, NULL);
glCompileShader(shader);
int success;
char infoLog[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 512, NULL, infoLog);
Msg("Failed to compile shader %s\n%s", filename, infoLog);
}
Msg("created shader from file %s", filename);
return shader;
}
Shader::Shader() :
m_name(nullptr),
m_stride(0),
m_layout_count(0)
{
}
Shader::~Shader()
{
if (m_name)
free( (void*)m_name );
Destroy();
}
void Shader::Create(const char* name, const char* vsfilepath, const char* psfilepath)
{
//m_name = strdup( name );
GLuint vertexShader = CreateShader(GL_VERTEX_SHADER, vsfilepath);
GLuint fragmentShader = CreateShader(GL_FRAGMENT_SHADER, psfilepath);
m_program = glCreateProgram();
glAttachShader(m_program, vertexShader);
glAttachShader(m_program, fragmentShader);
AllocateAttributes();
glLinkProgram(m_program);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
int success;
char infoLog[512];
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(m_program, 512, NULL, infoLog);
Msg("Failed to link program %s", infoLog);
}
}
void Shader::Destroy()
{
glDeleteProgram(m_program);
}

View File

@ -0,0 +1,98 @@
#ifndef SHADER_H
#define SHADER_H
#include <stdint.h>
#include <glad/glad.h>
const int SHADERUNIFORM_MAX_COUNT = 16;
const int INPUT_LAYOUT_MAX_COUNT = 8;
enum VertexAttribute_t {
VERTEXATTR_VEC2,
VERTEXATTR_VEC3,
VERTEXATTR_VEC4,
VERTEXATTR_MAX
};
enum ShaderSemantic_t {
SHADERSEMANTIC_POSITION,
SHADERSEMANTIC_COLOR,
SHADERSEMANTIC_TEXCOORD,
SHADERSEMANTIC_TEXCOORD0,
SHADERSEMANTIC_TEXCOORD1,
SHADERSEMANTIC_NORMAL,
SHADERSEMANTIC_TANGENT,
SHADERSEMANTIC_BITANGENT,
SHADERSEMANTIC_MAX
};
enum ShaderUniformType_t {
SHADERUNIFORM_FLOAT,
SHADERUNIFORM_VEC2,
SHADERUNIFORM_VEC3,
SHADERUNIFORM_VEC4,
SHADERUNIFORM_MAT4,
SHADERUNIFORM_MAX
};
struct InputLayoutDesc_t {
VertexAttribute_t attribute;
ShaderSemantic_t semantic;
};
struct ShaderUniformDesc_t {
ShaderUniformType_t type;
const char* name;
size_t size;
};
class Shader
{
public:
Shader();
~Shader();
void Create(const char* name, const char* vsfilepath, const char* psfilepath);
void Destroy();
void AllocateAttributes();
public:
// TEMP SOLUTION
ShaderUniformDesc_t m_uniform_desc[SHADERUNIFORM_MAX_COUNT];
size_t m_uniform_count;
InputLayoutDesc_t m_layouts[INPUT_LAYOUT_MAX_COUNT];
size_t m_layout_count;
GLuint m_glLayouts[INPUT_LAYOUT_MAX_COUNT];
// #TODO: REMOVE PLEASE
int m_stride;
const char* m_name;
GLuint m_program;
};
inline int GetVertexAttributeSize( VertexAttribute_t attrib )
{
switch ( attrib )
{
case VERTEXATTR_VEC2:
return 2;
case VERTEXATTR_VEC3:
return 3;
case VERTEXATTR_VEC4:
return 4;
default:
break;
}
return 0;
}
#endif // !SHADER_H

View File

@ -0,0 +1,190 @@
#include <assert.h>
#include <algorithm>
#include "utils/logger.h"
#include "render/shadersystem.h"
#include "render/shader.h"
#include <render/gl_shared.h>
static const char* g_uniformNameTable[UNIFORM_MAX] =
{
"u_modelMatrix",
"u_viewMatrix",
"u_projectionMatrix",
"u_modelViewProjection",
"u_customColor",
"u_sunDirection",
"u_sunColor",
"u_sunAmbientColor",
};
static const char* g_samplersNameTable[SAMPLER_MAX] =
{
"u_albedoTexture",
"u_normalTexture",
"u_lightmapTexture",
};
ShaderSystem* g_shaderSystem = nullptr;
ShaderSystem::ShaderSystem()
{
}
ShaderSystem::~ShaderSystem()
{
}
void ShaderSystem::Init()
{
Msg("Initializing Shader System ...");
}
void ShaderSystem::Shutdown()
{
for (int i = 0; i < m_shaders.size(); i++)
{
ShaderData& shaderData = m_shaders[i];
if (shaderData.shader)
{
delete shaderData.shader;
shaderData.shader = nullptr;
}
}
m_shaders.clear();
}
Shader* ShaderSystem::CreateShader(const char* name, const char* vsfilepath, const char* psfilepath, InputLayoutDesc_t* inputLayout /*= nullptr*/, int inputLayoutCount/* = 0*/)
{
auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [=](const ShaderData& shaderData) { return shaderData.shadername == name; });
if ( it != m_shaders.end() )
{
return it->shader;
}
Shader* pShader = new Shader();
if ( inputLayout && inputLayoutCount > 0 )
{
memcpy( pShader->m_layouts, inputLayout, inputLayoutCount * sizeof( InputLayoutDesc_t ) );
pShader->m_layout_count = inputLayoutCount;
}
pShader->Create( name, vsfilepath, psfilepath );
ShaderData shaderData = { name, pShader };
m_shaders.push_back(shaderData);
return pShader;
}
size_t g_vertex_attribs_sizetable[VERTEXATTR_MAX] =
{
2, // VERTEXATTR_VEC2
3, // VERTEXATTR_VEC3
4, // VERTEXATTR_VEC4
};
size_t g_vertex_attribs_realsizetable[VERTEXATTR_MAX] =
{
8, // VERTEXATTR_VEC2
12, // VERTEXATTR_VEC3
16, // VERTEXATTR_VEC4
};
void ApplyVertexFormat(const Shader* shader, size_t stride)
{
size_t appliedOffset = 0;
for (int i = 0; i < shader->m_layout_count; i++)
{
const InputLayoutDesc_t* layoutEntry = &shader->m_layouts[i];
glEnableVertexAttribArray(GLuint(i));
glVertexAttribPointer(GLuint(i), GLint(g_vertex_attribs_sizetable[layoutEntry->attribute]),
GL_FLOAT, GL_FALSE, static_cast<GLsizei>(stride),
(appliedOffset > 0) ? (void*)(appliedOffset * sizeof(float)) : (void*)0);
appliedOffset += g_vertex_attribs_sizetable[layoutEntry->attribute];
}
}
void ShaderSystem::SetShader(const Shader* shader)
{
assert( shader );
glUseProgram( shader->m_program );
// apply input layout
//for ( int i = 0; i < shader->m_layout_count; i++ )
//{
// const InputLayoutDesc_t& layout = shader->m_layouts[ i ];
//
// //glEnableVertexAttribArray( shader->m_glLayouts[ i ] );
// //glVertexAttribPointer( shader->m_glLayouts[ i ], GetVertexAttributeSize( layout.attribute ), GL_FLOAT, GL_FALSE, shader->m_stride, NULL );
// glEnableVertexAttribArray( i );
// glVertexAttribPointer( i, GetVertexAttributeSize( layout.attribute ), GL_FLOAT, GL_FALSE, shader->m_stride, NULL );
//}
ApplyVertexFormat( shader, shader->m_stride );
//for ( int i = 0; i < shader->m_layout_count; i++ )
//{
// const InputLayoutDesc_t& layout = shader->m_layouts[ i ];
//
// glEnableVertexAttribArray( shader->m_glLayouts[ i ] );
// glVertexAttribPointer( shader->m_glLayouts[ i ], GetVertexAttributeSize( layout.attribute ), GL_FLOAT, GL_FALSE, shader->m_stride, NULL );
//}
}
void ShaderSystem::SetUniformSampler(const Shader* shader, ShaderSamplers_t sampler, int index)
{
glGetError();
GLint uniformLocation = glGetUniformLocation(shader->m_program, g_samplersNameTable[sampler]);
glUniform1i(uniformLocation, static_cast<GLint>(index));
}
void ShaderSystem::SetUniformFloat4(const Shader* shader, ShaderUniform_t uniform, const void* data)
{
GLint location = glGetUniformLocation( shader->m_program, g_uniformNameTable[ uniform ] );
glUniform4fv( location, 1, ( const GLfloat* )data );
}
void ShaderSystem::SetUniformMatrix( const Shader* shader, ShaderUniform_t uniform, const void* data )
{
GLint location = glGetUniformLocation( shader->m_program, g_uniformNameTable[ uniform ] );
glUniformMatrix4fv( location, 1, GL_FALSE, ( const GLfloat* )data );
}
// #TODO: Move out
static const char* s_attributeNameTable[SHADERSEMANTIC_MAX] =
{
"a_position",//SHADERSEMANTIC_POSITION,
"a_color", //SHADERSEMANTIC_COLOR
"a_texcoord",//SHADERSEMANTIC_TEXCOORD,
"a_texcoord0", //SHADERSEMANTIC_TEXCOORD0,
"a_texcoord1",//SHADERSEMANTIC_TEXCOORD1,
"a_normal",//SHADERSEMANTIC_NORMAL,
"a_tangent",//SHADERSEMANTIC_TANGENT,
"a_bitangent"//SHADERSEMANTIC_BITANGENT,
};
void Shader::AllocateAttributes()
{
// Allocate input layout
for ( int i = 0; i < m_layout_count; i++ )
{
const InputLayoutDesc_t& layout = m_layouts[ i ];
// Msg( "Shader::AllocateAttributes: Bind %i as %s", i, s_attributeNameTable[ layout.semantic ] );
glBindAttribLocation( m_program, i, s_attributeNameTable[ layout.semantic ] );
GL_CHECK_ERROR();
// m_glLayouts[ i ] = glGetAttribLocation( m_program, s_attributeNameTable[i] );
// assert( m_glLayouts[ i ] );
}
}

View File

@ -0,0 +1,61 @@
#ifndef SHADERSYSTEM_H
#define SHADERSYSTEM_H
#include <string>
#include <vector>
#include "render/shader.h"
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
};
class ShaderSystem
{
public:
ShaderSystem();
~ShaderSystem();
void Init();
void Shutdown();
Shader* CreateShader(const char* name, const char* vsfilepath, const char* psfilepath, InputLayoutDesc_t* inputLayout = nullptr, int inputLayoutCount = 0);
void SetShader(const Shader* shader);
void SetUniformSampler( const Shader* shader, ShaderSamplers_t sampler, int index );
void SetUniformFloat4( const Shader* shader, ShaderUniform_t uniform, const void* data );
void SetUniformMatrix( const Shader* shader, ShaderUniform_t uniform, const void* data );
private:
struct ShaderData
{
std::string shadername;
Shader* shader;
};
std::vector<ShaderData> m_shaders;
};
extern ShaderSystem* g_shaderSystem;
#endif // !SHADERSYSTEM_H

View File

@ -0,0 +1,308 @@
#include <assert.h>
#include "render/texture2d.h"
#include "render/texturesmanager.h"
#include "render/gl_shared.h"
GLint getGlWrap(TextureWrap wrap);
GLint getGlTexFilter(TextureFilter filter);
Texture2D* Texture2D::Create()
{
return new Texture2D;
}
Texture2D::Texture2D()
{
m_pf = PF_UNKNOWN;
m_width = 0;
m_height = 0;
m_channels = 0;
m_handle = -1;
}
Texture2D::~Texture2D()
{
m_pf = PF_UNKNOWN;
m_width = 0;
m_height = 0;
m_channels = 0;
m_handle = -1;
}
void Texture2D::CreateBlackTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
uint8_t* data = new uint8_t[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 0;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateWhiteTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
uint8_t* data = new uint8_t[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 255;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateGrayTexture(int width, int height, int channels)
{
size_t textureSize = width * height * channels;
uint8_t* data = new uint8_t[textureSize];
assert(data);
for (int i = 0; i < (int)textureSize; i++) {
data[i] = 255 / 2;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateTexture_Generator(int width, int height, int channels, int color)
{
size_t textureSize = width * height * channels;
uint8_t* data = new uint8_t[textureSize];
assert(data);
m_textureFileName = "$generator_texture$";
for (int i = 0; i < (int)textureSize; i++) {
data[i] = color;
}
CreateFromExistedData(data, width, height, channels);
delete[] data;
}
void Texture2D::CreateFromExistedData(void* data, int width, int height, int channels)
{
//assert(data);
m_width = width;
m_height = height;
m_channels = channels;
glGenTextures(1, &m_handle);
glBindTexture(GL_TEXTURE_2D, m_handle);
glTexImage2D(GL_TEXTURE_2D, 0, (channels == 3) ? GL_RGB : GL_RGBA, width, height, 0, (channels == 3) ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture2D::CreateRaw(void* data, int width, int height, PixelFormat pf)
{
m_width = width;
m_height = height;
m_channels = (pf == PF_R8G8B8) ? 3 : 4;
m_pf = pf;
glGenTextures(1, &m_handle);
glBindTexture(GL_TEXTURE_2D, m_handle);
glTexImage2D(GL_TEXTURE_2D, 0, getGLInternalPF(pf), width, height, 0, getGLInternalPF(pf), GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
void Texture2D::GenerateMipmaps()
{
glBindTexture(GL_TEXTURE_2D, m_handle);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//if (g_texAnisoFilter.getValueB()) {
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, g_texAnisoLevel.getValueI());
//}
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture2D::Bind()
{
glBindTexture(GL_TEXTURE_2D, m_handle);
}
void Texture2D::setWrapS(TextureWrap wrap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getGlWrap(wrap));
}
void Texture2D::setWrapT(TextureWrap wrap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getGlWrap(wrap));
}
void Texture2D::setMin(TextureFilter filter)
{
GLint param = 0;
param = getGlTexFilter(filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
}
void Texture2D::setMag(TextureFilter filter)
{
GLint param = 0;
param = getGlTexFilter(filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
}
GLint getGlWrap(TextureWrap wrap)
{
GLint 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;
}
GLint getGlTexFilter(TextureFilter filter)
{
GLint 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;
}
uint32_t getGLPF(PixelFormat pf)
{
return 0;
//return uint32_t();
}
// Kirill: Remove to render_main.cpp or something else
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;
break;
case BF_ONE:
return GL_ONE;
break;
case BF_SRC_COLOR:
return GL_SRC_COLOR;
break;
case BF_ONE_MINUS_SRC_COLOR:
return GL_ONE_MINUS_SRC_COLOR;
break;
case BF_DST_COLOR:
return GL_DST_COLOR;
break;
case BF_ONE_MINUS_DST_COLOR:
return GL_ONE_MINUS_DST_COLOR;
break;
case BF_SRC_ALPHA:
return GL_SRC_ALPHA;
break;
case BF_ONE_MINUS_SRC_ALPHA:
return GL_ONE_MINUS_SRC_ALPHA;
break;
case BF_DST_ALPHA:
return GL_DST_ALPHA;
break;
case BF_ONE_MINUS_DST_ALPHA:
return GL_ONE_MINUS_DST_ALPHA;
break;
case BF_CONSTANT_COLOR:
return GL_CONSTANT_COLOR;
break;
case BF_ONE_MINUS_CONSTANT_COLOR:
return GL_ONE_MINUS_CONSTANT_COLOR;
break;
case BF_CONSTANT_ALPHA:
return GL_CONSTANT_ALPHA;
break;
case BF_ONE_MINUS_CONSTANT_ALPHA:
return GL_ONE_MINUS_CONSTANT_ALPHA;
break;
default:
break;
}
return 0;
}

View File

@ -0,0 +1,67 @@
#ifndef TEXTURE2D_H
#define TEXTURE2D_H
#include <string>
#include "render/render_shared.h"
enum class TextureWrap
{
Repeat,
MirroredRepeat,
ClampToEdge,
ClampToBorder
};
enum class TextureFilter
{
Nearest,
Linear,
NearestMipmapNearest,
LinearMipmapNearest,
NearestMipmapLinear,
LinearMipmapLinear
};
class TexturesManager;
class Texture2D
{
friend class TexturesManager;
public:
static Texture2D* Create();
public:
Texture2D();
~Texture2D();
void CreateBlackTexture(int width, int height, int channels);
void CreateWhiteTexture(int width, int height, int channels);
void CreateGrayTexture(int width, int height, int channels);
void CreateTexture_Generator(int width, int height, int channels, int color);
void CreateFromExistedData(void* data, int width, int height, int channels);
void CreateFromFile(const char* filename);
void CreateRaw(void* data, int width, int height, PixelFormat pf);
void GenerateMipmaps();
void Bind();
void setWrapS(TextureWrap wrap);
void setWrapT(TextureWrap wrap);
void setMin(TextureFilter filter);
void setMag(TextureFilter filter);
uint32_t GetHandle() { return m_handle; }
private:
std::string m_textureFileName;
PixelFormat m_pf;
int m_width;
int m_height;
int m_channels;
uint32_t m_handle;
};
#endif // !TEXTURE2D_H

View File

@ -0,0 +1,194 @@
#include "utils/logger.h"
#include "filesystem/filemanager.h"
#include "render/texture2d.h"
#include "render/texturesmanager.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <glad/glad.h>
// STB Image loading code
void Texture2D::CreateFromFile(const char* filename)
{
int width, height, channels;
m_textureFileName = filename;
File* file = g_fileManager->OpenFile(filename, FileAccess::Read);
file->seek(SeekDir::End, 0);
size_t imageSize = file->tell();
file->seek(SeekDir::Begin, 0);
uint8_t* fileData = (uint8_t*)malloc(imageSize);
file->read(fileData, imageSize);
g_fileManager->CloseFile(file);
uint8_t* imageData = stbi_load_from_memory(fileData, int(imageSize), &width, &height, &channels, 0);
if (imageData == NULL) {
free(fileData);
Msg("Texture loading error: %s (%s)", filename, stbi_failure_reason());
assert(imageData);
}
CreateFromExistedData(imageData, width, height, channels);
m_textureFileName = filename;
free(fileData);
stbi_image_free(imageData);
}
static const char* g_texFileExtensions[] = { ".png", ".jpeg", ".jpg", ".tga", ".bmp" };
const int kTexFileExtensionsSize = sizeof(g_texFileExtensions) / sizeof(g_texFileExtensions[0]);
TexturesManager* g_texturesManager = nullptr;
TexturesManager::TexturesManager()
{
m_notex = nullptr;
}
TexturesManager::~TexturesManager()
{
}
void TexturesManager::Init()
{
stbi_set_flip_vertically_on_load(true);
m_notex = LoadTexture2D("content/textures/system/notex.png", true);
if (!m_notex) {
Logger::error("TexturesManager::Init: Failed to initialize system texture! 'system/notex.png' is not exist.");
}
}
void TexturesManager::Shutdown()
{
if (!m_textures.empty()) {
Msg("--- unfreed textures ---");
for (std::vector<Texture2D*>::iterator it = m_textures.begin(); it != m_textures.end(); ++it) {
Msg("%s", (*it)->m_textureFileName.c_str());
delete* it;
*it = nullptr;
}
m_textures.clear();
}
}
void TexturesManager::SetTexture(int slot, Texture2D* texture)
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, texture ? texture->GetHandle() : 0);
}
Texture2D* TexturesManager::CreateManual2D(const char* name, uint32_t width, uint32_t height, PixelFormat format, bool useAsRenderTarget)
{
for (std::vector<Texture2D*>::iterator it = m_textures.begin(); it != m_textures.end(); ++it) {
if ((*it)->m_textureFileName == name) {
Logger::error("TexturesManager::CreateManual2D: texture %s is already created!", name);
}
}
// allocate
Texture2D* texture = Texture2D::Create();
texture->CreateRaw(nullptr, width, height, format);
texture->m_textureFileName = name;
if (useAsRenderTarget)
Msg("Created rt texture [%s]", name);
return texture;
}
bool IsSupportedExtension(const char* filename)
{
std::string ext = fs::getFileExtension(filename);
for (int i = 0; i < kTexFileExtensionsSize; i++) {
if (ext == g_texFileExtensions[i]) {
return true;
}
}
return false;
}
Texture2D* TexturesManager::LoadTexture2D(const char* texturename, bool useMipmaps /*= false*/)
{
int texturesNbr = m_textures.size();
for (int i = 0; i < texturesNbr; i++) {
if (m_textures[i]->m_textureFileName == texturename)
return m_textures[i];
}
if (strcmp(texturename, "$white$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$white$";
tex->CreateWhiteTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$black$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$black$";
tex->CreateBlackTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$gray$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->m_textureFileName = "$gray$";
tex->CreateGrayTexture(16, 16, 3);
m_textures.push_back(tex);
return tex;
}
if (strcmp(texturename, "$gray_console$") == 0) {
Texture2D* tex = Texture2D::Create();
tex->CreateTexture_Generator(16, 16, 3, 32);
m_textures.push_back(tex);
return tex;
}
if (strlen(texturename) <= 0) {
return m_notex;
}
std::string texnamebuf;
// find texture from disk
for (int i = 0; i < kTexFileExtensionsSize; i++)
{
std::string textureFilename = fs::getFileNameWithoutExtension(texturename);
textureFilename += g_texFileExtensions[i];
if (g_fileManager->FileExist(textureFilename.c_str()))
{
texnamebuf = textureFilename;
break;
}
}
if (!texnamebuf.empty()) {
Texture2D* texture = Texture2D::Create();
texture->CreateFromFile(texnamebuf.c_str());
if (useMipmaps)
texture->GenerateMipmaps();
Msg("loaded %s", fs::getFilenameWithoutPathAndExtension(texturename).c_str());
m_textures.push_back(texture);
return texture;
}
else if (texnamebuf.empty() && m_notex) {
Msg("not found %s", fs::getFilenameWithoutPathAndExtension(texturename).c_str());
return m_notex;
}
return nullptr;
}

View File

@ -0,0 +1,39 @@
#ifndef TEXTURESMANAGER_H
#define TEXTURESMANAGER_H
#include <stdint.h>
#include <vector>
#include "render/render_shared.h"
class Texture2D;
class TexturesManager
{
public:
TexturesManager();
~TexturesManager();
void Init();
void Shutdown();
void SetTexture(int slot, Texture2D* texture);
Texture2D* CreateManual2D(
const char* name,
uint32_t width,
uint32_t height,
PixelFormat format,
bool useAsRenderTarget = false);
Texture2D* LoadTexture2D(const char* texturename, bool useMipmaps = false);
private:
std::vector<Texture2D*> m_textures;
Texture2D* m_notex;
};
extern TexturesManager* g_texturesManager;
#endif // !TEXTURESMANAGER_H

460
src/engine/render/ui.cpp Normal file
View File

@ -0,0 +1,460 @@
#include <cstdint>
#include <cmath>
#include <cassert>
#include "utils/logger.h"
#include "render/ui.h"
#include "render/vertexbuffer.h"
#include "render/indexbuffer.h"
#include "render/renderdevice.h"
#include "render/shadersystem.h"
#include "render/texturesmanager.h"
#include "render/texture2d.h"
struct DrawInfo
{
uint16_t vxcount;
uint16_t idxcount;
};
struct UIGlobals {
VertexBuffer* vb;
IndexBuffer* ib;
Shader* shader;
Texture2D* activetexture = nullptr;
Texture2D* defaultTexture = nullptr;
UIVertex* vertices = nullptr;
uint16_t* indices = nullptr;
DrawInfo drawInfo[MAX_UI_VERTICES];
uint16_t count = 0;
uint16_t position = 0;
uint16_t Indexposition = 0;
uint16_t currentIdx = 0;
} g_ui;
void uiInit()
{
//////////////////////////////////////////////////////////////////////////
// Buffer and context state
// Buffer creation
g_ui.vb = g_renderDevice->CreateVertexBuffer(nullptr, MAX_UI_VERTICES, true);
g_ui.ib = g_renderDevice->CreateIndexBuffer(nullptr, MAX_UI_INDICES, true);
// Create shader
InputLayoutDesc_t inputLayout[] =
{
{ VERTEXATTR_VEC2, SHADERSEMANTIC_POSITION },
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD },
{ VERTEXATTR_VEC4, SHADERSEMANTIC_COLOR },
};
g_ui.shader = g_shaderSystem->CreateShader("ui", "content/shaders/ui_base.vs", "content/shaders/ui_tex.ps", inputLayout, sizeof(inputLayout) / sizeof(inputLayout[0]));
g_ui.shader->m_stride = sizeof( UIVertex );
g_ui.defaultTexture = g_texturesManager->LoadTexture2D("$white$");
}
void uiShutdown()
{
delete g_ui.ib;
delete g_ui.vb;
}
void uiDumpBuffers()
{
Msg( "--- UI Vertex Buffer ---" );
g_ui.vertices = (UIVertex*)g_ui.vb->MapBuffer(BufferAccess::WRITE_ONLY);
assert(g_ui.vertices);
for ( int i = 0; i < g_ui.position; i++ )
{
Msg( "%i: POSITION = %.2f %.2f", i, g_ui.vertices[ i ].position.x, g_ui.vertices[ i ].position.y );
Msg( "%i: TEXCOORD = %.2f %.2f", i, g_ui.vertices[ i ].uv.x, g_ui.vertices[ i ].uv.y );
Msg( "%i: COLOR = %.2f %.2f %.2f %.2f", i,
g_ui.vertices[ i ].color.x,
g_ui.vertices[ i ].color.y,
g_ui.vertices[ i ].color.z,
g_ui.vertices[ i ].color.w);
}
Msg( "------------------------" );
g_ui.vb->UnmapBuffer();
}
void uiBeginRender()
{
g_ui.vertices = (UIVertex*)g_ui.vb->MapBuffer(BufferAccess::WRITE_ONLY);
assert(g_ui.vertices);
g_ui.indices = (uint16_t*)g_ui.ib->MapBuffer(BufferAccess::WRITE_ONLY);
assert(g_ui.indices);
}
void uiDrawQuad(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d, const Vec4& color)
{
DrawInfo& drawInfo = g_ui.drawInfo[g_ui.count];
drawInfo.vxcount = 4;
drawInfo.idxcount = 6;
g_ui.indices[g_ui.Indexposition + 0] = g_ui.currentIdx;
g_ui.indices[g_ui.Indexposition + 1] = g_ui.currentIdx + 1;
g_ui.indices[g_ui.Indexposition + 2] = g_ui.currentIdx + 2;
g_ui.indices[g_ui.Indexposition + 3] = g_ui.currentIdx;
g_ui.indices[g_ui.Indexposition + 4] = g_ui.currentIdx + 2;
g_ui.indices[g_ui.Indexposition + 5] = g_ui.currentIdx + 3;
g_ui.vertices[g_ui.position + 0].position = a; g_ui.vertices[g_ui.position + 0].color = color;
g_ui.vertices[g_ui.position + 1].position = b; g_ui.vertices[g_ui.position + 1].color = color;
g_ui.vertices[g_ui.position + 2].position = c; g_ui.vertices[g_ui.position + 2].color = color;
g_ui.vertices[g_ui.position + 3].position = d; g_ui.vertices[g_ui.position + 3].color = color;
// texcoord
g_ui.vertices[g_ui.position + 0].uv = Vec2{ 0.0f, 1.0f };
g_ui.vertices[g_ui.position + 1].uv = Vec2{ 1.0f, 1.0f };
g_ui.vertices[g_ui.position + 2].uv = Vec2{ 1.0f, 0.0f };
g_ui.vertices[g_ui.position + 3].uv = Vec2{ 0.0f, 0.0f };
g_ui.currentIdx += 4;
g_ui.Indexposition += 6;
g_ui.position += 4;
g_ui.count++;
}
static inline float Rsqrt(float x) { return 1.0f / sqrtf(x); }
#define NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = Rsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0
void uiDrawLines(const Vec2* drawPoints, const size_t pointsCount, bool closed, const Vec4& color)
{
float thickness = 2.1f;
const int count = closed ? pointsCount : pointsCount - 1;
const int vtxCount = (count) * 4;
const int idxCount = (count) * 6;
for (int i1 = 0; i1 < count; i1++)
{
const int i2 = (i1 + 1) == pointsCount ? 0 : i1 + 1;
const Vec2& p1 = drawPoints[i1];
const Vec2& p2 = drawPoints[i2];
float dx = p2.x - p1.x;
float dy = p2.y - p1.y;
NORMALIZE2F_OVER_ZERO(dx, dy);
dx *= (thickness * 0.5f);
dy *= (thickness * 0.5f);
g_ui.vertices[g_ui.position + 0].position.x = p1.x + dy; g_ui.vertices[g_ui.position + 0].position.y = p1.y - dx; g_ui.vertices[g_ui.position + 0].color = color;
g_ui.vertices[g_ui.position + 1].position.x = p2.x + dy; g_ui.vertices[g_ui.position + 1].position.y = p2.y - dx; g_ui.vertices[g_ui.position + 1].color = color;
g_ui.vertices[g_ui.position + 2].position.x = p2.x - dy; g_ui.vertices[g_ui.position + 2].position.y = p2.y + dx; g_ui.vertices[g_ui.position + 2].color = color;
g_ui.vertices[g_ui.position + 3].position.x = p1.x - dy; g_ui.vertices[g_ui.position + 3].position.y = p1.y + dx; g_ui.vertices[g_ui.position + 3].color = color;
g_ui.indices[g_ui.Indexposition + 0] = g_ui.currentIdx;
g_ui.indices[g_ui.Indexposition + 1] = g_ui.currentIdx + 1;
g_ui.indices[g_ui.Indexposition + 2] = g_ui.currentIdx + 2;
g_ui.indices[g_ui.Indexposition + 3] = g_ui.currentIdx;
g_ui.indices[g_ui.Indexposition + 4] = g_ui.currentIdx + 2;
g_ui.indices[g_ui.Indexposition + 5] = g_ui.currentIdx + 3;
g_ui.currentIdx += 4;
g_ui.Indexposition += 6;
g_ui.position += 4;
DrawInfo& drawInfo = g_ui.drawInfo[g_ui.count];
drawInfo.vxcount = 4;
drawInfo.idxcount = 6;
g_ui.count++;
}
}
void uiDrawRect(const Vec2& position, const Vec2& size, const Vec4& color)
{
Vec2 quad[4];
quad[0] = { position.x, position.y };
quad[1] = { position.x + size.x, position.y };
quad[2] = { position.x + size.x, position.y + size.y };
quad[3] = { position.x, position.y + size.y };
uiDrawQuad(quad[0], quad[1], quad[2], quad[3], color);
}
void uiSetTexture(Texture2D* texture)
{
g_ui.activetexture = texture ? texture : g_ui.defaultTexture;
}
void uiSetTextureByName(const char* filename)
{
uiSetTexture( g_texturesManager->LoadTexture2D( filename ) );
}
void uiEndRender()
{
g_ui.indices = nullptr;
g_ui.vertices = nullptr;
g_ui.ib->UnmapBuffer();
g_ui.vb->UnmapBuffer();
int x = 0, y = 0, w = g_renderView.width, h = g_renderView.height;
g_renderDevice->SetViewport(x, y, w, h);
float L = x;
float R = x + w;
float T = y;
float B = y + h;
#if defined(GL_CLIP_ORIGIN)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
const float orthoProjection[4][4] =
{
{ 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ (R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f },
};
if ( g_ui.activetexture == nullptr )
g_ui.activetexture = g_ui.defaultTexture;
g_texturesManager->SetTexture( 0, g_ui.activetexture );
g_ui.activetexture->setMin(TextureFilter::Linear);
g_ui.activetexture->setMag(TextureFilter::Linear);
g_ui.activetexture->setWrapS(TextureWrap::ClampToEdge);
g_ui.activetexture->setWrapT(TextureWrap::ClampToEdge);
g_shaderSystem->SetShader( g_ui.shader );
g_shaderSystem->SetUniformMatrix( g_ui.shader, UNIFORM_PROJ_MATRIX, orthoProjection );
g_renderDevice->SetVerticesBuffer( g_ui.vb );
g_renderDevice->SetIndicesBuffer( g_ui.ib );
// Enable blending
g_renderDevice->SetBlending( true );
g_renderDevice->SetBlendingFunction( BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA );
// Disable depth
g_renderDevice->SetDepthTest( false );
g_renderDevice->SetBackfaceCull( false );
g_renderDevice->DrawElements( PT_TRIANGLES, g_ui.Indexposition, true );
// Uncomment for UI VB debugging
//uiDumpBuffers();
g_ui.currentIdx = 0;
g_ui.Indexposition = 0;
g_ui.position = 0;
g_ui.count = 0;
}
typedef struct Character {
int codePoint, x, y, width, height, originX, originY;
} Character;
typedef struct Font {
const char* name;
int size, bold, italic, width, height, characterCount;
Character* characters;
} Font;
static Character characters_Courier_New[] = {
{' ', 36, 61, 3, 3, 1, 1},
{'!', 498, 0, 10, 20, -1, 16},
{'"', 423, 43, 14, 13, 1, 16},
{'#', 160, 0, 16, 22, 2, 17},
{'$', 47, 0, 16, 23, 2, 17},
{'%', 357, 0, 16, 20, 2, 16},
{'&', 202, 24, 15, 19, 1, 15},
{'\'', 448, 43, 10, 13, -1, 16},
{'(', 111, 0, 11, 23, -2, 16},
{')', 122, 0, 11, 23, 1, 16},
{'*', 357, 43, 16, 15, 2, 16},
{'+', 392, 24, 18, 18, 3, 15},
{',', 437, 43, 11, 13, -1, 6},
{'-', 20, 61, 16, 9, 2, 10},
{'.', 474, 43, 10, 10, -1, 6},
{'/', 0, 0, 16, 24, 2, 18},
{'0', 373, 0, 16, 20, 2, 16},
{'1', 106, 24, 16, 19, 2, 16},
{'2', 122, 24, 16, 19, 2, 16},
{'3', 389, 0, 16, 20, 2, 16},
{'4', 138, 24, 16, 19, 2, 16},
{'5', 405, 0, 16, 20, 2, 16},
{'6', 453, 0, 15, 20, 1, 16},
{'7', 154, 24, 16, 19, 2, 16},
{'8', 421, 0, 16, 20, 2, 16},
{'9', 468, 0, 15, 20, 1, 16},
{':', 292, 43, 10, 16, -1, 12},
{';', 120, 43, 12, 18, 0, 12},
{'<', 297, 24, 19, 18, 4, 15},
{'=', 405, 43, 18, 13, 3, 12},
{'>', 316, 24, 19, 18, 3, 15},
{'?', 483, 0, 15, 20, 1, 16},
{'@', 232, 0, 15, 21, 2, 16},
{'A', 217, 24, 20, 18, 4, 15},
{'B', 410, 24, 18, 18, 3, 15},
{'C', 285, 0, 18, 20, 3, 16},
{'D', 428, 24, 18, 18, 3, 15},
{'E', 446, 24, 18, 18, 3, 15},
{'F', 54, 43, 17, 18, 2, 15},
{'G', 303, 0, 18, 20, 3, 16},
{'H', 464, 24, 18, 18, 3, 15},
{'I', 88, 43, 16, 18, 2, 15},
{'J', 0, 24, 18, 19, 2, 15},
{'K', 335, 24, 19, 18, 3, 15},
{'L', 482, 24, 18, 18, 3, 15},
{'M', 237, 24, 20, 18, 4, 15},
{'N', 354, 24, 19, 18, 4, 15},
{'O', 321, 0, 18, 20, 3, 16},
{'P', 71, 43, 17, 18, 2, 15},
{'Q', 142, 0, 18, 22, 3, 16},
{'R', 373, 24, 19, 18, 3, 15},
{'S', 437, 0, 16, 20, 2, 16},
{'T', 0, 43, 18, 18, 3, 15},
{'U', 18, 24, 18, 19, 3, 15},
{'V', 257, 24, 20, 18, 4, 15},
{'W', 277, 24, 20, 18, 4, 15},
{'X', 18, 43, 18, 18, 3, 15},
{'Y', 36, 43, 18, 18, 3, 15},
{'Z', 104, 43, 16, 18, 2, 15},
{'[', 63, 0, 12, 23, -1, 16},
{'\\', 16, 0, 16, 24, 2, 18},
{']', 75, 0, 12, 23, 1, 16},
{'^', 389, 43, 16, 14, 2, 17},
{'_', 0, 61, 20, 9, 4, -1},
{'`', 484, 43, 10, 10, -1, 17},
{'a', 132, 43, 18, 17, 3, 13},
{'b', 247, 0, 19, 20, 4, 16},
{'c', 186, 43, 17, 17, 2, 13},
{'d', 266, 0, 19, 20, 3, 16},
{'e', 150, 43, 18, 17, 3, 13},
{'f', 72, 24, 17, 19, 2, 16},
{'g', 214, 0, 18, 21, 3, 13},
{'h', 36, 24, 18, 19, 3, 16},
{'i', 170, 24, 16, 19, 2, 16},
{'j', 32, 0, 15, 24, 2, 16},
{'k', 54, 24, 18, 19, 3, 16},
{'l', 186, 24, 16, 19, 2, 16},
{'m', 219, 43, 20, 16, 4, 13},
{'n', 239, 43, 18, 16, 3, 13},
{'o', 168, 43, 18, 17, 3, 13},
{'p', 176, 0, 19, 21, 4, 13},
{'q', 195, 0, 19, 21, 3, 13},
{'r', 275, 43, 17, 16, 2, 13},
{'s', 203, 43, 16, 17, 2, 13},
{'t', 89, 24, 17, 19, 2, 15},
{'u', 257, 43, 18, 16, 3, 12},
{'v', 302, 43, 19, 15, 3, 12},
{'w', 321, 43, 18, 15, 3, 12},
{'x', 339, 43, 18, 15, 3, 12},
{'y', 339, 0, 18, 20, 3, 12},
{'z', 373, 43, 16, 15, 2, 12},
{'{', 87, 0, 12, 23, 0, 16},
{'|', 133, 0, 9, 23, -2, 16},
{'}', 99, 0, 12, 23, 0, 16},
{'~', 458, 43, 16, 11, 2, 11},
};
static Font font_Courier_New = { "Courier New", 20, 1, 0, 512, 128, 95, characters_Courier_New };
static Character characters_Arial[] = {
{' ', 10, 61, 3, 3, 1, 1},
{'!', 205, 34, 5, 15, 0, 14},
{'"', 202, 49, 8, 7, 1, 14},
{'#', 187, 19, 12, 15, 1, 14},
{'$', 71, 0, 12, 18, 1, 15},
{'%', 162, 0, 16, 15, 0, 14},
{'&', 208, 0, 14, 15, 1, 14},
{'\'', 210, 49, 5, 7, 1, 14},
{'(', 35, 0, 7, 19, 0, 14},
{')', 42, 0, 7, 19, 0, 14},
{'*', 193, 49, 9, 7, 1, 14},
{'+', 161, 49, 11, 10, 0, 11},
{',', 215, 49, 5, 7, 0, 3},
{'-', 246, 49, 8, 4, 1, 6},
{'.', 0, 61, 5, 4, 0, 3},
{'/', 177, 34, 7, 15, 1, 14},
{'0', 199, 19, 12, 15, 1, 14},
{'1', 184, 34, 7, 15, -1, 14},
{'2', 84, 34, 11, 15, 1, 14},
{'3', 211, 19, 12, 15, 1, 14},
{'4', 223, 19, 12, 15, 1, 14},
{'5', 235, 19, 12, 15, 1, 14},
{'6', 0, 34, 12, 15, 1, 14},
{'7', 12, 34, 12, 15, 1, 14},
{'8', 24, 34, 12, 15, 1, 14},
{'9', 36, 34, 12, 15, 1, 14},
{':', 156, 49, 5, 11, 0, 10},
{';', 223, 34, 5, 14, 0, 10},
{'<', 134, 49, 11, 11, 0, 12},
{'=', 182, 49, 11, 8, 0, 10},
{'>', 145, 49, 11, 11, 0, 12},
{'?', 95, 34, 11, 15, 1, 14},
{'@', 0, 0, 19, 19, 0, 14},
{'A', 222, 0, 14, 15, 1, 14},
{'B', 48, 34, 12, 15, 0, 14},
{'C', 236, 0, 14, 15, 0, 14},
{'D', 70, 19, 13, 15, 0, 14},
{'E', 60, 34, 12, 15, 0, 14},
{'F', 72, 34, 12, 15, 0, 14},
{'G', 0, 19, 14, 15, 0, 14},
{'H', 83, 19, 13, 15, 0, 14},
{'I', 210, 34, 5, 15, 0, 14},
{'J', 139, 34, 10, 15, 1, 14},
{'K', 96, 19, 13, 15, 0, 14},
{'L', 106, 34, 11, 15, 0, 14},
{'M', 178, 0, 15, 15, 0, 14},
{'N', 109, 19, 13, 15, 0, 14},
{'O', 193, 0, 15, 15, 0, 14},
{'P', 122, 19, 13, 15, 0, 14},
{'Q', 83, 0, 16, 16, 1, 14},
{'R', 14, 19, 14, 15, 0, 14},
{'S', 135, 19, 13, 15, 1, 14},
{'T', 148, 19, 13, 15, 1, 14},
{'U', 161, 19, 13, 15, 0, 14},
{'V', 28, 19, 14, 15, 1, 14},
{'W', 143, 0, 19, 15, 1, 14},
{'X', 42, 19, 14, 15, 1, 14},
{'Y', 56, 19, 14, 15, 1, 14},
{'Z', 174, 19, 13, 15, 1, 14},
{'[', 49, 0, 6, 19, 0, 14},
{'\\', 191, 34, 7, 15, 1, 14},
{']', 55, 0, 6, 19, 1, 14},
{'^', 172, 49, 10, 9, 1, 14},
{'_', 232, 49, 14, 4, 2, -1},
{'`', 5, 61, 5, 4, 0, 14},
{'a', 15, 49, 12, 12, 1, 11},
{'b', 117, 34, 11, 15, 0, 14},
{'c', 51, 49, 11, 12, 1, 11},
{'d', 128, 34, 11, 15, 1, 14},
{'e', 27, 49, 12, 12, 1, 11},
{'f', 169, 34, 8, 15, 1, 14},
{'g', 99, 0, 11, 16, 1, 11},
{'h', 149, 34, 10, 15, 0, 14},
{'i', 215, 34, 4, 15, 0, 14},
{'j', 61, 0, 6, 19, 2, 14},
{'k', 159, 34, 10, 15, 0, 14},
{'l', 219, 34, 4, 15, 0, 14},
{'m', 228, 34, 15, 12, 0, 11},
{'n', 106, 49, 10, 12, 0, 11},
{'o', 39, 49, 12, 12, 1, 11},
{'p', 110, 0, 11, 16, 0, 11},
{'q', 121, 0, 11, 16, 1, 11},
{'r', 126, 49, 8, 12, 0, 11},
{'s', 62, 49, 11, 12, 1, 11},
{'t', 198, 34, 7, 15, 1, 14},
{'u', 116, 49, 10, 12, 0, 11},
{'v', 73, 49, 11, 12, 1, 11},
{'w', 0, 49, 15, 12, 1, 11},
{'x', 84, 49, 11, 12, 1, 11},
{'y', 132, 0, 11, 16, 1, 11},
{'z', 95, 49, 11, 12, 1, 11},
{'{', 19, 0, 8, 19, 1, 14},
{'|', 67, 0, 4, 19, 0, 14},
{'}', 27, 0, 8, 19, 1, 14},
{'~', 220, 49, 12, 5, 1, 9},
};
static Font font_Arial = { "Arial", 18, 0, 0, 256, 128, 95, characters_Arial };

29
src/engine/render/ui.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include <utils/maths.h>
#define MAX_UI_VERTICES 2048 * 4
#define MAX_UI_INDICES 2048 * 4
class Texture2D;
struct UIVertex
{
Vec2 position;
Vec2 uv;
Vec4 color;
};
void uiInit();
void uiShutdown();
void uiBeginRender();
void uiDrawQuad(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d, const Vec4& color);
void uiDrawLines(const Vec2* drawPoints, const size_t pointsCount, bool closed, const Vec4& color);
void uiDrawRect(const Vec2& position, const Vec2& size, const Vec4& color);
void uiSetTexture(Texture2D* texture);
void uiSetTextureByName(const char* filename);
void uiEndRender();

View File

@ -0,0 +1,62 @@
#include "render/vertexbuffer.h"
#include "render/gl_shared.h"
VertexBuffer::VertexBuffer(void* data, size_t size, bool isStream /*= false*/)
{
glGenBuffers(1, &m_buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
glBufferData(GL_ARRAY_BUFFER, size, data, isStream ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//if (isStream) {
// Logger::msg("created dynamic vertex stream ...");
//}
}
VertexBuffer::~VertexBuffer()
{
glDeleteBuffers(1, &m_buffer);
}
void VertexBuffer::Bind()
{
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
}
void* VertexBuffer::MapBuffer(BufferAccess access)
{
GLenum accessGl = 0;
switch (access)
{
case BufferAccess::READ_ONLY:
accessGl = GL_READ_ONLY;
break;
case BufferAccess::WRITE_ONLY:
accessGl = GL_WRITE_ONLY;
break;
case BufferAccess::READ_WRITE:
accessGl = GL_READ_WRITE;
break;
}
Bind();
void* ptr = glMapBuffer(GL_ARRAY_BUFFER, accessGl);
//check_for_opengl_error();
return ptr;
}
void VertexBuffer::UnmapBuffer()
{
Bind();
glUnmapBuffer(GL_ARRAY_BUFFER);
}
void VertexBuffer::UpdateBuffer(void* data, size_t size)
{
glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW);
GL_CHECK_ERROR();
}

View File

@ -0,0 +1,28 @@
#ifndef VERTEXOBJECT_H
#define VERTEXOBJECT_H
#include <stdint.h>
#include "render/render_shared.h"
class RenderDevice;
class VertexBuffer
{
friend class RenderDevice;
public:
~VertexBuffer();
void Bind();
void* MapBuffer(BufferAccess access);
void UnmapBuffer();
void UpdateBuffer(void* data, size_t size);
private:
VertexBuffer(void* data, size_t size, bool isStream = false);
uint32_t m_buffer;
};
#endif // !VERTEXOBJECT_H

View File

@ -0,0 +1,3 @@
#include "sound_system.h"
ISoundSystem* g_soundSystem = nullptr;

View File

@ -0,0 +1,53 @@
#ifndef SOUND_SYSTEM_H
#define SOUND_SYSTEM_H
#pragma once
class ISound
{
public:
virtual ~ISound () { }
virtual void play () = 0;
virtual void Stop () = 0;
virtual void Pause () = 0;
virtual bool isPlaying () const = 0;
virtual bool isPaused () const = 0;
virtual bool IsLooped () const = 0;
virtual void SetLooped (bool bLooped) = 0;
virtual float GetVolume () const = 0;
virtual void SetVolume (float fVolume) = 0;
virtual void OnFrame (float delta) = 0;
};
typedef unsigned int SoundDeviceID;
class ISoundSystem
{
public:
virtual ~ISoundSystem () { }
virtual void selectDevice (SoundDeviceID deviceId) = 0;
virtual SoundDeviceID selectedDevice () const = 0;
virtual ISound* CreateSound (const char* sSoundFile) = 0;
virtual void DestroySound (ISound*& pSound) = 0;
virtual void Update (float delta) = 0;
virtual void StopAllSounds () = 0;
virtual void PauseAllSounds () = 0;
virtual void ReleaseAllSounds() = 0;
virtual float GetMasterVolume () const = 0;
virtual void SetMasterVolume (float fVolume) = 0;
};
ISoundSystem* CreateSoundSystem_DirectSound(void* wndHandle);
extern ISoundSystem* g_soundSystem;
#endif

View File

View File

@ -0,0 +1,378 @@
#include <assert.h>
#include "utils/logger.h"
#include "filesystem/stream.h"
#include "filesystem/filemanager.h"
#include "sound/sound_system.h"
#undef Msg
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <mmeapi.h>
#include <dsound.h>
#pragma comment(lib, "dsound.lib")
IDirectSound8* g_DirectSound = nullptr;
IDirectSoundBuffer* g_PrimaryBuffer = nullptr;
/////////////////////////////////////////////////////////////////////////////////////////
// Sound implementation
class Sound_DSound_Impl : public ISound
{
public:
Sound_DSound_Impl(const char* sSoundFile);
~Sound_DSound_Impl();
void play() override;
void Stop() override;
void Pause() override;
bool isPlaying() const override;
bool isPaused() const override;
bool IsLooped() const override;
void SetLooped(bool bLooped) override;
float GetVolume() const override;
void SetVolume(float fVolume) override;
void OnFrame(float delta) override;
private:
IDirectSoundBuffer8* m_pBuffer;
bool m_IsLopped;
};
Sound_DSound_Impl::Sound_DSound_Impl(const char* sSoundFile) : m_pBuffer(nullptr), m_IsLopped(false)
{
if (!strstr(sSoundFile, ".wav"))
Logger::error("Failed to load sound file '%s'. Only wav supported", sSoundFile);
StreamBase* pStream = g_fileManager->OpenStream( sSoundFile, FileAccess::Read );
assert( pStream );
pStream->seek(SeekDir::End, 0);
size_t length = pStream->tell();
pStream->seek(SeekDir::Begin, 0);
uint8_t* filedata = (uint8_t*)malloc(length);
pStream->readBuffer(filedata, length);
delete pStream;
pStream = nullptr;
DSBUFFERDESC bufferDesc = {};
//g_DirectSound->CreateSoundBuffer( as )
}
Sound_DSound_Impl::~Sound_DSound_Impl()
{
}
void Sound_DSound_Impl::play()
{
m_pBuffer->Play(0, 0, m_IsLopped ? DSBPLAY_LOOPING : 0);
}
void Sound_DSound_Impl::Stop()
{
m_pBuffer->Stop();
}
void Sound_DSound_Impl::Pause()
{
}
bool Sound_DSound_Impl::isPlaying() const
{
return false;
}
bool Sound_DSound_Impl::isPaused() const
{
return false;
}
bool Sound_DSound_Impl::IsLooped() const
{
return m_IsLopped;
}
void Sound_DSound_Impl::SetLooped(bool bLooped)
{
m_IsLopped = bLooped;
}
float Sound_DSound_Impl::GetVolume() const
{
return 1.0f;
}
void Sound_DSound_Impl::SetVolume(float fVolume)
{
}
void Sound_DSound_Impl::OnFrame(float delta)
{
}
//bool cSoundBuffer::SetVolume(short percent)
//{
// long Volume;
// if (m_buffer == NULL)
// return false;
//
// if (!percent)
// Volume = DSBVOLUME_MIN;
// else
// Volume = -20 * (100 - (percent % 101));
//
// if (FAILED(m_buffer->SetVolume(Volume)))
// return false; return true;
//}
//
//bool cSoundBuffer::SetPan(signed long level)
//{
// signed long Pan;
//
// if (m_buffer == NULL)
// return false;
//
// if (level < 0)
// Pan = DSBPAN_LEFT / 100 * ((-level) % 101);
// else
// Pan = DSBPAN_RIGHT / 100 * (level % 101);
//
// if (FAILED(m_buffer->SetPan(Pan)))
// return false;
//
// return true;
//}
/////////////////////////////////////////////////////////////////////////////////////////
// Sound System implementation
class SoundSystem_DSound : public ISoundSystem
{
public:
SoundSystem_DSound(HWND hWndHandle);
~SoundSystem_DSound();
void InitPrimaryBuffer();
void selectDevice(SoundDeviceID deviceId) override;
SoundDeviceID selectedDevice() const override;
ISound* CreateSound(const char* sSoundFile) override;
void DestroySound(ISound*& pSound) override;
void Update(float delta) override;
void StopAllSounds() override;
void PauseAllSounds() override;
void ReleaseAllSounds() override;
float GetMasterVolume() const override;
void SetMasterVolume(float fVolume) override;
private:
std::vector< Sound_DSound_Impl* > m_Sounds;
float m_MasterVolume;
};
SoundSystem_DSound::SoundSystem_DSound(HWND hWndHandle) :
m_MasterVolume(0.0f)
{
Logger::logPrint("Starting SOUND system ...");
HRESULT hr = DirectSoundCreate8(NULL, &g_DirectSound, NULL);
if (FAILED(hr))
Logger::error("Failed to initialize DirectSound");
// Set cooperative level to the engine window
hr = g_DirectSound->SetCooperativeLevel(hWndHandle, DSSCL_PRIORITY);
if (FAILED(hr))
Logger::error("g_DirectSound->SetCooperativeLevel(...) Failed!");
InitPrimaryBuffer();
Logger::logPrint("SoundSystem_DSound: Created device successfully");
}
SoundSystem_DSound::~SoundSystem_DSound()
{
ReleaseAllSounds();
if (g_PrimaryBuffer)
{
g_PrimaryBuffer->Release();
g_PrimaryBuffer = nullptr;
}
if (g_DirectSound)
{
g_DirectSound->Release();
g_DirectSound = nullptr;
}
}
void SoundSystem_DSound::InitPrimaryBuffer()
{
// Create primary buffer.
DSBUFFERDESC dsbd;
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
HRESULT hr = g_DirectSound->CreateSoundBuffer(&dsbd, &g_PrimaryBuffer, NULL);
if (FAILED(hr))
Logger::error("SoundSystem_DSound::InitPrimaryBuffer: Failed to create primary buffer");
const int bitCount = 16;
const int channelCount = 2;
const int sampleRate22k = 22050;
const int sampleRate44k = 44100;
// calculate buffer format
WAVEFORMATEX waveFormat;
memset(&waveFormat, 0, sizeof(waveFormat));
waveFormat.cbSize = sizeof(WAVEFORMATEX);
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = channelCount;
waveFormat.nSamplesPerSec = sampleRate44k;
waveFormat.nBlockAlign = channelCount * bitCount / 8;
waveFormat.nAvgBytesPerSec = sampleRate44k * waveFormat.nBlockAlign;
waveFormat.wBitsPerSample = sampleRate44k;
// For safety only :)
g_PrimaryBuffer->SetFormat(&waveFormat);
g_PrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
Logger::logPrint("SoundSystem_DSound::InitPrimaryBuffer: Created primary buffer with %i sample rate", waveFormat.nSamplesPerSec);
}
void SoundSystem_DSound::selectDevice(SoundDeviceID deviceId)
{
// Stub method
}
SoundDeviceID SoundSystem_DSound::selectedDevice() const
{
// Stub method
return 0;
}
// SOUND Creation
ISound* SoundSystem_DSound::CreateSound(const char* sSoundFile)
{
Sound_DSound_Impl* pSoundImpl = new Sound_DSound_Impl(sSoundFile);
m_Sounds.push_back(pSoundImpl);
return pSoundImpl;
}
void SoundSystem_DSound::DestroySound(ISound*& pSound)
{
// find sound in the cache
std::vector< Sound_DSound_Impl* >::iterator it = std::find(m_Sounds.begin(), m_Sounds.end(), pSound);
if (it != m_Sounds.end())
{
m_Sounds.erase( it );
}
// delete sound
delete pSound;
pSound = nullptr;
}
LONG dsu_CalcVolume(const float Volume)
{
LONG Result = 0;
if (Volume == 0)
Result = -10000;
else
Result = -round(1000 * log(1 / Volume));
return Result;
}
void SoundSystem_DSound::Update(float delta)
{
if (!g_PrimaryBuffer)
Logger::error("SoundSystem_DSound::Update: Canno't update sound system without primary buffer.");
g_PrimaryBuffer->SetVolume(dsu_CalcVolume(m_MasterVolume));
int soundsNbr = m_Sounds.size();
for (int i = 0; i < soundsNbr; i++)
{
// Sanity check
if (m_Sounds[i])
m_Sounds[i]->OnFrame( delta );
}
}
void SoundSystem_DSound::StopAllSounds()
{
int soundsNbr = m_Sounds.size();
for (int i = 0; i < soundsNbr; i++)
{
// Sanity check
if (m_Sounds[i])
m_Sounds[i]->Stop();
}
}
void SoundSystem_DSound::PauseAllSounds()
{
int soundsNbr = m_Sounds.size();
for (int i = 0; i < soundsNbr; i++)
{
// Sanity check
if (m_Sounds[i])
m_Sounds[i]->Pause();
}
}
void SoundSystem_DSound::ReleaseAllSounds()
{
int soundsNbr = m_Sounds.size();
for (int i = 0; i < soundsNbr; i++)
{
if (m_Sounds[i])
{
delete m_Sounds[i];
m_Sounds[i] = nullptr;
}
}
m_Sounds.clear();
Logger::logPrint("SoundSystem_DSound::ReleaseAllSounds: Cleared %i sounds", soundsNbr);
}
float SoundSystem_DSound::GetMasterVolume() const
{
return m_MasterVolume;
}
void SoundSystem_DSound::SetMasterVolume(float fVolume)
{
m_MasterVolume = fVolume;
}
// Sound System Factory
ISoundSystem* CreateSoundSystem_DirectSound(void* wndHandle)
{
return new SoundSystem_DSound( (HWND)wndHandle );
}

105
src/engine/utils/logger.cpp Normal file
View File

@ -0,0 +1,105 @@
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <Windows.h>
#include "utils/logger.h"
namespace
{
static FILE* s_logFileHandle = nullptr;
static DWORD s_logOpenTime = 0;
void logWriteMsg(const char* msg)
{
DWORD dwCurrentTime = GetTickCount() - s_logOpenTime;
static char buffer[1024];
int len = sprintf(buffer, "%02lu:%02lu.%02lu: %s",
dwCurrentTime / 60000, dwCurrentTime / 1000 % 60, dwCurrentTime % 1000 / 10, msg);
if (s_logFileHandle)
{
fwrite(buffer, sizeof(char), len, s_logFileHandle);
fflush(s_logFileHandle);
}
}
}
void Logger::init()
{
s_logFileHandle = fopen("output.txt", "w");
assert(s_logFileHandle);
struct tm newtime;
__time32_t aclock;
char buffer[32];
_time32(&aclock);
_localtime32_s(&newtime, &aclock);
errno_t errNum = asctime_s(buffer, 32, &newtime);
char timeBuffer[1024];
int len = sprintf(timeBuffer, "Log started: %s", buffer);
fwrite(timeBuffer, sizeof(char), len, s_logFileHandle);
s_logOpenTime = GetTickCount();
}
void Logger::shutdown()
{
if (s_logFileHandle)
{
fclose(s_logFileHandle);
s_logFileHandle = nullptr;
}
}
void Logger::logPrint(const char* msg, ...)
{
static char buffer[2048 * 2];
va_list args;
va_start(args, msg);
vsnprintf(buffer, sizeof(buffer), msg, args);
va_end(args);
strcat(buffer, "\n");
OutputDebugStringA(buffer);
// write to console
fwrite(buffer, sizeof(char), strlen(buffer), stdout);
logWriteMsg(buffer);
}
void Logger::error(const char* msg, ...)
{
static char buffer[2048 * 2];
va_list args;
va_start(args, msg);
vsnprintf(buffer, sizeof(buffer), msg, args);
va_end(args);
strcat(buffer, "\n");
OutputDebugStringA(buffer);
// write to console
fwrite(buffer, sizeof(char), strlen(buffer), stdout);
logWriteMsg(buffer);
MessageBoxA(NULL, buffer, "Engine Error", MB_OK | MB_ICONERROR);
if (IsDebuggerPresent())
DebugBreak();
//else
exit(-1);
}

16
src/engine/utils/logger.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef LOGGER_H
#define LOGGER_H
class Logger
{
public:
static void init();
static void shutdown();
static void logPrint(const char* msg, ...);
static void error(const char* msg, ...);
};
#define Msg Logger::logPrint
#define LogPrint Logger::logPrint
#endif // !LOGGER_H

View File

@ -0,0 +1,61 @@
#include <utils/maths.h>
Vec3 g_zeroVector = Vec3(0.0f, 0.0f, 0.0f);
Vec3 g_identityVector = Vec3(1.0f, 1.0f, 1.0f);
Matrix g_identityMatrix = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
BoundingBox g_identityBoundingBox = { { -0.1f, -0.1f, -0.1f }, { 0.1f, 0.1f, 0.1f } };
void TransformBoundingBox(BoundingBox& bbox, const glm::mat4& model)
{
#if 1
// transform to center/extents box representation
glm::vec3 center = (bbox.max + bbox.min) * glm::vec3(0.5);
glm::vec3 extents = bbox.max - center;
// transform center
glm::vec3 t_center = glm::vec3(model * glm::vec4(center, 1.0));
// transform extents (take maximum)
glm::mat3 abs_mat = glm::mat3(abs(glm::vec3(model[0])), abs(glm::vec3(model[1])), abs(glm::vec3(model[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;
bbox.min = tmin;
bbox.max = tmax;
#else
glm::mat3 M(model);
// Split the transform into a translation vector (T) and a 3x3 rotation (M).
BoundingBox B = {}; // zero-volume AABB at T
for (int i = 0, j = 0; i < 3, j < 3; i++, j++)
{
float a = M[i][j] * bbox.min[j];
float b = M[i][j] * bbox.max[j];
B.min[i] += a < b ? a : b;
B.max[i] += a < b ? b : a;
}
bbox.min = B.min;
bbox.max = B.max;
#endif
}
void TransformOBB(OBB& obb, const BoundingBox& bbox, const glm::mat4& model)
{
// transform to center/extents box representation
glm::vec3 center = (bbox.max + bbox.min) * glm::vec3(0.5);
glm::vec3 extents = bbox.max - center;
// transform center
glm::vec3 t_center = glm::vec3(model * glm::vec4(center, 1.0));
}

339
src/engine/utils/maths.h Normal file
View File

@ -0,0 +1,339 @@
// maths.h - Simple mathematics library with aggressive inlining.
#ifndef MATHS_H
#define MATHS_H
#include <math.h>
#include <memory.h>
// Define M_PI
#ifndef M_PI
#define M_PI 3.14159265358979323846 // pi
#endif // !M_PI
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/quaternion.hpp>
#pragma warning( disable : 4244 )
struct Point2
{
int x;
int y;
};
struct Vec2
{
float x;
float y;
Vec2() : x(0.0f), y(0.0f) {}
Vec2(float _val) : x(_val), y(_val) {}
Vec2(float _x, float _y) : x(_x), y(_y) {}
// Vec2 with Vec2 operations
inline Vec2 operator+(const Vec2& rhs) const { return Vec2(x + rhs.x, y + rhs.y); }
inline Vec2 operator-(const Vec2& rhs) const { return Vec2(x - rhs.x, y - rhs.y); }
inline Vec2 operator*(const Vec2& rhs) const { return Vec2(x * rhs.x, y * rhs.y); }
inline Vec2 operator/(const Vec2& rhs) const { return Vec2(x / rhs.x, y / rhs.y); }
inline Vec2& operator+=(const Vec2& rhs) { *this = *this + rhs; return *this; }
inline Vec2& operator*=(const Vec2& rhs) { *this = *this * rhs; return *this; }
inline Vec2& operator-=(const Vec2& rhs) { *this = *this - rhs; return *this; }
inline Vec2& operator/=(const Vec2& rhs) { *this = *this / rhs; return *this; }
// Vec2 with Scalar operations
inline Vec2 operator+(const float s) const { return Vec2(x + s, y + s); }
inline Vec2 operator-(const float s) const { return Vec2(x - s, y - s); }
inline Vec2 operator*(const float s) const { return Vec2(x * s, y * s); }
inline Vec2 operator/(const float s) const { return Vec2(x / s, y / s); }
inline Vec2& operator+=(const float s) { *this = *this + s; return *this; }
inline Vec2& operator*=(const float s) { *this = *this * s; return *this; }
inline Vec2& operator-=(const float s) { *this = *this - s; return *this; }
inline Vec2& operator/=(const float s) { *this = *this / s; return *this; }
};
struct Vec3
{
float x;
float y;
float z;
Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
Vec3(float _val) : x(_val), y(_val), z(_val) {}
Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
// Vec3 with Vec2 operations
inline Vec3 operator+(const Vec2& rhs) const { return Vec3(x + rhs.x, y + rhs.y, z); }
inline Vec3 operator-(const Vec2& rhs) const { return Vec3(x - rhs.x, y - rhs.y, z); }
inline Vec3 operator*(const Vec2& rhs) const { return Vec3(x * rhs.x, y * rhs.y, z); }
inline Vec3 operator/(const Vec2& rhs) const { return Vec3(x / rhs.x, y / rhs.y, z); }
inline Vec3& operator+=(const Vec2& rhs) { *this = *this + rhs; return *this; }
inline Vec3& operator*=(const Vec2& rhs) { *this = *this * rhs; return *this; }
inline Vec3& operator-=(const Vec2& rhs) { *this = *this - rhs; return *this; }
inline Vec3& operator/=(const Vec2& rhs) { *this = *this / rhs; return *this; }
// Vec3 with Vec3 operations
inline Vec3 operator+(const Vec3& rhs) const { return Vec3(x + rhs.x, y + rhs.y, z + rhs.z); }
inline Vec3 operator-(const Vec3& rhs) const { return Vec3(x - rhs.x, y - rhs.y, z - rhs.z); }
inline Vec3 operator*(const Vec3& rhs) const { return Vec3(x * rhs.x, y * rhs.y, z * rhs.z); }
inline Vec3 operator/(const Vec3& rhs) const { return Vec3(x / rhs.x, y / rhs.y, z / rhs.z); }
inline Vec3& operator+=(const Vec3& rhs) { *this = *this + rhs; return *this; }
inline Vec3& operator*=(const Vec3& rhs) { *this = *this * rhs; return *this; }
inline Vec3& operator-=(const Vec3& rhs) { *this = *this - rhs; return *this; }
inline Vec3& operator/=(const Vec3& rhs) { *this = *this / rhs; return *this; }
// Vec3 with Scalar operations
inline Vec3 operator+(const float s) const { return Vec3(x + s, y + s, z + s); }
inline Vec3 operator-(const float s) const { return Vec3(x - s, y - s, z - s); }
inline Vec3 operator*(const float s) const { return Vec3(x * s, y * s, z * s); }
inline Vec3 operator/(const float s) const { return Vec3(x / s, y / s, z / s); }
inline Vec3& operator+=(const float s) { *this = *this + s; return *this; }
inline Vec3& operator*=(const float s) { *this = *this * s; return *this; }
inline Vec3& operator-=(const float s) { *this = *this - s; return *this; }
inline Vec3& operator/=(const float s) { *this = *this / s; return *this; }
// Vec3 with GLM Vec3 operations (please delete someday :)
inline Vec3 operator+(const glm::vec3& rhs) const { return Vec3(x + rhs.x, y + rhs.y, z + rhs.z); }
inline Vec3 operator-(const glm::vec3& rhs) const { return Vec3(x - rhs.x, y - rhs.y, z - rhs.z); }
inline Vec3 operator*(const glm::vec3& rhs) const { return Vec3(x * rhs.x, y * rhs.y, z * rhs.z); }
inline Vec3 operator/(const glm::vec3& rhs) const { return Vec3(x / rhs.x, y / rhs.y, z / rhs.z); }
inline Vec3& operator+=(const glm::vec3& rhs) { *this = *this + rhs; return *this; }
inline Vec3& operator*=(const glm::vec3& rhs) { *this = *this * rhs; return *this; }
inline Vec3& operator-=(const glm::vec3& rhs) { *this = *this - rhs; return *this; }
inline Vec3& operator/=(const glm::vec3& rhs) { *this = *this / rhs; return *this; }
};
extern Vec3 g_zeroVector;
extern Vec3 g_identityVector;
struct Vec4
{
float x;
float y;
float z;
float w;
};
inline Vec3 operator+(const float s, const Vec3& v)
{
return Vec3(s + v.x, s + v.y, s + v.z);
}
inline Vec3 operator-(const float s, const Vec3& v)
{
return Vec3(s - v.x, s - v.y, s - v.z);
}
inline Vec3 operator*(const float s, const Vec3& v)
{
return Vec3(s * v.x, s * v.y, s * v.z);
}
inline Vec3 operator/(const float s, const Vec3& v)
{
return Vec3(s / v.x, s / v.y, s / v.z);
}
inline float lerp(float f, float a, float b)
{
return a * (1.0 - f) + (b * f);
}
inline Vec3 lerp(float f, const Vec3& a, const Vec3& b)
{
return a * (1.0 - f) + (b * f);
}
inline bool GetBoxIntersection2D(const Vec2& boxAmins, const Vec2& boxAmaxs,
const Vec2& boxBmins, const Vec2& boxBmaxs)
{
float xMin1 = boxAmins.x;
float yMin1 = boxAmins.y;
float xMax1 = boxAmaxs.x;
float yMax1 = boxAmaxs.y;
float xMin2 = boxBmins.x;
float yMin2 = boxBmins.y;
float xMax2 = boxBmaxs.x;
float yMax2 = boxBmaxs.y;
if (xMin1 < xMax2 || xMax1 > xMin2)
return false;
if (yMin1 < yMax2 || yMax1 > yMin2)
return false;
return true;
}
inline float DegtoRad(float _deg)
{
return _deg * M_PI / 180.0f;
}
inline float RadtoDeg(float _rad)
{
return _rad / M_PI * 180.0f;
}
inline Vec3 sub(const Vec3& _a, const Vec3& _b)
{
return Vec3(_a.x - _b.x, _a.y - _b.y, _a.z - _b.z);
}
inline Vec3 sub(const Vec3 _a, float _b)
{
return Vec3(_a.x - _b, _a.y - _b, _a.z - _b);
}
inline Vec3 mul(const Vec3& _a, const Vec3& _b)
{
return Vec3(_a.x * _b.x, _a.y * _b.y, _a.z * _b.z);
}
inline Vec3 mul(const Vec3& _a, float _b)
{
return Vec3(_a.x * _b, _a.y * _b, _a.z * _b);
}
inline float dot(const Vec3& _a, const Vec3& _b)
{
return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z;
}
inline float length(const Vec3& _a)
{
return sqrt(dot(_a, _a));
}
inline Vec3 normalize(const Vec3& _a)
{
const float invLen = 1.0f / length(_a);
const Vec3 result = mul(_a, invLen);
return result;
}
inline Vec3 cross(const Vec3& _a, const Vec3& _b)
{
return Vec3(_a.y * _b.z - _a.z * _b.y, _a.z * _b.x - _a.x * _b.z, _a.x * _b.y - _a.y * _b.x);
}
// Matrix class
struct Matrix
{
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
struct {
Vec3 i; float _14_;
Vec3 j; float _24_;
Vec3 k; float _34_;
Vec3 c; float _44_;
};
float m[4][4];
};
float* data() const { return (float*)this; }
float* operator()()const{ return (float*)this; }
};
extern Matrix g_identityMatrix;
inline Matrix MakePerspective(float fovy, float aspect, float znear, float zfar)
{
Matrix M = {};
float f = 1.f / tanf(fovy / 2.f),
A = (zfar + znear) / (znear - zfar),
B = (2.f * zfar * znear) / (znear - zfar);
M._11 = f / aspect; M._12 = 0.f; M._13 = 0.f; M._14 = 0.f;
M._21 = 0.f; M._22 = f; M._23 = 0.f; M._24 = 0.f;
M._31 = 0.f; M._32 = 0.f; M._33 = A; M._34 = B;
M._41 = 0.f; M._42 = 0.f; M._43 = -1.f; M._44 = 0.f;
return M;
}
struct BoundingBox
{
glm::vec3 min;
glm::vec3 max;
};
struct OBB
{
BoundingBox bbox;
glm::mat4 rot;
};
extern BoundingBox g_identityBoundingBox;
void TransformBoundingBox(BoundingBox& bbox, const glm::mat4& model);
void TransformOBB(OBB& obb, const BoundingBox& bbox, const glm::mat4& model);
inline bool GetBBoxIntersection3D(const BoundingBox& boxA, const BoundingBox& boxB)
{
return ((boxA.max.x >= boxB.min.x) && (boxA.min.x <= boxB.max.x) &&
(boxA.max.z >= boxB.min.z) && (boxA.min.z <= boxB.max.z) &&
(boxA.max.y >= boxB.min.y) && (boxA.min.y <= boxB.max.y));
}
inline bool RayBoxIntersection(const Vec3& ray_pos, const Vec3& ray_dir, BoundingBox& box, float& tmin)
{
float lo = ray_dir.x * (box.min.x - ray_pos.x);
float hi = ray_dir.x * (box.max.x - ray_pos.x);
float tmax;
tmin = fminf(lo, hi);
tmax = fmaxf(lo, hi);
float lo1 = ray_dir.y * (box.min.y - ray_pos.y);
float hi1 = ray_dir.y * (box.max.y - ray_pos.y);
tmin = fmaxf(tmin, fminf(lo1, hi1));
tmax = fminf(tmax, fmaxf(lo1, hi1));
float lo2 = ray_dir.z * (box.min.z - ray_pos.z);
float hi2 = ray_dir.z * (box.max.z - ray_pos.z);
tmin = fmaxf(tmin, fminf(lo2, hi2));
tmax = fminf(tmax, fmaxf(lo2, hi2));
return (tmin <= tmax) && (tmax > 0.f);
}
// GLM Stuff
inline glm::vec3 ToGlm(const Vec3& v)
{
return glm::vec3(v.x, v.y, v.z);
}
inline Vec3 ToEngine(const glm::vec3& v)
{
return Vec3(v.x, v.y, v.z);
}
#endif // !MATHS_H

View File

@ -0,0 +1,183 @@
#include <assert.h>
#include <algorithm>
#include "utils/objectmanager.h"
#include "utils/logger.h"
ObjectManager g_ObjectManager;
ObjectManager::ObjectManager()
{
}
ObjectManager::~ObjectManager()
{
}
void ObjectManager::Register( const RuntimeClass* _pRuntimeClass, IObjectConstructor* _pObjectConstructor )
{
// Find already registered object.
std::vector<ObjectRegistryEntry>::iterator it = std::find_if(
m_objectRegistry.begin(),
m_objectRegistry.end(),
[=]( const ObjectRegistryEntry& objectEntry )
{
return objectEntry.pRuntimeClass == _pRuntimeClass;
}
);
assert( it == m_objectRegistry.end() );
ObjectRegistryEntry entry = {};
entry.pRuntimeClass = _pRuntimeClass;
entry.pObjectConstructor = _pObjectConstructor;
m_objectRegistry.push_back( entry );
Msg( "ObjectManager: Registered object %s", _pRuntimeClass->m_classname );
}
IObjectBase* ObjectManager::Create( const RuntimeClass* _pRuntimeClass )
{
// Find already registered object.
std::vector<ObjectRegistryEntry>::iterator it = std::find_if(
m_objectRegistry.begin(),
m_objectRegistry.end(),
[=]( const ObjectRegistryEntry& objectEntry )
{
return objectEntry.pRuntimeClass == _pRuntimeClass;
}
);
assert( it != m_objectRegistry.end() );
IObjectConstructor* pObjectConstructor = it->pObjectConstructor;
assert( pObjectConstructor );
IObjectBase* pObject = pObjectConstructor->Create();
assert( pObject );
// Add reference
//pObject->AddRef();
return pObject;
}
IObjectBase* ObjectManager::CreateByName( const char* _pClassName )
{
// Find already registered object.
std::vector<ObjectRegistryEntry>::iterator it = std::find_if(
m_objectRegistry.begin(),
m_objectRegistry.end(),
[=]( const ObjectRegistryEntry& objectEntry )
{
return strcmp( objectEntry.pRuntimeClass->Name(), _pClassName ) == 0;
}
);
assert( it != m_objectRegistry.end() );
IObjectConstructor* pObjectConstructor = it->pObjectConstructor;
assert( pObjectConstructor );
IObjectBase* pObject = pObjectConstructor->Create();
assert( pObject );
// Add reference
pObject->AddRef();
return pObject;
}
/////////////////////////////////////////////////////////////////////
// Object System Test
class TestObject1 : public IObjectBase
{
DECLARE_RTTI_ROOT( TestObject1 );
public:
TestObject1();
virtual ~TestObject1();
virtual void Foo();
};
IMPLEMENT_RTTI_ROOT( TestObject1 );
TestObject1::TestObject1()
{
Msg( "TestObject1: ctor called" );
}
TestObject1::~TestObject1()
{
Msg( "TestObject1: dtor called" );
}
void TestObject1::Foo()
{
Msg( "TestObject1::Foo() called" );
}
class TestObject2 : public TestObject1
{
DECLARE_RTTI(TestObject2, TestObject1);
public:
TestObject2();
~TestObject2();
void Foo() override;
};
IMPLEMENT_RTTI(TestObject2, TestObject1);
TestObject2::TestObject2()
{
Msg("TestObject2: ctor called");
}
TestObject2::~TestObject2()
{
Msg("TestObject2: dtor called");
}
void TestObject2::Foo()
{
Msg("TestObject2::Foo() called");
}
void TestTPtr()
{
TPtr< TestObject1 > testObjectPtr = CreateObject<TestObject1>();
testObjectPtr->Foo();
TPtr< TestObject2 > testObject2 = CreateObject<TestObject2>();
testObject2->Foo();
}
void ObjectSystemTest()
{
RegisterObject< TestObject1 >();
RegisterObject< TestObject2 >();
Msg( "Creating object" );
IObjectBase* pObject = g_ObjectManager.Create( RUNTIME_CLASS( TestObject1 ) );
pObject->AddRef();
if ( TestObject1* pTestObject = DynamicCast< TestObject1 >( pObject ) )
{
Msg( "DynamicCast for TestObject1 was successful" );
pTestObject->Foo();
}
Msg( "Releasing object" );
pObject->Release();
TestTPtr();
}

View File

@ -0,0 +1,348 @@
#ifndef objectmanagerH_included
#define objectmanagerH_included
#include <assert.h>
#include <vector>
#include <utils/rtti.h>
#include <utils/refcount.h>
// #TODO: Make IRefCount or templated class for AddRef\Release and Ref Counting implementation
// \brief Base interface for all objects.
class IObjectBase : public RefCount
{
public:
// Virtual destructor
virtual ~IObjectBase() {}
// Get RuntimeClass.
virtual const RuntimeClass* GetRuntimeClass() const = 0;
};
// \brief Dynamic Cast
template < typename T >
T* DynamicCast( IObjectBase* _pObject )
{
const RuntimeClass* pRuntimeClass = RUNTIME_CLASS( T );
if ( _pObject->GetRuntimeClass()->IsKindOf( pRuntimeClass ) )
return static_cast< T* >( _pObject );
return nullptr;
}
template <class T>
class _NoAddRefReleaseOnTPtr : public T
{
private:
virtual uint64_t AddRef() = 0;
virtual uint64_t Release() = 0;
};
// TPtrBase provides the basis for all other smart pointers
// The other smartpointers add their own constructors and operators
template <class T>
class TPtrBase
{
protected:
TPtrBase()
{
p = NULL;
}
TPtrBase(T* lp)
{
p = lp;
if (p != NULL)
p->AddRef();
}
public:
typedef T _PtrClass;
~TPtrBase()
{
if (p)
p->Release();
}
operator T* () const
{
return p;
}
T& operator*() const
{
assert(p != NULL);
return *p;
}
//The assert on operator& usually indicates a bug. If this is really
//what is needed, however, take the address of the p member explicitly.
T** operator&()
{
assert(p == NULL);
return &p;
}
_NoAddRefReleaseOnTPtr<T>* operator->() const
{
assert(p != NULL);
return (_NoAddRefReleaseOnTPtr<T>*)p;
}
bool operator!() const
{
return (p == NULL);
}
bool operator<(T* pT) const
{
return p < pT;
}
bool operator!=(T* pT) const
{
return !operator==(pT);
}
bool operator==(T* pT) const
{
return p == pT;
}
// Release the interface and set to NULL
void Release()
{
T* pTemp = p;
if (pTemp)
{
p = NULL;
pTemp->Release();
}
}
// Compare two objects for equivalence
bool IsEqualObject(IObjectBase* pOther)
{
if (p == NULL && pOther == NULL)
return true; // They are both NULL objects
if (p == NULL || pOther == NULL)
return false; // One is NULL the other is not
return p->GetRuntimeClass()->IsKindOf( pOther->GetRuntimeClass() );
/* CComPtr<IUnknown> punk1;
CComPtr<IUnknown> punk2;
p->QueryInterface(__uuidof(IUnknown), (void**)&punk1);
pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2);
return punk1 == punk2;*/
}
// Attach to an existing interface (does not AddRef)
void Attach(T* p2) throw()
{
if (p)
p->Release();
p = p2;
}
// Detach the interface (does not Release)
T* Detach() throw()
{
T* pt = p;
p = NULL;
return pt;
}
bool CopyTo(T** ppT)
{
assert(ppT != NULL);
if (ppT == NULL)
return false;
*ppT = p;
if (p)
p->AddRef();
return true;
}
//template <class Q>
//bool QueryInterface(__deref_out_opt Q** pp) const throw()
//{
// assert(pp != NULL);
//
// const RuntimeClass* pRuntimeClass = RUNTIME_CLASS( Q );
// if ( pRuntimeClass->IsKindOf( pRuntimeClass ) )
// return (Q*)p;
// return p->QueryInterface(__uuidof(Q), (void**)pp);
//}
T* p;
};
inline IObjectBase* TPtrAssign(IObjectBase** pp, IObjectBase* lp)
{
if (pp == NULL)
return NULL;
if (lp != NULL)
lp->AddRef();
if (*pp)
(*pp)->Release();
*pp = lp;
return lp;
}
template <class T>
class TPtr : public TPtrBase<T>
{
public:
TPtr()
{
}
TPtr(T* lp) : TPtrBase<T>(lp)
{
}
TPtr(__in const TPtr<T>& lp) : TPtrBase<T>(lp.p)
{
}
T* operator=(T* lp)
{
if (*this != lp)
{
return static_cast<T*>(TPtrAssign((IObjectBase**)&p, lp));
}
return *this;
}
//template <typename Q>
//T* operator=(__in const TPtr<Q>& lp)
//{
// if (!IsEqualObject(lp))
// {
// return static_cast<T*>(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T)));
// }
// return *this;
//}
T* operator=(__in const TPtr<T>& lp)
{
if (*this != lp)
{
return static_cast<T*>(TPtrAssign((IObjectBase**)&p, lp));
}
return *this;
}
};
// \brief Dynamic Cast
template < typename T >
TPtr< T >* DynamicCast( TPtr< IObjectBase >& _pObject )
{
const RuntimeClass* pRuntimeClass = RUNTIME_CLASS( T );
if ( _pObject->GetRuntimeClass()->IsKindOf( pRuntimeClass ) )
return TPtr< T >( static_cast< T* >( _pObject ) );
return nullptr;
}
// \brief Interface for ObjectConstructor
class IObjectConstructor
{
public:
virtual ~IObjectConstructor() {}
// Create object
virtual IObjectBase* Create() = 0;
};
// \brief A helper class for creating object from inplace new.
template <typename T>
class ObjectConstructor : public IObjectConstructor
{
public:
// Singleton
static ObjectConstructor* GetInstance();
public:
IObjectBase* Create() override;
};
template<typename T>
inline ObjectConstructor<T>* ObjectConstructor<T>::GetInstance()
{
static ObjectConstructor<T> s_Instance;
return &s_Instance;
}
template<typename T>
inline IObjectBase* ObjectConstructor<T>::Create()
{
return new T();
}
// \brief The Object Manager. Store all Runtime Classes and create refcount objects
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
// Register IObjectBase to the object manager
void Register( const RuntimeClass* _pRuntimeClass, IObjectConstructor* _pObjectConstructor );
// Create object
IObjectBase* Create( const RuntimeClass* _pRuntimeClass );
IObjectBase* CreateByName( const char* _pClassName );
// Templated version of Create
template < typename T >
T* Create();
private:
struct ObjectRegistryEntry
{
const RuntimeClass* pRuntimeClass;
IObjectConstructor* pObjectConstructor;
};
std::vector<ObjectRegistryEntry> m_objectRegistry;
};
template< typename T >
inline T* ObjectManager::Create()
{
return Create(RUNTIME_CLASS(T));
}
extern ObjectManager g_ObjectManager;
// Helper function for registering object
template < typename T >
void RegisterObject()
{
g_ObjectManager.Register( RUNTIME_CLASS( T ), ObjectConstructor< T >::GetInstance() );
}
// Helper function for creating object
template < typename T >
TPtr< T > CreateObject()
{
IObjectBase* pObject = g_ObjectManager.Create( RUNTIME_CLASS( T ) );
return TPtr< T >( ( T* )pObject );
}
#endif // !objectmanagerH_included

View File

@ -0,0 +1,45 @@
#ifndef REFCOUNT_H
#define REFCOUNT_H
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
class RefCount
{
public:
// Virtual destructor
virtual ~RefCount() {}
// Add reference
uint64_t AddRef();
// Release (remove reference and destroy object at zero reference's)
uint64_t Release();
private:
// Ref counting
uint64_t m_RefCount = 0;
};
inline uint64_t RefCount::AddRef()
{
++m_RefCount;
return m_RefCount;
}
inline uint64_t RefCount::Release()
{
assert(m_RefCount > 0);
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
#endif

23
src/engine/utils/rtti.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "rtti.h"
RuntimeClass::RuntimeClass(const char* classname) : m_classname(classname), m_baseRuntimeClass(nullptr)
{
}
RuntimeClass::RuntimeClass(const char* classname, const RuntimeClass* baseTypeInfo) : m_classname(classname), m_baseRuntimeClass(baseTypeInfo)
{
}
bool RuntimeClass::IsKindOf(const RuntimeClass* typeInfo) const
{
for (const RuntimeClass* it = this; it != nullptr; it = it->m_baseRuntimeClass)
if (it == typeInfo)
return true;
return false;
}
const char* RuntimeClass::Name() const
{
return m_classname;
}

43
src/engine/utils/rtti.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef RTTI_H
#define RTTI_H
struct RuntimeClass
{
RuntimeClass(const char* classname);
RuntimeClass(const char* classname, const RuntimeClass* baseTypeInfo);
bool IsKindOf(const RuntimeClass* typeInfo) const;
const char* Name() const;
const RuntimeClass* m_baseRuntimeClass;
const char* m_classname;
};
#define DECLARE_RTTI_ROOT(typeName) \
public: \
static const RuntimeClass s_runtimeClass; \
static const RuntimeClass* GetStaticRuntimeClass() { return &s_runtimeClass; } \
virtual const RuntimeClass* GetRuntimeClass() const { return GetStaticRuntimeClass(); }
#define DECLARE_RTTI(typeName, baseTypeName) \
public: \
static const RuntimeClass s_runtimeClass; \
static const RuntimeClass* GetStaticRuntimeClass() { return &s_runtimeClass; } \
virtual const RuntimeClass* GetRuntimeClass() const { return GetStaticRuntimeClass(); }
#define IMPLEMENT_RTTI_ROOT(typeName) \
const RuntimeClass typeName::s_runtimeClass(#typeName, nullptr)
#define IMPLEMENT_RTTI(typeName, baseTypeName) \
const RuntimeClass typeName::s_runtimeClass(#typeName, baseTypeName::GetStaticRuntimeClass())
template <typename T>
const RuntimeClass* GetRuntimeClass()
{
return T::GetStaticRuntimeClass();
}
#define RUNTIME_CLASS(typeName) (typeName::GetStaticRuntimeClass())
#endif //!RTTI_H

View File

@ -0,0 +1,14 @@
#include <stdarg.h>
#include "utils/string.h"
const char* va(const char* fmt, ...)
{
va_list args;
static char buffer[4096];
va_start(args, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
return buffer;
}

10
src/engine/utils/string.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
#include <string>
typedef std::string String;
const char* va(const char* fmt, ...);
#endif // !UTILS_STRING_H

View File

@ -0,0 +1,65 @@
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "timer.h"
#if defined(WIN32) || defined(_WIN32)
class SystemTimerWin32 : public SystemTimer
{
public:
void Init();
void Shutdown();
void Update();
float GetTime();
float GetDelta();
private:
LARGE_INTEGER m_frequency;
LARGE_INTEGER m_startTime;
LARGE_INTEGER m_endTime;
float m_floatFrequency;
float m_deltaTime;
};
static SystemTimerWin32 s_system_timer_win32;
SystemTimer* g_systemTimer = (SystemTimer*)&s_system_timer_win32;
void SystemTimerWin32::Init()
{
QueryPerformanceFrequency(&m_frequency);
m_floatFrequency = (float)m_frequency.QuadPart;
QueryPerformanceCounter(&m_startTime);
m_startTime = m_endTime;
}
void SystemTimerWin32::Shutdown()
{
}
void SystemTimerWin32::Update()
{
QueryPerformanceCounter(&m_startTime);
m_deltaTime = static_cast<float>(m_startTime.QuadPart - m_endTime.QuadPart) / m_frequency.QuadPart;
if (m_deltaTime > 10.0f)
m_deltaTime = 0.0f;
m_endTime = m_startTime;
}
float SystemTimerWin32::GetTime()
{
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
return static_cast<float>(time.QuadPart / m_frequency.QuadPart);
}
float SystemTimerWin32::GetDelta()
{
return m_deltaTime;
}
#endif // WIN32

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