52 #define MAX_SUBMODEL_COLLISION_ROT_ANGLE (PI / 6.0f) // max 30 degrees per frame
61 static int model_initted = 0;
72 static uint Global_checksum = 0;
75 #define PM_COMPATIBLE_VERSION 1900
80 #define PM_OBJFILE_MAJOR_VERSION 30
82 static int Model_signature = 0;
137 : submodel_num(_submodel_num)
139 memset(&submodel_info_1, 0,
sizeof(submodel_info_1));
153 : is_ship(_is_ship), model_instance_num(_model_instance_num), list()
203 for (i=0; i<pm->
n_paths; i++ ) {
229 for (i=0; i<pm->
n_docks; i++ ) {
265 for (i = 0; i < pm->
n_models; i++) {
266 if ( !Cmdline_nohtl ) {
282 if ( !Cmdline_nohtl ) {
308 if ( pm->
id == it->model_num ) {
312 if ( pm->
id == it->cockpit_model_num ) {
313 it->cockpit_model_num = -1;
316 if ( pm->
id == it->model_num_hud ) {
317 it->model_num_hud = -1;
334 Polygon_models[
num] = NULL;
341 if ( !model_initted) {
346 mprintf((
"Freeing all existing models...\n" ));
360 for ( i = 0; i < Polygon_model_instances.size(); ++
i ) {
361 if ( Polygon_model_instances[i] ) {
368 Nmodel_instance_num = -1;
370 Polygon_model_instances.clear();
377 if ( !model_initted ) {
382 mprintf((
"Starting model page in...\n" ));
385 if (Polygon_models[i] != NULL)
396 mprintf((
"Stopping model page in...\n" ));
399 if (Polygon_models[i] == NULL)
402 if (Polygon_models[i]->used_this_mission)
413 if ( model_initted ) {
423 Polygon_models[
i] = NULL;
436 while ( isspace(*p) || (*p ==
'=') )
439 while ( !iscntrl(*p1) )
457 va_start(args, n_args);
459 for (
int i = 0;
i < n_args; ++
i)
461 const char *
option = va_arg(args,
const char *);
464 if ((pos = strstr(props, option)) !=
nullptr)
470 pos += strlen(option);
492 int prop_string(
char *props,
char **
p,
const char *option0,
const char *option1)
496 int prop_string(
char *props,
char **
p,
const char *option0,
const char *option1,
const char *option2)
498 return prop_string(props, p, 3, option0, option1, option2);
510 for (i = 0; i < n_subsystems; i++ ) {
512 for ( j = 0; j < n_subsystems; j++ ) {
544 if ( j == n_subsystems )
558 if ( (p = strstr(props,
"$name")) != NULL)
567 if ( strstr(lcdname,
"engine") ) {
569 }
else if ( strstr(lcdname,
"radar") ) {
571 }
else if ( strstr(lcdname,
"turret") ) {
575 if ( (p = strstr(props,
"$fov")) != NULL )
583 if ( (p = strstr(props,
"$crewspot")) != NULL) {
588 }
else if ( strstr(lcdname,
"navigation") ) {
590 }
else if ( strstr(lcdname,
"communication") ) {
592 }
else if ( strstr(lcdname,
"weapon") ) {
594 }
else if ( strstr(lcdname,
"sensor") ) {
596 }
else if ( strstr(lcdname,
"solar") ) {
598 }
else if ( strstr(lcdname,
"gas") ) {
600 }
else if ( strstr(lcdname,
"activator") ) {
604 mprintf((
"Subsystem '%s' on ship %s is not recognized as a common subsystem type\n", dname,
model_get(model_num)->
filename));
607 if ( (strstr(props,
"$triggered")) != NULL ) {
613 if (
prop_string(props,
nullptr,
"$dumb_rotate") >= 0) {
620 else if ((idx =
prop_string(props, &p,
"$rotate_time",
"$rotate_rate",
"$rotate")) >= 0) {
628 if (idx == 0 || idx == 2) {
629 float turn_time =
static_cast<float>(atof(buf));
630 if (turn_time == 0.0
f) {
634 turn_rate =
PI2 / turn_time;
637 turn_rate =
static_cast<float>(atof(buf));
641 if ( (p = strstr(props,
"$pbank")) != NULL) {
653 if ( (strstr(props,
"$stepped")) != NULL) {
659 if ( (p = strstr(props,
"$steps")) != NULL) {
667 if ( (p = strstr(props,
"$t_paused")) != NULL) {
675 if ( (p = strstr(props,
"$t_transit")) != NULL) {
683 if ( (p = strstr(props,
"$fraction_accel")) != NULL) {
716 if (delta_angle >
PI) {
717 delta_angle = (
PI2 - delta_angle);
730 if (!ss_warning_shown) {
732 ss_warning_shown = 1;
741 for (i = 0; i < n_subsystems; i++ ) {
742 subsystemp = &slist[
i];
748 nprintf((
"Model",
"NOTE: Subsystem \"%s\" in model \"%s\" is represented as \"%s\" in ships.tbl. This works fine in FSO v3.6 and up, "
762 subsystemp->
pnt = *pnt;
764 set_subsystem_info(model_num, subsystemp, props, subobj_name);
772 if ( !ss_warning_shown) {
773 _splitpath(model_filename, NULL, NULL, bname, NULL);
775 Warning(
LOCATION,
"Not all subsystems in model \"%s\" have a record in ships.tbl.\nThis can cause game to crash.\n\nList of subsystems not found from table is in log file.\n",
model_get(model_num)->
filename );
777 ss_warning_shown = 1;
784 _splitpath(model_filename, NULL, NULL, bname, NULL);
785 mprintf((
"A subsystem was found in model %s that does not have a record in ships.tbl.\nA list of subsystems for this ship will be dumped to:\n\ndata%stables%s%s.subsystems for inclusion\ninto ships.tbl.\n", model_filename,
DIR_SEPARATOR_STR,
DIR_SEPARATOR_STR, bname));
786 char tmp_buffer[128];
787 sprintf(tmp_buffer,
"$Subsystem:\t\t\t%s,1,0.0\n", subobj_name);
788 cfputs(tmp_buffer, ss_fp);
798 if ( modelnum < 0 )
return;
799 if (obj==NULL)
return;
801 if (ident[0] ==
'\0') {
804 }
else if ( islast ) {
815 while( child > -1 ) {
867 for (i = 0; i < pm->
n_models; i++) {
872 for ( i = 0; i < pm->
n_models; i++ ) {
878 bool use_batched_rendering =
true;
889 use_batched_rendering =
false;
895 use_batched_rendering =
false;
899 if ( use_batched_rendering ) {
906 for (i = 0; i < pm->
n_models; i++) {
914 if ( use_batched_rendering ) {
936 bool swap_was_necessary =
false;
938 if (mins->
xyz.x > maxs->
xyz.x)
941 mins->
xyz.x = maxs->
xyz.x;
943 swap_was_necessary =
true;
945 if (mins->
xyz.y > maxs->
xyz.y)
948 mins->
xyz.y = maxs->
xyz.y;
950 swap_was_necessary =
true;
952 if (mins->
xyz.z > maxs->
xyz.z)
955 mins->
xyz.z = maxs->
xyz.z;
957 swap_was_necessary =
true;
964 if (swap_was_necessary)
967 const int NUM_BYTES = 24;
968 typedef struct converter
974 float min_x, min_y, min_z, max_x, max_y, max_z;
976 ubyte _byte[NUM_BYTES];
982 z._float.min_x = mins->
xyz.x;
983 z._float.min_y = mins->
xyz.y;
984 z._float.min_z = mins->
xyz.z;
985 z._float.max_x = maxs->
xyz.x;
986 z._float.max_y = maxs->
xyz.y;
987 z._float.max_z = maxs->
xyz.z;
991 char text[100 + (5 * NUM_BYTES)];
992 strcpy_s(text,
"The following is the correct hex string for the minima and maxima:\n");
995 for (
int i = 0;
i < NUM_BYTES;
i++)
997 sprintf(hex_str,
"%02X ", z._byte[
i]);
1006 return swap_was_necessary;
1011 box[0].
xyz.x = big_mn->
xyz.x; box[0].
xyz.y = big_mn->
xyz.y; box[0].
xyz.z = big_mn->
xyz.z;
1012 box[1].
xyz.x = big_mx->
xyz.x; box[1].
xyz.y = big_mn->
xyz.y; box[1].
xyz.z = big_mn->
xyz.z;
1013 box[2].
xyz.x = big_mx->
xyz.x; box[2].
xyz.y = big_mx->
xyz.y; box[2].
xyz.z = big_mn->
xyz.z;
1014 box[3].
xyz.x = big_mn->
xyz.x; box[3].
xyz.y = big_mx->
xyz.y; box[3].
xyz.z = big_mn->
xyz.z;
1017 box[4].
xyz.x = big_mn->
xyz.x; box[4].
xyz.y = big_mn->
xyz.y; box[4].
xyz.z = big_mx->
xyz.z;
1018 box[5].
xyz.x = big_mx->
xyz.x; box[5].
xyz.y = big_mn->
xyz.y; box[5].
xyz.z = big_mx->
xyz.z;
1019 box[6].
xyz.x = big_mx->
xyz.x; box[6].
xyz.y = big_mx->
xyz.y; box[6].
xyz.z = big_mx->
xyz.z;
1020 box[7].
xyz.x = big_mn->
xyz.x; box[7].
xyz.y = big_mx->
xyz.y; box[7].
xyz.z = big_mx->
xyz.z;
1032 int id,
len, next_chunk;
1036 fp =
cfopen(filename,
"rb");
1041 }
else if (ferror == 0) {
1061 _splitpath(filename, NULL, NULL, bname, NULL);
1062 sprintf(debug_name,
"%s.subsystems", bname);
1065 mprintf((
"Can't open debug file for writing subsystems for %s\n", filename));
1067 strcpy_s(model_filename, filename);
1068 ss_warning_shown = 0;
1086 Warning(
LOCATION,
"Bad version (%d) in model file <%s>",version,filename);
1110 while (!
cfeof(fp)) {
1122 #if defined( FREESPACE1_FORMAT )
1127 #elif defined( FREESPACE2_FORMAT )
1135 if ( pm->
rad <= 0.1f )
1180 Warning(
LOCATION,
"Moment of inertia values for model %s are invalid. This has to be fixed.\n", pm->
filename);
1189 float area_mass = (
float) pow(vol_mass, 0.6667
f) * 4.65f;
1191 pm->
mass = area_mass;
1192 float mass_ratio = vol_mass / area_mass;
1200 Warning(
LOCATION,
"Moment of inertia values for model %s are invalid. This has to be fixed.\n", pm->
filename);
1215 mprintf((
"Model %s has a null moment of inertia! (This is only a problem if the model is a ship.)\n", filename));
1233 for (i=0; i<pm->
num_xc; i++) {
1274 #if defined( FREESPACE2_FORMAT )
1287 #if defined ( FREESPACE1_FORMAT )
1329 }
else if(strstr(props,
"$triggered")) {
1334 if ( ( p = strstr(props,
"$look_at")) != NULL ) {
1344 int idx =
prop_string(props, &p,
"$dumb_rotate_time",
"$dumb_rotate_rate",
"$dumb_rotate");
1356 float turn_time =
static_cast<float>(atof(buf));
1357 if (turn_time == 0.0
f) {
1361 turn_rate =
PI2 / turn_time;
1364 turn_rate =
static_cast<float>(atof(buf));
1374 || strstr(props,
"$triggered") || strstr(props,
"$rotate") || strstr(props,
"$gun_rotation")) {
1385 if ( ( p = strstr(props,
"$special"))!= NULL ) {
1389 if ( !
stricmp(type,
"subsystem") ) {
1391 rotating_submodel_has_subsystem =
true;
1392 }
else if ( !
stricmp(type,
"no_rotate") ) {
1423 if (strstr(props,
"$no_collisions") != NULL )
1428 if (strstr(props,
"$nocollide_this_only") != NULL )
1433 if (strstr(props,
"$collide_invisible") != NULL )
1438 if (strstr(props,
"$gun_rotation") != NULL)
1443 if ( (p = strstr(props,
"$lod0_name")) != NULL)
1446 if (strstr(props,
"$attach_thrusters") != NULL )
1451 if ( (p = strstr(props,
"$detail_box:")) != NULL ) {
1453 while (*p ==
' ') p++;
1456 if ( (p = strstr(props,
"$box_offset:")) != NULL ) {
1458 while (*p ==
' ') p++;
1460 while (*p !=
',') p++;
1462 while (*p !=
',') p++;
1468 if ( (p = strstr(props,
"$box_min:")) != NULL ) {
1470 while (*p ==
' ') p++;
1472 while (*p !=
',') p++;
1474 while (*p !=
',') p++;
1480 if ( (p = strstr(props,
"$box_max:")) != NULL ) {
1482 while (*p ==
' ') p++;
1484 while (*p !=
',') p++;
1486 while (*p !=
',') p++;
1493 if ( (p = strstr(props,
"$detail_sphere:")) != NULL ) {
1495 while (*p ==
' ') p++;
1498 if ( (p = strstr(props,
"$radius:")) != NULL ) {
1500 while (*p ==
' ') p++;
1506 if ( (p = strstr(props,
"$offset:")) != NULL ) {
1508 while (*p ==
' ') p++;
1510 while (*p !=
',') p++;
1512 while (*p !=
',') p++;
1524 if ( (p = strstr(props,
"$uvec:")) != NULL ) {
1527 char *parsed_string =
p;
1529 while (*parsed_string ==
' ') {
1533 orient->
vec.uvec.xyz.x = (
float)(strtod(parsed_string, (
char **)NULL));
1536 parsed_string = strchr(parsed_string,
',');
1537 if (parsed_string == NULL) {
1539 "Submodel '%s' of model '%s' has an improperly formatted $uvec: declaration in its properties."
1540 "\n\n$uvec: should be followed by 3 numbers separated with commas."
1541 "\n\nCouldn't find first comma (,)!",
1546 while (*parsed_string ==
' ') {
1550 orient->
vec.uvec.xyz.y = (
float)(strtod(parsed_string, (
char **)NULL));
1553 parsed_string = strchr(parsed_string,
',');
1554 if (parsed_string == NULL) {
1556 "Submodel '%s' of model '%s' has an improperly formatted $uvec: declaration in its properties."
1557 "\n\n$uvec: should be followed by 3 numbers separated with commas."
1558 "\n\nCouldn't find second comma (,)!",
1563 while (*parsed_string ==
' ') {
1567 orient->
vec.uvec.xyz.z = (
float)(strtod(parsed_string, (
char **)NULL));
1569 if ( (p = strstr(props,
"$fvec:")) != NULL ) {
1570 parsed_string = p + 6;
1572 while (*parsed_string ==
' ') {
1576 orient->
vec.fvec.xyz.x = (
float)(strtod(parsed_string, (
char **)NULL));
1579 parsed_string = strchr(parsed_string,
',');
1580 if (parsed_string == NULL) {
1582 "Submodel '%s' of model '%s' has an improperly formatted $fvec: declaration in its properties."
1583 "\n\n$fvec: should be followed by 3 numbers separated with commas."
1584 "\n\nCouldn't find first comma (,)!",
1589 while (*parsed_string ==
' ') {
1593 orient->
vec.fvec.xyz.y = (
float)(strtod(parsed_string, (
char **)NULL));
1596 parsed_string = strchr(parsed_string,
',');
1597 if (parsed_string == NULL) {
1599 "Submodel '%s' of model '%s' has an improperly formatted $fvec: declaration in its properties."
1600 "\n\n$fvec: should be followed by 3 numbers separated with commas."
1601 "\n\nCouldn't find second comma (,)!",
1606 while (*parsed_string ==
' ') {
1610 orient->
vec.fvec.xyz.z = (
float)(strtod(parsed_string, (
char **)NULL));
1627 if (parent_num > -1) {
1633 Warning(
LOCATION,
"Improper custom orientation matrix for subsystem %s, you must define a up vector, then a forward vector", pm->
submodel[n].
name);
1638 if (parent_num > -1) {
1644 if (strstr(props,
"$fvec:") != NULL) {
1645 Warning(
LOCATION,
"Improper custom orientation matrix for subsystem %s, you must define a up vector, then a forward vector", pm->
submodel[n].
name);
1649 if ( !rotating_submodel_has_subsystem ) {
1664 if ( nchunks > 0 ) {
1736 for ( j = 0; j < 3; j++ ) {
1745 for ( j = 0; j < 3; j++ ) {
1765 for (i = 0; i < pm->
n_guns; i++ ) {
1774 bank->
norm[j] = temp_vec;
1796 bank->
norm[j] = temp_vec;
1811 for (i = 0; i < pm->
n_docks; i++ ) {
1816 if ( (p = strstr(props,
"$name"))!= NULL ) {
1821 nprintf((
"Model",
"model '%s' has trailing whitespace on bay name '%s'; this will be trimmed\n", pm->
filename, bay->
name));
1824 if (strlen(bay->
name) == 0) {
1825 nprintf((
"Model",
"model '%s' has an empty name specified for docking point %d\n", pm->
filename, i));
1828 nprintf((
"Model",
"model '%s' has no name specified for docking point %d\n", pm->
filename, i));
1850 Warning(
LOCATION,
"Model '%s' has %d slots in dock point '%s'; models must have exactly %d slots per dock point.", filename, bay->
num_slots, bay->
name, 2);
1862 Warning(
LOCATION,
"Model '%s' has two identical docking slot positions on docking port '%s'. This is not allowed. A new second slot position will be generated.", filename, bay->
name);
1865 bay->
pnt[1].
xyz.z += 10.0f;
1872 Warning(
LOCATION,
"Model '%s', docking port '%s' has docking slot positions that lie on the same axis as the docking normal. This will cause a NULL VEC crash when docked to another ship. A new docking normal will be generated.", filename, bay->
name);
1903 for (
int gpb = 0; gpb < gpb_num; gpb++)
1926 int length = strlen(props);
1930 int base_length = strlen(
"$glow_texture=");
1931 Assert(strstr( (
const char *)&props,
"$glow_texture=") != NULL);
1932 Assert(length > base_length);
1933 char *glow_texture_name = props + base_length;
1935 if (glow_texture_name[0] ==
'$')
1936 glow_texture_name++;
1942 Warning(
LOCATION,
"Couldn't open glowpoint texture '%s'\nreferenced by model '%s'\n", glow_texture_name, pm->
filename);
1949 strcat(glow_texture_name,
"-neb");
1955 nprintf((
"Model",
"Glow point bank nebula texture not found for '%s', using normal glowpoint texture instead\n", pm->
filename));
2013 int length = strlen(props);
2015 int base_length = strlen(
"$engine_subsystem=");
2016 Assert( strstr( (
const char *)&props,
"$engine_subsystem=") != NULL );
2017 Assert( length > base_length );
2018 char *engine_subsys_name = props + base_length;
2019 if (engine_subsys_name[0] ==
'$') {
2020 engine_subsys_name++;
2023 nprintf((
"wash",
"Ship %s with engine wash associated with subsys %s\n", filename, engine_subsys_name));
2026 int table_error = 1;
2028 for (
int k=0; k<n_subsystems; k++) {
2049 Warning(
LOCATION,
"Inconsistent model: Engine wash engine subsystem does not match any ship subsytem names for ship model %s", filename);
2081 for ( i = 0; i < n_banks; i++ ) {
2083 int physical_parent;
2092 for ( snum = 0; snum < n_subsystems; snum++ ) {
2093 subsystemp = &subsystems[snum];
2107 for (j = 0; j < n_slots; j++ ) {
2116 Assertion( n_slots > 0,
"Turret %s in model %s has no firing points.\n", subsystemp->
name, pm->
filename);
2125 if ( (n_subsystems == 0) || (snum == n_subsystems) ) {
2128 nprintf((
"Warning",
"Turret submodel %i not found for turret %i in model %s\n", parent, i, pm->
filename));
2131 for (j = 0; j < n_slots; j++ )
2145 for (i = 0; i < n_specials; i++) {
2156 p = strstr(name,
"$split");
2161 }
else if ( ( p = strstr(props_spcl,
"$special"))!= NULL ) {
2165 if ( !
stricmp(type,
"subsystem") ) {
2166 do_new_subsystem( n_subsystems, subsystems, -1, radius, &pnt, props_spcl, &name[1], pm->
id );
2167 }
else if ( !
stricmp(type,
"shieldpoint") ) {
2170 }
else if ( strstr(name,
"$enginelarge") || strstr(name,
"$enginehuge") ){
2171 do_new_subsystem( n_subsystems, subsystems, -1, radius, &pnt, props_spcl, &name[1], pm->
id );
2173 nprintf((
"Warning",
"Unknown special object type %s while reading model %s\n", name, pm->
filename));
2191 for (i=0; i<
n; i++ )
2241 for (i=0; i<pm->
n_paths; i++ ) {
2254 for ( j = 0; j < pm->
n_models; j++ ) {
2284 for ( k = 0; k < nturrets; k++ )
2303 for (i = 0; i < num_eyes; i++ ) {
2312 int num_ins, num_verts, num_faces,
idx, idx2, idx3;
2319 for(idx=0; idx<num_ins; idx++){
2336 for(idx2=0; idx2<num_verts; idx2++){
2346 for(idx3=0; idx3<3; idx3++){
2376 mprintf((
"Unknown chunk <%c%c%c%c>, len = %d\n",
id,
id>>8,
id>>16,
id>>24,len));
2381 cfseek(fp,next_chunk,SEEK_SET);
2394 ss_fp =
cfopen(debug_name,
"rb");
2429 if (strstr(tmp_name,
"thruster") || strstr(tmp_name,
"invisible") || strstr(tmp_name,
"warpmap"))
2438 if ( (strstr(tmp_name,
"-trans") && !strstr(tmp_name,
"-transpo")) || strstr(tmp_name,
"shockwave") || !strcmp(tmp_name,
"nameplate") ) {
2442 if (strstr(tmp_name,
"-amb")) {
2521 int shader_flags = 0;
2575 int i,
num, arc_idx;
2578 if ( !model_initted )
2588 if ( Polygon_models[i] ) {
2589 if (!
stricmp(filename, Polygon_models[i]->filename) && !duplicate) {
2592 return Polygon_models[
i]->
id;
2594 }
else if ( num == -1 ) {
2606 mprintf((
"Loading model '%s' into slot '%i'\n", filename, num ));
2609 Polygon_models[
num] =
pm;
2614 uint org_sig =
static_cast<uint>(Model_signature);
2615 if ( org_sig + MAX_POLYGON_MODELS > INT_MAX || org_sig + MAX_POLYGON_MODELS < org_sig ) {
2616 Model_signature = 0;
2620 Assert( (Model_signature % MAX_POLYGON_MODELS) == 0 );
2621 pm->
id = Model_signature +
num;
2622 Assert( (pm->
id % MAX_POLYGON_MODELS) == num );
2625 Parse_normal_problem_count = 0;
2630 char busy_text[60] = {
'\0' };
2632 strcat_s( busy_text,
"** ModelLoad: " );
2639 if (
read_model_file(pm, filename, n_subsystems, subsystems, ferror) < 0) {
2644 Polygon_models[
num] = NULL;
2654 sprintf(buffer,
"Serious problem loading model %s, %d normals capped to zero",
2655 filename, Parse_normal_problem_count);
2672 char destroyed_name[128];
2675 strcat_s( destroyed_name,
"-destroyed" );
2685 char live_debris_name[128];
2687 strcpy_s( live_debris_name,
"debris-" );
2693 if ( strstr( pm->
submodel[j].
name, live_debris_name )) {
2726 l1 = strlen(sm1->
name);
2744 if ( i==j )
continue;
2752 if ((
int)strlen(sm2->
name)!=l1)
continue;
2756 for ( k=0; k<l1; k++) {
2760 if (ndiff==0) first_diff = k;
2766 if (sm1->
name[k] != sm2->
name[k] ) {
2767 if (ndiff==0) first_diff = k;
2776 dl1 = tolower(sm1->
lod_name[first_diff]) -
'a';
2780 dl1 = tolower(sm1->
name[first_diff]) -
'a';
2782 dl2 = tolower(sm2->
name[first_diff]) -
'a';
2790 if ( (dl1<0) || (dl2<0) || (dl1>=MAX_MODEL_DETAIL_LEVELS) || (dl2>=MAX_MODEL_DETAIL_LEVELS) )
continue;
2796 mprintf((
"Submodel '%s' is detail level %d of '%s'\n", sm2->
name, dl2 + 1, sm1->
name ));
2802 if ( sm1->
details[j] == -1 ) {
2844 pm->
ram_used = ram_after - ram_before;
2861 for ( i = 0; i < (
int)Polygon_model_instances.size(); i++) {
2862 if ( !Polygon_model_instances[i] ) {
2872 if ( open_slot < 0 ) {
2873 Polygon_model_instances.push_back( pmi );
2874 open_slot = Polygon_model_instances.size() - 1;
2876 Polygon_model_instances[open_slot] = pmi;
2883 for ( i = 0; i < pm->
n_models; i++ ) {
2891 for (i = 0; i < pm->
n_models; i++) {
2897 if (intrinsic_rotate.
list.empty()) {
2898 Assertion(!intrinsic_rotate.
list.empty(),
"This model has the PM_FLAG_HAS_INTRINSIC_ROTATE flag; why doesn't it have an intrinsic-rotating submodel?");
2900 Intrinsic_rotations.push_back(intrinsic_rotate);
2909 Assert(model_instance_num >= 0);
2910 Assert(model_instance_num < (
int)Polygon_model_instances.size());
2911 Assert(Polygon_model_instances[model_instance_num] != NULL);
2924 for (
auto intrinsic_it = Intrinsic_rotations.begin(); intrinsic_it != Intrinsic_rotations.end(); ++intrinsic_it) {
2925 if (intrinsic_it->model_instance_num == model_instance_num) {
2926 Intrinsic_rotations.erase(intrinsic_it);
2938 int index_1, index_2;
2940 Assert( (path_num >= 0) && (path_num < pm->n_paths) );
2943 mp = &pm->
paths[path_num];
2976 for (i = 0; i < n_subsystems; i++)
2977 subsystems[i].path_num = -1;
2979 for (i = 0; i < n_subsystems; i++)
2981 for (j = 0; j < pm->
n_paths; j++)
2983 if ( ((subsystems[i].subobj_num != -1) && (subsystems[i].subobj_num == pm->
paths[j].
parent_submodel)) ||
2997 if (subsystems[i].path_num == -1)
3032 bool too_many_paths =
false;
3033 for (i = 0; i < pm->
n_paths; i++)
3040 strncpy(temp, pm->
paths[i].
name + 4, 2);
3042 bay_num = atoi(temp);
3046 if(bay_num > MAX_SHIP_BAY_PATHS)
3048 too_many_paths =
true;
3088 if (child->
live_debris[idx] == live_debris_model_num) {
3100 Error(
LOCATION,
"Could not find parent submodel for live debris");
3136 if ( model_num < 0 ) {
3137 Warning(
LOCATION,
"Invalid model number %d requested. Please post the call stack where an SCP coder can see it.\n", model_num);
3143 Assertion( num >= 0,
"Model id %d is invalid. Please backtrace and investigate.\n", num);
3145 Assertion( Polygon_models[num],
"No model with id %d found. Please backtrace and investigate.\n", num );
3146 Assertion( Polygon_models[num]->
id == model_num,
"Index collision between model %s and requested model %d. Please backtrace and investigate.\n", Polygon_models[num]->
filename, model_num );
3151 return Polygon_models[
num];
3156 Assert( model_instance_num >= 0 );
3157 Assert( model_instance_num < (
int)Polygon_model_instances.size() );
3158 if ( model_instance_num < 0 || model_instance_num >= (
int)Polygon_model_instances.size() ) {
3172 int i,
x,
y,min_x, min_y, max_x, max_y;
3181 int hull = po->
detail[0];
3183 min_x = min_y = max_x = max_y = 0;
3185 for (i=0; i<8; i++ ) {
3196 if ( n_valid_pts == 0 ) {
3202 if ( x < min_x ) min_x =
x;
3203 if ( y < min_y ) min_y =
y;
3205 if ( x > max_x ) max_x =
x;
3206 if ( y > max_y ) max_y =
y;
3213 if ( n_valid_pts < 8 ) {
3217 if (x1) *x1 = min_x;
3218 if (y1) *y1 = min_y;
3220 if (x2) *x2 = max_x;
3221 if (y2) *y2 = max_y;
3236 int i,
x,
y,min_x, min_y, max_x, max_y;
3240 if ( (submodel < 0) || (submodel >= po->
n_models ) )
return 1;
3247 min_x = min_y = max_x = max_y = 0;
3249 for (i=0; i<8; i++ ) {
3260 if ( n_valid_pts == 0 ) {
3266 if ( x < min_x ) min_x =
x;
3267 if ( y < min_y ) min_y =
y;
3269 if ( x > max_x ) max_x =
x;
3270 if ( y > max_y ) max_y =
y;
3277 if ( n_valid_pts == 0 ) {
3281 if (x1) *x1 = min_x;
3282 if (y1) *y1 = min_y;
3284 if (x2) *x2 = max_x;
3285 if (y2) *y2 = max_y;
3350 float width = radius;
3489 float rotation_time;
3492 rotation_time = 0.0f;
3502 float *ang_prev = NULL, *ang_next = NULL;
3506 ang_next = &sii->
angs.
p;
3511 ang_next = &sii->
angs.
h;
3516 ang_next = &sii->
angs.
b;
3521 if ( (ang_prev == NULL) && (ang_next == NULL) )
3532 float step_offset_time = (
float)fmod(rotation_time, step_time);
3534 int cur_step =
int( ((rotation_time - step_offset_time) / step_time) + 0.5
f);
3547 *ang_next = cur_step * step_size;
3556 if (step_offset_time < coast_start_time) {
3558 float accel_time = step_offset_time;
3561 }
else if (step_offset_time < decel_start_time) {
3563 float coast_time = step_offset_time - coast_start_time;
3566 }
else if (step_offset_time < pause_start_time) {
3573 *ang_next += step_size;
3605 nprintf((
"Model",
"NOTE: Matched $look_at: target <%s> with subobject id %d\n", sm->
look_at,
i));
3670 *a = asinf(c.
a1d[axis]);
3672 *a =
PI-asinf(c.
a1d[axis]);
3677 }
else {
if (*a < 0.0
f )
3712 float final_turn_rate;
3718 }
else if (diff < 0) {
3720 if (final_turn_rate < sii->desired_turn_rate) {
3740 while (sii->
angs.
p < 0.0f)
3749 while (sii->
angs.
h < 0.0f)
3758 while (sii->
angs.
b < 0.0f)
3849 vec3d fvec, uvec, rvec;
3854 float offset_base_h = 0.0f;
3855 float offset_barrel_h = 0.0f;
3856 #ifdef WMC_SIDE_TURRETS
3857 offset_base_h = -
PI_2;
3858 offset_barrel_h = -
PI_2;
3865 base->
angs.
h = offset_base_h;
3866 gun->
angs.
h = offset_barrel_h;
3871 gun->
angs.
h = offset_barrel_h;
3874 base->
angs.
h = 0.0f + offset_base_h;
3876 gun->
angs.
h = offset_barrel_h;
3914 bool limited_base_rotation =
false;
3922 if ( base == gun ) {
3939 matrix world_to_turret_matrix;
3940 vec3d world_to_turret_translate;
3944 vm_vec_add( &world_to_turret_translate, pos, &tempv );
3951 vm_vec_sub( &tempv, dst, &world_to_turret_translate );
3963 if (reset ==
false) {
3964 desired_angles.
p = acosf(of_dst.
xyz.z);
3966 desired_angles.
b = 0.0f;
3968 desired_angles.
p = 0.0f;
3969 desired_angles.
h = 0.0f;
3970 desired_angles.
b = 0.0f;
3981 limited_base_rotation =
true;
3988 float base_delta, gun_delta;
3999 base_delta =
vm_interp_angle(&base_angles->
h, desired_angles.
h, step_size, limited_base_rotation);
4006 base_delta = (
float) (fabs(base_delta)) / step_size;
4007 if (base_delta > 1.0
f)
4017 gun_delta = (
float) (fabs(gun_delta)) / step_size;
4018 if (gun_delta > 1.0
f)
4079 vec3d tempv1, tempv2;
4186 vec3d tempv1, tempv2;
4221 vec3d tempv1, tempv2;
4261 matrix submodel_instance_matrix, rotation_matrix, inv_orientation;
4304 *outnorm = *submodel_norm;
4306 matrix submodel_instance_matrix, rotation_matrix, inv_orientation;
4315 if ( mn == submodel_num) {
4316 vec3d submodel_pnt_offset = *submodel_pnt;
4325 vec3d tvec = submodel_pnt_offset;
4326 vm_vec_unrotate(&submodel_pnt_offset, &tvec, &submodel_instance_matrix);
4328 vec3d tnorm = *outnorm;
4346 vec3d tnorm = *outnorm;
4351 mn = parent_model_num;
4372 *outorient = *submodel_orient;
4374 matrix submodel_instance_matrix, rotation_matrix, inv_orientation;
4383 if ( mn == submodel_num) {
4384 vec3d submodel_pnt_offset = *submodel_pnt;
4393 vec3d tvec = submodel_pnt_offset;
4394 vm_vec_unrotate(&submodel_pnt_offset, &tvec, &submodel_instance_matrix);
4396 matrix tnorm = *outorient;
4414 matrix tnorm = *outorient;
4419 mn = parent_model_num;
4480 if (model_instance_num < 0) {
4487 if (model_instance_num < 0) {
4519 if (sii !=
nullptr) {
4524 submodel_vector->push_back(i);
4536 submodel_vector.push_back(mn);
4686 sm_instance->
angs.
p = 0.0f;
4687 sm_instance->
angs.
b = 0.0f;
4688 sm_instance->
angs.
h = 0.0f;
4693 sm_instance->
sii = NULL;
4702 for ( i = 0; i < pm->
n_models; i++ ) {
4733 Assert( sub_model_num >= 0 );
4734 Assert( sub_model_num < pm->n_models );
4736 if ( sub_model_num < 0 )
return;
4737 if ( sub_model_num >= pm->
n_models )
return;
4778 Assert( sub_model_num >= 0 );
4779 Assert( sub_model_num < pm->n_models );
4781 if ( sub_model_num < 0 )
return;
4782 if ( sub_model_num >= pm->
n_models )
return;
4792 sm->
angs.
p = angle_1;
4793 sm->
angs.
h = angle_2;
4805 Assertion(sub_model_num >= 0 && sub_model_num < pm->n_models,
4806 "Sub model number (%d) which should be updated is out of range! Must be between 0 and %d. This happend on model %s.",
4809 if ( sub_model_num < 0 )
return;
4810 if ( sub_model_num >= pm->
n_models )
return;
4853 for (
auto submodel_it = ir->
list.begin(); submodel_it != ir->
list.end(); ++submodel_it)
4881 if (model_instance_num >= 0)
4883 for (
auto intrinsic_it = Intrinsic_rotations.begin(); intrinsic_it != Intrinsic_rotations.end(); ++intrinsic_it)
4885 if (intrinsic_it->model_instance_num == model_instance_num)
4887 Assertion(intrinsic_it->is_ship,
"This code path is only for ship rotations! See the comments associated with the model_do_intrinsic_rotations function!");
4902 for (
auto intrinsic_it = Intrinsic_rotations.begin(); intrinsic_it != Intrinsic_rotations.end(); ++intrinsic_it)
4904 if (!intrinsic_it->is_ship)
4939 vec3d *mpoint1, *mpoint2;
5009 if ( sub_model_num == -1 ) {
5010 sub_model_num = pm->
detail[0];
5013 Assert( sub_model_num >= 0 );
5014 Assert( sub_model_num < pm->n_models );
5016 if ( sub_model_num < 0 )
return;
5017 if ( sub_model_num >= pm->
n_models )
return;
5042 for (i = index_to_start_at; i < pm->
n_docks; i++ )
5069 if(!
stricmp(name, Dock_type_names[i].name)) {
5083 for (i = 0; i < pm->
n_docks; i++ )
5091 if (!
strnicmp(name,
"<unnamed bay ", 13))
5093 int index = (name[13] -
'A');
5166 bool slot_found =
false;
5168 for ( i = 0; i < Bsp_collision_tree_list.size(); ++
i ) {
5169 if ( !Bsp_collision_tree_list[i].used ) {
5176 Bsp_collision_tree_list[
i].used =
true;
5184 Bsp_collision_tree_list.push_back(tree);
5186 return Bsp_collision_tree_list.size() - 1;
5192 Assert((
uint) tree_index < Bsp_collision_tree_list.size());
5194 return &Bsp_collision_tree_list[tree_index];
5199 Bsp_collision_tree_list[tree_index].used =
false;
5201 if ( Bsp_collision_tree_list[tree_index].node_list ) {
5202 vm_free(Bsp_collision_tree_list[tree_index].node_list);
5205 if ( Bsp_collision_tree_list[tree_index].leaf_list ) {
5206 vm_free(Bsp_collision_tree_list[tree_index].leaf_list);
5209 if ( Bsp_collision_tree_list[tree_index].point_list ) {
5210 vm_free( Bsp_collision_tree_list[tree_index].point_list );
5213 if ( Bsp_collision_tree_list[tree_index].vert_list ) {
5214 vm_free( Bsp_collision_tree_list[tree_index].vert_list);
5218 #if BYTE_ORDER == BIG_ENDIAN
5233 ubyte * normcount = p+20;
5238 for (n=0; n<nverts; n++ ) {
5246 for (i=0; i<normcount[
n]; i++){
5278 if ( nv < 0 )
return;
5293 for (i=0;i<nv;i++) {
5297 center_point.
xyz.x /= nv;
5298 center_point.
xyz.y /= nv;
5299 center_point.
xyz.z /= nv;
5301 *
vp(p+20) = center_point;
5305 for (i=0;i<nv;i++) {
5336 if ( nv < 0 )
return;
5338 verts = (
short *)(p+44);
5339 for (i=0; i<nv*2; i++){
5348 for (i=0;i<nv;i++) {
5352 center_point.
xyz.x /= nv;
5353 center_point.
xyz.y /= nv;
5354 center_point.
xyz.z /= nv;
5356 *
vp(p+20) = center_point;
5360 for (i=0;i<nv;i++) {
5378 w(p+36) = frontlist;
5413 #endif // BIG_ENDIAN
5417 #if BYTE_ORDER == BIG_ENDIAN
5419 int chunk_type, chunk_size;
5426 w(p+4) = chunk_size;
5428 while (chunk_type !=
OP_EOF) {
5429 switch (chunk_type) {
5455 mprintf((
"Bad chunk type %d, len=%d in modelread:swap_bsp_data\n", chunk_type, chunk_size ));
5464 w(p+4) = chunk_size;
5473 #if BYTE_ORDER == BIG_ENDIAN
5474 char *type_p = (
char *)(buffer);
5475 int *size_p = (
int *)(buffer+1);
5492 unsigned int *front_offset_p = (
unsigned int*)(buffer+29);
5493 unsigned int *back_offset_p = (
unsigned int*)(buffer+33);
5496 unsigned int *num_polygons_p = (
unsigned int*)(buffer+29);
5498 unsigned int *shld_polys = (
unsigned int*)(buffer+33);
5502 *front_offset_p =
INTEL_INT(*front_offset_p);
5503 *back_offset_p =
INTEL_INT(*back_offset_p);
5507 *num_polygons_p =
INTEL_INT(*num_polygons_p);
5508 for (
unsigned int i = 0;
i < *num_polygons_p;
i++)
5553 for(;gpo != glowpoint_bank_overrides.end(); ++gpo) {
5554 if(!strcmp(gpo->name, name)) {
5558 return glowpoint_bank_overrides.end();
5579 bool replace =
false;
5590 mprintf((
"+nocreate specified in non-modular glowpoint table.\n"));
5614 char glow_texture_name[32];
5619 if (
stricmp(glow_texture_name,
"none")) {
5624 Warning(
LOCATION,
"Couldn't open texture '%s'\nreferenced by glowpoint present '%s'\n", glow_texture_name, gpo.
name);
5631 char glow_texture_neb_name[256];
5632 strncpy(glow_texture_neb_name, glow_texture_name, 256);
5633 strcat(glow_texture_neb_name,
"-neb");
5639 nprintf((
"Model",
"Glowpoint preset nebula texture not found for '%s', using normal glowpoint texture instead\n", gpo.
name));
5659 if (!
stricmp(pulsetype,
"sine")) {
5662 else if (!
stricmp(pulsetype,
"cosine")) {
5665 else if (!
stricmp(pulsetype,
"triangle")) {
5668 else if (!
stricmp(pulsetype,
"shiftedtriangle")) {
5730 Warning(
LOCATION,
"Null vector specified in cone direction for glowpoint override %s. Discarding preset.", gpo.
name);
5745 Warning(
LOCATION,
"Null vector specified in rotation axis for glowpoint override %s. Discarding preset.", gpo.
name);
5755 if (gpoi == glowpoint_bank_overrides.end()) {
5757 glowpoint_bank_overrides.push_back(gpo);
5762 Warning(
LOCATION,
"+nocreate not specified for glowpoint override that already exists. Discarding duplicate entry: %s", gpo.
name);
5765 glowpoint_bank_overrides.erase(gpoi);
5766 glowpoint_bank_overrides.push_back(gpo);
5774 mprintf((
"Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
5781 glowpoint_bank_overrides.clear();
int model_find_2d_bound(int model_num, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
SCP_vector< bsp_collision_tree > Bsp_collision_tree_list
void model_get_submodel_tree_list(SCP_vector< int > &submodel_vector, polymodel *pm, int mn)
void model_get_rotating_submodel_list(SCP_vector< int > *submodel_vector, object *objp)
#define MAX_POLYGON_MODELS
#define MOVEMENT_TYPE_ROT
void model_clear_instance(int model_num)
int timestamp(int delta_ms)
struct screen3d::@234::@236 xyw
#define SUBSYSTEM_NAVIGATION
vec3d render_sphere_offset
model_subsystem * system_info
weapon Weapons[MAX_WEAPONS]
void world_find_real_model_point(vec3d *out, vec3d *world_pt, polymodel *pm, int submodel_num, matrix *orient, vec3d *pos)
char lod_name[MAX_NAME_LEN]
#define MOVEMENT_TYPE_NONE
int Cmdline_old_collision_sys
SCP_vector< submodel_intrinsic_rotation > list
float vm_vec_mag_quick(const vec3d *v)
matrix * vm_matrix_x_matrix(matrix *dest, const matrix *src0, const matrix *src1)
int live_debris[MAX_LIVE_DEBRIS]
intrinsic_rotation(bool _is_ship, int _model_instance_num)
void create_family_tree(polymodel *obj)
void model_do_intrinsic_rotations_sub(intrinsic_rotation *ir)
GLfloat GLfloat GLfloat GLfloat h
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
weapon_info Weapon_info[MAX_WEAPON_TYPES]
submodel_instance_info * sii
insignia ins[MAX_MODEL_INSIGNIAS]
int debris_objects[MAX_DEBRIS_OBJECTS]
float vm_vec_mag(const vec3d *v)
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
void drop_trailing_white_space(char *str)
void model_clear_submodel_instances(int model_instance_num)
GLsizei const GLfloat * value
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)
asteroid Asteroids[MAX_ASTEROIDS]
#define SDR_FLAG_MODEL_CLIP
matrix * vm_angles_2_matrix(matrix *m, const angles *a)
void vm_rotate_matrix_by_angles(matrix *orient, const angles *tangles)
int turret_gun_rotation_snd
int prop_string(char *props, char **p, int n_args,...)
SCP_vector< glow_point_bank_override >::iterator get_glowpoint_bank_override_by_name(const char *name)
float model_get_radius(int modelnum)
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define MAX_MODEL_TEXTURES
void swap_sldc_data(ubyte *buffer)
int detail[MAX_MODEL_DETAIL_LEVELS]
#define MSS_MODEL_FLAG_MASK
float detail_depth[MAX_MODEL_DETAIL_LEVELS]
#define SDR_FLAG_MODEL_DIFFUSE_MAP
#define MSS_FLAG_TRIGGERED
int subsystem_stricmp(const char *str1, const char *str2)
float u[MAX_INS_FACES][MAX_INS_FACE_VECS]
int rotating_submodel_has_ship_subsys(int submodel, ship *shipp)
#define gr_maybe_create_shader
void model_remove_bsp_collision_tree(int tree_index)
struct vec3d::@225::@227 xyz
stepped_rotation_t * stepped_rotation
#define MOVEMENT_TYPE_TRIGGERED
matrix * vm_copy_transpose(matrix *dest, const matrix *src)
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
float vm_interp_angle(float *h, float desired_angle, float step_size, bool force_front)
#define Assertion(expr, msg,...)
#define END_OF_LIST(head)
char * model_get_dock_name(int modelnum, int index)
void model_do_intrinsic_rotations(int model_instance_num)
char look_at[MAX_NAME_LEN]
void model_set_subsys_path_nums(polymodel *pm, int n_subsystems, model_subsystem *subsystems)
bool pulse_period_override
char model_filename[_MAX_PATH]
int model_find_bay_path(int modelnum, char *bay_path_name)
#define SDR_FLAG_MODEL_DEFERRED
void interp_clear_instance()
#define gr_destroy_buffer
#define DOCK_TYPE_GENERIC
#define MAX_SHIP_BAY_PATHS
void model_clear_instance_info(submodel_instance_info *sii)
GLfloat GLfloat GLfloat v2
int details[MAX_MODEL_DETAIL_LEVELS]
void model_set_instance_techroom(int model_num, int sub_model_num, float angle_1, float angle_2)
void swap_bsp_flatpoly(polymodel *pm, ubyte *p)
void model_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_num, int submodel_num, const matrix *objorient, const vec3d *objpos)
#define SDR_FLAG_MODEL_LIGHT
int required_string_either(char *str1, char *str2)
Checks for one of two required strings.
#define PM_COMPATIBLE_VERSION
int turret_base_rotation_snd
void find_submodel_instance_point(vec3d *outpnt, int model_instance_num, int submodel_num)
GLenum GLuint GLenum GLsizei const GLchar * buf
#define SUBSYSTEM_GAS_COLLECT
vec3d turret_firing_point[MAX_TFP]
float gun_submodel_rotation
void model_page_in_start()
thruster_bank * thrusters
#define SDR_FLAG_MODEL_FOG
float base_rotation_rate_pct
void stuff_float(float *f)
#define IS_VEC_NULL_SQ_SAFE(v)
void swap_bsp_tmappoly(polymodel *pm, ubyte *p)
void interp_pack_vertex_buffers(polymodel *pm, int mn)
char debug_name[_MAX_PATH]
void model_do_children_look_at(polymodel *pm, int mn)
#define SDR_FLAG_MODEL_MISC_MAP
#define SUBSYSTEM_COMMUNICATION
void create_vertex_buffer(polymodel *pm)
void game_busy(const char *filename=NULL)
void g3_done_instance(bool set_api=false)
int model_get_dock_index_type(int modelnum, int index)
float atan2_safe(float y, float x)
#define PM_FLAG_HAS_INTRINSIC_ROTATE
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
#define SDR_FLAG_MODEL_SPEC_MAP
void vm_vec_add2(vec3d *dest, const vec3d *src)
int submodel_find_2d_bound_min(int model_num, int submodel, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
polymodel * model_get(int model_num)
void parse_glowpoint_table(const char *filename)
char * Subsystem_types[SUBSYSTEM_MAX]
struct matrix::@228::@230 vec
int LoadTexture(char *filename, char *dbg_name)
void model_update_instance(int model_instance_num, int sub_model_num, submodel_instance_info *sii, int flags)
void vm_vec_scale(vec3d *dest, float s)
void swap_bsp_data(polymodel *pm, void *model_ptr)
int subobj_find_2d_bound(float radius, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
GLboolean GLboolean GLboolean GLboolean a
#define SDR_FLAG_MODEL_SHADOW_MAP
#define DIR_SEPARATOR_STR
int cf_exists_full(const char *filename, int dir_type)
void get_user_prop_value(char *buf, char *value)
void find_submodel_instance_world_point(vec3d *outpnt, int model_instance_num, int submodel_num, const matrix *objorient, const vec3d *objpos)
void submodel_stepped_rotate(model_subsystem *psub, submodel_instance_info *sii)
bsp_collision_tree * model_get_bsp_collision_tree(int tree_index)
void model_make_turret_matrix(int model_num, model_subsystem *turret)
struct engine_wash_info * engine_wash_pointer
void model_init_submodel_axis_pt(submodel_instance_info *sii, int model_num, int submodel_num)
#define strnicmp(s1, s2, n)
texture_map maps[MAX_MODEL_TEXTURES]
void model_instance_find_world_dir(vec3d *out_dir, vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient)
void stuff_string(char *outstr, int type, int len, char *terminators)
bool use_render_box_offset
float get_submodel_delta_angle(submodel_instance_info *sii)
void vm_orthogonalize_matrix(matrix *m_src)
void vm_vec_sub2(vec3d *dest, const vec3d *src)
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void vm_set_identity(matrix *m)
void model_instance_find_obj_dir(vec3d *w_vec, vec3d *m_vec, int model_instance_num, int submodel_num, matrix *objorient)
submodel_instance * submodel
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)
int model_get_num_dock_points(int modelnum)
vertex_buffer detail_buffers[MAX_MODEL_DETAIL_LEVELS]
vertex_buffer trans_buffer
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
vec3d norm[MAX_DOCK_SLOTS]
int required_string(const char *pstr)
int model_render_flags_size
queued_animation * triggers
void interp_configure_vertex_buffers(polymodel *, int)
#define MOVEMENT_TYPE_LOOK_AT
float vm_vec_normalized_dir(vec3d *dest, const vec3d *end, const vec3d *start)
int model_get_dock_types(int modelnum)
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
int optional_string(const char *pstr)
#define SDR_FLAG_MODEL_NORMAL_MAP
void model_calc_bound_box(vec3d *box, vec3d *big_mn, vec3d *big_mx)
void interp_create_transparency_index_buffer(polymodel *pm, int detail_num)
bool use_render_sphere_offset
void model_set_instance_info(submodel_instance_info *sii, float turn_rate, float turn_accel)
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
#define MSS_FLAG_TURRET_ALT_MATH
void model_load_texture(polymodel *pm, int i, char *file)
SCP_vector< vec3d > shield_points
int model_create_bsp_collision_tree()
bool Parsing_modular_table
int turret_num_firing_points
float vm_vec_normalize_safe(vec3d *v)
int g3_project_vertex(vertex *point)
float vm_delta_from_interp_angle(float current_angle, float desired_angle)
#define SUBSYSTEM_WEAPONS
void model_instance_find_world_point(vec3d *outpnt, vec3d *mpnt, int model_instance_num, int submodel_num, const matrix *objorient, const vec3d *objpos)
#define MSS_FLAG_FIRE_ON_TARGET
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
char crewspot[MAX_NAME_LEN]
ubyte * shield_collision_tree
void world_find_model_instance_point(vec3d *out, vec3d *world_pt, const polymodel_instance *pmi, int submodel_num, const matrix *orient, const vec3d *pos)
object Objects[MAX_OBJECTS]
GLint GLint GLint GLint GLint x
#define PM_OBJFILE_MAJOR_VERSION
void model_delete_instance(int model_instance_num)
flag_def_list model_render_flags[]
SCP_vector< polymodel_instance * > Polygon_model_instances
#define vm_vec_make(v, _x, _y, _z)
void model_find_obj_dir(vec3d *w_vec, vec3d *m_vec, int model_num, int submodel_num, matrix *objorient)
void stuff_boolean(int *i, bool a_to_eol)
int model_get_parent_submodel_for_live_debris(int model_num, int live_debris_model_num)
void _splitpath(char *path, char *drive, char *dir, char *fname, char *ext)
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
void model_page_out_textures(int model_num, bool release=false)
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int cf_chksum_long(const char *filename, uint *chksum, int max_size, int cf_type)
void model_octant_free(polymodel *pm)
void glowpoint_override_defaults(glow_point_bank_override *gpo)
float submodel_get_radius(int modelnum, int submodelnum)
#define MOVEMENT_TYPE_ROT_SPECIAL
int is_valid_vec(const vec3d *vec)
int faces[MAX_INS_FACES][MAX_INS_FACE_VECS]
int Parse_normal_problem_count
void reset_parse(char *text)
float model_get_core_radius(int modelnum)
GLuint const GLchar * name
#define SDR_FLAG_MODEL_GLOW_MAP
int model_find_dock_name_index(int modelnum, char *name)
#define MAX_DEBRIS_OBJECTS
#define MOVEMENT_TYPE_INTRINSIC_ROTATE
void cfread_vector(vec3d *vec, CFILE *file, int ver, vec3d *deflt)
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
float gun_rotation_rate_pct
void model_instance_free_all()
void do_new_subsystem(int n_subsystems, model_subsystem *slist, int subobj_num, float rad, vec3d *pnt, char *props, char *subobj_name, int model_num)
ubyte arc_type[MAX_ARC_EFFECTS]
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
int weapon_rotation_pbank
void submodel_look_at(polymodel *pm, int mn)
void parse_triggers(int &n_trig, queued_animation **triggers, char *props)
#define SDR_FLAG_MODEL_ENV_MAP
float turret_turning_rate
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)
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
char parent_name[MAX_NAME_LEN]
float v[MAX_INS_FACES][MAX_INS_FACE_VECS]
#define MSS_MODEL_FLAG2_MASK
ship_subsys * ship_get_subsys(ship *shipp, char *subsys_name)
void swap_bsp_sortnorms(polymodel *pm, ubyte *p)
void model_find_world_dir(vec3d *out_dir, vec3d *in_dir, int model_num, int submodel_num, const matrix *objorient)
int vm_vec_same(const vec3d *v1, const vec3d *v2)
glow_point_bank * glow_point_banks
int cfputs(const char *str, CFILE *cfile)
GLint GLsizei GLsizei height
void model_copy_subsystems(int n_subsystems, model_subsystem *d_sp, model_subsystem *s_sp)
#define SDR_FLAG_MODEL_HEIGHT_MAP
void model_allocate_interp_data(int, int, int)
void print_family_tree(polymodel *obj, int modelnum, char *ident, int islast)
#define SUBSYSTEM_SENSORS
#define SUBSYSTEM_UNKNOWN
void fvi_two_lines_in_3space(const vec3d *p1, const vec3d *v1, const vec3d *p2, const vec3d *v2, float *s, float *t)
bool maybe_swap_mins_maxs(vec3d *mins, vec3d *maxs)
#define MAX_SUBMODEL_COLLISION_ROT_ANGLE
char subobj_name[MAX_NAME_LEN]
float render_sphere_radius
#define MSS_FLAG_ARTILLERY
texture_info textures[TM_NUM_TYPES]
SCP_vector< ship_info > Ship_info
#define MOVEMENT_AXIS_NONE
void model_set_instance(int model_num, int sub_model_num, submodel_instance_info *sii, int flags)
int MessageBox(HWND h, const char *s1, const char *s2, int i)
void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api=true)
#define MAX_MODEL_DETAIL_LEVELS
GLsizei GLsizei GLuint * obj
int read_model_file(polymodel *pm, char *filename, int n_subsystems, model_subsystem *subsystems, int ferror)
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
GLenum GLuint GLenum GLsizei length
vec3d arc_pts[MAX_ARC_EFFECTS][2]
void model_set_bay_path_nums(polymodel *pm)
vec3d * vm_vec_perp(vec3d *dest, const vec3d *p0, const vec3d *p1, const vec3d *p2)
void interp_create_detail_index_buffer(polymodel *pm, int detail)
int cfread_int(CFILE *file, int ver, int deflt)
float cfread_float(CFILE *file, int ver, float deflt)
int parse_modular_table(const char *name_check, void(*parse_callback)(const char *filename), int path_type, int sort_type)
GLsizei GLsizei GLchar * source
int model_find_dock_index(int modelnum, int dock_type, int index_to_start_at)
void swap_bsp_defpoints(ubyte *p)
eye view_positions[MAX_EYES]
matrix world_to_turret_matrix
#define SUBSYSTEM_ACTIVATION
#define SDR_FLAG_MODEL_ANIMATED
float split_plane[MAX_SPLIT_PLANE]
void model_do_look_at(int pn)
submodel_intrinsic_rotation(int _submodel_num, float _turn_rate)
bool is_minimum_GLSL_version()
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror, int duplicate)
void world_find_model_point(vec3d *out, vec3d *world_pt, const polymodel *pm, int submodel_num, const matrix *orient, const vec3d *pos)
struct engine_wash_info * wash_info_pointer
void model_octant_create(polymodel *pm)
#define MSS_FLAG_STEPPED_ROTATE
int is_white_space(char ch)
void model_page_in_stop()
vec3d * vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
void make_submodel_world_matrix(polymodel *pm, int sn, vec3d *v)
SCP_vector< intrinsic_rotation > Intrinsic_rotations
polymodel * Polygon_models[MAX_POLYGON_MODELS]
submodel_instance_info submodel_info_1
int cfclose(CFILE *cfile)
#define SDR_FLAG_MODEL_TRANSFORM
int stuff_float_list(float *flp, int max_floats)
void model_clear_submodel_instance(submodel_instance *sm_instance, bsp_info *sm)
int model_create_instance(bool is_ship, int model_num)
void model_maybe_fixup_subsys_path(polymodel *pm, int path_num)
char filename[FILESPEC_LENGTH]
bool glow_bitmap_override
#define MSS_FLAG_TURRET_MATRIX
SCP_vector< asteroid_info > Asteroid_info
void submodel_rotate(model_subsystem *psub, submodel_instance_info *sii)
void model_get_rotating_submodel_axis(vec3d *model_axis, vec3d *world_axis, int model_instance_num, int submodel_num, matrix *objorient)
vec3d pnt[MAX_DOCK_SLOTS]
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
void model_add_arc(int model_num, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type)
matrix vmd_identity_matrix
void model_find_submodel_offset(vec3d *outpnt, int model_num, int sub_model_num)
flag_def_list Dock_type_names[]
int cfilelength(CFILE *cfile)
void model_unload(int modelnum, int force)
SCP_vector< glow_point_bank_override > glowpoint_bank_overrides
polymodel_instance * model_get_instance(int model_instance_num)
void dump_object_tree(polymodel *obj)
int path_indexes[MAX_SHIP_BAY_PATHS]
float vm_vec_normalize(vec3d *v)
void cfread_string_len(char *buf, int n, CFILE *file)
Read a fixed length string that is not null-terminated, with the length stored in file...
void model_collide_parse_bsp(bsp_collision_tree *tree, void *model_ptr, int version)
int model_find_2d_bound_min(int model_num, matrix *orient, vec3d *pos, int *x1, int *y1, int *x2, int *y2)
int cfseek(CFILE *fp, int offset, int where)
#define MSS_FLAG_CREWPOINT