void objfly_move_to_new_segment( object * obj, short newseg, int first_time ) { segment *pseg; int old_object_seg = obj->segnum; if ( newseg != obj->segnum ) obj_relink(obj-Objects, newseg ); pseg = &Segments[obj->segnum]; if ( first_time || obj->segnum != old_object_seg) { //moved into new seg vms_vector curcenter,nextcenter; fix step_size,seg_time; short entry_side,exit_side; //what sides we entry and leave through vms_vector dest_point; //where we are heading (center of exit_side) vms_angvec dest_angles; //where we want to be pointing //find new exit side if ( !first_time ) { entry_side = matt_find_connect_side(obj->segnum,old_object_seg); exit_side = Side_opposite[entry_side]; } //if (first_time) obj->fly_info.ft_mode = FP_FORWARD; if (first_time || entry_side==-1 || (pseg->children[exit_side]==-1) || (obj->fly_info.ft_mode!=FP_FORWARD) ) { int i; vms_vector prefvec,segcenter,sidevec; fix best_val=-f2_0; int best_side; //find exit side if (obj->fly_info.ft_mode == FP_FORWARD) { if (first_time) prefvec = obj->orient.fvec; else prefvec = obj->fly_info.heading; vm_vec_normalize(&prefvec); } else prefvec = obj->orient.vecs[obj->fly_info.ft_mode%3]; if (obj->fly_info.ft_mode >= 3) {prefvec.x = -prefvec.x; prefvec.y = -prefvec.y; prefvec.z = -prefvec.z;} compute_segment_center(&segcenter,pseg); best_side=-1; for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) { fix d; if (pseg->children[i]!=-1) { compute_center_point_on_side(&sidevec,pseg,i); vm_vec_sub2(&sidevec,&segcenter); vm_vec_normalize(&sidevec); d = vm_vec_dotprod(&sidevec,&prefvec); if (labs(d) < MIN_D) d=0; if (d > best_val || (d==best_val && i==exit_side)) {best_val=d; best_side=i;} } } if (best_val > 0) obj->fly_info.ft_mode = FP_FORWARD; Assert(best_side!=-1); exit_side = best_side; } //update target point & angles compute_center_point_on_side(&dest_point,pseg,exit_side); //update target point and movement points vm_vec_sub(&obj->phys_info.velocity,&dest_point,&obj->pos); step_size = vm_vec_normalize(&obj->phys_info.velocity); vm_vec_scale(&obj->phys_info.velocity, obj->phys_info.speed); compute_segment_center(&curcenter,pseg); compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]); vm_vec_sub(&obj->fly_info.heading,&nextcenter,&curcenter); angles_from_vector(&dest_angles,&obj->fly_info.heading); //extract angles if (first_time) angles_from_vector(&obj->phys_info.rotvel,&obj->orient.fvec); seg_time = fixdiv(step_size,obj->phys_info.speed); //how long through seg if (seg_time) { obj->fly_info.angle_step.p = fixdiv(delta_ang(obj->phys_info.rotvel.p,dest_angles.p),seg_time); obj->fly_info.angle_step.b = fixdiv(delta_ang(obj->phys_info.rotvel.b,dest_angles.b),seg_time); obj->fly_info.angle_step.h = fixdiv(delta_ang(obj->phys_info.rotvel.h,dest_angles.h),seg_time); } else { obj->phys_info.rotvel = dest_angles; obj->fly_info.angle_step.p = obj->fly_info.angle_step.b = obj->fly_info.angle_step.h = 0; } } }
do_endlevel_flythrough(int n) { object *obj; segment *pseg; int old_player_seg; flydata = &fly_objects[n]; obj = flydata->obj; old_player_seg = obj->segnum; //move the player for this frame if (!flydata->first_time) { vm_vec_scale_add2(&obj->pos,&flydata->step,FrameTime); angvec_add2_scale(&flydata->angles,&flydata->angstep,FrameTime); vm_angles_2_matrix(&obj->orient,&flydata->angles); } //check new player seg update_object_seg(obj); pseg = &Segments[obj->segnum]; if (flydata->first_time || obj->segnum != old_player_seg) { //moved into new seg vms_vector curcenter,nextcenter; fix step_size,seg_time; short entry_side,exit_side; //what sides we entry and leave through vms_vector dest_point; //where we are heading (center of exit_side) vms_angvec dest_angles; //where we want to be pointing vms_matrix dest_orient; int up_side; //find new exit side if (!flydata->first_time) { entry_side = matt_find_connect_side(obj->segnum,old_player_seg); exit_side = Side_opposite[entry_side]; } if (flydata->first_time || entry_side==-1 || pseg->children[exit_side]==-1) exit_side = find_exit_side(obj); { //find closest side to align to fix d,largest_d=-f1_0; int i; for (i=0;i<6;i++) { #ifdef COMPACT_SEGS vms_vector v1; get_side_normal(pseg, i, 0, &v1 ); d = vm_vec_dot(&v1,&flydata->obj->orient.uvec); #else d = vm_vec_dot(&pseg->sides[i].normals[0],&flydata->obj->orient.uvec); #endif if (d > largest_d) {largest_d = d; up_side=i;} } } //update target point & angles compute_center_point_on_side(&dest_point,pseg,exit_side); //update target point and movement points //offset object sideways if (flydata->offset_frac) { int s0=-1,s1,i; vms_vector s0p,s1p; fix dist; for (i=0;i<6;i++) if (i!=entry_side && i!=exit_side && i!=up_side && i!=Side_opposite[up_side]) if (s0==-1) s0 = i; else s1 = i; compute_center_point_on_side(&s0p,pseg,s0); compute_center_point_on_side(&s1p,pseg,s1); dist = fixmul(vm_vec_dist(&s0p,&s1p),flydata->offset_frac); if (dist-flydata->offset_dist > MAX_SLIDE_PER_SEGMENT) dist = flydata->offset_dist + MAX_SLIDE_PER_SEGMENT; flydata->offset_dist = dist; vm_vec_scale_add2(&dest_point,&obj->orient.rvec,dist); } vm_vec_sub(&flydata->step,&dest_point,&obj->pos); step_size = vm_vec_normalize_quick(&flydata->step); vm_vec_scale(&flydata->step,flydata->speed); compute_segment_center(&curcenter,pseg); compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]); vm_vec_sub(&flydata->headvec,&nextcenter,&curcenter); #ifdef COMPACT_SEGS { vms_vector _v1; get_side_normal(pseg, up_side, 0, &_v1 ); vm_vector_2_matrix(&dest_orient,&flydata->headvec,&_v1,NULL); } #else vm_vector_2_matrix(&dest_orient,&flydata->headvec,&pseg->sides[up_side].normals[0],NULL); #endif vm_extract_angles_matrix(&dest_angles,&dest_orient); if (flydata->first_time) vm_extract_angles_matrix(&flydata->angles,&obj->orient); seg_time = fixdiv(step_size,flydata->speed); //how long through seg if (seg_time) { flydata->angstep.x = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.p,dest_angles.p),seg_time))); flydata->angstep.z = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.b,dest_angles.b),seg_time))); flydata->angstep.y = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.h,dest_angles.h),seg_time))); } else { flydata->angles = dest_angles; flydata->angstep.x = flydata->angstep.y = flydata->angstep.z = 0; } } flydata->first_time=0; }
do_flythrough(object *obj,int first_time) //set true if init { segment *pseg; int old_player_seg = obj->segnum; if (first_time) { //vms_vector zero_vector = {0,0,0}; obj->control_type = CT_FLYTHROUGH; //obj->fly_info.angle_step.p = 0; //obj->fly_info.angle_step.b = 0; //obj->fly_info.angle_step.h = 0; //obj->fly_info.heading = zero_vector; } //move the player for this frame if (!first_time) { //vms_vector tempv; //fix rot_step; vm_vec_scale_add2(&obj->pos,&player_step,FrameTime); angvec_add2_scale(&player_angles,&player_angstep,FrameTime); vm_angles_2_matrix(&obj->orient,&player_angles); } //check new player seg update_object_seg(obj); pseg = &Segments[obj->segnum]; if (first_time || obj->segnum != old_player_seg) { //moved into new seg vms_vector curcenter,nextcenter; fix step_size,seg_time; short entry_side,exit_side; //what sides we entry and leave through vms_vector dest_point; //where we are heading (center of exit_side) vms_angvec dest_angles; //where we want to be pointing //find new exit side if (!first_time) { entry_side = matt_find_connect_side(obj->segnum,old_player_seg); exit_side = Side_opposite[entry_side]; } if (first_time) ft_preference = FP_FORWARD; if (first_time || entry_side==-1 || pseg->children[exit_side]==-1 || ft_preference!=FP_FORWARD) { int i; vms_vector prefvec,segcenter,sidevec; fix best_val=-f2_0; int best_side; //find exit side if (ft_preference == FP_FORWARD) { if (first_time) prefvec = obj->orient.fvec; else prefvec = headvec; vm_vec_normalize(&prefvec); } else prefvec = obj->orient.vecs[ft_preference%3]; if (ft_preference >= 3) {prefvec.x = -prefvec.x; prefvec.y = -prefvec.y; prefvec.z = -prefvec.z;} compute_segment_center(&segcenter,pseg); best_side=-1; for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) { fix d; if (pseg->children[i]!=-1) { compute_center_point_on_side(&sidevec,pseg,i); //vm_vec_sub2(&sidevec,&segcenter); //vm_vec_normalize(&sidevec); vm_vec_normalized_dir(&sidevec,&sidevec,&segcenter); d = vm_vec_dotprod(&sidevec,&prefvec); if (labs(d) < MIN_D) d=0; if (d > best_val || (d==best_val && i==exit_side)) {best_val=d; best_side=i;} } } if (best_val > 0) ft_preference = FP_FORWARD; Assert(best_side!=-1); exit_side = best_side; } //update target point & angles compute_center_point_on_side(&dest_point,pseg,exit_side); //update target point and movement points vm_vec_sub(&player_step,&dest_point,&obj->pos); step_size = vm_vec_normalize(&player_step); vm_vec_scale(&player_step,player_speed); compute_segment_center(&curcenter,pseg); compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]); vm_vec_sub(&headvec,&nextcenter,&curcenter); //angles_from_vector(&dest_angles,&headvec); //extract angles vm_extract_angles_vector(&dest_angles,&headvec); //extract angles if (first_time) //angles_from_vector(&player_angles,&obj->orient.fvec); vm_extract_angles_vector(&player_angles,&obj->orient.fvec); seg_time = fixdiv(step_size,player_speed); //how long through seg if (seg_time) { player_angstep.p = fixdiv(delta_ang(player_angles.p,dest_angles.p),seg_time); player_angstep.b = fixdiv(delta_ang(player_angles.b,dest_angles.b),seg_time); player_angstep.h = fixdiv(delta_ang(player_angles.h,dest_angles.h),seg_time); } else { player_angles = dest_angles; player_angstep.p = player_angstep.b = player_angstep.h = 0; } } }