mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-12 14:59:48 -10:00
ok, something aparently went wrong, last time, so I'm commiting again
hopefully it should work this time damnit WORK!!!
This commit is contained in:
1 parent
3979af39b1
commit
6d7c837732
42 files changed
+1798
-448
No files matched your search
+625
-77
@@ -9,13 +9,16 @@
|
||||
|
||||
/*
|
||||
* $Logfile: /Freespace2/code/Model/ModelRead.cpp $
|
||||
* $Revision: 2.122 $
|
||||
* $Date: 2007-01-10 01:44:39 $
|
||||
* $Author: taylor $
|
||||
* $Revision: 2.123 $
|
||||
* $Date: 2007-01-14 14:03:33 $
|
||||
* $Author: bobboau $
|
||||
*
|
||||
* file which reads and deciphers POF information
|
||||
*
|
||||
* $Log: not supported by cvs2svn $
|
||||
* Revision 2.122 2007/01/10 01:44:39 taylor
|
||||
* add support for new IBX format which can support up to UINT_MAX worth of verts (NOTE: D3D code still needs to be made compatible with this!!)
|
||||
*
|
||||
* Revision 2.121 2006/12/28 22:47:03 Goober5000
|
||||
* fix spelling... *twitch*
|
||||
*
|
||||
@@ -1227,10 +1230,22 @@
|
||||
#include "cfile/cfile.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "parse/scripting.h"
|
||||
#include "parse/lua.h"
|
||||
|
||||
|
||||
#include "gamesnd/gamesnd.h"
|
||||
|
||||
flag_def_list model_render_flags[] =
|
||||
{
|
||||
{"no lighting", MR_NO_LIGHTING},
|
||||
{"transparent", MR_ALL_XPARENT},
|
||||
{"no Zbuffer", MR_NO_ZBUFFER},
|
||||
{"no cull", MR_NO_CULL},
|
||||
{"no glowmaps", MR_NO_GLOWMAPS}
|
||||
};
|
||||
|
||||
int model_render_flags_size = sizeof(model_render_flags)/sizeof(flag_def_list);
|
||||
|
||||
#define MAX_SUBMODEL_COLLISION_ROT_ANGLE (PI / 6.0f) // max 30 degrees per frame
|
||||
|
||||
@@ -1356,15 +1371,15 @@ void model_unload(int modelnum, int force)
|
||||
vm_free(pm->docking_bays);
|
||||
}
|
||||
|
||||
|
||||
if ( pm->thrusters ) {
|
||||
//thrusters are vectors now, and they are on a per submodel basis now too
|
||||
/* if ( pm->thrusters ) {
|
||||
for (i = 0; i < pm->n_thrusters; i++) {
|
||||
if (pm->thrusters[i].points)
|
||||
vm_free(pm->thrusters[i].points);
|
||||
}
|
||||
|
||||
vm_free(pm->thrusters);
|
||||
}
|
||||
}*/
|
||||
|
||||
if ( pm->glow_point_banks ) { // free the glows!!! -Bobboau
|
||||
for (i = 0; i < pm->n_glow_point_banks; i++) {
|
||||
@@ -1556,6 +1571,7 @@ void model_copy_subsystems( int n_subsystems, model_subsystem *d_sp, model_subsy
|
||||
int nfp;
|
||||
|
||||
dest->turret_fov = source->turret_fov;
|
||||
dest->turret_y_fov = source->turret_y_fov;
|
||||
dest->turret_num_firing_points = source->turret_num_firing_points;
|
||||
dest->turret_norm = source->turret_norm;
|
||||
dest->turret_matrix = source->turret_matrix;
|
||||
@@ -1605,6 +1621,16 @@ static void set_subsystem_info( model_subsystem *subsystemp, char *props, char *
|
||||
strcpy(buf,"180");
|
||||
angle = ANG_TO_RAD(atoi(buf))/2.0f;
|
||||
subsystemp->turret_fov = (float)cos(angle);
|
||||
|
||||
if ( (p = strstr(props, "$y_fov")) != NULL ){
|
||||
get_user_prop_value(p+6, buf); // get the value of the fov
|
||||
angle = ANG_TO_RAD(atoi(buf))/2.0f;
|
||||
subsystemp->turret_y_fov = (float)(angle);
|
||||
}else{
|
||||
subsystemp->turret_y_fov = -2.0f;
|
||||
}
|
||||
|
||||
|
||||
subsystemp->turret_num_firing_points = 0;
|
||||
|
||||
if ( (p = strstr(props, "$crewspot")) != NULL) {
|
||||
@@ -1636,6 +1662,11 @@ static void set_subsystem_info( model_subsystem *subsystemp, char *props, char *
|
||||
subsystemp->flags |= MSS_FLAG_TRIGGERED;
|
||||
}
|
||||
|
||||
//unnesisary additional formatting
|
||||
// if ( (p = strstr(props, "$orient:")) != NULL ) {
|
||||
// p+=8;
|
||||
|
||||
|
||||
// Rotating subsystem
|
||||
if ( (p = strstr(props, "$rotate")) != NULL) {
|
||||
subsystemp->flags |= MSS_FLAG_ROTATES;
|
||||
@@ -2192,7 +2223,7 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
|
||||
//mprintf(0,"Got chunk SOBJ, len=%d\n",len);
|
||||
|
||||
n = cfread_int(fp);
|
||||
pm->submodel[n].sub_object_number = n = cfread_int(fp);
|
||||
//mprintf(("SOBJ IDed itself as %d", n));
|
||||
|
||||
Assert(n < pm->n_models );
|
||||
@@ -2245,6 +2276,19 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
}
|
||||
}
|
||||
|
||||
if(( p = strstr(props, "$look_at:"))!= NULL ){
|
||||
pm->submodel[n].movement_type = MOVEMENT_TYPE_LOOK_AT;
|
||||
pm->submodel[n].look_at = atoi(p+9);
|
||||
}else{
|
||||
pm->submodel[n].look_at = -1;
|
||||
}
|
||||
if(( p = strstr(props, "$dumb_rotate:"))!= NULL ){
|
||||
pm->submodel[n].movement_type = MSS_FLAG_DUM_ROTATES;
|
||||
pm->submodel[n].dumb_turn_rate = atof(p+13);
|
||||
}else{
|
||||
pm->submodel[n].dumb_turn_rate = 0.0f;
|
||||
}
|
||||
|
||||
if ( pm->submodel[n].name[0] == '\0' ) {
|
||||
strcpy(pm->submodel[n].name, "unknown object name");
|
||||
}
|
||||
@@ -2283,6 +2327,14 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
else
|
||||
pm->submodel[n].gun_rotation = false;
|
||||
|
||||
if ( (p = strstr(props, "$detail_sphere:")) != NULL ) {
|
||||
p += 15;
|
||||
pm->submodel[n].use_render_sphere = atoi(p);
|
||||
p=strstr(p, ",");
|
||||
pm->submodel[n].render_sphere = (float)strtod(++p, (char **)NULL);
|
||||
pm->submodel[n].render_sphere*=pm->submodel[n].render_sphere;
|
||||
}
|
||||
|
||||
if ( (p = strstr(props, "$detail_box:")) != NULL ) {
|
||||
p += 13;
|
||||
pm->submodel[n].use_render_box = atoi(p);
|
||||
@@ -2310,6 +2362,70 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
}
|
||||
}
|
||||
|
||||
matrix *o = &pm->submodel[n].orientation;
|
||||
if((p = strstr(props, "$uvec:")) != NULL ){
|
||||
p+=6;
|
||||
|
||||
char*c = p;
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.uvec.xyz.x = atof(c);
|
||||
c = strchr(c,',');//find end of number
|
||||
c++;
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.uvec.xyz.y = atof(c);
|
||||
c = strchr(c,',');//find end of number
|
||||
c++;
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.uvec.xyz.z = atof(c);
|
||||
if((p = strstr(props, "$fvec:")) != NULL ){
|
||||
c = p+6;
|
||||
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.fvec.xyz.x = atof(c);
|
||||
c = strchr(c,',');//find end of number
|
||||
c++;
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.fvec.xyz.y = atof(c);
|
||||
c = strchr(c,',');//find end of number
|
||||
c++;
|
||||
while(*c==' ')c++;//skip spaces
|
||||
o->vec.fvec.xyz.z = atof(c);
|
||||
|
||||
vm_vec_crossprod(&o->vec.rvec, &o->vec.uvec, &o->vec.fvec);
|
||||
vm_vec_crossprod(&o->vec.fvec, &o->vec.rvec, &o->vec.uvec);
|
||||
vm_vec_normalize(&o->vec.uvec);
|
||||
vm_vec_normalize(&o->vec.fvec);
|
||||
vm_vec_normalize(&o->vec.rvec);
|
||||
|
||||
}else{
|
||||
int p = pm->submodel[n].parent;
|
||||
if(p >-1){
|
||||
matrix *O = &pm->submodel[p].orientation;
|
||||
memcpy(o,O,sizeof(matrix));
|
||||
}else{
|
||||
memset(o,0,sizeof(matrix));
|
||||
}
|
||||
Error( LOCATION, "improper custum orientation matrix, you must define a up vector, then a forward vector");
|
||||
}
|
||||
}else{
|
||||
int p = pm->submodel[n].parent;
|
||||
if(p >-1){
|
||||
matrix *O = &pm->submodel[p].orientation;
|
||||
memcpy(o,O,sizeof(matrix));
|
||||
}else{
|
||||
memset(o,0,sizeof(matrix));
|
||||
}
|
||||
if(strstr(props, "$fvec:") != NULL )Error( LOCATION, "improper custum orientation matrix, you must define a up vector, then a forward vector");
|
||||
}
|
||||
|
||||
pm->submodel[n].ang_vel.p = 0.0f;
|
||||
pm->submodel[n].ang_vel.b = 0.0f;
|
||||
pm->submodel[n].ang_vel.h = 0.0f;
|
||||
|
||||
pm->submodel[n].ang_acl.p = 1.0f;
|
||||
pm->submodel[n].ang_acl.b = 1.0f;
|
||||
pm->submodel[n].ang_acl.h = 1.0f;
|
||||
|
||||
if ( !rotating_submodel_has_subsystem ) {
|
||||
nprintf(("Model", "Model %s: Rotating Submodel without subsystem: %s\n", pm->filename, pm->submodel[n].name));
|
||||
|
||||
@@ -2396,6 +2512,21 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
pm->shield.tris[i].neighbors[j] = cfread_int( fp ); // read in the neighbor indices -- indexes into tri list
|
||||
}
|
||||
}
|
||||
for(i = 0; i<pm->shield.nverts; i++){
|
||||
vec3d*norm = &pm->shield.verts[i].norm;
|
||||
vm_vec_zero(norm);
|
||||
int n = 0;
|
||||
for(j = 0; j<pm->shield.ntris; j++){
|
||||
for (int k = 0; k<3; k++){
|
||||
if(pm->shield.tris[j].verts[k] == i){
|
||||
n++;
|
||||
vm_vec_add2(norm, &pm->shield.tris[j].norm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(n)
|
||||
vm_vec_scale(norm, 1.0f/float(n));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2576,26 +2707,22 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
}
|
||||
|
||||
case ID_FUEL:
|
||||
{//go ahead remove this bracket, see what it's for, I dare you
|
||||
char props[MAX_PROP_LEN];
|
||||
pm->n_thrusters = cfread_int(fp);
|
||||
int n_thrusters = cfread_int(fp);
|
||||
|
||||
if (pm->n_thrusters > 0) {
|
||||
pm->thrusters = (thruster_bank *)vm_malloc(sizeof(thruster_bank) * pm->n_thrusters);
|
||||
Assert( pm->thrusters != NULL );
|
||||
if (n_thrusters > 0) {
|
||||
|
||||
for (i = 0; i < pm->n_thrusters; i++ ) {
|
||||
thruster_bank *bank = &pm->thrusters[i];
|
||||
thruster_bank bank;
|
||||
for (i = 0; i < n_thrusters; i++ ) {
|
||||
|
||||
bank->num_points = cfread_int(fp);
|
||||
bank->points = NULL;
|
||||
int num_points = cfread_int(fp);
|
||||
|
||||
if (bank->num_points > 0)
|
||||
bank->points = (glow_point *) vm_malloc(sizeof(glow_point) * bank->num_points);
|
||||
|
||||
bank ->obj_num = -1;
|
||||
bank.obj_num = -1;
|
||||
bank.sub_model = -1;
|
||||
|
||||
if (pm->version < 2117) {
|
||||
bank->wash_info_pointer = NULL;
|
||||
bank.wash_info_pointer = NULL;
|
||||
} else {
|
||||
cfread_string_len( props, MAX_PROP_LEN, fp );
|
||||
// look for $engine_subsystem=xxx
|
||||
@@ -2613,23 +2740,25 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
|
||||
// set wash_info_index to invalid
|
||||
int table_error = 1;
|
||||
bank->wash_info_pointer = NULL;
|
||||
bank.wash_info_pointer = NULL;
|
||||
bank.sub_model = -1;
|
||||
for (int k=0; k<n_subsystems; k++) {
|
||||
if ( !subsystem_stricmp(subsystems[k].subobj_name, engine_subsys_name) ) {
|
||||
bank->wash_info_pointer = subsystems[k].engine_wash_pointer;
|
||||
if (bank->wash_info_pointer != NULL) {
|
||||
bank.wash_info_pointer = subsystems[k].engine_wash_pointer;
|
||||
if (bank.wash_info_pointer != NULL) {
|
||||
table_error = 0;
|
||||
}
|
||||
// also set what subsystem this is attached to but not if we only have one thruster bank
|
||||
// do this so that original :V: models still work like they used to
|
||||
if (pm->n_thrusters > 1) {
|
||||
bank->obj_num = k;
|
||||
if (n_thrusters > 1) {
|
||||
bank.obj_num = k;
|
||||
}
|
||||
bank.sub_model = subsystems[k].subobj_num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( (bank->wash_info_pointer == NULL) && (n_subsystems > 0) ) {
|
||||
if ( (bank.wash_info_pointer == NULL) && (n_subsystems > 0) ) {
|
||||
if (table_error) {
|
||||
// Warning(LOCATION, "No engine wash table entry in ships.tbl for ship model %s", filename);
|
||||
} else {
|
||||
@@ -2637,26 +2766,42 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bank->wash_info_pointer = NULL;
|
||||
bank.wash_info_pointer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < bank->num_points; j++) {
|
||||
glow_point *p = &bank->points[j];
|
||||
glow_point p;
|
||||
vec3d os;
|
||||
if(bank.sub_model > -1){
|
||||
model_find_submodel_offset(&os, pm->id, bank.sub_model);
|
||||
}
|
||||
for (j = 0; j < num_points; j++) {
|
||||
|
||||
cfread_vector( &(p->pnt), fp );
|
||||
cfread_vector( &(p->norm), fp );
|
||||
cfread_vector( &(p.pnt), fp );
|
||||
cfread_vector( &(p.norm), fp );
|
||||
|
||||
if ( pm->version > 2004 ) {
|
||||
p->radius = cfread_float( fp );
|
||||
p.radius = cfread_float( fp );
|
||||
//mprintf(( "Rad = %.2f\n", rad ));
|
||||
} else {
|
||||
p->radius = 1.0f;
|
||||
p.radius = 1.0f;
|
||||
}
|
||||
if(bank.sub_model > -1){
|
||||
vm_vec_sub2(&p.pnt, &os);
|
||||
}
|
||||
|
||||
bank.points.push_back(p);
|
||||
}
|
||||
//mprintf(( "Num slots = %d\n", bank->num_slots ));
|
||||
if(bank.sub_model < 0){
|
||||
pm->submodel[pm->detail[0]].submodel_thruster.push_back(bank);
|
||||
}else{
|
||||
pm->submodel[bank.sub_model].submodel_thruster.push_back(bank);
|
||||
}
|
||||
bank.points.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_TGUN:
|
||||
@@ -4121,6 +4266,157 @@ void submodel_rotate(model_subsystem *psub, submodel_instance_info *sii)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*void submodel_scripted_rotate(object* ship_obj, ship_subsys *pss)
|
||||
{
|
||||
|
||||
if ( pss->system_info->subobj_num < 0 ) return;
|
||||
if(!pss->system_info->scripted_rotation.IsValid())return;
|
||||
|
||||
pss->submodel_info_1.prev_angs = pss->submodel_info_1.angs;
|
||||
|
||||
script_lua_odata lua_ship_obj = l_Ship.Set(object_h(ship_obj));
|
||||
script_lua_odata lua_subsys = l_Subsystem.Set(ship_subsys_h(ship_obj,pss));
|
||||
|
||||
Script_system.SetGlobal("Self", 'o', &lua_ship_obj);
|
||||
Script_system.SetGlobal(pss->system_info->name, 'o', &lua_subsys);
|
||||
|
||||
Script_system.RunBytecode(pss->system_info->scripted_rotation);
|
||||
|
||||
Script_system.GetGlobal(pss->system_info->name, 'o', lua_subsys);
|
||||
|
||||
Script_system.RemGlobal(pss->system_info->name);
|
||||
Script_system.RemGlobal("Self");
|
||||
|
||||
}
|
||||
*/
|
||||
void submodel_scripted_rotate(object* ship_obj, ship_subsys *pss)
|
||||
{
|
||||
model_subsystem *psub = pss->system_info;
|
||||
submodel_instance_info *sii = &pss->submodel_info_1;
|
||||
|
||||
if ( psub->subobj_num < 0 ) return;
|
||||
if(!psub->scripted_rotation.IsValid())return;
|
||||
|
||||
sii->prev_angs = sii->angs;
|
||||
|
||||
// ade_odata ade_ship_obj = l_Ship.Set(object_h(ship_obj));
|
||||
ade_odata ade_sys = l_Subsystem.Set(ship_subsys_h(ship_obj, pss));
|
||||
|
||||
Script_system.SetHookObject("Self", OBJ_INDEX(ship_obj));
|
||||
Script_system.SetHookVar(pss->system_info->name, 'o', &ade_sys);
|
||||
|
||||
Script_system.RunBytecode(psub->scripted_rotation);
|
||||
|
||||
Script_system.RemHookVar("Self");
|
||||
Script_system.RemHookVar(pss->system_info->name);
|
||||
|
||||
}
|
||||
|
||||
void world_find_real_model_point(vec3d *out, vec3d *world_pt, polymodel *pm, int submodel_num, matrix *orient, vec3d *pos);
|
||||
|
||||
void submodel_look_at(polymodel *pm, int mn)
|
||||
{
|
||||
bsp_info * sm;
|
||||
|
||||
if ( mn < 0 ) return;
|
||||
|
||||
sm = &pm->submodel[mn];
|
||||
angles *angs = &pm->submodel[mn].angs;
|
||||
|
||||
if ( sm->movement_type != MOVEMENT_TYPE_LOOK_AT ) return;
|
||||
|
||||
// save last angles
|
||||
// sii->prev_angs = sii->angs;
|
||||
|
||||
// probably send in a calculated desired turn rate
|
||||
/* float diff = sii->desired_turn_rate - sii->cur_turn_rate;
|
||||
|
||||
float final_turn_rate;
|
||||
if (diff > 0) {
|
||||
final_turn_rate = sii->cur_turn_rate + sii->turn_accel * flFrametime;
|
||||
if (final_turn_rate > sii->desired_turn_rate) {
|
||||
final_turn_rate = sii->desired_turn_rate;
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
final_turn_rate = sii->cur_turn_rate - sii->turn_accel * flFrametime;
|
||||
if (final_turn_rate < sii->desired_turn_rate) {
|
||||
final_turn_rate = sii->desired_turn_rate;
|
||||
}
|
||||
} else {
|
||||
final_turn_rate = sii->desired_turn_rate;
|
||||
}
|
||||
|
||||
float delta = (sii->cur_turn_rate + final_turn_rate) * 0.5f * flFrametime;
|
||||
sii->cur_turn_rate = final_turn_rate;
|
||||
*/
|
||||
|
||||
vec3d other, mp;
|
||||
|
||||
int pmn = pm->id;
|
||||
|
||||
model_find_world_point(&mp, &vmd_zero_vector, pmn, sm->look_at, &vmd_identity_matrix, &vmd_zero_vector);
|
||||
world_find_real_model_point(&other, &mp, pm, mn, &vmd_identity_matrix, &vmd_zero_vector);
|
||||
if(!IS_MAT_NULL(&pm->submodel[mn].orientation))vm_vec_rotate(&mp, &other, &pm->submodel[mn].orientation);
|
||||
else mp = other;
|
||||
|
||||
// vm_vec_sub2(&mp, &other);
|
||||
|
||||
|
||||
vec3d d, l;
|
||||
model_find_submodel_offset(&d, pmn, mn);
|
||||
model_find_submodel_offset(&l, pmn, sm->look_at);
|
||||
vm_vec_sub(&other, &l, &d);
|
||||
if(!IS_MAT_NULL(&pm->submodel[mn].orientation))vm_vec_rotate(&l, &other, &pm->submodel[mn].orientation);
|
||||
else l = other;
|
||||
|
||||
|
||||
|
||||
float *a;
|
||||
int axis;
|
||||
|
||||
switch( sm->movement_axis ) {
|
||||
case MOVEMENT_AXIS_X:
|
||||
l.xyz.x = 0;
|
||||
mp.xyz.x = 0;
|
||||
a = &angs->p;
|
||||
axis = 0;
|
||||
break;
|
||||
case MOVEMENT_AXIS_Y:
|
||||
l.xyz.y = 0;
|
||||
mp.xyz.y = 0;
|
||||
a = &angs->h;
|
||||
axis = 1;
|
||||
break;
|
||||
case MOVEMENT_AXIS_Z:
|
||||
l.xyz.z = 0;
|
||||
mp.xyz.z = 0;
|
||||
a = &angs->b;
|
||||
axis = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
vm_vec_normalize(&mp);
|
||||
vm_vec_normalize(&l);
|
||||
|
||||
vec3d c;
|
||||
vm_vec_crossprod(&c, &l, &mp);
|
||||
float dot=vm_vec_dotprod(&l,&mp);
|
||||
if(dot>=0.0f){
|
||||
*a = asin(c.a1d[axis]);
|
||||
}else{
|
||||
*a = PI-asin(c.a1d[axis]);
|
||||
}
|
||||
if (*a > PI2 )
|
||||
*a -= PI2;
|
||||
else if (*a < 0.0f )
|
||||
*a += PI2;
|
||||
|
||||
for (int k=0; k<sm->num_details; k++ ) {
|
||||
pm->submodel[sm->details[k]].angs = *angs;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
void submodel_ai_rotate(model_subsystem *psub, submodel_instance_info *sii)
|
||||
{
|
||||
@@ -4205,35 +4501,39 @@ void submodel_ai_rotate(model_subsystem *psub, submodel_instance_info *sii)
|
||||
// right handed or left handed.
|
||||
void model_make_turret_matrix(int model_num, model_subsystem * turret )
|
||||
{
|
||||
|
||||
|
||||
polymodel * pm;
|
||||
vec3d fvec, uvec, rvec;
|
||||
|
||||
pm = model_get(model_num);
|
||||
bsp_info * gun = &pm->submodel[turret->turret_gun_sobj];
|
||||
bsp_info * base = &pm->submodel[turret->subobj_num];
|
||||
float offset_base_h = 0.0f;
|
||||
float offset_barrel_h = 0.0f;
|
||||
#ifdef WMC_SIDE_TURRETS
|
||||
offset_base_h = -PI_2;
|
||||
offset_barrel_h = -PI_2;
|
||||
#endif
|
||||
|
||||
model_clear_instance(model_num);
|
||||
base->angs.h = offset_base_h;
|
||||
gun->angs.h = offset_barrel_h;
|
||||
model_find_world_dir(&fvec, &turret->turret_norm, model_num, turret->turret_gun_sobj, &vmd_identity_matrix, NULL );
|
||||
|
||||
base->angs.h = -PI_2 + offset_base_h;
|
||||
gun->angs.p = -PI_2;
|
||||
gun->angs.h = offset_barrel_h;
|
||||
base->angs.h = -PI/2.0f;
|
||||
gun->angs.p = -PI/2.0f;
|
||||
model_find_world_dir(&rvec, &turret->turret_norm, model_num, turret->turret_gun_sobj, &vmd_identity_matrix, NULL );
|
||||
|
||||
base->angs.h = 0.0f + offset_base_h;
|
||||
gun->angs.p = -PI_2;
|
||||
gun->angs.h = offset_barrel_h;
|
||||
base->angs.h = 0.0f;
|
||||
gun->angs.p = -PI/2.0f;
|
||||
model_find_world_dir(&uvec, &turret->turret_norm, model_num, turret->turret_gun_sobj, &vmd_identity_matrix, NULL );
|
||||
|
||||
|
||||
/* fvec = turret->turret_norm;
|
||||
uvec = vmd_zero_vector;
|
||||
if(fvec.xyz.x == 0.0f && fvec.xyz.z == 0.0f){
|
||||
uvec = base->offset;
|
||||
if(IS_VEC_NULL(&uvec))uvec.xyz.y = 1;
|
||||
}else{
|
||||
uvec.xyz.y = fvec.xyz.y;
|
||||
if(IS_VEC_NULL(&uvec))uvec.xyz.y = 1;
|
||||
}*/
|
||||
|
||||
vm_vec_normalize(&fvec);
|
||||
// vm_vec_crossprod(&rvec, &uvec, &fvec);
|
||||
// vm_vec_crossprod(&uvec, &fvec, &rvec);
|
||||
vm_vec_normalize(&rvec);
|
||||
vm_vec_normalize(&uvec);
|
||||
|
||||
@@ -4260,6 +4560,8 @@ void model_make_turret_matrix(int model_num, model_subsystem * turret )
|
||||
// Returns 1 if rotated gun, 0 if no gun to rotate (rotation handled by AI)
|
||||
int model_rotate_gun(int model_num, model_subsystem *turret, matrix *orient, angles *base_angles, angles *gun_angles, vec3d *pos, vec3d *dst)
|
||||
{
|
||||
matrix *o = &model_get(turret->model_num)->submodel[turret->subobj_num].orientation;
|
||||
|
||||
polymodel * pm;
|
||||
|
||||
pm = model_get(model_num);
|
||||
@@ -4279,50 +4581,139 @@ int model_rotate_gun(int model_num, model_subsystem *turret, matrix *orient, ang
|
||||
model_make_turret_matrix(model_num, turret );
|
||||
|
||||
Assert( turret->flags & MSS_FLAG_TURRET_MATRIX);
|
||||
// Assert( gun->movement_axis == MOVEMENT_AXIS_X ); // Gun must be able to change pitch
|
||||
// Assert( base->movement_axis == MOVEMENT_AXIS_Z ); // Parent must be able to change heading
|
||||
|
||||
//------------
|
||||
// rotate the dest point into the turret gun normal's frame of
|
||||
// reference, but not using the turret's angles.
|
||||
// Call this vector of_dst
|
||||
// Call this vector of_dst
|
||||
// Object Frame Destination
|
||||
vec3d of_dst;
|
||||
matrix world_to_turret_matrix; // converts world coordinates to turret's FOR
|
||||
vec3d world_to_turret_translate; // converts world coordinates to turret's FOR
|
||||
vec3d tempv;
|
||||
|
||||
vm_vec_unrotate( &tempv, &base->offset, orient);
|
||||
vm_vec_add( &world_to_turret_translate, pos, &tempv );
|
||||
|
||||
vm_vec_sub(&of_dst, dst, pos);
|
||||
vm_vec_rotate(&tempv, &of_dst, orient);
|
||||
model_2_submodel(pm, turret->subobj_num, &tempv, NULL);
|
||||
|
||||
|
||||
vm_matrix_x_matrix( &world_to_turret_matrix, orient, &turret->turret_matrix );
|
||||
|
||||
vm_vec_sub( &tempv, dst, &world_to_turret_translate );
|
||||
vm_vec_rotate( &of_dst, &tempv, &world_to_turret_matrix );
|
||||
|
||||
vm_vec_normalize(&of_dst);
|
||||
|
||||
//------------
|
||||
// Find the heading and pitch that the gun needs to turn to
|
||||
// by extracting them from the of_dst vector.
|
||||
// Call this the desired_angles
|
||||
angles desired_angles;
|
||||
// vm_extract_angles_vector(&desired_angles, &of_dst);
|
||||
angles old1, old2;
|
||||
old1 = *base_angles;
|
||||
old2 = *gun_angles;
|
||||
|
||||
desired_angles.p = (float)acos(of_dst.xyz.z);
|
||||
desired_angles.h = PI - atan2_safe(of_dst.xyz.x, of_dst.xyz.y);
|
||||
desired_angles.b = 0.0f;
|
||||
//figure out what angles we are going to need
|
||||
if(IS_MAT_NULL(o)){
|
||||
//the old turret code
|
||||
vm_vec_rotate(&of_dst, &tempv, &turret->turret_matrix);
|
||||
vm_vec_normalize(&of_dst);
|
||||
|
||||
desired_angles.p = acosf(of_dst.xyz.z);
|
||||
desired_angles.h = PI - atan2_safe(of_dst.xyz.x, of_dst.xyz.y);
|
||||
desired_angles.b = 0.0f;
|
||||
|
||||
// mprintf(( "Z = %.1f, atan= %.1f\n", of_dst.xyz.z, desired_angles.p ));
|
||||
}else{
|
||||
//the new turret code, only active when someone has defined it's orientation
|
||||
|
||||
//------------
|
||||
// Gradually turn the turret towards the desired angles
|
||||
//put of_dst into the proper frame
|
||||
tempv = of_dst;
|
||||
vm_vec_rotate( &of_dst, &tempv, o );
|
||||
|
||||
vm_vec_normalize(&of_dst);
|
||||
|
||||
//need to take the gun's exsisting pitch,
|
||||
//subtract the angle that would give the gun it's current pitch
|
||||
|
||||
float n; //y component of the turret normal is all we need
|
||||
// vm_vec_rotate( &n, &turret->turret_norm, o );
|
||||
//we only need the y component so let's not waste math
|
||||
n = (turret->turret_norm.xyz.x*o->vec.uvec.xyz.x)+(turret->turret_norm.xyz.y*o->vec.uvec.xyz.y)+(turret->turret_norm.xyz.z*o->vec.uvec.xyz.z);
|
||||
|
||||
|
||||
//makeing sure normalise worked
|
||||
//sometimes it's off by a tiny bit, and we don't want acos bitching
|
||||
if(n > 1)n = 1;
|
||||
if(n < -1)n = -1;
|
||||
if(of_dst.xyz.y > 1)of_dst.xyz.y = 1;
|
||||
if(of_dst.xyz.y < -1)of_dst.xyz.y = -1;
|
||||
|
||||
|
||||
desired_angles.p = acosf(of_dst.xyz.y)-acosf(n);
|
||||
desired_angles.h = PI/2.0f-atan2_safe(of_dst.xyz.z, of_dst.xyz.x);
|
||||
desired_angles.b = 0.0f;
|
||||
|
||||
|
||||
//this allows turrets that can rotate 360 to track 360,
|
||||
//rather than stopping and going the other way when the turret has rotated 180
|
||||
if((turret->turret_y_fov >0.0f && fabs(turret->turret_fov) < -.9999f || fabs(turret->turret_fov) >= 0.0f)// if we have a turret that can turn all the way around
|
||||
&& (base_angles->h < 0 && desired_angles.h > 0 || base_angles->h > 0 && desired_angles.h < 0 )// and the current and desired coords are on opposite sides of zero
|
||||
&& fabs((base_angles->h) - (desired_angles.h)) > PI){//and the absolute diference between them is more than half a rotation
|
||||
//then go the other direction
|
||||
if(desired_angles.h > base_angles->h)desired_angles.h -= 2.0f* PI;
|
||||
else desired_angles.h += 2.0f* PI;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//move the turret
|
||||
/* angles t;
|
||||
angles ap;
|
||||
|
||||
ap.h = fabs(fabs(desired_angles.h) - fabs(base_angles->h));
|
||||
ap.p = fabs(fabs(desired_angles.p) - fabs(gun_angles->p));
|
||||
|
||||
//how far it will move this frame
|
||||
float step_size = turret->turret_turning_rate * flFrametime;
|
||||
|
||||
if(base_angles->h < desired_angles.h)base_angles->h+=step_size*(ap.h/PI);
|
||||
else if(base_angles->h > desired_angles.h) base_angles->h-=step_size*(ap.h/PI);
|
||||
|
||||
if((old1.h < base_angles->h && base_angles->h > desired_angles.h) || (old1.h > base_angles->h && base_angles->h < desired_angles.h))
|
||||
base_angles->h = desired_angles.h;
|
||||
|
||||
if(gun_angles->p < desired_angles.p)gun_angles->p+=step_size*(ap.p/PI);
|
||||
else if(gun_angles->p > desired_angles.p)gun_angles->p-=step_size*(ap.p/PI);
|
||||
|
||||
if((old2.p < gun_angles->p && gun_angles->p > desired_angles.p) || (old2.p > gun_angles->p && gun_angles->p < desired_angles.p))
|
||||
gun_angles->p = desired_angles.p;
|
||||
*/
|
||||
angles t;
|
||||
angles ap;
|
||||
|
||||
ap.h = fabs(desired_angles.h - base_angles->h);
|
||||
ap.p = fabs(desired_angles.p - gun_angles->p);
|
||||
|
||||
//how far it will move this frame
|
||||
// float step_size = turret->turret_turning_rate * flFrametime;
|
||||
|
||||
if(base->ang_vel.h < turret->turret_turning_rate*(ap.h/PI))base->ang_vel.h+=flFrametime*turret->turret_turning_rate;
|
||||
else if(base->ang_vel.h > turret->turret_turning_rate*(ap.h/PI)) base->ang_vel.h-=flFrametime*turret->turret_turning_rate/(ap.h/PI_2+.1);
|
||||
if(base->ang_vel.h > turret->turret_turning_rate)base->ang_vel.h = turret->turret_turning_rate;
|
||||
if(base->ang_vel.h < 0.0f)base->ang_vel.h = 0.0f;
|
||||
|
||||
if(base_angles->h < desired_angles.h)base_angles->h+=base->ang_vel.h*flFrametime;
|
||||
else if(base_angles->h > desired_angles.h) base_angles->h-=base->ang_vel.h*flFrametime;
|
||||
|
||||
// if((old1.h < base_angles->h && base_angles->h > desired_angles.h) || (old1.h > base_angles->h && base_angles->h < desired_angles.h))
|
||||
// base_angles->h = desired_angles.h;
|
||||
|
||||
if(base->ang_vel.p < turret->turret_turning_rate*(ap.p/PI))base->ang_vel.p+=flFrametime*turret->turret_turning_rate;
|
||||
else if(base->ang_vel.p > turret->turret_turning_rate*(ap.p/PI)) base->ang_vel.p-=flFrametime*turret->turret_turning_rate/(ap.p/PI_2+.1);
|
||||
if(base->ang_vel.p > turret->turret_turning_rate)base->ang_vel.p = turret->turret_turning_rate;
|
||||
if(base->ang_vel.p < 0.0f)base->ang_vel.p = 0.0f;
|
||||
|
||||
if(gun_angles->p < desired_angles.p)gun_angles->p+=base->ang_vel.p*flFrametime;
|
||||
else if(gun_angles->p > desired_angles.p)gun_angles->p-=base->ang_vel.p*flFrametime;
|
||||
|
||||
// if((old2.p < gun_angles->p && gun_angles->p > desired_angles.p) || (old2.p > gun_angles->p && gun_angles->p < desired_angles.p))
|
||||
// gun_angles->p = desired_angles.p;
|
||||
|
||||
|
||||
// if(step_size && base_angles->h == desired_angles.h)Assert(fabs(old1.h) - fabs(base_angles->h) <= step_size+.0001f);
|
||||
// if(step_size && gun_angles->p == desired_angles.p)Assert(fabs(old2.p) - fabs(gun_angles->p) <= step_size+.0001f);
|
||||
|
||||
|
||||
vm_interp_angle(&base_angles->h, desired_angles.h, step_size);
|
||||
vm_interp_angle(&gun_angles->p, desired_angles.p, step_size);
|
||||
|
||||
// base_angles->h -= step_size*(key_down_timef(KEY_1)-key_down_timef(KEY_2) );
|
||||
// gun_angles->p += step_size*(key_down_timef(KEY_3)-key_down_timef(KEY_4) );
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -4365,9 +4756,20 @@ void model_find_world_point(vec3d * outpnt, vec3d *mpnt,int model_num,int sub_mo
|
||||
//instance up the tree for this point
|
||||
while ((mn >= 0) && (pm->submodel[mn].parent >= 0)) {
|
||||
|
||||
matrix *o = &pm->submodel[mn].orientation;
|
||||
matrix inv, f;
|
||||
|
||||
vm_angles_2_matrix(&m,&pm->submodel[mn].angs );
|
||||
|
||||
if(!IS_MAT_NULL(&pm->submodel[mn].orientation)){
|
||||
vm_matrix_inverse(&inv, &pm->submodel[mn].orientation);
|
||||
vm_matrix_x_matrix(&f, &m, &inv);
|
||||
vm_matrix_x_matrix(&m, &pm->submodel[mn].orientation, &f);
|
||||
}
|
||||
|
||||
vm_vec_unrotate(&tpnt,&pnt,&m);
|
||||
|
||||
|
||||
vm_vec_add(&pnt,&tpnt,&pm->submodel[mn].offset );
|
||||
|
||||
mn = pm->submodel[mn].parent;
|
||||
@@ -4378,6 +4780,78 @@ void model_find_world_point(vec3d * outpnt, vec3d *mpnt,int model_num,int sub_mo
|
||||
vm_vec_add2(outpnt,objpos);
|
||||
}
|
||||
|
||||
//will transform the given offset and orientation matrix from model space
|
||||
//into the given submodel's frame of reference,
|
||||
//pass this coords already transformed into object space in most situations to get usefull stuff
|
||||
//NOTE: this will not apply prop defined orientations to the last object,
|
||||
//but it will take it into account
|
||||
void model_2_submodel(polymodel *pm, int sn, vec3d*v, matrix*m){
|
||||
|
||||
if (pm->submodel[sn].parent != -1)//this will recursively build the proper path through the tree
|
||||
model_2_submodel(pm,pm->submodel[sn].parent,v, m);
|
||||
|
||||
vm_vec_sub2(v, &pm->submodel[sn].offset);
|
||||
vec3d t = *v;
|
||||
|
||||
matrix a;
|
||||
vm_angles_2_matrix(&a, &pm->submodel[sn].angs);
|
||||
if(!IS_MAT_NULL(&pm->submodel[sn].orientation)){
|
||||
matrix inv, f;
|
||||
vm_matrix_inverse(&inv, &pm->submodel[sn].orientation);
|
||||
vm_matrix_x_matrix(&f, &a, &inv);
|
||||
vm_matrix_x_matrix(&a, &pm->submodel[sn].orientation, &f);
|
||||
}
|
||||
vm_vec_rotate(v, &t, &a);
|
||||
|
||||
if(m){
|
||||
//if you want to know the ending transformation as well, here it is
|
||||
matrix M = *m;
|
||||
vm_matrix_x_matrix(m, &M, &a);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void make_submodel_world_matrix(polymodel *pm, int sn, vec3d*v){
|
||||
if (pm->submodel[sn].parent != -1)
|
||||
make_submodel_world_matrix(pm,pm->submodel[sn].parent,v);
|
||||
vm_vec_sub2(v, &pm->submodel[sn].offset);
|
||||
vec3d t = *v;
|
||||
|
||||
matrix a;
|
||||
vm_angles_2_matrix(&a, &pm->submodel[sn].angs);
|
||||
if(!IS_MAT_NULL(&pm->submodel[sn].orientation)){
|
||||
matrix inv, f;
|
||||
vm_matrix_inverse(&inv, &pm->submodel[sn].orientation);
|
||||
vm_matrix_x_matrix(&f, &a, &inv);
|
||||
vm_matrix_x_matrix(&a, &pm->submodel[sn].orientation, &f);
|
||||
}
|
||||
vm_vec_rotate(v, &t, &a);
|
||||
|
||||
}
|
||||
|
||||
//just like below, exept it actualy does what it says it does
|
||||
void world_find_real_model_point(vec3d *out, vec3d *world_pt, polymodel *pm, int submodel_num, matrix *orient, vec3d *pos)
|
||||
{
|
||||
|
||||
|
||||
vec3d tempv1, tempv2;
|
||||
|
||||
// get into ship RF
|
||||
vm_vec_sub(&tempv1, world_pt, pos);
|
||||
vm_vec_rotate(&tempv2, &tempv1, orient);
|
||||
|
||||
if (pm->submodel[submodel_num].parent == -1) {
|
||||
*out = tempv2;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3d os = ZERO_VECTOR;
|
||||
// put into submodel RF
|
||||
make_submodel_world_matrix(pm,submodel_num, &tempv2);
|
||||
*out = tempv2;
|
||||
}
|
||||
|
||||
|
||||
// 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])
|
||||
@@ -4510,7 +4984,20 @@ void model_find_world_dir(vec3d * out_dir, vec3d *in_dir,int model_num, int sub_
|
||||
//instance up the tree for this point
|
||||
while ((mn >= 0) && (pm->submodel[mn].parent >= 0)) {
|
||||
|
||||
matrix *o = &pm->submodel[mn].orientation;
|
||||
matrix inv, f;
|
||||
|
||||
vm_angles_2_matrix(&m,&pm->submodel[mn].angs );
|
||||
|
||||
if(!IS_MAT_NULL(&pm->submodel[mn].orientation)){
|
||||
vm_matrix_inverse(&inv, &pm->submodel[mn].orientation);
|
||||
vm_matrix_x_matrix(&f, &m, &inv);
|
||||
vm_matrix_x_matrix(&m, &pm->submodel[mn].orientation, &f);
|
||||
}
|
||||
/* if(!IS_MAT_NULL(o)){
|
||||
vm_vec_unrotate(&tpnt,&pnt,o);
|
||||
}*/
|
||||
|
||||
vm_vec_unrotate(&tpnt,&pnt,&m);
|
||||
pnt = tpnt;
|
||||
|
||||
@@ -4521,7 +5008,6 @@ void model_find_world_dir(vec3d * out_dir, vec3d *in_dir,int model_num, int sub_
|
||||
vm_vec_unrotate(out_dir,&pnt,objorient);
|
||||
}
|
||||
|
||||
|
||||
// Clears all the submodel instances stored in a model to their defaults.
|
||||
void model_clear_instance(int model_num)
|
||||
{
|
||||
@@ -4651,6 +5137,68 @@ void model_set_instance(int model_num, int sub_model_num, submodel_instance_info
|
||||
}
|
||||
}
|
||||
|
||||
void model_do_childeren_dumb_rotation(polymodel * pm, int mn){
|
||||
while ( mn >= 0 ) {
|
||||
|
||||
bsp_info * sm = &pm->submodel[mn];
|
||||
|
||||
if ( sm->movement_type == MSS_FLAG_DUM_ROTATES ){
|
||||
float *ang;
|
||||
int axis = sm->movement_axis;
|
||||
switch(axis){
|
||||
case MOVEMENT_AXIS_X:
|
||||
ang = &sm->angs.p;
|
||||
break;
|
||||
case MOVEMENT_AXIS_Z:
|
||||
ang = &sm->angs.b;
|
||||
break;
|
||||
default:
|
||||
case MOVEMENT_AXIS_Y:
|
||||
ang = &sm->angs.h;
|
||||
break;
|
||||
}
|
||||
*ang = sm->dumb_turn_rate * float(timestamp())/1000.0f;
|
||||
*ang = ((*ang/(PI*2.0f))-float(int(*ang/(PI*2.0f))))*(PI*2.0f);
|
||||
//this keeps ang from getting bigger than 2PI
|
||||
}
|
||||
|
||||
if(pm->submodel[mn].first_child >-1)model_do_childeren_dumb_rotation(pm, pm->submodel[mn].first_child);
|
||||
|
||||
mn = pm->submodel[mn].next_sibling;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void model_do_dumb_rotation(int pn){
|
||||
polymodel * pm;
|
||||
|
||||
pm = model_get(pn);
|
||||
int mn = pm->detail[0];
|
||||
|
||||
model_do_childeren_dumb_rotation(pm,mn);
|
||||
}
|
||||
|
||||
void model_do_childeren_look_at(polymodel * pm, int mn){
|
||||
while ( mn >= 0 ) {
|
||||
|
||||
submodel_look_at(pm, mn);
|
||||
if(pm->submodel[mn].first_child >-1)model_do_childeren_look_at(pm, pm->submodel[mn].first_child);
|
||||
|
||||
mn = pm->submodel[mn].next_sibling;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void model_do_look_at(int pn){
|
||||
polymodel * pm;
|
||||
|
||||
pm = model_get(pn);
|
||||
int mn = pm->detail[0];
|
||||
|
||||
model_do_childeren_look_at(pm,mn);
|
||||
}
|
||||
|
||||
// Finds a point on the rotation axis of a submodel, used in collision, generally find rotational velocity
|
||||
void model_init_submodel_axis_pt(submodel_instance_info *sii, int model_num, int submodel_num)
|
||||
|
||||
Reference in new issue
Block a user