stuff
[carveJwlIkooP6JGAAIwe30JlM.git] / main.c
1 #include "common.h"
2
3 /* Resources */
4 vg_tex2d tex_norwey = { .path = "textures/norway_foliage.qoi" };
5 vg_tex2d tex_grid = { .path = "textures/grid.qoi" };
6 vg_tex2d tex_sky = { .path = "textures/sky.qoi" };
7 vg_tex2d tex_gradients = { .path = "textures/gradients.qoi",
8 .flags = VG_TEXTURE_CLAMP };
9 vg_tex2d tex_cement = { .path = "textures/cement512.qoi" };
10 vg_tex2d tex_water = { .path = "textures/water.qoi" };
11
12 /* Convars */
13 static int debugview = 0;
14 static int sv_debugcam = 0;
15
16 /* Components */
17 #include "road.h"
18 #include "scene.h"
19 #include "ik.h"
20 #include "terrain.h"
21 #include "character.h"
22 #include "ragdoll.h"
23 #include "rigidbody.h"
24 #include "render.h"
25 #include "gate.h"
26 #include "water.h"
27 #include "world.h"
28 #include "player.h"
29
30 #include "shaders/blit.h"
31 #include "shaders/standard.h"
32 #include "shaders/unlit.h"
33
34 void vg_register(void)
35 {
36 shader_blit_register();
37 shader_standard_register();
38 shader_unlit_register();
39
40 terrain_register();
41 character_register();
42 water_register();
43 gate_register();
44 }
45
46 vg_tex2d *texture_list[] =
47 {
48 &tex_norwey,
49 &tex_gradients,
50 &tex_grid,
51 &tex_sky,
52 &tex_cement,
53 &tex_water,
54 &tex_water_surf
55 };
56
57 int main( int argc, char *argv[] )
58 {
59 vg_init( argc, argv, "Voyager Game Engine" );
60 }
61
62 static int playermodel( int argc, char const *argv[] )
63 {
64 if( argc < 1 ) return 0;
65
66 glmesh old_mesh = player.mdl.mesh;
67
68 if( character_load( &player.mdl, argv[0] ) )
69 mesh_free( &old_mesh );
70
71 return 1;
72 }
73
74 void vg_start(void)
75 {
76 vg_convar_push( (struct vg_convar){
77 .name = "freecam",
78 .data = &freecam,
79 .data_type = k_convar_dtype_i32,
80 .opt_i32 = { .min=0, .max=1, .clamp=1 },
81 .persistent = 1
82 });
83
84 vg_convar_push( (struct vg_convar){
85 .name = "grid",
86 .data = &walk_grid_iterations,
87 .data_type = k_convar_dtype_i32,
88 .opt_i32 = { .min=0, .max=1, .clamp=0 },
89 .persistent = 1
90 });
91
92 vg_convar_push( (struct vg_convar){
93 .name = "walk_speed",
94 .data = &k_walkspeed,
95 .data_type = k_convar_dtype_f32,
96 .opt_f32 = { .clamp = 0 },
97 .persistent = 1
98 });
99
100 vg_convar_push( (struct vg_convar){
101 .name = "debugcam",
102 .data = &sv_debugcam,
103 .data_type = k_convar_dtype_i32,
104 .opt_i32 = { .min=0, .max=1, .clamp=0 },
105 .persistent = 1
106 });
107
108 vg_convar_push( (struct vg_convar){
109 .name = "debugview",
110 .data = &debugview,
111 .data_type = k_convar_dtype_i32,
112 .opt_i32 = { .min=0, .max=1, .clamp=0 },
113 .persistent = 1
114 });
115
116 vg_function_push( (struct vg_cmd){
117 .name = "reset",
118 .function = reset_player
119 });
120
121 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
122
123 render_init();
124 gate_init();
125 terrain_init();
126 character_init();
127
128 character_load( &player.mdl, "ch_default" );
129 character_init_ragdoll( &player.mdl );
130
131 world_load();
132
133 reset_player( 1, (const char *[]){ "tutorial" } );
134 player_transform_update();
135 }
136
137 void vg_free(void)
138 {
139 vg_tex2d_free( texture_list, vg_list_size(texture_list) );
140 }
141
142 void vg_update(void)
143 {
144 player_update();
145 }
146
147 static void vg_framebuffer_resize( int w, int h )
148 {
149 render_fb_resize();
150 gate_fb_resize();
151 water_fb_resize();
152 }
153
154 void vg_render(void)
155 {
156 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
157 glViewport( 0,0, vg_window_x, vg_window_y );
158
159 glDisable( GL_DEPTH_TEST );
160 glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
161 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
162
163 float speed = freecam? 0.0f: v3_length( player.v );
164 v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
165 v3_muls( shake, speed*0.01f, shake );
166
167 m4x4f world_4x4;
168 m4x3_expand( player.camera_inverse, world_4x4 );
169
170 gpipeline.fov = freecam? 60.0f: 120.0f; /* 120 */
171 m4x4_projection( vg_pv, gpipeline.fov,
172 (float)vg_window_x / (float)vg_window_y,
173 0.025f, 1000.0f );
174
175 m4x4_mul( vg_pv, world_4x4, vg_pv );
176
177 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
178 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
179 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
180
181 glEnable( GL_DEPTH_TEST );
182
183 /*
184 * Draw world
185 */
186
187 render_world( vg_pv, player.camera );
188 render_water_texture( player.camera );
189
190 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
191 render_water_surface( vg_pv, player.camera );
192
193 vg_tex2d_bind( &tex_water, 1 );
194
195 for( int i=0; i<world.gate_count; i++ )
196 {
197 render_gate( &world.gates[i], player.camera );
198 }
199
200
201 /* Copy the RGB of what we have into the background buffer */
202 glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
203 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, gpipeline.fb_background );
204 glBlitFramebuffer( 0,0, vg_window_x, vg_window_y,
205 0,0, vg_window_x, vg_window_y,
206 GL_COLOR_BUFFER_BIT,
207 GL_LINEAR );
208
209 /* Clear out the colour buffer, but keep depth */
210 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
211 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
212
213 if( !player.is_dead )
214 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
215 else
216 glClear( GL_COLOR_BUFFER_BIT );
217
218 draw_player();
219
220 /* Draw back in the background
221 *
222 * TODO: need to disable alpha write in the terrain shader so this works
223 * again.
224 */
225 glEnable(GL_BLEND);
226 glDisable(GL_DEPTH_TEST);
227 glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
228 glBlendEquation(GL_FUNC_ADD);
229
230 shader_blit_use();
231 shader_blit_uTexMain( 0 );
232 glActiveTexture(GL_TEXTURE0);
233 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
234
235 render_fsquad();
236 glDisable(GL_BLEND);
237
238 /* Other shite */
239 glDisable( GL_DEPTH_TEST );
240 vg_lines_drawall( (float *)vg_pv );
241 glViewport( 0,0, vg_window_x, vg_window_y );
242 }
243
244 void vg_ui(void)
245 {
246 char buf[20];
247
248 snprintf( buf, 20, "%.2fm/s", v3_length( player.v ) );
249 gui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left );
250
251 snprintf( buf, 20, "%.2f %.2f %.2f m/s",
252 player.a[0], player.a[1], player.a[2] );
253 gui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left );
254
255 snprintf( buf, 20, "pos %.2f %.2f %.2f",
256 player.co[0], player.co[1], player.co[2] );
257 gui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left );
258
259 if( vg_gamepad_ready )
260 {
261 for( int i=0; i<6; i++ )
262 {
263 snprintf( buf, 20, "%.2f", vg_gamepad.axes[i] );
264 gui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left );
265 }
266 }
267 else
268 {
269 gui_text( (ui_px [2]){ 0, 60 },
270 "Gamepad not ready", 1, k_text_align_left );
271 }
272 }