Fix major overstep with last commit
[carveJwlIkooP6JGAAIwe30JlM.git] / world_gen.h
1 #ifndef WORLD_GEN_H
2 #define WORLD_GEN_H
3
4 #include "world.h"
5
6 static void world_add_all_if_material( m4x3f transform, scene *pscene,
7 mdl_header *mdl, u32 id )
8 {
9 for( int i=0; i<mdl->node_count; i++ )
10 {
11 mdl_node *pnode = mdl_node_from_id( mdl, i );
12
13 for( int j=0; j<pnode->submesh_count; j++ )
14 {
15 mdl_submesh *sm = mdl_node_submesh( mdl, pnode, j );
16
17 if( sm->material_id == id )
18 {
19 m4x3f transform2;
20 mdl_node_transform( pnode, transform2 );
21 m4x3_mul( transform, transform2, transform2 );
22
23 scene_add_submesh( pscene, mdl, sm, transform2 );
24 }
25 }
26
27 if( pnode->classtype == k_classtype_instance )
28 {
29 if( pnode->sub_uid )
30 {
31 u32 instance_id = pnode->sub_uid -1;
32 struct instance_cache *cache = &world.instance_cache[instance_id];
33 mdl_header *mdl2 = cache->mdl;
34
35 m4x3f transform2;
36 mdl_node_transform( pnode, transform2 );
37 m4x3_mul( transform, transform2, transform2 );
38
39 world_add_all_if_material( transform2, pscene, mdl2, id );
40 }
41 }
42 }
43 }
44
45 static void world_apply_procedural_foliage(void)
46 {
47 mdl_header *mfoliage = mdl_load("models/rs_foliage.mdl");
48
49 v3f volume;
50 v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume );
51 volume[1] = 1.0f;
52
53 m4x3f transform;
54 mdl_node *mblob = mdl_node_from_name( mfoliage, "blob" );
55 mdl_submesh *sm_blob = mdl_node_submesh( mfoliage, mblob, 0 );
56
57 for( int i=0;i<100000;i++ )
58 {
59 v3f pos;
60 v3_mul( volume, (v3f){ vg_randf(), 1000.0f, vg_randf() }, pos );
61 pos[1] = 1000.0f;
62 v3_add( pos, world.geo.bbx[0], pos );
63
64 ray_hit hit;
65 hit.dist = INFINITY;
66
67 if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
68 {
69 if( (hit.normal[1] > 0.8f) && ray_hit_is_terrain(&hit) &&
70 (hit.pos[1] > 0.0f+10.0f) )
71 {
72 v4f qsurface, qrandom;
73 v3f axis;
74
75 v3_cross( (v3f){0.0f,1.0f,0.0f}, hit.normal, axis );
76
77 float angle = v3_dot(hit.normal,(v3f){0.0f,1.0f,0.0f});
78 q_axis_angle( qsurface, axis, angle );
79 q_axis_angle( qrandom, (v3f){0.0f,1.0f,0.0f}, vg_randf()*VG_TAUf );
80 q_mul( qsurface, qrandom, qsurface );
81 q_m3x3( qsurface, transform );
82
83 v3_copy( hit.pos, transform[3] );
84 scene_add_submesh( &world.foliage, mfoliage, sm_blob, transform);
85 }
86 }
87 }
88
89 vg_free( mfoliage );
90 }
91
92 static void world_load(void)
93 {
94 mdl_header *mworld = mdl_load( "models/mp_dev.mdl" );
95 vg_info( "Loading world: models/mp_dev.mdl\n" );
96
97 world.spawn_count = 0;
98 world.traffic_count = 0;
99 world.instance_cache = NULL;
100
101 /*
102 * Process entities
103 */
104 for( int i=0; i<mworld->node_count; i++ )
105 {
106 mdl_node *pnode = mdl_node_from_id( mworld, i );
107
108 if( pnode->classtype == k_classtype_none )
109 {}
110 else if( pnode->classtype == k_classtype_spawn )
111 {
112 struct respawn_point *rp = &world.spawns[ world.spawn_count ++ ];
113
114 v3_copy( pnode->co, rp->co );
115 v4_copy( pnode->q, rp->q );
116 strcpy( rp->name, mdl_pstr( mworld, pnode->pstr_name ) );
117 }
118 else if( pnode->classtype == k_classtype_water )
119 {
120 if( wrender.enabled )
121 {
122 vg_warn( "Multiple water surfaces in level! ('%s')\n",
123 mdl_pstr( mworld, pnode->pstr_name ));
124 continue;
125 }
126
127 mdl_submesh *sm = mdl_node_submesh( mworld, pnode, 0 );
128
129 if( sm )
130 {
131 vg_acquire_thread_sync();
132 {
133 glmesh surf;
134 mdl_unpack_submesh( mworld, &surf, sm );
135 water_set_surface( &surf, pnode->co[1] );
136 }
137 vg_release_thread_sync();
138 }
139 }
140 else if( pnode->classtype == k_classtype_car_path )
141 {
142 struct classtype_car_path *p = mdl_get_entdata( mworld, pnode );
143 traffic_node *tn = &world.traffic[ world.traffic_count ];
144 tn->mn_next = NULL;
145 tn->mn_next1 = NULL;
146
147 if( p->target ) tn->mn_next = mdl_node_from_id( mworld, p->target );
148 if( p->target1 ) tn->mn_next1 = mdl_node_from_id( mworld, p->target1 );
149
150 m4x3f transform;
151 mdl_node_transform( pnode, transform );
152 m3x3_mulv( transform, (v3f){1.0f,0.0f,0.0f}, tn->h );
153 v3_copy( transform[3], tn->co );
154
155 pnode->sub_uid = world.traffic_count ++;
156 }
157 else if( pnode->classtype == k_classtype_instance )
158 {
159 struct classtype_instance *inst = mdl_get_entdata( mworld, pnode );
160 pnode->sub_uid = 0;
161
162 int cached = 0;
163 for( int i=0; i<world.instance_cache_count; i++ )
164 {
165 struct instance_cache *cache = &world.instance_cache[i];
166 if( inst->pstr_file == cache->pstr_file )
167 {
168 cached = 1;
169 pnode->sub_uid = i+1;
170 break;
171 }
172 }
173
174 if( !cached )
175 {
176 world.instance_cache = buffer_reserve(
177 world.instance_cache, world.instance_cache_count,
178 &world.instance_cache_cap, 1,
179 sizeof(struct instance_cache) );
180
181 struct instance_cache *cache =
182 &world.instance_cache[world.instance_cache_count];
183
184 const char *filename = mdl_pstr(mworld, inst->pstr_file);
185
186 cache->pstr_file = inst->pstr_file;
187 cache->mdl = mdl_load( filename );
188
189 if( cache->mdl )
190 {
191 world.instance_cache_count ++;
192 pnode->sub_uid = world.instance_cache_count;
193 mdl_link_materials( mworld, cache->mdl );
194 vg_success( "Cached %s\n", filename );
195 }
196 else
197 {
198 vg_warn( "Failed to cache %s\n", filename );
199 }
200 }
201 }
202 }
203
204 world.instance_cache = buffer_fix( world.instance_cache,
205 world.instance_cache_count,
206 &world.instance_cache_cap,
207 sizeof( struct instance_cache ) );
208
209 #if 0
210 traffic_finalize( world.traffic, world.traffic_count );
211 for( int i=0; i<vg_list_size(world.van_man); i++ )
212 world.van_man[i].current =&world.traffic[vg_randint(world.traffic_count)];
213 #endif
214
215 /*
216 * Compile meshes into the world scenes
217 */
218 scene_init( &world.geo );
219
220 u32 mat_surf = 0,
221 mat_surf_oob = 0,
222 mat_vertex_blend = 0,
223 mat_alphatest = 0,
224 mat_graffiti = 0,
225 mat_subworld = 0,
226 mat_terrain = 0;
227
228 for( int i=1; i<mworld->material_count; i++ )
229 {
230 mdl_material *mat = mdl_material_from_id( mworld, i );
231 const char *mat_name = mdl_pstr( mworld, mat->pstr_name );
232
233 if( !strcmp( "surf", mat_name ))
234 mat_surf = i;
235 else if( !strcmp( "surf_oob", mat_name ))
236 mat_surf_oob = i;
237 else if( !strcmp( "vertex_blend", mat_name ))
238 mat_vertex_blend = i;
239 else if( !strcmp( "alphatest", mat_name ))
240 mat_alphatest = i;
241 else if( !strcmp( "graffitibox", mat_name ))
242 mat_graffiti = i;
243 else if( !strcmp( "terrain", mat_name ) )
244 mat_terrain = i;
245 }
246
247 m4x3f midentity;
248 m4x3_identity( midentity );
249
250 if( mat_terrain )
251 world_add_all_if_material( midentity, &world.geo, mworld, mat_terrain );
252 scene_copy_slice( &world.geo, &world.sm_terrain );
253
254 if( mat_surf_oob )
255 world_add_all_if_material( midentity, &world.geo, mworld, mat_surf_oob );
256 else
257 vg_warn( "No OOB surface\n" );
258 scene_copy_slice( &world.geo, &world.sm_geo_std_oob );
259
260 if( mat_surf )
261 world_add_all_if_material( midentity, &world.geo, mworld, mat_surf );
262 scene_copy_slice( &world.geo, &world.sm_geo_std );
263
264 if( mat_vertex_blend )
265 world_add_all_if_material( midentity, &world.geo,mworld,mat_vertex_blend);
266 scene_copy_slice( &world.geo, &world.sm_geo_vb );
267
268 vg_acquire_thread_sync();
269 scene_upload( &world.geo );
270 vg_release_thread_sync();
271
272 scene_bh_create( &world.geo );
273
274
275 /* Foliage /nocollide layer.
276 * TODO: Probably should have material traits for this
277 */
278 scene_init( &world.foliage );
279
280 world_apply_procedural_foliage();
281 scene_copy_slice( &world.foliage, &world.sm_foliage_main );
282
283 world_add_all_if_material( midentity, &world.foliage, mworld, mat_alphatest);
284 scene_copy_slice( &world.foliage, &world.sm_foliage_alphatest );
285
286 world_add_all_if_material( midentity, &world.foliage, mworld, mat_graffiti );
287 scene_copy_slice( &world.foliage, &world.sm_graffiti );
288
289
290 vg_acquire_thread_sync();
291 {
292 scene_upload( &world.foliage );
293
294 /*
295 * Rendering the depth map
296 */
297 m4x4f ortho;
298 m4x3f camera;
299
300 v3f extent;
301 v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent );
302
303 float fl = world.geo.bbx[0][0],
304 fr = world.geo.bbx[1][0],
305 fb = world.geo.bbx[0][2],
306 ft = world.geo.bbx[1][2],
307 rl = 1.0f / (fr-fl),
308 tb = 1.0f / (ft-fb);
309
310 m4x4_zero( ortho );
311 ortho[0][0] = 2.0f * rl;
312 ortho[2][1] = 2.0f * tb;
313 ortho[3][0] = (fr + fl) * -rl;
314 ortho[3][1] = (ft + fb) * -tb;
315 ortho[3][3] = 1.0f;
316 m4x3_identity( camera );
317
318 glViewport( 0, 0, 1024, 1024 );
319 glDisable(GL_DEPTH_TEST);
320 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
321 shader_fscolour_use();
322 shader_fscolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} );
323 render_fsquad();
324
325 glEnable(GL_BLEND);
326 glBlendFunc(GL_ONE, GL_ONE);
327 glBlendEquation(GL_MAX);
328 render_world_depth( ortho, camera );
329 glDisable(GL_BLEND);
330 glEnable(GL_DEPTH_TEST);
331 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
332
333
334 /*
335 * TODO: World settings entity
336 */
337 struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting;
338 v4_copy( wrender.plane, winfo->g_water_plane );
339
340 v4f bounds;
341 bounds[0] = world.geo.bbx[0][0];
342 bounds[1] = world.geo.bbx[0][2];
343 bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]);
344 bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]);
345 v4_copy( bounds, winfo->g_depth_bounds );
346
347 winfo->g_water_fog = 0.04f;
348 render_update_lighting_ub();
349 }
350
351 vg_release_thread_sync();
352
353 world_routes_loadfrom( mworld );
354
355 for( int i=0; i<world.instance_cache_count; i++ )
356 vg_free( world.instance_cache[i].mdl );
357
358 vg_free( world.instance_cache );
359 vg_free( mworld );
360 scene_free_offline_buffers( &world.foliage );
361
362 /*
363 * Setup scene collider
364 */
365 v3_zero( world.rb_geo.co );
366 q_identity( world.rb_geo.q );
367
368 world.rb_geo.type = k_rb_shape_scene;
369 world.rb_geo.inf.scene.pscene = &world.geo;
370 world.rb_geo.is_world = 1;
371 rb_init( &world.rb_geo );
372 }
373
374 #endif /* WORLD_GEN_H */