File: model.h

package info (click to toggle)
freespace2 3.7.4%2Brepack-1.1
  • links: PTS, VCS
  • area: non-free
  • in suites: bullseye
  • size: 22,268 kB
  • sloc: cpp: 393,535; ansic: 4,106; makefile: 1,091; xml: 181; sh: 137
file content (1405 lines) | stat: -rw-r--r-- 63,553 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/ 



#ifndef _MODEL_H
#define _MODEL_H

#include "globalincs/globals.h"	// for NAME_LENGTH
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "object/object.h"

class object;
class model_render_params;

extern flag_def_list model_render_flags[];
extern int model_render_flags_size;

#define MAX_DEBRIS_OBJECTS	32
#define MAX_MODEL_DETAIL_LEVELS	8
#define MAX_PROP_LEN			256
#define MAX_NAME_LEN			32
#define MAX_ARC_EFFECTS		8

#define MOVEMENT_TYPE_NONE				-1
#define MOVEMENT_TYPE_POS				0
#define MOVEMENT_TYPE_ROT				1
#define MOVEMENT_TYPE_ROT_SPECIAL		2	// for turrets only
#define MOVEMENT_TYPE_TRIGGERED			3	// triggered rotation
#define MOVEMENT_TYPE_INTRINSIC_ROTATE	4	// intrinsic (non-subsystem-based) rotation
#define MOVEMENT_TYPE_LOOK_AT			5	// the subobject is always looking at a 'look at' subobject, as best it can - Bobboau


// DA 11/13/98 Reordered to account for difference between max and game
#define MOVEMENT_AXIS_NONE	-1
#define MOVEMENT_AXIS_X		0
#define MOVEMENT_AXIS_Y		2
#define MOVEMENT_AXIS_Z		1

// defines for special objects like gun and missile points, docking point, etc
// Hoffoss: Please make sure that subsystem NONE is always index 0, and UNKNOWN is
// always the last subsystem in the list.  Also, make sure that MAX is correct.
// Otherwise, problems will arise in Fred.

#define SUBSYSTEM_NONE				0
#define SUBSYSTEM_ENGINE			1
#define SUBSYSTEM_TURRET			2
#define SUBSYSTEM_RADAR				3
#define SUBSYSTEM_NAVIGATION		4
#define SUBSYSTEM_COMMUNICATION	5
#define SUBSYSTEM_WEAPONS			6
#define SUBSYSTEM_SENSORS			7
#define SUBSYSTEM_SOLAR				8
#define SUBSYSTEM_GAS_COLLECT		9
#define SUBSYSTEM_ACTIVATION		10
#define SUBSYSTEM_UNKNOWN			11
#define SUBSYSTEM_MAX				12				//	maximum value for subsystem_xxx, for error checking

// Goober5000
extern char *Subsystem_types[SUBSYSTEM_MAX];

#define MAX_TFP						10				// maximum number of turret firing points

#define MAX_SPLIT_PLANE				5				// number of artist specified split planes (used in big ship explosions)

// Data specific to a particular instance of a submodel.  This gets stuffed/unstuffed using
// the model_clear_instance, model_set_instance, model_get_instance functions.
typedef struct submodel_instance_info {
	int		blown_off;								// If set, this subobject is blown off
	angles	angs;										// The current angle this thing is turned to.
	angles	prev_angs;
	vec3d	pt_on_axis;								// in ship RF
	float		cur_turn_rate;
	float		desired_turn_rate;
	float		turn_accel;
	int		axis_set;
	int		step_zero_timestamp;		// timestamp determines when next step is to begin (for stepped rotation)
} submodel_instance_info;

typedef struct submodel_instance {
	angles angs;
	angles prev_angs;
	vec3d mc_base;
	matrix mc_orient;
	bool collision_checked;
	bool blown_off;
	submodel_instance_info *sii;
} submodel_instance;

// Data specific to a particular instance of a model.
typedef struct polymodel_instance {
	int model_num;					// global model num index, same as polymodel->id
	submodel_instance *submodel;	// array of submodel instances; mirrors the polymodel->submodel array
} polymodel_instance;

#define MAX_MODEL_SUBSYSTEMS		200				// used in ships.cpp (only place?) for local stack variable DTP; bumped to 200
													// when reading in ships.tbl

#define MSS_FLAG_ROTATES			(1 << 0)		// This means the object rotates automatically with "turn_rate"
#define MSS_FLAG_STEPPED_ROTATE		(1 << 1)		// This means that the rotation occurs in steps
#define MSS_FLAG_AI_ROTATE			(1 << 2)		// This means that the rotation is controlled by ai
#define MSS_FLAG_CREWPOINT			(1 << 3)		// If set, this is a crew point.
#define MSS_FLAG_TURRET_MATRIX		(1 << 4)		// If set, this has it's turret matrix created correctly.
#define MSS_FLAG_AWACS				(1 << 5)		// If set, this subsystem has AWACS capability
#define MSS_FLAG_ARTILLERY			(1 << 6)		// if this rotates when weapons are fired - Goober5000
#define MSS_FLAG_TRIGGERED			(1 << 7)		// rotates when triggered by something
#define MSS_FLAG_UNTARGETABLE		(1 << 8)		// Goober5000
#define MSS_FLAG_CARRY_NO_DAMAGE	(1 << 9)		// WMC
#define MSS_FLAG_USE_MULTIPLE_GUNS	(1 << 10)		// WMC
#define MSS_FLAG_FIRE_ON_NORMAL		(1 << 11)		// forces a turret to fire down its normal vecs
#define MSS_FLAG_TURRET_HULL_CHECK	(1 << 12)		// makes the turret check to see if it's going to shoot through it's own hull before fireing - Bobboau
#define MSS_FLAG_TURRET_FIXED_FP	(1 << 13)		// forces turret (when defined with multiple weapons) to prevent the firepoints from alternating
#define MSS_FLAG_TURRET_SALVO		(1 << 14)		// forces turret to fire salvos (all guns simultaneously) - independent targeting
#define MSS_FLAG_FIRE_ON_TARGET		(1 << 15)		// prevents turret from firing unless it is pointing at the firingpoints are pointing at the target
#define MSS_FLAG_NO_SS_TARGETING	(1 << 16)		// toggles the subsystem targeting for the turret
#define MSS_FLAG_TURRET_RESET_IDLE	(1 << 17)		// makes turret reset to their initial position if the target is out of field of view
#define MSS_FLAG_TURRET_ALT_MATH	(1 << 18)		// tells the game to use additional calculations should turret have a defined y fov
#define MSS_FLAG_CARRY_SHOCKWAVE	(1 << 19)		// subsystem - even with 'carry no damage' flag - will carry shockwave damage to the hull
#define MSS_FLAG_ALLOW_LANDING		(1 << 20)		// This subsystem can be landed on
#define MSS_FLAG_FOV_EDGE_CHECK		(1 << 21)		// Tells the game to use better FOV edge checking with this turret
#define MSS_FLAG_FOV_REQUIRED		(1 << 22)		// Tells game not to allow this turret to attempt targeting objects out of FOV
#define MSS_FLAG_NO_REPLACE			(1 << 23)		// set the subsys not to draw replacement ('destroyed') model
#define MSS_FLAG_NO_LIVE_DEBRIS		(1 << 24)		// sets the subsys not to release live debris
#define MSS_FLAG_IGNORE_IF_DEAD		(1 << 25)		// tells homing missiles to ignore the subsys if its dead and home on to hull instead of earlier subsys pos
#define MSS_FLAG_ALLOW_VANISHING	(1 << 26)		// allows subsystem to vanish (prevents explosions & sounds effects from being played)
#define MSS_FLAG_DAMAGE_AS_HULL		(1 << 27)		// applies armor damage to subsystem instead of subsystem damage - FUBAR
#define MSS_FLAG_TURRET_LOCKED      (1 << 28)       // Turret starts locked by default - Sushi
#define MSS_FLAG_NO_AGGREGATE		(1 << 29)		// Don't include with aggregate subsystem types - Goober5000
#define MSS_FLAG_TURRET_ANIM_WAIT   (1 << 30)		// Turret won't fire until animation is complete - Sushi

#define MSS_FLAG2_PLAYER_TURRET_SOUND			 (1 << 0)
#define MSS_FLAG2_TURRET_ONLY_TARGET_IF_CAN_FIRE (1 << 1)	// Turrets only target things they're allowed to shoot at (e.g. if check-hull fails, won't keep targeting)
#define MSS_FLAG2_NO_DISAPPEAR					 (1 << 2)	// Submodel won't disappear when subsystem destroyed
#define MSS_FLAG2_COLLIDE_SUBMODEL				 (1 << 3)	// subsystem takes damage only from hits which impact the associated submodel
#define MSS_FLAG2_DESTROYED_ROTATION			 (1 << 4)   // allows subobjects to continue to rotate even if they have been destroyed
#define MSS_FLAG2_TURRET_USE_AMMO				 (1 << 5)	// enables ammo consumption for turrets (DahBlount)
#define MSS_FLAG2_AUTOREPAIR_IF_DISABLED		 (1 << 6)	// Allows the subsystem to repair itself even if disabled (MageKing17)
#define MSS_FLAG2_NO_AUTOREPAIR_IF_DISABLED		 (1 << 7)	// Inversion of the previous; disallows this particular subsystem if the ship-wide flag is set (MageKing17)
#define MSS_FLAG2_SHARE_FIRE_DIRECTION			 (1 << 8)	// (DahBlount) Whenever the turret fires, make all firing points fire in the same direction.

#define NUM_SUBSYSTEM_FLAGS			33

// all subsys flags set in model file, used to copy only these flags for different table entries using the same model
#define MSS_MODEL_FLAG_MASK				(MSS_FLAG_CREWPOINT | MSS_FLAG_ROTATES | MSS_FLAG_TRIGGERED | MSS_FLAG_ARTILLERY | MSS_FLAG_STEPPED_ROTATE)
#define MSS_MODEL_FLAG2_MASK			0

// definition of stepped rotation struct
typedef struct stepped_rotation {
	int num_steps;				// number of steps in complete revolution
	float fraction;			// fraction of time in step spent in accel
	float t_transit;			// time spent moving from one step to next
	float t_pause;				// time at rest between steps
	float max_turn_rate;		// max turn rate going betweens steps
	float max_turn_accel;	// max accel going between steps
} stepped_rotation_t;

struct queued_animation;

// definition for model subsystems.
typedef struct model_subsystem {					/* contains rotation rate info */

	uint	flags;								// See MSS_FLAG_* defines above
	uint	flags2;
	char	name[MAX_NAME_LEN];					// name of the subsystem.  Probably displayed on HUD
	char	subobj_name[MAX_NAME_LEN];			// Temporary (hopefully) parameter used to match stuff in ships.tbl
	char	alt_sub_name[NAME_LENGTH];			// Karajorma - Name that overrides name of original
	char	alt_dmg_sub_name[NAME_LENGTH];		// Name for the damage popup subsystems, allows for translation
	int		subobj_num;							// subobject number (from bspgen) -- used to match subobjects of subsystems to these entries; index to polymodel->submodel
	int		model_num;							// Which model this is attached to (i.e. the polymodel[] index); same as polymodel->id
	int		type;								// type. see SUBSYSTEM_* types above.  A generic type thing
	vec3d	pnt;								// center point of this subsystem
	float	radius;								// the extent of the subsystem
	float	max_subsys_strength;				// maximum hits of this subsystem
	int		armor_type_idx;						// Armor type on teh subsystem -C

	//	The following items are specific to turrets and will probably be moved to
	//	a separate struct so they don't take up space for all subsystem types.
	char	crewspot[MAX_NAME_LEN];				// unique identifying name for this turret -- used to assign AI class and multiplayer people
	vec3d	turret_norm;						//	direction this turret faces
	matrix	turret_matrix;						// turret_norm converted to a matrix.
	float	turret_fov;							//	dot of turret_norm:vec_to_enemy > this means can see
	float	turret_max_fov;						//  dot of turret_norm:vec_to_enemy <= this means barrels can elevate up to the target
	float	turret_y_fov;						//  turret's base's fov
	int		turret_num_firing_points;			// number of firing points on this turret
	vec3d	turret_firing_point[MAX_TFP];		//	in parent object's reference frame, point from which to fire.
	int		turret_gun_sobj;					// Which subobject in this model the firing points are linked to.
	float	turret_turning_rate;				// How fast the turret turns. Read from ships.tbl
	int		turret_base_rotation_snd;				// Sound to make when the turret moves
	float	turret_base_rotation_snd_mult;			// Volume multiplier for the turret sounds
	int		turret_gun_rotation_snd;				// Sound to make when the turret moves
	float	turret_gun_rotation_snd_mult;			// Volume multiplier for the turret sounds


	//Sound stuff
	int		alive_snd;		//Sound to make while the subsystem is not-dead
	int		dead_snd;		//Sound to make when the subsystem is dead.
	int		rotation_snd;	//Sound to make when the subsystem is rotating. (ie turrets)

	// engine wash info
	struct engine_wash_info		*engine_wash_pointer;					// index into Engine_wash_info

	// rotation specific info
	float		turn_rate;							// The turning rate of this subobject, if MSS_FLAG_ROTATES is set.
	int			weapon_rotation_pbank;				// weapon-controlled rotation - Goober5000
	stepped_rotation_t	*stepped_rotation;			// turn rotation struct

	// AWACS specific information
	float		awacs_intensity;						// awacs intensity of this subsystem
	float		awacs_radius;							// radius of effect of the AWACS

	int		primary_banks[MAX_SHIP_PRIMARY_BANKS];					// default primary weapons -hoffoss
	int		primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS];		// capacity of a bank - Goober5000
	int		secondary_banks[MAX_SHIP_SECONDARY_BANKS];				// default secondary weapons -hoffoss
	int		secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS];	// capacity of a bank -hoffoss
	int		path_num;								// path index into polymodel .paths array.  -2 if none exists, -1 if not defined

	int n_triggers;
	queued_animation *triggers;		//all the triggered animations associated with this object

	int		turret_reset_delay;

	// target priority setting for turrets
	int      target_priority[32];
	int      num_target_priorities;

	float	optimum_range;
	float	favor_current_facing;

	float	turret_rof_scaler;

	//Per-turret ownage settings - SUSHI
	int turret_max_bomb_ownage; 
	int turret_max_target_ownage; 
} model_subsystem;

typedef struct model_special {
	struct	model_special *next, *prev;		// for using as a linked list
	int		bank;										// used for sequencing gun/missile backs. approach/docking points
	int		slot;										// location for gun or missile in this bank
	vec3d	pnt;										// point where this special submodel thingy is at
	vec3d	norm;										// normal for the special submodel thingy
} model_special;

// model arc types
#define MARC_TYPE_NORMAL					0		// standard freespace 1 blue lightning arcs
#define MARC_TYPE_EMP						1		// EMP blast type arcs

#define MAX_LIVE_DEBRIS	7

typedef struct model_tmap_vert {
	ushort vertnum;
	ushort normnum;
	float u,v;
} model_tmap_vert;

struct bsp_collision_node {
	vec3d min;
	vec3d max;

	int back;
	int front;

	int leaf;
};

struct bsp_collision_leaf {
	vec3d plane_pnt;
	vec3d plane_norm;
	float face_rad;
	int vert_start;
	ubyte num_verts;
	ubyte tmap_num;

	int next;
};

struct bsp_collision_tree {
	bsp_collision_node *node_list;
	int n_nodes;

	bsp_collision_leaf *leaf_list;
	int n_leaves;

	model_tmap_vert *vert_list;
	vec3d *point_list;

	int n_verts;
	bool used;
};

class bsp_info
{
public:
	bsp_info()
		: movement_type(-1), movement_axis(0), can_move(false), bsp_data_size(0), bsp_data(NULL), collision_tree_index(-1),
		rad(0.0f), blown_off(0), my_replacement(-1), i_replace(-1), is_live_debris(0), num_live_debris(0),
		is_thruster(0), is_damaged(0), parent(-1), num_children(0), first_child(-1), next_sibling(-1), num_details(0),
		num_arcs(0), outline_buffer(NULL), n_verts_outline(0), render_sphere_radius(0.0f), use_render_box(0), use_render_box_offset(false),
		use_render_sphere(0), use_render_sphere_offset(false), gun_rotation(false), no_collisions(false),
		nocollide_this_only(false), collide_invisible(false), force_turret_normal(false), attach_thrusters(false), dumb_turn_rate(0.0f),
		look_at_num(-1)
	{
		name[0] = 0;
		lod_name[0] = 0;
		look_at[0] = 0;

		offset = geometric_center = min = max = render_box_min = render_box_max = render_box_offset = render_sphere_offset = vmd_zero_vector;
		orientation = vmd_identity_matrix;

		memset(&bounding_box, 0, 8 * sizeof(vec3d));
		memset(&angs, 0, sizeof(angles));
		memset(&live_debris, 0, MAX_LIVE_DEBRIS * sizeof(int));
		memset(&details, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(int));
		memset(&arc_pts, 0, MAX_ARC_EFFECTS * 2 * sizeof(vec3d));
		memset(&arc_type, 0, MAX_ARC_EFFECTS * sizeof(ubyte));
	}

	char		name[MAX_NAME_LEN];	// name of the subsystem.  Probably displayed on HUD
	int		movement_type;			// -1 if no movement, otherwise rotational or positional movement -- subobjects only
	int		movement_axis;			// which axis this subobject moves or rotates on.
	bool	can_move;				// If true, the position and/or orientation of this submodel can change due to rotation of itself OR a parent

	vec3d	offset;					// 3d offset from parent object
	matrix	orientation;			// 3d orientation relative to parent object

	int		bsp_data_size;
	ubyte		*bsp_data;

	int collision_tree_index;

	vec3d	geometric_center;		// geometric center of this subobject.  In the same Frame Of 
	                              //  Reference as all other vertices in this submodel. (Relative to pivot point)
	float		rad;						// radius for each submodel

	vec3d	min;						// The min point of this object's geometry
	vec3d	max;						// The max point of this object's geometry
	vec3d	bounding_box[8];		// calculated fron min/max

	int		blown_off;				// If set, this subobject is blown off. Stuffed by model_set_instance
	int		my_replacement;		// If not -1 this subobject is what should get rendered instead of this one
	int		i_replace;				// If this is not -1, then this subobject will replace i_replace when it is damaged
	angles	angs;					// The rotation angles of this subobject (Within its own orientation, NOT relative to parent - KeldorKatarn)

	int		is_live_debris;		// whether current submodel is a live debris model
	int		num_live_debris;		// num live debris models assocaiated with a submodel
	int		live_debris[MAX_LIVE_DEBRIS];	// array of live debris submodels for a submodel

	int		is_thruster;
	int		is_damaged;

	// Tree info
	int		parent;					// what is parent for each submodel, -1 if none
	int		num_children;			// How many children this model has
	int		first_child;			// The first_child of this model, -1 if none
	int		next_sibling;			// This submodel's next sibling, -1 if none

	int		num_details;			// How many submodels are lower detail "mirrors" of this submodel
	int		details[MAX_MODEL_DETAIL_LEVELS];		// A list of all the lower detail "mirrors" of this submodel

	// Electrical Arc Effect Info
	// Sets a spark for this submodel between vertex v1 and v2	
	int		num_arcs;												// See model_add_arc for more info	
	vec3d	arc_pts[MAX_ARC_EFFECTS][2];	
	ubyte		arc_type[MAX_ARC_EFFECTS];							// see MARC_TYPE_* defines
	
	// buffers used by HT&L
	vertex_buffer buffer;
	vertex_buffer trans_buffer;

	vertex *outline_buffer;
	uint n_verts_outline;

	vec3d	render_box_min;
	vec3d	render_box_max;
	vec3d	render_box_offset;
	float	render_sphere_radius;
	vec3d	render_sphere_offset;
	int		use_render_box;			// 0==do nothing, 1==only render this object if you are inside the box, -1==only if you're outside
	bool	use_render_box_offset;		// whether an offset has been defined; needed because one can't tell just by looking at render_box_offset
	int		use_render_sphere;		// 0==do nothing, 1==only render this object if you are inside the sphere, -1==only if you're outside
	bool 	use_render_sphere_offset;// whether an offset has been defined; needed because one can't tell just by looking at render_sphere_offset
	bool	gun_rotation;			// for animated weapon models
	bool	no_collisions;			// for $no_collisions property - kazan
	bool	nocollide_this_only;	//SUSHI: Like no_collisions, but not recursive. For the "replacement" collision model scheme.
	bool	collide_invisible;		//SUSHI: If set, this submodel should allow collisions for invisible textures. For the "replacement" collision model scheme.
	bool	force_turret_normal;	//Wanderer: Sets the turret uvec to override any input of for turret normal.
	char	lod_name[MAX_NAME_LEN];	//FUBAR:  Name to be used for LOD naming comparison to preserve compatibility with older tables.  Only used on LOD0 
	bool	attach_thrusters;		//zookeeper: If set and this submodel or any of its parents rotates, also rotates associated thrusters.
	float	dumb_turn_rate;			//Bobboau
	//int	look_at;				//Bobboau
	int		look_at_num;			//VA - number of the submodel to be looked at by this submodel (-1 if none)
	char	look_at[MAX_NAME_LEN];	//VA - name of submodel to be looked at by this submodel
};

void parse_triggersint(int &n_trig, queued_animation **triggers, char *props);

#define MP_TYPE_UNUSED 0
#define MP_TYPE_SUBSYS 1

typedef struct mp_vert {
	vec3d		pos;				// xyz coordinates of vertex in object's frame of reference
	int			nturrets;		// number of turrets guarding this vertex
	int			*turret_ids;	// array of indices into ship_subsys linked list (can't index using [] though)
	float			radius;			// How far the closest obstruction is from this vertex
} mp_vert;

typedef struct model_path {
	char			name[MAX_NAME_LEN];					// name of the subsystem.  Probably displayed on HUD
	char			parent_name[MAX_NAME_LEN];			// parent name of submodel that path is linked to in POF
	int			parent_submodel;
	int			nverts;
	mp_vert		*verts;
	int			goal;			// Which of the verts is the one closest to the goal of this path
	int			type;			// What this path takes you to... See MP_TYPE_??? defines above for details
	int			value;		// This depends on the type.
									// For MP_TYPE_UNUSED, this means nothing.
									// For MP_TYPE_SUBSYS, this is the subsystem number this path takes you to.
} model_path;

// info for gun and missile banks.  Also used for docking points.  There should always
// only be two slots for each docking bay

#define MAX_SLOTS		25

typedef struct w_bank {
	int		num_slots;
	vec3d	pnt[MAX_SLOTS];
	vec3d	norm[MAX_SLOTS];
	float		radius[MAX_SLOTS];
} w_bank;

struct glow_point{
	vec3d	pnt;
	vec3d	norm;
	float	radius;
};

typedef struct thruster_bank {
	int		num_points;
	glow_point *points;

	// Engine wash info
	struct engine_wash_info	*wash_info_pointer;		// index into Engine_wash_info
	int		obj_num;		// what subsystem number this bank is on; index to ship_info->subsystems
	int		submodel_num;	// what submodel number this bank is on; index to polymodel->submodel/polymodel_instance->submodel
} thruster_bank;

#define PULSE_SIN 1
#define PULSE_COS 2
#define PULSE_TRI 3
#define PULSE_SHIFTTRI 4

typedef struct glow_point_bank {  // glow bank structure -Bobboau
	int			type;
	int			glow_timestamp; 
	int			on_time; 
	int			off_time; 
	int			disp_time; 
	bool		is_on;
	int			submodel_parent; 
	int			LOD; 
	int			num_points; 
	glow_point	*points;
	int			glow_bitmap; 
	int			glow_neb_bitmap; 
} glow_point_bank;

typedef struct glow_point_bank_override {
	char		name[33];
	int			type;
	int			on_time; 
	int			off_time; 
	int			disp_time; 
	int			glow_bitmap; 
	int			glow_neb_bitmap;
	bool		is_on;

	bool		type_override;
	bool		on_time_override; 
	bool		off_time_override; 
	bool		disp_time_override; 
	bool		glow_bitmap_override;

	ubyte		pulse_type;
	int			pulse_period;
	float		pulse_amplitude;
	float		pulse_bias;
	float		pulse_exponent;
	bool		is_lightsource;
	float		radius_multi;
	vec3d		light_color;
	vec3d		light_mix_color;
	bool		lightcone;
	float		cone_angle;
	float		cone_inner_angle;
	vec3d		cone_direction;
	bool		dualcone;
	bool		rotating;
	vec3d		rotation_axis;
	float		rotation_speed;

	bool		pulse_period_override;
} glow_point_bank_override;

// defines for docking bay things.  The types are essentially flags since docking bays can probably
// be used for multiple things in some cases (i.e. rearming and general docking)
//WMC - IMPORTANT, update Dock_type_names array if you add a new one of these
extern flag_def_list Dock_type_names[];
extern int Num_dock_type_names;

#define DOCK_TYPE_CARGO				(1<<0)
#define DOCK_TYPE_REARM				(1<<1)
#define DOCK_TYPE_GENERIC			(1<<2)

#define MAX_DOCK_SLOTS	2

typedef struct dock_bay {
	int		num_slots;
	int		type_flags;					// indicates what this docking bay can be used for (i.e. cargo/rearm, etc)
	int		num_spline_paths;			// number of spline paths which lead to this docking bay
	int		*splines;					// array of indices into the Spline_path array
	char		name[MAX_NAME_LEN];		// name of this docking location
	vec3d	pnt[MAX_DOCK_SLOTS];
	vec3d	norm[MAX_DOCK_SLOTS];
} dock_bay;

// struct that holds the indicies into path information associated with a fighter bay on a capital ship
// NOTE: Fighter bay paths are identified by the path_name $bayN (where N is numbered from 1).
//			Capital ships only have ONE fighter bay on the entire ship
// NOTE: MAX_SHIP_BAY_PATHS cannot be bumped higher than 31 without rewriting the arrival/departure flag logic.
#define MAX_SHIP_BAY_PATHS		31
typedef struct ship_bay {
	int	num_paths;							// how many paths are associated with the model's fighter bay
	int	path_indexes[MAX_SHIP_BAY_PATHS];	// index into polymodel->paths[] array
	int	arrive_flags;	// bitfield, set to 1 when that path number is reserved for an arrival
	int	depart_flags;	// bitfield, set to 1 when that path number is reserved for a departure
} ship_bay_t;

// three structures now used for representing shields.
// shield_tri structure stores information concerning each face of the shield.
// verts indexes into the verts array in the higher level structure
// neighbors indexes into the tris array in the higher level structure
typedef struct shield_tri {
  int used;
  int verts[3];			// 3 indices into vertex list of the shield.  list found in shield_info struct
  int neighbors[3];		// indices into array of triangles. neighbor = shares edge.  list found in shield_info struct
  vec3d norm;				// norm of this triangle
} shield_tri;

// a list of these shield_vertex structures comprimises the vertex list of the shield.
// The verts array in the shield_tri structure points to one of these members
typedef struct shield_vertex {
	vec3d	pos;
	float		u,v;
} shield_vertex;

// the high level shield structure.  A ship without any shield has nverts and ntris set to 0.
// The vertex list and the tris list are used by the shield_tri structure
typedef struct shield_info {
	int				nverts;
	int				ntris;
	shield_vertex	*verts;
	shield_tri		*tris;
} shield_info;

#define BSP_LIGHT_TYPE_WEAPON 1
#define BSP_LIGHT_TYPE_THRUSTER 2

typedef struct bsp_light {
	vec3d			pos;
	int				type;		// See BSP_LIGHT_TYPE_?? for values
	float				value;	// How much to light up this light.  0-1.
} bsp_light;

// model_octant - There are 8 of these per model.  They are a handy way to categorize
// a lot of model properties to get some easy 8x optimizations for model stuff.
typedef struct model_octant {
	vec3d		min, max;				// The bounding box that makes up this octant defined as 2 points.
	int			nverts;					// how many vertices are in this octant
	vec3d		**verts;					// The vertices in this octant in the high-res hull.  A vertex can only be in one octant.
	int			nshield_tris;			// how many shield triangles are in the octant
	shield_tri	**shield_tris;			// the shield triangles that make up this octant. A tri could be in multiple octants.
} model_octant;

#define MAX_EYES	10

typedef struct eye {
	int		parent;			// parent's subobject number
	vec3d	pnt;				// the point for the eye
	vec3d	norm;				// direction the eye faces.  Not used with first eye since player orient is used
} eye;

typedef struct cross_section {
	float z;
	float radius;
} cross_section;

#define MAX_MODEL_INSIGNIAS		6
#define MAX_INS_FACE_VECS			3
#define MAX_INS_VECS					81
#define MAX_INS_FACES				128
typedef struct insignia {
	int detail_level;
	int num_faces;					
	int faces[MAX_INS_FACES][MAX_INS_FACE_VECS];		// indices into the vecs array	
	float u[MAX_INS_FACES][MAX_INS_FACE_VECS];		// u tex coords on a per-face-per-vertex basis
	float v[MAX_INS_FACES][MAX_INS_FACE_VECS];		// v tex coords on a per-face-per-vertex bases
	vec3d vecs[MAX_INS_VECS];								// vertex list	
	vec3d offset;	// global position offset for this insignia
	vec3d norm[MAX_INS_VECS]	;					//normal of the insignia-Bobboau
} insignia;

#define PM_FLAG_ALLOW_TILING			(1<<0)					// Allow texture tiling
#define PM_FLAG_AUTOCEN					(1<<1)					// contains autocentering info	
#define PM_FLAG_TRANS_BUFFER			(1<<2)					// render transparency buffer
#define PM_FLAG_BATCHED					(1<<3)					// this model can be batch rendered
#define PM_FLAG_HAS_INTRINSIC_ROTATE	(1<<4)					// whether this model has an intrinsic rotation submodel somewhere

// Goober5000
class texture_info
{
private:
	int original_texture;	// what gets read in from file
	int texture;			// what texture you draw with; reset to original_textures by model_set_instance

	//WMC - Removed unneeded struct and is_anim to clean this up.
	//If num_frames is < 2, it doesn't need to be treated like an animation.
	int num_frames;
	float total_time;		// in seconds

public:
	texture_info();
	texture_info(int bm_handle);
	void clear();

	int GetNumFrames();
	int GetOriginalTexture();
	int GetTexture();
	float GetTotalTime();

	int LoadTexture(char *filename, char *dbg_name);

	void PageIn();
	void PageOut(bool release);

	int ResetTexture();
	int SetTexture(int n_tex);
};

#define TM_BASE_TYPE		0		// the standard base map
#define TM_GLOW_TYPE		1		// optional glow map
#define TM_SPECULAR_TYPE	2		// optional specular map
#define TM_NORMAL_TYPE		3		// optional normal map
#define TM_HEIGHT_TYPE		4		// optional height map (for parallax mapping)
#define TM_MISC_TYPE		5		// optional utility map
#define TM_NUM_TYPES		6		//WMC - Number of texture_info objects in texture_map
									//Used by scripting - if you change this, do a search
									//to update switch() statement in lua.cpp
// taylor
//WMC - OOPified
class texture_map
{
public:
	texture_info textures[TM_NUM_TYPES];

	bool is_ambient;
	bool is_transparent;

	int FindTexture(int bm_handle);
	int FindTexture(char *name);

	void PageIn();
	void PageOut(bool release);

	void Clear();
	void ResetToOriginal();

	texture_map()
		: is_ambient(false), is_transparent(false)
	{}
};

#define MAX_REPLACEMENT_TEXTURES MAX_MODEL_TEXTURES * TM_NUM_TYPES

// Goober5000 - since we need something < 0
#define REPLACE_WITH_INVISIBLE	-47

//used to describe a polygon model
// NOTE: Because WMC OOPified the textures, this must now be treated as a class, rather than a struct.
//       Additionally, a lot of model initialization and de-initialization is currently done in model_load or model_unload.
class polymodel
{
public:
	// initialize to 0 and NULL because previously a memset was used
	polymodel()
		: id(-1), version(0), flags(0), n_detail_levels(0), num_debris_objects(0), n_models(0), num_lights(0), lights(NULL),
		n_view_positions(0), rad(0.0f), core_radius(0.0f), n_textures(0), submodel(NULL), n_guns(0), n_missiles(0), n_docks(0),
		n_thrusters(0), gun_banks(NULL), missile_banks(NULL), docking_bays(NULL), thrusters(NULL), ship_bay(NULL),
		shield_collision_tree(NULL), sldc_size(0), n_paths(0), paths(NULL), mass(0), num_xc(0), xc(NULL), num_split_plane(0),
		num_ins(0), used_this_mission(0), n_glow_point_banks(0), glow_point_banks(NULL), gun_submodel_rotation(0),
		vertex_buffer_id(-1)
	{
		filename[0] = 0;
		mins = maxs = autocenter = center_of_mass = vmd_zero_vector;
		moment_of_inertia = vmd_identity_matrix;

		memset(&detail, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(int));
		memset(&detail_depth, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(float));
		memset(&debris_objects, 0, MAX_DEBRIS_OBJECTS * sizeof(int));
		memset(&bounding_box, 0, 8 * sizeof(vec3d));
		memset(&view_positions, 0, MAX_EYES * sizeof(eye));
		memset(&shield, 0, sizeof(shield_info));
		memset(&octants, 0, 8 * sizeof(model_octant));
		memset(&split_plane, 0, MAX_SPLIT_PLANE * sizeof(float));
		memset(&ins, 0, MAX_MODEL_INSIGNIAS * sizeof(insignia));

#ifndef NDEBUG
		ram_used = 0;
		debug_info_size = 0;
		debug_info = NULL;
#endif
	}


	int			id;				// what the polygon model number is.  (Index in Polygon_models)
	int			version;
	char			filename[FILESPEC_LENGTH];

	uint			flags;			// 1=allow tiling
	int			n_detail_levels;
	int			detail[MAX_MODEL_DETAIL_LEVELS];
	float			detail_depth[MAX_MODEL_DETAIL_LEVELS];

	int			num_debris_objects;
	int			debris_objects[MAX_DEBRIS_OBJECTS];

	int			n_models;

	vec3d		mins,maxs;							//min,max for whole model
	vec3d		bounding_box[8];

	int			num_lights;							// how many lights there are
	bsp_light *	lights;								// array of light info

	int			n_view_positions;					// number of viewing positions available on this ship
	eye			view_positions[MAX_EYES];		//viewing positions.  Default to {0,0,0}. in location 0

	vec3d		autocenter;							// valid only if PM_FLAG_AUTOCEN is set

	float			rad;									// The radius of everything in the model; shields, thrusters.
	float			core_radius;						// The radius to be used for collision detection in small ship vs big ships.
															// This is equal to 1/2 of the smallest dimension of the hull's bounding box.
	// texture maps for model
	int n_textures;
	texture_map	maps[MAX_MODEL_TEXTURES];
	
	bsp_info		*submodel;							// an array of size n_models of submodel info.

	// linked lists for special polygon types on this model.  Most ships I think will have most
	// of these.  (most ships however, probably won't have approach points).
	int			n_guns;								// number of primary gun points (not counting turrets)
	int			n_missiles;							// number of secondary missile points (not counting turrets)
	int			n_docks;								// number of docking points
	int			n_thrusters;						// number of thrusters on this ship.
	w_bank		*gun_banks;							// array of gun banks
	w_bank		*missile_banks;					// array of missile banks
	dock_bay		*docking_bays;						// array of docking point pairs
	thruster_bank		*thrusters;							// array of thruster objects -- likely to change in the future
	ship_bay_t		*ship_bay;							// contains path indexes for ship bay approach/depart paths

	shield_info	shield;								// new shield information
	ubyte	*shield_collision_tree;
	int		sldc_size;
	SCP_vector<vec3d>		shield_points;

	int			n_paths;
	model_path	*paths;

	// physics info
	float			mass;
	vec3d		center_of_mass;
	matrix		moment_of_inertia;
	
	model_octant	octants[8];

	int num_xc;				// number of cross sections
	cross_section* xc;	// pointer to array of cross sections (used in big ship explosions)

	int num_split_plane;	// number of split planes
	float split_plane[MAX_SPLIT_PLANE];	// actual split plane z coords (for big ship explosions)

	insignia		ins[MAX_MODEL_INSIGNIAS];
	int			num_ins;

#ifndef NDEBUG
	int			ram_used;		// How much RAM this model uses
	int			debug_info_size;
	char			*debug_info;
#endif

	int used_this_mission;		// used for page-in system, how many times this model has been loaded per mission - taylor

	int n_glow_point_banks;						// number of glow points on this ship. -Bobboau
	glow_point_bank *glow_point_banks;			// array of glow objects -Bobboau

	float gun_submodel_rotation;

	int vertex_buffer_id;			// HTL vertex buffer id

	vertex_buffer detail_buffers[MAX_MODEL_DETAIL_LEVELS];
};

// Call once to initialize the model system
void model_init();

// call to unload a model (works like bm_unload()), "force" SHOULD NEVER BE SET outside of modelread.cpp!!!!
void model_unload(int modelnum, int force = 0);

// Call to free all existing models
void model_free_all();
void model_instance_free_all();

// Loads a model from disk and returns the model number it loaded into.
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror = 1, int duplicate = 0);

int model_create_instance(bool is_ship, int model_num);
void model_delete_instance(int model_instance_num);

// Goober5000
void model_load_texture(polymodel *pm, int i, char *file);

// Returns a pointer to the polymodel structure for model 'n'
polymodel *model_get(int model_num);

polymodel_instance* model_get_instance(int model_instance_num);

// routine to copy susbsystems.  Must be called when subsystems sets are the same -- see ship.cpp
void model_copy_subsystems(int n_subsystems, model_subsystem *d_sp, model_subsystem *s_sp);

// If MR_FLAG_OUTLINE bit set this color will be used for outlines.
// This defaults to black.
void model_set_outline_color(int r, int g, int b);

void model_set_outline_color_fast(void *outline_color);

// IF MR_LOCK_DETAIL is set, then it will always draw detail level 'n'
// This defaults to 0. (0=highest, larger=lower)
void model_set_detail_level(int n);

// Flags you can pass to model_render
#define MR_NORMAL					(0)			// Draw a normal object
#define MR_SHOW_OUTLINE				(1<<0)		// Draw the object in outline mode. Color specified by model_set_outline_color
#define MR_SKYBOX					(1<<1)		// Draw as a skybox
#define MR_DESATURATED				(1<<2)		// Draw model in monochrome using outline color
#define MR_EMPTY_SLOT0				(1<<3)		// Show the radius around the object
#define MR_EMPTY_SLOT1				(1<<4)		// Show the shield mesh
#define MR_SHOW_THRUSTERS			(1<<5)		// Show the engine thrusters. See model_set_thrust for how long it draws.
#define MR_EMPTY_SLOT2				(1<<6)		// Only draw the detail level defined in model_set_detail_level
#define MR_NO_POLYS					(1<<7)		// Don't draw the polygons.
#define MR_NO_LIGHTING				(1<<8)		// Don't perform any lighting on the model.
#define MR_NO_TEXTURING				(1<<9)		// Draw textures as flat-shaded polygons.
#define MR_NO_CORRECT				(1<<10)		// Don't to correct texture mapping
#define MR_NO_SMOOTHING				(1<<11)		// Don't perform smoothing on vertices.
#define MR_IS_ASTEROID				(1<<12)		// When set, treat this as an asteroid.  
#define MR_IS_MISSILE				(1<<13)		// When set, treat this as a missilie.  No lighting, small thrusters.
#define MR_SHOW_OUTLINE_PRESET		(1<<14)		// Draw the object in outline mode. Color assumed to be set already.	
#define MR_SHOW_INVISIBLE_FACES		(1<<15)		// Show invisible faces as green...
#define MR_AUTOCENTER				(1<<16)		// Always use the center of the hull bounding box as the center, instead of the pivot point
#define MR_EMPTY_SLOT3				(1<<17)		// draw bay paths
#define MR_ALL_XPARENT				(1<<18)		// render it fully transparent
#define MR_NO_ZBUFFER				(1<<19)		// switch z-buffering off completely 
#define MR_NO_CULL					(1<<20)		// don't cull backfacing poly's
#define MR_EMPTY_SLOT4				(1<<21)		// force a given texture to always be used
#define MR_NO_BATCH					(1<<22)		// don't use submodel batching when rendering
#define MR_EDGE_ALPHA				(1<<23)		// makes norms that are faceing away from you render more transparent -Bobboau
#define MR_CENTER_ALPHA				(1<<24)		// oposite of above -Bobboau
#define MR_NO_FOGGING				(1<<25)		// Don't fog - taylor
#define MR_SHOW_OUTLINE_HTL			(1<<26)		// Show outlines (wireframe view) using HTL method
#define MR_NO_GLOWMAPS				(1<<27)		// disable rendering of glowmaps - taylor
#define MR_FULL_DETAIL				(1<<28)		// render all valid objects, particularly ones that are otherwise in/out of render boxes - taylor
#define MR_FORCE_CLAMP				(1<<29)		// force clamp - Hery
#define MR_EMPTY_SLOT5				(1<<30)		// Use a animated Shader - Valathil
#define MR_ATTACHED_MODEL			(1<<31)		// Used for attached weapon model lodding

#define MR_DEPRECATED_NORMAL					(0)			// Draw a normal object
#define MR_DEPRECATED_SHOW_OUTLINE				(1<<0)		// Draw the object in outline mode. Color specified by model_set_outline_color
#define MR_DEPRECATED_SHOW_PIVOTS				(1<<1)		// Show the pivot points
#define MR_DEPRECATED_SHOW_PATHS				(1<<2)		// Show the paths associated with a model
#define MR_DEPRECATED_SHOW_RADIUS				(1<<3)		// Show the radius around the object
#define MR_DEPRECATED_SHOW_SHIELDS				(1<<4)		// Show the shield mesh
#define MR_DEPRECATED_SHOW_THRUSTERS			(1<<5)		// Show the engine thrusters. See model_set_thrust for how long it draws.
#define MR_DEPRECATED_LOCK_DETAIL				(1<<6)		// Only draw the detail level defined in model_set_detail_level
#define MR_DEPRECATED_NO_POLYS					(1<<7)		// Don't draw the polygons.
#define MR_DEPRECATED_NO_LIGHTING				(1<<8)		// Don't perform any lighting on the model.
#define MR_DEPRECATED_NO_TEXTURING				(1<<9)		// Draw textures as flat-shaded polygons.
#define MR_DEPRECATED_NO_CORRECT				(1<<10)		// Don't to correct texture mapping
#define MR_DEPRECATED_NO_SMOOTHING				(1<<11)		// Don't perform smoothing on vertices.
#define MR_DEPRECATED_IS_ASTEROID				(1<<12)		// When set, treat this as an asteroid.  
#define MR_DEPRECATED_IS_MISSILE				(1<<13)		// When set, treat this as a missilie.  No lighting, small thrusters.
#define MR_DEPRECATED_SHOW_OUTLINE_PRESET		(1<<14)		// Draw the object in outline mode. Color assumed to be set already.	
#define MR_DEPRECATED_SHOW_INVISIBLE_FACES		(1<<15)		// Show invisible faces as green...
#define MR_DEPRECATED_AUTOCENTER				(1<<16)		// Always use the center of the hull bounding box as the center, instead of the pivot point
#define MR_DEPRECATED_BAY_PATHS					(1<<17)		// draw bay paths
#define MR_DEPRECATED_ALL_XPARENT				(1<<18)		// render it fully transparent
#define MR_DEPRECATED_NO_ZBUFFER				(1<<19)		// switch z-buffering off completely 
#define MR_DEPRECATED_NO_CULL					(1<<20)		// don't cull backfacing poly's
#define MR_DEPRECATED_FORCE_TEXTURE				(1<<21)		// force a given texture to always be used
#define MR_DEPRECATED_FORCE_LOWER_DETAIL		(1<<22)		// force the model to draw 1 LOD lower, if possible
#define MR_DEPRECATED_EDGE_ALPHA				(1<<23)		// makes norms that are faceing away from you render more transparent -Bobboau
#define MR_DEPRECATED_CENTER_ALPHA				(1<<24)		// oposite of above -Bobboau
#define MR_DEPRECATED_NO_FOGGING				(1<<25)		// Don't fog - taylor
#define MR_DEPRECATED_SHOW_OUTLINE_HTL			(1<<26)		// Show outlines (wireframe view) using HTL method
#define MR_DEPRECATED_NO_GLOWMAPS				(1<<27)		// disable rendering of glowmaps - taylor
#define MR_DEPRECATED_FULL_DETAIL				(1<<28)		// render all valid objects, particularly ones that are otherwise in/out of render boxes - taylor
#define MR_DEPRECATED_FORCE_CLAMP				(1<<29)		// force clamp - Hery
#define MR_DEPRECATED_ANIMATED_SHADER			(1<<30)		// Use a animated Shader - Valathil
#define MR_DEPRECATED_ATTACHED_MODEL			(1<<31)		// Used for attached weapon model lodding

#define MR_DEBUG_PIVOTS				(1<<0)		// Show the pivot points
#define MR_DEBUG_PATHS				(1<<1)		// Show the paths associated with a model
#define MR_DEBUG_RADIUS				(1<<2)		// Show the radius around the object
#define MR_DEBUG_SHIELDS			(1<<3)		// Show the shield mesh
#define MR_DEBUG_BAY_PATHS			(1<<4)		// draw bay paths

//Defines for the render parameter of model_render, model_really_render and model_render_buffers
#define MODEL_RENDER_OPAQUE 1
#define MODEL_RENDER_TRANS 2
#define MODEL_RENDER_ALL 3

// Renders a model and all it's submodels.
// See MR_? defines for values for flags
void model_render_DEPRECATED(int model_num, matrix *orient, vec3d * pos, uint flags = MR_DEPRECATED_NORMAL, int objnum = -1, int lighting_skip = -1, int *replacement_textures = NULL, int render = MODEL_RENDER_ALL, const bool is_skybox = false);

// Renders just one particular submodel on a model.
// See MR_? defines for values for flags
void submodel_render_DEPRECATED(int model_num,int submodel_num, matrix *orient, vec3d * pos, uint flags = MR_DEPRECATED_NORMAL, int objnum = -1, int *replacement_textures = NULL, int render = MODEL_RENDER_ALL);

// Returns the radius of a model
float model_get_radius(int modelnum);
float submodel_get_radius(int modelnum, int submodelnum);

// Returns the core radius (smallest dimension of hull's bounding box, used for collision detection with big ships only)
float model_get_core_radius(int modelnum);

// Returns zero is x1,y1,x2,y2 are valid
// returns 1 for invalid model, 2 for point offscreen.
// note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
// This function just looks at the radius, and not the orientation, so the
// bounding box won't change depending on the obj's orient.
extern int model_find_2d_bound(int model_num,matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);

// Returns zero is x1,y1,x2,y2 are valid
// returns 1 for invalid model, 2 for point offscreen.
// note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
// This function looks at the object's bounding box and it's orientation,
// so the bounds will change as the object rotates, to give the minimum bouding
// rect.
extern int model_find_2d_bound_min(int model_num,matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);

// Returns zero is x1,y1,x2,y2 are valid
// returns 1 for invalid model, 2 for point offscreen.
// note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
// This function looks at the object's bounding box and it's orientation,
// so the bounds will change as the object rotates, to give the minimum bouding
// rect.
int submodel_find_2d_bound_min(int model_num,int submodel, matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);


// Returns zero is x1,y1,x2,y2 are valid
// Returns 2 for point offscreen.
// note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
// This function just looks at the radius, and not the orientation, so the
// bounding box won't change depending on the obj's orient.
int subobj_find_2d_bound(float radius, matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);

// stats variables
#ifndef NDEBUG
extern int modelstats_num_polys;
extern int modelstats_num_polys_drawn;
extern int modelstats_num_verts;
extern int modelstats_num_sortnorms;
#endif

// Tries to move joints so that the turret points to the point dst.
// turret1 is the angles of the turret, turret2 is the angles of the gun from turret
extern int model_rotate_gun(int model_num, model_subsystem *turret, matrix *orient, angles *base_angles, angles *gun_angles, vec3d *pos, vec3d *dst, int obj_idx, bool reset = false);

// Gets and sets turret rotation matrix
extern void model_make_turret_matrix(int model_num, model_subsystem * turret );

// Rotates the angle of a submodel.  Use this so the right unlocked axis
// gets stuffed.
extern void submodel_rotate(model_subsystem *psub, submodel_instance_info *sii);
extern void submodel_rotate(bsp_info *sm, submodel_instance_info *sii);

// Rotates the angle of a submodel.  Use this so the right unlocked axis
// gets stuffed.  Does this for stepped rotations
void submodel_stepped_rotate(model_subsystem *psub, submodel_instance_info *sii);

// Goober5000
// For a submodel, return its overall offset from the main model.
extern void model_find_submodel_offset(vec3d *outpnt, int model_num, int sub_model_num);

// Given a point (pnt) that is in sub_model_num's frame of
// reference, and given the object's orient and position, 
// return the point in 3-space in outpnt.
extern void model_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_num, int submodel_num, const matrix *objorient, const vec3d *objpos);
extern void model_instance_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_instance_num, int submodel_num, const matrix *objorient, const vec3d *objpos);

// Given a point in the world RF, find the corresponding point in the model RF.
// This is special purpose code, specific for model collision.
// NOTE - this code ASSUMES submodel is 1 level down from hull (detail[0])
void world_find_model_point(vec3d *out, vec3d *world_pt, const polymodel *pm, int submodel_num, const matrix *orient, const vec3d *pos);
void world_find_model_instance_point(vec3d *out, vec3d *world_pt, const polymodel_instance *pmi, int submodel_num, const matrix *orient, const vec3d *pos);

extern void find_submodel_instance_point(vec3d *outpnt, int model_instance_num, int submodel_num);
extern void find_submodel_instance_point_normal(vec3d *outpnt, vec3d *outnorm, int model_instance_num, int submodel_num, const vec3d *submodel_pnt, const vec3d *submodel_norm);
extern void find_submodel_instance_point_orient(vec3d *outpnt, matrix *outorient, int model_instance_num, int submodel_num, const vec3d *submodel_pnt, const matrix *submodel_orient);
extern void find_submodel_instance_world_point(vec3d *outpnt, int model_instance_num, int submodel_num, const matrix *objorient, const vec3d *objpos);

// Given a polygon model index, find a list of rotating submodels to be used for collision
void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp);

// Given a polygon model index, get a list of a model tree starting from that index
void model_get_submodel_tree_list(SCP_vector<int> &submodel_vector, polymodel* pm, int mn);

// For a rotating submodel, find a point on the axis
void model_init_submodel_axis_pt(submodel_instance_info *sii, int model_num, int submodel_num);

// Given a direction (pnt) that is in sub_model_num's frame of
// reference, and given the object's orient and position, 
// return the point in 3-space in outpnt.
extern void model_find_world_dir(vec3d *out_dir, vec3d *in_dir, int model_num, int submodel_num, const matrix *objorient);
extern void model_instance_find_world_dir(vec3d *out_dir, vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient);

// Clears all the submodel instances stored in a model to their defaults.
extern void model_clear_instance(int model_num);

void model_clear_submodel_instance( submodel_instance *sm_instance, bsp_info *sm );
void model_clear_submodel_instances( int model_instance_num );

// Sets rotating submodel turn info to that stored in model
void model_set_instance_info(submodel_instance_info *sii, float turn_rate, float turn_accel);

// Clears all the values in a particular instance to their defaults.
extern void model_clear_instance_info(submodel_instance_info * sii);

// Sets the submodel instance data in a submodel
extern void model_set_instance(int model_num, int sub_model_num, submodel_instance_info *sii, int flags = 0);
extern void model_set_instance_techroom(int model_num, int sub_model_num, float angle_1, float angle_2);

void model_update_instance(int model_instance_num, int sub_model_num, submodel_instance_info *sii, int flags);

// Adds an electrical arcing effect to a submodel
void model_add_arc(int model_num, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type);

// Fills in an array with points from a model.  Only gets up to max_num verts.
// Returns number of verts found
extern int submodel_get_points(int model_num, int submodel_num, int max_num, vec3d **nts);

// Gets two random points on the surface of a submodel
extern void submodel_get_two_random_points(int model_num, int submodel_num, vec3d *v1, vec3d *v2, vec3d *n1 = NULL, vec3d *n2 = NULL);
extern void submodel_get_two_random_points_better(int model_num, int submodel_num, vec3d *v1, vec3d *v2);
// gets the index into the docking_bays array of the specified type of docking point
// Returns the index.  second functions returns the index of the docking bay with
// the specified name
extern int model_find_dock_index(int modelnum, int dock_type, int index_to_start_at = 0);
extern int model_find_dock_name_index(int modelnum, char *name);

// returns the actual name of a docking point on a model, needed by Fred.
char *model_get_dock_name(int modelnum, int index);

// returns number of docking points for a model
int model_get_num_dock_points(int modelnum);
int model_get_dock_index_type(int modelnum, int index);

// get all the different docking point types on a model
int model_get_dock_types(int modelnum);

// Goober5000
// returns index in [0, MAX_SHIP_BAY_PATHS)
int model_find_bay_path(int modelnum, char *bay_path_name);

// Returns number of verts in a submodel;
int submodel_get_num_verts(int model_num, int submodel_num);

// Returns number of polygons in a submodel;
int submodel_get_num_polys(int model_num, int submodel_num);

// Given a vector that is in sub_model_num's frame of
// reference, and given the object's orient and position,
// return the vector in the model's frame of reference.
void model_find_obj_dir(vec3d *w_vec, vec3d *m_vec, int model_instance_num, int submodel_num, matrix *objorient);
void model_instance_find_obj_dir(vec3d *w_vec, vec3d *m_vec, int model_instance_num, int submodel_num, matrix *objorient);


// This is the interface to model_check_collision.  Rather than passing all these
// values and returning values in globals, just fill in a temporary variable with
// the input values and call model_check_collision
typedef struct mc_info {
	// Input values
	int		model_instance_num;
	int		model_num;			// What model to check
	int		submodel_num;		// What submodel to check if MC_SUBMODEL is set
	matrix	*orient;				// The orient of the model
	vec3d	*pos;					// The pos of the model in world coordinates
	vec3d	*p0;					// The starting point of the ray (sphere) to check
	vec3d	*p1;					// The ending point of the ray (sphere) to check
	int		flags;				// Flags that the model_collide code looks at.  See MC_??? defines
	float		radius;				// If MC_CHECK_THICK is set, checks a sphere moving with the radius.
	int		lod;				// Which detail level of the submodel to check instead
	
	// Return values
	int		num_hits;			// How many collisions were found
	float		hit_dist;			// The distance from p0 to hitpoint
	vec3d	hit_point;			// Where the collision occurred at in hit_submodel's coordinate system
	vec3d	hit_point_world;	// Where the collision occurred at in world coordinates
	int		hit_submodel;		// Which submodel got hit.
	int		hit_bitmap;			// Which texture got hit.  -1 if not a textured poly
	float		hit_u, hit_v;		// Where on hit_bitmap the ray hit.  Invalid if hit_bitmap < 0
	int		shield_hit_tri;	// Which triangle on the shield got hit or -1 if none
	vec3d	hit_normal;			//	Vector normal of polygon of collision.  (This is in submodel RF)
	int		edge_hit;			// Set if an edge got hit.  Only valid if MC_CHECK_THICK is set.	
	ubyte		*f_poly;				// pointer to flat poly where we intersected
	ubyte		*t_poly;				// pointer to tmap poly where we intersected
	bsp_collision_leaf *bsp_leaf;

										// flags can be changed for the case of sphere check finds an edge hit
} mc_info;

inline void mc_info_init(mc_info *mc)
{
	mc->model_instance_num = -1;
	mc->model_num = -1;
	mc->submodel_num = -1;
	mc->orient = nullptr;
	mc->pos = nullptr;
	mc->p0 = nullptr;
	mc->p1 = nullptr;
	mc->flags = 0;
	mc->lod = 0;
	mc->radius = 0;
	mc->num_hits = 0; 
	mc->hit_dist = 0;
	mc->hit_point = vmd_zero_vector;
	mc->hit_point_world = vmd_zero_vector;
	mc->hit_submodel = -1;
	mc->hit_bitmap = -1;
	mc->hit_u = 0; mc->hit_v = 0;
	mc->shield_hit_tri = -1;
	mc->hit_normal = vmd_zero_vector;
	mc->edge_hit = 0;
	mc->f_poly = nullptr;
	mc->t_poly = nullptr;
	mc->bsp_leaf = nullptr;
}


//======== MODEL_COLLIDE ============

//	Model Collision flags, used in model_collide()
#define MC_CHECK_MODEL			(1<<0)			// Check the polygons in the model.
#define MC_CHECK_SHIELD			(1<<1)			//	check for collision against shield, if it exists.
#define MC_ONLY_SPHERE			(1<<2)			// Only check bounding sphere. Not accurate, but fast.  
															// NOTE!  This doesn't set hit_point correctly with MC_CHECK_SPHERELINE
#define MC_ONLY_BOUND_BOX		(1<<3)			// Only check bounding boxes.  Pretty accurate and slower than MC_ONLY_SPHERE.
															// Checks the rotatated bounding box of each submodel.  
															// NOTE!  This doesn't set hit_point correctly with MC_CHECK_SPHERELINE
#define MC_CHECK_RAY				(1<<4)			// Checks a ray from p0 *through* p1 on to infinity
#define MC_CHECK_SPHERELINE	(1<<5)			// Checks a moving sphere rather than just a ray.  Radius
#define MC_SUBMODEL				(1<<6)			// If this is set, only check the submodel specified in mc->submodel_num. Use with MC_CHECK_MODEL
#define MC_SUBMODEL_INSTANCE	(1<<7)			// Check submodel and its children (of a rotating submodel)
#define MC_CHECK_INVISIBLE_FACES (1<<8)		// Check the invisible faces.


/*
   Checks to see if a vector from p0 to p0 collides with a model of
   type 'model_num' at 'orient' 'pos'.

   Returns the number of polys that were hit.  Zero is none, obviously.
  	Return true if a collision with hull (or shield, if MC_CHECK_SHIELD set), 
	else return false.

   If it did it one or more, then hitpt is the closest 3d point that the
   vector hit.  See the MC_? defines for flag values.

   Model_collide can test a sphere against either (1) shield or (2) model.

   To check a sphere, set the radius of sphere in mc_info structure and
   set the flag MC_CHECK_SPHERE.

   Here is a sample for how to use:
  
	mc_info mc;

	mc.model_num = ???;			// Fill in the model to check
	mc.orient = &obj->orient;	// The object's orient
	mc.pos = &obj->pos;			// The object's position
	mc.p0 = &p0;					// Point 1 of ray to check
	mc.p1 = &p1;					// Point 2 of ray to check
	mc.flags = MC_CHECK_MODEL;	// flags

** TO COLLIDE AGAINST A LINE SEGMENT

  model_collide(&mc);
	if (mc.num_hits) {		
		// We hit submodel mc.hit_submodel on texture mc.hitbitmap,
		// at point mc.hit_point_world, with uv's of mc.hit_u, mc.hit_v.
	}

** TO COLLIDE AGAINST A SPHERE
	mc.flags |= MC_CHECK_SPHERELINE;
	mc.radius = radius;

	model_collide(&mc, radius);
	if (mc.num_hits) {		
		// We hit submodel mc.hit_submodel on texture mc.hitbitmap,
		// at point mc.hit_point_world, with uv's of mc.hit_u, mc.hit_v.
		// Check (mc.edge_hit) to see if we hit an edge
	}
*/

int model_collide(mc_info *mc_info_obj);
void model_collide_parse_bsp(bsp_collision_tree *tree, void *model_ptr, int version);

bsp_collision_tree *model_get_bsp_collision_tree(int tree_index);
void model_remove_bsp_collision_tree(int tree_index);
int model_create_bsp_collision_tree();

void model_collide_preprocess(matrix *orient, int model_instance_num, int detail = 0);

// Sets the submodel instance data in a submodel
// If show_damaged is true it shows only damaged submodels.
// If it is false it shows only undamaged submodels.
void model_show_damaged(int model_num, int show_damaged);


//=========================== MODEL OCTANT STUFF ================================

//  Models are now divided into 8 octants.    Shields too.
//  This made the collision code faster.   Shield is 4x and ship faces
//  are about 2x faster.

//  Before, calling model_collide with flags=0 didn't check the shield
//  but did check the model itself.   Setting the shield flags caused
//  the shield to get check along with the ship.
//  Now, you need to explicitly tell the model_collide code to check
//  the model, so you can check the model or shield or both.

//  If you need to check them both, do it in one call; this saves some
//  time.    If checking the shield is sufficient for determining 
//  something   (like if it is under the hud) then use just shield 
//  check, it is at least 5x faster than checking the model itself.


// Model octant ordering - this is a made up ordering, but it makes sense.
// X Y Z  index description
// - - -  0     left bottom rear
// - - +  1     left bottom front
// - + -  2     left top rear
// - + +  3     left top front
// + - -  4     right bottom rear
// + - +  5     right bottom front
// + + -  6     right top rear
// + + +  7     right top front

// Returns which octant point 'pnt' is closet to. This will always return 
// a valid octant (0-7) since the point doesn't have to be in an octant.
// If model_orient and/or model_pos are NULL, pnt is assumed to already 
// be rotated into the model's local coordinates.  
// If oct is not null, it will be filled in with a pointer to the octant
// data.
int model_which_octant_distant(vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, model_octant **oct);

// Returns which octant point 'pnt' is in. This might return
// -1 if the point isn't in any octant.
// If model_orient and/or model_pos are NULL, pnt is assumed to already 
// be rotated into the model's local coordinates.
// If oct is not null, it will be filled in with a pointer to the octant
// data.  Or NULL if the pnt isn't in the octant.
int model_which_octant(vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, model_octant **oct);

typedef struct mst_info {
	int primary_bitmap;
	int primary_glow_bitmap;
	int secondary_glow_bitmap;
	int tertiary_glow_bitmap;
	int distortion_bitmap;

	bool use_ab;
	float glow_noise;
	vec3d rotvel;
	vec3d length;

	float glow_rad_factor;
	float secondary_glow_rad_factor;
	float tertiary_glow_rad_factor;
	float glow_length_factor;
	float distortion_rad_factor;
	float distortion_length_factor;
	bool draw_distortion;

	mst_info() : primary_bitmap(-1), primary_glow_bitmap(-1), secondary_glow_bitmap(-1), tertiary_glow_bitmap(-1), distortion_bitmap(-1),
					use_ab(false), glow_noise(1.0f), rotvel(vmd_zero_vector), length(vmd_zero_vector), glow_rad_factor(1.0f),
					secondary_glow_rad_factor(1.0f), tertiary_glow_rad_factor(1.0f), glow_length_factor(1.0f), distortion_rad_factor(1.0f), distortion_length_factor(1.0f),
					draw_distortion(true)
				{}
} mst_info;

// scale the engines thrusters by this much
// Only enabled if MR_SHOW_THRUSTERS is on
void model_set_thrust(int model_num = -1, mst_info *mst = NULL);


//=======================================================================================
// Finds the closest point on a model to a point in space.  Actually only finds a point
// on the bounding box of the model.    
// Given:
//   model_num      Which model
//   submodel_num   Which submodel, -1 for hull
//   orient         Orientation of the model
//   pos            Position of the model
//   eye_pos        Point that you want to find the closest point to
// Returns:
//   distance from eye_pos to closest_point.  0 means eye_pos is 
//   on or inside the bounding box.
//   Also fills in outpnt with the actual closest point.
float model_find_closest_point(vec3d *outpnt, int model_num, int submodel_num, matrix *orient, vec3d * pos, vec3d *eye_pos);

// set the insignia bitmap to be used when rendering a ship with an insignia (-1 switches it off altogether)
void model_set_insignia_bitmap(int bmap);

// set model transparency for use with MR_ALL_XPARENT
void model_set_alpha(float alpha);

// set the forces bitmap
void model_set_forced_texture(int bmap);

// see if the given texture is used by the passed model. 0 if not used, 1 if used, -1 on error
int model_find_texture(int model_num, int bitmap);

// find closest point on extended bounding box (the bounding box plus all the planes that make it up)
// returns closest distance to extended box
// positive return value means start_point is outside extended box
// displaces closest point an optional amount delta to the outside of the box
// closest_box_point can be NULL.
float get_world_closest_box_point_with_delta(vec3d *closest_box_point, object *box_obj, vec3d *start_point, int *is_inside, float delta);

// given a newly loaded model, page in all textures
void model_page_in_textures(int modelnum, int ship_info_index = -1);

// given a model, unload all of its textures
void model_page_out_textures(int model_num, bool release = false);

void model_set_warp_globals(float scale_x = 1.0f, float scale_y = 1.0f, float scale_z = 1.0f, int bitmap_id = -1, float alpha = -1.0f);

void model_set_replacement_textures(int *replacement_textures);

void model_setup_cloak(vec3d *shift, int full_cloak, int alpha);
void model_finish_cloak(int full_cloak);

void model_do_look_at(int model_num); //Bobboau

void model_do_intrinsic_rotations(int model_instance_num = -1);

int model_should_render_engine_glow(int objnum, int bank_obj);

void model_interp_set_clip_plane(vec3d* pos = NULL, vec3d* normal = NULL);

void model_interp_set_animated_effect_and_timer(int effect_num = 0, float effect_timer = 0.0f);

bool model_get_team_color(team_color *clr, const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime);

void model_interp_set_team_color(const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime);

void moldel_calc_facing_pts( vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add, vec3d *Eyeposition );

void interp_render_arc(vec3d *v1, vec3d *v2, color *primary, color *secondary, float arc_width);

void model_render_insignias(polymodel *pm, int detail_level, int bitmap_num);

void model_draw_debug_points( polymodel *pm, bsp_info * submodel, uint flags );

void model_render_shields( polymodel * pm, uint flags );

void model_draw_paths( int model_num, uint flags );

void model_draw_paths_htl( int model_num, uint flags );

void model_draw_bay_paths(int model_num);

void model_draw_bay_paths_htl(int model_num);

void glowpoint_init();
SCP_vector<glow_point_bank_override>::iterator get_glowpoint_bank_override_by_name(const char* name);
extern SCP_vector<glow_point_bank_override> glowpoint_bank_overrides;

#endif // _MODEL_H