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