@@ -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
12621271void 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
28412845bool 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);
0 commit comments