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