Again reworked new bump hack to only apply when fate == HIT_WALL (to not break level SKYBOX) and made bumping by distance between object position and wall hit point; Removed/handled some safety checks in find_plane_line_intersection() to make sliding along joining edges smoother again while bad values *should* be handled in pyhsics.c and not make object warp-crashing tru the whole level or stuck in walls (fvi code should still be rewritten tho)

This commit is contained in:
zicodxx 2011-03-14 11:07:36 +01:00
parent c5092c89c7
commit 8cff6ca835
3 changed files with 29 additions and 79 deletions

View file

@ -1,5 +1,9 @@
D1X-Rebirth Changelog
20110314
--------
main/fvi.c, main/physics.c: Again reworked new bump hack to only apply when fate == HIT_WALL (to not break level SKYBOX) and made bumping by distance between object position and wall hit point; Removed/handled some safety checks in find_plane_line_intersection() to make sliding along joining edges smoother again while bad values *should* be handled in pyhsics.c and not make object warp-crashing tru the whole level or stuck in walls (fvi code should still be rewritten tho)
20110310
--------
main/kconfig.c: Due to lazy copy&paste sliding up/down speed was divided by 2 - fixed

View file

@ -35,31 +35,6 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#define face_type_num(nfaces,face_num,tri_edge) ((nfaces==1)?0:(tri_edge*2 + face_num))
// keep the original ASM code here in case we need it again one day...
// static inline int oflow_check(fix a,fix b) {
// register int __ret;
// int dummy;
// __asm__ (
// " cdq;"
// " xorl %%edx,%%eax;"
// " subl %%edx,%%eax;"
// " xchgl %%ebx,%%eax;"
// " cdq;"
// " xorl %%edx,%%eax;"
// " subl %%edx,%%eax;"
// " imull %%ebx;"
// " sarl $15,%%edx;"
// " orw %%dx,%%dx;"
// " setnz %%al;"
// " movzbl %%al,%%eax"
// : "=a" (__ret), "=b" (dummy) : "a" (a), "1" (b) : "%edx");
// return __ret;
// }
static int oflow_check(fix a,fix b) {
return 0; /* hoping the floating point fix-math is used */
}
//find the point on the specified plane where the line intersects
//returns true if point found, false if line parallel to plane
//new_pnt is the found point on the plane
@ -76,42 +51,22 @@ int find_plane_line_intersection(vms_vector *new_pnt,vms_vector *plane_pnt,vms_v
num = vm_vec_dot(plane_norm,&w);
den = -vm_vec_dot(plane_norm,&d);
//Why does this assert hit so often
// Assert(num > -rad);
num -= rad; //move point out by rad
num -= rad; //move point out by rad
//check for various bad values
if ( (den==0) || //moving parallel to wall, so can't hit it
((den>0) &&
( (num>den) || //frac greater than one
((-num>>15)>=den))) || //will overflow (large negative)
(den<0 && num<den)) //frac greater than one
if (den == 0) // moving parallel to wall, so can't hit it
return 0;
//do check for potenial overflow
{
fix k;
if (labs(num)/(f1_0/2) >= labs(den)) {Int3(); return 0;}
k = fixdiv(num,den);
Assert(k<=f1_0); //should be trapped above
// Assert(k>=0);
if (oflow_check(d.x,k) || oflow_check(d.y,k) || oflow_check(d.z,k)) return 0;
//Note: it is ok for k to be greater than 1, since this might mean
//that an object with a non-zero radius that moved from p0 to p1
//actually hit the wall on the "other side" of p0.
}
//check for various bad values
if (den > 0 && (-num>>15) >= den) //will overflow (large negative)
num = (f1_0-f0_5)*den;
// FIXME: need to handle those or catch somewhere else?
// if (den > 0 && num > den) //frac greater than one
// return 0;
// if (den < 0 && num < den) //frac greater than one
// return 0;
vm_vec_scale2(&d,num,den);
vm_vec_add(new_pnt,p0,&d);
//we should have vm_vec_scale2_add2()
return 1;
}
@ -356,17 +311,11 @@ int check_line_to_line(fix *t1,fix *t2,vms_vector *p1,vms_vector *v1,vms_vector
det.uvec = *v2;
d = calc_det_value(&det);
if (oflow_check(d,cross_mag2))
return 0;
else
*t1 = fixdiv(d,cross_mag2);
*t1 = fixdiv(d,cross_mag2);
det.uvec = *v1;
d = calc_det_value(&det);
if (oflow_check(d,cross_mag2))
return 0;
else
*t2 = fixdiv(d,cross_mag2);
*t2 = fixdiv(d,cross_mag2);
return 1; //found point
}

View file

@ -297,7 +297,7 @@ void do_physics_sim(object *obj)
int fate=0;
vms_vector frame_vec; //movement in this frame
vms_vector new_pos,ipos; //position after this frame
int count=0,bumpcount=0;
int count=0;
int objnum;
int WallHitSeg, WallHitSide;
fvi_info hit_info;
@ -495,21 +495,6 @@ void do_physics_sim(object *obj)
if ( iseg != obj->segnum )
obj_relink(objnum, iseg );
/*
* On joining edges fvi tends to get inaccurate as hell due to object size. And I have no means to fix that - shame on me (that whole code should be rewritten). Approach is to check if the object interects with the wall and if so, move it out towards segment center. Two things to improve:
* 1) object_intersects_wall() does not say how far we went inside the wall which is why we use while to move out until we do not intersect anymore. This should be improved so we only move one time.
* 2) we move the object towards segment center. Depending on the level architecture this is safe. However this will heavily influence velocity and reduce sliding speed near joining edges. Also depending on velocity it's still possible we might not pass an endge leading into another segment since we are pulled back to the old one.
*/
if (obj->type == OBJ_PLAYER || obj->type == OBJ_ROBOT)
while (object_intersects_wall(obj) && bumpcount++ < 64)
{
vms_vector center,bump_vec;
//bump player a little towards center of segment to unstick
compute_segment_center(&center,&Segments[iseg]);
vm_vec_normalized_dir_quick(&bump_vec,&center,&obj->pos);
vm_vec_scale_add2(&obj->pos,&bump_vec,F0_1);
}
//if start point not in segment, move object to center of segment
if (get_seg_masks(&obj->pos,obj->segnum,0,__FILE__,__LINE__).centermask!=0) {
int n;
@ -619,6 +604,18 @@ void do_physics_sim(object *obj)
try_again = 1;
}
}
/*
* On joining edges fvi tends to get inaccurate as hell due to object size. And I have no means to fix that - shame on me (that whole code should be rewritten). Approach is to check if the object interects with the wall and if so, move it out towards segment center. (also see FIXME in find_plane_line_intersection)
*/
if (object_intersects_wall(obj) && (obj->type == OBJ_PLAYER || obj->type == OBJ_ROBOT))
{
vms_vector center,bump_vec;
compute_segment_center(&center,&Segments[obj->segnum]);
vm_vec_normalized_dir_quick(&bump_vec,&center,&obj->pos);
vm_vec_scale_add2(&obj->pos,&bump_vec,vm_vec_dist(&hit_info.hit_pnt, &obj->pos));
}
break;
}