Descent3/physics/newstyle_fi.cpp

463 lines
14 KiB
C++
Raw Permalink Normal View History

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2024-04-16 03:43:29 +00:00
#include "findintersection.h"
#include "game.h"
#include "log.h"
#include "polymodel.h"
#include "pserror.h"
#include "vecmat.h"
2024-04-16 03:43:29 +00:00
#ifndef NED_PHYSICS
#include "multi.h"
#endif
extern matrix View_matrix;
extern vector View_position;
static vector Original_pos;
static matrix Original_orient;
2024-04-16 03:43:29 +00:00
static vector fvi_move_fvec;
static vector fvi_move_uvec;
static bool fvi_do_orient;
2024-04-16 03:43:29 +00:00
static bool Fvi_f_normal;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
#define MAX_INSTANCE_DEPTH 30
2024-04-16 03:43:29 +00:00
struct instance_context {
2024-04-16 18:56:40 +00:00
matrix m;
vector p;
vector p0;
vector p1;
vector fvec;
vector uvec;
2024-04-16 03:43:29 +00:00
};
static struct instance_context instance_stack[MAX_INSTANCE_DEPTH];
static int instance_depth = 0;
static inline void ns_compute_movement_AABB();
static inline bool ns_movement_manual_AABB(vector *min_xyz, vector *max_xyz);
static void CollideSubmodelFacesUnsorted(poly_model *pm, bsp_info *sm);
/// instance at specified point with specified orientation.
/// if matrix==NULL, don't modify matrix. This will be like doing an offset.
static void newstyle_StartInstanceMatrix(vector *pos, matrix *orient);
/// instance at specified point with specified orientation.
/// if angles==NULL, don't modify matrix. This will be like doing an offset.
static void newstyle_StartInstanceAngles(vector *pos, angvec *angles);
/// pops the old context
static void newstyle_DoneInstance();
2024-05-24 02:57:25 +00:00
static void CollideSubmodel(poly_model *pm, bsp_info *sm, uint32_t f_render_sub);
static void CollidePolygonModel(vector *pos, matrix *orient, int model_num, float *normalized_time,
uint32_t f_render_sub);
2024-04-16 18:56:40 +00:00
static void BuildModelAngleMatrix(matrix *mat, angle ang, vector *axis) {
float x, y, z;
float s, c, t;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
x = axis->x;
y = axis->y;
z = axis->z;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
s = (float)FixSin(ang);
c = (float)FixCos(ang);
t = 1.0f - c;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
mat->rvec.x = t * x * x + c;
mat->rvec.y = t * x * y + s * z;
mat->rvec.z = t * x * z - s * y;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
mat->uvec.x = t * x * y - s * z;
mat->uvec.y = t * y * y + c;
mat->uvec.z = t * y * z + s * x;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
mat->fvec.x = t * x * z + s * y;
mat->fvec.y = t * y * z - s * x;
mat->fvec.z = t * z * z + c;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
float fvi_hit_param;
2024-04-16 03:43:29 +00:00
bool fvi_check_param;
static vector ns_min_xyz;
static vector ns_max_xyz;
inline void ns_compute_movement_AABB() {
2024-04-16 18:56:40 +00:00
vector delta_movement = *fvi_query_ptr->p1 - *fvi_query_ptr->p0;
vector offset_vec;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
offset_vec.x = fvi_query_ptr->rad;
offset_vec.y = fvi_query_ptr->rad;
offset_vec.z = fvi_query_ptr->rad;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
ns_min_xyz = ns_max_xyz = *fvi_query_ptr->p0;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
ns_min_xyz -= offset_vec;
ns_max_xyz += offset_vec;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (delta_movement.x > 0.0f)
ns_max_xyz.x += delta_movement.x;
else
ns_min_xyz.x += delta_movement.x;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (delta_movement.y > 0.0f)
ns_max_xyz.y += delta_movement.y;
else
ns_min_xyz.y += delta_movement.y;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (delta_movement.z > 0.0f)
ns_max_xyz.z += delta_movement.z;
else
ns_min_xyz.z += delta_movement.z;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
inline bool ns_movement_manual_AABB(vector *min_xyz, vector *max_xyz) {
bool overlap = true;
if (max_xyz->y < ns_min_xyz.y || ns_max_xyz.y < min_xyz->y || max_xyz->x < ns_min_xyz.x ||
ns_max_xyz.x < min_xyz->x || max_xyz->z < ns_min_xyz.z || ns_max_xyz.z < min_xyz->z)
overlap = false;
return overlap;
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
// collide with a submodel
// Parameters: nv - the number of verts in the poly
2024-04-16 03:43:29 +00:00
// pointlist - a pointer to a list of pointers to points
// bm - the bitmap handle if texturing. ignored if flat shading
2024-04-16 18:56:40 +00:00
static void CollideSubmodelFacesUnsorted(poly_model *pm, bsp_info *sm) {
int i;
int j;
vector colp;
vector newp;
float col_dist; // distance to hit point
vector *vertex_list[32];
vector wall_norm;
int face_hit_type;
// (For this reference frame)
ns_compute_movement_AABB();
if (ns_movement_manual_AABB(&sm->min, &sm->max)) {
for (i = 0; i < sm->num_faces; i++) {
if (ns_movement_manual_AABB(&sm->face_min[i], &sm->face_max[i])) {
polyface *fp = &sm->faces[i];
if (fp->texnum >= 0 && (GameTextures[pm->textures[fp->texnum]].flags & (TF_FLY_THRU | TF_PASS_THRU)) == 0) {
2024-04-16 18:56:40 +00:00
ASSERT(fp->nverts <= 32);
for (j = 0; j < fp->nverts; j++) {
vertex_list[j] = &sm->verts[fp->vertnums[j]];
}
face_hit_type = check_line_to_face(&newp, &colp, &col_dist, &wall_norm, fvi_query_ptr->p0, fvi_query_ptr->p1,
&fp->normal, vertex_list, fp->nverts, fvi_query_ptr->rad);
if ((fvi_query_ptr->flags & FQ_OBJ_BACKFACE) && (!face_hit_type)) {
vector face_normal = fp->normal;
int count;
face_normal *= -1.0f;
for (count = 0; count < fp->nverts; count++) {
vertex_list[fp->nverts - count - 1] = &sm->verts[fp->vertnums[count]];
}
face_hit_type =
check_line_to_face(&newp, &colp, &col_dist, &wall_norm, fvi_query_ptr->p0, fvi_query_ptr->p1,
&face_normal, vertex_list, fp->nverts, fvi_query_ptr->rad);
}
if (face_hit_type) {
if (col_dist < fvi_collision_dist) {
vector x;
fvi_check_param = true;
x = *fvi_query_ptr->p1 - *fvi_query_ptr->p0;
vm_NormalizeVector(&x);
fvi_hit_param = (newp - *fvi_query_ptr->p0) * x;
if (!(fvi_hit_param > -10000000.0 && fvi_hit_param < 10000000.0)) {
LOG_WARNING << "FVI Warning: fvi_hit_param seems yucky!";
2024-04-16 18:56:40 +00:00
}
fvi_collision_dist = col_dist;
fvi_hit_data_ptr->num_hits = 1;
fvi_hit_data_ptr->hit_object[0] = fvi_curobj;
fvi_hit_data_ptr->hit_subobject[0] = sm - pm->submodel;
fvi_hit_data_ptr->hit_type[0] = HIT_SPHERE_2_POLY_OBJECT;
fvi_hit_data_ptr->hit_wallnorm[0] = wall_norm;
fvi_hit_data_ptr->hit_face_pnt[0] = colp;
fvi_hit_data_ptr->hit_face[0] = i;
Fvi_f_normal = true;
if (fvi_do_orient) {
fvi_hit_data_ptr->hit_subobj_fvec = fvi_move_fvec;
fvi_hit_data_ptr->hit_subobj_uvec = fvi_move_uvec;
fvi_hit_data_ptr->hit_subobj_pos = newp;
}
}
}
}
}
}
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
// instance at specified point with specified orientation
// if matrix==NULL, don't modify matrix. This will be like doing an offset
void newstyle_StartInstanceMatrix(vector *pos, matrix *orient) {
vector tempv, temp0, temp1;
matrix tempm, tempm2;
ASSERT(instance_depth < MAX_INSTANCE_DEPTH);
instance_stack[instance_depth].m = View_matrix;
instance_stack[instance_depth].p = View_position;
instance_stack[instance_depth].p0 = *fvi_query_ptr->p0;
instance_stack[instance_depth].p1 = *fvi_query_ptr->p1;
if (fvi_do_orient) {
instance_stack[instance_depth].fvec = fvi_move_fvec;
instance_stack[instance_depth].uvec = fvi_move_uvec;
}
instance_depth++;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
// step 1: subtract object position from view position
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
tempv = View_position - *pos;
temp0 = *fvi_query_ptr->p0 - *pos;
temp1 = *fvi_query_ptr->p1 - *pos;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (orient) {
// step 2: rotate view vector through object matrix
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
View_position = tempv * *orient;
*fvi_query_ptr->p0 = temp0 * *orient;
*fvi_query_ptr->p1 = temp1 * *orient;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (fvi_do_orient) {
fvi_move_fvec = fvi_move_fvec * *orient;
fvi_move_uvec = fvi_move_uvec * *orient;
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
// step 3: rotate object matrix through view_matrix (vm = ob * vm)
tempm2 = ~*orient;
tempm = tempm2 * View_matrix;
View_matrix = tempm;
}
2024-04-16 03:43:29 +00:00
}
2024-04-16 18:56:40 +00:00
// instance at specified point with specified orientation
// if angles==NULL, don't modify matrix. This will be like doing an offset
static void newstyle_StartInstanceAngles(vector *pos, angvec *angles) {
matrix tm;
2024-04-16 03:43:29 +00:00
if (angles == nullptr) {
newstyle_StartInstanceMatrix(pos, nullptr);
2024-04-16 18:56:40 +00:00
return;
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
vm_AnglesToMatrix(&tm, angles->p, angles->h, angles->b);
newstyle_StartInstanceMatrix(pos, &tm);
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
// pops the old context
static void newstyle_DoneInstance() {
instance_depth--;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
ASSERT(instance_depth >= 0);
View_position = instance_stack[instance_depth].p;
View_matrix = instance_stack[instance_depth].m;
*fvi_query_ptr->p0 = instance_stack[instance_depth].p0;
*fvi_query_ptr->p1 = instance_stack[instance_depth].p1;
if (fvi_do_orient) {
fvi_move_fvec = instance_stack[instance_depth].fvec;
fvi_move_uvec = instance_stack[instance_depth].uvec;
}
2024-04-16 03:43:29 +00:00
}
2024-05-24 02:57:25 +00:00
void CollideSubmodel(poly_model *pm, bsp_info *sm, uint32_t f_render_sub) {
2024-04-16 18:56:40 +00:00
// Don't collide with door housings (That is the 'room' portion of the door)
if ((sm->flags & SOF_SHELL) || (sm->flags & SOF_FRONTFACE))
return;
StartPolyModelPosInstance(&sm->mod_pos);
vector temp_vec = sm->mod_pos + sm->offset;
newstyle_StartInstanceAngles(&temp_vec, &sm->angs);
// Check my bit to see if I get collided with. :)
if (f_render_sub & (0x00000001 << (sm - pm->submodel)))
CollideSubmodelFacesUnsorted(pm, sm);
for (int i = 0; i < sm->num_children; i++) {
CollideSubmodel(pm, &pm->submodel[sm->children[i]], f_render_sub);
}
newstyle_DoneInstance();
DonePolyModelPosInstance();
2024-04-16 03:43:29 +00:00
}
2024-05-24 02:57:25 +00:00
void CollidePolygonModel(vector *pos, matrix *orient, int model_num, float *normalized_time, uint32_t f_render_sub) {
2024-04-16 18:56:40 +00:00
poly_model *po;
ASSERT(Poly_models[model_num].used);
ASSERT(Poly_models[model_num].new_style);
fvi_check_param = false;
po = &Poly_models[model_num];
newstyle_StartInstanceMatrix(pos, orient);
SetModelAnglesAndPos(po, normalized_time);
for (int i = 0; i < po->n_models; i++) {
bsp_info *sm = &po->submodel[i];
if (sm->parent == -1)
CollideSubmodel(po, sm, f_render_sub);
}
newstyle_DoneInstance();
2024-04-16 03:43:29 +00:00
}
#define MULTI_ADD_SPHERE_MIN 1.4f
#define MULTI_ADD_SPHERE_MAX 2.5f
2024-04-16 18:56:40 +00:00
bool PolyCollideObject(object *obj) {
#ifndef NED_PHYSICS
float normalized_time[MAX_SUBOBJECTS];
#endif
vector temp_pos = Original_pos = View_position;
matrix temp_orient = Original_orient = View_matrix;
bool f_use_big_sphere = false;
float addition;
ASSERT(obj >= Objects && obj <= &Objects[Highest_object_index]);
#ifndef NED_PHYSICS
Resolve out-of-bounds in PolyCollideObject (Observed in Retribution level 7 while interacting with an Old Scratch robot.) Potentially might fix issue #530. fvi_moveobj=-1 fvi_moveobj=101 fvi_moveobj=235 fvi_moveobj=374 fvi_moveobj=-378 fvi_moveobj=-378 fvi_moveobj=-374 ==59260==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000003c8f058 at pc 0x0000012857fc bp 0x7ffffb094c50 sp 0x7ffffb094c48 READ of size 1 at 0x000003c8f058 thread T0 f0 PolyCollideObject(object*) $GIT/physics/newstyle_fi.cpp:370 f1 check_hit_obj(int) $GIT/physics/findintersection.cpp:3483 f2 fvi_rooms_objs $GIT/physics/findintersection.cpp:4398 f3 fvi_FindIntersection(fvi_query*, fvi_info*, bool) $GIT/physics/findintersection.cpp:2812 f4 AquireElectricalTarget(object*) $GIT/Descent3/WeaponFire.cpp:1189 f5 CreateAndFireWeapon(vector*, vector*, object*, int) $GIT/Descent3/WeaponFire.cpp:1326 f6 FireWeaponFromObject(object*, int, int, bool, bool) $GIT/Descent3/WeaponFire.cpp:1887 f7 WBFireBattery(object*, otype_wb_info*, int, int, float) $GIT/Descent3/robotfire.cpp:149 f8 FireWeaponFromPlayer(object*, int, int, bool, float) $GIT/Descent3/WeaponFire.cpp:3004 f9 DoFlyingControl(object*) $GIT/Descent3/object.cpp:2450 f10 ObjDoFrame(object*) $GIT/Descent3/object.cpp:2668 f11 ObjDoFrameAll() $GIT/Descent3/object.cpp:2988 f12 GameFrame() $GIT/Descent3/GameLoop.cpp:2980 f13 GameSequencer() $GIT/Descent3/gamesequence.cpp:1221 f14 PlayGame() $GIT/Descent3/game.cpp:834 f15 MainLoop() $GIT/Descent3/descent.cpp:555 f16 Descent3() $GIT/Descent3/descent.cpp:508 f17 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151 0x000003c8f058 is located 52 bytes after global variable 'last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f020) of size 4 0x000003c8f058 is located 8 bytes before global variable 'guard variable for MultiSendHeartbeat()::last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f060) of size 8
2024-08-30 03:02:22 +00:00
if ((Game_mode & GM_MULTI) && !(Netgame.flags & NF_USE_ACC_WEAP) &&
fvi_moveobj >= 0 && Objects[fvi_moveobj].type == OBJ_WEAPON &&
2024-04-16 18:56:40 +00:00
obj->type == OBJ_PLAYER)
f_use_big_sphere = true;
#endif
Resolve out-of-bounds in PolyCollideObject (Observed in Retribution level 7 while interacting with an Old Scratch robot.) Potentially might fix issue #530. fvi_moveobj=-1 fvi_moveobj=101 fvi_moveobj=235 fvi_moveobj=374 fvi_moveobj=-378 fvi_moveobj=-378 fvi_moveobj=-374 ==59260==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000003c8f058 at pc 0x0000012857fc bp 0x7ffffb094c50 sp 0x7ffffb094c48 READ of size 1 at 0x000003c8f058 thread T0 f0 PolyCollideObject(object*) $GIT/physics/newstyle_fi.cpp:370 f1 check_hit_obj(int) $GIT/physics/findintersection.cpp:3483 f2 fvi_rooms_objs $GIT/physics/findintersection.cpp:4398 f3 fvi_FindIntersection(fvi_query*, fvi_info*, bool) $GIT/physics/findintersection.cpp:2812 f4 AquireElectricalTarget(object*) $GIT/Descent3/WeaponFire.cpp:1189 f5 CreateAndFireWeapon(vector*, vector*, object*, int) $GIT/Descent3/WeaponFire.cpp:1326 f6 FireWeaponFromObject(object*, int, int, bool, bool) $GIT/Descent3/WeaponFire.cpp:1887 f7 WBFireBattery(object*, otype_wb_info*, int, int, float) $GIT/Descent3/robotfire.cpp:149 f8 FireWeaponFromPlayer(object*, int, int, bool, float) $GIT/Descent3/WeaponFire.cpp:3004 f9 DoFlyingControl(object*) $GIT/Descent3/object.cpp:2450 f10 ObjDoFrame(object*) $GIT/Descent3/object.cpp:2668 f11 ObjDoFrameAll() $GIT/Descent3/object.cpp:2988 f12 GameFrame() $GIT/Descent3/GameLoop.cpp:2980 f13 GameSequencer() $GIT/Descent3/gamesequence.cpp:1221 f14 PlayGame() $GIT/Descent3/game.cpp:834 f15 MainLoop() $GIT/Descent3/descent.cpp:555 f16 Descent3() $GIT/Descent3/descent.cpp:508 f17 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151 0x000003c8f058 is located 52 bytes after global variable 'last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f020) of size 4 0x000003c8f058 is located 8 bytes before global variable 'guard variable for MultiSendHeartbeat()::last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f060) of size 8
2024-08-30 03:02:22 +00:00
fvi_do_orient = fvi_moveobj >= 0 && Objects[fvi_moveobj].type == OBJ_WEAPON;
2024-04-16 18:56:40 +00:00
2024-04-16 03:43:29 +00:00
#ifndef NED_PHYSICS
2024-04-16 18:56:40 +00:00
if (f_use_big_sphere) {
addition = fvi_query_ptr->rad;
if (addition < MULTI_ADD_SPHERE_MIN) {
addition = MULTI_ADD_SPHERE_MIN;
Resolve out-of-bounds in PolyCollideObject (Observed in Retribution level 7 while interacting with an Old Scratch robot.) Potentially might fix issue #530. fvi_moveobj=-1 fvi_moveobj=101 fvi_moveobj=235 fvi_moveobj=374 fvi_moveobj=-378 fvi_moveobj=-378 fvi_moveobj=-374 ==59260==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000003c8f058 at pc 0x0000012857fc bp 0x7ffffb094c50 sp 0x7ffffb094c48 READ of size 1 at 0x000003c8f058 thread T0 f0 PolyCollideObject(object*) $GIT/physics/newstyle_fi.cpp:370 f1 check_hit_obj(int) $GIT/physics/findintersection.cpp:3483 f2 fvi_rooms_objs $GIT/physics/findintersection.cpp:4398 f3 fvi_FindIntersection(fvi_query*, fvi_info*, bool) $GIT/physics/findintersection.cpp:2812 f4 AquireElectricalTarget(object*) $GIT/Descent3/WeaponFire.cpp:1189 f5 CreateAndFireWeapon(vector*, vector*, object*, int) $GIT/Descent3/WeaponFire.cpp:1326 f6 FireWeaponFromObject(object*, int, int, bool, bool) $GIT/Descent3/WeaponFire.cpp:1887 f7 WBFireBattery(object*, otype_wb_info*, int, int, float) $GIT/Descent3/robotfire.cpp:149 f8 FireWeaponFromPlayer(object*, int, int, bool, float) $GIT/Descent3/WeaponFire.cpp:3004 f9 DoFlyingControl(object*) $GIT/Descent3/object.cpp:2450 f10 ObjDoFrame(object*) $GIT/Descent3/object.cpp:2668 f11 ObjDoFrameAll() $GIT/Descent3/object.cpp:2988 f12 GameFrame() $GIT/Descent3/GameLoop.cpp:2980 f13 GameSequencer() $GIT/Descent3/gamesequence.cpp:1221 f14 PlayGame() $GIT/Descent3/game.cpp:834 f15 MainLoop() $GIT/Descent3/descent.cpp:555 f16 Descent3() $GIT/Descent3/descent.cpp:508 f17 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151 0x000003c8f058 is located 52 bytes after global variable 'last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f020) of size 4 0x000003c8f058 is located 8 bytes before global variable 'guard variable for MultiSendHeartbeat()::last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f060) of size 8
2024-08-30 03:02:22 +00:00
if (fvi_moveobj >= 0 && Objects[fvi_moveobj].mtype.phys_info.flags & PF_NEVER_USE_BIG_SPHERE)
2024-04-16 18:56:40 +00:00
addition /= 2;
} else if (addition > MULTI_ADD_SPHERE_MAX)
addition = MULTI_ADD_SPHERE_MAX;
fvi_query_ptr->rad += addition;
}
2024-04-16 03:43:29 +00:00
#endif
2024-04-16 18:56:40 +00:00
Resolve out-of-bounds in PolyCollideObject (Observed in Retribution level 7 while interacting with an Old Scratch robot.) Potentially might fix issue #530. fvi_moveobj=-1 fvi_moveobj=101 fvi_moveobj=235 fvi_moveobj=374 fvi_moveobj=-378 fvi_moveobj=-378 fvi_moveobj=-374 ==59260==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000003c8f058 at pc 0x0000012857fc bp 0x7ffffb094c50 sp 0x7ffffb094c48 READ of size 1 at 0x000003c8f058 thread T0 f0 PolyCollideObject(object*) $GIT/physics/newstyle_fi.cpp:370 f1 check_hit_obj(int) $GIT/physics/findintersection.cpp:3483 f2 fvi_rooms_objs $GIT/physics/findintersection.cpp:4398 f3 fvi_FindIntersection(fvi_query*, fvi_info*, bool) $GIT/physics/findintersection.cpp:2812 f4 AquireElectricalTarget(object*) $GIT/Descent3/WeaponFire.cpp:1189 f5 CreateAndFireWeapon(vector*, vector*, object*, int) $GIT/Descent3/WeaponFire.cpp:1326 f6 FireWeaponFromObject(object*, int, int, bool, bool) $GIT/Descent3/WeaponFire.cpp:1887 f7 WBFireBattery(object*, otype_wb_info*, int, int, float) $GIT/Descent3/robotfire.cpp:149 f8 FireWeaponFromPlayer(object*, int, int, bool, float) $GIT/Descent3/WeaponFire.cpp:3004 f9 DoFlyingControl(object*) $GIT/Descent3/object.cpp:2450 f10 ObjDoFrame(object*) $GIT/Descent3/object.cpp:2668 f11 ObjDoFrameAll() $GIT/Descent3/object.cpp:2988 f12 GameFrame() $GIT/Descent3/GameLoop.cpp:2980 f13 GameSequencer() $GIT/Descent3/gamesequence.cpp:1221 f14 PlayGame() $GIT/Descent3/game.cpp:834 f15 MainLoop() $GIT/Descent3/descent.cpp:555 f16 Descent3() $GIT/Descent3/descent.cpp:508 f17 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151 0x000003c8f058 is located 52 bytes after global variable 'last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f020) of size 4 0x000003c8f058 is located 8 bytes before global variable 'guard variable for MultiSendHeartbeat()::last_heartbeat' defined in '$GIT/Descent3/multi.cpp:9459:16' (0x3c8f060) of size 8
2024-08-30 03:02:22 +00:00
if (fvi_do_orient && fvi_moveobj >= 0) {
2024-04-16 18:56:40 +00:00
fvi_move_fvec = Objects[fvi_moveobj].orient.fvec;
fvi_move_uvec = Objects[fvi_moveobj].orient.uvec;
}
Fvi_f_normal = false;
View_position = obj->pos;
View_matrix = obj->orient;
ASSERT(obj->flags & OF_POLYGON_OBJECT);
2024-04-16 03:43:29 +00:00
#ifndef NED_PHYSICS
2024-04-16 18:56:40 +00:00
if (obj->type == OBJ_PLAYER || obj->type == OBJ_ROBOT || obj->type == OBJ_DEBRIS || obj->type == OBJ_DOOR ||
obj->type == OBJ_BUILDING || obj->type == OBJ_CLUTTER || obj->type == OBJ_BUILDING) {
SetNormalizedTimeObj(obj, normalized_time);
CollidePolygonModel(&obj->pos, &obj->orient, obj->rtype.pobj_info.model_num, normalized_time,
obj->rtype.pobj_info.subobj_flags);
} else {
CollidePolygonModel(&obj->pos, &obj->orient, obj->rtype.pobj_info.model_num, nullptr,
2024-04-16 18:56:40 +00:00
obj->rtype.pobj_info.subobj_flags);
}
2024-04-16 03:43:29 +00:00
#else
2024-04-16 18:56:40 +00:00
CollidePolygonModel(&obj->pos, &obj->orient, obj->rtype.pobj_info.model_num, NULL, obj->rtype.pobj_info.subobj_flags);
2024-04-16 03:43:29 +00:00
#endif
2024-04-16 18:56:40 +00:00
View_position = temp_pos;
View_matrix = temp_orient;
// Converts everything into world coordinates from submodel space
if (fvi_check_param) {
vector pnt = fvi_hit_data_ptr->hit_face_pnt[0];
int mn = fvi_hit_data_ptr->hit_subobject[0];
matrix m;
poly_model *pm = &Poly_models[obj->rtype.pobj_info.model_num];
while (mn != -1) {
vector tpnt;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
vm_AnglesToMatrix(&m, pm->submodel[mn].angs.p, pm->submodel[mn].angs.h, pm->submodel[mn].angs.b);
vm_TransposeMatrix(&m);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
tpnt = pnt * m;
fvi_hit_data_ptr->hit_wallnorm[0] = fvi_hit_data_ptr->hit_wallnorm[0] * m;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
pnt = tpnt + pm->submodel[mn].offset + pm->submodel[mn].mod_pos;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
mn = pm->submodel[mn].parent;
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
fvi_hit_data_ptr->hit_face_pnt[0] = pnt;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
m = obj->orient;
vm_TransposeMatrix(&m);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
fvi_hit_data_ptr->hit_wallnorm[0] = fvi_hit_data_ptr->hit_wallnorm[0] * m;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
// now instance for the entire object
fvi_hit_data_ptr->hit_face_pnt[0] = fvi_hit_data_ptr->hit_face_pnt[0] * m;
fvi_hit_data_ptr->hit_face_pnt[0] += obj->pos;
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
// Now get the hit point
vector x = *fvi_query_ptr->p1 - *fvi_query_ptr->p0;
vm_NormalizeVector(&x);
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
fvi_hit_data_ptr->hit_pnt = *fvi_query_ptr->p0 + x * fvi_hit_param;
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
if (f_use_big_sphere) {
fvi_query_ptr->rad -= addition;
}
2024-04-16 03:43:29 +00:00
2024-04-16 18:56:40 +00:00
return Fvi_f_normal;
2024-04-16 03:43:29 +00:00
}