medium sized dollop
[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 "vg/vg_loader.h"
9
10 #include "network.h"
11 #include "network_msg.h"
12 #include "scene.h"
13 #include "terrain.h"
14 #include "render.h"
15 #include "rigidbody.h"
16 #include "bvh.h"
17 #include "lighting.h"
18 #include "model.h"
19
20 #include "traffic.h" /*TODO: -> world_traffic.h */
21
22 #include "shaders/terrain.h"
23 #include "shaders/sky.h"
24 #include "shaders/planeinf.h"
25 #include "shaders/standard.h"
26 #include "shaders/vblend.h"
27 #include "shaders/gpos.h"
28 #include "shaders/fscolour.h"
29 #include "shaders/alphatest.h"
30
31 enum { k_max_ui_segments = 8 };
32 enum { k_max_ui_splits_per_segment = 16 };
33
34 enum { k_max_ui_elements = k_max_ui_segments*k_max_ui_splits_per_segment };
35 enum { k_max_element_verts = 10 };
36 enum { k_max_element_indices = 20 };
37
38 enum { k_route_ui_max_verts = k_max_ui_elements*k_max_element_verts };
39 enum { k_route_ui_max_indices = k_max_ui_elements*k_max_element_indices };
40
41 static struct gworld
42 {
43 /* gameplay */
44 struct respawn_point
45 {
46 v3f co;
47 v4f q;
48 char name[32];
49 }
50 spawns[32];
51 u32 spawn_count;
52
53 struct subworld_routes
54 {
55 struct route_node
56 {
57 v3f co, right, up, h;
58 u32 next[2];
59
60 u32 special_type, special_id, current_refs, ref_count;
61 u32 route_ids[4]; /* Gates can be linked into up to four routes */
62 }
63 *nodes;
64
65 u32 node_count,
66 node_cap;
67
68 struct route
69 {
70 u32 track_id;
71 v4f colour;
72
73 u32 start;
74 mdl_submesh sm;
75
76 int active;
77 float factive;
78
79 double best_lap, latest_pass; /* Session */
80
81 struct
82 {
83 GLuint vao, vbo, ebo;
84
85 u32 indices_head;
86 u32 vertex_head;
87
88 float last_notch;
89
90 struct route_ui_segment
91 {
92 float length;
93 u32 vertex_start, vertex_count,
94 index_start, index_count, notches;
95 }
96 segments[k_max_ui_segments];
97
98 u32 segment_start, segment_count, fade_start, fade_count;
99 double fade_timer_start;
100 float xpos;
101 }
102 ui;
103
104 m4x3f scoreboard_transform;
105 }
106 *routes;
107
108 double last_interaction;
109
110 u32 route_count,
111 route_cap;
112
113 struct route_gate
114 {
115 struct teleport_gate
116 {
117 v3f co[2];
118 v4f q[2];
119 v2f dims;
120
121 m4x3f to_world, recv_to_world, transport;
122 }
123 gate;
124
125 u32 node_id;
126
127 struct route_timing
128 {
129 u32 version; /* Incremented on every teleport */
130 double time;
131 }
132 timing;
133 }
134 *gates;
135
136 struct route_collector
137 {
138 struct route_timing timing;
139 }
140 *collectors;
141
142 u32 gate_count,
143 gate_cap,
144 collector_count,
145 collector_cap;
146
147 u32 active_gate,
148 current_run_version;
149
150 scene scene_lines;
151 }
152 routes;
153
154 struct subworld_sfd
155 {
156 scene mesh;
157 mdl_submesh *sm_module, *sm_card;
158 glmesh temp;
159
160 struct sfd_instance
161 {
162 float *buffer;
163
164 u32 w,h;
165 }
166 tester;
167 }
168 sfd;
169
170 /* Paths */
171 traffic_node traffic[128];
172 u32 traffic_count;
173
174 #if 0
175 traffic_driver van_man[6];
176 #endif
177
178 /* Physics */
179
180 /* Rendering & geometry */
181 scene geo, foliage;
182 rigidbody rb_geo;
183
184 /* TODO Maybe make this less hardcoded */
185 mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb,
186 sm_foliage_main, sm_foliage_alphatest,
187 sm_graffiti, sm_subworld, sm_terrain;
188
189 glmesh skybox, skydome;
190 mdl_submesh dome_upper, dome_lower;
191
192 glmesh cars;
193 mdl_submesh car_holden;
194
195 /* Load time */
196
197 struct instance_cache
198 {
199 mdl_header *mdl;
200 u32 pstr_file;
201 }
202 * instance_cache;
203 u32 instance_cache_count,
204 instance_cache_cap;
205
206 v3f render_gate_pos;
207 int active_route_board;
208 }
209 world;
210
211 /*
212 * API
213 */
214
215 static int ray_hit_is_ramp( ray_hit *hit );
216 static int ray_hit_is_terrain( ray_hit *hit );
217 static void ray_world_get_tri( ray_hit *hit, v3f tri[3] );
218 static int ray_world( v3f pos, v3f dir, ray_hit *hit );
219
220 /*
221 * Submodules
222 */
223 #include "world_routes.h"
224 #include "world_sfd.h"
225 #include "world_render.h"
226 #include "world_water.h"
227 #include "world_gen.h"
228 #include "world_gate.h"
229
230 /*
231 * -----------------------------------------------------------------------------
232 * Events
233 * -----------------------------------------------------------------------------
234 */
235
236 static int world_init(void)
237 {
238 shader_terrain_register();
239 shader_sky_register();
240 shader_planeinf_register();
241 shader_gpos_register();
242 shader_fscolour_register();
243 shader_alphatest_register();
244
245 vg_info( "Loading world resources\n" );
246
247 mdl_header *mcars = mdl_load( "models/rs_cars.mdl" );
248 mdl_node *nholden = mdl_node_from_name( mcars, "holden" );
249 world.car_holden = *mdl_node_submesh( mcars, nholden, 0 );
250
251 mdl_header *msky = mdl_load("models/rs_skydome.mdl");
252 mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ),
253 *nupper = mdl_node_from_name( msky, "dome_upper" );
254
255 world.dome_lower = *mdl_node_submesh( msky, nlower, 0 );
256 world.dome_upper = *mdl_node_submesh( msky, nupper, 0 );
257
258 /* TODO: cleanup resource acquisition */
259 if( !mcars || !msky )
260 {
261 free( mcars );
262 free( msky );
263 return 0;
264 }
265
266 if( vg_acquire_thread_sync(1) )
267 {
268 if( !mdl_unpack_glmesh( mcars, &world.cars ) )
269 {
270 free( mcars );
271 free( msky );
272 vg_release_thread_sync(1);
273 return 0;
274 }
275
276 if( !mdl_unpack_glmesh( msky, &world.skydome ) )
277 {
278 mesh_free( &world.cars );
279 free( mcars );
280 free( msky );
281 vg_release_thread_sync(1);
282 return 0;
283 }
284
285 vg_release_thread_sync(1);
286 }
287 else
288 {
289 free(mcars);
290 free(msky);
291 return 0;
292 }
293
294 free(mcars);
295 free(msky);
296
297 vg_info( "Loading other world systems\n" );
298
299 if( !vg_loader_highwater( (void *)mesh_free, &world.cars ) ) return 0;
300 if( !vg_loader_highwater( (void *)mesh_free, &world.skydome ) ) return 0;
301
302 /* Other systems */
303
304 if( !world_render_init() ) return 0;
305 if( !vg_loader_highwater( world_render_free, NULL ) ) return 0;
306
307 if( !world_sfd_init() ) return 0;
308 if( !vg_loader_highwater( world_sfd_free, NULL ) ) return 0;
309
310 if( !world_water_init() ) return 0;
311 if( !vg_loader_highwater( world_water_free, NULL ) ) return 0;
312
313 if( !world_gates_init() ) return 0;
314 if( !vg_loader_highwater( world_gates_free, NULL ) ) return 0;
315
316 if( !world_routes_init() ) return 0;
317 if( !vg_loader_highwater( world_routes_free, NULL ) ) return 0;
318 return 1;
319 }
320
321 static void world_update( v3f pos )
322 {
323 world_routes_update();
324 world_routes_debug();
325
326 int closest = 0;
327 float min_dist = INFINITY;
328
329 for( int i=0; i<world.routes.route_count; i++ )
330 {
331 float d = v3_dist2( world.routes.routes[i].scoreboard_transform[3], pos );
332
333 if( d < min_dist )
334 {
335 min_dist = d;
336 closest = i;
337 }
338 }
339
340 if( (world.active_route_board != closest) || network_scores_updated )
341 {
342 network_scores_updated = 0;
343 world.active_route_board = closest;
344 struct subworld_sfd *sfd = &world.sfd;
345
346 struct route *route = &world.routes.routes[closest];
347
348 u32 id = route->track_id;
349
350 if( id != 0xffffffff )
351 {
352 struct netmsg_board *local_board = &scoreboard_client_data.boards[id];
353
354 for( int i=0; i<13; i++ )
355 {
356 sfd_encode( &sfd->tester, i, &local_board->data[27*i] );
357 }
358 }
359 }
360
361 sfd_update( &world.sfd.tester );
362
363 #if 0
364 rb_solver_reset();
365 rb_build_manifold_terrain_sphere( &world.mr_ball );
366
367 for( int i=0; i<5; i++ )
368 rb_solve_contacts( rb_contact_buffer, rb_contact_count );
369
370 rb_iter( &world.mr_ball );
371 rb_update_transform( &world.mr_ball );
372 rb_debug( &world.mr_ball, 0 );
373
374 for( int i=0; i<vg_list_size(world.van_man); i++ )
375 {
376 traffic_drive( &world.van_man[i] );
377 traffic_visualize_car( &world.van_man[i] );
378 }
379 #endif
380 }
381
382 /*
383 * -----------------------------------------------------------------------------
384 * API implementation
385 * -----------------------------------------------------------------------------
386 */
387
388 static void ray_world_get_tri( ray_hit *hit, v3f tri[3] )
389 {
390 for( int i=0; i<3; i++ )
391 v3_copy( world.geo.verts[ hit->tri[i] ].co, tri[i] );
392 }
393
394 static int ray_world( v3f pos, v3f dir, ray_hit *hit )
395 {
396 return scene_raycast( &world.geo, pos, dir, hit );
397 }
398
399 static int ray_hit_is_terrain( ray_hit *hit )
400 {
401 u32 valid_start = 0,
402 valid_end = world.sm_terrain.vertex_count;
403
404 return (hit->tri[0] >= valid_start) &&
405 (hit->tri[0] < valid_end);
406 }
407
408 static int ray_hit_is_ramp( ray_hit *hit )
409 {
410 u32 valid_start = world.sm_geo_std.vertex_start,
411 valid_end = world.sm_geo_vb.vertex_start;
412
413 return (hit->tri[0] >= valid_start) &&
414 (hit->tri[0] < valid_end);
415 }
416
417 #endif /* WORLD_H */