void orient_editor::update_object(object *ptr) { if (ptr->type != OBJ_WAYPOINT && m_point_to) { vec3d v, loc; matrix m; memset(&v, 0, sizeof(vec3d)); loc.xyz.x = convert(m_location_x); loc.xyz.y = convert(m_location_y); loc.xyz.z = convert(m_location_z); if (((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->GetCheck() == 1) { v = Objects[index[m_object_index]].pos; vm_vec_sub2(&v, &ptr->pos); } else if (((CButton *) GetDlgItem(IDC_POINT_TO_LOCATION))->GetCheck() == 1) { vm_vec_sub(&v, &loc, &ptr->pos); } else { Assert(0); // neither radio button is checked. } if (!v.xyz.x && !v.xyz.y && !v.xyz.z){ return; // can't point to itself. } vm_vector_2_matrix(&m, &v, NULL, NULL); ptr->orient = m; } }
// --------------------------------------------------------------------------------------------------- // Do chase mode. // View current segment (Cursegp) from the previous segment. void set_chase_matrix(segment *sp) { int v; vms_vector forvec = ZERO_VECTOR, upvec; vms_vector tv = ZERO_VECTOR; segment *psp; // move back two segments, if possible, else move back one, if possible, else use current if (IS_CHILD(sp->children[WFRONT])) { psp = &Segments[sp->children[WFRONT]]; if (IS_CHILD(psp->children[WFRONT])) psp = &Segments[psp->children[WFRONT]]; } else psp = sp; for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++) vm_vec_add2(&forvec,&Vertices[sp->verts[v]]); vm_vec_scale(&forvec,F1_0/MAX_VERTICES_PER_SEGMENT); for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++) vm_vec_add2(&tv,&Vertices[psp->verts[v]]); vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT); Ed_view_target = forvec; vm_vec_sub2(&forvec,&tv); extract_up_vector_from_segment(psp,&upvec); if (!((forvec.x == 0) && (forvec.y == 0) && (forvec.z == 0))) vm_vector_2_matrix(&LargeView.ev_matrix,&forvec,&upvec,NULL); }
//find the distance between a segment and a point static fix compute_dist(const vcsegptr_t seg,const vms_vector &pos) { auto delta = compute_segment_center(seg); vm_vec_sub2(delta,pos); return vm_vec_mag(delta); }
//find the distance between a segment and a point fix compute_dist(segment *seg,vms_vector *pos) { vms_vector delta; compute_segment_center(&delta,seg); vm_vec_sub2(&delta,pos); return vm_vec_mag(&delta); }
void move_player_2_segment_and_rotate(segment *seg,int side) { vms_vector vp; vms_vector upvec; static int edgenum=0; compute_segment_center(&ConsoleObject->pos,seg); compute_center_point_on_side(&vp,seg,side); vm_vec_sub2(&vp,&ConsoleObject->pos); vm_vec_sub(&upvec, &Vertices[Cursegp->verts[Side_to_verts[Curside][edgenum%4]]], &Vertices[Cursegp->verts[Side_to_verts[Curside][(edgenum+3)%4]]]); edgenum++; vm_vector_2_matrix(&ConsoleObject->orient,&vp,&upvec,NULL); // vm_vector_2_matrix(&ConsoleObject->orient,&vp,NULL,NULL); obj_relink( ConsoleObject-Objects, SEG_PTR_2_NUM(seg) ); }
void do_object_physics( object * obj ) { vms_angvec rotang; vms_vector frame_vec; //movement in this frame vms_vector new_pos,ipos; //position after this frame int iseg; int hit; vms_matrix rotmat,new_pm; int count=0; short joy_x,joy_y,btns; int joyx_moved,joyy_moved; fix speed; vms_vector *desired_upvec; fixang delta_ang,roll_ang; vms_vector forvec = {0,0,f1_0}; vms_matrix temp_matrix; //check keys rotang.pitch = ROT_SPEED * (key_down_time(KEY_UP) - key_down_time(KEY_DOWN)); rotang.head = ROT_SPEED * (key_down_time(KEY_RIGHT) - key_down_time(KEY_LEFT)); rotang.bank = 0; //check for joystick movement joy_get_pos(&joy_x,&joy_y); btns=joy_get_btns(); joyx_moved = (abs(joy_x - _old_joy_x)>JOY_NULL); joyy_moved = (abs(joy_y - _old_joy_y)>JOY_NULL); if (abs(joy_x) < JOY_NULL) joy_x = 0; if (abs(joy_y) < JOY_NULL) joy_y = 0; if (!rotang.pitch) rotang.pitch = fixmul(-joy_y * 128,FrameTime); if (!rotang.head) rotang.head = fixmul(joy_x * 128,FrameTime); if (joyx_moved) _old_joy_x = joy_x; if (joyy_moved) _old_joy_y = joy_y; speed = ((btns&2) || keyd_pressed[KEY_A])?SLOW_SPEED*3:(keyd_pressed[KEY_Z]?SLOW_SPEED/2:SLOW_SPEED); //now build matrices, do rotations, etc., etc. vm_angles_2_matrix(&rotmat,&rotang); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; //move player vm_vec_copy_scale(&obj->velocity,&obj->orient.fvec,speed); vm_vec_copy_scale(&frame_vec,&obj->velocity,FrameTime); do { fix wall_part; vms_vector tvec; count++; vm_vec_add(&new_pos,&obj->pos,&frame_vec); hit = find_vector_intersection(&ipos,&iseg,&obj->pos,obj->seg_id,&new_pos,obj->size,-1); obj->seg_id = iseg; obj->pos = ipos; //-FIXJOHN-if (hit==HIT_OBJECT) ExplodeObject(hit_objnum); if (hit==HIT_WALL) { vm_vec_sub(&frame_vec,&new_pos,&obj->pos); //part through wall wall_part = vm_vec_dot(wall_norm,&frame_vec); vm_vec_copy_scale(&tvec,wall_norm,wall_part); if ((wall_part == 0) || (vm_vec_mag(&tvec) < 5)) Int3(); vm_vec_sub2(&frame_vec,&tvec); } } while (hit == HIT_WALL); Assert(check_point_in_seg(&obj->pos,obj->seg_id,0).centermask==0); //now bank player according to segment orientation desired_upvec = &Segments[obj->seg_id].sides[3].faces[0].normal; if (labs(vm_vec_dot(desired_upvec,&obj->orient.fvec)) < f1_0/2) { vm_vector_2_matrix(&temp_matrix,&obj->orient.fvec,desired_upvec,NULL); delta_ang = vm_vec_delta_ang(&obj->orient.uvec,&temp_matrix.uvec,&obj->orient.fvec); if (rotang.head) delta_ang += (rotang.head<0)?TURNROLL_ANG:-TURNROLL_ANG; if (abs(delta_ang) > DAMP_ANG) { roll_ang = fixmul(FrameTime,ROLL_RATE); if (abs(delta_ang) < roll_ang) roll_ang = delta_ang; else if (delta_ang<0) roll_ang = -roll_ang; vm_vec_ang_2_matrix(&rotmat,&forvec,roll_ang); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; } } }
// ----------------------------------------------------------------------------- void draw_coordinate_axes(void) { int i; short Axes_verts[16]; vms_vector tvec,xvec,yvec,zvec; for (i=0; i<16; i++) Axes_verts[i] = alloc_vert(); create_coordinate_axes_from_segment(Cursegp,Axes_verts); vm_vec_sub(&xvec,&Vertices[Axes_verts[1]],&Vertices[Axes_verts[0]]); vm_vec_sub(&yvec,&Vertices[Axes_verts[2]],&Vertices[Axes_verts[0]]); vm_vec_sub(&zvec,&Vertices[Axes_verts[3]],&Vertices[Axes_verts[0]]); // Create the letter X tvec = xvec; vm_vec_add(&Vertices[Axes_verts[4]],&Vertices[Axes_verts[1]],vm_vec_scale(&tvec,F1_0/16)); tvec = yvec; vm_vec_add2(&Vertices[Axes_verts[4]],vm_vec_scale(&tvec,F1_0/8)); vm_vec_sub(&Vertices[Axes_verts[6]],&Vertices[Axes_verts[4]],vm_vec_scale(&tvec,F2_0)); tvec = xvec; vm_vec_scale(&tvec,F1_0/8); vm_vec_add(&Vertices[Axes_verts[7]],&Vertices[Axes_verts[4]],&tvec); vm_vec_add(&Vertices[Axes_verts[5]],&Vertices[Axes_verts[6]],&tvec); // Create the letter Y tvec = yvec; vm_vec_add(&Vertices[Axes_verts[11]],&Vertices[Axes_verts[2]],vm_vec_scale(&tvec,F1_0/16)); vm_vec_add(&Vertices[Axes_verts[8]],&Vertices[Axes_verts[11]],&tvec); vm_vec_add(&Vertices[Axes_verts[9]],&Vertices[Axes_verts[11]],vm_vec_scale(&tvec,F1_0*2)); vm_vec_add(&Vertices[Axes_verts[10]],&Vertices[Axes_verts[11]],&tvec); tvec = xvec; vm_vec_scale(&tvec,F1_0/16); vm_vec_sub2(&Vertices[Axes_verts[9]],&tvec); vm_vec_add2(&Vertices[Axes_verts[10]],&tvec); // Create the letter Z tvec = zvec; vm_vec_add(&Vertices[Axes_verts[12]],&Vertices[Axes_verts[3]],vm_vec_scale(&tvec,F1_0/16)); tvec = yvec; vm_vec_add2(&Vertices[Axes_verts[12]],vm_vec_scale(&tvec,F1_0/8)); vm_vec_sub(&Vertices[Axes_verts[14]],&Vertices[Axes_verts[12]],vm_vec_scale(&tvec,F2_0)); tvec = zvec; vm_vec_scale(&tvec,F1_0/8); vm_vec_add(&Vertices[Axes_verts[13]],&Vertices[Axes_verts[12]],&tvec); vm_vec_add(&Vertices[Axes_verts[15]],&Vertices[Axes_verts[14]],&tvec); rotate_list(16,Axes_verts); gr_setcolor(AXIS_COLOR); draw_line(Axes_verts[0],Axes_verts[1]); draw_line(Axes_verts[0],Axes_verts[2]); draw_line(Axes_verts[0],Axes_verts[3]); // draw the letter X draw_line(Axes_verts[4],Axes_verts[5]); draw_line(Axes_verts[6],Axes_verts[7]); // draw the letter Y draw_line(Axes_verts[8],Axes_verts[9]); draw_line(Axes_verts[8],Axes_verts[10]); draw_line(Axes_verts[8],Axes_verts[11]); // draw the letter Z draw_line(Axes_verts[12],Axes_verts[13]); draw_line(Axes_verts[13],Axes_verts[14]); draw_line(Axes_verts[14],Axes_verts[15]); for (i=0; i<16; i++) free_vert(Axes_verts[i]); }
/** * nstance at specified point with specified orientation * * if matrix==NULL, don't modify matrix. This will be like doing an offset * if pos==NULL, no position change */ void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api) { vec3d tempv; matrix tempm,tempm2; Assert( G3_count == 1 ); Assert(instance_depth<MAX_INSTANCE_DEPTH); instance_stack[instance_depth].m = View_matrix; instance_stack[instance_depth].p = View_position; instance_stack[instance_depth].lm = Light_matrix; instance_stack[instance_depth].lb = Light_base; instance_stack[instance_depth].om = Object_matrix; instance_stack[instance_depth].op = Object_position; instance_depth++; // Make sure orient is valid if (!orient) { orient = &vmd_identity_matrix; // Assume no change in orient } if ( pos ) { //step 1: subtract object position from view position vm_vec_sub2(&View_position,pos); //step 2: rotate view vector through object matrix vm_vec_rotate(&tempv,&View_position,orient); View_position = tempv; vm_vec_unrotate(&tempv,pos,&Object_matrix); vm_vec_add2(&Object_position, &tempv); } else { // No movement, leave View_position alone } //step 3: rotate object matrix through view_matrix (vm = ob * vm) vm_copy_transpose(&tempm2,orient); vm_matrix_x_matrix(&tempm,&tempm2,&View_matrix); View_matrix = tempm; vm_matrix_x_matrix(&Object_matrix,&instance_stack[instance_depth-1].om,orient); // Update the lighting matrix matrix saved_orient = Light_matrix; vec3d saved_base = Light_base; if ( pos ) { vm_vec_unrotate(&Light_base,pos,&saved_orient ); vm_vec_add2(&Light_base, &saved_base ); } else { // No movement, light_base doesn't change. } vm_matrix_x_matrix(&Light_matrix,&saved_orient, orient); if(!Cmdline_nohtl && set_api) gr_start_instance_matrix(pos, orient); }
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; } } }
// ----------------------------------------------------------------------------------------------------------- // add rotational velocity & acceleration void do_physics_sim_rot(object *obj) { vms_angvec tangles; vms_matrix rotmat,new_orient; //fix rotdrag_scale; physics_info *pi; Assert(FrameTime > 0); //Get MATT if hit this! pi = &obj->mtype.phys_info; if (!(pi->rotvel.x || pi->rotvel.y || pi->rotvel.z || pi->rotthrust.x || pi->rotthrust.y || pi->rotthrust.z)) return; if (obj->mtype.phys_info.drag) { int count; vms_vector accel; fix drag,r,k; count = FrameTime / FT; r = FrameTime % FT; k = fixdiv(r,FT); drag = (obj->mtype.phys_info.drag*5)/2; const char ORIGINAL = 0; const char LINEAR_INTERPOLATION = 1; const char GEOMETRIC_DRAG = 2; const char STRATEGY = ORIGINAL; if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_copy_scale(&accel,&obj->mtype.phys_info.rotthrust,fixdiv(f1_0,obj->mtype.phys_info.mass)); } if(STRATEGY == ORIGINAL) { while (count--) { if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_add2(&obj->mtype.phys_info.rotvel,&accel); } vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-drag); } //do linear scale on remaining bit of time if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_scale_add2(&obj->mtype.phys_info.rotvel,&accel,k); } vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-fixmul(k,drag)); } else if (STRATEGY == LINEAR_INTERPOLATION) { vms_vector target_rotvel; vm_vec_copy_scale(&target_rotvel, &obj->mtype.phys_info.rotvel, F1_0); // Target 21.3 FPS -- three iterations for(int i = 0; i < 3; i++) { if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_add2(&target_rotvel, &accel); } vm_vec_scale(&target_rotvel,f1_0-drag); } fix target_frametime = F1_0 / 64 * 3; fix interpolation_fraction = fixdiv(FrameTime, target_frametime); vm_vec_sub2(&target_rotvel, &obj->mtype.phys_info.rotvel); vm_vec_scale(&target_rotvel, interpolation_fraction); vm_vec_add2(&obj->mtype.phys_info.rotvel, &target_rotvel); } else if(STRATEGY == GEOMETRIC_DRAG) { while (count--) { if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_add2(&obj->mtype.phys_info.rotvel,&accel); } vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-drag); } //do linear scale on remaining bit of time if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_scale_add2(&obj->mtype.phys_info.rotvel,&accel,k); } double target_frametime = 3.0/64.0; const double fix_offset = 65536.0; double interpolation_fraction = ((double)(r) / fix_offset) / target_frametime ; double ddrag = (double)(drag) / fix_offset; double kdrag = pow((1.0 - ddrag), interpolation_fraction*3); fix fractional_drag = (fix)(kdrag * fix_offset); vm_vec_scale(&obj->mtype.phys_info.rotvel,fractional_drag); //vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-fixmul(k,drag)); } /* fix k_drag = f1_0-fixmul(k,drag); if(FrameTime < F1_0/30) { // Pegged to 30 FPS for now double fix_offset = (double) F1_0; double target_framerate = 20.0; double ddrag = ((double) drag)/fix_offset; //double target_drag = (1.0-ddrag)*(1.0-ddrag)*(1.0-ddrag*2.0/15.0); // Drag value multiplied by at 30 hz double target_drag = (1.0-ddrag)*(1.0-ddrag)*(1.0-ddrag)*(1.0-ddrag*2.0/15.0); // Drag value at 20 hz double frame_pow = 20.0 * ((double)(FrameTime)/fix_offset); double frame_drag = pow(target_drag, frame_pow); k_drag = (fix) (frame_drag*fix_offset); } if (obj->mtype.phys_info.flags & PF_USES_THRUST) { vm_vec_copy_scale(&accel,&obj->mtype.phys_info.rotthrust,fixdiv(f1_0,obj->mtype.phys_info.mass)); // CED -- fix this for frame independence! while (count--) { vm_vec_add2(&obj->mtype.phys_info.rotvel,&accel); vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-drag); } //do linear scale on remaining bit of time vm_vec_scale_add2(&obj->mtype.phys_info.rotvel,&accel,k); //vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-fixmul(k,drag)); vm_vec_scale(&obj->mtype.phys_info.rotvel,k_drag); } else { fix total_drag=f1_0; while (count--) total_drag = fixmul(total_drag,f1_0-drag); //do linear scale on remaining bit of time //total_drag = fixmul(total_drag,f1_0-fixmul(k,drag)); total_drag = fixmul(total_drag,k_drag); vm_vec_scale(&obj->mtype.phys_info.rotvel,total_drag); } */ } //now rotate object //unrotate object for bank caused by turn if (obj->mtype.phys_info.turnroll) { vms_matrix new_pm; tangles.p = tangles.h = 0; tangles.b = -obj->mtype.phys_info.turnroll; vm_angles_2_matrix(&rotmat,&tangles); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; } tangles.p = fixmul(obj->mtype.phys_info.rotvel.x,FrameTime); tangles.h = fixmul(obj->mtype.phys_info.rotvel.y,FrameTime); tangles.b = fixmul(obj->mtype.phys_info.rotvel.z,FrameTime); vm_angles_2_matrix(&rotmat,&tangles); vm_matrix_x_matrix(&new_orient,&obj->orient,&rotmat); obj->orient = new_orient; if (obj->mtype.phys_info.flags & PF_TURNROLL) set_object_turnroll(obj); //re-rotate object for bank caused by turn if (obj->mtype.phys_info.turnroll) { vms_matrix new_pm; tangles.p = tangles.h = 0; tangles.b = obj->mtype.phys_info.turnroll; vm_angles_2_matrix(&rotmat,&tangles); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; } check_and_fix_matrix(&obj->orient); }