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
|