1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10
11
12 #ifndef _MODEL_H
13 #define _MODEL_H
14
15 #include "globalincs/globals.h" // for NAME_LENGTH
16 #include "globalincs/pstypes.h"
17
18 #include "actions/Program.h"
19 #include "gamesnd/gamesnd.h"
20 #include "graphics/2d.h"
21 #include "io/timer.h"
22 #include "model/model_flags.h"
23 #include "object/object.h"
24 #include "ship/ship_flags.h"
25
26 class object;
27 class ship_info;
28 class model_render_params;
29
30 extern flag_def_list model_render_flags[];
31 extern int model_render_flags_size;
32
33 #define MAX_DEBRIS_OBJECTS 32
34 #define MAX_MODEL_DETAIL_LEVELS 8
35 #define MAX_PROP_LEN 256
36 #define MAX_NAME_LEN 32
37 #define MAX_ARC_EFFECTS 8
38
39 #define MOVEMENT_TYPE_NONE -1
40 #define MOVEMENT_TYPE_POS 0
41 #define MOVEMENT_TYPE_ROT 1
42 #define MOVEMENT_TYPE_ROT_SPECIAL 2 // for turrets only
43 #define MOVEMENT_TYPE_TRIGGERED 3 // triggered rotation
44 #define MOVEMENT_TYPE_INTRINSIC_ROTATE 4 // intrinsic (non-subsystem-based) rotation
45
46
47 // DA 11/13/98 Reordered to account for difference between max and game
48 #define MOVEMENT_AXIS_NONE -1
49 #define MOVEMENT_AXIS_X 0
50 #define MOVEMENT_AXIS_Y 2
51 #define MOVEMENT_AXIS_Z 1
52 #define MOVEMENT_AXIS_OTHER 3
53
54 // defines for special objects like gun and missile points, docking point, etc
55 // Hoffoss: Please make sure that subsystem NONE is always index 0, and UNKNOWN is
56 // always the last subsystem in the list. Also, make sure that MAX is correct.
57 // Otherwise, problems will arise in Fred.
58
59 #define SUBSYSTEM_NONE 0
60 #define SUBSYSTEM_ENGINE 1
61 #define SUBSYSTEM_TURRET 2
62 #define SUBSYSTEM_RADAR 3
63 #define SUBSYSTEM_NAVIGATION 4
64 #define SUBSYSTEM_COMMUNICATION 5
65 #define SUBSYSTEM_WEAPONS 6
66 #define SUBSYSTEM_SENSORS 7
67 #define SUBSYSTEM_SOLAR 8
68 #define SUBSYSTEM_GAS_COLLECT 9
69 #define SUBSYSTEM_ACTIVATION 10
70 #define SUBSYSTEM_UNKNOWN 11
71 #define SUBSYSTEM_MAX 12 // maximum value for subsystem_xxx, for error checking
72
73 // Goober5000
74 extern const char *Subsystem_types[SUBSYSTEM_MAX];
75
76 #define MAX_TFP 10 // maximum number of turret firing points
77
78 #define MAX_SPLIT_PLANE 5 // number of artist specified split planes (used in big ship explosions)
79
80 // Data specific to a particular instance of a submodel.
81 struct submodel_instance
82 {
83 float cur_angle = 0.0f; // The current angle this thing is turned to.
84 float prev_angle = 0.0f;
85 float turret_idle_angle = 0.0f; // If this is a turret, this is the expected idling angle of the submodel
86
87 float current_turn_rate = 0.0f;
88 float desired_turn_rate = 0.0f;
89 float turn_accel = 0.0f;
90 int step_zero_timestamp = timestamp(); // timestamp determines when next step is to begin (for stepped rotation)
91
92 vec3d point_on_axis; // in ship RF
93 bool axis_set = false;
94 bool blown_off = false; // If set, this subobject is blown off
95
96 bool collision_checked = false;
97
98 // These fields are the true standard reference for submodel rotation. They should seldom be read directly
99 // and should almost never be written directly. In most cases, coders should prefer cur_angle and prev_angle.
100 matrix canonical_orient = vmd_identity_matrix;
101 matrix canonical_prev_orient = vmd_identity_matrix;
102
103 // --- these fields used to be in bsp_info ---
104
105 // Electrical Arc Effect Info
106 // Sets a spark for this submodel between vertex v1 and v2
107 int num_arcs = 0; // See model_add_arc for more info
108 vec3d arc_pts[MAX_ARC_EFFECTS][2];
109 ubyte arc_type[MAX_ARC_EFFECTS]; // see MARC_TYPE_* defines
110
submodel_instancesubmodel_instance111 submodel_instance()
112 {
113 memset(&arc_pts, 0, MAX_ARC_EFFECTS * 2 * sizeof(vec3d));
114 memset(&arc_type, 0, MAX_ARC_EFFECTS * sizeof(ubyte));
115 }
116 };
117
118 // Data specific to a particular instance of a model.
119 struct polymodel_instance
120 {
121 int id = -1; // global model_instance num index
122 int model_num = -1; // global model num index, same as polymodel->id
123 submodel_instance *submodel = nullptr; // array of submodel instances; mirrors the polymodel->submodel array
124 };
125
126 #define MAX_MODEL_SUBSYSTEMS 200 // used in ships.cpp (only place?) for local stack variable DTP; bumped to 200
127 // when reading in ships.tbl
128
129 // definition of stepped rotation struct
130 typedef struct stepped_rotation {
131 int num_steps; // number of steps in complete revolution
132 float fraction; // fraction of time in step spent in accel
133 float t_transit; // time spent moving from one step to next
134 float t_pause; // time at rest between steps
135 float max_turn_rate; // max turn rate going betweens steps
136 float max_turn_accel; // max accel going between steps
137 } stepped_rotation_t;
138
139 struct queued_animation;
140
141 // definition for model subsystems.
142 class model_subsystem { /* contains rotation rate info */
143 public:
144 flagset<Model::Subsystem_Flags> flags; // See model_flags.h
145 char name[MAX_NAME_LEN]; // name of the subsystem. Probably displayed on HUD
146 char subobj_name[MAX_NAME_LEN]; // Temporary (hopefully) parameter used to match stuff in ships.tbl
147 char alt_sub_name[NAME_LENGTH]; // Karajorma - Name that overrides name of original
148 char alt_dmg_sub_name[NAME_LENGTH]; // Name for the damage popup subsystems, allows for translation
149 int subobj_num; // subobject number (from bspgen) -- used to match subobjects of subsystems to these entries; index to polymodel->submodel
150 int model_num; // Which model this is attached to (i.e. the polymodel[] index); same as polymodel->id
151 int type; // type. see SUBSYSTEM_* types above. A generic type thing
152 vec3d pnt; // center point of this subsystem
153 float radius; // the extent of the subsystem
154 float max_subsys_strength; // maximum hits of this subsystem
155 int armor_type_idx; // Armor type on teh subsystem -C
156
157 // The following items are specific to turrets and will probably be moved to
158 // a separate struct so they don't take up space for all subsystem types.
159 char crewspot[MAX_NAME_LEN]; // unique identifying name for this turret -- used to assign AI class and multiplayer people
160 vec3d turret_norm; // direction this turret faces (i.e. the normal to the turret base, or the center of the field of view)
161 float turret_fov; // dot of turret_norm:vec_to_enemy > this means can see
162 float turret_max_fov; // dot of turret_norm:vec_to_enemy <= this means barrels can elevate up to the target
163 float turret_base_fov; // turret's base's fov
164 int turret_num_firing_points; // number of firing points on this turret
165 vec3d turret_firing_point[MAX_TFP]; // in parent object's reference frame, point from which to fire.
166 int turret_gun_sobj; // Which subobject in this model the firing points are linked to.
167 float turret_turning_rate; // How fast the turret turns. Read from ships.tbl
168 gamesnd_id turret_base_rotation_snd; // Sound to make when the turret moves
169 float turret_base_rotation_snd_mult; // Volume multiplier for the turret sounds
170 gamesnd_id turret_gun_rotation_snd; // Sound to make when the turret moves
171 float turret_gun_rotation_snd_mult; // Volume multiplier for the turret sounds
172
173
174 //Sound stuff
175 gamesnd_id alive_snd; //Sound to make while the subsystem is not-dead
176 gamesnd_id dead_snd; //Sound to make when the subsystem is dead.
177 gamesnd_id rotation_snd; //Sound to make when the subsystem is rotating. (ie turrets)
178
179 // engine wash info
180 struct engine_wash_info *engine_wash_pointer; // index into Engine_wash_info
181
182 // rotation specific info
183 float turn_rate; // The turning rate of this subobject, if MSS_FLAG_ROTATES is set.
184 int weapon_rotation_pbank; // weapon-controlled rotation - Goober5000
185 stepped_rotation_t *stepped_rotation; // turn rotation struct
186
187 // AWACS specific information
188 float awacs_intensity; // awacs intensity of this subsystem
189 float awacs_radius; // radius of effect of the AWACS
190
191 int primary_banks[MAX_SHIP_PRIMARY_BANKS]; // default primary weapons -hoffoss
192 int primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS]; // capacity of a bank - Goober5000
193 int secondary_banks[MAX_SHIP_SECONDARY_BANKS]; // default secondary weapons -hoffoss
194 int secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS]; // capacity of a bank -hoffoss
195 int path_num; // path index into polymodel .paths array. -2 if none exists, -1 if not defined
196
197 int n_triggers;
198 queued_animation *triggers; //all the triggered animations associated with this object
199
200 int turret_reset_delay;
201
202 // target priority setting for turrets
203 int target_priority[32];
204 int num_target_priorities;
205
206 float optimum_range;
207 float favor_current_facing;
208
209 float turret_rof_scaler;
210
211 //Per-turret ownage settings - SUSHI
212 int turret_max_bomb_ownage;
213 int turret_max_target_ownage;
214
215 actions::ProgramSet beam_warmdown_program;
216
217 void reset();
218
219 model_subsystem();
220 };
221
222 typedef struct model_special {
223 struct model_special *next, *prev; // for using as a linked list
224 int bank; // used for sequencing gun/missile backs. approach/docking points
225 int slot; // location for gun or missile in this bank
226 vec3d pnt; // point where this special submodel thingy is at
227 vec3d norm; // normal for the special submodel thingy
228 } model_special;
229
230 // model arc types
231 #define MARC_TYPE_NORMAL 0 // standard freespace 1 blue lightning arcs
232 #define MARC_TYPE_EMP 1 // EMP blast type arcs
233
234 #define MAX_LIVE_DEBRIS 7
235
236 typedef struct model_tmap_vert {
237 ushort vertnum;
238 ushort normnum;
239 float u,v;
240 } model_tmap_vert;
241
242 struct bsp_collision_node {
243 vec3d min;
244 vec3d max;
245
246 int back;
247 int front;
248
249 int leaf;
250 };
251
252 struct bsp_collision_leaf {
253 vec3d plane_pnt;
254 vec3d plane_norm;
255 float face_rad;
256 int vert_start;
257 ubyte num_verts;
258 ubyte tmap_num;
259
260 int next;
261 };
262
263 struct bsp_collision_tree {
264 bsp_collision_node *node_list;
265 int n_nodes;
266
267 bsp_collision_leaf *leaf_list;
268 int n_leaves;
269
270 model_tmap_vert *vert_list;
271 vec3d *point_list;
272
273 int n_verts;
274 bool used;
275 };
276
277 class bsp_info
278 {
279 public:
bsp_info()280 bsp_info()
281 : can_move(false), bsp_data_size(0), bsp_data(nullptr), collision_tree_index(-1),
282 rad(0.0f), my_replacement(-1), i_replace(-1), is_live_debris(false), num_live_debris(0),
283 parent(-1), num_children(0), first_child(-1), next_sibling(-1), num_details(0),
284 outline_buffer(nullptr), n_verts_outline(0), render_sphere_radius(0.0f), use_render_box(0), use_render_box_offset(false),
285 use_render_sphere(0), use_render_sphere_offset(false), gun_rotation(false), no_collisions(false),
286 nocollide_this_only(false), collide_invisible(false), attach_thrusters(false)
287 {
288 name[0] = 0;
289 lod_name[0] = 0;
290
291 offset = geometric_center = min = max = render_box_min = render_box_max = render_box_offset = render_sphere_offset = vmd_zero_vector;
292 frame_of_reference = vmd_identity_matrix;
293
294 memset(&bounding_box, 0, 8 * sizeof(vec3d));
295 memset(&live_debris, 0, MAX_LIVE_DEBRIS * sizeof(int));
296 memset(&details, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(int));
297 }
298
299 char name[MAX_NAME_LEN]; // name of the subsystem. Probably displayed on HUD
300 int movement_type = -1; // -1 if no movement, otherwise rotational or positional movement -- subobjects only
301 vec3d movement_axis = vmd_zero_vector; // which axis this subobject moves or rotates on.
302 int movement_axis_id = -1; // for optimization
303 bool can_move; // If true, the position and/or orientation of this submodel can change due to rotation of itself OR a parent
304
305 vec3d offset; // 3d offset from parent object
306 matrix frame_of_reference; // used to be called 'orientation' - this is just used for setting the rotation axis and the animation angles
307
308 int bsp_data_size;
309 ubyte *bsp_data;
310
311 int collision_tree_index;
312
313 vec3d geometric_center; // geometric center of this subobject. In the same Frame Of
314 // Reference as all other vertices in this submodel. (Relative to pivot point)
315 float rad; // radius for each submodel
316
317 vec3d min; // The min point of this object's geometry
318 vec3d max; // The max point of this object's geometry
319 vec3d bounding_box[8]; // calculated fron min/max
320
321 int my_replacement; // If not -1 this subobject is what should get rendered instead of this one
322 int i_replace; // If this is not -1, then this subobject will replace i_replace when it is damaged
323
324 bool is_live_debris; // whether current submodel is a live debris model
325 int num_live_debris; // num live debris models assocaiated with a submodel
326 int live_debris[MAX_LIVE_DEBRIS]; // array of live debris submodels for a submodel
327
328 bool is_thruster = false; // is an engine thruster submodel
329 bool is_damaged = false; // is a submodel that represents a damaged submodel (e.g. a -destroyed version of some other submodel)
330
331 // Tree info
332 int parent; // what is parent for each submodel, -1 if none
333 int num_children; // How many children this model has
334 int first_child; // The first_child of this model, -1 if none
335 int next_sibling; // This submodel's next sibling, -1 if none
336
337 int num_details; // How many submodels are lower detail "mirrors" of this submodel
338 int details[MAX_MODEL_DETAIL_LEVELS]; // A list of all the lower detail "mirrors" of this submodel
339
340 // buffers used by HT&L
341 vertex_buffer buffer;
342 vertex_buffer trans_buffer;
343
344 vertex *outline_buffer;
345 uint n_verts_outline;
346
347 vec3d render_box_min;
348 vec3d render_box_max;
349 vec3d render_box_offset;
350 float render_sphere_radius;
351 vec3d render_sphere_offset;
352 int use_render_box; // 0==do nothing, 1==only render this object if you are inside the box, -1==only if you're outside
353 bool use_render_box_offset; // whether an offset has been defined; needed because one can't tell just by looking at render_box_offset
354 int use_render_sphere; // 0==do nothing, 1==only render this object if you are inside the sphere, -1==only if you're outside
355 bool use_render_sphere_offset;// whether an offset has been defined; needed because one can't tell just by looking at render_sphere_offset
356 bool do_not_scale_detail_distances{false}; // if set should not scale boxes or spheres based on 'model detail' settings
357 bool gun_rotation; // for animated weapon models
358 bool no_collisions; // for $no_collisions property - kazan
359 bool nocollide_this_only; //SUSHI: Like no_collisions, but not recursive. For the "replacement" collision model scheme.
360 bool collide_invisible; //SUSHI: If set, this submodel should allow collisions for invisible textures. For the "replacement" collision model scheme.
361 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
362 bool attach_thrusters; //zookeeper: If set and this submodel or any of its parents rotates, also rotates associated thrusters.
363
364 float dumb_turn_rate = 0.0f; //Bobboau
365 int look_at_submodel = -1; //VA - number of the submodel to be looked at by this submodel (-1 if none)
366 float look_at_offset = -1.0f; //angle in radians that the submodel should be turned from its initial orientation to be considered "looking at" something (-1 if set on first eval)
367 };
368
369 #define MP_TYPE_UNUSED 0
370 #define MP_TYPE_SUBSYS 1
371
372 typedef struct mp_vert {
373 vec3d pos; // xyz coordinates of vertex in object's frame of reference
374 int nturrets; // number of turrets guarding this vertex
375 int *turret_ids; // array of indices into ship_subsys linked list (can't index using [] though)
376 float radius; // How far the closest obstruction is from this vertex
377 } mp_vert;
378
379 typedef struct model_path {
380 char name[MAX_NAME_LEN]; // name of the path. Should be unique
381 char parent_name[MAX_NAME_LEN]; // parent name of submodel that path is linked to in POF
382 int parent_submodel;
383 int nverts;
384 mp_vert *verts;
385 int goal; // Which of the verts is the one closest to the goal of this path
386 int type; // What this path takes you to... See MP_TYPE_??? defines above for details
387 int value; // This depends on the type.
388 // For MP_TYPE_UNUSED, this means nothing.
389 // For MP_TYPE_SUBSYS, this is the subsystem number this path takes you to.
390 } model_path;
391
392 // info for gun and missile banks. Also used for docking points. There should always
393 // only be two slots for each docking bay
394
395 struct w_bank
396 {
397 int num_slots = 0;
398 vec3d *pnt = nullptr;
399 vec3d *norm = nullptr;
400 float *external_model_angle_offset = nullptr;
401
~w_bankw_bank402 ~w_bank()
403 {
404 delete[] pnt;
405 delete[] norm;
406 delete[] external_model_angle_offset;
407 }
408 };
409
410 struct glow_point{
411 vec3d pnt;
412 vec3d norm;
413 float radius;
414 };
415
416 typedef struct thruster_bank {
417 int num_points;
418 glow_point *points;
419
420 // Engine wash info
421 struct engine_wash_info *wash_info_pointer; // index into Engine_wash_info
422 int obj_num; // what subsystem number this bank is on; index to ship_info->subsystems
423 int submodel_num; // what submodel number this bank is on; index to polymodel->submodel/polymodel_instance->submodel
424 } thruster_bank;
425
426 #define PULSE_SIN 1
427 #define PULSE_COS 2
428 #define PULSE_TRI 3
429 #define PULSE_SHIFTTRI 4
430
431 typedef struct glow_point_bank { // glow bank structure -Bobboau
432 int type;
433 int glow_timestamp;
434 int on_time;
435 int off_time;
436 int disp_time;
437 bool is_on;
438 int submodel_parent;
439 int LOD;
440 int num_points;
441 glow_point *points;
442 int glow_bitmap;
443 int glow_neb_bitmap;
444 } glow_point_bank;
445
446 typedef struct glow_point_bank_override {
447 char name[33];
448 int type;
449 int on_time;
450 int off_time;
451 int disp_time;
452 int glow_bitmap;
453 int glow_neb_bitmap;
454 bool is_on;
455
456 bool type_override;
457 bool on_time_override;
458 bool off_time_override;
459 bool disp_time_override;
460 bool glow_bitmap_override;
461
462 ubyte pulse_type;
463 int pulse_period;
464 float pulse_amplitude;
465 float pulse_bias;
466 float pulse_exponent;
467 bool is_lightsource;
468 float radius_multi;
469 vec3d light_color;
470 vec3d light_mix_color;
471 bool lightcone;
472 float cone_angle;
473 float cone_inner_angle;
474 vec3d cone_direction;
475 bool dualcone;
476 bool rotating;
477 vec3d rotation_axis;
478 float rotation_speed;
479
480 bool pulse_period_override;
481 } glow_point_bank_override;
482
483 // defines for docking bay things. The types are essentially flags since docking bays can probably
484 // be used for multiple things in some cases (i.e. rearming and general docking)
485 //WMC - IMPORTANT, update Dock_type_names array if you add a new one of these
486 extern flag_def_list Dock_type_names[];
487 extern int Num_dock_type_names;
488
489 #define DOCK_TYPE_CARGO (1<<0)
490 #define DOCK_TYPE_REARM (1<<1)
491 #define DOCK_TYPE_GENERIC (1<<2)
492
493 #define MAX_DOCK_SLOTS 2
494
495 typedef struct dock_bay {
496 int num_slots;
497 int type_flags; // indicates what this docking bay can be used for (i.e. cargo/rearm, etc)
498 int num_spline_paths; // number of spline paths which lead to this docking bay
499 int *splines; // array of indices into the Spline_path array
500 char name[MAX_NAME_LEN]; // name of this docking location
501 vec3d pnt[MAX_DOCK_SLOTS];
502 vec3d norm[MAX_DOCK_SLOTS];
503 } dock_bay;
504
505 // struct that holds the indicies into path information associated with a fighter bay on a capital ship
506 // NOTE: Fighter bay paths are identified by the path_name $bayN (where N is numbered from 1).
507 // Capital ships only have ONE fighter bay on the entire ship
508 // NOTE: MAX_SHIP_BAY_PATHS cannot be bumped higher than 31 without rewriting the arrival/departure flag logic.
509 #define MAX_SHIP_BAY_PATHS 31
510 typedef struct ship_bay {
511 int num_paths; // how many paths are associated with the model's fighter bay
512 int path_indexes[MAX_SHIP_BAY_PATHS]; // index into polymodel->paths[] array
513 int arrive_flags; // bitfield, set to 1 when that path number is reserved for an arrival
514 int depart_flags; // bitfield, set to 1 when that path number is reserved for a departure
515 } ship_bay_t;
516
517 // three structures now used for representing shields.
518 // shield_tri structure stores information concerning each face of the shield.
519 // verts indexes into the verts array in the higher level structure
520 // neighbors indexes into the tris array in the higher level structure
521 typedef struct shield_tri {
522 int used;
523 int verts[3]; // 3 indices into vertex list of the shield. list found in shield_info struct
524 int neighbors[3]; // indices into array of triangles. neighbor = shares edge. list found in shield_info struct
525 vec3d norm; // norm of this triangle
526 } shield_tri;
527
528 // a list of these shield_vertex structures comprimises the vertex list of the shield.
529 // The verts array in the shield_tri structure points to one of these members
530 typedef struct shield_vertex {
531 vec3d pos;
532 float u,v;
533 } shield_vertex;
534
535 // the high level shield structure. A ship without any shield has nverts and ntris set to 0.
536 // The vertex list and the tris list are used by the shield_tri structure
537 struct shield_info {
538 int nverts;
539 int ntris;
540 shield_vertex *verts;
541 shield_tri *tris;
542
543 gr_buffer_handle buffer_id;
544 int buffer_n_verts;
545 vertex_layout layout;
546
shield_infoshield_info547 shield_info() : nverts(0), ntris(0), verts(NULL), tris(NULL), buffer_id(-1), buffer_n_verts(0), layout() { }
548 };
549
550 #define BSP_LIGHT_TYPE_WEAPON 1
551 #define BSP_LIGHT_TYPE_THRUSTER 2
552
553 typedef struct bsp_light {
554 vec3d pos;
555 int type; // See BSP_LIGHT_TYPE_?? for values
556 } bsp_light;
557
558 // model_octant - There are 8 of these per model. They are a handy way to categorize
559 // a lot of model properties to get some easy 8x optimizations for model stuff.
560 typedef struct model_octant {
561 vec3d min, max; // The bounding box that makes up this octant defined as 2 points.
562 int nverts; // how many vertices are in this octant
563 vec3d **verts; // The vertices in this octant in the high-res hull. A vertex can only be in one octant.
564 int nshield_tris; // how many shield triangles are in the octant
565 shield_tri **shield_tris; // the shield triangles that make up this octant. A tri could be in multiple octants.
566 } model_octant;
567
568 #define MAX_EYES 10
569
570 typedef struct eye {
571 int parent; // parent's subobject number
572 vec3d pnt; // the point for the eye
573 vec3d norm; // direction the eye faces. Not used with first eye since player orient is used
574 } eye;
575
576 typedef struct cross_section {
577 float z;
578 float radius;
579 } cross_section;
580
581 #define MAX_MODEL_INSIGNIAS 6
582 #define MAX_INS_FACE_VECS 3
583 #define MAX_INS_VECS 81
584 #define MAX_INS_FACES 128
585 typedef struct insignia {
586 int detail_level;
587 int num_faces;
588 int faces[MAX_INS_FACES][MAX_INS_FACE_VECS]; // indices into the vecs array
589 float u[MAX_INS_FACES][MAX_INS_FACE_VECS]; // u tex coords on a per-face-per-vertex basis
590 float v[MAX_INS_FACES][MAX_INS_FACE_VECS]; // v tex coords on a per-face-per-vertex bases
591 vec3d vecs[MAX_INS_VECS]; // vertex list
592 vec3d offset; // global position offset for this insignia
593 vec3d norm[MAX_INS_VECS] ; //normal of the insignia-Bobboau
594 } insignia;
595
596 #define PM_FLAG_ALLOW_TILING (1<<0) // Allow texture tiling
597 #define PM_FLAG_AUTOCEN (1<<1) // contains autocentering info
598 #define PM_FLAG_TRANS_BUFFER (1<<2) // render transparency buffer
599 #define PM_FLAG_BATCHED (1<<3) // this model can be batch rendered
600 #define PM_FLAG_HAS_INTRINSIC_ROTATE (1<<4) // whether this model has an intrinsic rotation submodel somewhere
601
602 // Goober5000
603 class texture_info
604 {
605 private:
606 int original_texture; // what gets read in from file
607 int texture; // what texture you draw with; reset to original_textures by model_set_instance
608
609 //WMC - Removed unneeded struct and is_anim to clean this up.
610 //If num_frames is < 2, it doesn't need to be treated like an animation.
611 int num_frames;
612 float total_time; // in seconds
613
614 public:
615 texture_info();
616 texture_info(int bm_handle);
617 void clear();
618
619 int GetNumFrames();
620 int GetOriginalTexture();
621 int GetTexture();
622 float GetTotalTime();
623
624 int LoadTexture(const char *filename, const char *dbg_name = "<UNKNOWN>");
625
626 void PageIn();
627 void PageOut(bool release);
628
629 int ResetTexture();
630 int SetTexture(int n_tex);
631 };
632
633 #define TM_BASE_TYPE 0 // the standard base map
634 #define TM_GLOW_TYPE 1 // optional glow map
635 #define TM_SPECULAR_TYPE 2 // optional specular map
636 #define TM_NORMAL_TYPE 3 // optional normal map
637 #define TM_HEIGHT_TYPE 4 // optional height map (for parallax mapping)
638 #define TM_MISC_TYPE 5 // optional utility map
639 #define TM_SPEC_GLOSS_TYPE 6 // optional reflectance map (specular and gloss)
640 #define TM_AMBIENT_TYPE 7 // optional ambient occlusion map with ambient occlusion and cavity occlusion factors for red and green channels.
641 #define TM_NUM_TYPES 8 //WMC - Number of texture_info objects in texture_map
642 //Used by scripting - if you change this, do a search
643 //to update switch() statement in lua.cpp
644 // taylor
645 //WMC - OOPified
646 class texture_map
647 {
648 public:
649 texture_info textures[TM_NUM_TYPES];
650
651 bool is_ambient;
652 bool is_transparent;
653
654 int FindTexture(int bm_handle);
655 int FindTexture(const char* name);
656
657 void PageIn();
658 void PageOut(bool release);
659
660 void Clear();
661 void ResetToOriginal();
662
texture_map()663 texture_map()
664 : is_ambient(false), is_transparent(false)
665 {}
666 };
667
668 #define MAX_REPLACEMENT_TEXTURES MAX_MODEL_TEXTURES * TM_NUM_TYPES
669
670 // Goober5000 - since we need something < 0
671 #define REPLACE_WITH_INVISIBLE -47
672
673 //used to describe a polygon model
674 // NOTE: Because WMC OOPified the textures, this must now be treated as a class, rather than a struct.
675 // Additionally, a lot of model initialization and de-initialization is currently done in model_load or model_unload.
676 class polymodel
677 {
678 public:
679 // initialize to 0 and NULL because previously a memset was used
polymodel()680 polymodel()
681 : id(-1), version(0), flags(0), n_detail_levels(0), num_debris_objects(0), n_models(0), num_lights(0), lights(NULL),
682 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),
683 n_thrusters(0), gun_banks(NULL), missile_banks(NULL), docking_bays(NULL), thrusters(NULL), ship_bay(NULL), shield(),
684 shield_collision_tree(NULL), sldc_size(0), n_paths(0), paths(NULL), mass(0), num_xc(0), xc(NULL), num_split_plane(0),
685 num_ins(0), used_this_mission(0), n_glow_point_banks(0), glow_point_banks(nullptr),
686 vert_source()
687 {
688 filename[0] = 0;
689 mins = maxs = autocenter = center_of_mass = vmd_zero_vector;
690 moment_of_inertia = vmd_identity_matrix;
691
692 memset(&detail, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(int));
693 memset(&detail_depth, 0, MAX_MODEL_DETAIL_LEVELS * sizeof(float));
694 memset(&debris_objects, 0, MAX_DEBRIS_OBJECTS * sizeof(int));
695 memset(&bounding_box, 0, 8 * sizeof(vec3d));
696 memset(&view_positions, 0, MAX_EYES * sizeof(eye));
697 memset(&octants, 0, 8 * sizeof(model_octant));
698 memset(&split_plane, 0, MAX_SPLIT_PLANE * sizeof(float));
699 memset(&ins, 0, MAX_MODEL_INSIGNIAS * sizeof(insignia));
700
701 #ifndef NDEBUG
702 ram_used = 0;
703 debug_info_size = 0;
704 debug_info = NULL;
705 #endif
706 }
707
708
709 int id; // what the polygon model number is. (Index in Polygon_models)
710 int version;
711 char filename[FILESPEC_LENGTH];
712
713 uint flags; // 1=allow tiling
714 int n_detail_levels;
715 int detail[MAX_MODEL_DETAIL_LEVELS];
716 float detail_depth[MAX_MODEL_DETAIL_LEVELS];
717
718 int num_debris_objects;
719 int debris_objects[MAX_DEBRIS_OBJECTS];
720
721 int n_models;
722
723 vec3d mins,maxs; //min,max for whole model
724 vec3d bounding_box[8];
725
726 int num_lights; // how many lights there are
727 bsp_light * lights; // array of light info
728
729 int n_view_positions; // number of viewing positions available on this ship
730 eye view_positions[MAX_EYES]; //viewing positions. Default to {0,0,0}. in location 0
731
732 vec3d autocenter; // valid only if PM_FLAG_AUTOCEN is set
733
734 float rad; // The radius of everything in the model; shields, thrusters.
735 float core_radius; // The radius to be used for collision detection in small ship vs big ships.
736 // This is equal to 1/2 of the smallest dimension of the hull's bounding box.
737 // texture maps for model
738 int n_textures;
739 texture_map maps[MAX_MODEL_TEXTURES];
740
741 bsp_info *submodel; // an array of size n_models of submodel info.
742
743 // linked lists for special polygon types on this model. Most ships I think will have most
744 // of these. (most ships however, probably won't have approach points).
745 int n_guns; // number of primary gun points (not counting turrets)
746 int n_missiles; // number of secondary missile points (not counting turrets)
747 int n_docks; // number of docking points
748 int n_thrusters; // number of thrusters on this ship.
749 w_bank *gun_banks; // array of gun banks
750 w_bank *missile_banks; // array of missile banks
751 dock_bay *docking_bays; // array of docking point pairs
752 thruster_bank *thrusters; // array of thruster objects -- likely to change in the future
753 ship_bay_t *ship_bay; // contains path indexes for ship bay approach/depart paths
754
755 shield_info shield; // new shield information
756 ubyte *shield_collision_tree;
757 int sldc_size;
758 SCP_vector<vec3d> shield_points;
759
760 int n_paths;
761 model_path *paths;
762
763 // physics info
764 float mass;
765 vec3d center_of_mass;
766 matrix moment_of_inertia;
767
768 model_octant octants[8];
769
770 int num_xc; // number of cross sections
771 cross_section* xc; // pointer to array of cross sections (used in big ship explosions)
772
773 int num_split_plane; // number of split planes
774 float split_plane[MAX_SPLIT_PLANE]; // actual split plane z coords (for big ship explosions)
775
776 insignia ins[MAX_MODEL_INSIGNIAS];
777 int num_ins;
778
779 #ifndef NDEBUG
780 int ram_used; // How much RAM this model uses
781 int debug_info_size;
782 char *debug_info;
783 #endif
784
785 int used_this_mission; // used for page-in system, how many times this model has been loaded per mission - taylor
786
787 int n_glow_point_banks; // number of glow points on this ship. -Bobboau
788 glow_point_bank *glow_point_banks; // array of glow objects -Bobboau
789
790 indexed_vertex_source vert_source;
791
792 vertex_buffer detail_buffers[MAX_MODEL_DETAIL_LEVELS];
793 };
794
795 // Call once to initialize the model system
796 void model_init();
797
798 // call to unload a model (works like bm_unload()), "force" SHOULD NEVER BE SET outside of modelread.cpp!!!!
799 void model_unload(int modelnum, int force = 0);
800
801 // Call to free all existing models
802 void model_free_all();
803 void model_instance_free_all();
804
805 // Loads a model from disk and returns the model number it loaded into.
806 int model_load(const char *filename, int n_subsystems, model_subsystem *subsystems, int ferror = 1, int duplicate = 0);
807
808 int model_create_instance(bool is_ship, int model_num);
809 void model_delete_instance(int model_instance_num);
810
811 // Goober5000
812 void model_load_texture(polymodel *pm, int i, char *file);
813
814 // Returns a pointer to the polymodel structure for model 'n'
815 polymodel *model_get(int model_num);
816
817 polymodel_instance* model_get_instance(int model_instance_num);
818
819 // routine to copy subsystems. Must be called when subsystems sets are the same -- see ship.cpp
820 void model_copy_subsystems(int n_subsystems, model_subsystem *d_sp, model_subsystem *s_sp);
821
822 // If MR_FLAG_OUTLINE bit set this color will be used for outlines.
823 // This defaults to black.
824 void model_set_outline_color(int r, int g, int b);
825
826 // IF MR_LOCK_DETAIL is set, then it will always draw detail level 'n'
827 // This defaults to 0. (0=highest, larger=lower)
828 void model_set_detail_level(int n);
829
830 // Flags you can pass to model_render
831 #define MR_NORMAL (0) // Draw a normal object
832 #define MR_SHOW_OUTLINE (1<<0) // Draw the object in outline mode. Color specified by model_set_outline_color
833 #define MR_SKYBOX (1<<1) // Draw as a skybox
834 #define MR_DESATURATED (1<<2) // Draw model in monochrome using outline color
835 #define MR_STENCIL_WRITE (1<<3) // Write stencil buffere where the model was rendered
836 #define MR_STENCIL_READ (1<<4) // Only draw pixels of the model where the stencil buffer has the right value (see MR_STENCIL_WRITE)
837 #define MR_SHOW_THRUSTERS (1<<5) // Show the engine thrusters. See model_set_thrust for how long it draws.
838 #define MR_NO_COLOR_WRITES (1<<6) // Don't write anything to the color buffers (used when setting the stencil buffer)
839 #define MR_NO_POLYS (1<<7) // Don't draw the polygons.
840 #define MR_NO_LIGHTING (1<<8) // Don't perform any lighting on the model.
841 #define MR_NO_TEXTURING (1<<9) // Draw textures as flat-shaded polygons.
842 #define MR_NO_CORRECT (1<<10) // Don't to correct texture mapping
843 #define MR_NO_SMOOTHING (1<<11) // Don't perform smoothing on vertices.
844 #define MR_IS_ASTEROID (1<<12) // When set, treat this as an asteroid.
845 #define MR_IS_MISSILE (1<<13) // When set, treat this as a missilie. No lighting, small thrusters.
846 #define MR_SHOW_OUTLINE_PRESET (1<<14) // Draw the object in outline mode. Color assumed to be set already.
847 #define MR_SHOW_INVISIBLE_FACES (1<<15) // Show invisible faces as green...
848 #define MR_AUTOCENTER (1<<16) // Always use the center of the hull bounding box as the center, instead of the pivot point
849 #define MR_EMPTY_SLOT3 (1<<17) // draw bay paths
850 #define MR_ALL_XPARENT (1<<18) // render it fully transparent
851 #define MR_NO_ZBUFFER (1<<19) // switch z-buffering off completely
852 #define MR_NO_CULL (1<<20) // don't cull backfacing poly's
853 #define MR_EMPTY_SLOT4 (1<<21) // force a given texture to always be used
854 #define MR_NO_BATCH (1<<22) // don't use submodel batching when rendering
855 #define MR_EDGE_ALPHA (1<<23) // makes norms that are faceing away from you render more transparent -Bobboau
856 #define MR_CENTER_ALPHA (1<<24) // oposite of above -Bobboau
857 #define MR_NO_FOGGING (1<<25) // Don't fog - taylor
858 #define MR_SHOW_OUTLINE_HTL (1<<26) // Show outlines (wireframe view) using HTL method
859 #define MR_NO_GLOWMAPS (1<<27) // disable rendering of glowmaps - taylor
860 #define MR_FULL_DETAIL (1<<28) // render all valid objects, particularly ones that are otherwise in/out of render boxes - taylor
861 #define MR_FORCE_CLAMP (1<<29) // force clamp - Hery
862 #define MR_EMPTY_SLOT5 (1<<30) // Use a animated Shader - Valathil
863 #define MR_ATTACHED_MODEL (1<<31) // Used for attached weapon model lodding
864
865 #define MR_DEBUG_PIVOTS (1<<0) // Show the pivot points
866 #define MR_DEBUG_PATHS (1<<1) // Show the paths associated with a model
867 #define MR_DEBUG_RADIUS (1<<2) // Show the radius around the object
868 #define MR_DEBUG_SHIELDS (1<<3) // Show the shield mesh
869 #define MR_DEBUG_BAY_PATHS (1<<4) // draw bay paths
870 #define MR_DEBUG_NO_DIFFUSE (1<<5)
871 #define MR_DEBUG_NO_SPEC (1<<6)
872 #define MR_DEBUG_NO_NORMAL (1<<7)
873 #define MR_DEBUG_NO_ENV (1<<8)
874 #define MR_DEBUG_NO_GLOW (1<<9)
875 #define MR_DEBUG_NO_HEIGHT (1<<10)
876 #define MR_DEBUG_NO_AMBIENT (1<<11)
877 #define MR_DEBUG_NO_MISC (1<<12)
878 #define MR_DEBUG_NO_REFLECT (1<<13)
879
880 //Defines for the render parameter of model_render, model_really_render and model_render_buffers
881 #define MODEL_RENDER_OPAQUE 1
882 #define MODEL_RENDER_TRANS 2
883 #define MODEL_RENDER_ALL 3
884
885 // Returns the radius of a model
886 float model_get_radius(int modelnum);
887 float submodel_get_radius(int modelnum, int submodelnum);
888
889 // Returns the core radius (smallest dimension of hull's bounding box, used for collision detection with big ships only)
890 float model_get_core_radius(int modelnum);
891
892 // Returns zero is x1,y1,x2,y2 are valid
893 // returns 1 for invalid model, 2 for point offscreen.
894 // note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
895 // This function looks at the object's bounding box and it's orientation,
896 // so the bounds will change as the object rotates, to give the minimum bouding
897 // rect.
898 extern int model_find_2d_bound_min(int model_num,matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);
899
900 // Returns zero is x1,y1,x2,y2 are valid
901 // returns 1 for invalid model, 2 for point offscreen.
902 // note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
903 // This function looks at the object's bounding box and it's orientation,
904 // so the bounds will change as the object rotates, to give the minimum bouding
905 // rect.
906 int submodel_find_2d_bound_min(int model_num,int submodel, matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);
907
908
909 // Returns zero is x1,y1,x2,y2 are valid
910 // Returns 2 for point offscreen.
911 // note that x1,y1,x2,y2 aren't clipped to 2d screen coordinates!
912 // This function just looks at the radius, and not the orientation, so the
913 // bounding box won't change depending on the obj's orient.
914 int subobj_find_2d_bound(float radius, matrix *orient, vec3d * pos,int *x1, int *y1, int *x2, int *y2);
915
916 // stats variables
917 #ifndef NDEBUG
918 extern int modelstats_num_polys;
919 extern int modelstats_num_polys_drawn;
920 extern int modelstats_num_verts;
921 extern int modelstats_num_sortnorms;
922 #endif
923
924 // Tries to move joints so that the turret points to the point dst.
925 extern int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, ship_subsys *ss, vec3d *dst, bool reset = false);
926
927 // Rotates the angle of a submodel. Use this so the right unlocked axis
928 // gets stuffed.
929 extern void submodel_canonicalize(bsp_info *sm, submodel_instance *smi, bool clamp);
930 extern void submodel_rotate(model_subsystem *psub, submodel_instance *smi);
931 extern void submodel_rotate(bsp_info *sm, submodel_instance *smi);
932
933 // Rotates the angle of a submodel. Use this so the right unlocked axis
934 // gets stuffed. Does this for stepped rotations
935 void submodel_stepped_rotate(model_subsystem *psub, submodel_instance *smi);
936
937 // Goober5000
938 // For a submodel, return its overall offset from the main model.
939 extern void model_find_submodel_offset(vec3d *outpnt, const polymodel *pm, int sub_model_num);
940
941 // Given a point (pnt) that is in sub_model_num's frame of
942 // reference, and given the object's orient and position,
943 // return the point in 3-space in outpnt.
944 extern void model_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_num, int submodel_num, const matrix *objorient, const vec3d *objpos);
945 extern void model_instance_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_instance_num, int submodel_num, const matrix *objorient, const vec3d *objpos);
946 extern void model_find_world_point(vec3d *outpnt, vec3d *mpnt, const polymodel *pm, int submodel_num, const matrix *objorient, const vec3d *objpos);
947 extern void model_instance_find_world_point(vec3d *outpnt, vec3d *mpnt, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient, const vec3d *objpos);
948
949 // Given a point in the world RF, find the corresponding point in the model RF.
950 // This is special purpose code, specific for model collision.
951 // NOTE - this code ASSUMES submodel is 1 level down from hull (detail[0])
952 void world_find_model_instance_point(vec3d *out, vec3d *world_pt, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *orient, const vec3d *pos);
953
954 extern void find_submodel_instance_point(vec3d *outpnt, const polymodel *pm, const polymodel_instance *pmi, int submodel_num);
955 extern void find_submodel_instance_point_normal(vec3d *outpnt, vec3d *outnorm, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const vec3d *submodel_pnt, const vec3d *submodel_norm);
956 extern void find_submodel_instance_point_orient(vec3d *outpnt, matrix *outorient, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const vec3d *submodel_pnt, const matrix *submodel_orient);
957 extern void find_submodel_instance_world_point(vec3d *outpnt, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient, const vec3d *objpos);
958
959 // Given a polygon model index, find a list of rotating submodels to be used for collision
960 void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp);
961
962 // Given a polygon model index, get a list of a model tree starting from that index
963 void model_get_submodel_tree_list(SCP_vector<int> &submodel_vector, polymodel* pm, int mn);
964
965 // For a rotating submodel, find a point on the axis
966 void model_init_submodel_axis_pt(polymodel *pm, polymodel_instance *pmi, int submodel_num);
967
968 // Given a direction (pnt) that is in sub_model_num's frame of
969 // reference, and given the object's orient and position,
970 // return the point in 3-space in outpnt.
971 extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_num, int submodel_num, const matrix *objorient);
972 extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, int submodel_num, const matrix *objorient);
973 extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient, bool use_submodel_parent = false);
974 extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient);
975
976 // Clears all the submodel instances stored in a model to their defaults.
977 extern void model_clear_instance(int model_num);
978
979 // Sets rotating submodel turn info to that stored in model
980 extern void model_set_submodel_turn_info(submodel_instance *smi, float turn_rate, float turn_accel);
981
982 // Sets the submodel instance data in a submodel
983 extern void model_set_up_techroom_instance(ship_info *sip, int model_instance_num);
984
985 void model_update_instance(int model_instance_num, int submodel_num, flagset<Ship::Subsystem_Flags>& flags);
986 void model_update_instance(polymodel *pm, polymodel_instance *pmi, int submodel_num, flagset<Ship::Subsystem_Flags>& flags);
987
988 // Adds an electrical arcing effect to a submodel
989 void model_instance_clear_arcs(polymodel *pm, polymodel_instance *pmi);
990 void model_instance_add_arc(polymodel *pm, polymodel_instance *pmi, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type);
991
992 // Gets two random points on the surface of a submodel
993 extern void submodel_get_two_random_points(int model_num, int submodel_num, vec3d *v1, vec3d *v2, vec3d *n1 = NULL, vec3d *n2 = NULL);
994
995 extern void submodel_get_two_random_points_better(int model_num, int submodel_num, vec3d * v1, vec3d * v2, int seed = -1);
996
997 // gets the average position of the mesh at a particular z slice, approximately
998 void submodel_get_cross_sectional_avg_pos(int model_num, int submodel_num, float z_slice_pos, vec3d* pos);
999 // generates a random position more or less inside-ish a mesh at a particular z slice
1000 void submodel_get_cross_sectional_random_pos(int model_num, int submodel_num, float z_slice_pos, vec3d* pos);
1001
1002 // gets the index into the docking_bays array of the specified type of docking point
1003 // Returns the index. second functions returns the index of the docking bay with
1004 // the specified name
1005 extern int model_find_dock_index(int modelnum, int dock_type, int index_to_start_at = 0);
1006 extern int model_find_dock_name_index(int modelnum, const char* name);
1007
1008 // returns the actual name of a docking point on a model, needed by Fred.
1009 char *model_get_dock_name(int modelnum, int index);
1010
1011 // returns number of docking points for a model
1012 int model_get_num_dock_points(int modelnum);
1013 int model_get_dock_index_type(int modelnum, int index);
1014
1015 // get all the different docking point types on a model
1016 int model_get_dock_types(int modelnum);
1017
1018 // Goober5000
1019 // returns index in [0, MAX_SHIP_BAY_PATHS)
1020 int model_find_bay_path(int modelnum, char *bay_path_name);
1021
1022 // Returns number of polygons in a submodel;
1023 int submodel_get_num_polys(int model_num, int submodel_num);
1024
1025
1026 // This is the interface to model_check_collision. Rather than passing all these
1027 // values and returning values in globals, just fill in a temporary variable with
1028 // the input values and call model_check_collision
1029 typedef struct mc_info {
1030 // Input values
1031 int model_instance_num;
1032 int model_num; // What model to check
1033 int submodel_num; // What submodel to check if MC_SUBMODEL is set
1034 matrix *orient; // The orient of the model
1035 vec3d *pos; // The pos of the model in world coordinates
1036 vec3d *p0; // The starting point of the ray (sphere) to check
1037 vec3d *p1; // The ending point of the ray (sphere) to check
1038 int flags; // Flags that the model_collide code looks at. See MC_??? defines
1039 float radius; // If MC_CHECK_THICK is set, checks a sphere moving with the radius.
1040 int lod; // Which detail level of the submodel to check instead
1041
1042 // Return values
1043 int num_hits; // How many collisions were found
1044 float hit_dist; // The distance from p0 to hitpoint
1045 vec3d hit_point; // Where the collision occurred at in hit_submodel's coordinate system
1046 vec3d hit_point_world; // Where the collision occurred at in world coordinates
1047 int hit_submodel; // Which submodel got hit.
1048 int hit_bitmap; // Which texture got hit. -1 if not a textured poly
1049 float hit_u, hit_v; // Where on hit_bitmap the ray hit. Invalid if hit_bitmap < 0
1050 int shield_hit_tri; // Which triangle on the shield got hit or -1 if none
1051 vec3d hit_normal; // Vector normal of polygon of collision. (This is in submodel RF)
1052 int edge_hit; // Set if an edge got hit. Only valid if MC_CHECK_THICK is set.
1053 ubyte *f_poly; // pointer to flat poly where we intersected
1054 ubyte *t_poly; // pointer to tmap poly where we intersected
1055 bsp_collision_leaf *bsp_leaf;
1056
1057 // flags can be changed for the case of sphere check finds an edge hit
1058 } mc_info;
1059
mc_info_init(mc_info * mc)1060 inline void mc_info_init(mc_info *mc)
1061 {
1062 mc->model_instance_num = -1;
1063 mc->model_num = -1;
1064 mc->submodel_num = -1;
1065 mc->orient = nullptr;
1066 mc->pos = nullptr;
1067 mc->p0 = nullptr;
1068 mc->p1 = nullptr;
1069 mc->flags = 0;
1070 mc->lod = 0;
1071 mc->radius = 0;
1072 mc->num_hits = 0;
1073 mc->hit_dist = 0;
1074 mc->hit_point = vmd_zero_vector;
1075 mc->hit_point_world = vmd_zero_vector;
1076 mc->hit_submodel = -1;
1077 mc->hit_bitmap = -1;
1078 mc->hit_u = 0; mc->hit_v = 0;
1079 mc->shield_hit_tri = -1;
1080 mc->hit_normal = vmd_zero_vector;
1081 mc->edge_hit = 0;
1082 mc->f_poly = nullptr;
1083 mc->t_poly = nullptr;
1084 mc->bsp_leaf = nullptr;
1085 }
1086
1087
1088 //======== MODEL_COLLIDE ============
1089
1090 // Model Collision flags, used in model_collide()
1091 #define MC_CHECK_MODEL (1<<0) // Check the polygons in the model.
1092 #define MC_CHECK_SHIELD (1<<1) // check for collision against shield, if it exists.
1093 #define MC_ONLY_SPHERE (1<<2) // Only check bounding sphere. Not accurate, but fast.
1094 // NOTE! This doesn't set hit_point correctly with MC_CHECK_SPHERELINE
1095 #define MC_ONLY_BOUND_BOX (1<<3) // Only check bounding boxes. Pretty accurate and slower than MC_ONLY_SPHERE.
1096 // Checks the rotatated bounding box of each submodel.
1097 // NOTE! This doesn't set hit_point correctly with MC_CHECK_SPHERELINE
1098 #define MC_CHECK_RAY (1<<4) // Checks a ray from p0 *through* p1 on to infinity
1099 #define MC_CHECK_SPHERELINE (1<<5) // Checks a moving sphere rather than just a ray. Radius
1100 #define MC_SUBMODEL (1<<6) // If this is set, only check the submodel specified in mc->submodel_num. Use with MC_CHECK_MODEL
1101 #define MC_SUBMODEL_INSTANCE (1<<7) // Check submodel and its children (of a rotating submodel)
1102 #define MC_CHECK_INVISIBLE_FACES (1<<8) // Check the invisible faces.
1103
1104
1105 /*
1106 Checks to see if a vector from p0 to p0 collides with a model of
1107 type 'model_num' at 'orient' 'pos'.
1108
1109 Returns the number of polys that were hit. Zero is none, obviously.
1110 Return true if a collision with hull (or shield, if MC_CHECK_SHIELD set),
1111 else return false.
1112
1113 If it did it one or more, then hitpt is the closest 3d point that the
1114 vector hit. See the MC_? defines for flag values.
1115
1116 Model_collide can test a sphere against either (1) shield or (2) model.
1117
1118 To check a sphere, set the radius of sphere in mc_info structure and
1119 set the flag MC_CHECK_SPHERE.
1120
1121 Here is a sample for how to use:
1122
1123 mc_info mc;
1124
1125 mc.model_num = ???; // Fill in the model to check
1126 mc.orient = &obj->orient; // The object's orient
1127 mc.pos = &obj->pos; // The object's position
1128 mc.p0 = &p0; // Point 1 of ray to check
1129 mc.p1 = &p1; // Point 2 of ray to check
1130 mc.flags = MC_CHECK_MODEL; // flags
1131
1132 ** TO COLLIDE AGAINST A LINE SEGMENT
1133
1134 model_collide(&mc);
1135 if (mc.num_hits) {
1136 // We hit submodel mc.hit_submodel on texture mc.hitbitmap,
1137 // at point mc.hit_point_world, with uv's of mc.hit_u, mc.hit_v.
1138 }
1139
1140 ** TO COLLIDE AGAINST A SPHERE
1141 mc.flags |= MC_CHECK_SPHERELINE;
1142 mc.radius = radius;
1143
1144 model_collide(&mc, radius);
1145 if (mc.num_hits) {
1146 // We hit submodel mc.hit_submodel on texture mc.hitbitmap,
1147 // at point mc.hit_point_world, with uv's of mc.hit_u, mc.hit_v.
1148 // Check (mc.edge_hit) to see if we hit an edge
1149 }
1150 */
1151
1152 int model_collide(mc_info *mc_info_obj);
1153 void model_collide_parse_bsp(bsp_collision_tree *tree, void *model_ptr, int version);
1154
1155 bsp_collision_tree *model_get_bsp_collision_tree(int tree_index);
1156 void model_remove_bsp_collision_tree(int tree_index);
1157 int model_create_bsp_collision_tree();
1158
1159 //=========================== MODEL OCTANT STUFF ================================
1160
1161 // Models are now divided into 8 octants. Shields too.
1162 // This made the collision code faster. Shield is 4x and ship faces
1163 // are about 2x faster.
1164
1165 // Before, calling model_collide with flags=0 didn't check the shield
1166 // but did check the model itself. Setting the shield flags caused
1167 // the shield to get check along with the ship.
1168 // Now, you need to explicitly tell the model_collide code to check
1169 // the model, so you can check the model or shield or both.
1170
1171 // If you need to check them both, do it in one call; this saves some
1172 // time. If checking the shield is sufficient for determining
1173 // something (like if it is under the hud) then use just shield
1174 // check, it is at least 5x faster than checking the model itself.
1175
1176
1177 // Model octant ordering - this is a made up ordering, but it makes sense.
1178 // X Y Z index description
1179 // - - - 0 left bottom rear
1180 // - - + 1 left bottom front
1181 // - + - 2 left top rear
1182 // - + + 3 left top front
1183 // + - - 4 right bottom rear
1184 // + - + 5 right bottom front
1185 // + + - 6 right top rear
1186 // + + + 7 right top front
1187
1188 typedef struct mst_info {
1189 int primary_bitmap;
1190 int primary_glow_bitmap;
1191 int secondary_glow_bitmap;
1192 int tertiary_glow_bitmap;
1193 int distortion_bitmap;
1194
1195 bool use_ab;
1196 float glow_noise;
1197 vec3d rotvel;
1198 vec3d length;
1199
1200 float glow_rad_factor;
1201 float secondary_glow_rad_factor;
1202 float tertiary_glow_rad_factor;
1203 float glow_length_factor;
1204 float distortion_rad_factor;
1205 float distortion_length_factor;
1206 bool draw_distortion;
1207
mst_infomst_info1208 mst_info() : primary_bitmap(-1), primary_glow_bitmap(-1), secondary_glow_bitmap(-1), tertiary_glow_bitmap(-1), distortion_bitmap(-1),
1209 use_ab(false), glow_noise(1.0f), rotvel(vmd_zero_vector), length(vmd_zero_vector), glow_rad_factor(1.0f),
1210 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),
1211 draw_distortion(true)
1212 {}
1213 } mst_info;
1214
1215 // scale the engines thrusters by this much
1216 // Only enabled if MR_SHOW_THRUSTERS is on
1217 void model_set_thrust(int model_num = -1, mst_info *mst = NULL);
1218
1219
1220 //=======================================================================================
1221 // Finds the closest point on a model to a point in space. Actually only finds a point
1222 // on the bounding box of the model.
1223 // Given:
1224 // model_num Which model
1225 // submodel_num Which submodel, -1 for hull
1226 // orient Orientation of the model
1227 // pos Position of the model
1228 // eye_pos Point that you want to find the closest point to
1229 // Returns:
1230 // distance from eye_pos to closest_point. 0 means eye_pos is
1231 // on or inside the bounding box.
1232 // Also fills in outpnt with the actual closest point.
1233 float model_find_closest_point(vec3d *outpnt, int model_num, int submodel_num, const matrix *orient, const vec3d *pos, const vec3d *eye_pos);
1234
1235 // Like the above, but finds the closest two points to each other.
1236 float model_find_closest_points(vec3d *outpnt1, int model_num1, int submodel_num1, const matrix *orient1, const vec3d *pos1, vec3d *outpnt2, int model_num2, int submodel_num2, const matrix *orient2, const vec3d *pos2);
1237
1238 // see if the given texture is used by the passed model. 0 if not used, 1 if used, -1 on error
1239 int model_find_texture(int model_num, int bitmap);
1240
1241 // find closest point on extended bounding box (the bounding box plus all the planes that make it up)
1242 // returns closest distance to extended box
1243 // positive return value means start_point is outside extended box
1244 // displaces closest point an optional amount delta to the outside of the box
1245 // closest_box_point can be NULL.
1246 float get_world_closest_box_point_with_delta(vec3d *closest_box_point, object *box_obj, vec3d *start_point, int *is_inside, float delta);
1247
1248 // given a newly loaded model, page in all textures
1249 void model_page_in_textures(int modelnum, int ship_info_index = -1);
1250
1251 // given a model, unload all of its textures
1252 void model_page_out_textures(int model_num, bool release = false);
1253
1254 void model_do_intrinsic_rotations(int model_instance_num = -1);
1255
1256 int model_should_render_engine_glow(int objnum, int bank_obj);
1257
1258 bool model_get_team_color(team_color *clr, const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime);
1259
1260 void moldel_calc_facing_pts( vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add, vec3d *Eyeposition );
1261
1262 void model_render_insignias(polymodel *pm, int detail_level, int bitmap_num);
1263
1264 void model_draw_debug_points( polymodel *pm, bsp_info * submodel, uint flags );
1265
1266 void model_render_shields( polymodel * pm, uint flags );
1267
1268 void model_draw_paths_htl( int model_num, uint flags );
1269
1270 void model_draw_bay_paths_htl(int model_num);
1271
1272 bool model_interp_config_buffer(indexed_vertex_source *vert_src, vertex_buffer *vb, bool update_ibuffer_only);
1273 bool model_interp_pack_buffer(indexed_vertex_source *vert_src, vertex_buffer *vb);
1274 void model_interp_submit_buffers(indexed_vertex_source *vert_src, size_t vertex_stride);
1275 void model_allocate_interp_data(int n_verts = 0, int n_norms = 0);
1276
1277 void glowpoint_init();
1278 SCP_vector<glow_point_bank_override>::iterator get_glowpoint_bank_override_by_name(const char* name);
1279 extern SCP_vector<glow_point_bank_override> glowpoint_bank_overrides;
1280
1281 #endif // _MODEL_H
1282