the better walkgrid
[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 #if 0
63 rigidbody mr_box = {
64 .bbx = {{ -1.0f, -0.25f, -0.25f }, { 1.0f, 0.25f, 0.25f }}
65 };
66
67 rigidbody mrs_box = {
68 .bbx = {{ -0.5f, -0.25f, -0.25f }, { 0.5f, 0.25f, 0.25f }}
69 };
70
71 teleport_gate gate_a = {
72 .co = { 0.0f, -3.0f, -15.0f },
73 .q = { 0.0f, 0.0f, 0.0f, 1.0f }
74 },
75 gate_b = {
76 .co = { -8.0f, -3.0f, -17.0f },
77 .q = { 0.0f, 0.0f, 0.0f, 1.0f }
78 };
79 #endif
80
81 static int playermodel( int argc, char const *argv[] )
82 {
83 if( argc < 1 ) return 0;
84
85 glmesh old_mesh = player.mdl.mesh;
86
87 if( character_load( &player.mdl, argv[0] ) )
88 mesh_free( &old_mesh );
89
90 return 1;
91 }
92
93 void vg_start(void)
94 {
95 vg_convar_push( (struct vg_convar){
96 .name = "freecam",
97 .data = &freecam,
98 .data_type = k_convar_dtype_i32,
99 .opt_i32 = { .min=0, .max=1, .clamp=1 },
100 .persistent = 1
101 });
102
103 vg_convar_push( (struct vg_convar){
104 .name = "grid",
105 .data = &walk_grid_iterations,
106 .data_type = k_convar_dtype_i32,
107 .opt_i32 = { .min=0, .max=1, .clamp=0 },
108 .persistent = 1
109 });
110
111 vg_convar_push( (struct vg_convar){
112 .name = "walk_speed",
113 .data = &k_walkspeed,
114 .data_type = k_convar_dtype_f32,
115 .opt_f32 = { .clamp = 0 },
116 .persistent = 1
117 });
118
119 vg_convar_push( (struct vg_convar){
120 .name = "debugcam",
121 .data = &sv_debugcam,
122 .data_type = k_convar_dtype_i32,
123 .opt_i32 = { .min=0, .max=1, .clamp=0 },
124 .persistent = 1
125 });
126
127 vg_convar_push( (struct vg_convar){
128 .name = "debugview",
129 .data = &debugview,
130 .data_type = k_convar_dtype_i32,
131 .opt_i32 = { .min=0, .max=1, .clamp=0 },
132 .persistent = 1
133 });
134
135 vg_function_push( (struct vg_cmd){
136 .name = "reset",
137 .function = reset_player
138 });
139
140 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
141
142 render_init();
143 gate_init();
144 terrain_init();
145 character_init();
146
147 character_load( &player.mdl, "ch_default" );
148 character_init_ragdoll( &player.mdl );
149
150 world_load();
151
152 reset_player( 1, (const char *[]){ "tutorial" } );
153 player_transform_update();
154 }
155
156 void vg_update(void)
157 {
158 player_update();
159 }
160
161 static void vg_framebuffer_resize( int w, int h )
162 {
163 render_fb_resize();
164 gate_fb_resize();
165 water_fb_resize();
166 }
167
168 void vg_render(void)
169 {
170 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
171 glViewport( 0,0, vg_window_x, vg_window_y );
172
173 glDisable( GL_DEPTH_TEST );
174 glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
175 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
176
177 float speed = freecam? 0.0f: v3_length( player.v );
178 v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
179 v3_muls( shake, speed*0.01f, shake );
180
181 if( player.is_dead )
182 {
183 #if 0
184 v3f delta;
185 v3_sub( player.mdl.ragdoll[k_chpart_head].co, player.follow, delta );
186 v3_normalize(delta);
187
188 v3f follow_pos;
189 v3_muladds( player.mdl.ragdoll[k_chpart_head].co, delta,
190 -1.5f, follow_pos );
191 v3_lerp( player.follow, follow_pos, 0.1f, player.follow );
192 v3_negate( player.follow, final );
193
194
195 float yaw = atan2f( delta[0], -delta[2] );
196 float pitch = asinf( delta[1] );
197 m4x3_rotate_x( world_matrix, -pitch );
198 m4x3_rotate_y( world_matrix, yaw );
199 #endif
200 }
201 else
202 {
203 }
204
205 m4x4f world_4x4;
206 m4x3_expand( player.camera_inverse, world_4x4 );
207
208 gpipeline.fov = freecam? 60.0f: 100.0f; /* 120 */
209 m4x4_projection( vg_pv, gpipeline.fov,
210 (float)vg_window_x / (float)vg_window_y,
211 0.025f, 1000.0f );
212
213 m4x4_mul( vg_pv, world_4x4, vg_pv );
214
215 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
216 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
217 vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
218
219 glEnable( GL_DEPTH_TEST );
220
221 /*
222 * Draw world
223 */
224
225 render_world( vg_pv, player.camera );
226 render_water_texture( player.camera );
227
228 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
229 render_water_surface( vg_pv );
230
231 #if 0
232 vg_tex2d_bind( &tex_water, 1 );
233 render_gate( &gate_a, cam_transform );
234 #endif
235
236
237 /* Copy the RGB of what we have into the background buffer */
238 glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 );
239 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, gpipeline.fb_background );
240 glBlitFramebuffer( 0,0, vg_window_x, vg_window_y,
241 0,0, vg_window_x, vg_window_y,
242 GL_COLOR_BUFFER_BIT,
243 GL_LINEAR );
244
245 /* Clear out the colour buffer, but keep depth */
246 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
247 glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
248
249 if( !player.is_dead )
250 glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
251 else
252 glClear( GL_COLOR_BUFFER_BIT );
253
254 draw_player();
255
256 /* Draw back in the background */
257 glEnable(GL_BLEND);
258 glDisable(GL_DEPTH_TEST);
259 glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
260 glBlendEquation(GL_FUNC_ADD);
261
262 shader_blit_use();
263 shader_blit_uTexMain( 0 );
264 glActiveTexture(GL_TEXTURE0);
265 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
266
267 render_fsquad();
268 glDisable(GL_BLEND);
269
270 /* Other shite */
271 glDisable( GL_DEPTH_TEST );
272 vg_lines_drawall( (float *)vg_pv );
273
274 /* Debugger camera */
275 #if 0
276 glViewport( 0,0, 800, 800 );
277 glClearColor( 0.1f, 0.0f, 0.2f, 1.0f );
278 glClear( GL_DEPTH_BUFFER_BIT );
279
280 m4x3_identity( world_matrix );
281
282 v3f debugcam;
283 v3_negate( player.co, debugcam );
284 debugcam[2] -= 2.0f;
285 debugcam[1] -= 0.7f;
286
287 m4x3_translate( world_matrix, debugcam );
288 m4x3_expand( world_matrix, world_4x4 );
289
290 m4x4_projection( vg_pv,
291 100.0f,
292 (float)128.0f / (float)128.0f,
293 0.1f, 1000.0f );
294 m4x4_mul( vg_pv, world_4x4, vg_pv );
295
296 if(sv_debugcam)
297 {
298 glEnable( GL_DEPTH_TEST );
299 draw_player();
300 }
301 #endif
302
303 glDisable( GL_DEPTH_TEST );
304 vg_lines_drawall( (float *)vg_pv );
305
306 glViewport( 0,0, vg_window_x, vg_window_y );
307 }
308
309 void vg_ui(void)
310 {
311 char buf[20];
312
313 snprintf( buf, 20, "%.2fm/s", v3_length( player.v ) );
314 gui_text( (ui_px [2]){ 0, 0 }, buf, 1, k_text_align_left );
315
316 snprintf( buf, 20, "%.2f %.2f %.2f m/s",
317 player.a[0], player.a[1], player.a[2] );
318 gui_text( (ui_px [2]){ 0, 20 }, buf, 1, k_text_align_left );
319
320 snprintf( buf, 20, "pos %.2f %.2f %.2f",
321 player.co[0], player.co[1], player.co[2] );
322 gui_text( (ui_px [2]){ 0, 40 }, buf, 1, k_text_align_left );
323
324 if( vg_gamepad_ready )
325 {
326 for( int i=0; i<6; i++ )
327 {
328 snprintf( buf, 20, "%.2f", vg_gamepad.axes[i] );
329 gui_text( (ui_px [2]){ 0, (i+3)*20 }, buf, 1, k_text_align_left );
330 }
331 }
332 else
333 {
334 gui_text( (ui_px [2]){ 0, 60 },
335 "Gamepad not ready", 1, k_text_align_left );
336 }
337 }
338
339 void vg_free(void){}