checkin
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
1 #include "common.h"
2
3 static int ray_world( v3f pos, v3f dir, ray_hit *hit );
4
5 #ifndef WORLD_H
6 #define WORLD_H
7
8 #include "scene.h"
9 #include "terrain.h"
10 #include "render.h"
11 #include "water.h"
12 #include "rigidbody.h"
13 #include "gate.h"
14 #include "bvh.h"
15 #include "lighting.h"
16 #include "model.h"
17
18 #include "shaders/terrain.h"
19 #include "shaders/sky.h"
20 #include "shaders/planeinf.h"
21 #include "shaders/standard.h"
22 #include "shaders/vblend.h"
23 #include "shaders/gpos.h"
24 #include "shaders/fscolour.h"
25
26 static struct gworld
27 {
28 /* gameplay */
29 v3f tutorial;
30 teleport_gate gates[64];
31 u32 gate_count;
32
33 /* Physics */
34 rigidbody temp_rbs[128];
35 u32 rb_count;
36 bh_tree bhcubes;
37
38 /* Rendering & geometry */
39 scene geo, foliage, props;
40 submodel sm_road, sm_terrain;
41
42 glmesh skybox, skydome;
43 submodel dome_upper,
44 dome_lower;
45 }
46 world;
47
48 vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi",
49 .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
50
51 vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
52 .flags = VG_TEXTURE_NEAREST };
53
54 static void ray_world_get_tri( ray_hit *hit, v3f tri[3] )
55 {
56 for( int i=0; i<3; i++ )
57 v3_copy( world.geo.verts[ hit->tri[i] ].co, tri[i] );
58 }
59
60 static int ray_world( v3f pos, v3f dir, ray_hit *hit )
61 {
62 return scene_raycast( &world.geo, pos, dir, hit );
63 }
64
65 static int ray_hit_is_ramp( ray_hit *hit )
66 {
67 return hit->tri[0] < world.sm_road.vertex_count;
68 }
69
70 static void world_register(void)
71 {
72 shader_terrain_register();
73 shader_sky_register();
74 shader_planeinf_register();
75 shader_gpos_register();
76 shader_fscolour_register();
77 }
78
79 static void world_free(void)
80 {
81 /* TODO.. */
82 }
83
84 static void render_world_depth( m4x4f projection, m4x3f camera );
85 static void world_load(void)
86 {
87 /*
88 * Setup scene
89 *
90 * TODO: Call world_free when its ready here
91 *
92 */
93 scene_init( &world.geo );
94 model *mworld = vg_asset_read( "models/mp_dev.mdl" );
95
96 for( int i=0; i<mworld->layer_count; i++ )
97 {
98 submodel *sm = model_get_submodel( mworld, i );
99 if( !strcmp( sm->material, "surf" ) )
100 scene_add_model( &world.geo, mworld, sm, sm->pivot, 0.0f, 1.0f );
101
102 }
103 for( int i=0; i<mworld->layer_count; i++ )
104 {
105 submodel *sm = model_get_submodel( mworld, i );
106 if( !strcmp( sm->material, "vertex_blend" ) )
107 {
108 m4x3f transform;
109 q_m3x3( sm->q, transform );
110 v3_copy( sm->pivot, transform[3] );
111 scene_add_foliage( &world.geo, mworld, sm, transform );
112 }
113 }
114 scene_copy_slice( &world.geo, &world.sm_road );
115
116 for( int i=0; i<mworld->layer_count; i++ )
117 {
118 submodel *sm = model_get_submodel( mworld, i );
119 if( !strcmp( sm->material, "terrain" ) )
120 scene_add_model( &world.geo, mworld, sm, sm->pivot, 0.0f, 1.0f );
121 }
122
123
124 scene_copy_slice( &world.geo, &world.sm_terrain );
125
126 /*
127 * TODO: Parametric marker import
128 */
129 v3_copy( model_marker_get( mworld, "start" )->co, world.tutorial );
130
131 /*
132 * Initialize gates
133 */
134
135 world.gate_count = 0;
136 for( int i=0; i<mworld->marker_count; i++ )
137 {
138 model_marker *ga = model_get_marker( mworld, i );
139
140 if( ga->classtype == k_classtype_gate )
141 {
142 struct classtype_gate *data = get_entdata_raw( mworld, ga );
143
144 if( data->target )
145 {
146 model_marker *gb = model_get_marker( mworld, data->target );
147
148 teleport_gate *gate = &world.gates[ world.gate_count ++ ];
149
150 v3_copy( ga->co, gate->co[0] );
151 v3_copy( gb->co, gate->co[1] );
152 v4_copy( ga->q, gate->q[0] );
153 v4_copy( gb->q, gate->q[1] );
154 v2_copy( ga->s, gate->dims );
155
156 gate_transform_update( gate );
157 }
158 }
159 }
160
161 /*
162 * Load water mesh (1 per world)
163 */
164 for( int i=0; i<mworld->layer_count; i++ )
165 {
166 submodel *sm = model_get_submodel( mworld, i );
167 if( !strcmp( sm->material, "water" ) )
168 {
169 glmesh surf;
170 model_unpack_submodel( mworld, &surf, sm );
171
172 water_init();
173 water_set_surface( &surf, sm->pivot[1] );
174
175 vg_info( "%.3f\n", sm->pivot[1] );
176
177 break;
178 }
179 }
180
181 scene_bh_create( &world.geo );
182 scene_upload( &world.geo );
183
184 scene_init( &world.foliage );
185 model *mfoliage = vg_asset_read("models/rs_foliage.mdl");
186
187 /*
188 * TODO: Load any other meshes into the foliage scene, and create rbs for
189 * them.
190 *
191 * then compute bvh
192 */
193
194 for( int i=0; i<mworld->layer_count; i++ )
195 {
196 submodel *sm = model_get_submodel( mworld, i );
197 if( !strcmp( sm->material, "surf" ) ||
198 !strcmp( sm->material, "terrain" ) ||
199 !strcmp( sm->material, "water" ) ||
200 !strcmp( sm->material, "vertex_blend") )
201 continue;
202
203 m4x3f transform;
204 q_m3x3( sm->q, transform );
205 v3_copy( sm->pivot, transform[3] );
206 scene_add_foliage( &world.foliage, mworld, sm, transform );
207
208 rigidbody *rb = &world.temp_rbs[ world.rb_count ++ ];
209
210 box_copy( sm->bbx, rb->bbx );
211 v3_copy( sm->pivot, rb->co );
212 rb_init( rb );
213 v4_copy( sm->q, rb->q );
214 rb_update_transform( rb );
215 }
216
217 v3f volume;
218 v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
219 volume[1] = 1.0f;
220
221 m4x3f transform;
222
223 submodel *sm_blob = submodel_get( mfoliage, "blob" ),
224 *sm_tree = submodel_get( mfoliage, "tree" );
225
226 for( int i=0;i<100000;i++ )
227 {
228 v3f pos;
229 v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
230 pos[1] = 1000.0f;
231 v3_add( pos, world.geo.bbx[0], pos );
232
233 ray_hit hit;
234 hit.dist = INFINITY;
235
236 if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
237 {
238 if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) &&
239 hit.pos[1] > water_height()+10.0f )
240 {
241 v4f qsurface, qrandom;
242 v3f axis;
243
244 v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
245
246 float angle = v3_dot(hit.normal,(v3f){0.0f,1.0f,0.0f});
247 q_axis_angle( qsurface, axis, angle );
248 q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf()*VG_TAUf );
249 q_mul( qsurface, qrandom, qsurface );
250 q_m3x3( qsurface, transform );
251
252 v3_copy( hit.pos, transform[3] );
253
254 if( vg_randf() < 0.0006f )
255 {
256 m3x3_identity( transform );
257 scene_add_foliage( &world.foliage, mfoliage, sm_tree, transform);
258 }
259 else
260 scene_add_foliage( &world.foliage, mfoliage, sm_blob, transform);
261 }
262 }
263 }
264
265 free( mfoliage );
266 scene_upload( &world.foliage );
267
268
269 /* Prop layer */
270 scene_init( &world.props );
271 for( int i=0; i<mworld->layer_count; i++ )
272 {
273 submodel *sm = model_get_submodel( mworld, i );
274 if( !strcmp( sm->material, "vertex_blend" ) )
275 {
276 m4x3f transform;
277 q_m3x3( sm->q, transform );
278 v3_copy( sm->pivot, transform[3] );
279 scene_add_foliage( &world.props, mworld, sm, transform );
280 }
281 }
282
283 scene_upload( &world.props );
284 free( mworld );
285 bh_create( &world.bhcubes,
286 &bh_system_rigidbodies, world.temp_rbs, world.rb_count );
287
288 /*
289 * Rendering the depth map
290 */
291 m4x4f ortho;
292 m4x3f camera;
293
294 v3f extent;
295 v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent );
296
297 float fl = world.geo.bbx[0][0],
298 fr = world.geo.bbx[1][0],
299 fb = world.geo.bbx[0][2],
300 ft = world.geo.bbx[1][2],
301 rl = 1.0f / (fr-fl),
302 tb = 1.0f / (ft-fb);
303
304 m4x4_zero( ortho );
305 ortho[0][0] = 2.0f * rl;
306 ortho[2][1] = 2.0f * tb;
307 ortho[3][0] = (fr + fl) * -rl;
308 ortho[3][1] = (ft + fb) * -tb;
309 ortho[3][3] = 1.0f;
310 m4x3_identity( camera );
311
312 glViewport( 0, 0, 1024, 1024 );
313 glDisable(GL_DEPTH_TEST);
314 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
315 shader_fscolour_use();
316 shader_fscolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
317 render_fsquad();
318
319 glEnable(GL_BLEND);
320 glBlendFunc(GL_ONE, GL_ONE);
321 glBlendEquation(GL_MAX);
322 render_world_depth( ortho, camera );
323 glDisable(GL_BLEND);
324 glEnable(GL_DEPTH_TEST);
325
326 /*
327 * TODO: World settings entity
328 */
329 struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting;
330 v4_copy( wrender.plane, winfo->g_water_plane );
331
332 v4f bounds;
333 bounds[0] = world.geo.bbx[0][0];
334 bounds[1] = world.geo.bbx[0][2];
335 bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]);
336 bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]);
337 v4_copy( bounds, winfo->g_depth_bounds );
338
339 winfo->g_water_fog = 0.04f;
340 render_update_lighting_ub();
341 }
342
343 static void world_init(void)
344 {
345 vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours,
346 &tex_terrain_noise }, 2 );
347
348
349 model *msky = vg_asset_read("models/rs_skydome.mdl");
350 model_unpack( msky, &world.skydome );
351
352 world.dome_lower = *submodel_get( msky, "dome_lower" );
353 world.dome_upper = *submodel_get( msky, "dome_upper" );
354
355 free(msky);
356 }
357
358 /*
359 * Rendering
360 */
361
362 static void bind_terrain_textures(void)
363 {
364 vg_tex2d_bind( &tex_terrain_noise, 0 );
365 vg_tex2d_bind( &tex_terrain_colours, 1 );
366 }
367
368 static void render_props( m4x4f projection, v3f camera )
369 {
370 m4x3f identity_matrix;
371 m4x3_identity( identity_matrix );
372
373 shader_vblend_use();
374 shader_vblend_uTexGarbage(0);
375 shader_vblend_uTexGradients(1);
376 shader_link_standard_ub( _shader_vblend.id, 2 );
377 bind_terrain_textures();
378
379 shader_vblend_uPv( projection );
380 shader_vblend_uMdl( identity_matrix );
381 shader_vblend_uCamera( camera );
382
383 scene_bind( &world.props );
384 scene_draw( &world.props );
385 }
386
387 static void render_terrain( m4x4f projection, v3f camera )
388 {
389 m4x3f identity_matrix;
390 m4x3_identity( identity_matrix );
391
392 shader_terrain_use();
393 shader_terrain_uTexGarbage(0);
394 shader_terrain_uTexGradients(1);
395 shader_link_standard_ub( _shader_terrain.id, 2 );
396 bind_terrain_textures();
397
398 shader_terrain_uPv( projection );
399 shader_terrain_uMdl( identity_matrix );
400 shader_terrain_uCamera( camera );
401
402 scene_bind( &world.geo );
403 scene_draw( &world.geo );
404
405 glDisable(GL_CULL_FACE);
406 scene_bind( &world.foliage );
407 scene_draw( &world.foliage );
408 glEnable(GL_CULL_FACE);
409 }
410
411 static void render_lowerdome( m4x3f camera )
412 {
413 m4x4f projection, full;
414 pipeline_projection( projection, 0.4f, 1000.0f );
415
416 m4x3f inverse;
417 m3x3_transpose( camera, inverse );
418 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
419 m4x3_expand( inverse, full );
420 m4x4_mul( projection, full, full );
421
422 m4x3f identity_matrix;
423 m4x3_identity( identity_matrix );
424
425 shader_planeinf_use();
426 shader_planeinf_uMdl(identity_matrix);
427 shader_planeinf_uPv(full);
428 shader_planeinf_uCamera(camera[3]);
429 shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f, water_height()} );
430
431 submodel_draw( &world.dome_lower );
432 }
433
434 static void render_sky(m4x3f camera)
435 {
436 m4x4f projection, full;
437 pipeline_projection( projection, 0.4f, 1000.0f );
438
439 m4x3f inverse;
440 m3x3_transpose( camera, inverse );
441 v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]);
442 m4x3_expand( inverse, full );
443 m4x4_mul( projection, full, full );
444
445 m4x3f identity_matrix;
446 m4x3_identity( identity_matrix );
447
448 shader_sky_use();
449 shader_sky_uMdl(identity_matrix);
450 shader_sky_uPv(full);
451 shader_sky_uTexGarbage(0);
452 shader_sky_uTime( vg_time );
453
454 vg_tex2d_bind( &tex_terrain_noise, 0 );
455
456 glDepthMask( GL_FALSE );
457 glDisable( GL_DEPTH_TEST );
458
459 mesh_bind( &world.skydome );
460 submodel_draw( &world.dome_upper );
461
462 glEnable( GL_DEPTH_TEST );
463 glDepthMask( GL_TRUE );
464 }
465
466 static void render_world( m4x4f projection, m4x3f camera )
467 {
468 render_sky( camera );
469 render_props( projection, camera[3] );
470 render_terrain( projection, camera[3] );
471 }
472
473 static void render_world_depth( m4x4f projection, m4x3f camera )
474 {
475 m4x3f identity_matrix;
476 m4x3_identity( identity_matrix );
477
478 shader_gpos_use();
479 shader_gpos_uCamera( camera[3] );
480 shader_gpos_uPv( projection );
481 shader_gpos_uMdl( identity_matrix );
482
483 scene_bind( &world.geo );
484 scene_draw( &world.geo );
485
486 #if 0
487 glDisable(GL_CULL_FACE);
488 scene_bind( &world.foliage );
489 scene_draw( &world.foliage );
490 glEnable(GL_CULL_FACE);
491 #endif
492
493 scene_bind( &world.props );
494 scene_draw( &world.props );
495 }
496
497 #endif /* WORLD_H */