void CCharShape::AdjustOrientation (CControl *ctrl, bool eps, ETR_DOUBLE dist_from_surface, const TVector3d& surf_nml) { TVector3d new_y, new_z; static const TVector3d minus_z_vec(0, 0, -1); static const TVector3d y_vec(0, 1, 0); if (dist_from_surface > 0) { new_y = ctrl->cvel; new_y.Norm(); new_z = ProjectToPlane (new_y, TVector3d(0, -1, 0)); new_z.Norm(); new_z = AdjustRollvector (ctrl, ctrl->cvel, new_z); } else { new_z = -1.0 * surf_nml; new_z = AdjustRollvector (ctrl, ctrl->cvel, new_z); new_y = ProjectToPlane (surf_nml, ctrl->cvel); new_y.Norm(); } TVector3d new_x = CrossProduct (new_y, new_z); TMatrix<4, 4> cob_mat(new_x, new_y, new_z); TQuaternion new_orient = MakeQuaternionFromMatrix (cob_mat); if (!ctrl->orientation_initialized) { ctrl->orientation_initialized = true; ctrl->corientation = new_orient; } ETR_DOUBLE time_constant = dist_from_surface > 0 ? TO_AIR_TIME : TO_TIME; float dtime = eps ? EPS : g_game.time_step; ctrl->corientation = InterpolateQuaternions ( ctrl->corientation, new_orient, min (dtime / time_constant, 1.0)); ctrl->plane_nml = RotateVector (ctrl->corientation, minus_z_vec); ctrl->cdirection = RotateVector (ctrl->corientation, y_vec); cob_mat = MakeMatrixFromQuaternion(ctrl->corientation); // Trick rotations new_y = TVector3d (cob_mat[1][0], cob_mat[1][1], cob_mat[1][2]); TMatrix<4, 4> rot_mat = RotateAboutVectorMatrix(new_y, (ctrl->roll_factor * 360)); cob_mat = rot_mat * cob_mat; new_x = TVector3d (cob_mat[0][0], cob_mat[0][1], cob_mat[0][2]); rot_mat = RotateAboutVectorMatrix (new_x, ctrl->flip_factor * 360); cob_mat = rot_mat * cob_mat; TransformNode (0, cob_mat, cob_mat.GetTransposed()); }
static void adjust_orientation(Player& plyr, float dtime, const ppogl::Vec3d& vel, float dist_from_surface, const ppogl::Vec3d& surf_nml) { static ppogl::Vec3d minus_z_vec(0., 0., -1.); static ppogl::Vec3d y_vec(0., 1., 0.); ppogl::Vec3d new_y, new_z; if( dist_from_surface > 0 ){ new_y = 1.*vel; new_y.normalize(); new_z = projectIntoPlane( new_y, ppogl::Vec3d(0., -1., 0.) ); new_z.normalize(); new_z = adjust_tux_zvec_for_roll( plyr, vel, new_z ); }else{ new_z = -1.*surf_nml; new_z = adjust_tux_zvec_for_roll( plyr, vel, new_z ); new_y = projectIntoPlane( surf_nml,1.*vel); new_y.normalize(); } ppogl::Vec3d new_x = new_y^new_z; pp::Quat new_orient; pp::Matrix inv_cob_mat; pp::Matrix rot_mat; { pp::Matrix cob_mat; pp::Matrix::makeChangeOfBasisMatrix( cob_mat, inv_cob_mat, new_x, new_y, new_z ); new_orient = pp::Quat(cob_mat); } if( !plyr.orientation_initialized ){ plyr.orientation_initialized = true; plyr.orientation = new_orient; } float time_constant = dist_from_surface > 0 ? TUX_ORIENTATION_AIRBORNE_TIME_CONSTANT : TUX_ORIENTATION_TIME_CONSTANT; plyr.orientation = pp::Quat::interpolate( plyr.orientation, new_orient, MIN( dtime / time_constant, 1.0 ) ); plyr.plane_nml = plyr.orientation.rotate( minus_z_vec ); plyr.direction = plyr.orientation.rotate( y_vec ); pp::Matrix cob_mat( plyr.orientation ); // Trick rotations new_y = ppogl::Vec3d( cob_mat.data[1][0], cob_mat.data[1][1], cob_mat.data[1][2] ); rot_mat.makeRotationAboutVector( new_y, ( plyr.control.barrel_roll_factor * 360 ) ); cob_mat=rot_mat*cob_mat; new_x = ppogl::Vec3d( cob_mat.data[0][0], cob_mat.data[0][1], cob_mat.data[0][2] ); rot_mat.makeRotationAboutVector( new_x, plyr.control.flip_factor * 360 ); cob_mat=rot_mat*cob_mat; inv_cob_mat.transpose(cob_mat); const std::string& tux_root = tux[plyr.num].getRootNode(); transform_scene_node( tux_root, cob_mat, inv_cob_mat ); }