Skip to content

Commit 12672d0

Browse files
authored
Merge pull request #3310 from Baezon/fix-fov-edge-checks
Fix Fov_edge_checks
2 parents de7081f + 804a222 commit 12672d0

File tree

2 files changed

+34
-118
lines changed

2 files changed

+34
-118
lines changed

code/ai/aiturret.cpp

Lines changed: 33 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -98,124 +98,51 @@ typedef struct eval_enemy_obj_struct {
9898
*
9999
* @return 1 if objp is in fov of the specified turret. Otherwise return 0.
100100
*/
101-
int object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
101+
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
102102
{
103103
vec3d v2e;
104104
float size_mod;
105-
bool in_fov;
105+
bool in_fov = false;
106106

107-
vm_vec_normalized_dir(&v2e, &objp->pos, tpos);
108-
size_mod = objp->radius / (dist + objp->radius);
109-
110-
in_fov = turret_fov_test(ss, tvec, &v2e, size_mod);
111-
112-
if ( in_fov ) {
113-
return 1;
114-
}
107+
if (ss->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
108+
int model_num;
109+
switch (objp->type) {
110+
case OBJ_SHIP:
111+
model_num = Ship_info[Ships[objp->instance].ship_info_index].model_num;
112+
break;
113+
case OBJ_ASTEROID:
114+
model_num = Asteroid_info[Asteroids[objp->instance].asteroid_type].model_num[Asteroids[objp->instance].asteroid_subtype];
115+
break;
116+
default:
117+
vm_vec_normalized_dir(&v2e, &objp->pos, tpos);
118+
size_mod = objp->radius / (dist + objp->radius);
115119

116-
return 0;
117-
}
120+
in_fov = turret_fov_test(ss, tvec, &v2e, size_mod);
118121

119-
bool is_object_radius_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, vec3d *v2e, vec3d *predicted_pos, float distance)
120-
{
121-
float target_dist = distance;
122-
if (distance == 0.0f)
123-
target_dist = vm_vec_dist(predicted_pos,tpos);
124-
125-
if (object_in_turret_fov(objp, ss, tvec, tpos, target_dist + objp->radius)) {
126-
// so the targeted spot in not in fov but the enemy + radius is
127-
// lets align the darn gun and try shooting there
128-
vec3d temp_vec;
129-
float multiplier = 0;
130-
model_subsystem *tp = ss->system_info;
122+
return in_fov;
123+
}
131124

132-
// project v2e_from_turret to turret normal
133-
// substract resultant vector from the temp_vec (v2e_from_turret)
134-
// adjust z component as necessary
135-
// calculate multiplier for the resultant vector
136-
// use multiplier and the z component and compose a new vector
137-
float dot = vm_vec_dot(v2e, tvec);
125+
auto pm = model_get(model_num);
126+
for (int i = 0; i < 8; i++) {
127+
vec3d bbox_point;
128+
vm_vec_unrotate(&bbox_point, &pm->bounding_box[i], &objp->orient);
129+
bbox_point += objp->pos;
138130

139-
vm_vec_scale_add(&temp_vec, v2e, tvec, -dot);
131+
vm_vec_normalized_dir(&v2e, &bbox_point, tpos);
132+
in_fov = turret_fov_test(ss, tvec, &v2e, -0.2f);
140133

141-
if (IS_VEC_NULL_SQ_SAFE(&temp_vec)) {
142-
// return false, target is perfectly aligned over or below the turret
143-
// safe bet is to allow turret to reacquire better target
144-
return false;
134+
if (in_fov)
135+
return true;
145136
}
146137

147-
// normalize the vec, it needs to be done regardless
148-
vm_vec_normalize(&temp_vec);
149-
bool fix_elevation = false;
150-
bool fix_base_rot = false;
151-
152-
if (dot < tp->turret_fov) {
153-
dot = tp->turret_fov;
154-
fix_elevation = true;
155-
}
156-
if (dot > tp->turret_max_fov) {
157-
dot = tp->turret_max_fov;
158-
fix_elevation = true;
159-
}
160-
161-
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
162-
// 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);
168-
169-
vec3d temp_vec2;
170-
vm_vec_rotate(&temp_vec2, &temp_vec, &world_to_turret_matrix);
171-
172-
// now in turrets frame of reference
173-
// 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;
177-
// make sure null vecs wont happen
178-
if (!IS_VEC_NULL_SQ_SAFE(&temp_vec2)) {
179-
vm_vec_normalize(&temp_vec2);
180-
// only do this if it actually is required
181-
if (-temp_vec2.xyz.y < tp->turret_y_fov) {
182-
float check_pos = 1;
183-
184-
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-
// back to world frame
195-
vm_vec_unrotate(&temp_vec, &temp_vec2, &world_to_turret_matrix);
196-
}
197-
}
198-
}
199-
}
138+
} else {
139+
vm_vec_normalized_dir(&v2e, &objp->pos, tpos);
140+
size_mod = objp->radius / (dist + objp->radius);
200141

201-
if (fix_elevation || fix_base_rot) {
202-
if (fix_elevation) {
203-
multiplier = sqrtf(1 - (dot*dot));
204-
// keep the temp_vec scaled with the tweaked vector
205-
vm_vec_scale(&temp_vec, multiplier);
206-
}
207-
vm_vec_scale_add(v2e, &temp_vec, tvec, dot);
208-
// and we are done with v2e...
209-
vm_vec_scale_add(predicted_pos, tpos, v2e, target_dist);
210-
// and we are done with predicted position
211-
return true;
212-
} else {
213-
mprintf(("Warning: Function 'is_object_radius_in_turret_fov' was called\nwithout need to fix turret alignments\n"));
214-
return false;
215-
}
142+
in_fov = turret_fov_test(ss, tvec, &v2e, size_mod);
216143
}
217-
// outside of the expanded radii, unable to align, return false
218-
return false;
144+
145+
return in_fov;
219146
}
220147

221148
/**
@@ -1196,17 +1123,11 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
11961123
if ( tagged_only_flag && ship_is_tagged(&Objects[aip->target_objnum]) ) {
11971124
// select new target if aip->target_objnum is out of field of view
11981125
vec3d v2e;
1199-
float dist;
12001126
bool in_fov;
1201-
dist = vm_vec_normalized_dir(&v2e, &Objects[aip->target_objnum].pos, tpos);
1127+
vm_vec_normalized_dir(&v2e, &Objects[aip->target_objnum].pos, tpos);
12021128

12031129
in_fov = turret_fov_test(turret_subsys, tvec, &v2e);
12041130

1205-
if (turret_subsys->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
1206-
if (in_fov == false)
1207-
if (object_in_turret_fov(&Objects[aip->target_objnum], turret_subsys, tvec, tpos, dist + Objects[aip->target_objnum].radius))
1208-
in_fov = true;
1209-
}
12101131
// MODIFY FOR ATTACKING BIG SHIP
12111132
// dot += (0.5f * Objects[aip->target_objnum].radius / dist);
12121133
if (in_fov) {
@@ -1448,11 +1369,6 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
14481369

14491370
in_fov = turret_fov_test(ss, gvec, &v2e);
14501371

1451-
if (ss->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
1452-
if (in_fov == false)
1453-
in_fov = is_object_radius_in_turret_fov(&Objects[ss->turret_enemy_objnum], ss, gvec, &gun_pos, &v2e, predicted_enemy_pos, 0.0f);
1454-
}
1455-
14561372
if (in_fov) {
14571373
ret_val = model_rotate_gun(objp, pm, pmi, tp, predicted_enemy_pos);
14581374
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {

code/ship/ship.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
17651765

17661766
// return 1 if objp is in fov of the specified turret, tp. Otherwise return 0.
17671767
// dist = distance from turret to center point of object
1768-
int object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist);
1768+
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist);
17691769

17701770
// functions for testing fov.. returns true if fov test is passed.
17711771
bool turret_std_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod = 0);

0 commit comments

Comments
 (0)