1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <ctype.h>
6 #include <sys/stat.h>
7 #include <math.h>
8
9 #ifdef __MSW__
10 # include <windows.h>
11 #endif
12
13 #include <GL/gl.h>
14
15 #include "../include/fio.h"
16 #include "../include/string.h"
17 #include "../include/strexp.h"
18 #include "../include/disk.h"
19
20 #include "gw.h"
21 #include "cp.h"
22 #include "sfm.h"
23 #include "sarreality.h"
24 #include "obj.h"
25 #include "objsound.h"
26 #include "objutils.h"
27 #include "objio.h"
28 #include "messages.h"
29 #include "simmanage.h"
30 #include "simcb.h"
31 #include "simutils.h"
32 #include "weather.h"
33 #include "sar.h"
34 #include "sarfio.h"
35 #include "sceneio.h"
36 #include "config.h"
37
38
39 void SARSceneDestroy(
40 sar_core_struct *core_ptr,
41 sar_scene_struct *scene,
42 sar_object_struct ***ptr, int *total
43 );
44 void SARSceneLoadLocationsToList(
45 sar_core_struct *core_ptr, sar_menu_struct *m,
46 sar_menu_list_struct *list, int list_num,
47 const char *filename
48 );
49 int SARSceneAddPlayerObject(
50 sar_core_struct *core_ptr, sar_scene_struct *scene,
51 const char *model_file,
52 sar_position_struct *pos, sar_direction_struct *dir
53 );
54 int SARSceneLoadFromFile(
55 sar_core_struct *core_ptr,
56 sar_scene_struct *scene,
57 const char *filename,
58 const char *weather_preset_name,
59 void *client_data,
60 int (*progress_func)(void *, long, long)
61 );
62
63
64 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
65 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
66 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
67
68 #define RADTODEG(r) ((r) * 180 / PI)
69 #define DEGTORAD(d) ((d) * PI / 180)
70
71 #define ISCOMMENT(c) ((c) == SAR_COMMENT_CHAR)
72 #define ISCR(c) (((c) == '\n') || ((c) == '\r'))
73
74 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
75
76
77 /*
78 * Deletes all resources on the scene structure and all
79 * objects on the given objects pointer array.
80 *
81 * Does not delete the scene structure itself, but the
82 * scene structure will be reset.
83 */
SARSceneDestroy(sar_core_struct * core_ptr,sar_scene_struct * scene,sar_object_struct *** ptr,int * total)84 void SARSceneDestroy(
85 sar_core_struct *core_ptr, sar_scene_struct *scene,
86 sar_object_struct ***ptr, int *total
87 )
88 {
89 int i;
90 const sar_option_struct *opt = &core_ptr->option;
91
92 if(opt->runtime_debug)
93 printf("SARSceneDestroy(): Destroying scene...\n");
94
95
96 /* Check if total objects is not NULL (which implies ptr is not
97 * NULL)
98 */
99 if(total != NULL)
100 {
101 /* Delete objects pointer array from last to first */
102 for(i = (*total) - 1; i >= 0; i--)
103 SARObjDelete(core_ptr, ptr, total, i);
104 *total = 0;
105 }
106 if(ptr != NULL)
107 {
108 free(*ptr);
109 *ptr = NULL;
110 }
111
112
113 /* Delete scene */
114 if(scene != NULL)
115 {
116 sar_scene_base_struct *base = &scene->base;
117 sar_scene_horizon_struct *horizon_ptr = &scene->horizon;
118
119 /* Title */
120 free(scene->title);
121 scene->title = NULL;
122
123 /* Ground base */
124 /* Visual model simple (far away) */
125 SARVisualModelUnref(scene, base->visual_model_simple);
126 base->visual_model_simple = NULL;
127 /* Visual model complex (close up) */
128 SARVisualModelUnref(scene, base->visual_model_close);
129 base->visual_model_close = NULL;
130
131 /* Cloud Layers */
132 for(i = 0; i < scene->total_cloud_layers; i++)
133 SARCloudLayerDelete(scene, scene->cloud_layer[i]);
134 free(scene->cloud_layer);
135 scene->cloud_layer = NULL;
136 scene->total_cloud_layers = 0;
137
138 /* Cloud BillBoards */
139 for(i = 0; i < scene->total_cloud_bbs; i++)
140 SARCloudBBDelete(scene->cloud_bb[i]);
141 free(scene->cloud_bb);
142 scene->cloud_bb = NULL;
143 scene->total_cloud_bbs = 0;
144
145 /* Horizon */
146 horizon_ptr = &scene->horizon;
147 for(i = 0; i < horizon_ptr->total_textures; i++)
148 V3DTextureDestroy(horizon_ptr->texture[i]);
149 free(horizon_ptr->texture);
150 horizon_ptr->texture = NULL;
151 horizon_ptr->total_textures = 0;
152
153
154 /* Ground objects list, delete only the pointer array and
155 * not each object
156 */
157 free(scene->ground_object);
158 scene->ground_object = NULL;
159 scene->total_ground_objects = 0;
160
161 /* Humans that need rescue list */
162 free(scene->human_need_rescue_object);
163 scene->human_need_rescue_object = NULL;
164 scene->total_human_need_rescue_objects = 0;
165
166 /* Visual models, all visual models should have been
167 * unref'ed by now. So here we actually delete
168 * and destroy the GL lists
169 */
170 SARVisualModelDeleteAll(scene);
171
172 /* Delete all textures */
173 for(i = 0; i < scene->total_texture_refs; i++)
174 V3DTextureDestroy(scene->texture_ref[i]);
175 free(scene->texture_ref); /* Free pointer array */
176 scene->texture_ref = NULL;
177 scene->total_texture_refs = 0;
178
179 /* Reset texture reference indices for special textures */
180 scene->texnum_sun = -1;
181 scene->texnum_moon = -1;
182 scene->texnum_spotlightcast = -1;
183
184 /* Delete all sound sources */
185 for(i = 0; i < scene->total_sndsrcs; i++)
186 SARSoundSourceDelete(scene->sndsrc[i]);
187 free(scene->sndsrc);
188 scene->sndsrc = NULL;
189 scene->total_sndsrcs = 0;
190
191 /* Control panel */
192 CPDelete(
193 (ControlPanel *)scene->player_control_panel
194 );
195 scene->player_control_panel = NULL;
196
197
198 /* Messages */
199 strlistfree(scene->message, scene->total_messages);
200 scene->message = NULL;
201 scene->total_messages = 0;
202
203 /* Sticky banner message */
204 strlistfree(
205 scene->sticky_banner_message,
206 scene->total_sticky_banner_messages
207 );
208 scene->sticky_banner_message = NULL;
209 scene->total_sticky_banner_messages = 0;
210
211 /* Camera reference name/description title string */
212 free(scene->camera_ref_title);
213 scene->camera_ref_title = NULL;
214
215 /* FDM Realm */
216 if(scene->realm != NULL)
217 SFMShutdown(scene->realm);
218
219 /* Reset the rest of the scene structure */
220 memset(scene, 0x00, sizeof(sar_scene_struct));
221 }
222
223 if(opt->runtime_debug)
224 printf("SARSceneDestroy(): Scene destroyed.\n");
225 }
226
227 /*
228 * Loads the list of Registered Locations from the specified
229 * scene file to the specified List.
230 */
SARSceneLoadLocationsToList(sar_core_struct * core_ptr,sar_menu_struct * m,sar_menu_list_struct * list,int list_num,const char * filename)231 void SARSceneLoadLocationsToList(
232 sar_core_struct *core_ptr, sar_menu_struct *m,
233 sar_menu_list_struct *list, int list_num,
234 const char *filename
235 )
236 {
237 int i, ptype, total_parms;
238 void *p, **parm;
239
240 if(list == NULL)
241 return;
242
243 /* Delete existing items in the List */
244 for(i = 0; i < list->total_items; i++)
245 SARDeleteListItemData(list->item[i]);
246 SARMenuListDeleteAllItems(m, list_num);
247
248 /* Load all SAR_PARM_REGISTER_LOCATION parameters from the
249 * scene file
250 */
251 if(SARParmLoadFromFile(
252 filename, SAR_FILE_FORMAT_SCENE,
253 &parm, &total_parms,
254 SAR_PARM_REGISTER_LOCATION, /* Filter */
255 NULL, NULL
256 ))
257 return;
258
259 /* Iterate through loaded parms */
260 for(i = 0; i < total_parms; i++)
261 {
262 p = parm[i];
263 if(p == NULL)
264 continue;
265
266 ptype = *(int *)p;
267 if(ptype == SAR_PARM_REGISTER_LOCATION)
268 {
269 int n;
270 sar_menu_list_item_data_struct *d;
271 sar_parm_register_location_struct *pv =
272 (sar_parm_register_location_struct *)p;
273
274 /* Allocate a new list item data */
275 d = SAR_MENU_LIST_ITEM_DATA(calloc(
276 1, sizeof(sar_menu_list_item_data_struct)
277 ));
278 if(d != NULL)
279 {
280 /* Position */
281 memcpy(
282 &d->pos,
283 &pv->pos,
284 sizeof(sar_position_struct)
285 );
286
287 /* Direction */
288 memcpy(
289 &d->dir,
290 &pv->dir,
291 sizeof(sar_direction_struct)
292 );
293
294 /* Name */
295 d->name = STRDUP(pv->name);
296
297 /* Add this location to the menu's list object */
298 n = SARMenuListAppendItem(
299 m, list_num,
300 d->name, d,
301 0
302 );
303 if(n < 0)
304 {
305 fprintf(
306 stderr,
307 "Error appending list item for starting location `%s'\n",
308 d->name
309 );
310
311 free(d->filename);
312 free(d->name);
313 free(d);
314 }
315 d = NULL;
316 }
317 }
318 }
319
320 /* Delete loaded parms */
321 SARParmDeleteAll(&parm, &total_parms);
322 }
323
324
325 /*
326 * Adds a player object to the scene using the specified model
327 * file and initial position & direction.
328 *
329 * Updates the player object references on the scene.
330 *
331 * All inputs must be valid (except for pos and dir).
332 *
333 * Returns non-zero on error.
334 */
SARSceneAddPlayerObject(sar_core_struct * core_ptr,sar_scene_struct * scene,const char * model_file,sar_position_struct * pos,sar_direction_struct * dir)335 int SARSceneAddPlayerObject(
336 sar_core_struct *core_ptr, sar_scene_struct *scene,
337 const char *model_file,
338 sar_position_struct *pos, sar_direction_struct *dir
339 )
340 {
341 int obj_num;
342 sar_object_struct *obj_ptr;
343 sar_object_aircraft_struct *obj_aircraft_ptr;
344 sar_position_struct lpos;
345 sar_direction_struct ldir;
346
347
348 if((core_ptr == NULL) || (scene == NULL) || (model_file == NULL))
349 return(-1);
350
351 /* Create player object on to scene */
352 obj_num = SARObjNew(
353 scene, &core_ptr->object, &core_ptr->total_objects,
354 SAR_OBJ_TYPE_AIRCRAFT
355 );
356 obj_ptr = (obj_num > -1) ? core_ptr->object[obj_num] : NULL;
357 if(obj_ptr == NULL)
358 return(-1);
359
360 /* Update player object references on scene structure (this
361 * must be done immediately after creating of the player object
362 * so that SARObjLoadFromFile() can tell this is the player
363 * object
364 */
365 scene->player_obj_num = obj_num;
366 scene->player_obj_ptr = obj_ptr;
367
368 /* Load player object model file */
369 SARObjLoadFromFile(core_ptr, obj_num, model_file);
370
371 /* Set object name to "player", this will override the name
372 * of this object specified in the model file. This needs to
373 * be set so that subsequent configurations can reffer to
374 * this object by the name of "player" in order to match it
375 * (ie in mission files)
376 */
377 free(obj_ptr->name);
378 obj_ptr->name = STRDUP("player");
379
380
381 /* Set local position structure */
382 if(pos != NULL)
383 memcpy(&lpos, pos, sizeof(sar_position_struct));
384 else
385 memset(&lpos, 0x00, sizeof(sar_position_struct));
386
387 /* Adjust ground_elevation_msl so that it's at the position of
388 * the player object, this way the player won't suddenly drop
389 * and be destroyed
390 */
391 obj_ptr->ground_elevation_msl = lpos.z;
392
393 /* Move player up from ground level so that it does not added into
394 * the scene while embedded in the ground (which may cause a
395 * crash if the given pos is ontop of a building)
396 */
397 obj_aircraft_ptr = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
398 if(obj_aircraft_ptr != NULL)
399 {
400 lpos.z += (float)MAX(obj_aircraft_ptr->belly_height, 0.0);
401 lpos.z += (float)MAX(obj_aircraft_ptr->gear_height, 0.0);
402 }
403
404 /* Add other object types that need their position modified here */
405
406 /* Set local direction structure */
407 if(dir != NULL)
408 memcpy(&ldir, dir, sizeof(sar_direction_struct));
409 else
410 memset(&ldir, 0x00, sizeof(sar_direction_struct));
411
412 /* Move player object to starting location and attitude */
413 SARSimWarpObject(scene, obj_ptr, &lpos, &ldir);
414
415 return(0);
416 }
417
418 /*
419 * Opens the Scene from the specified file.
420 *
421 * All default values for the Scene will be allocated/created/set
422 * and any existing values will be deleted/reset.
423 *
424 */
SARSceneLoadFromFile(sar_core_struct * core_ptr,sar_scene_struct * scene,const char * filename,const char * weather_preset_name,void * client_data,int (* progress_func)(void *,long,long))425 int SARSceneLoadFromFile(
426 sar_core_struct *core_ptr,
427 sar_scene_struct *scene,
428 const char *filename,
429 const char *weather_preset_name,
430 void *client_data,
431 int (*progress_func)(void *, long, long)
432 )
433 {
434 void *p, **parm;
435 int i, status, ptype, total_parms;
436 int obj_num = -1, *total;
437 gw_display_struct *display;
438 sar_direction_struct *dir;
439 sar_color_struct *c;
440 sar_object_struct *obj_ptr = NULL, ***ptr;
441 sar_object_aircraft_struct *obj_aircraft_ptr = NULL;
442 sar_object_ground_struct *obj_ground_ptr = NULL;
443 sar_object_helipad_struct *obj_helipad_ptr = NULL;
444 sar_object_runway_struct *obj_runway_ptr = NULL;
445 sar_object_human_struct *obj_human_ptr = NULL;
446 sar_object_smoke_struct *obj_smoke_ptr = NULL;
447 sar_object_fire_struct *obj_fire_ptr = NULL;
448 sar_scene_horizon_struct *horizon_ptr;
449 struct stat stat_buf;
450
451 sar_parm_version_struct *p_version;
452 sar_parm_name_struct *p_name;
453 sar_parm_description_struct *p_description;
454 sar_parm_player_model_file_struct *p_player_model_file;
455 sar_parm_weather_struct *p_weather;
456 sar_parm_register_location_struct *p_register_location;
457 sar_parm_scene_gps_struct *p_scene_gps;
458 sar_parm_scene_map_struct *p_scene_map;
459 sar_parm_scene_elevation_struct *p_scene_elevation;
460 sar_parm_scene_cant_struct *p_scene_cant;
461 sar_parm_scene_ground_flags_struct *p_scene_ground_flags;
462 sar_parm_scene_ground_tile_struct *p_scene_ground_tile;
463 sar_parm_texture_base_directory_struct *p_texture_base_directory;
464 sar_parm_texture_load_struct *p_texture_load;
465 sar_parm_new_object_struct *p_new_object;
466 sar_parm_new_helipad_struct *p_new_helipad;
467 sar_parm_new_runway_struct *p_new_runway;
468 sar_parm_new_human_struct *p_new_human;
469 sar_parm_new_smoke_struct *p_new_smoke;
470 sar_parm_new_fire_struct *p_new_fire;
471 sar_parm_new_premodeled_struct *p_new_premodeled;
472 sar_parm_model_file_struct *p_model_file;
473 sar_parm_range_struct *p_range;
474 sar_parm_range_far_struct *p_range_far;
475 sar_parm_translate_struct *p_translate;
476 sar_parm_translate_random_struct *p_translate_random;
477 sar_parm_rotate_struct *p_rotate;
478 sar_parm_no_depth_test_struct *p_no_depth_test;
479 sar_parm_polygon_offset_struct *p_polygon_offset;
480 sar_parm_contact_bounds_spherical_struct *p_contact_bounds_spherical;
481 sar_parm_contact_bounds_cylendrical_struct *p_contact_bounds_cylendrical;
482 sar_parm_contact_bounds_rectangular_struct *p_contact_bounds_rectangular;
483 sar_parm_ground_elevation_struct *p_ground_elevation;
484 sar_parm_object_name_struct *p_object_name;
485 sar_parm_object_map_description_struct *p_object_map_description;
486 sar_parm_fuel_struct *p_fuel;
487 sar_parm_hitpoints_struct *p_hitpoints;
488 sar_parm_engine_state_struct *p_engine_state;
489 sar_parm_passengers_struct *p_passengers;
490 sar_parm_runway_approach_lighting_north_struct *p_runway_applight_n;
491 sar_parm_runway_approach_lighting_south_struct *p_runway_applight_s;
492 sar_parm_human_message_enter_struct *p_human_message_enter;
493 sar_parm_human_reference_struct *p_human_reference;
494
495
496 /* Resets object substructure pointers to NULL */
497 #define DO_RESET_SUBSTRUCTURE_PTRS { \
498 obj_aircraft_ptr = NULL; \
499 obj_ground_ptr = NULL; \
500 obj_helipad_ptr = NULL; \
501 obj_runway_ptr = NULL; \
502 obj_human_ptr = NULL; \
503 obj_smoke_ptr = NULL; \
504 obj_fire_ptr = NULL; \
505 }
506
507
508 if((core_ptr == NULL) || (scene == NULL) || (filename == NULL))
509 return(-1);
510
511 display = core_ptr->display;
512
513 ptr = &core_ptr->object;
514 total = &core_ptr->total_objects;
515
516 /* Check if the file exists and get its stats */
517 if(stat(filename, &stat_buf))
518 {
519 char *s = STRDUP(strerror(errno));
520 if(s == NULL)
521 s = STRDUP("no such file");
522 *s = toupper(*s);
523 fprintf(
524 stderr,
525 "%s: %s.\n",
526 filename, s
527 );
528 free(s);
529 return(-1);
530 }
531
532 /* Load all parameters from file */
533 status = SARParmLoadFromFile(
534 filename, SAR_FILE_FORMAT_SCENE,
535 &parm, &total_parms,
536 -1, /* No filter */
537 NULL, NULL
538 );
539 if(status)
540 {
541 fprintf(
542 stderr,
543 "%s: Error loading scene.\n",
544 filename
545 );
546 return(-1);
547 }
548
549
550 /* Delete the specified Scene and all its objects */
551 SARSceneDestroy(core_ptr, scene, ptr, total);
552
553
554 /* Reset Scene values */
555 scene->tod = (12 * 3600); /* Noon */
556 scene->tod_code = SAR_TOD_CODE_DAY;
557 scene->cant_angle = (float)(0.0 * PI);
558 scene->base_flags = 0;
559 scene->msl_elevation = 0.0f;
560
561 scene->dms_x_offset = 0;
562 scene->dms_y_offset = 0;
563 scene->planet_radius = SAR_DEF_PLANET_RADIUS;
564
565 scene->visual_model = NULL;
566 scene->total_visual_models = 0;
567
568 c = &scene->sky_nominal_color;
569 c->a = 1.0f;
570 c->r = 1.0f;
571 c->g = 1.0f;
572 c->b = 1.0f;
573 c = &scene->sky_brighten_color;
574 c->a = 1.0f;
575 c->r = 1.0f;
576 c->g = 1.0f;
577 c->b = 1.0f;
578 c = &scene->sky_darken_color;
579 c->a = 1.0f;
580 c->r = 1.0f;
581 c->g = 1.0f;
582 c->b = 1.0f;
583
584 c = &scene->star_low_color;
585 c->a = 1.0f;
586 c->r = 1.0f;
587 c->g = 1.0f;
588 c->b = 1.0f;
589 c = &scene->star_high_color;
590 c->a = 1.0f;
591 c->r = 1.0f;
592 c->g = 1.0f;
593 c->b = 1.0f;
594
595 c = &scene->sun_low_color;
596 c->a = 1.0f;
597 c->r = 1.0f;
598 c->g = 1.0f;
599 c->b = 1.0f;
600 c = &scene->sun_high_color;
601 c->a = 1.0f;
602 c->r = 1.0f;
603 c->g = 1.0f;
604 c->b = 1.0f;
605
606 c = &scene->moon_low_color;
607 c->a = 1.0f;
608 c->r = 1.0f;
609 c->g = 1.0f;
610 c->b = 1.0f;
611 c = &scene->moon_high_color;
612 c->a = 1.0f;
613 c->r = 1.0f;
614 c->g = 1.0f;
615 c->b = 1.0f;
616
617 scene->moon_visibility_hint = 0;
618 scene->rain_density_coeff = 0.0f;
619
620 scene->player_obj_num = -1;
621 scene->player_obj_ptr = NULL;
622 scene->player_has_crashed = False;
623
624 scene->ground_object = NULL;
625 scene->total_ground_objects = 0;
626
627 scene->human_need_rescue_object = NULL;
628 scene->total_human_need_rescue_objects = 0;
629
630 scene->camera_ref = SAR_CAMERA_REF_COCKPIT;
631 scene->camera_fovz = (float)SFMDegreesToRadians(40.0);
632 dir = &scene->camera_cockpit_dir;
633 dir->heading = (float)(0.0f * PI);
634 dir->pitch = (float)(0.0f * PI);
635 dir->bank = (float)(0.0f * PI);
636 dir = &scene->camera_spot_dir;
637 dir->heading = (float)(1.25f * PI);
638 dir->pitch = (float)(1.92f * PI);
639 dir->bank = (float)(0.0f * PI);
640 scene->camera_spot_dist = 20.0f;
641 dir = &scene->camera_hoist_dir;
642 dir->heading = (float)(0.75f * PI);
643 dir->pitch = (float)(1.92f * PI);
644 dir->bank = (float)(0.0f * PI);
645 scene->camera_hoist_dist = 20.0f;
646 scene->camera_target = -1;
647
648 memset(
649 scene->camera_rotmatrix,
650 0x00,
651 SAR_CAMERA_ROTMATRIX_MAX * (3 * 3) * sizeof(double)
652 );
653 scene->camera_rotmatrix_count = 0;
654
655 scene->light_visibility_hint = 0;
656 scene->light_xc = -2.0f; /* Not in camera view */
657 scene->light_yc = -2.0f;
658
659 scene->cloud_layer = NULL;
660 scene->total_cloud_layers = 0;
661
662 scene->cloud_bb = NULL;
663 scene->total_cloud_bbs = 0;
664 scene->pri_lightening_coeff = 0.0f;
665
666 scene->texture_ref = NULL;
667 scene->total_texture_refs = 0;
668
669 scene->texnum_sun = -1;
670 scene->texnum_moon = -1;
671 scene->texnum_spotlightcast = -1;
672
673 scene->sndsrc = NULL;
674 scene->total_sndsrcs = 0;
675
676 scene->player_control_panel = NULL;
677
678 /* Reset initial GL states */
679 if(display != NULL)
680 {
681 StateGLResetAll(&display->state_gl);
682 StateGLEnable(&display->state_gl, GL_CULL_FACE);
683 StateGLFrontFace(&display->state_gl, GL_CCW);
684 StateGLShadeModel(&display->state_gl, GL_FLAT);
685 }
686 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
687 glPixelStorei(GL_PACK_ALIGNMENT, 1);
688
689
690 /* Allocate the Messages List */
691 scene->total_messages = 6; /* Maximum of 6 at one time */
692 free(scene->message);
693 scene->message = (char **)calloc(
694 scene->total_messages, sizeof(char *)
695 );
696 if(scene->message == NULL)
697 scene->total_messages = 0;
698
699 scene->message_display_until = 0;
700 scene->camera_ref_title_display_until = 0;
701
702 /* Allocate the FDM Realm */
703 scene->realm = SFMInit(0, NULL);
704 if(scene->realm == NULL)
705 {
706 fprintf(
707 stderr,
708 "SARSceneLoadFromFile(): Error: Unable to create FDM Realm.\n"
709 );
710 }
711 else
712 {
713 SFMRealmStruct *realm = scene->realm;
714
715 /* Set up FDM realm values */
716 realm->lapsed_time = 0;
717 realm->time_compensation = 1.0f;
718 realm->time_compression = 1.0f;
719
720 realm->gravity = SFMDefaultGravity;
721
722 /* Set up realm callback data and callback function ptrs */
723 realm->init_model_cb_client_data = core_ptr;
724 realm->init_model_cb = SARSimInitModelCB;
725 realm->destroy_model_cb_client_data = core_ptr;
726 realm->destroy_model_cb = SARSimDestroyModelCB;
727 realm->airborne_cb_client_data = core_ptr;
728 realm->airborne_cb = SARSimAirborneCB;
729 realm->touch_down_cb_client_data = core_ptr;
730 realm->touch_down_cb = SARSimTouchDownCB;
731 realm->overspeed_cb_client_data = core_ptr;
732 realm->overspeed_cb = SARSimOverspeedCB;
733 realm->collision_cb_client_data = core_ptr;
734 realm->collision_cb = SARSimCollisionCB;
735 }
736
737 #define APPEND_TEXTURE(_t_) { \
738 const int n = MAX(scene->total_texture_refs, 0); \
739 scene->total_texture_refs = n + 1; \
740 scene->texture_ref = (v3d_texture_ref_struct **)realloc( \
741 scene->texture_ref, \
742 scene->total_texture_refs * sizeof(v3d_texture_ref_struct *) \
743 ); \
744 if(scene->texture_ref == NULL) { \
745 scene->total_texture_refs = 0; \
746 return(-3); \
747 } \
748 scene->texture_ref[n] = (_t_); \
749 }
750
751 /* Render built in textures */
752 if(True)
753 {
754 #if 0
755 v3d_texture_ref_struct *t = SARCreateBladeBlurTexture(
756 SAR_STD_TEXNAME_ROTOR_BLADE_BLUR, 0.98f
757 );
758 APPEND_TEXTURE(t);
759 #endif
760 }
761
762
763 /* Load all textures specified in the global Textures List */
764 if(True)
765 {
766 const char *name, *path;
767 char *full_path;
768 const sar_texture_name_struct *tn;
769 const int tex_fmt = V3D_TEX_FORMAT_RGBA;
770
771 /* Iterate through each Texture Name in the Textures List */
772 for(i = 0; i < core_ptr->total_texture_list; i++)
773 {
774 tn = core_ptr->texture_list[i];
775 if(tn == NULL)
776 continue;
777
778 name = tn->name;
779 path = tn->filename;
780 if((name == NULL) || (path == NULL))
781 continue;
782
783 if(ISPATHABSOLUTE(path))
784 {
785 full_path = STRDUP(path);
786 }
787 else
788 {
789 full_path = STRDUP(PrefixPaths(
790 dname.local_data, path
791 ));
792 if((full_path != NULL) ? stat(full_path, &stat_buf) : True)
793 {
794 free(full_path);
795 full_path = STRDUP(PrefixPaths(
796 dname.global_data, path
797 ));
798 }
799 }
800 if(full_path != NULL)
801 {
802 v3d_texture_ref_struct *t = V3DTextureLoadFromFile2DPreempt(
803 full_path, name, tex_fmt
804 );
805 V3DTexturePriority(t, tn->priority);
806 APPEND_TEXTURE(t);
807 free(full_path);
808 }
809 else
810 {
811 fprintf(
812 stderr,
813 "%s: Warning: Unable to complete texture \"%s\" path \"%s\".\n",
814 filename, name, path
815 );
816 }
817 }
818 }
819
820 /* Set references to frequently used global textures */
821 if(True)
822 {
823 scene->texnum_sun = SARGetTextureRefNumberByName(
824 scene, SAR_STD_TEXNAME_SUN
825 );
826 scene->texnum_moon = SARGetTextureRefNumberByName(
827 scene, SAR_STD_TEXNAME_MOON
828 );
829 scene->texnum_spotlightcast = SARGetTextureRefNumberByName(
830 scene, SAR_STD_TEXNAME_SPOTLIGHTCAST
831 );
832
833 }
834
835 #undef APPEND_TEXTURE
836
837 /* Create default global sound sources list */
838 if(True)
839 {
840 #define LOAD_SNDSRC(name,filename,filename_far,range,range_far) \
841 { \
842 i = MAX(scene->total_sndsrcs, 0); \
843 scene->total_sndsrcs = i + 1; \
844 scene->sndsrc = (sar_sound_source_struct **)realloc( \
845 scene->sndsrc, \
846 scene->total_sndsrcs * sizeof(sar_sound_source_struct *) \
847 ); \
848 if(scene->sndsrc == NULL) \
849 { \
850 scene->total_sndsrcs = 0; \
851 } \
852 else \
853 { \
854 char *s, *full_path, *full_path_far; \
855 \
856 /* Complete Filenames */ \
857 s = STRDUP(PrefixPaths(dname.local_data, filename)); \
858 if((s != NULL) ? stat(s, &stat_buf) : True) { \
859 free(s); \
860 s = STRDUP(PrefixPaths(dname.global_data, filename)); \
861 } \
862 full_path = s; \
863 \
864 s = STRDUP(PrefixPaths(dname.local_data, filename_far)); \
865 if((s != NULL) ? stat(s, &stat_buf) : True) { \
866 free(s); \
867 s = STRDUP(PrefixPaths(dname.global_data, filename_far)); \
868 } \
869 full_path_far = s; \
870 \
871 /* Check if file exists */ \
872 if((full_path != NULL) ? stat(full_path, &stat_buf) : True) \
873 fprintf(stderr, \
874 "SARSceneLoadFromFile(): Warning: Unable to find sound file \"%s\"\n",\
875 filename \
876 ); \
877 if((full_path_far != NULL) ? stat(full_path_far, &stat_buf) : True) \
878 fprintf(stderr, \
879 "SARSceneLoadFromFile(): Warning: Unable to find sound file \"%s\"\n",\
880 filename_far \
881 ); \
882 \
883 /* Create sound source */ \
884 scene->sndsrc[i] = SARSoundSourceNew( \
885 name, full_path, full_path_far, \
886 range, range_far, \
887 NULL, 0.0f, NULL, \
888 0 /* Sample rate limit in Hz */ \
889 ); \
890 \
891 free(full_path); \
892 free(full_path_far); \
893 } \
894 }
895
896 /* Gound Contact Sounds */
897 LOAD_SNDSRC(
898 "land_wheel_skid",
899 SAR_DEF_SOUND_LAND_WHEEL_SKID,
900 SAR_DEF_SOUND_LAND_WHEEL_SKID,
901 600.0f,
902 400.0f
903 );
904 LOAD_SNDSRC(
905 "land_ski_skid",
906 SAR_DEF_SOUND_LAND_SKI_SKID,
907 SAR_DEF_SOUND_LAND_SKI_SKID,
908 600.0f,
909 400.0f
910 );
911 LOAD_SNDSRC(
912 "land_ski",
913 SAR_DEF_SOUND_LAND_SKI,
914 SAR_DEF_SOUND_LAND_SKI,
915 600.0f,
916 400.0f
917 );
918 LOAD_SNDSRC(
919 "land_belly",
920 SAR_DEF_SOUND_LAND_BELLY,
921 SAR_DEF_SOUND_LAND_BELLY,
922 1200.0f,
923 900.0f
924 );
925
926 /* Thud Sounds */
927 LOAD_SNDSRC(
928 "thud_light",
929 SAR_DEF_SOUND_THUD_LIGHT,
930 SAR_DEF_SOUND_THUD_LIGHT,
931 600.0f,
932 400.0f
933 );
934 LOAD_SNDSRC(
935 "thud_medium",
936 SAR_DEF_SOUND_THUD_MEDIUM,
937 SAR_DEF_SOUND_THUD_MEDIUM,
938 600.0f,
939 400.0f
940 );
941 LOAD_SNDSRC(
942 "thud_heavy",
943 SAR_DEF_SOUND_THUD_HEAVY,
944 SAR_DEF_SOUND_THUD_HEAVY,
945 600.0f,
946 400.0f
947 );
948
949 /* Crash & Collision Sounds */
950 LOAD_SNDSRC(
951 "crash_obstruction",
952 SAR_DEF_SOUND_CRASH_OBSTRUCTION,
953 SAR_DEF_SOUND_CRASH_OBSTRUCTION,
954 3300.0f, /* About 2 miles */
955 2500.0f
956 );
957 LOAD_SNDSRC(
958 "crash_ground",
959 SAR_DEF_SOUND_CRASH_GROUND,
960 SAR_DEF_SOUND_CRASH_GROUND,
961 3300.0f, /* About 2 miles */
962 2500.0f
963 );
964 LOAD_SNDSRC(
965 "splash_aircraft",
966 SAR_DEF_SOUND_SPLASH_AIRCRAFT,
967 SAR_DEF_SOUND_SPLASH_AIRCRAFT,
968 2500.0f, /* About 1.5 miles */
969 2000.0f
970 );
971 LOAD_SNDSRC(
972 "splash_human",
973 SAR_DEF_SOUND_SPLASH_HUMAN,
974 SAR_DEF_SOUND_SPLASH_HUMAN,
975 600.0f,
976 400.0f
977 );
978
979 #undef LOAD_SNDSRC
980 }
981
982 /* Create the Horizon */
983 horizon_ptr = &scene->horizon;
984 horizon_ptr->last_tod = -1; /* Reset to -1 so horizon gets updated */
985 horizon_ptr->texture = NULL;
986 horizon_ptr->total_textures = 0;
987
988
989 /* Generate weather settings from the specified Weather Data
990 * Entry
991 */
992 SARWeatherSetScenePreset(
993 core_ptr->weather_data,
994 scene,
995 weather_preset_name
996 );
997
998 /* Iterate through loaded parms */
999 for(i = 0; i < total_parms; i++)
1000 {
1001 p = parm[i];
1002 if(p == NULL)
1003 continue;
1004
1005 ptype = *(int *)p;
1006
1007 if(progress_func != NULL)
1008 {
1009 if(progress_func(client_data, i + 1, total_parms))
1010 break;
1011 }
1012
1013 /* Handle by parm type */
1014 switch(ptype)
1015 {
1016 case SAR_PARM_VERSION:
1017 p_version = (sar_parm_version_struct *)p;
1018 if((p_version->major > PROG_VERSION_MAJOR) ||
1019 (p_version->minor > PROG_VERSION_MINOR) ||
1020 (p_version->release > PROG_VERSION_RELEASE)
1021 )
1022 {
1023 int need_warn = 0;
1024 if(p_version->major > PROG_VERSION_MAJOR)
1025 need_warn = 1;
1026 else if((p_version->major == PROG_VERSION_MAJOR) &&
1027 (p_version->minor > PROG_VERSION_MINOR)
1028 )
1029 need_warn = 1;
1030 else if((p_version->major == PROG_VERSION_MAJOR) &&
1031 (p_version->minor == PROG_VERSION_MINOR) &&
1032 (p_version->release == PROG_VERSION_RELEASE)
1033 )
1034 need_warn = 1;
1035 if(need_warn)
1036 fprintf(
1037 stderr,
1038 "%s: Warning: File format version %i.%i.%i is newer than program\
1039 version %i.%i.%i.",
1040 filename,
1041 p_version->major, p_version->minor,
1042 p_version->release, PROG_VERSION_MAJOR,
1043 PROG_VERSION_MINOR, PROG_VERSION_RELEASE
1044 );
1045 }
1046 break;
1047
1048 case SAR_PARM_NAME:
1049 p_name = (sar_parm_name_struct *)p;
1050 free(scene->title);
1051 scene->title = STRDUP(p_name->name);
1052 break;
1053
1054 case SAR_PARM_DESCRIPTION:
1055 p_description = (sar_parm_description_struct *)p;
1056 break;
1057
1058 case SAR_PARM_PLAYER_MODEL_FILE:
1059 p_player_model_file = (sar_parm_player_model_file_struct *)p;
1060 break;
1061
1062 case SAR_PARM_WEATHER:
1063 p_weather = (sar_parm_weather_struct *)p;
1064 break;
1065
1066 case SAR_PARM_REGISTER_LOCATION:
1067 p_register_location = (sar_parm_register_location_struct *)p;
1068 break;
1069
1070 case SAR_PARM_SCENE_GPS:
1071 p_scene_gps = (sar_parm_scene_gps_struct *)p;
1072 scene->dms_x_offset = p_scene_gps->dms_x_offset;
1073 scene->dms_y_offset = p_scene_gps->dms_y_offset;
1074 scene->planet_radius = p_scene_gps->planet_radius;
1075 break;
1076
1077 case SAR_PARM_SCENE_MAP:
1078 p_scene_map = (sar_parm_scene_map_struct *)p;
1079 break;
1080
1081 case SAR_PARM_SCENE_ELEVATION:
1082 p_scene_elevation = (sar_parm_scene_elevation_struct *)p;
1083 scene->msl_elevation = p_scene_elevation->elevation;
1084 break;
1085
1086 case SAR_PARM_SCENE_CANT:
1087 p_scene_cant = (sar_parm_scene_cant_struct *)p;
1088 scene->cant_angle = p_scene_cant->cant;
1089 break;
1090
1091 case SAR_PARM_SCENE_GROUND_FLAGS:
1092 p_scene_ground_flags = (sar_parm_scene_ground_flags_struct *)p;
1093 scene->base_flags = (sar_scene_base_flags)p_scene_ground_flags->flags;
1094 break;
1095
1096 case SAR_PARM_SCENE_GROUND_TILE:
1097 p_scene_ground_tile = (sar_parm_scene_ground_tile_struct *)p;
1098 if(True)
1099 {
1100 float min, max;
1101 GLuint list;
1102 sar_visual_model_struct **vmodel;
1103 v3d_texture_ref_struct *t = NULL;
1104
1105 /* Close range tiling size and range */
1106 scene->base.tile_width = ((p_scene_ground_tile->tile_width > 0) ?
1107 p_scene_ground_tile->tile_width : SAR_DEF_GROUND_BASE_TILE_WIDTH
1108 );
1109 scene->base.tile_height = ((p_scene_ground_tile->tile_height > 0) ?
1110 p_scene_ground_tile->tile_height : SAR_DEF_GROUND_BASE_TILE_HEIGHT
1111 );
1112 scene->base.close_range = ((p_scene_ground_tile->close_range > 0) ?
1113 p_scene_ground_tile->close_range : SAR_DEF_GROUND_BASE_TILE_CLOSE_RANGE
1114 );
1115 /* Far solid color */
1116 memcpy(
1117 &scene->base.color, &p_scene_ground_tile->color,
1118 sizeof(sar_color_struct)
1119 );
1120
1121 /* Select texture */
1122 t = SARGetTextureRefByName(scene, p_scene_ground_tile->texture_name);
1123
1124 /* Create the simple/far Ground Base Visual Model
1125 * as needed
1126 */
1127 vmodel = &scene->base.visual_model_simple;
1128 if(*vmodel != NULL)
1129 {
1130 fprintf(
1131 stderr,
1132 "%s: Warning: Ground base simple/far visual model is already defined.\n",
1133 filename
1134 );
1135 }
1136 else
1137 {
1138 /* Create new visual model */
1139 *vmodel = SARVisualModelNew(
1140 scene, NULL, NULL
1141 );
1142
1143 /* (Re)generate GL list on visual model structure */
1144 list = (GLuint)SARVisualModelNewList(*vmodel);
1145 if(list != 0)
1146 {
1147 /* Mark visual model as loading */
1148 (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADING;
1149
1150 /* Begin recording new list */
1151 glNewList(list, GL_COMPILE);
1152 {
1153 /* Far (big) ground base tiles */
1154 min = -(SAR_MAX_VISIBILITY_DISTANCE +
1155 (0.25 * SAR_MAX_VISIBILITY_DISTANCE));
1156 max = (SAR_MAX_VISIBILITY_DISTANCE +
1157 (0.25 * SAR_MAX_VISIBILITY_DISTANCE));
1158 SARObjGenerateTilePlane(
1159 min, max, /* Min and max */
1160 (float)(max / 4), /* Tile width and height */
1161 (float)(max / 4)
1162 );
1163 }
1164 glEndList();
1165
1166 /* Mark visual model as done loading */
1167 (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADED;
1168 }
1169 }
1170
1171 /* Create the detailed/near Ground Base Visual Model
1172 * as needed
1173 */
1174 vmodel = &scene->base.visual_model_close;
1175 if(*vmodel != NULL)
1176 {
1177 fprintf(
1178 stderr,
1179 "%s: Warning: Ground base detailed/near visual model is already defined.\n",
1180 filename
1181 );
1182 }
1183 else
1184 {
1185 /* Create new visual model */
1186 *vmodel = SARVisualModelNew(
1187 scene, NULL, NULL
1188 );
1189
1190 /* (Re)generate GL list on visual model structure */
1191 list = (GLuint)SARVisualModelNewList(*vmodel);
1192 if(list != 0)
1193 {
1194 /* Mark visual model as loading */
1195 (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADING;
1196
1197 /* Begin recording new list */
1198 glNewList(list, GL_COMPILE);
1199 {
1200 /* Select tiled ground texture if defined, if
1201 * no texture then a texture unselect will be
1202 * recorded.
1203 */
1204 V3DTextureSelect(t);
1205
1206 /* Generate close range textured tiles */
1207 SARObjGenerateTilePlane(
1208 -scene->base.close_range, /* Min */
1209 scene->base.close_range, /* Max */
1210 (float)scene->base.tile_width, /* Tile width */
1211 (float)scene->base.tile_height /* Tile height */
1212 );
1213 }
1214 glEndList();
1215
1216 /* Mark visual model as done loading */
1217 (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADED;
1218 }
1219 }
1220 }
1221 break;
1222
1223 case SAR_PARM_TEXTURE_BASE_DIRECTORY:
1224 p_texture_base_directory = (sar_parm_texture_base_directory_struct *)p;
1225 break;
1226
1227 case SAR_PARM_TEXTURE_LOAD:
1228 p_texture_load = (sar_parm_texture_load_struct *)p;
1229 SARObjLoadTexture(
1230 core_ptr, scene, p_texture_load
1231 );
1232 break;
1233
1234 /* Skip mission parms */
1235
1236 case SAR_PARM_NEW_OBJECT:
1237 p_new_object = (sar_parm_new_object_struct *)p;
1238 obj_num = SARObjNew(
1239 scene, ptr, total,
1240 p_new_object->object_type
1241 );
1242 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1243
1244 /* Reset all substructure type pointers */
1245 DO_RESET_SUBSTRUCTURE_PTRS
1246
1247 if(obj_ptr != NULL)
1248 {
1249 /* Get pointer to substructure */
1250 switch(obj_ptr->type)
1251 {
1252 case SAR_OBJ_TYPE_GARBAGE:
1253 case SAR_OBJ_TYPE_STATIC:
1254 case SAR_OBJ_TYPE_AUTOMOBILE:
1255 case SAR_OBJ_TYPE_WATERCRAFT:
1256 break;
1257 case SAR_OBJ_TYPE_AIRCRAFT:
1258 obj_aircraft_ptr = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
1259 break;
1260 case SAR_OBJ_TYPE_GROUND:
1261 obj_ground_ptr = SAR_OBJ_GET_GROUND(obj_ptr);
1262 break;
1263 case SAR_OBJ_TYPE_RUNWAY:
1264 case SAR_OBJ_TYPE_HELIPAD:
1265 case SAR_OBJ_TYPE_HUMAN:
1266 case SAR_OBJ_TYPE_SMOKE:
1267 case SAR_OBJ_TYPE_FIRE:
1268 case SAR_OBJ_TYPE_EXPLOSION:
1269 case SAR_OBJ_TYPE_CHEMICAL_SPRAY:
1270 case SAR_OBJ_TYPE_FUELTANK:
1271 case SAR_OBJ_TYPE_PREMODELED:
1272 break;
1273 }
1274 }
1275 break;
1276
1277 case SAR_PARM_NEW_HELIPAD:
1278 p_new_helipad = (sar_parm_new_helipad_struct *)p;
1279 DO_RESET_SUBSTRUCTURE_PTRS
1280 obj_num = SARObjLoadHelipad(
1281 core_ptr, scene, p_new_helipad
1282 );
1283 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1284 obj_helipad_ptr = SAR_OBJ_GET_HELIPAD(obj_ptr);
1285 break;
1286
1287 case SAR_PARM_NEW_RUNWAY:
1288 p_new_runway = (sar_parm_new_runway_struct *)p;
1289 DO_RESET_SUBSTRUCTURE_PTRS
1290 obj_num = SARObjLoadRunway(
1291 core_ptr, scene, p_new_runway
1292 );
1293 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1294 obj_runway_ptr = SAR_OBJ_GET_RUNWAY(obj_ptr);
1295 break;
1296
1297 case SAR_PARM_NEW_HUMAN:
1298 p_new_human = (sar_parm_new_human_struct *)p;
1299 DO_RESET_SUBSTRUCTURE_PTRS
1300 obj_num = SARObjLoadHuman(
1301 core_ptr, scene, p_new_human
1302 );
1303 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1304 obj_human_ptr = SAR_OBJ_GET_HUMAN(obj_ptr);
1305 break;
1306
1307 case SAR_PARM_NEW_FIRE:
1308 p_new_fire = (sar_parm_new_fire_struct *)p;
1309 DO_RESET_SUBSTRUCTURE_PTRS
1310 obj_num = SARObjLoadFire(
1311 core_ptr, scene, p_new_fire
1312 );
1313 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1314 obj_fire_ptr = SAR_OBJ_GET_FIRE(obj_ptr);
1315 break;
1316
1317 case SAR_PARM_NEW_SMOKE:
1318 p_new_smoke = (sar_parm_new_smoke_struct *)p;
1319 DO_RESET_SUBSTRUCTURE_PTRS
1320 obj_num = SARObjLoadSmoke(
1321 core_ptr, scene, p_new_smoke
1322 );
1323 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1324 obj_smoke_ptr = SAR_OBJ_GET_SMOKE(obj_ptr);
1325 break;
1326
1327 case SAR_PARM_NEW_PREMODELED:
1328 p_new_premodeled = (sar_parm_new_premodeled_struct *)p;
1329 DO_RESET_SUBSTRUCTURE_PTRS
1330 obj_num = SARObjPremodeledNew(
1331 core_ptr, scene,
1332 p_new_premodeled->model_type,
1333 p_new_premodeled->argc,
1334 p_new_premodeled->argv
1335 );
1336 obj_ptr = (obj_num > -1) ? (*ptr)[obj_num] : NULL;
1337 break;
1338
1339 case SAR_PARM_MODEL_FILE:
1340 p_model_file = (sar_parm_model_file_struct *)p;
1341 if((p_model_file->file != NULL) && (obj_ptr != NULL))
1342 SARObjLoadFromFile(core_ptr, obj_num, p_model_file->file);
1343 break;
1344
1345 case SAR_PARM_RANGE:
1346 p_range = (sar_parm_range_struct *)p;
1347 if(obj_ptr != NULL)
1348 {
1349 obj_ptr->range = (float)MAX(p_range->range, 0.0);
1350 }
1351 break;
1352
1353 case SAR_PARM_RANGE_FAR:
1354 p_range_far = (sar_parm_range_far_struct *)p;
1355 if(obj_ptr != NULL)
1356 {
1357 obj_ptr->range_far = (float)MAX(p_range_far->range_far, 0.0);
1358 }
1359 break;
1360
1361 case SAR_PARM_TRANSLATE:
1362 p_translate = (sar_parm_translate_struct *)p;
1363 SARObjLoadTranslate(
1364 core_ptr, scene,
1365 obj_ptr, p_translate
1366 );
1367 break;
1368
1369 case SAR_PARM_TRANSLATE_RANDOM:
1370 p_translate_random = (sar_parm_translate_random_struct *)p;
1371 /* Ignore this, for missions only) */
1372 break;
1373
1374 case SAR_PARM_ROTATE:
1375 p_rotate = (sar_parm_rotate_struct *)p;
1376 if(obj_ptr != NULL)
1377 {
1378 SARSimWarpObject(
1379 scene, obj_ptr,
1380 NULL, &p_rotate->rotate
1381 );
1382 }
1383 break;
1384
1385 case SAR_PARM_NO_DEPTH_TEST:
1386 p_no_depth_test = (sar_parm_no_depth_test_struct *)p;
1387 if(obj_ptr != NULL)
1388 {
1389 obj_ptr->flags |= SAR_OBJ_FLAG_NO_DEPTH_TEST;
1390 }
1391 break;
1392
1393 case SAR_PARM_POLYGON_OFFSET:
1394 p_polygon_offset = (sar_parm_polygon_offset_struct *)p;
1395 if(obj_ptr != NULL)
1396 {
1397 obj_ptr->flags |= p_polygon_offset->flags;
1398 }
1399 break;
1400
1401 case SAR_PARM_CONTACT_BOUNDS_SPHERICAL:
1402 p_contact_bounds_spherical = (sar_parm_contact_bounds_spherical_struct *)p;
1403 if(obj_ptr != NULL)
1404 {
1405 sar_contact_bounds_struct *cb = obj_ptr->contact_bounds;
1406 SARObjAddContactBoundsSpherical(
1407 obj_ptr,
1408 (cb != NULL) ? cb->crash_flags : 0,
1409 (cb != NULL) ? cb->crash_type : 0,
1410 p_contact_bounds_spherical->radius
1411 );
1412 }
1413 break;
1414
1415 case SAR_PARM_CONTACT_BOUNDS_CYLENDRICAL:
1416 p_contact_bounds_cylendrical = (sar_parm_contact_bounds_cylendrical_struct *)p;
1417 if(obj_ptr != NULL)
1418 {
1419 sar_contact_bounds_struct *cb = obj_ptr->contact_bounds;
1420 SARObjAddContactBoundsCylendrical(
1421 obj_ptr,
1422 (cb != NULL) ? cb->crash_flags : 0,
1423 (cb != NULL) ? cb->crash_type : 0,
1424 p_contact_bounds_cylendrical->radius,
1425 p_contact_bounds_cylendrical->height_min,
1426 p_contact_bounds_cylendrical->height_max
1427 );
1428 }
1429 break;
1430
1431 case SAR_PARM_CONTACT_BOUNDS_RECTANGULAR:
1432 p_contact_bounds_rectangular = (sar_parm_contact_bounds_rectangular_struct *)p;
1433 if(obj_ptr != NULL)
1434 {
1435 sar_contact_bounds_struct *cb = obj_ptr->contact_bounds;
1436 SARObjAddContactBoundsRectangular(
1437 obj_ptr,
1438 (cb != NULL) ? cb->crash_flags : 0,
1439 (cb != NULL) ? cb->crash_type : 0,
1440 p_contact_bounds_rectangular->x_min,
1441 p_contact_bounds_rectangular->x_max,
1442 p_contact_bounds_rectangular->y_min,
1443 p_contact_bounds_rectangular->y_max,
1444 p_contact_bounds_rectangular->z_min,
1445 p_contact_bounds_rectangular->z_max
1446 );
1447 }
1448 break;
1449
1450 case SAR_PARM_GROUND_ELEVATION:
1451 p_ground_elevation = (sar_parm_ground_elevation_struct *)p;
1452 if(obj_ground_ptr != NULL)
1453 {
1454 obj_ground_ptr->elevation = p_ground_elevation->elevation;
1455 }
1456 else
1457 {
1458 fprintf(
1459 stderr,
1460 "%s: Warning:\
1461 Unable to set ground elevation for object not of type \"%i\".\n",
1462 filename, SAR_OBJ_TYPE_GROUND
1463 );
1464 }
1465 break;
1466
1467 case SAR_PARM_OBJECT_NAME:
1468 p_object_name = (sar_parm_object_name_struct *)p;
1469 if(obj_ptr != NULL)
1470 {
1471 free(obj_ptr->name);
1472 obj_ptr->name = STRDUP(p_object_name->name);
1473 }
1474 break;
1475
1476 case SAR_PARM_OBJECT_MAP_DESCRIPTION:
1477 p_object_map_description = (sar_parm_object_map_description_struct *)p;
1478 if(obj_ptr != NULL)
1479 {
1480 /* Ignore this */
1481 }
1482 break;
1483
1484 case SAR_PARM_FUEL:
1485 p_fuel = (sar_parm_fuel_struct *)p;
1486 if(obj_aircraft_ptr != NULL)
1487 {
1488 /* Set current fuel */
1489 obj_aircraft_ptr->fuel = p_fuel->fuel;
1490
1491 /* Set max only if not negative */
1492 if(p_fuel->fuel_max >= 0.0)
1493 obj_aircraft_ptr->fuel_max = p_fuel->fuel_max;
1494
1495 /* Sanitize current */
1496 if(obj_aircraft_ptr->fuel > obj_aircraft_ptr->fuel_max)
1497 obj_aircraft_ptr->fuel = obj_aircraft_ptr->fuel_max;
1498 }
1499 break;
1500
1501 case SAR_PARM_HITPOINTS:
1502 p_hitpoints = (sar_parm_hitpoints_struct *)p;
1503 if(obj_ptr != NULL)
1504 {
1505 /* Set current hit points */
1506 obj_ptr->hit_points = p_hitpoints->hitpoints;
1507
1508 /* Set max only if not negative */
1509 if(p_hitpoints->hitpoints_max >= 0.0)
1510 obj_ptr->hit_points_max = p_hitpoints->hitpoints_max;
1511
1512 /* Sanitize current */
1513 if(obj_ptr->hit_points > obj_ptr->hit_points_max)
1514 obj_ptr->hit_points = obj_ptr->hit_points_max;
1515 }
1516 break;
1517
1518 case SAR_PARM_ENGINE_STATE:
1519 p_engine_state = (sar_parm_engine_state_struct *)p;
1520 /* TODO Work on this later */
1521 break;
1522
1523 case SAR_PARM_PASSENGERS:
1524 p_passengers = (sar_parm_passengers_struct *)p;
1525 /* TODO Work on this later */
1526 break;
1527
1528 case SAR_PARM_RUNWAY_APPROACH_LIGHTING_NORTH:
1529 p_runway_applight_n =
1530 (sar_parm_runway_approach_lighting_north_struct *)p;
1531 if((obj_ptr != NULL) && (obj_runway_ptr != NULL))
1532 {
1533 obj_runway_ptr->north_approach_lighting_flags =
1534 p_runway_applight_n->flags;
1535 }
1536 break;
1537
1538 case SAR_PARM_RUNWAY_APPROACH_LIGHTING_SOUTH:
1539 p_runway_applight_s =
1540 (sar_parm_runway_approach_lighting_south_struct *)p;
1541 if((obj_ptr != NULL) && (obj_runway_ptr != NULL))
1542 {
1543 obj_runway_ptr->south_approach_lighting_flags =
1544 p_runway_applight_s->flags;
1545 }
1546 break;
1547
1548 case SAR_PARM_HUMAN_MESSAGE_ENTER:
1549 p_human_message_enter = (sar_parm_human_message_enter_struct *)p;
1550 if((obj_ptr != NULL) && (obj_human_ptr != NULL))
1551 {
1552 free(obj_human_ptr->mesg_enter);
1553 obj_human_ptr->mesg_enter = STRDUP(
1554 p_human_message_enter->message
1555 );
1556 }
1557 break;
1558
1559 case SAR_PARM_HUMAN_REFERENCE:
1560 p_human_reference = (sar_parm_human_reference_struct *)p;
1561 if((obj_ptr != NULL) && (obj_human_ptr != NULL) &&
1562 (p_human_reference->reference_name != NULL)
1563 )
1564 {
1565 int human_ref_obj_num = -1;
1566 const char *ref_name = (const char *)p_human_reference->reference_name;
1567
1568 /* Run towards? */
1569 if(p_human_reference->flags & SAR_HUMAN_FLAG_RUN_TOWARDS)
1570 {
1571 obj_human_ptr->flags |= SAR_HUMAN_FLAG_RUN_TOWARDS;
1572 }
1573 /* Run away? */
1574 else if(p_human_reference->flags & SAR_HUMAN_FLAG_RUN_AWAY)
1575 {
1576 obj_human_ptr->flags |= SAR_HUMAN_FLAG_RUN_AWAY;
1577 }
1578
1579 /* Handle reference object name */
1580 if(!strcasecmp(ref_name, "player"))
1581 {
1582 /* Set special intercept code to intercept the player */
1583 obj_human_ptr->intercepting_object = -2;
1584 }
1585 else
1586 {
1587 /* All else match by object name */
1588 SARObjMatchPointerByName(
1589 scene, *ptr, *total,
1590 ref_name, &human_ref_obj_num
1591 );
1592 obj_human_ptr->intercepting_object = human_ref_obj_num;
1593 }
1594 }
1595 break;
1596
1597 } /* Handle by parm type */
1598 } /* Iterate through loaded parms */
1599
1600
1601 /* Delete loaded parms */
1602 SARParmDeleteAll(&parm, &total_parms);
1603
1604 #undef DO_RESET_SUBSTRUCTURE_PTRS
1605
1606 return(0);
1607 }
1608