Fixed incorrect/missing calculation of collision point in check_vector_to_sphere_1 and added special check in check_vector_to_object to only apply for certain objects; Removed extrapolation of physics as it would unintentionally cause premature collisions (requires further fixing of do_physics_sim and do_physics_sim_rot to properly scale to FrameTime)
This commit is contained in:
parent
3ea6b0eb18
commit
d2b0a4d02d
|
@ -414,7 +414,7 @@ static int special_check_line_to_face(vms_vector *newp,const vms_vector *p0,cons
|
|||
//vector defined by p0,p1
|
||||
//returns dist if intersects, and fills in intp
|
||||
//else returns 0
|
||||
static int check_vector_to_sphere_1(vms_vector *intp,const vms_vector *p0,const vms_vector *p1,const vms_vector *sphere_pos,fix sphere_rad)
|
||||
static int check_vector_to_sphere_1(vms_vector *intp,const vms_vector *p0,const vms_vector *p1,const vms_vector *sphere_pos,fix sphere_rad,sbyte haveignoreobj)
|
||||
{
|
||||
vms_vector d,dn,w,closest_point;
|
||||
fix mag_d,dist,w_dist,int_dist;
|
||||
|
@ -454,11 +454,25 @@ static int check_vector_to_sphere_1(vms_vector *intp,const vms_vector *p0,const
|
|||
|
||||
int_dist = w_dist-shorten;
|
||||
|
||||
if (int_dist > mag_d || int_dist < 0) {
|
||||
//past one or the other end of vector, which means we're inside
|
||||
|
||||
*intp = *p0; //don't move at all
|
||||
return 1;
|
||||
if (int_dist > mag_d || int_dist < 0) //past one or the other end of vector, which means we're inside
|
||||
{
|
||||
if (haveignoreobj) // see comment in check_vector_to_object on why we do this...
|
||||
{
|
||||
*intp = *p0; //don't move at all
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//past one or the other end of vector, which means we're inside? WRONG! Either you're inside OR you didn't quite make it!
|
||||
if(vm_vec_dist(p0, sphere_pos) < sphere_rad)
|
||||
{
|
||||
*intp = *p0; //don't move at all
|
||||
vm_vec_scale_add(intp,p0,&dn,int_dist); //calc intersection point
|
||||
return int_dist;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vm_vec_scale_add(intp,p0,&dn,int_dist); //calc intersection point
|
||||
|
@ -578,11 +592,21 @@ static int check_vector_to_sphere_1(vms_vector *intp,const vms_vector *p0,const
|
|||
//$$}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//determine if a vector intersects with an object
|
||||
//if no intersects, returns 0, else fills in intp and returns dist
|
||||
static fix check_vector_to_object(vms_vector *intp,const vms_vector *p0,const vms_vector *p1,fix rad,const object *obj,const object *otherobj)
|
||||
{
|
||||
fix size = obj->size;
|
||||
sbyte i = 0, haveignoreobj = 0;
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
const static int numignore = 10;
|
||||
static const ubyte ignoreobjs[numignore] = { OBJ_NONE, OBJ_FIREBALL, OBJ_HOSTAGE, OBJ_CAMERA, OBJ_POWERUP, OBJ_DEBRIS, OBJ_CLUTTER, OBJ_GHOST, OBJ_LIGHT, OBJ_COOP };
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
const static int numignore = 11;
|
||||
static const ubyte ignoreobjs[numignore] = { OBJ_NONE, OBJ_FIREBALL, OBJ_HOSTAGE, OBJ_CAMERA, OBJ_POWERUP, OBJ_DEBRIS, OBJ_CLUTTER, OBJ_GHOST, OBJ_LIGHT, OBJ_COOP, OBJ_MARKER };
|
||||
#endif
|
||||
|
||||
if (obj->type == OBJ_ROBOT && Robot_info[get_robot_id(obj)].attack_type)
|
||||
size = (size*3)/4;
|
||||
|
@ -592,8 +616,19 @@ static fix check_vector_to_object(vms_vector *intp,const vms_vector *p0,const vm
|
|||
((otherobj->type == OBJ_PLAYER) ||
|
||||
((Game_mode&GM_MULTI_COOP) && otherobj->type == OBJ_WEAPON && otherobj->ctype.laser_info.parent_type == OBJ_PLAYER)))
|
||||
size = size/2;
|
||||
/*
|
||||
* Okay, look, I know this is stupid but hear me out:
|
||||
* The original version of check_vector_to_sphere_1 contains a bug that messes up the collision point of two objects under certain conditions.
|
||||
* This breaks several things, most notably splash damage of projectiles which may very well explode out of range of the target.
|
||||
* However, fixing this bug breaks how non-solid objects are supposed to be handled (collide but don't stop moving). So maybe this bug was just a misconception. Who knows?
|
||||
* Since this function here addresses how different object types are handled, I use it to determine which objects the fix of check_vector_to_sphere_1 will NOT apply to.
|
||||
* If you have a better idea, let me know.
|
||||
*/
|
||||
for (i = 0; i < numignore; i++)
|
||||
if (obj->type == ignoreobjs[i] || otherobj->type == ignoreobjs[i])
|
||||
haveignoreobj = 1;
|
||||
|
||||
return check_vector_to_sphere_1(intp,p0,p1,&obj->pos,size+rad);
|
||||
return check_vector_to_sphere_1(intp,p0,p1,&obj->pos,size+rad,haveignoreobj);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,6 @@ void do_physics_sim(vobjptridx_t obj)
|
|||
physics_info *pi;
|
||||
segnum_t orig_segnum = obj->segnum;
|
||||
int bounced=0;
|
||||
fix PhysTime = (FrameTime<DESIGNATED_GAME_FRAMETIME?DESIGNATED_GAME_FRAMETIME:FrameTime);
|
||||
|
||||
Assert(obj->movement_type == MT_PHYSICS);
|
||||
|
||||
|
@ -336,12 +335,7 @@ void do_physics_sim(vobjptridx_t obj)
|
|||
|
||||
n_phys_segs = 0;
|
||||
|
||||
/* As this engine was not designed for that high FPS as we intend, we use DESIGNATED_GAME_FRAMETIME max. for sim_time to ensure
|
||||
scaling and dot products stay accurate and reliable. The object position intended for this frame will be scaled down later,
|
||||
after the main collision-loop is done.
|
||||
This won't make collision results be equal in all FPS settings, but hopefully more accurate, the higher our FPS are.
|
||||
*/
|
||||
sim_time = PhysTime; //FrameTime;
|
||||
sim_time = FrameTime;
|
||||
|
||||
//debug_obj = obj;
|
||||
|
||||
|
@ -366,7 +360,6 @@ void do_physics_sim(vobjptridx_t obj)
|
|||
Assert(!(obj->mtype.phys_info.flags&PF_USES_THRUST) || obj->mtype.phys_info.drag!=0);
|
||||
|
||||
//do thrust & drag
|
||||
// NOTE: this always must be dependent on FrameTime, if sim_time differs!
|
||||
if ((drag = obj->mtype.phys_info.drag) != 0) {
|
||||
|
||||
int count;
|
||||
|
@ -717,25 +710,6 @@ void do_physics_sim(vobjptridx_t obj)
|
|||
}
|
||||
}
|
||||
|
||||
// As sim_time may not base on FrameTime, scale actual object position to get accurate movement
|
||||
if (PhysTime/FrameTime > 0)
|
||||
{
|
||||
vms_vector md;
|
||||
vm_vec_sub(&md, &obj->pos, &start_pos);
|
||||
vm_vec_scale(&md, F1_0/((float)PhysTime/FrameTime));
|
||||
vm_vec_add(&obj->pos,&start_pos, &md);
|
||||
//check for and update correct object segment
|
||||
if(!get_seg_masks(&obj->pos, obj->segnum, 0, __FILE__, __LINE__).centermask == 0)
|
||||
{
|
||||
if (!update_object_seg(obj)) {
|
||||
if (!(Game_mode & GM_MULTI))
|
||||
Int3();
|
||||
compute_segment_center(&obj->pos,&Segments[obj->segnum]);
|
||||
obj->pos.x += obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After collision with objects and walls, set velocity from actual movement
|
||||
if (!obj_stopped && !bounced
|
||||
&& ((obj->type == OBJ_PLAYER) || (obj->type == OBJ_ROBOT) || (obj->type == OBJ_DEBRIS))
|
||||
|
|
Loading…
Reference in a new issue