// function to predict an object's position given the delta time and an objects physics info void physics_predict_pos(physics_info *pi, float delta_time, vec3d *predicted_pos) { apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.x, pi->vel.xyz.x, delta_time, NULL, &predicted_pos->xyz.x ); apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.y, pi->vel.xyz.y, delta_time, NULL, &predicted_pos->xyz.y ); apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.z, pi->vel.xyz.z, delta_time, NULL, &predicted_pos->xyz.z ); }
// function to predict an object's velocity given the parameters void physics_predict_vel(physics_info *pi, float delta_time, vec3d *predicted_vel) { if (pi->flags & PF_CONST_VEL) { predicted_vel = &pi->vel; } else { apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.x, pi->vel.xyz.x, delta_time, &predicted_vel->xyz.x, NULL ); apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.y, pi->vel.xyz.y, delta_time, &predicted_vel->xyz.y, NULL ); apply_physics( pi->side_slip_time_const, pi->desired_vel.xyz.z, pi->vel.xyz.z, delta_time, &predicted_vel->xyz.z, NULL ); } }
bool physical_object::update(const optional_time_point& aNow, const vec3& aForce) { bool updated = false; if (iTimeOfLastUpdate == boost::none) { iTimeOfLastUpdate = aNow; updated = true; } next_physics() = current_physics(); if (iTimeOfLastUpdate != boost::none && aNow != boost::none) updated = apply_physics((*aNow - *iTimeOfLastUpdate).count() * std::chrono::steady_clock::period::num / static_cast<double>(std::chrono::steady_clock::period::den), aForce) || updated; else updated = apply_physics(1.0, aForce) || updated; iTimeOfLastUpdate = aNow; current_physics() = next_physics(); return updated; }
void warp_camera::do_frame(float in_frametime) { vec3d new_vel, delta_pos; apply_physics( c_damping, c_desired_vel.xyz.x, c_vel.xyz.x, in_frametime, &new_vel.xyz.x, &delta_pos.xyz.x ); apply_physics( c_damping, c_desired_vel.xyz.y, c_vel.xyz.y, in_frametime, &new_vel.xyz.y, &delta_pos.xyz.y ); apply_physics( c_damping, c_desired_vel.xyz.z, c_vel.xyz.z, in_frametime, &new_vel.xyz.z, &delta_pos.xyz.z ); c_vel = new_vel; vm_vec_add2( &c_pos, &delta_pos ); float ot = c_time+0.0f; c_time += in_frametime; if ( (ot < 0.667f) && ( c_time >= 0.667f ) ) { vec3d tmp; tmp.xyz.z = 4.739f; // always go this fast forward. // pick x and y velocities so they are always on a // circle with a 25 m radius. float tmp_angle = frand()*PI2; tmp.xyz.x = 22.0f * (float)sin(tmp_angle); tmp.xyz.y = -22.0f * (float)cos(tmp_angle); this->set_velocity( &tmp, 0 ); } if ( (ot < 3.0f ) && ( c_time >= 3.0f ) ) { vec3d tmp = ZERO_VECTOR; this->set_velocity( &tmp, 0 ); } }
void physics_sim_rot_editor(matrix * orient, physics_info * pi, float sim_time) { angles tangles; vec3d new_vel; matrix tmp; angles t1, t2; apply_physics( pi->rotdamp, pi->desired_rotvel.xyz.x, pi->rotvel.xyz.x, sim_time, &new_vel.xyz.x, NULL ); apply_physics( pi->rotdamp, pi->desired_rotvel.xyz.y, pi->rotvel.xyz.y, sim_time, &new_vel.xyz.y, NULL ); apply_physics( pi->rotdamp, pi->desired_rotvel.xyz.z, pi->rotvel.xyz.z, sim_time, &new_vel.xyz.z, NULL ); pi->rotvel = new_vel; tangles.p = pi->rotvel.xyz.x*sim_time; tangles.h = pi->rotvel.xyz.y*sim_time; tangles.b = pi->rotvel.xyz.z*sim_time; t1 = t2 = tangles; t1.h = 0.0f; t1.b = 0.0f; t2.p = 0.0f; t2.b = 0.0f; // put in p & b like normal vm_angles_2_matrix(&pi->last_rotmat, &t1 ); vm_matrix_x_matrix( &tmp, orient, &pi->last_rotmat ); // Put in heading separately vm_angles_2_matrix(&pi->last_rotmat, &t2 ); vm_matrix_x_matrix( orient, &pi->last_rotmat, &tmp ); vm_orthogonalize_matrix(orient); }
// Adds velocity to position // finds velocity and displacement in local coords void physics_sim_vel(vec3d * position, physics_info * pi, float sim_time, matrix *orient) { vec3d local_disp; // displacement in this frame vec3d local_v_in; // velocity in local coords at the start of this frame vec3d local_desired_vel; // desired velocity in local coords vec3d local_v_out; // velocity in local coords following this frame vec3d damp; // Maybe clear the reduced_damp flag. // This fixes the problem of the player getting near-instantaneous acceleration under unknown circumstances. // The larger problem is probably that PF_USE_VEL is getting stuck set. if ((pi->flags & PF_REDUCED_DAMP) && (timestamp_elapsed(pi->reduced_damp_decay))) { pi->flags &= ~PF_REDUCED_DAMP; } // Set up damping constants based on special conditions // ie. shockwave, collision, weapon, dead if (pi->flags & PF_DEAD_DAMP) { // side_slip_time_const is already quite large and now needs to be applied in all directions vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, pi->side_slip_time_const ); } else if (pi->flags & PF_REDUCED_DAMP) { // case of shock, weapon, collide, etc. if ( timestamp_elapsed(pi->reduced_damp_decay) ) { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, 0.0f ); } else { // damp is multiplied by fraction and not fraction^2, gives better collision separation float reduced_damp_fraction_time_left = timestamp_until( pi->reduced_damp_decay ) / (float) REDUCED_DAMP_TIME; damp.xyz.x = pi->side_slip_time_const * ( 1 + (REDUCED_DAMP_FACTOR-1) * reduced_damp_fraction_time_left ); damp.xyz.y = pi->side_slip_time_const * ( 1 + (REDUCED_DAMP_FACTOR-1) * reduced_damp_fraction_time_left ); damp.xyz.z = pi->side_slip_time_const * reduced_damp_fraction_time_left * REDUCED_DAMP_FACTOR; } } else { // regular damping if (pi->use_newtonian_damp) { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, pi->side_slip_time_const ); } else { vm_vec_make( &damp, pi->side_slip_time_const, pi->side_slip_time_const, 0.0f ); } } // Note: CANNOT maintain a *local velocity* since a rotation can occur in this frame. // thus the local velocity of in the next frame can be different (this would require rotate to change local vel // and this is not desired // get local components of current velocity vm_vec_rotate (&local_v_in, &pi->vel, orient); // get local components of desired velocity vm_vec_rotate (&local_desired_vel, &pi->desired_vel, orient); // find updated LOCAL velocity and position in the local x direction apply_physics (damp.xyz.x, local_desired_vel.xyz.x, local_v_in.xyz.x, sim_time, &local_v_out.xyz.x, &local_disp.xyz.x); // find updated LOCAL velocity and position in the local y direction apply_physics (damp.xyz.y, local_desired_vel.xyz.y, local_v_in.xyz.y, sim_time, &local_v_out.xyz.y, &local_disp.xyz.y); // find updated LOCAL velocity and position in the local z direction // for player ship, damp should normally be zero, but may be altered in a shockwave // in death, shockwave,etc. we want damping time const large for all 3 axes // warp in test - make excessive speed drop exponentially from max allowed // become (0.01x in 3 sec) int special_warp_in = FALSE; float excess = local_v_in.xyz.z - pi->max_vel.xyz.z; if (excess > 5 && (pi->flags & PF_SPECIAL_WARP_IN)) { special_warp_in = TRUE; float exp_factor = float(exp(-sim_time / SPECIAL_WARP_T_CONST)); local_v_out.xyz.z = pi->max_vel.xyz.z + excess * exp_factor; local_disp.xyz.z = (pi->max_vel.xyz.z * sim_time) + excess * (float(SPECIAL_WARP_T_CONST) * (1.0f - exp_factor)); } else if (pi->flags & PF_SPECIAL_WARP_OUT) { float exp_factor = float(exp(-sim_time / SPECIAL_WARP_T_CONST)); vec3d temp; vm_vec_rotate(&temp, &pi->prev_ramp_vel, orient); float deficeit = temp.xyz.z - local_v_in.xyz.z; local_v_out.xyz.z = local_v_in.xyz.z + deficeit * (1.0f - exp_factor); local_disp.xyz.z = (local_v_in.xyz.z * sim_time) + deficeit * (sim_time - (float(SPECIAL_WARP_T_CONST) * (1.0f - exp_factor))); } else { apply_physics (damp.xyz.z, local_desired_vel.xyz.z, local_v_in.xyz.z, sim_time, &local_v_out.xyz.z, &local_disp.xyz.z); } // maybe turn off special warp in flag if ((pi->flags & PF_SPECIAL_WARP_IN) && (excess < 5)) { pi->flags &= ~(PF_SPECIAL_WARP_IN); } // update world position from local to world coords using orient vec3d world_disp; vm_vec_unrotate (&world_disp, &local_disp, orient); vm_vec_add2 (position, &world_disp); // update world velocity vm_vec_unrotate(&pi->vel, &local_v_out, orient); if (special_warp_in) { vm_vec_rotate(&pi->prev_ramp_vel, &pi->vel, orient); } }
void physics_sim_rot(matrix * orient, physics_info * pi, float sim_time ) { angles tangles; vec3d new_vel; matrix tmp; float shock_amplitude; float rotdamp; float shock_fraction_time_left; Assert(is_valid_matrix(orient)); Assert(is_valid_vec(&pi->rotvel)); Assert(is_valid_vec(&pi->desired_rotvel)); // Handle special case of shockwave shock_amplitude = 0.0f; if ( pi->flags & PF_IN_SHOCKWAVE ) { if ( timestamp_elapsed(pi->shockwave_decay) ) { pi->flags &= ~PF_IN_SHOCKWAVE; rotdamp = pi->rotdamp; } else { shock_fraction_time_left = timestamp_until( pi->shockwave_decay ) / (float) SW_BLAST_DURATION; rotdamp = pi->rotdamp + pi->rotdamp * (SW_ROT_FACTOR - 1) * shock_fraction_time_left; shock_amplitude = pi->shockwave_shake_amp * shock_fraction_time_left; } } else { rotdamp = pi->rotdamp; } // Do rotational physics with given damping apply_physics( rotdamp, pi->desired_rotvel.xyz.x, pi->rotvel.xyz.x, sim_time, &new_vel.xyz.x, NULL ); apply_physics( rotdamp, pi->desired_rotvel.xyz.y, pi->rotvel.xyz.y, sim_time, &new_vel.xyz.y, NULL ); apply_physics( rotdamp, pi->desired_rotvel.xyz.z, pi->rotvel.xyz.z, sim_time, &new_vel.xyz.z, NULL ); Assert(is_valid_vec(&new_vel)); pi->rotvel = new_vel; tangles.p = pi->rotvel.xyz.x*sim_time; tangles.h = pi->rotvel.xyz.y*sim_time; tangles.b = pi->rotvel.xyz.z*sim_time; /* // Make ship shake due to afterburner. if (pi->flags & PF_AFTERBURNER_ON || !timestamp_elapsed(pi->afterburner_decay) ) { float max_speed; max_speed = vm_vec_mag_quick(&pi->max_vel); tangles.p += (float) (rand()-RAND_MAX_2) * RAND_MAX_1f * pi->speed/max_speed/64.0f; tangles.h += (float) (rand()-RAND_MAX_2) * RAND_MAX_1f * pi->speed/max_speed/64.0f; if ( pi->flags & PF_AFTERBURNER_ON ) { pi->afterburner_decay = timestamp(ABURN_DECAY_TIME); } } */ // Make ship shake due to shockwave, decreasing in amplitude at the end of the shockwave if ( pi->flags & PF_IN_SHOCKWAVE ) { tangles.p += (float) (myrand()-RAND_MAX_2) * RAND_MAX_1f * shock_amplitude; tangles.h += (float) (myrand()-RAND_MAX_2) * RAND_MAX_1f * shock_amplitude; } vm_angles_2_matrix(&pi->last_rotmat, &tangles ); vm_matrix_x_matrix( &tmp, orient, &pi->last_rotmat ); *orient = tmp; vm_orthogonalize_matrix(orient); }
//-------------------------------------------------------------- void testApp::update(){ walls(); apply_physics(); }