From 609bd15fd16d0d6ecd9dc45e3cdbc32d7ce1232a Mon Sep 17 00:00:00 2001 From: zicodxx Date: Wed, 4 May 2011 02:15:07 +0200 Subject: [PATCH] Since current approach to improve wall collisions prevented the player to enter segments which basically are too small for the player ship, added simple bumping function via object_intersects_wall(); Also when validating segments check for segment degeneration outside the editor build, too and set flag in segment structure for all different purposes but right now helps us to disable bumping when encountering degenerated segments and not break such levels --- CHANGELOG.txt | 4 +++ editor/segment.c | 80 -------------------------------------------- main/fvi.c | 5 ++- main/gameseg.c | 86 ++++++++++++++++++++++++++++++++++++++++++++---- main/physics.c | 37 ++++++++++++++------- main/segment.h | 1 + 6 files changed, 113 insertions(+), 100 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 94da78037..4033a755a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D1X-Rebirth Changelog +20110504 +-------- +editor/segment.c, main/fvi.c, main/gameseg.c, main/physics.c, main/segment.h: Since current approach to improve wall collisions prevented the player to enter segments which basically are too small for the player ship, added simple bumping function via object_intersects_wall(); Also when validating segments check for segment degeneration outside the editor build, too and set flag in segment structure for all different purposes but right now helps us to disable bumping when encountering degenerated segments and not break such levels + 20110424 -------- d1x-rebirth.xcodeproj/project.pbxproj, main/newmenu.c: Check if a menu closed in a subfunction before setting it's return value, fixing crash when levels are mismatched in multiplayer; Small tidy up for Xcode project diff --git a/editor/segment.c b/editor/segment.c index 02e86ec77..155958dae 100644 --- a/editor/segment.c +++ b/editor/segment.c @@ -475,50 +475,6 @@ int med_set_vertex(int vnum,vms_vector *vp) return vnum; } - - -// ---- -// A side is determined to be degenerate if the cross products of 3 consecutive points does not point outward. -int check_for_degenerate_side(segment *sp, int sidenum) -{ - sbyte *vp = Side_to_verts[sidenum]; - vms_vector vec1, vec2, cross, vec_to_center; - vms_vector segc, sidec; - fix dot; - int degeneracy_flag = 0; - - compute_segment_center(&segc, sp); - compute_center_point_on_side(&sidec, sp, sidenum); - vm_vec_sub(&vec_to_center, &segc, &sidec); - - //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[1]]], &Vertices[sp->verts[vp[0]]]); - //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); - //vm_vec_normalize(&vec1); - //vm_vec_normalize(&vec2); - vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[1]]], &Vertices[sp->verts[(int) vp[0]]]); - vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); - vm_vec_cross(&cross, &vec1, &vec2); - - dot = vm_vec_dot(&vec_to_center, &cross); - if (dot <= 0) - degeneracy_flag |= 1; - - //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); - //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[3]]], &Vertices[sp->verts[vp[2]]]); - //vm_vec_normalize(&vec1); - //vm_vec_normalize(&vec2); - vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); - vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[3]]], &Vertices[sp->verts[(int) vp[2]]]); - vm_vec_cross(&cross, &vec1, &vec2); - - dot = vm_vec_dot(&vec_to_center, &cross); - if (dot <= 0) - degeneracy_flag |= 1; - - return degeneracy_flag; - -} - // ------------------------------------------------------------------------------- void create_removable_wall(segment *sp, int sidenum, int tmap_num) { @@ -530,42 +486,6 @@ void create_removable_wall(segment *sp, int sidenum, int tmap_num) assign_light_to_side(sp, sidenum); } -// ---- -// See if a segment has gotten turned inside out, or something. -// If so, set global Degenerate_segment_found and return 1, else return 0. -int check_for_degenerate_segment(segment *sp) -{ - vms_vector fvec, rvec, uvec, cross; - fix dot; - int i, degeneracy_flag = 0; // degeneracy flag for current segment - - extract_forward_vector_from_segment(sp, &fvec); - extract_right_vector_from_segment(sp, &rvec); - extract_up_vector_from_segment(sp, &uvec); - - vm_vec_normalize(&fvec); - vm_vec_normalize(&rvec); - vm_vec_normalize(&uvec); - - vm_vec_cross(&cross, &fvec, &rvec); - dot = vm_vec_dot(&cross, &uvec); - - if (dot > 0) - degeneracy_flag = 0; - else { - degeneracy_flag = 1; - } - - // Now, see if degenerate because of any side. - for (i=0; i 0 && (-num>>15) >= den) //will overflow (large negative) num = (f1_0-f0_5)*den; - // FIXME: Handle those better! if (den > 0 && num > den) //frac greater than one - num = den; //return 0; + return 0; if (den < 0 && num < den) //frac greater than one - num = den; //return 0; + return 0; if (labs (num) / (f1_0 / 2) >= labs (den)) return 0; diff --git a/main/gameseg.c b/main/gameseg.c index 35b8684ba..bb30419a2 100644 --- a/main/gameseg.c +++ b/main/gameseg.c @@ -1178,7 +1178,6 @@ void extract_orient_from_segment(vms_matrix *m,segment *seg) vm_vector_2_matrix(m,&fvec,&uvec,NULL); } -#ifdef EDITOR // ------------------------------------------------------------------------------------------ // Extract the forward vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the front face of the segment @@ -1205,8 +1204,87 @@ void extract_up_vector_from_segment(segment *sp,vms_vector *vp) { extract_vector_from_segment(sp,vp,WBOTTOM,WTOP); } + +// ---- +// A side is determined to be degenerate if the cross products of 3 consecutive points does not point outward. +int check_for_degenerate_side(segment *sp, int sidenum) +{ + sbyte *vp = Side_to_verts[sidenum]; + vms_vector vec1, vec2, cross, vec_to_center; + vms_vector segc, sidec; + fix dot; + int degeneracy_flag = 0; + + compute_segment_center(&segc, sp); + compute_center_point_on_side(&sidec, sp, sidenum); + vm_vec_sub(&vec_to_center, &segc, &sidec); + + //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[1]]], &Vertices[sp->verts[vp[0]]]); + //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); + //vm_vec_normalize(&vec1); + //vm_vec_normalize(&vec2); + vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[1]]], &Vertices[sp->verts[(int) vp[0]]]); + vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); + vm_vec_cross(&cross, &vec1, &vec2); + + dot = vm_vec_dot(&vec_to_center, &cross); + if (dot <= 0) + degeneracy_flag |= 1; + + //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); + //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[3]]], &Vertices[sp->verts[vp[2]]]); + //vm_vec_normalize(&vec1); + //vm_vec_normalize(&vec2); + vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); + vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[3]]], &Vertices[sp->verts[(int) vp[2]]]); + vm_vec_cross(&cross, &vec1, &vec2); + + dot = vm_vec_dot(&vec_to_center, &cross); + if (dot <= 0) + degeneracy_flag |= 1; + + return degeneracy_flag; + +} + +// ---- +// See if a segment has gotten turned inside out, or something. +// If so, set global Degenerate_segment_found and return 1, else return 0. +int check_for_degenerate_segment(segment *sp) +{ + vms_vector fvec, rvec, uvec, cross; + fix dot; + int i, degeneracy_flag = 0; // degeneracy flag for current segment + + extract_forward_vector_from_segment(sp, &fvec); + extract_right_vector_from_segment(sp, &rvec); + extract_up_vector_from_segment(sp, &uvec); + + vm_vec_normalize(&fvec); + vm_vec_normalize(&rvec); + vm_vec_normalize(&uvec); + + vm_vec_cross(&cross, &fvec, &rvec); + dot = vm_vec_dot(&cross, &uvec); + + if (dot > 0) + degeneracy_flag = 0; + else { + degeneracy_flag = 1; + } + + // Now, see if degenerate because of any side. + for (i=0; isides[sidenum]; @@ -1642,8 +1720,6 @@ void validate_segment_side(segment *sp, int sidenum) // sp->sides[sidenum].render_flag = 0; } -extern int check_for_degenerate_segment(segment *sp); - // ------------------------------------------------------------------------------- // Make a just-modified segment valid. // check all sides to see how many faces they each should have (0,1,2) @@ -1652,9 +1728,7 @@ void validate_segment(segment *sp) { int side; - #ifdef EDITOR - check_for_degenerate_segment(sp); - #endif + sp->degenerated = check_for_degenerate_segment(sp); for (side = 0; side < MAX_SIDES_PER_SEGMENT; side++) validate_segment_side(sp, side); diff --git a/main/physics.c b/main/physics.c index ab0e3903b..51917358e 100644 --- a/main/physics.c +++ b/main/physics.c @@ -287,6 +287,30 @@ void do_physics_sim_rot(object *obj) check_and_fix_matrix(&obj->orient); } +// 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. +void fix_illegal_wall_intersection(object *obj) +{ + int i = 0; + vms_vector center,bump_vec; + + if ( !(obj->type == OBJ_PLAYER || obj->type == OBJ_ROBOT) ) + return; + if ( !object_intersects_wall(obj) ) + return; + + // HACK: check if the segment the object is located in and all it's children are valid. Otherwise we will break some levels where some segments are only passable since they are degenerated... + if ( Segments[obj->segnum].degenerated ) + return; + for (i = 0; i < MAX_SIDES_PER_SEGMENT; i++) + if ( Segments[obj->segnum].children[i] > -1 && Segments[obj->segnum].children[i] <= Highest_segment_index ) + if ( Segments[Segments[obj->segnum].children[i]].degenerated ) + return; + + compute_segment_center(¢er,&Segments[obj->segnum]); + vm_vec_normalized_dir_quick(&bump_vec,¢er,&obj->pos); + vm_vec_scale_add2(&obj->pos,&bump_vec,F0_1); +} + // ----------------------------------------------------------------------------------------------------------- //Simulate a physics object for this frame void do_physics_sim(object *obj) @@ -562,17 +586,6 @@ void do_physics_sim(object *obj) vms_vector moved_v; fix hit_speed=0, wall_part=0; - /* - * 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(¢er,&Segments[obj->segnum]); - vm_vec_normalized_dir_quick(&bump_vec,¢er,&obj->pos); - vm_vec_scale_add2(&obj->pos,&bump_vec,F0_1); - } - // Find hit speed vm_vec_sub(&moved_v,&obj->pos,&save_pos); @@ -716,6 +729,8 @@ void do_physics_sim(object *obj) vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&moved_vec,fixdiv(f1_0,FrameTime)); } + fix_illegal_wall_intersection(obj); + //Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0); //if (obj->control_type == CT_FLYING) diff --git a/main/segment.h b/main/segment.h index dc67ed267..7a4d64240 100644 --- a/main/segment.h +++ b/main/segment.h @@ -108,6 +108,7 @@ typedef struct segment { sbyte matcen_num; // which center segment is associated with. short value; fix static_light; //average static light in segment + int degenerated; // true if this segment has gotten turned inside out, or something. #ifndef EDITOR short pad; //make structure longword aligned #endif