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