Skip to content

Commit eb538ff

Browse files
committed
update turret_alt_math for moving subsystems
1 parent 609ed4e commit eb538ff

File tree

7 files changed

+58
-54
lines changed

7 files changed

+58
-54
lines changed

code/ai/aiturret.cpp

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ typedef struct eval_enemy_obj_struct {
8787
int nearest_objnum;
8888
} eval_enemy_obj_struct;
8989

90+
// the current world orientation of the turret matrix, corresponding to its fvec and uvec defined in the model
91+
// is NOT affected by the turret's current aiming
92+
void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num, int submodel_num, const matrix* objorient)
93+
{
94+
auto pmi = model_get_instance(model_instance_num);
95+
auto pm = model_get(pmi->model_num);
96+
vec3d fvec, uvec;
97+
model_instance_find_world_dir(&fvec, &pm->submodel[submodel_num].frame_of_reference.vec.fvec, pm, pmi, pm->submodel[submodel_num].parent, objorient);
98+
model_instance_find_world_dir(&uvec, &pm->submodel[submodel_num].frame_of_reference.vec.uvec, pm, pmi, pm->submodel[submodel_num].parent, objorient);
99+
vm_vector_2_matrix_norm(out_mat, &fvec, &uvec);
100+
}
101+
90102
/**
91103
* Is object in turret field of view?
92104
*
@@ -158,41 +170,38 @@ bool is_object_radius_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec,
158170
fix_elevation = true;
159171
}
160172

161-
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
173+
if (tp->flags[Model::Subsystem_Flags::Turret_restricted_fov]) {
162174
// Since we no longer maintain world_to_turret_matrix, regenerate it here.
163-
vec3d turret_norm;
164-
matrix turret_matrix, world_to_turret_matrix;
165-
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->subobj_num, &vmd_identity_matrix);
166-
vm_vector_2_matrix(&turret_matrix, &turret_norm, nullptr, nullptr);
167-
vm_matrix_x_matrix(&world_to_turret_matrix, &objp->orient, &turret_matrix);
175+
matrix turret_matrix;
176+
turret_instance_find_world_orient(&turret_matrix, Ships[Objects[ss->parent_objnum].instance].model_instance_num, tp->subobj_num, &vmd_identity_matrix);
168177

169-
vec3d temp_vec2;
170-
vm_vec_rotate(&temp_vec2, &temp_vec, &world_to_turret_matrix);
178+
vec3d turret_v2e;
179+
vm_vec_rotate(&turret_v2e, &temp_vec, &turret_matrix);
171180

172181
// now in turrets frame of reference
173182
// check if math is actually possible
174-
if (!((temp_vec2.xyz.x == 0) && (temp_vec2.xyz.y == 0))) {
175-
float temp_z = temp_vec2.xyz.z;
176-
temp_vec2.xyz.z = 0.0f;
183+
if (!((turret_v2e.xyz.x == 0) && (turret_v2e.xyz.z == 0))) {
184+
float temp_y = turret_v2e.xyz.y;
185+
turret_v2e.xyz.y = 0.0f;
177186
// make sure null vecs wont happen
178-
if (!IS_VEC_NULL_SQ_SAFE(&temp_vec2)) {
179-
vm_vec_normalize(&temp_vec2);
187+
if (!IS_VEC_NULL_SQ_SAFE(&turret_v2e)) {
188+
vm_vec_normalize(&turret_v2e);
180189
// only do this if it actually is required
181-
if (-temp_vec2.xyz.y < tp->turret_y_fov) {
190+
if (turret_v2e.xyz.z < tp->turret_base_fov) {
182191
float check_pos = 1;
183192

184193
fix_base_rot = true;
185-
temp_vec2.xyz.y = -tp->turret_y_fov;
186-
if (temp_vec2.xyz.x < 0)
187-
check_pos = -1;
188-
temp_vec2.xyz.x = check_pos * sqrtf(1 - (temp_vec2.xyz.y*temp_vec2.xyz.y));
189-
190-
// restore z component
191-
float scaler = sqrtf(1 - (temp_z*temp_z));
192-
vm_vec_scale(&temp_vec2,scaler);
193-
temp_vec2.xyz.z = temp_z;
194+
turret_v2e.xyz.z = tp->turret_base_fov;
195+
if (turret_v2e.xyz.x < 0)
196+
check_pos = -1;
197+
turret_v2e.xyz.x = check_pos * sqrtf(1 - (turret_v2e.xyz.z* turret_v2e.xyz.z));
198+
199+
// restore y component
200+
float scalar = sqrtf(1 - (temp_y*temp_y));
201+
vm_vec_scale(&turret_v2e, scalar);
202+
turret_v2e.xyz.z = temp_y;
194203
// back to world frame
195-
vm_vec_unrotate(&temp_vec, &temp_vec2, &world_to_turret_matrix);
204+
vm_vec_unrotate(&temp_vec, &turret_v2e, &turret_matrix);
196205
}
197206
}
198207
}
@@ -1256,7 +1265,7 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
12561265
if (gpos)
12571266
model_instance_find_world_point(gpos, &vmd_zero_vector, model_instance_num, tp->subobj_num, &objp->orient, &objp->pos);
12581267
if (gvec)
1259-
model_instance_find_world_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient);
1268+
model_instance_find_world_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient, true);
12601269
}
12611270

12621271
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss);
@@ -1317,7 +1326,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
13171326
} else {
13181327
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
13191328
// the turret norm here is from the perspective of the base submodel, not the gun submodel
1320-
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, pm, pmi, tp->subobj_num, &objp->orient);
1329+
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, pm, pmi, pm->submodel[tp->subobj_num].parent, &objp->orient);
13211330
ai_big_pick_attack_point_turret(lep, ssp, &tmp_pos, &turret_norm, &enemy_point, MIN(wip->max_speed * wip->lifetime, wip->weapon_range), tp->turret_fov);
13221331
}
13231332
else {
@@ -1491,7 +1500,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp
14911500
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, 1, &dot_out, &vector_out)) {
14921501
vec3d turret_norm;
14931502

1494-
model_instance_find_world_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient);
1503+
model_instance_find_world_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient, true);
14951504
float dot_return = vm_vec_dot(&turret_norm, &vector_out);
14961505

14971506
if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) {
@@ -2812,25 +2821,20 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
28122821
model_subsystem *tp = ss->system_info;
28132822
float dot = vm_vec_dot(v2e, gvec);
28142823
if (((dot + size_mod) >= tp->turret_fov) && ((dot - size_mod) <= tp->turret_max_fov)) {
2815-
2816-
// Since we no longer maintain world_to_turret_matrix, regenerate it here.
2817-
object *objp = &Objects[ss->parent_objnum];
2818-
vec3d turret_norm;
2819-
matrix turret_matrix, world_to_turret_matrix;
2820-
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->subobj_num, &vmd_identity_matrix);
2821-
vm_vector_2_matrix(&turret_matrix, &turret_norm, nullptr, nullptr);
2822-
vm_matrix_x_matrix(&world_to_turret_matrix, &objp->orient, &turret_matrix);
2824+
object* objp = &Objects[ss->parent_objnum];
2825+
matrix turret_matrix;
2826+
turret_instance_find_world_orient(&turret_matrix, Ships[objp->instance].model_instance_num, tp->subobj_num, &objp->orient);
28232827

28242828
vec3d of_dst;
2825-
vm_vec_rotate( &of_dst, v2e, &world_to_turret_matrix );
2826-
if ((of_dst.xyz.x == 0) && (of_dst.xyz.y == 0)) {
2827-
return true;
2828-
} else {
2829-
of_dst.xyz.z = 0;
2829+
vm_vec_rotate(&of_dst, v2e, &turret_matrix);
2830+
if ((of_dst.xyz.x == 0) && (of_dst.xyz.z == 0))
2831+
return true;
2832+
else {
2833+
of_dst.xyz.y = 0;
28302834
if (!IS_VEC_NULL_SQ_SAFE(&of_dst)) {
28312835
vm_vec_normalize(&of_dst);
28322836
// now we have 2d vector with lenght of 1 that points at the targets direction after being rotated to turrets FOR
2833-
if ((-of_dst.xyz.y + size_mod) >= tp->turret_y_fov)
2837+
if ((of_dst.xyz.z + size_mod) >= tp->turret_base_fov)
28342838
return true;
28352839
}
28362840
}
@@ -2841,7 +2845,7 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
28412845
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
28422846
{
28432847
bool in_fov = false;
2844-
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_alt_math])
2848+
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_restricted_fov])
28452849
in_fov = turret_adv_fov_test(ss, gvec, v2e, size_mod);
28462850
else
28472851
in_fov = turret_std_fov_test(ss, gvec, v2e, size_mod);

code/model/model.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class model_subsystem { /* contains rotation rate info */
159159
vec3d turret_norm; // direction this turret faces (i.e. the normal to the turret base, or the center of the field of view)
160160
float turret_fov; // dot of turret_norm:vec_to_enemy > this means can see
161161
float turret_max_fov; // dot of turret_norm:vec_to_enemy <= this means barrels can elevate up to the target
162-
float turret_y_fov; // turret's base's fov
162+
float turret_base_fov; // turret's base's fov
163163
int turret_num_firing_points; // number of firing points on this turret
164164
vec3d turret_firing_point[MAX_TFP]; // in parent object's reference frame, point from which to fire.
165165
int turret_gun_sobj; // Which subobject in this model the firing points are linked to.
@@ -962,7 +962,7 @@ void model_init_submodel_axis_pt(polymodel *pm, polymodel_instance *pmi, int sub
962962
// return the point in 3-space in outpnt.
963963
extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_num, int submodel_num, const matrix *objorient);
964964
extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, int submodel_num, const matrix *objorient);
965-
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient);
965+
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient, bool parent = false);
966966
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient);
967967

968968
// Clears all the submodel instances stored in a model to their defaults.

code/model/model_flags.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Model {
2323
Fire_on_target, // prevents turret from firing unless it is pointing at the firingpoints are pointing at the target
2424
No_ss_targeting, // toggles the subsystem targeting for the turret
2525
Turret_reset_idle, // makes turret reset to their initial position if the target is out of field of view
26-
Turret_alt_math, // tells the game to use additional calculations should turret have a defined y fov
26+
Turret_restricted_fov, // tells the game to use additional calculations should turret have a limited base fov or elevation
2727
Dum_rotates, // Bobboau
2828
Carry_shockwave, // subsystem - even with 'carry no damage' flag - will carry shockwave damage to the hull
2929
Allow_landing, // This subsystem can be landed on

code/model/modelread.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3813,7 +3813,7 @@ int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, model
38133813
}
38143814
}
38153815

3816-
if (turret->flags[Model::Subsystem_Flags::Turret_alt_math])
3816+
if (turret->flags[Model::Subsystem_Flags::Turret_restricted_fov])
38173817
limited_base_rotation = true;
38183818

38193819
//------------
@@ -4237,11 +4237,11 @@ void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *
42374237
}
42384238

42394239
// the same as model_find_world_dir - just taking model instance data into account
4240-
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient)
4240+
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient, bool parent)
42414241
{
42424242
auto pmi = model_get_instance(model_instance_num);
42434243
auto pm = model_get(pmi->model_num);
4244-
model_instance_find_world_dir(out_dir, in_dir, pm, pmi, submodel_num, objorient);
4244+
model_instance_find_world_dir(out_dir, in_dir, pm, pmi, parent ? pm->submodel[submodel_num].parent : submodel_num, objorient);
42454245
}
42464246

42474247
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient)
@@ -5370,7 +5370,7 @@ void model_subsystem::reset()
53705370

53715371
turret_fov = 0;
53725372
turret_max_fov = 0;
5373-
turret_y_fov = 0;
5373+
turret_base_fov = 0;
53745374
turret_num_firing_points = 0;
53755375
for (auto it = std::begin(turret_firing_point); it != std::end(turret_firing_point); ++it)
53765376
it->xyz.x = it->xyz.y = it->xyz.z = 0.0f;

code/scripting/api/objs/subsystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ ADE_FUNC(getFOVs, l_Subsystem, nullptr, "Returns current turrets FOVs", "number,
697697

698698
fov = tp->turret_fov;
699699
fov_e = tp->turret_max_fov;
700-
fov_y = tp->turret_y_fov;
700+
fov_y = tp->turret_base_fov;
701701

702702
return ade_set_args(L, "fff", fov, fov_e, fov_y);
703703
}

code/ship/ship.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4815,7 +4815,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
48154815
stuff_int(&value);
48164816
CAP(value, 0, 359);
48174817
float angle = fl_radians(value)/2.0f;
4818-
sp->turret_y_fov = cosf(angle);
4818+
sp->turret_base_fov = cosf(angle);
48194819
turret_has_base_fov = true;
48204820
}
48214821

@@ -4914,7 +4914,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
49144914
}
49154915

49164916
if (turret_has_base_fov)
4917-
sp->flags.set(Model::Subsystem_Flags::Turret_alt_math);
4917+
sp->flags.set(Model::Subsystem_Flags::Turret_restricted_fov);
49184918

49194919
if (optional_string("+non-targetable")) {
49204920
Warning(LOCATION, "Grammar error in table file. Please change \"+non-targetable\" to \"+untargetable\".");

code/weapon/beam.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3567,9 +3567,9 @@ int beam_ok_to_fire(beam *b)
35673567

35683568
if (b->flags & BF_IS_FIGHTER_BEAM) {
35693569
turret_normal = b->objp->orient.vec.fvec;
3570-
b->subsys->system_info->flags.remove(Model::Subsystem_Flags::Turret_alt_math);
3570+
b->subsys->system_info->flags.remove(Model::Subsystem_Flags::Turret_restricted_fov);
35713571
} else {
3572-
model_instance_find_world_dir(&turret_normal, &b->subsys->system_info->turret_norm, Ships[b->objp->instance].model_instance_num, b->subsys->system_info->subobj_num, &b->objp->orient);
3572+
model_instance_find_world_dir(&turret_normal, &b->subsys->system_info->turret_norm, Ships[b->objp->instance].model_instance_num, b->subsys->system_info->subobj_num, &b->objp->orient, true);
35733573
}
35743574

35753575
if (!(turret_fov_test(b->subsys, &turret_normal, &aim_dir))) {

0 commit comments

Comments
 (0)