Пример #1
0
void update_view( player_data_t *plyr, scalar_t dt )
{
    point_t view_pt;
    vector_t view_dir, up_dir, vel_dir, view_vec;
    scalar_t ycoord;
    scalar_t course_angle;
    vector_t axis;
    matrixgl_t rot_mat;
    vector_t y_vec;
    vector_t mz_vec;
    vector_t vel_proj;
    quaternion_t rot_quat;
    scalar_t speed;
    vector_t vel_cpy;
    scalar_t time_constant_mult;

    vel_cpy = plyr->vel;
    speed = normalize_vector( &vel_cpy );

    time_constant_mult = 1.0 /
	min( 1.0, 
	     max( 0.0, 
		  ( speed - NO_INTERPOLATION_SPEED ) /
		  ( BASELINE_INTERPOLATION_SPEED - NO_INTERPOLATION_SPEED )));

    up_dir = make_vector( 0, 1, 0 );

    vel_dir = plyr->vel;
    normalize_vector( &vel_dir );

    course_angle = get_course_angle();

    switch( plyr->view.mode ) {
    case TUXEYE:
    {
        scalar_t f = 2;
        vector_t v = plyr->plane_nml;
        scalar_t n = 1.;

        view_pt = plyr->pos;

        view_pt.x += v.x / n  * 0.3;
        view_pt.y += v.y / n * 0.3;
        view_pt.y += 0.1;
        view_pt.z += v.z / n * 0.3;


        if(plyr->control.flip_factor || plyr->control.barrel_roll_factor) {
            matrixgl_t mat1, mat;
			vector_t right;

            scalar_t n = sqrt(plyr->viewdir_for_tuxeye.x * plyr->viewdir_for_tuxeye.x + plyr->viewdir_for_tuxeye.y * plyr->viewdir_for_tuxeye.y + plyr->viewdir_for_tuxeye.z * plyr->viewdir_for_tuxeye.z);
            plyr->viewdir_for_tuxeye.x /= n;
            plyr->viewdir_for_tuxeye.y /= n;
            plyr->viewdir_for_tuxeye.z /= n;
            n = sqrt(plyr->updir_for_tuxeye.x * plyr->updir_for_tuxeye.x + plyr->updir_for_tuxeye.y * plyr->updir_for_tuxeye.y + plyr->updir_for_tuxeye.z * plyr->updir_for_tuxeye.z);
            plyr->updir_for_tuxeye.x /= n;
            plyr->updir_for_tuxeye.y /= n;
            plyr->updir_for_tuxeye.z /= n;
            right = cross_product(plyr->updir_for_tuxeye, plyr->viewdir_for_tuxeye);
            make_rotation_about_vector_matrix( mat1, right, jump_from_time(plyr->control.flip_factor) * 360 );
            make_rotation_about_vector_matrix( mat, plyr->viewdir_for_tuxeye, jump_from_time(plyr->control.barrel_roll_factor)  * 360 );
            multiply_matrices(mat, mat1, mat);
            view_dir = transform_vector(mat, plyr->viewdir_for_tuxeye);
            up_dir = transform_vector(mat, plyr->updir_for_tuxeye);
        }
        else {
            view_dir = plyr->direction;
            view_dir.y += 0.1;

            view_dir.x = (plyr->view.dir.x * f +  view_dir.x) / (f + 1);
            view_dir.y = (plyr->view.dir.y * f + view_dir.y) / (f + 1);
            view_dir.z = (plyr->view.dir.z * f + view_dir.z) / (f + 1);
            plyr->viewdir_for_tuxeye = view_dir;

            up_dir = plyr->plane_nml;
            up_dir.x = (plyr->view.up.x * f +  up_dir.x) / (f + 1);
            up_dir.y = (plyr->view.up.y * f + up_dir.y) / (f + 1);
            up_dir.z = (plyr->view.up.z * f + up_dir.z) / (f + 1);
            plyr->updir_for_tuxeye = up_dir;
        }
        break;
    }
    case BEHIND:
    {
	/* Camera-on-a-string mode */

	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );

	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	y_vec = make_vector( 0.0, 1.0, 0.0 );
	mz_vec = make_vector( 0.0, 0.0, -1.0 );
	vel_proj = project_into_plane( y_vec, vel_dir );

	normalize_vector( &vel_proj );

	/* Rotate view_vec so that it places the camera behind player */
	rot_quat = make_rotation_quaternion( mz_vec, vel_proj );

	view_vec = rotate_vector( rot_quat, view_vec );


	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );

	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
        } 

	/* Interpolate view point */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for (i=0; i<2; i++) {
		view_pt = 
		    interpolate_view_pos( plyr->pos, plyr->pos, 
					  MAX_CAMERA_PITCH, plyr->view.pos, 
					  view_pt, CAMERA_DISTANCE, dt,
					  BEHIND_ORBIT_TIME_CONSTANT * 
					  time_constant_mult );
	    }
	}

	/* Make sure interpolated view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        } 

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );
	
	axis = cross_product( y_vec, view_vec );
	normalize_vector( &axis );
	
	make_rotation_about_vector_matrix( rot_mat, axis,
					   PLAYER_ANGLE_IN_CAMERA );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

	/* Interpolate orientation of camera */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for (i=0; i<2; i++) {
		interpolate_view_frame( plyr->view.up, plyr->view.dir,
					&up_dir, &view_dir, dt,
					BEHIND_ORIENT_TIME_CONSTANT );
		up_dir = make_vector( 0.0, 1.0, 0.0 );
	    }
	}

        break;
    }

    case FOLLOW: 
    {
	/* Camera follows player (above and behind) */

	up_dir = make_vector( 0, 1, 0 );

	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE +
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	y_vec = make_vector( 0.0, 1.0, 0.0 );
	mz_vec = make_vector( 0.0, 0.0, -1.0 );
	vel_proj = project_into_plane( y_vec, vel_dir );

	normalize_vector( &vel_proj );

	/* Rotate view_vec so that it places the camera behind player */
	rot_quat = make_rotation_quaternion( mz_vec, vel_proj );

	view_vec = rotate_vector( rot_quat, view_vec );


	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );


	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
	}

	/* Interpolate view point */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for ( i=0; i<2; i++ ) {
		view_pt = 
		    interpolate_view_pos( plyr->view.plyr_pos, plyr->pos, 
					  MAX_CAMERA_PITCH, plyr->view.pos, 
					  view_pt, CAMERA_DISTANCE, dt,
					  FOLLOW_ORBIT_TIME_CONSTANT *
					  time_constant_mult );
	    }
	}

	/* Make sure interpolate view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        } 

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );
	
	axis = cross_product( y_vec, view_vec );
	normalize_vector( &axis );
	
	make_rotation_about_vector_matrix( rot_mat, axis,
					   PLAYER_ANGLE_IN_CAMERA );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

	/* Interpolate orientation of camera */
	if ( plyr->view.initialized ) {
	    /* Interpolate twice to get a second-order filter */
	    int i;
	    for ( i=0; i<2; i++ ) {
		interpolate_view_frame( plyr->view.up, plyr->view.dir,
					&up_dir, &view_dir, dt,
					FOLLOW_ORIENT_TIME_CONSTANT );
		up_dir = make_vector( 0.0, 1.0, 0.0 );
	    }
	}

        break;
    }

    case ABOVE:
    {
	/* Camera always uphill of player */

	up_dir = make_vector( 0, 1, 0 );


	/* Construct vector from player to camera */
	view_vec = make_vector( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+ 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
	view_vec = scale_vector( CAMERA_DISTANCE, view_vec );

	
	/* Construct view point */
	view_pt = move_point( plyr->pos, view_vec );


	/* Make sure view point is above terrain */
        ycoord = find_y_coord( view_pt.x, view_pt.z );

        if ( view_pt.y < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y = ycoord + MIN_CAMERA_HEIGHT;
	}

	/* Construct view direction */
	view_vec = subtract_points( view_pt, plyr->pos );

	make_rotation_matrix( rot_mat, PLAYER_ANGLE_IN_CAMERA, 'x' );
	view_dir = scale_vector( -1.0, 
				 transform_vector( rot_mat, view_vec ) );

        break;
    }

    default:
	code_not_reached();
    } 

    /* Create view matrix */
    plyr->view.pos = view_pt;
    plyr->view.dir = view_dir;
    plyr->view.up = up_dir;
    plyr->view.plyr_pos = plyr->pos;
    plyr->view.initialized = True;

    setup_view_matrix( plyr );
} 
Пример #2
0
/*! 
  Updates camera and sets the view matrix
  \pre     plyr != NULL, plyr has been initialized with position & 
           velocity info., plyr->view.mode has been set
  \arg \c  plyr pointer to player data
  \arg \c  dt time step size  

  \return  none
  \author  jfpatry
  \date    Created:  2000-08-26
  \date    Modified: 2000-08-26
*/
void
update_view(Player& plyr, const float dt)
{
    ppogl::Vec3d view_pt;
    ppogl::Vec3d view_dir;
	
    ppogl::Vec3d vel_cpy = plyr.vel;
    const float speed = vel_cpy.normalize();
	const float time_constant_mult = 1.0 / 	MIN( 1.0, 
		MAX( 0.0,  ( speed - NO_INTERPOLATION_SPEED ) /  ( BASELINE_INTERPOLATION_SPEED - NO_INTERPOLATION_SPEED )));

    ppogl::Vec3d up_dir = ppogl::Vec3d( 0, 1, 0 );

    ppogl::Vec3d vel_dir = plyr.vel;
    vel_dir.normalize();

    const float course_angle = Course::getAngle();

    switch(plyr.view.mode){

    case BEHIND:
    {
		/* Camera-on-a-string mode */

		/* Construct vector from player to camera */
		ppogl::Vec3d view_vec(0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );

		view_vec = CAMERA_DISTANCE*view_vec;

		ppogl::Vec3d y_vec(0.0, 1.0, 0.0);
		ppogl::Vec3d mz_vec(0.0, 0.0, -1.0);
		ppogl::Vec3d vel_proj = projectIntoPlane( y_vec, vel_dir );

		vel_proj.normalize();

		/* Rotate view_vec so that it places the camera behind player */
		pp::Quat rot_quat(mz_vec, vel_proj);

		view_vec = rot_quat.rotate(view_vec);


		/* Construct view point */
		view_pt = plyr.pos - view_vec;

		/* Make sure view point is above terrain */
        float ycoord = find_y_coord( view_pt );

        if ( view_pt.y() < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y() = ycoord + MIN_CAMERA_HEIGHT;
        } 

		/* Interpolate view point */
		if ( plyr.view.initialized ) {
	    	/* Interpolate twice to get a second-order filter */
	    	for (int i=0; i<2; i++) {
				view_pt = 
		    		interpolate_view_pos( plyr.pos, plyr.pos, 
						MAX_CAMERA_PITCH, plyr.view.pos, 
						view_pt, CAMERA_DISTANCE, dt,
						BEHIND_ORBIT_TIME_CONSTANT * 
						time_constant_mult );
	    	}
		}

		/* Make sure interpolated view point is above terrain */
        ycoord = find_y_coord( view_pt );

        if ( view_pt.y() < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            view_pt.y() = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        } 

		/* Construct view direction */
		view_vec = view_pt - plyr.pos;
	
		ppogl::Vec3d axis = y_vec^view_vec;
		axis.normalize();
	
		pp::Matrix rot_mat;
		rot_mat.makeRotationAboutVector( axis,
					   PLAYER_ANGLE_IN_CAMERA );
		view_dir = -1.0*rot_mat.transformVector( view_vec );

		/* Interpolate orientation of camera */
		if ( plyr.view.initialized ) {
			/* Interpolate twice to get a second-order filter */
			for (int i=0; i<2; i++) {
				interpolate_view_frame( plyr.view.up, plyr.view.dir,
					up_dir, view_dir, dt,
					BEHIND_ORIENT_TIME_CONSTANT );
			up_dir = ppogl::Vec3d( 0.0, 1.0, 0.0 );
	    	}
		}
        break;
    }

    case FOLLOW: 
    {
		/* Camera follows player (above and behind) */

		up_dir = ppogl::Vec3d( 0, 1, 0 );

		/* Construct vector from player to camera */
		ppogl::Vec3d view_vec( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE +
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle -
				    CAMERA_ANGLE_ABOVE_SLOPE + 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
		view_vec = CAMERA_DISTANCE*view_vec;

		ppogl::Vec3d y_vec(0.0, 1.0, 0.0);
		ppogl::Vec3d mz_vec(0.0, 0.0, -1.0);
		ppogl::Vec3d vel_proj = projectIntoPlane( y_vec, vel_dir );

		vel_proj.normalize();

		/* Rotate view_vec so that it places the camera behind player */
		pp::Quat rot_quat(mz_vec, vel_proj);

		view_vec = rot_quat.rotate( view_vec );


		/* Construct view point */
		view_pt = plyr.pos + view_vec;


		/* Make sure view point is above terrain */
        float ycoord = find_y_coord( view_pt );

        if ( view_pt.y() < ycoord + MIN_CAMERA_HEIGHT ) {
            view_pt.y() = ycoord + MIN_CAMERA_HEIGHT;
		}

		/* Interpolate view point */
		if ( plyr.view.initialized ) {
		    /* Interpolate twice to get a second-order filter */
	        for (int i=0; i<2; i++ ) {
			view_pt = 
		    	interpolate_view_pos( plyr.view.plyr_pos, plyr.pos, 
					  MAX_CAMERA_PITCH, plyr.view.pos, 
					  view_pt, CAMERA_DISTANCE, dt,
					  FOLLOW_ORBIT_TIME_CONSTANT *
					  time_constant_mult );
	    	}
		}

		/* Make sure interpolate view point is above terrain */
        	ycoord = find_y_coord( view_pt );

        	if ( view_pt.y() < ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT ) {
            	view_pt.y() = ycoord + ABSOLUTE_MIN_CAMERA_HEIGHT;
        	} 

		/* Construct view direction */
		view_vec = view_pt - plyr.pos;
	
		ppogl::Vec3d axis = y_vec^view_vec;
		axis.normalize();
		
		pp::Matrix rot_mat;
		rot_mat.makeRotationAboutVector( axis, PLAYER_ANGLE_IN_CAMERA );
		view_dir = -1.0*rot_mat.transformVector( view_vec );

		/* Interpolate orientation of camera */
		if ( plyr.view.initialized ) {
	    	/* Interpolate twice to get a second-order filter */
	    	for (int i=0; i<2; i++ ) {
			interpolate_view_frame( plyr.view.up, plyr.view.dir,
					up_dir, view_dir, dt,
					FOLLOW_ORIENT_TIME_CONSTANT );
			up_dir = ppogl::Vec3d( 0.0, 1.0, 0.0 );
	    	}
		}
        break;
    }

    case ABOVE:
    {
		/* Camera always uphill of player */

		up_dir = ppogl::Vec3d( 0, 1, 0 );


		/* Construct vector from player to camera */
		ppogl::Vec3d view_vec( 0, 
				sin( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+
				    PLAYER_ANGLE_IN_CAMERA ) ),
				cos( ANGLES_TO_RADIANS( 
				    course_angle - 
				    CAMERA_ANGLE_ABOVE_SLOPE+ 
				    PLAYER_ANGLE_IN_CAMERA ) ) );
		view_vec = CAMERA_DISTANCE*view_vec;

	
		/* Construct view point */
		view_pt = plyr.pos + view_vec;


		/* Make sure view point is above terrain */
        float ycoord = find_y_coord( view_pt );

        if ( view_pt.y() < ycoord + MIN_CAMERA_HEIGHT ) {
			view_pt.y() = ycoord + MIN_CAMERA_HEIGHT;
		}

		/* Construct view direction */
		view_vec = view_pt - plyr.pos;
		pp::Matrix rot_mat;
		rot_mat.makeRotation( PLAYER_ANGLE_IN_CAMERA, ppogl::AXIS_X );
		view_dir = -1.0*rot_mat.transformVector( view_vec );

        break;
    }

    default:
		PP_NOT_REACHED();
    } 

    /* Create view matrix */
    plyr.view.pos = view_pt;
    plyr.view.dir = view_dir;
    plyr.view.up = up_dir;
    plyr.view.plyr_pos = plyr.pos;
    plyr.view.initialized = true;
}