1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 
6 #ifdef __MSW__
7 # include <windows.h>
8 #endif
9 
10 #include <GL/gl.h>
11 
12 #include "../include/string.h"
13 
14 #include "matrixmath.h"
15 #include "sfm.h"
16 
17 #include "sound.h"
18 #include "sarreality.h"
19 #include "obj.h"
20 #include "objsound.h"
21 #include "objutils.h"
22 #include "sar.h"
23 #include "config.h"
24 
25 
26 #ifdef __MSW__
27 static double rint(double x);
28 #endif	/* __MSW__ */
29 
30 int SARObjIsAllocated(
31 	sar_object_struct **ptr, int total,
32 	int n
33 );
34 sar_object_struct *SARObjGetPtr(
35 	sar_object_struct **ptr, int total,
36 	int n
37 );
38 int SARGetObjectNumberFromPointer(
39 	sar_scene_struct *scene,
40 	sar_object_struct **ptr, int total,
41 	sar_object_struct *obj_ptr
42 );
43 int SARIsTextureAllocated(sar_scene_struct *scene, int n);
44 sar_object_struct *SARObjMatchPointerByName(
45 	sar_scene_struct *scene,
46 	sar_object_struct **ptr, int total,
47 	const char *name, int *obj_num
48 );
49 
50 v3d_texture_ref_struct *SARGetTextureRefByName(
51 	sar_scene_struct *scene, const char *name
52 );
53 int SARGetTextureRefNumberByName(
54 	sar_scene_struct *scene, const char *name
55 );
56 
57 int SARObjLandingGearState(sar_object_struct *obj_ptr);
58 
59 sar_obj_part_struct *SARObjGetPartPtr(
60 	sar_object_struct *obj_ptr, sar_obj_part_type type, int skip
61 );
62 sar_obj_rotor_struct *SARObjGetRotorPtr(
63 	sar_object_struct *obj_ptr, int n, int *total
64 );
65 sar_obj_hoist_struct *SARObjGetHoistPtr(
66 	sar_object_struct *obj_ptr, int n, int *total
67 );
68 int SARObjGetOnBoardPtr(
69 	sar_object_struct *obj_ptr,
70 	int **crew, int **passengers, int **passengers_max,
71 	float **passengers_mass,
72 	int **passengers_leave_pending, int **passengers_drop_pending
73 );
74 sar_external_fueltank_struct *SARObjGetFuelTankPtr(
75 	sar_object_struct *obj_ptr, int n, int *total
76 );
77 
78 sar_visual_model_struct *SARVisualModelNew(
79 	sar_scene_struct *scene,
80 	const char *filename, const char *name
81 );
82 void *SARVisualModelNewList(sar_visual_model_struct *vmodel);
83 int SARVisualModelGetRefCount(sar_visual_model_struct *vmodel);
84 void SARVisualModelRef(sar_visual_model_struct *vmodel);
85 void SARVisualModelUnref(
86 	sar_scene_struct *scene, sar_visual_model_struct *vmodel
87 );
88 void SARVisualModelCallList(sar_visual_model_struct *vmodel);
89 static void SARVisualModelDelete(sar_visual_model_struct *vmodel);
90 void SARVisualModelDeleteAll(sar_scene_struct *scene);
91 
92 sar_cloud_layer_struct *SARCloudLayerNew(
93 	sar_scene_struct *scene,
94 	int tile_width, int tile_height,
95 	float range, float altitude,
96 	const char *tex_name
97 );
98 void SARCloudLayerDelete(
99 	sar_scene_struct *scene,
100 	sar_cloud_layer_struct *cloud_layer_ptr
101 );
102 
103 sar_cloud_bb_struct *SARCloudBBNew(
104 	sar_scene_struct *scene,
105 	int tile_width, int tile_height,
106 	const sar_position_struct *pos,
107 	float width, float height,	/* In meters */
108 	const char *tex_name,
109 	time_t lightening_min_int,      /* In ms */
110 	time_t lightening_max_int       /* In ms */
111 );
112 void SARCloudBBDelete(sar_cloud_bb_struct *cloud_bb_ptr);
113 
114 int SARObjAddToGroundList(
115 	sar_scene_struct *scene, sar_object_struct *obj_ptr
116 );
117 void SARObjRemoveFromGroundList(
118 	sar_scene_struct *scene, sar_object_struct *obj_ptr
119 );
120 
121 int SARObjAddToHumanRescueList(
122 	sar_scene_struct *scene, sar_object_struct *obj_ptr
123 );
124 void SARObjRemoveFromHumanRescueList(
125 	sar_scene_struct *scene, sar_object_struct *obj_ptr
126 );
127 
128 int SARObjAddContactBoundsSpherical(
129 	sar_object_struct *obj_ptr,
130 	sar_obj_flags_t crash_flags, int crash_type,
131 	float contact_radius
132 );
133 int SARObjAddContactBoundsCylendrical(
134 	sar_object_struct *obj_ptr,
135 	sar_obj_flags_t crash_flags, int crash_type,
136 	float contact_radius,
137 	float contact_h_min, float contact_h_max
138 );
139 int SARObjAddContactBoundsRectangular(
140 	sar_object_struct *obj_ptr,
141 	sar_obj_flags_t crash_flags, int crash_type,
142 	float contact_x_min, float contact_x_max,
143 	float contact_y_min, float contact_y_max,
144 	float contact_z_min, float contact_z_max
145 );
146 
147 int SARObjInterceptNew(
148 	sar_scene_struct *scene,
149 	sar_intercept_struct ***ptr, int *total,
150 	sar_obj_flags_t flags,
151 	float x, float y, float z,
152 	float radius,
153 	float urgency,
154 	const char *name
155 );
156 static sar_obj_part_struct *SARObjPartNewNexus(
157 	sar_scene_struct *scene,
158 	sar_obj_part_struct ***ptr, int *total,
159 	sar_obj_part_type type
160 );
161 sar_obj_part_struct *SARObjPartNew(
162 	sar_scene_struct *scene,
163 	sar_obj_part_struct ***ptr, int *total,
164 	sar_obj_part_type type
165 );
166 sar_obj_part_struct *SARObjAirBrakeNew(
167 	sar_scene_struct *scene,
168 	sar_obj_part_struct ***ptr, int *total
169 );
170 sar_obj_part_struct *SARObjDoorRescueNew(
171 	sar_scene_struct *scene,
172 	sar_obj_part_struct ***ptr, int *total
173 );
174 sar_obj_part_struct *SARObjLandingGearNew(
175 	sar_scene_struct *scene,
176 	sar_obj_part_struct ***ptr, int *total
177 );
178 int SARObjExternalFuelTankNew(
179 	sar_scene_struct *scene,
180 	sar_external_fueltank_struct ***ptr, int *total
181 );
182 int SARObjRotorNew(
183 	sar_scene_struct *scene,
184 	sar_obj_rotor_struct ***ptr, int *total
185 );
186 sar_light_struct *SARObjLightNew(
187 	sar_scene_struct *scene,
188 	sar_light_struct ***ptr, int *total
189 );
190 int SARObjNew(
191 	sar_scene_struct *scene,
192 	sar_object_struct ***ptr, int *total,
193 	int type
194 );
195 
196 void SARObjDeleteIntercepts(
197 	sar_scene_struct *scene,
198 	sar_intercept_struct ***ptr, int *total
199 );
200 void SARObjDeleteLights(
201 	sar_scene_struct *scene,
202 	sar_light_struct ***ptr, int *total
203 );
204 void SARObjDeleteParts(
205 	sar_scene_struct *scene,
206 	sar_obj_part_struct ***ptr, int *total
207 );
208 void SARObjDeleteExternalFuelTanks(
209 	sar_scene_struct *scene,
210 	sar_external_fueltank_struct ***ptr, int *total
211 );
212 void SARObjDeleteRotors(
213 	sar_scene_struct *scene,
214 	sar_obj_rotor_struct ***ptr, int *total
215 );
216 void SARObjDelete(
217 	void *core_ptr,
218 	sar_object_struct ***ptr, int *total, int n
219 );
220 
221 void SARObjGenerateTilePlane(
222 	float min, float max,
223 	float tile_width, float tile_height
224 );
225 
226 
227 #define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
228 #define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
229 #define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
230 #define STRDUP(s)       (((s) != NULL) ? strdup(s) : NULL)
231 
232 #define MAX(a,b)        (((a) > (b)) ? (a) : (b))
233 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
234 #define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
235 
236 #define ISSTREMPTY(s)	(((s) != NULL) ? (*(s) == '\0') : True)
237 #define STRLEN(s)	(((s) != NULL) ? ((int)strlen(s)) : 0)
238 
239 
240 #ifdef __MSW__
rint(double x)241 static double rint(double x)
242 {
243 	if((double)((double)x - (int)x) > (double)0.5)
244 	    return((double)((int)x + (int)1));
245 	else
246 	    return((double)((int)x));
247 }
248 #endif	/* __MSW__ */
249 
250 
251 /*
252  *	Returns true if object n is allocated in the given array.
253  */
SARObjIsAllocated(sar_object_struct ** ptr,int total,int n)254 int SARObjIsAllocated(
255 	sar_object_struct **ptr, int total,
256 	int n
257 )
258 {
259 	if((ptr == NULL) || (n < 0) || (n >= total))
260 	    return(0);
261 	else if(ptr[n] == NULL)
262 	    return(0);
263 	else
264 	    return(1);
265 }
266 
267 /*
268  *	Returns pointer to object n if it is valid and not NULL.
269  *
270  *	Returns NULL on error.
271  */
SARObjGetPtr(sar_object_struct ** ptr,int total,int n)272 sar_object_struct *SARObjGetPtr(
273 	sar_object_struct **ptr, int total,
274 	int n
275 )
276 {
277 	if((ptr == NULL) || (n < 0) || (n >= total))
278 	    return(NULL);
279 	else
280 	    return(ptr[n]);
281 }
282 
283 
284 /*
285  *	Returns the number of the object pointer in the given pointer
286  *	array or -1 if no match.
287  */
SARGetObjectNumberFromPointer(sar_scene_struct * scene,sar_object_struct ** ptr,int total,sar_object_struct * obj_ptr)288 int SARGetObjectNumberFromPointer(
289 	sar_scene_struct *scene,
290 	sar_object_struct **ptr, int total,
291 	sar_object_struct *obj_ptr
292 )
293 {
294 	int i;
295 
296 	if(obj_ptr == NULL)
297 	    return(-1);
298 
299 	for(i = 0; i < total; i++)
300 	{
301 	    if(ptr[i] == obj_ptr)
302 		return(i);
303 	}
304 
305 	return(-1);
306 }
307 
308 /*
309  *	Checks if the texture is allocated on the scene.
310  */
SARIsTextureAllocated(sar_scene_struct * scene,int n)311 int SARIsTextureAllocated(sar_scene_struct *scene, int n)
312 {
313 	if((scene == NULL) || (n < 0) || (n >= scene->total_texture_refs))
314 	    return(0);
315 	else if(scene->texture_ref[n] == NULL)
316 	    return(0);
317 	else
318 	    return(1);
319 }
320 
321 /*
322  *	Returns the pointer to the object matching the given name or
323  *	NULL if no match was made.
324  */
SARObjMatchPointerByName(sar_scene_struct * scene,sar_object_struct ** ptr,int total,const char * name,int * obj_num)325 sar_object_struct *SARObjMatchPointerByName(
326 	sar_scene_struct *scene,
327 	sar_object_struct **ptr, int total,
328 	const char *name, int *obj_num
329 )
330 {
331 	int i;
332 	sar_object_struct *obj_ptr;
333 
334 
335 	if(obj_num != NULL)
336 	    *obj_num = -1;
337 
338 	/* Go through each object */
339 	for(i = 0; i < total; i++)
340 	{
341 	    obj_ptr = ptr[i];
342 	    if((obj_ptr != NULL) ? (obj_ptr->name == NULL) : 1)
343 		continue;
344 
345 	    /* Names match? */
346 	    if(!strcasecmp(obj_ptr->name, name))
347 	    {
348 		if(obj_num != NULL)
349 		    *obj_num = i;
350 
351 		return(obj_ptr);
352 	    }
353 	}
354 
355 	return(NULL);
356 }
357 
358 /*
359  *	Returns a pointer to the texture reference structure matching
360  *	the given name. Can return NULL for failed match.
361  */
SARGetTextureRefByName(sar_scene_struct * scene,const char * name)362 v3d_texture_ref_struct *SARGetTextureRefByName(
363 	sar_scene_struct *scene, const char *name
364 )
365 {
366 	int i, total;
367 	v3d_texture_ref_struct *t, **ptr;
368 
369 
370 	if((scene == NULL) || (name == NULL))
371 	    return(NULL);
372 
373 	ptr = scene->texture_ref;
374 	total = scene->total_texture_refs;
375 
376 	for(i = 0; i < total; i++)
377 	{
378 	    t = ptr[i];
379 	    if((t != NULL) ? (t->name == NULL) : 1)
380 		continue;
381 
382 	    if((t->name == name) ? 1 : !strcasecmp(t->name, name))
383 		return(t);
384 	}
385 
386 	return(NULL);
387 }
388 
389 /*
390  *	Same as SARGetTextureRefByName() except that it returns the
391  *	texture index number of -1 on error.
392  */
SARGetTextureRefNumberByName(sar_scene_struct * scene,const char * name)393 int SARGetTextureRefNumberByName(
394 	sar_scene_struct *scene, const char *name
395 )
396 {
397 	int i, total;
398 	v3d_texture_ref_struct *t, **ptr;
399 
400 	if((scene == NULL) || ISSTREMPTY(name))
401 	    return(-1);
402 
403 	ptr = scene->texture_ref;
404 	total = scene->total_texture_refs;
405 
406 	for(i = 0; i < total; i++)
407 	{
408 	    t = ptr[i];
409 	    if((t != NULL) ? (t->name == NULL) : 1)
410 		continue;
411 
412 	    if((t->name == name) ? 1 : !strcasecmp(t->name, name))
413 		return(i);
414 	}
415 
416 	return(-1);
417 }
418 
419 
420 /*
421  *	Returns -1 if the object does not have landing gears, 0 if the
422  *	landing gears exist but are up, or 1 if the landing gears are
423  *	down.
424  */
SARObjLandingGearState(sar_object_struct * obj_ptr)425 int SARObjLandingGearState(sar_object_struct *obj_ptr)
426 {
427 	sar_object_aircraft_struct *aircraft;
428 
429 	if(obj_ptr == NULL)
430 	    return(-1);
431 
432 	aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
433 	return((aircraft != NULL) ?
434 	    aircraft->landing_gear_state : -1
435 	);
436 }
437 
438 /*
439  *	Returns the pointer to the part structure on the object that
440  *	matches the given part type. The skip indicates the number
441  *	of part structures of the specified type to be skipped.
442  */
SARObjGetPartPtr(sar_object_struct * obj_ptr,sar_obj_part_type type,int skip)443 sar_obj_part_struct *SARObjGetPartPtr(
444 	sar_object_struct *obj_ptr, sar_obj_part_type type, int skip
445 )
446 {
447 	int i, j, m = 0;
448 	sar_object_aircraft_struct *aircraft;
449 	sar_obj_part_struct *part, **list = NULL;
450 
451 
452 	if(obj_ptr == NULL)
453 	    return(NULL);
454 
455 
456 	/* Begin checking object type and get the object parts list */
457 
458 	/* Aircraft */
459 	aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
460 	if(aircraft != NULL)
461 	{
462 	    list = aircraft->part;
463 	    m = aircraft->total_parts;
464 	}
465 
466 
467 	/* Got list of object parts? */
468 	if(list != NULL)
469 	{
470 	    for(i = 0, j = 0; i < m; i++)
471 	    {
472 		part = list[i];
473 		if(part == NULL)
474 		    continue;
475 		if(part->type != type)
476 		    continue;
477 
478 		/* Increment j, the skip count. If the skip count is still
479 		 * at or below the requested number of times to skip n,
480 		 * then skip this part.
481 		 */
482 		j++;
483 		if(j <= skip)
484 		    continue;
485 
486 		return(part);
487 	    }
488 	}
489 
490 	return(NULL);
491 }
492 
493 /*
494  *	Returns pointer to the n th index rotor and optional total
495  *	on the given object. Can return NULL if none exist.
496  *
497  *	If object only has one, then pass n as 0.
498  */
SARObjGetRotorPtr(sar_object_struct * obj_ptr,int n,int * total)499 sar_obj_rotor_struct *SARObjGetRotorPtr(
500 	sar_object_struct *obj_ptr, int n, int *total
501 )
502 {
503 	sar_object_aircraft_struct *aircraft;
504 
505 
506 	if(total != NULL)
507 	    *total = 0;
508 
509 	if(obj_ptr == NULL)
510 	    return(NULL);
511 
512 	aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
513 	if(aircraft != NULL)
514 	{
515 	    if(total != NULL)
516 		*total = aircraft->total_rotors;
517 	    if((aircraft->rotor != NULL) &&
518 	       (n >= 0) && (n < aircraft->total_rotors)
519 	    )
520 		return(aircraft->rotor[n]);
521 	}
522 
523 	return(NULL);
524 }
525 
526 /*
527  *      Returns pointer to the n th index door and optional total
528  *      on the given object. Can return NULL if none exist.
529  *
530  *      If object only has one, then pass n as 0.
531  */
SARObjGetHoistPtr(sar_object_struct * obj_ptr,int n,int * total)532 sar_obj_hoist_struct *SARObjGetHoistPtr(
533 	sar_object_struct *obj_ptr, int n, int *total
534 )
535 {
536 	sar_object_aircraft_struct *aircraft;
537 
538 
539 	if(total != NULL)
540 	    *total = 0;
541 
542 	if(obj_ptr == NULL)
543 	    return(NULL);
544 
545 	aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
546 	if(aircraft != NULL)
547 	{
548 	    if(total != NULL)
549 		*total = 1;
550 	    if(n == 0)
551 		return(aircraft->hoist);
552 	}
553 
554 	return(NULL);
555 }
556 
557 /*
558  *	Returns pointers to the object's value for crew and passengers
559  *	(and related information).
560  *
561  *	Returns -1 on error, -2 if the object's type does not have
562  *	passengers, and 0 on success.
563  */
SARObjGetOnBoardPtr(sar_object_struct * obj_ptr,int ** crew,int ** passengers,int ** passengers_max,float ** passengers_mass,int ** passengers_leave_pending,int ** passengers_drop_pending)564 int SARObjGetOnBoardPtr(
565 	sar_object_struct *obj_ptr,
566 	int **crew, int **passengers, int **passengers_max,
567 	float **passengers_mass,
568 	int **passengers_leave_pending, int **passengers_drop_pending
569 )
570 {
571 	sar_object_aircraft_struct *aircraft;
572 
573 
574 	if(crew != NULL)
575 	    *crew = NULL;
576 	if(passengers != NULL)
577 	    *passengers = NULL;
578 	if(passengers_max != NULL)
579 	    *passengers_max = NULL;
580 	if(passengers_mass != NULL)
581 	    *passengers_mass = NULL;
582 	if(passengers_leave_pending != NULL)
583 	    *passengers_leave_pending = NULL;
584 	if(passengers_drop_pending != NULL)
585 	    *passengers_drop_pending = NULL;
586 
587 	if(obj_ptr == NULL)
588 	    return(-1);
589 
590 	switch(obj_ptr->type)
591 	{
592 	  case SAR_OBJ_TYPE_GARBAGE:
593 	  case SAR_OBJ_TYPE_STATIC:
594 	  case SAR_OBJ_TYPE_AUTOMOBILE:
595 	  case SAR_OBJ_TYPE_WATERCRAFT:
596 	    return(-2);
597 	    break;
598 	  case SAR_OBJ_TYPE_AIRCRAFT:
599 	    aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
600 	    if(aircraft != NULL)
601 	    {
602 		if(crew != NULL)
603 		    *crew = &aircraft->crew;
604 		if(passengers != NULL)
605 		    *passengers = &aircraft->passengers;
606 		if(passengers_max != NULL)
607 		    *passengers_max = &aircraft->passengers_max;
608 		if(passengers_mass != NULL)
609 		    *passengers_mass = &aircraft->passengers_mass;
610 		if(passengers_leave_pending != NULL)
611 		    *passengers_leave_pending = &aircraft->passengers_leave_pending;
612 		if(passengers_drop_pending != NULL)
613 		    *passengers_drop_pending = &aircraft->passengers_drop_pending;
614 		return(0);
615 	    }
616 	    break;
617 	  case SAR_OBJ_TYPE_GROUND:
618 	  case SAR_OBJ_TYPE_RUNWAY:
619 	  case SAR_OBJ_TYPE_HELIPAD:
620 	  case SAR_OBJ_TYPE_HUMAN:
621 	  case SAR_OBJ_TYPE_SMOKE:
622 	  case SAR_OBJ_TYPE_FIRE:
623 	  case SAR_OBJ_TYPE_EXPLOSION:
624 	  case SAR_OBJ_TYPE_CHEMICAL_SPRAY:
625 	  case SAR_OBJ_TYPE_FUELTANK:
626 	  case SAR_OBJ_TYPE_PREMODELED:
627 	    return(-2);
628   	    break;
629 	}
630 
631 	return(-1);
632 }
633 
634 /*
635  *      Returns pointer to the n th external reserved fuel tank and
636  *	optional total on the given object. Can return NULL if none exist.
637  *
638  *      If object only has one, then pass n as 0.
639  */
SARObjGetFuelTankPtr(sar_object_struct * obj_ptr,int n,int * total)640 sar_external_fueltank_struct *SARObjGetFuelTankPtr(
641 	sar_object_struct *obj_ptr, int n, int *total
642 )
643 {
644 	sar_object_aircraft_struct *aircraft;
645 
646 	if(total != NULL)
647 	    *total = 0;
648 
649 	if(obj_ptr == NULL)
650 	    return(NULL);
651 
652 	switch(obj_ptr->type)
653 	{
654 	  case SAR_OBJ_TYPE_GARBAGE:
655 	  case SAR_OBJ_TYPE_STATIC:
656 	  case SAR_OBJ_TYPE_AUTOMOBILE:
657 	  case SAR_OBJ_TYPE_WATERCRAFT:
658 	    break;
659 	  case SAR_OBJ_TYPE_AIRCRAFT:
660 	    aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
661 	    if(aircraft != NULL)
662 	    {
663 		if(total != NULL)
664 		    *total = aircraft->total_external_fueltanks;
665 
666 		if((aircraft->external_fueltank != NULL) &&
667 		   (n >= 0) && (n < aircraft->total_external_fueltanks)
668 		)
669 		    return(aircraft->external_fueltank[n]);
670 	    }
671 	    break;
672 	  case SAR_OBJ_TYPE_GROUND:
673 	  case SAR_OBJ_TYPE_RUNWAY:
674 	  case SAR_OBJ_TYPE_HELIPAD:
675 	  case SAR_OBJ_TYPE_HUMAN:
676 	  case SAR_OBJ_TYPE_SMOKE:
677 	  case SAR_OBJ_TYPE_FIRE:
678 	  case SAR_OBJ_TYPE_EXPLOSION:
679 	  case SAR_OBJ_TYPE_CHEMICAL_SPRAY:
680 	  case SAR_OBJ_TYPE_FUELTANK:
681 	  case SAR_OBJ_TYPE_PREMODELED:
682 	    break;
683 	}
684 	return(NULL);
685 }
686 
687 
688 /*
689  *	Creates a new or returns an existing Visual Model on the
690  *	specified Scene.
691  *
692  *	If the specified Visual Model filename and name both match an
693  *	existing Visual Model on the Scene then that Visual Model is
694  *	returned.
695  *
696  *	If filename or name is NULL then a new visual model will be
697  *	created and will be treated as `unique' meaning that it will not
698  *	be returned for match with any other call to SARVisualModelNew()
699  *	(since the filename and name are unmatchable).
700  *
701  *	A new visual model will be given one ref count, while an existing
702  *	visual model will have its ref count incremented by one. There
703  *	will never be a case where a returned visual model will have only
704  *	0 or negative ref counts. Ref counts on returned visual models
705  *	will always be 1 or greater.
706  *
707  *	Can return NULL on error.
708  */
SARVisualModelNew(sar_scene_struct * scene,const char * filename,const char * name)709 sar_visual_model_struct *SARVisualModelNew(
710 	sar_scene_struct *scene,
711 	const char *filename, const char *name
712 )
713 {
714 	int i;
715 	sar_visual_model_struct *vmodel;
716 
717 	if(scene == NULL)
718 	    return(NULL);
719 
720 	/* Both filename and name given? */
721 	if((filename != NULL) && (name != NULL))
722 	{
723 	    /* Check for an existing visual model with the same
724 	     * filename and name
725 	     */
726 	    for(i = 0; i < scene->total_visual_models; i++)
727 	    {
728 		vmodel = scene->visual_model[i];
729 		if(vmodel == NULL)
730 		    continue;
731 
732 		/* Both filename and name match (case sensitive)? */
733 		if((vmodel->filename != NULL) && (vmodel->name != NULL))
734 		{
735 		    if(!strcmp(vmodel->filename, filename) &&
736 		       !strcmp(vmodel->name, name)
737 		    )
738 		    {
739 			/* Increment the ref count for matched visual
740 			 * model and return its pointer
741 			 */
742 			vmodel->ref_count++;
743 			return(vmodel);
744 		    }
745 		}
746 	    }
747 	}
748 
749 
750 	/* Create new visual model */
751 
752 	/* Sanitize total */
753 	if(scene->total_visual_models < 0)
754 	    scene->total_visual_models = 0;
755 
756 	/* Look for available pointer */
757 	for(i = 0; i < scene->total_visual_models; i++)
758 	{
759 	    if(scene->visual_model[i] == NULL)
760 		break;
761 	}
762 	if(i < scene->total_visual_models)
763 	{
764 	    /* Got available pointer at index i */
765 	}
766 	else
767 	{
768 	    /* Need to allocate a new pointer */
769 	    i = scene->total_visual_models;
770 	    scene->total_visual_models = i + 1;
771 	    scene->visual_model = (sar_visual_model_struct **)realloc(
772 		scene->visual_model,
773 		scene->total_visual_models * sizeof(sar_visual_model_struct *)
774 	    );
775 	    if(scene->visual_model == NULL)
776 	    {
777 		scene->total_visual_models = 0;
778 		return(NULL);
779 	    }
780 	    else
781 	    {
782 		scene->visual_model[i] = NULL;
783 	    }
784 	}
785 
786 	/* Allocate new structure */
787 	scene->visual_model[i] = vmodel = SAR_VISUAL_MODEL(calloc(
788 	    1, sizeof(sar_visual_model_struct)
789 	));
790 	if(vmodel != NULL)
791 	{
792 	    vmodel->load_state = SAR_VISUAL_MODEL_NOT_LOADED;
793 
794 	    /* Set initial ref count to 1 for all new visual models
795 	     * this is how calling functions can tell that this is a
796 	     * new visual model
797 	     */
798 	    vmodel->ref_count = 1;
799 
800 	    vmodel->filename = STRDUP(filename);
801 	    vmodel->name = STRDUP(name);
802 
803 	    vmodel->data = NULL;
804 
805 	    vmodel->mem_size = 0;
806 	    vmodel->statements = 0;
807 	    vmodel->primitives = 0;
808 	}
809 
810 	return(vmodel);
811 }
812 
813 /*
814  *	(Re)generates a GL display list on the given visual model.
815  *
816  *	The return value is really a GLuint (not a void *), can return
817  *	NULL on failure.
818  */
SARVisualModelNewList(sar_visual_model_struct * vmodel)819 void *SARVisualModelNewList(sar_visual_model_struct *vmodel)
820 {
821 	GLuint list;
822 
823 	if(vmodel == NULL)
824 	    return(NULL);
825 
826 	/* Get existing GL display list if any */
827 	list = (GLuint)vmodel->data;
828 	if(list > 0)
829 	{
830 	    /* Already has an allocated GL display list so delete it
831 	     * and create a new one
832 	     */
833 	    glDeleteLists(list, 1);
834 	    list = 0;
835 	    vmodel->data = NULL;
836 	}
837 
838 	/* Create new GL display list */
839 	list = glGenLists(1);
840 
841 	/* Set new GL display list as the data pointer on the visual
842 	 * model structure
843 	 */
844 	vmodel->data = (void *)list;
845 
846 	return((void *)list);
847 }
848 
849 /*
850  *	Returns number of ref counts on visual model.
851  *
852  *	Can return -1 if visual model is NULL.
853  */
SARVisualModelGetRefCount(sar_visual_model_struct * vmodel)854 int SARVisualModelGetRefCount(sar_visual_model_struct *vmodel)
855 {
856 	if(vmodel != NULL)
857 	    return(vmodel->ref_count);
858 	else
859 	    return(-1);
860 }
861 
862 /*
863  *	Increases the ref count on the given visual model by one.
864  */
SARVisualModelRef(sar_visual_model_struct * vmodel)865 void SARVisualModelRef(sar_visual_model_struct *vmodel)
866 {
867 	if(vmodel != NULL)
868 	    vmodel->ref_count++;
869 }
870 
871 /*
872  *	Decrease the ref count on the given visual model by one.
873  *
874  *	If (after decrement) the ref count drops to 0 then the given
875  *	visual model will be destroyed and its pointer should not
876  *	be referenced again.
877  *
878  *	It's a general sense to not reference any pointer value again from
879  *	any one variable after it's passed to this function. The scene
880  *	structure's visual_model list is ultimatly to hold the pointer
881  *	the visual model all the way to when it is down to its last
882  *	ref count of 0.
883  *
884  *	If scene is not NULL then any visual model pointers on the
885  *	scene's visual models list matching the given vmodel pointer
886  *	will be set to NULL.
887  */
SARVisualModelUnref(sar_scene_struct * scene,sar_visual_model_struct * vmodel)888 void SARVisualModelUnref(
889 	sar_scene_struct *scene, sar_visual_model_struct *vmodel
890 )
891 {
892 	if(vmodel == NULL)
893 	    return;
894 
895 	/* Reference counts have already reached 0? */
896 	if(vmodel->ref_count < 1)
897 	    fprintf(
898 		stderr,
899 "SARVisualModelUnref(): Warning: \
900 Visual model \"%s\" has less than 1 reference count.\n",
901 		vmodel->name
902 	    );
903 
904 	/* Reduce reference count */
905 	vmodel->ref_count--;
906 	if(vmodel->ref_count < 0)
907 	    vmodel->ref_count = 0;
908 
909 	/* No reference counts left? */
910 	if(vmodel->ref_count == 0)
911 	{
912 	    /* Reference counts have reached 0 on this visual model,
913 	     * so once that happens the visual model needs
914 	     * to be deleted and removed from the Scene
915 	     */
916 
917 	    /* Delete this visual model, deleting its GL
918 	     * display list and the visual model structure itself
919 	     */
920 	    SARVisualModelDelete(vmodel);
921 
922 	    /* Pointer vmodel is now invalid, but do not set it to
923 	     * NULL just yet as it needs to be used to check for
924 	     * references to it on the scene structure
925 	     */
926 	    if(scene != NULL)
927 	    {
928 		int i;
929 
930 		for(i = 0; i < scene->total_visual_models; i++)
931 		{
932 		    if(scene->visual_model[i] == vmodel)
933 			scene->visual_model[i] = NULL;
934 		}
935 	    }
936 	}
937 }
938 
939 /*
940  *      Calls the GL list on the visual model if it is not 0.
941  */
SARVisualModelCallList(sar_visual_model_struct * vmodel)942 void SARVisualModelCallList(sar_visual_model_struct *vmodel)
943 {
944 	GLuint list = (vmodel != NULL) ? (GLuint)vmodel->data : 0;
945 	if(list > 0)
946 	    glCallList(list);
947 }
948 
949 /*
950  *	Deletes the Visual Model.
951  *
952  *	This function is intended to be called from SARVisualModelUnref().
953  */
SARVisualModelDelete(sar_visual_model_struct * vmodel)954 static void SARVisualModelDelete(sar_visual_model_struct *vmodel)
955 {
956 	GLuint list;
957 
958 	if(vmodel == NULL)
959 	    return;
960 
961 	if(vmodel->ref_count > 0)
962 	    fprintf(
963 		stderr,
964 "SARVisualModelDelete(): Warning: \
965 Visual model `%s' still has %i reference counts.\n",
966 		vmodel->name, vmodel->ref_count
967 	    );
968 
969 	free(vmodel->filename);
970 	free(vmodel->name);
971 
972 	list = (GLuint)vmodel->data;
973 	if(list > 0)
974 	    glDeleteLists(list, 1);
975 
976 	free(vmodel);
977 }
978 
979 /*
980  *	Deletes all the Visual Models on the specified Scene.
981  */
SARVisualModelDeleteAll(sar_scene_struct * scene)982 void SARVisualModelDeleteAll(sar_scene_struct *scene)
983 {
984 	int i;
985 
986 	if(scene == NULL)
987 	    return;
988 
989 	for(i = 0; i < scene->total_visual_models; i++)
990 	{
991 	    /* Delete the visual model, note that its ref counts
992 	     * should be 0 at this point
993 	     */
994 	    SARVisualModelDelete(scene->visual_model[i]);
995 	}
996 	free(scene->visual_model);
997 	scene->visual_model = NULL;
998 	scene->total_visual_models = 0;
999 }
1000 
1001 
1002 /*
1003  *	Creates a new Cloud Layer.
1004  */
SARCloudLayerNew(sar_scene_struct * scene,int tile_width,int tile_height,float range,float altitude,const char * tex_name)1005 sar_cloud_layer_struct *SARCloudLayerNew(
1006 	sar_scene_struct *scene,
1007 	int tile_width, int tile_height,
1008 	float range,			/* Tiling range in meters */
1009 	float altitude,		/* Altitude in meters */
1010 	const char *tex_name
1011 )
1012 {
1013 	GLuint list;
1014 	float min, max;
1015 	v3d_texture_ref_struct *t;
1016 	sar_visual_model_struct **vmodel;
1017 	sar_cloud_layer_struct *cloud_layer_ptr = (sar_cloud_layer_struct *)
1018 	    calloc(1, sizeof(sar_cloud_layer_struct));
1019 
1020 
1021 	if(cloud_layer_ptr == NULL)
1022 	    return(NULL);
1023 
1024 	cloud_layer_ptr->tile_width = tile_width;
1025 	cloud_layer_ptr->tile_height = tile_height;
1026 	cloud_layer_ptr->range = MAX(range, MAX(tile_width, tile_height));
1027 	cloud_layer_ptr->z = altitude;
1028 
1029 	/* Match texture by name */
1030 	t = SARGetTextureRefByName(scene, tex_name);
1031 
1032 	/* Calculate entire size limits */
1033 	min = -cloud_layer_ptr->range;
1034 	max = cloud_layer_ptr->range;
1035 
1036 	/* Get pointer to visual model */
1037 	vmodel = &cloud_layer_ptr->visual_model;
1038 
1039 	/* Unref visual model if its pointer to reference is not NULL */
1040 	if((*vmodel) != NULL)
1041 	{
1042 	    SARVisualModelUnref(scene, *vmodel);
1043 	    (*vmodel) = NULL;
1044 	}
1045 
1046 	/* Create new visual model */
1047 	(*vmodel) = SARVisualModelNew(
1048 	    scene, NULL, NULL
1049 	);
1050 
1051 	/* (Re)generate GL list on visual model structure */
1052 	list = (GLuint)SARVisualModelNewList(*vmodel);
1053 	if(list != 0)
1054 	{
1055 	    /* Mark as loading */
1056 	    (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADING;
1057 
1058 	    /* Begin recording GL list */
1059 	    glNewList(list, GL_COMPILE);
1060 	    {
1061 		/* Select texture if defined */
1062 		V3DTextureSelect(t);
1063 
1064 		/* Do not set color */
1065 
1066 		/* Close range textured tiles */
1067 		SARObjGenerateTilePlane(
1068 		    min, max,			/* Min and max */
1069 		    (float)tile_width, (float)tile_height	/* Tiling size */
1070 		);
1071 	    }
1072 	    glEndList();
1073 
1074 	    /* Mark as done loading */
1075 	    (*vmodel)->load_state = SAR_VISUAL_MODEL_LOADED;
1076 	}
1077 
1078 	return(cloud_layer_ptr);
1079 }
1080 
1081 /*
1082  *	Deletes the Cloud Layer.
1083  *
1084  *	If scene is NULL then the visual model will not be unref'ed.
1085  */
SARCloudLayerDelete(sar_scene_struct * scene,sar_cloud_layer_struct * cloud_layer_ptr)1086 void SARCloudLayerDelete(
1087 	sar_scene_struct *scene,
1088 	sar_cloud_layer_struct *cloud_layer_ptr
1089 )
1090 {
1091 	if(cloud_layer_ptr == NULL)
1092 	    return;
1093 
1094 	SARVisualModelUnref(scene, cloud_layer_ptr->visual_model);
1095 	free(cloud_layer_ptr->tex_name);
1096 	free(cloud_layer_ptr);
1097 }
1098 
1099 /*
1100  *	Creates a new Cloud BillBoard.
1101  */
SARCloudBBNew(sar_scene_struct * scene,int tile_width,int tile_height,const sar_position_struct * pos,float width,float height,const char * tex_name,time_t lightening_min_int,time_t lightening_max_int)1102 sar_cloud_bb_struct *SARCloudBBNew(
1103 	sar_scene_struct *scene,
1104 	int tile_width, int tile_height,
1105 	const sar_position_struct *pos,
1106 	float width, float height,	/* In meters */
1107 	const char *tex_name,
1108 	time_t lightening_min_int,      /* In ms */
1109 	time_t lightening_max_int       /* In ms */
1110 )
1111 {
1112 	sar_cloud_bb_struct *cloud = SAR_CLOUD_BB(
1113 	    calloc(1, sizeof(sar_cloud_bb_struct))
1114 	);
1115 	if(cloud == NULL)
1116 	    return(NULL);
1117 
1118 	cloud->tile_width = tile_width;
1119 	cloud->tile_height = tile_height;
1120 
1121 	cloud->tex_name = STRDUP(tex_name);
1122 
1123 	/* Match texture number on scene */
1124 	cloud->tex_num = SARGetTextureRefNumberByName(
1125 	    scene, tex_name
1126 	);
1127 
1128 	if(pos != NULL)
1129 	    memcpy(&cloud->pos, pos, sizeof(sar_position_struct));
1130 
1131 	cloud->width = width;
1132 	cloud->height = height;
1133 
1134 	cloud->lightening_min_int = lightening_min_int;
1135 	cloud->lightening_max_int = lightening_max_int;
1136 	cloud->lightening_next_on = 0;
1137 	cloud->lightening_next_off = 0;
1138 	cloud->lightening_started_on = 0;
1139 
1140 	memset(
1141 	    &cloud->lightening_point[0], 0x00,
1142 	    SAR_LIGHTENING_POINTS_MAX * sizeof(sar_position_struct)
1143 	);
1144 
1145 	return(cloud);
1146 }
1147 
1148 /*
1149  *	Deletes the Cloud BillBoard.
1150  */
SARCloudBBDelete(sar_cloud_bb_struct * cloud_bb_ptr)1151 void SARCloudBBDelete(sar_cloud_bb_struct *cloud_bb_ptr)
1152 {
1153 	if(cloud_bb_ptr == NULL)
1154 	    return;
1155 
1156 	free(cloud_bb_ptr->tex_name);
1157 	free(cloud_bb_ptr);
1158 }
1159 
1160 
1161 /*
1162  *	Checks if the object is in the scene's ground list.
1163  *	If not, then it will add it to the list. Returns 0 on success
1164  *	or negative on error/already in list.
1165  */
SARObjAddToGroundList(sar_scene_struct * scene,sar_object_struct * obj_ptr)1166 int SARObjAddToGroundList(
1167 	sar_scene_struct *scene,
1168 	sar_object_struct *obj_ptr
1169 )
1170 {
1171 	int i;
1172 
1173 
1174 	if((scene == NULL) ||
1175 	   (obj_ptr == NULL)
1176 	)
1177 	    return(-1);
1178 
1179 	if(scene->total_ground_objects < 0)
1180 	    scene->total_ground_objects = 0;
1181 
1182 	/* Check if already in list */
1183 	for(i = 0; i < scene->total_ground_objects; i++)
1184 	{
1185 	    if(obj_ptr == scene->ground_object[i])
1186 		return(-2);
1187 	}
1188 
1189 	/* Not in list, so add to list */
1190 	for(i = 0; i < scene->total_ground_objects; i++)
1191 	{
1192 	    if(scene->ground_object[i] == NULL)
1193 	    {
1194 		/* Found an empty entry */
1195 		scene->ground_object[i] = obj_ptr;
1196 		return(0);
1197 	    }
1198 	}
1199 
1200 	/* Need to allocate more entries */
1201 	i = scene->total_ground_objects;
1202 	scene->total_ground_objects++;
1203 
1204 	scene->ground_object = (sar_object_struct **)realloc(
1205 	    scene->ground_object,
1206 	    scene->total_ground_objects * sizeof(sar_object_struct *)
1207 	);
1208 	if(scene->ground_object == NULL)
1209 	{
1210 	    scene->total_ground_objects = 0;
1211 	    return(-1);
1212 	}
1213 
1214 	scene->ground_object[i] = obj_ptr;
1215 
1216 	return(0);
1217 }
1218 
1219 /*
1220  *	Removes the object from the ground list if it is in there.
1221  */
SARObjRemoveFromGroundList(sar_scene_struct * scene,sar_object_struct * obj_ptr)1222 void SARObjRemoveFromGroundList(
1223 	sar_scene_struct *scene,
1224 	sar_object_struct *obj_ptr
1225 )
1226 {
1227 	int i;
1228 
1229 
1230 	if((scene == NULL) || (obj_ptr == NULL))
1231 	    return;
1232 
1233 	for(i = 0; i < scene->total_ground_objects; i++)
1234 	{
1235 	    if(obj_ptr == scene->ground_object[i])
1236 		scene->ground_object[i] = NULL;
1237 	}
1238 }
1239 
1240 /*
1241  *	Adds object pointer to the humans need rescue list on the scene:
1242  */
SARObjAddToHumanRescueList(sar_scene_struct * scene,sar_object_struct * obj_ptr)1243 int SARObjAddToHumanRescueList(
1244 	sar_scene_struct *scene,
1245 	sar_object_struct *obj_ptr
1246 )
1247 {
1248 	int i;
1249 
1250 
1251 	if((scene == NULL) ||
1252 	   (obj_ptr == NULL)
1253 	)
1254 	    return(-1);
1255 
1256 	if(scene->total_human_need_rescue_objects < 0)
1257 	    scene->total_human_need_rescue_objects = 0;
1258 
1259 	/* Check if already in list */
1260 	for(i = 0; i < scene->total_human_need_rescue_objects; i++)
1261 	{
1262 	    if(obj_ptr == scene->human_need_rescue_object[i])
1263 		return(-2);
1264 	}
1265 
1266 	/* Not in list, so add to list */
1267 	for(i = 0; i < scene->total_human_need_rescue_objects; i++)
1268 	{
1269 	    if(scene->human_need_rescue_object[i] == NULL)
1270 	    {
1271 		/* Found an empty entry */
1272 		scene->human_need_rescue_object[i] = obj_ptr;
1273 		return(0);
1274 	    }
1275 	}
1276 
1277 	/* Need to allocate more entries */
1278 	i = scene->total_human_need_rescue_objects;
1279 	scene->total_human_need_rescue_objects++;
1280 
1281 	scene->human_need_rescue_object = (sar_object_struct **)realloc(
1282 	    scene->human_need_rescue_object,
1283 	    scene->total_human_need_rescue_objects * sizeof(sar_object_struct *)
1284 	);
1285 	if(scene->human_need_rescue_object == NULL)
1286 	{
1287 	    scene->total_human_need_rescue_objects = 0;
1288 	    return(-1);
1289 	}
1290 
1291 	scene->human_need_rescue_object[i] = obj_ptr;
1292 
1293 	return(0);
1294 }
1295 
1296 /*
1297  *	Removes object from humans that need rescue list if it is in
1298  *	there.
1299  */
SARObjRemoveFromHumanRescueList(sar_scene_struct * scene,sar_object_struct * obj_ptr)1300 void SARObjRemoveFromHumanRescueList(
1301 	sar_scene_struct *scene,
1302 	sar_object_struct *obj_ptr
1303 )
1304 {
1305 	int i;
1306 
1307 	if((scene == NULL) || (obj_ptr == NULL))
1308 	    return;
1309 
1310 	for(i = 0; i < scene->total_human_need_rescue_objects; i++)
1311 	{
1312 	    if(obj_ptr == scene->human_need_rescue_object[i])
1313 		scene->human_need_rescue_object[i] = NULL;
1314 	}
1315 }
1316 
1317 
1318 /*
1319  *	Allocate (as needed) contact bounds structure to object
1320  *	for shape SAR_CONTACT_SHAPE_SPHERICAL.
1321  *
1322  *      Returns non-zero on error.
1323  */
SARObjAddContactBoundsSpherical(sar_object_struct * obj_ptr,sar_obj_flags_t crash_flags,int crash_type,float contact_radius)1324 int SARObjAddContactBoundsSpherical(
1325 	sar_object_struct *obj_ptr,
1326 	sar_obj_flags_t crash_flags, int crash_type,
1327 	float contact_radius
1328 )
1329 {
1330 	sar_contact_bounds_struct *cb;
1331 
1332 
1333 	if(obj_ptr == NULL)
1334 	    return(-1);
1335 
1336 	/* Allocate as needed */
1337 	if(obj_ptr->contact_bounds == NULL)
1338 	    obj_ptr->contact_bounds = SAR_CONTACT_BOUNDS(
1339 		calloc(1, sizeof(sar_contact_bounds_struct))
1340 	    );
1341 
1342 	cb = obj_ptr->contact_bounds;
1343 	if(cb == NULL)
1344 	    return(-1);
1345 
1346 	cb->crash_flags = crash_flags;
1347 	cb->crash_type = crash_type;
1348 	cb->contact_shape = SAR_CONTACT_SHAPE_SPHERICAL;
1349 
1350 	cb->contact_radius = (float)MAX(contact_radius, 0.0);
1351 
1352 	return(0);
1353 }
1354 
1355 /*
1356  *      Allocate (as needed) contact bounds structure to object
1357  *      for shape SAR_CONTACT_SHAPE_CYLENDRICAL.
1358  *
1359  *      Returns non-zero on error.
1360  */
SARObjAddContactBoundsCylendrical(sar_object_struct * obj_ptr,sar_obj_flags_t crash_flags,int crash_type,float contact_radius,float contact_h_min,float contact_h_max)1361 int SARObjAddContactBoundsCylendrical(
1362 	sar_object_struct *obj_ptr,
1363 	sar_obj_flags_t crash_flags, int crash_type,
1364 	float contact_radius,
1365 	float contact_h_min, float contact_h_max
1366 )
1367 {
1368 	sar_contact_bounds_struct *cb;
1369 
1370 
1371 	if(obj_ptr == NULL)
1372 	    return(-1);
1373 
1374 	/* Allocate as needed */
1375 	if(obj_ptr->contact_bounds == NULL)
1376 	    obj_ptr->contact_bounds = SAR_CONTACT_BOUNDS(
1377 		calloc(1, sizeof(sar_contact_bounds_struct))
1378 	    );
1379 
1380 	cb = obj_ptr->contact_bounds;
1381 	if(cb == NULL)
1382 	    return(-1);
1383 
1384 	cb->crash_flags = crash_flags;
1385 	cb->crash_type = crash_type;
1386 	cb->contact_shape = SAR_CONTACT_SHAPE_CYLENDRICAL;
1387 
1388 	cb->contact_radius = (float)MAX(contact_radius, 0.0);
1389 	cb->contact_h_min = contact_h_min;
1390 	cb->contact_h_max = contact_h_max;
1391 
1392 	/* Flip height as needed */
1393 	if(cb->contact_h_min > cb->contact_h_max)
1394 	{
1395 	    float h = cb->contact_h_min;
1396 
1397 	    cb->contact_h_min = cb->contact_h_max;
1398 	    cb->contact_h_max = h;
1399 	}
1400 
1401 	return(0);
1402 }
1403 
1404 /*
1405  *      Allocate (as needed) contact bounds structure to object
1406  *      for shape SAR_CONTACT_SHAPE_RECTANGULAR.
1407  *
1408  *	Returns non-zero on error.
1409  */
SARObjAddContactBoundsRectangular(sar_object_struct * obj_ptr,sar_obj_flags_t crash_flags,int crash_type,float contact_x_min,float contact_x_max,float contact_y_min,float contact_y_max,float contact_z_min,float contact_z_max)1410 int SARObjAddContactBoundsRectangular(
1411 	sar_object_struct *obj_ptr,
1412 	sar_obj_flags_t crash_flags, int crash_type,
1413 	float contact_x_min, float contact_x_max,
1414 	float contact_y_min, float contact_y_max,
1415 	float contact_z_min, float contact_z_max
1416 )
1417 {
1418 	sar_contact_bounds_struct *cb;
1419 
1420 
1421 	if(obj_ptr == NULL)
1422 	    return(-1);
1423 
1424 	/* Allocate as needed */
1425 	if(obj_ptr->contact_bounds == NULL)
1426 	    obj_ptr->contact_bounds = SAR_CONTACT_BOUNDS(
1427 		calloc(1, sizeof(sar_contact_bounds_struct))
1428 	    );
1429 
1430 	cb = obj_ptr->contact_bounds;
1431 	if(cb == NULL)
1432 	    return(-1);
1433 
1434 	cb->crash_flags = crash_flags;
1435 	cb->crash_type = crash_type;
1436 	cb->contact_shape = SAR_CONTACT_SHAPE_RECTANGULAR;
1437 
1438 	cb->contact_x_min = contact_x_min;
1439 	cb->contact_x_max = contact_x_max;
1440 	if(cb->contact_x_min > cb->contact_x_max)
1441 	{
1442 	    float d = cb->contact_x_min;
1443 
1444 	    cb->contact_x_min = cb->contact_x_max;
1445 	    cb->contact_x_max = d;
1446 	}
1447 
1448 	cb->contact_y_min = contact_y_min;
1449 	cb->contact_y_max = contact_y_max;
1450 	if(cb->contact_y_min > cb->contact_y_max)
1451 	{
1452 	    float d = cb->contact_y_min;
1453 
1454 	    cb->contact_y_min = cb->contact_y_max;
1455 	    cb->contact_y_max = d;
1456 	}
1457 
1458 	cb->contact_z_min = contact_z_min;
1459 	cb->contact_z_max = contact_z_max;
1460 	if(cb->contact_z_min > cb->contact_z_max)
1461 	{
1462 	    float d = cb->contact_z_min;
1463 
1464 	    cb->contact_z_min = cb->contact_z_max;
1465 	    cb->contact_z_max = d;
1466 	}
1467 
1468 	/* Calculate trig values based on object's current heading */
1469 	cb->cos_heading = (float)cos(-obj_ptr->dir.heading);
1470 	cb->sin_heading = (float)sin(-obj_ptr->dir.heading);
1471 
1472 	return(0);
1473 }
1474 
1475 
1476 /*
1477  *	Adds an intercept to the object. Returns the allocated intercept
1478  *	index number or -1 on error.
1479  */
SARObjInterceptNew(sar_scene_struct * scene,sar_intercept_struct *** ptr,int * total,sar_obj_flags_t flags,float x,float y,float z,float radius,float urgency,const char * name)1480 int SARObjInterceptNew(
1481 	sar_scene_struct *scene,
1482 	sar_intercept_struct ***ptr, int *total,
1483 	sar_obj_flags_t flags,
1484 	float x, float y, float z,
1485 	float radius,
1486 	float urgency,
1487 	const char *name
1488 )
1489 {
1490 	int n;
1491 	sar_intercept_struct *intercept_ptr;
1492 
1493 
1494 	if((ptr == NULL) || (total == NULL))
1495 	    return(-1);
1496 
1497 	/* Append intercept */
1498 	n = MAX(*total, 0);
1499 	*total = n + 1;
1500 	*ptr = (sar_intercept_struct **)realloc(
1501 	    *ptr,
1502 	    (*total) * sizeof(sar_intercept_struct *)
1503 	);
1504 	if(*ptr == NULL)
1505 	{
1506 	    *total = 0;
1507 	    return(-1);
1508 	}
1509 
1510 	/* Allocate structure */
1511 	(*ptr)[n] = intercept_ptr = (sar_intercept_struct *)calloc(
1512 	    1, sizeof(sar_intercept_struct)
1513 	);
1514 	if(intercept_ptr == NULL)
1515 	    return(-1);
1516 
1517 	/* Set values */
1518 	intercept_ptr->flags = flags;
1519 	intercept_ptr->x = x;
1520 	intercept_ptr->y = y;
1521 	intercept_ptr->z = z;
1522 	intercept_ptr->radius = (float)MAX(radius, 0.0);
1523 	intercept_ptr->urgency = (float)CLIP(urgency, 0.0, 1.0);
1524 	intercept_ptr->name = STRDUP(name);
1525 
1526 	return(n);
1527 }
1528 
1529 
1530 /*
1531  *	Nexus for creating a new Part in the Object Parts List.
1532  */
SARObjPartNewNexus(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total,sar_obj_part_type type)1533 static sar_obj_part_struct *SARObjPartNewNexus(
1534 	sar_scene_struct *scene,
1535 	sar_obj_part_struct ***ptr, int *total,
1536 	sar_obj_part_type type
1537 )
1538 {
1539 	int i, n;
1540 	sar_obj_part_struct *part;
1541 
1542 	if((ptr == NULL) || (total == NULL))
1543 	    return(NULL);
1544 
1545 	for(i = 0; i < *total; i++)
1546 	{
1547 	    if((*ptr)[i] == NULL)
1548 		break;
1549 	}
1550 	if(i < *total)
1551 	{
1552 	    n = i;
1553 	}
1554 	else
1555 	{
1556 	    n = MAX(*total, 0);
1557 	    *total = n + 1;
1558 
1559 	    *ptr = (sar_obj_part_struct **)realloc(
1560 		*ptr,
1561 		(*total) * sizeof(sar_obj_part_struct *)
1562 	    );
1563 	    if(*ptr == NULL)
1564 	    {
1565 		*total = 0;
1566 		return(NULL);
1567 	    }
1568 	}
1569 
1570 	(*ptr)[n] = part = (sar_obj_part_struct *)calloc(
1571 	    1, sizeof(sar_obj_part_struct)
1572 	);
1573 	if(part == NULL)
1574 	    return(NULL);
1575 
1576 	part->type = type;
1577 	part->flags = 0;
1578 	part->temperature = SAR_DEF_TEMPERATURE;
1579 
1580 	return(part);
1581 }
1582 
1583 /*
1584  *	Creates a new Part on the Object Parts List.
1585  */
SARObjPartNew(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total,sar_obj_part_type type)1586 sar_obj_part_struct *SARObjPartNew(
1587 	sar_scene_struct *scene,
1588 	sar_obj_part_struct ***ptr, int *total,
1589 	sar_obj_part_type type
1590 )
1591 {
1592 	return(SARObjPartNewNexus(
1593 	    scene, ptr, total, type
1594 	));
1595 }
1596 
1597 /*
1598  *	Creates a new Air Brake on the Object Parts List.
1599  */
SARObjAirBrakeNew(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total)1600 sar_obj_part_struct *SARObjAirBrakeNew(
1601 	sar_scene_struct *scene,
1602 	sar_obj_part_struct ***ptr, int *total
1603 )
1604 {
1605 	return(SARObjPartNewNexus(
1606 	    scene, ptr, total, SAR_OBJ_PART_TYPE_AIR_BRAKE
1607 	));
1608 }
1609 
1610 /*
1611  *	Creates a new Rescue Door on the Object Parts List.
1612  */
SARObjDoorRescueNew(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total)1613 sar_obj_part_struct *SARObjDoorRescueNew(
1614 	sar_scene_struct *scene,
1615 	sar_obj_part_struct ***ptr, int *total
1616 )
1617 {
1618 	return(SARObjPartNewNexus(
1619 	    scene, ptr, total, SAR_OBJ_PART_TYPE_DOOR_RESCUE
1620 	));
1621 }
1622 
1623 /*
1624  *	Creates a new Landing Gear on the Object Parts List.
1625  */
SARObjLandingGearNew(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total)1626 sar_obj_part_struct *SARObjLandingGearNew(
1627 	sar_scene_struct *scene,
1628 	sar_obj_part_struct ***ptr, int *total
1629 )
1630 {
1631 	return(SARObjPartNewNexus(
1632 	    scene, ptr, total, SAR_OBJ_PART_TYPE_LANDING_GEAR
1633 	));
1634 }
1635 
1636 /*
1637  *	Creates a new External Fuel Tank Object.
1638  */
SARObjExternalFuelTankNew(sar_scene_struct * scene,sar_external_fueltank_struct *** ptr,int * total)1639 int SARObjExternalFuelTankNew(
1640 	sar_scene_struct *scene,
1641 	sar_external_fueltank_struct ***ptr, int *total
1642 )
1643 {
1644 	int i, n;
1645 	sar_external_fueltank_struct *eft;
1646 
1647 	if((ptr == NULL) || (total == NULL))
1648 	    return(-1);
1649 
1650 	for(i = 0; i < (*total); i++)
1651 	{
1652 	    if((*ptr)[i] == NULL)
1653 		break;
1654 	}
1655 	if(i < *total)
1656 	{
1657 	    n = i;
1658 	}
1659 	else
1660 	{
1661 	    n = MAX(*total, 0);
1662 	    *total = (*total) + 1;
1663 
1664 	    *ptr = (sar_external_fueltank_struct **)realloc(
1665 		*ptr,
1666 		(*total) * sizeof(sar_external_fueltank_struct *)
1667 	    );
1668 	    if(*ptr == NULL)
1669 	    {
1670 		*total = 0;
1671 		return(-1);
1672 	    }
1673 	}
1674 
1675 	(*ptr)[n] = (sar_external_fueltank_struct *)calloc(
1676 	    1, sizeof(sar_external_fueltank_struct)
1677 	);
1678 	eft = (*ptr)[n];
1679 	if(eft == NULL)
1680 	    return(-1);
1681 
1682 	/* Reset values */
1683 	eft->flags = 0;
1684 
1685 	return(n);
1686 }
1687 
1688 /*
1689  *	Creates a new Rotor on the specified Object Rotors List.
1690  */
SARObjRotorNew(sar_scene_struct * scene,sar_obj_rotor_struct *** ptr,int * total)1691 int SARObjRotorNew(
1692 	sar_scene_struct *scene,
1693 	sar_obj_rotor_struct ***ptr, int *total
1694 )
1695 {
1696 	int i, n;
1697 	sar_obj_rotor_struct *rotor;
1698 
1699 	if((ptr == NULL) || (total == NULL))
1700 	    return(-1);
1701 
1702 	for(i = 0; i < *total; i++)
1703 	{
1704 	    if((*ptr)[i] == NULL)
1705 		break;
1706 	}
1707 	if(i < *total)
1708 	{
1709 	    n = i;
1710 	}
1711 	else
1712 	{
1713 	    n = MAX(*total, 0);
1714 	    *total = n + 1;
1715 
1716 	    *ptr = (sar_obj_rotor_struct **)realloc(
1717 		*ptr,
1718 		(*total) * sizeof(sar_obj_rotor_struct *)
1719 	    );
1720 	    if(*ptr == NULL)
1721 	    {
1722 		*total = 0;
1723 		return(-1);
1724 	    }
1725 	}
1726 
1727 	(*ptr)[n] = rotor = (sar_obj_rotor_struct *)calloc(
1728 	    1, sizeof(sar_obj_rotor_struct)
1729 	);
1730 	if(rotor == NULL)
1731 	    return(-1);
1732 
1733 	rotor->flags = 0;
1734 	rotor->dir.heading = (float)(0.0 * PI);
1735 	rotor->dir.pitch = (float)(0.5 * PI);
1736 	rotor->dir.bank = (float)(0.0 * PI);
1737 	rotor->blade_blur_tex_num = -1;
1738 	rotor->wash_tex_num = -1;
1739 
1740 	return(n);
1741 }
1742 
1743 /*
1744  *	Creates a new Light on the specified Object Light List.
1745  */
SARObjLightNew(sar_scene_struct * scene,sar_light_struct *** ptr,int * total)1746 sar_light_struct *SARObjLightNew(
1747 	sar_scene_struct *scene,
1748 	sar_light_struct ***ptr, int *total
1749 )
1750 {
1751 	int i, n;
1752 	sar_light_struct *light;
1753 
1754 	if((ptr == NULL) || (total == NULL))
1755 	    return(NULL);
1756 
1757 	for(i = 0; i < *total; i++)
1758 	{
1759 	    if((*ptr)[i] == NULL)
1760 		break;
1761 	}
1762 	if(i < *total)
1763 	{
1764 	    n = i;
1765 	}
1766 	else
1767 	{
1768 	    n = MAX(*total, 0);
1769 	    *total = n + 1;
1770 	    *ptr = (sar_light_struct **)realloc(
1771 		*ptr,
1772 		(*total) * sizeof(sar_light_struct *)
1773 	    );
1774 	    if(*ptr == NULL)
1775 	    {
1776 		*total = 0;
1777 		return(NULL);
1778 	    }
1779 	}
1780 
1781 	(*ptr)[n] = light = (sar_light_struct *)calloc(
1782 	    1, sizeof(sar_light_struct)
1783 	);
1784 	if(light == NULL)
1785 	    return(NULL);
1786 
1787 	light->flags = 0;
1788 
1789 	return(light);
1790 }
1791 
1792 
1793 /*
1794  *	Creates a new Object on the specified Scene.
1795  */
SARObjNew(sar_scene_struct * scene,sar_object_struct *** ptr,int * total,int type)1796 int SARObjNew(
1797 	sar_scene_struct *scene,
1798 	sar_object_struct ***ptr, int *total,
1799 	int type
1800 )
1801 {
1802 	int i, n, len;
1803 	sar_object_struct *obj_ptr;
1804 
1805 	if((scene == NULL) || (ptr == NULL) || (total == NULL) ||
1806 	   (type <= SAR_OBJ_TYPE_GARBAGE)
1807 	)
1808 	    return(-1);
1809 
1810 	for(i = 0; i < *total; i++)
1811 	{
1812 	    if((*ptr)[i] == NULL)
1813 		break;
1814 
1815 	    if((*ptr)[i]->type <= SAR_OBJ_TYPE_GARBAGE)
1816 		break;
1817 	}
1818 	if(i < *total)
1819 	{
1820 	    n = i;
1821 	}
1822 	else
1823 	{
1824 	    n = MAX(*total, 0);
1825 	    (*total) = n + 1;
1826 
1827 	    *ptr = (sar_object_struct **)realloc(
1828 		*ptr,
1829 		(*total) * sizeof(sar_object_struct *)
1830 	    );
1831 	    if(*ptr == NULL)
1832 	    {
1833 		*total = 0;
1834 		return(-1);
1835 	    }
1836 
1837 	    (*ptr)[n] = NULL;
1838 	}
1839 
1840 	/* Allocate object structure as needed */
1841 	if((*ptr)[n] == NULL)
1842 	{
1843 	    (*ptr)[n] = (sar_object_struct *)calloc(
1844 		1, sizeof(sar_object_struct)
1845 	    );
1846 	    if((*ptr)[n] == NULL)
1847 		return(-1);
1848 	}
1849 
1850 	obj_ptr = (*ptr)[n];
1851 
1852 
1853 	/* Set object type */
1854 	obj_ptr->type = type;
1855 
1856 	obj_ptr->temperature = SAR_DEF_TEMPERATURE;
1857 
1858 	/* Mark birth time */
1859 	obj_ptr->birth_time_ms = cur_millitime;
1860 	obj_ptr->birth_time_sec = cur_systime;
1861 
1862 	/* Allocate substructure by the Object's type */
1863 	switch(type)
1864 	{
1865 	  case SAR_OBJ_TYPE_GARBAGE:
1866 	    len = 0;
1867 	    break;
1868 	  case SAR_OBJ_TYPE_STATIC:
1869 	    len = 0;
1870 	    break;
1871 	  case SAR_OBJ_TYPE_AUTOMOBILE:
1872 	    len = 0;
1873 	    break;
1874 	  case SAR_OBJ_TYPE_WATERCRAFT:
1875 	    len = 0;
1876 	    break;
1877 	  case SAR_OBJ_TYPE_AIRCRAFT:
1878 	    len = sizeof(sar_object_aircraft_struct);
1879 	    break;
1880 	  case SAR_OBJ_TYPE_GROUND:
1881 	    len = sizeof(sar_object_ground_struct);
1882 	    break;
1883 	  case SAR_OBJ_TYPE_RUNWAY:
1884 	    len = sizeof(sar_object_runway_struct);
1885 	    break;
1886 	  case SAR_OBJ_TYPE_HELIPAD:
1887 	    len = sizeof(sar_object_helipad_struct);
1888 	    break;
1889 	  case SAR_OBJ_TYPE_HUMAN:
1890 	    len = sizeof(sar_object_human_struct);
1891 	    break;
1892 	  case SAR_OBJ_TYPE_SMOKE:
1893 	    len = sizeof(sar_object_smoke_struct);
1894 	    break;
1895 	  case SAR_OBJ_TYPE_FIRE:
1896 	    len = sizeof(sar_object_fire_struct);;
1897 	    break;
1898 	  case SAR_OBJ_TYPE_EXPLOSION:
1899 	    len = sizeof(sar_object_explosion_struct);
1900 	    break;
1901 	  case SAR_OBJ_TYPE_FUELTANK:
1902 	    len = sizeof(sar_object_fueltank_struct);
1903 	    break;
1904 	  case SAR_OBJ_TYPE_PREMODELED:
1905 	    len = sizeof(sar_object_premodeled_struct);
1906 	    break;
1907 	  default:
1908 	    len = 0;
1909 	    break;
1910 	}
1911 
1912 	/* If size of substructure is positive then allocate it */
1913 	if(len > 0)
1914 	    obj_ptr->data = calloc(1, len);
1915 	else
1916 	    obj_ptr->data = NULL;
1917 
1918 
1919 	/* If object type is SAR_OBJ_TYPE_GROUND, then add it to the
1920 	 * scene's list of ground objects
1921 	 */
1922 	if((scene != NULL) &&
1923 	   (obj_ptr->type == SAR_OBJ_TYPE_GROUND)
1924 	)
1925 	    SARObjAddToGroundList(scene, obj_ptr);
1926 
1927 
1928 	return(n);
1929 }
1930 
1931 
1932 /*
1933  *	Deletes all intercept structures in the given array.
1934  */
SARObjDeleteIntercepts(sar_scene_struct * scene,sar_intercept_struct *** ptr,int * total)1935 void SARObjDeleteIntercepts(
1936 	sar_scene_struct *scene,
1937 	sar_intercept_struct ***ptr, int *total
1938 )
1939 {
1940 	int i;
1941 	sar_intercept_struct *intercept_ptr;
1942 
1943 
1944 	if((ptr == NULL) || (total == NULL))
1945 	    return;
1946 
1947 	for(i = 0; i < (*total); i++)
1948 	{
1949 	    intercept_ptr = (*ptr)[i];
1950 	    if(intercept_ptr == NULL)
1951 		continue;
1952 
1953 	    free(intercept_ptr->name);
1954 	    free(intercept_ptr);
1955 	}
1956 
1957 	free(*ptr);
1958 	(*ptr) = NULL;
1959 	(*total) = 0;
1960 }
1961 
1962 /*
1963  *	Deletes all structures and resources in the array of light
1964  *	structures.
1965  */
SARObjDeleteLights(sar_scene_struct * scene,sar_light_struct *** ptr,int * total)1966 void SARObjDeleteLights(
1967 	sar_scene_struct *scene,
1968 	sar_light_struct ***ptr, int *total
1969 )
1970 {
1971 	int i;
1972 	sar_light_struct *light;
1973 
1974 
1975 	if((ptr == NULL) || (total == NULL))
1976 	    return;
1977 
1978 	for(i = 0; i < *total; i++)
1979 	{
1980 	    light = (*ptr)[i];
1981 	    if(light == NULL)
1982 		continue;
1983 
1984 	    free(light);
1985 	}
1986 
1987 	free(*ptr);
1988 	*ptr = NULL;
1989 	*total = 0;
1990 }
1991 
1992 
1993 /*
1994  *	Delete the list of object parts.
1995  */
SARObjDeleteParts(sar_scene_struct * scene,sar_obj_part_struct *** ptr,int * total)1996 void SARObjDeleteParts(
1997 	sar_scene_struct *scene,
1998 	sar_obj_part_struct ***ptr, int *total
1999 )
2000 {
2001 	int i;
2002 	sar_obj_part_struct *part;
2003 
2004 	if((ptr == NULL) || (total == NULL))
2005 	    return;
2006 
2007 	for(i = 0; i < *total; i++)
2008 	{
2009 	    part = (*ptr)[i];
2010 	    if(part == NULL)
2011 		continue;
2012 
2013 	    SARVisualModelUnref(scene, part->visual_model);
2014 	    SARVisualModelUnref(scene, part->visual_model_ir);
2015 	    free(part);
2016 	}
2017 
2018 	free(*ptr);
2019 	(*ptr) = NULL;
2020 	(*total) = 0;
2021 }
2022 
2023 
2024 /*
2025  *	Deletes the list of external fuel tanks.
2026  */
SARObjDeleteExternalFuelTanks(sar_scene_struct * scene,sar_external_fueltank_struct *** ptr,int * total)2027 void SARObjDeleteExternalFuelTanks(
2028 	sar_scene_struct *scene,
2029 	sar_external_fueltank_struct ***ptr, int *total
2030 )
2031 {
2032 	int i;
2033 	sar_external_fueltank_struct *eft;
2034 
2035 	for(i = 0; i < (*total); i++)
2036 	{
2037 	    eft = (*ptr)[i];
2038 	    if(eft == NULL)
2039 		continue;
2040 
2041 	    SARVisualModelUnref(scene, eft->visual_model);
2042 	    SARVisualModelUnref(scene, eft->visual_model_ir);
2043 	    free(eft);
2044 	}
2045 
2046 	free(*ptr);
2047 	(*ptr) = NULL;
2048 
2049 	(*total) = 0;
2050 }
2051 
2052 /*
2053  *      Deletes all structures and resources in the array of landing
2054  *      gear structures.
2055  */
SARObjDeleteRotors(sar_scene_struct * scene,sar_obj_rotor_struct *** ptr,int * total)2056 void SARObjDeleteRotors(
2057 	sar_scene_struct *scene,
2058 	sar_obj_rotor_struct ***ptr, int *total
2059 )
2060 {
2061 	int i;
2062 	sar_obj_rotor_struct *rotor;
2063 
2064 	if((ptr == NULL) || (total == NULL))
2065 	    return;
2066 
2067 	for(i = 0; i < *total; i++)
2068 	{
2069 	    rotor = (*ptr)[i];
2070 	    if(rotor == NULL)
2071 		continue;
2072 
2073 	    SARVisualModelUnref(scene, rotor->visual_model);
2074 	    SARVisualModelUnref(scene, rotor->visual_model_ir);
2075 	    free(rotor);
2076 	}
2077 
2078 	free(*ptr);
2079 	*ptr = NULL;
2080 	*total = 0;
2081 }
2082 
2083 /*
2084  *	Deletes object n from the array, setting it to NULL.
2085  */
SARObjDelete(void * core_ptr,sar_object_struct *** ptr,int * total,int n)2086 void SARObjDelete(
2087 	void *core_ptr,
2088 	sar_object_struct ***ptr, int *total, int n
2089 )
2090 {
2091 	sar_core_struct *cp = core_ptr;
2092 	sar_scene_struct *scene;
2093 	snd_recorder_struct *recorder;
2094 
2095 	if(cp == NULL)
2096 	    return;
2097 
2098 	scene = cp->scene;
2099 	if(scene == NULL)
2100 	{
2101 	    fprintf(
2102 		stderr,
2103 		"SARObjDelete(): Error: Scene is NULL.\n"
2104 	    );
2105 	    return;
2106 	}
2107 
2108 	recorder = cp->recorder;
2109 
2110 	if(SARObjIsAllocated(*ptr, *total, n))
2111 	{
2112 	    int i;
2113 	    sar_object_struct *obj_ptr, *obj_ptr2;
2114 	    sar_object_aircraft_struct *aircraft;
2115 	    sar_object_runway_struct *runway;
2116 	    sar_object_helipad_struct *helipad;
2117 	    sar_object_ground_struct *ground;
2118 	    sar_object_smoke_struct *smoke;
2119 	    sar_object_explosion_struct *explosion;
2120 	    sar_object_fire_struct *fire;
2121 	    sar_object_chemical_spray_struct *chemical_spray;
2122 	    sar_object_fueltank_struct *fueltank;
2123 	    sar_object_human_struct *human;
2124 	    sar_object_premodeled_struct *premodeled;
2125 
2126 
2127 	    obj_ptr = (*ptr)[n];
2128 
2129 #define VISUAL_MODEL_UNREF(_vm_)	\
2130  SARVisualModelUnref(scene, (_vm_))
2131 
2132 #define SOUND_STOP_PLAY(_sp_)		\
2133  SoundStopPlay(recorder, (_sp_))
2134 
2135 	    /* Delete substructure */
2136 	    if(obj_ptr->data != NULL)
2137 	    {
2138 		switch(obj_ptr->type)
2139 		{
2140 		  case SAR_OBJ_TYPE_GARBAGE:
2141 		  case SAR_OBJ_TYPE_STATIC:
2142 		  case SAR_OBJ_TYPE_AUTOMOBILE:
2143 		  case SAR_OBJ_TYPE_WATERCRAFT:
2144 		    break;
2145 		  case SAR_OBJ_TYPE_AIRCRAFT:
2146 		    aircraft = SAR_OBJ_GET_AIRCRAFT(obj_ptr);
2147 		    if(aircraft != NULL)
2148 		    {
2149 			sar_obj_hoist_struct *hoist;
2150 
2151 		        /* Engine sound play object and source index */
2152 		        SOUND_STOP_PLAY(aircraft->engine_inside_sndplay);
2153 		        aircraft->engine_inside_sndsrc = -1;
2154 
2155 		        SOUND_STOP_PLAY(aircraft->engine_outside_sndplay);
2156 		        aircraft->engine_outside_sndsrc = -1;
2157 
2158 			/* Repeating warning sound play object and source index */
2159 			SOUND_STOP_PLAY(aircraft->stall_sndplay);
2160 			aircraft->stall_sndsrc = -1;
2161 
2162 			SOUND_STOP_PLAY(aircraft->overspeed_sndplay);
2163 			aircraft->overspeed_sndsrc = -1;
2164 
2165 			/* Cockpit visual model */
2166 			VISUAL_MODEL_UNREF(aircraft->visual_model_cockpit);
2167 
2168 			/* Delete all parts and their visual models */
2169 			SARObjDeleteParts(
2170 			    scene, &aircraft->part, &aircraft->total_parts
2171 			);
2172 
2173 			/* Delete all rotors and their visual models */
2174 			SARObjDeleteRotors(
2175 			    scene, &aircraft->rotor, &aircraft->total_rotors
2176 			);
2177 
2178 			/* Delete all external fuel tanks and their visual models */
2179 			SARObjDeleteExternalFuelTanks(
2180 			    scene,
2181 			    &aircraft->external_fueltank,
2182 			    &aircraft->total_external_fueltanks
2183 			);
2184 
2185 			/* Delete hoist */
2186 			hoist = aircraft->hoist;
2187 		        if(hoist != NULL)
2188 		        {
2189 			    free(hoist->occupant);
2190 			    free(hoist);
2191 			    aircraft->hoist = NULL;
2192 		        }
2193 
2194 		        /* Delete all way pointer intercepts */
2195 		        SARObjDeleteIntercepts(
2196 			    scene,
2197 			    &aircraft->intercept,
2198 			    &aircraft->total_intercepts
2199 		        );
2200 
2201 		        /* Flight dynamics model */
2202 		        if((scene->realm != NULL) &&
2203 		           (aircraft->fdm != NULL)
2204 		        )
2205 		        {
2206 			    SFMModelDelete(scene->realm, aircraft->fdm);
2207 #if 0
2208 			    /* SFM fdm destroy callback will call our
2209 			     * callback function to set this pointer to
2210 			     * NULL
2211 			     */
2212 			    aircraft->fdm = NULL;
2213 #endif
2214 			}
2215 		    }
2216 		    break;
2217 		  case SAR_OBJ_TYPE_GROUND:
2218 		    ground = SAR_OBJ_GET_GROUND(obj_ptr);
2219 		    if(ground != NULL)
2220 		    {
2221 		        /* Heightfield z points map */
2222 		        free(ground->z_point_value);
2223 		        ground->z_point_value = NULL;
2224 
2225 		        ground->grid_points_x = 0;
2226 		        ground->grid_points_y = 0;
2227 		        ground->grid_points_total = 0;
2228 		    }
2229 		    break;
2230 	          case SAR_OBJ_TYPE_RUNWAY:
2231 		    runway = SAR_OBJ_GET_RUNWAY(obj_ptr);
2232 		    if(runway != NULL)
2233 		    {
2234 		        free(runway->north_label);
2235 		        free(runway->south_label);
2236 		        VISUAL_MODEL_UNREF(runway->north_label_vmodel);
2237 		        VISUAL_MODEL_UNREF(runway->south_label_vmodel);
2238 		        VISUAL_MODEL_UNREF(runway->threshold_vmodel);
2239 		        VISUAL_MODEL_UNREF(runway->td_marker_vmodel);
2240 		        VISUAL_MODEL_UNREF(runway->midway_marker_vmodel);
2241 		        VISUAL_MODEL_UNREF(
2242 			    runway->north_displaced_threshold_vmodel
2243 		        );
2244 		        VISUAL_MODEL_UNREF(
2245 			    runway->south_displaced_threshold_vmodel
2246 		        );
2247 		    }
2248 		    break;
2249 		  case SAR_OBJ_TYPE_HELIPAD:
2250 		    helipad = SAR_OBJ_GET_HELIPAD(obj_ptr);
2251 		    if(helipad != NULL)
2252 		    {
2253 		        free(helipad->label);
2254 		        VISUAL_MODEL_UNREF(helipad->label_vmodel);
2255 		    }
2256 		    break;
2257 		  case SAR_OBJ_TYPE_HUMAN:
2258 		    human = SAR_OBJ_GET_HUMAN(obj_ptr);
2259 		    if(human != NULL)
2260 		    {
2261 			free(human->mesg_enter);
2262 		    }
2263 		    break;
2264 		  case SAR_OBJ_TYPE_SMOKE:
2265 		    smoke = SAR_OBJ_GET_SMOKE(obj_ptr);
2266 		    if(smoke != NULL)
2267 		    {
2268 		        free(smoke->unit);
2269 		        smoke->unit = NULL;
2270 		        smoke->total_units = 0;
2271 		    }
2272 		    break;
2273 		  case SAR_OBJ_TYPE_FIRE:
2274 		    fire = SAR_OBJ_GET_FIRE(obj_ptr);
2275 		    if(fire != NULL)
2276 		    {
2277 
2278 		    }
2279 		    break;
2280 		  case SAR_OBJ_TYPE_EXPLOSION:
2281 		    explosion = SAR_OBJ_GET_EXPLOSION(obj_ptr);
2282 		    if(explosion != NULL)
2283 		    {
2284 
2285 		    }
2286 		    break;
2287 		  case SAR_OBJ_TYPE_CHEMICAL_SPRAY:
2288 		    chemical_spray = SAR_OBJ_GET_CHEMICAL_SPRAY(obj_ptr);
2289 		    if(chemical_spray != NULL)
2290 		    {
2291 		        chemical_spray->owner = -1;
2292 		        chemical_spray->tex_num = -1;
2293 		    }
2294 		    break;
2295 		  case SAR_OBJ_TYPE_FUELTANK:
2296 		    fueltank = SAR_OBJ_GET_FUELTANK(obj_ptr);
2297 		    if(fueltank != NULL)
2298 		    {
2299 
2300 		    }
2301 		    break;
2302 		  case SAR_OBJ_TYPE_PREMODELED:
2303 		    premodeled = SAR_OBJ_GET_PREMODELED(obj_ptr);
2304 		    if(premodeled != NULL)
2305 		    {
2306 
2307 		    }
2308 		    break;
2309 		}
2310 
2311 		free(obj_ptr->data);
2312 		obj_ptr->data = NULL;
2313 	    }
2314 
2315 	    /* Delete standard visual models */
2316 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_shadow);
2317 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_night);
2318 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_dusk);
2319 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_dawn);
2320 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_far);
2321 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model_ir);
2322 	    VISUAL_MODEL_UNREF(obj_ptr->visual_model);
2323 
2324 	    /* Delete contact bounds */
2325 	    if(obj_ptr->contact_bounds != NULL)
2326 	    {
2327 		free(obj_ptr->contact_bounds);
2328 		obj_ptr->contact_bounds = NULL;
2329 	    }
2330 
2331 	    /* Delete lights */
2332 	    SARObjDeleteLights(
2333 		scene,
2334 		&obj_ptr->light, &obj_ptr->total_lights
2335 	    );
2336 
2337 	    /* Delete sound sources */
2338 	    for(i = 0; i < obj_ptr->total_sndsrcs; i++)
2339 		SARSoundSourceDelete(obj_ptr->sndsrc[i]);
2340 	    free(obj_ptr->sndsrc);
2341 	    obj_ptr->sndsrc = NULL;
2342 	    obj_ptr->total_sndsrcs = 0;
2343 
2344 
2345 	    /* Delete name */
2346 	    free(obj_ptr->name);
2347 	    obj_ptr->name = NULL;
2348 
2349 	    /* Delete the Object itself */
2350 	    free(obj_ptr);
2351 	    (*ptr)[n] = NULL;
2352 
2353 
2354 	    /* Object has now been deleted, now we need to check if
2355 	     * any other objects are referencing this object
2356 	     *
2357 	     * If so, then we need to reset those references
2358 	     */
2359 	    for(i = 0; i < *total; i++)
2360 	    {
2361 		obj_ptr2 = (*ptr)[i];
2362 		if(obj_ptr2 == NULL)
2363 		    continue;
2364 
2365 		/* Skip this object */
2366 		if(i == n)
2367 		    continue;
2368 
2369 		switch(obj_ptr2->type)
2370 		{
2371 		  case SAR_OBJ_TYPE_GARBAGE:
2372 		  case SAR_OBJ_TYPE_STATIC:
2373 		  case SAR_OBJ_TYPE_AUTOMOBILE:
2374 		  case SAR_OBJ_TYPE_WATERCRAFT:
2375 		  case SAR_OBJ_TYPE_AIRCRAFT:
2376 		  case SAR_OBJ_TYPE_GROUND:
2377 		  case SAR_OBJ_TYPE_RUNWAY:
2378 		    break;
2379 		  case SAR_OBJ_TYPE_HELIPAD:
2380 		    helipad = SAR_OBJ_GET_HELIPAD(obj_ptr2);
2381 		    if(helipad != NULL)
2382 		    {
2383 			if(helipad->ref_object == n)
2384 			    helipad->ref_object = -1;
2385 		    }
2386 		    break;
2387 		  case SAR_OBJ_TYPE_HUMAN:
2388 		    human = SAR_OBJ_GET_HUMAN(obj_ptr2);
2389 		    if(human != NULL)
2390 		    {
2391 			if(human->intercepting_object == n)
2392 			    human->intercepting_object = -1;
2393 		    }
2394 		    break;
2395 		  case SAR_OBJ_TYPE_SMOKE:
2396 		    smoke = SAR_OBJ_GET_SMOKE(obj_ptr2);
2397 		    if(smoke != NULL)
2398 		    {
2399 			if(smoke->ref_object == n)
2400 			    smoke->ref_object = -1;
2401 		    }
2402 		    break;
2403 		  case SAR_OBJ_TYPE_FIRE:
2404 		    fire = SAR_OBJ_GET_FIRE(obj_ptr2);
2405 		    if(fire != NULL)
2406 		    {
2407 			if(fire->ref_object == n)
2408 			    fire->ref_object = -1;
2409 		    }
2410 		    break;
2411 		  case SAR_OBJ_TYPE_EXPLOSION:
2412 		    explosion = SAR_OBJ_GET_EXPLOSION(obj_ptr2);
2413 		    if(explosion != NULL)
2414 		    {
2415 			if(explosion->ref_object == n)
2416 			    explosion->ref_object = -1;
2417 		    }
2418 		    break;
2419 		  case SAR_OBJ_TYPE_CHEMICAL_SPRAY:
2420 		    chemical_spray = SAR_OBJ_GET_CHEMICAL_SPRAY(obj_ptr2);
2421 		    if(chemical_spray != NULL)
2422 		    {
2423 			if(chemical_spray->owner == n)
2424 			    chemical_spray->owner = -1;
2425 		    }
2426 		    break;
2427 		  case SAR_OBJ_TYPE_FUELTANK:
2428 		    fueltank = SAR_OBJ_GET_FUELTANK(obj_ptr2);
2429 		    if(fueltank != NULL)
2430 		    {
2431 			if(fueltank->ref_object == n)
2432 			    fueltank->ref_object = -1;
2433 		    }
2434 		    break;
2435 		  case SAR_OBJ_TYPE_PREMODELED:
2436 		    break;
2437 		}
2438 	    }
2439 
2440 	    /* Unreference this object from the scene structure so that
2441 	     * no other resources check the scene structure and mistake
2442 	     * the object as still being allocated
2443 	     */
2444 	    if(scene != NULL)
2445 	    {
2446 		/* Was this referenced as the player object? */
2447 		if(obj_ptr == scene->player_obj_ptr)
2448 		    scene->player_obj_ptr = NULL;
2449 
2450 		if(n == scene->player_obj_num)
2451 		    scene->player_obj_num = -1;
2452 
2453 		/* Was this referenced as the camera target? */
2454 		if(n == scene->camera_target)
2455 		    scene->camera_target = -1;
2456 
2457 		/* Remove this object from ground list as needed */
2458 		SARObjRemoveFromGroundList(scene, obj_ptr);
2459 
2460 		/* Remove this object from human need rescue list as needed */
2461 		SARObjRemoveFromHumanRescueList(scene, obj_ptr);
2462 	    }
2463 
2464 #undef VISUAL_MODEL_UNREF
2465 #undef SOUND_STOP_PLAY
2466 	}
2467 }
2468 
2469 /*
2470  *	Generates an array of tiles. The call to begin a list and
2471  *	set up color and texture should already have been made before
2472  *	calling this function.
2473  */
SARObjGenerateTilePlane(float min,float max,float tile_width,float tile_height)2474 void SARObjGenerateTilePlane(
2475 	float min, float max,	/* In meters */
2476 	float tile_width, float tile_height
2477 )
2478 {
2479 	float x, y, x2, y2;
2480 
2481 
2482 	/* Begin gl instructions */
2483 	glBegin(GL_QUADS);
2484 
2485 	/* Quadrant 1 is `upper right' and quadrants are numbed
2486 	 * clockwise.
2487 	 */
2488 
2489 	/* Quads in quadrant 1 */
2490 	for(y = 0; y < max; y += tile_height)
2491 	{
2492 	    for(x = 0; x < max; x += tile_width)
2493 	    {
2494 		x2 = x + tile_width;
2495 		y2 = y + tile_height;
2496 		{
2497 		    glNormal3f(0.0f, 1.0f, 0.0f);
2498 		    glTexCoord2f(0.0f, 1.0f - 0.0f);
2499 		    glVertex3f((GLfloat)x, (GLfloat)0.0f, (GLfloat)-y);
2500 		    glTexCoord2f(1.0f, 1.0f - 0.0f);
2501 		    glVertex3f((GLfloat)x2, (GLfloat)0.0f, (GLfloat)-y);
2502 		    glTexCoord2f(1.0f, 1.0f - 1.0f);
2503 		    glVertex3f((GLfloat)x2, (GLfloat)0.0f, (GLfloat)-y2);
2504 		    glTexCoord2f(0.0f, 1.0f - 1.0f);
2505 		    glVertex3f((GLfloat)x, (GLfloat)0.0f, (GLfloat)-y2);
2506 		}
2507 	    }
2508 	}
2509 	/* Quads in quadrant 2 */
2510 	for(y = 0; y > min; y -= tile_height)
2511 	{
2512 	    for(x = 0; x < max; x += tile_width)
2513 	    {
2514 		x2 = x + tile_width;
2515 		y2 = y - tile_height;
2516 		{
2517 		    glNormal3f(0.0f, 1.0f, 0.0f);
2518 		    glTexCoord2f(0.0f, 1.0f - 0.0f);
2519 		    glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y2);
2520 		    glTexCoord2f(1.0f, 1.0f - 0.0f);
2521 		    glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y2);
2522 		    glTexCoord2f(1.0f, 1.0f - 1.0f);
2523 		    glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y);
2524 		    glTexCoord2f(0.0f, 1.0f - 1.0f);
2525 		    glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y);
2526 	       }
2527 	   }
2528        }
2529        /* Quads in quadrant 3 */
2530        for(y = 0; y > min; y -= tile_height)
2531        {
2532 	   for(x = 0; x > min; x -= tile_width)
2533 	   {
2534 	       x2 = x - tile_width;
2535 	       y2 = y - tile_height;
2536 	       {
2537 		   glNormal3f(0.0f, 1.0f, 0.0f);
2538 		   glTexCoord2f(1.0f, 1.0f - 1.0f);
2539 		   glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y);
2540 		   glTexCoord2f(0.0f, 1.0f - 1.0f);
2541 		   glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y);
2542 		   glTexCoord2f(0.0f, 1.0f - 0.0f);
2543 		   glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y2);
2544 		   glTexCoord2f(1.0f, 1.0f - 0.0f);
2545 		   glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y2);
2546 	       }
2547 	    }
2548 	}
2549 	/* Quads in quadrant 4 */
2550 	for(y = 0; y < max; y += tile_height)
2551 	{
2552 	    for(x = 0; x > min; x -= tile_width)
2553 	    {
2554 		x2 = x - tile_width;
2555 		y2 = y + tile_height;
2556 		{
2557 		   glNormal3f(0.0f, 1.0f, 0.0f);
2558 		   glTexCoord2f(1.0f, 1.0f - 1.0f);
2559 		   glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y2);
2560 		   glTexCoord2f(0.0f, 1.0f - 1.0f);
2561 		   glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y2);
2562 		   glTexCoord2f(0.0f, 1.0f - 0.0f);
2563 		   glVertex3f((GLfloat)x2, 0.0f, (GLfloat)-y);
2564 		   glTexCoord2f(1.0f, 1.0f - 0.0f);
2565 		   glVertex3f((GLfloat)x, 0.0f, (GLfloat)-y);
2566 		}
2567 	    }
2568 	}
2569 	glEnd();
2570 }
2571