Beispiel #1
0
/*! 
  Interpolates between camera orientations
  \pre     p_up2, p_dir2 != NULL; *p_up2 is the target up vector; 
	   *p_dir2 is the target view direction
  \arg \c  up1 original up vector
  \arg \c  dir1 original view direction
  \arg \c  p_up2 pointer to target up vector; is overwritten with 
           interpolated up vector
  \arg \c  p_dir2 pointer to target view direction; is overwritten with 
           interpolated view direction
  \arg \c  dt time step
  \arg \c  time_constant interpolation time constant

  \return  none
  \author  jfpatry
  \date    Created:  2000-08-26
  \date    Modified: 2000-08-26
*/
void interpolate_view_frame( vector_t up1, vector_t dir1,
			     vector_t *p_up2, vector_t *p_dir2,
			     scalar_t dt, scalar_t time_constant )
{
    quaternion_t q1, q2;
    scalar_t alpha;
    vector_t x1, y1, z1;
    vector_t x2, y2, z2;
    matrixgl_t cob_mat1, inv_cob_mat1;
    matrixgl_t cob_mat2, inv_cob_mat2;

    /* Now interpolate between camera orientations */
    z1 = scale_vector( -1.0, dir1 );
    normalize_vector( &z1 );

    y1 = project_into_plane( z1, up1 );
    normalize_vector( &y1 );

    x1 = cross_product( y1, z1 );

    make_change_of_basis_matrix( cob_mat1, inv_cob_mat1,
				 x1, y1, z1 );

    q1 = make_quaternion_from_matrix( cob_mat1 );

    z2 = scale_vector( -1.0, *p_dir2 );
    normalize_vector( &z2 );

    y2 = project_into_plane( z2, *p_up2 );
    normalize_vector( &y2 );

    x2 = cross_product( y2, z2 );

    make_change_of_basis_matrix( cob_mat2, inv_cob_mat2,
				 x2, y2, z2 );

    q2 = make_quaternion_from_matrix( cob_mat2 );

    alpha = min( MAX_INTERPOLATION_VALUE, 
		 1.0 - exp( -dt / time_constant ) );

    q2 = interpolate_quaternions( q1, q2, alpha );

    make_matrix_from_quaternion( cob_mat2, q2 );

    p_up2->x = cob_mat2[1][0];
    p_up2->y = cob_mat2[1][1];
    p_up2->z = cob_mat2[1][2];

    p_dir2->x = -cob_mat2[2][0];
    p_dir2->y = -cob_mat2[2][1];
    p_dir2->z = -cob_mat2[2][2];
}
Beispiel #2
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 );
} 
Beispiel #3
0
void draw_billboard( player_data_t *plyr, 
		     point_t center_pt, scalar_t width, scalar_t height, 
		     bool_t use_world_y_axis, 
		     point2d_t min_tex_coord, point2d_t max_tex_coord )
{
    point_t pt;
    vector_t x_vec;
    vector_t y_vec;
    vector_t z_vec;

    x_vec.x = plyr->view.inv_view_mat[0][0];
    x_vec.y = plyr->view.inv_view_mat[0][1];
    x_vec.z = plyr->view.inv_view_mat[0][2];

    if ( use_world_y_axis ) {
	y_vec = make_vector( 0, 1, 0 );
	x_vec = project_into_plane( y_vec, x_vec );
	normalize_vector( &x_vec );
	z_vec = cross_product( x_vec, y_vec );
    } else {
	y_vec.x = plyr->view.inv_view_mat[1][0];
	y_vec.y = plyr->view.inv_view_mat[1][1];
	y_vec.z = plyr->view.inv_view_mat[1][2];
	z_vec.x = plyr->view.inv_view_mat[2][0];
	z_vec.y = plyr->view.inv_view_mat[2][1];
	z_vec.z = plyr->view.inv_view_mat[2][2];
    }

#ifdef __APPLE__DISABLED__
    glNormal3f( z_vec.x, z_vec.y, z_vec.z );

    pt = move_point( center_pt, scale_vector( -width/2.0, x_vec ) );
    pt = move_point( pt, scale_vector( -height/2.0, y_vec ) );
    point_t pt2 = move_point( pt, scale_vector( width, x_vec ) );
    point_t pt3 = move_point( pt2, scale_vector( height, y_vec ) );
    point_t pt4 = move_point( pt3, scale_vector( -width, x_vec ) );

    const GLfloat vertices2 []=
    {
       pt.x, pt.y, pt.z,
       pt2.x, pt2.y, pt2.z,
       pt3.x, pt3.y, pt3.z,
       pt4.x, pt4.y, pt4.z
    };

    const GLshort texCoords2 []=
    {
       min_tex_coord.x, min_tex_coord.y,
       max_tex_coord.x, min_tex_coord.y,
       max_tex_coord.x, max_tex_coord.y,
       min_tex_coord.x, max_tex_coord.y,
    };

    glEnableClientState (GL_VERTEX_ARRAY);
    glVertexPointer (3, GL_FLOAT , 0, vertices2);	
    glTexCoordPointer(2, GL_SHORT, 0, texCoords2);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
#else
    glBegin( GL_QUADS );
    {
	pt = move_point( center_pt, scale_vector( -width/2.0, x_vec ) );
	pt = move_point( pt, scale_vector( -height/2.0, y_vec ) );
	glNormal3f( z_vec.x, z_vec.y, z_vec.z );
	glTexCoord2f( min_tex_coord.x, min_tex_coord.y );
	glVertex3f( pt.x, pt.y, pt.z );

	pt = move_point( pt, scale_vector( width, x_vec ) );
	glTexCoord2f( max_tex_coord.x, min_tex_coord.y );
	glVertex3f( pt.x, pt.y, pt.z );

	pt = move_point( pt, scale_vector( height, y_vec ) );
	glTexCoord2f( max_tex_coord.x, max_tex_coord.y );
	glVertex3f( pt.x, pt.y, pt.z );

	pt = move_point( pt, scale_vector( -width, x_vec ) );
	glTexCoord2f( min_tex_coord.x, max_tex_coord.y );
	glVertex3f( pt.x, pt.y, pt.z );
    }
    glEnd();
#endif
}