Back to index

extremetuxracer  0.5beta
Defines | Functions | Variables
view.cpp File Reference
#include "view.h"
#include "phys_sim.h"
#include "model_hndl.h"
#include "hier.h"
#include "stuff.h"
#include "ppgltk/alg/defs.h"

Go to the source code of this file.

Defines

#define MIN_CAMERA_HEIGHT   1.5
#define ABSOLUTE_MIN_CAMERA_HEIGHT   0.3
#define CAMERA_DISTANCE   4.0
#define CAMERA_ANGLE_ABOVE_SLOPE   10
#define PLAYER_ANGLE_IN_CAMERA   20
#define MAX_CAMERA_PITCH   40
#define BEHIND_ORBIT_TIME_CONSTANT   0.06
#define BEHIND_ORIENT_TIME_CONSTANT   0.06
#define FOLLOW_ORBIT_TIME_CONSTANT   0.06
#define FOLLOW_ORIENT_TIME_CONSTANT   0.06
#define MAX_INTERPOLATION_VALUE   0.3
#define BASELINE_INTERPOLATION_SPEED   4.5
#define NO_INTERPOLATION_SPEED   2.0

Functions

void set_view_mode (Player &plyr, view_mode_t mode)
view_mode_t get_view_mode (Player &plyr)
void traverse_dag_for_view_point (scene_node_t *node, pp::Matrix trans)
pp::Vec3d get_tux_view_pt (Player &plyr)
void set_tux_eye (tux_eye_t which_eye, pp::Vec3d pt)
pp::Vec3d interpolate_view_pos (pp::Vec3d plyr_pos1, pp::Vec3d plyr_pos2, double max_vec_angle, pp::Vec3d pos1, pp::Vec3d pos2, double dist, double dt, double time_constant)
 Interpolates between camera positions.
void interpolate_view_frame (pp::Vec3d up1, pp::Vec3d dir1, pp::Vec3d *p_up2, pp::Vec3d *p_dir2, double dt, double time_constant)
 Interpolates between camera orientations.
void setup_view_matrix (Player &plyr)
void update_view (Player &plyr, double dt)
 Updates camera and sets the view matrix.

Variables

static pp::Vec3d tux_eye_pts [2]
static pp::Vec3d tux_view_pt

Define Documentation

#define ABSOLUTE_MIN_CAMERA_HEIGHT   0.3

Definition at line 35 of file view.cpp.

#define BASELINE_INTERPOLATION_SPEED   4.5

Definition at line 68 of file view.cpp.

#define BEHIND_ORBIT_TIME_CONSTANT   0.06

Definition at line 50 of file view.cpp.

#define BEHIND_ORIENT_TIME_CONSTANT   0.06

Definition at line 54 of file view.cpp.

#define CAMERA_ANGLE_ABOVE_SLOPE   10

Definition at line 41 of file view.cpp.

#define CAMERA_DISTANCE   4.0

Definition at line 38 of file view.cpp.

#define FOLLOW_ORBIT_TIME_CONSTANT   0.06

Definition at line 57 of file view.cpp.

#define FOLLOW_ORIENT_TIME_CONSTANT   0.06

Definition at line 61 of file view.cpp.

#define MAX_CAMERA_PITCH   40

Definition at line 47 of file view.cpp.

#define MAX_INTERPOLATION_VALUE   0.3

Definition at line 65 of file view.cpp.

#define MIN_CAMERA_HEIGHT   1.5

Definition at line 32 of file view.cpp.

#define NO_INTERPOLATION_SPEED   2.0

Definition at line 71 of file view.cpp.

#define PLAYER_ANGLE_IN_CAMERA   20

Definition at line 44 of file view.cpp.


Function Documentation

Definition at line 108 of file view.cpp.

{ 
    pp::Matrix trans;
    char *tux_root_node_name;
    scene_node_t *tux_root_node;

    trans.makeIdentity();

    tux_root_node_name = ModelHndl->get_tux_root_node();

    if ( get_scene_node( tux_root_node_name, &tux_root_node ) != TCL_OK ) {
       check_assertion(0, "couldn't load tux's root node" );
    } 

    traverse_dag_for_view_point( tux_root_node, trans );

    tux_view_pt = tux_view_pt+ (0.2*plyr.plane_nml);

    return tux_view_pt; 
}

Here is the call graph for this function:

Definition at line 82 of file view.cpp.

{
    return plyr.view.mode;
} 
void interpolate_view_frame ( pp::Vec3d  up1,
pp::Vec3d  dir1,
pp::Vec3d p_up2,
pp::Vec3d p_dir2,
double  dt,
double  time_constant 
)

Interpolates between camera orientations.

Precondition:
p_up2, p_dir2 != NULL; *p_up2 is the target up vector; *p_dir2 is the target view direction
  • up1 original up vector
  • dir1 original view direction
  • p_up2 pointer to target up vector; is overwritten with interpolated up vector
  • p_dir2 pointer to target view direction; is overwritten with interpolated view direction
  • dt time step
  • time_constant interpolation time constant
Returns:
none
Author:
jfpatry
Date:
Created: 2000-08-26
Modified: 2000-08-26

Definition at line 222 of file view.cpp.

{
    pp::Quat q1, q2;
    double alpha;
    pp::Vec3d x1, y1, z1;
    pp::Vec3d x2, y2, z2;
    pp::Matrix cob_mat1, inv_cob_mat1;
    pp::Matrix inv_cob_mat2;

    /* Now interpolate between camera orientations */
    z1 = -1.0*dir1;
    z1.normalize();

    y1 = projectIntoPlane( z1, up1 );
    y1.normalize();

    x1 = y1^z1;

    pp::Matrix::makeChangeOfBasisMatrix( cob_mat1, inv_cob_mat1,
                             x1, y1, z1 );

    q1 = pp::Quat( cob_mat1 );

    z2 = -1.0*(*p_dir2);
    z2.normalize();

    y2 = projectIntoPlane( z2, *p_up2 );
    y2.normalize();

    x2 = y2^z2;
       {
              pp::Matrix cob_mat2;
       pp::Matrix::makeChangeOfBasisMatrix( cob_mat2, inv_cob_mat2,
                             x2, y2, z2 );

       q2 = pp::Quat( cob_mat2 );
       }
    alpha = MIN( MAX_INTERPOLATION_VALUE, 
               1.0 - exp( -dt / time_constant ) );

    q2 = pp::Quat::interpolate( q1, q2, alpha );

    pp::Matrix cob_mat2( q2 );

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

    p_dir2->x = -cob_mat2.data[2][0];
    p_dir2->y = -cob_mat2.data[2][1];
    p_dir2->z = -cob_mat2.data[2][2];
}

Here is the call graph for this function:

Here is the caller graph for this function:

pp::Vec3d interpolate_view_pos ( pp::Vec3d  plyr_pos1,
pp::Vec3d  plyr_pos2,
double  max_vec_angle,
pp::Vec3d  pos1,
pp::Vec3d  pos2,
double  dist,
double  dt,
double  time_constant 
)

Interpolates between camera positions.

  • plyr_pos1 pos1 is relative to this position
  • plyr_pos2 pos2 is relative to this position
  • max_vec_angle Maximum downward pitch of vector from camera to player
  • pos1 original camera position
  • pos2 target camera position
  • dist distance of interpolated camera position from player
  • dt time step size (s)
  • time_constant time constant to use in interpolation (s)
Returns:
Interpolated camera position
Author:
jfpatry
Date:
Created: 2000-08-26
Modified: 2000-08-26

Definition at line 155 of file view.cpp.

{
    static pp::Vec3d y_vec(0.0, 1.0, 0.0);

    pp::Quat q1, q2;
    pp::Vec3d vec1, vec2;
    double alpha;
    double theta;
    pp::Matrix rot_mat;
    pp::Vec3d axis;

    vec1 = pos1 - plyr_pos1;
    vec2 = pos2 - plyr_pos2;

    vec1.normalize();
    vec2.normalize();

    q1 = pp::Quat( y_vec, vec1 );
    q2 = pp::Quat( y_vec, vec2 );

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

    q2 = pp::Quat::interpolate( q1, q2, alpha );

    vec2 = q2.rotate( y_vec );

    /* Constrain angle with x-z plane */
    theta = RADIANS_TO_ANGLES( M_PI/2 - acos(vec2*y_vec) );

    if ( theta > max_vec_angle )
    {
       axis = y_vec^vec2;
       axis.normalize();

       rot_mat.makeRotationAboutVector( axis, 
                                      theta-max_vec_angle );
       vec2 = rot_mat.transformVector( vec2 );
    }

    return plyr_pos2+dist*vec2;

}

Here is the call graph for this function:

Here is the caller graph for this function:

void set_tux_eye ( tux_eye_t  which_eye,
pp::Vec3d  pt 
)

Definition at line 129 of file view.cpp.

{
    tux_eye_pts[ which_eye ] = pt;

    tux_view_pt.x = ( tux_eye_pts[0].x + tux_eye_pts[1].x ) / 2.0; 
    tux_view_pt.y = ( tux_eye_pts[0].y + tux_eye_pts[1].y ) / 2.0; 
    tux_view_pt.z = ( tux_eye_pts[0].z + tux_eye_pts[1].z ) / 2.0; 
}

Here is the caller graph for this function:

void set_view_mode ( Player plyr,
view_mode_t  mode 
)

Definition at line 76 of file view.cpp.

{
    plyr.view.mode = mode;
    print_debug( DEBUG_VIEW, "View mode: %d", plyr.view.mode );
} 

Here is the call graph for this function:

Here is the caller graph for this function:

void setup_view_matrix ( Player plyr)

Definition at line 277 of file view.cpp.

{
    pp::Vec3d view_x, view_y, view_z;
    pp::Matrix view_mat;
    pp::Vec3d viewpt_in_view_frame;

    view_z = -1*plyr.view.dir;
    view_x = plyr.view.up^view_z;
    view_y = view_z^view_x;
    view_z.normalize();
    view_x.normalize();
    view_y.normalize();

    plyr.view.inv_view_mat.makeIdentity();

    plyr.view.inv_view_mat.data[0][0] = view_x.x;
    plyr.view.inv_view_mat.data[0][1] = view_x.y;
    plyr.view.inv_view_mat.data[0][2] = view_x.z;

    plyr.view.inv_view_mat.data[1][0] = view_y.x;
    plyr.view.inv_view_mat.data[1][1] = view_y.y;
    plyr.view.inv_view_mat.data[1][2] = view_y.z;

    plyr.view.inv_view_mat.data[2][0] = view_z.x;
    plyr.view.inv_view_mat.data[2][1] = view_z.y;
    plyr.view.inv_view_mat.data[2][2] = view_z.z;

    plyr.view.inv_view_mat.data[3][0] = plyr.view.pos.x;
    plyr.view.inv_view_mat.data[3][1] = plyr.view.pos.y;
    plyr.view.inv_view_mat.data[3][2] = plyr.view.pos.z;
    plyr.view.inv_view_mat.data[3][3] = 1;
    
    view_mat.transpose(plyr.view.inv_view_mat);

    view_mat.data[0][3] = 0;
    view_mat.data[1][3] = 0;
    view_mat.data[2][3] = 0;
    
    viewpt_in_view_frame = view_mat.transformPoint( plyr.view.pos );
    
    view_mat.data[3][0] = -viewpt_in_view_frame.x;
    view_mat.data[3][1] = -viewpt_in_view_frame.y;
    view_mat.data[3][2] = -viewpt_in_view_frame.z;
    
    glLoadIdentity();
    glMultMatrixd( (double *) view_mat.data );
}

Here is the call graph for this function:

Here is the caller graph for this function:

void traverse_dag_for_view_point ( scene_node_t node,
pp::Matrix  trans 
)

Definition at line 87 of file view.cpp.

{
    pp::Matrix new_trans;
    scene_node_t *child;

    check_assertion( node != NULL, "node is NULL" );

    new_trans=trans*node->trans;

    if ( node->eye == true ) {
       set_tux_eye( node->which_eye,
                   new_trans.transformPoint( pp::Vec3d( 0., 0., 0. ) ) );
    }

    child = node->child;
    while (child != NULL) {
        traverse_dag_for_view_point( child, new_trans );
        child = child->next;
    } 
}

Here is the call graph for this function:

Here is the caller graph for this function:

void update_view ( Player plyr,
double  dt 
)

Updates camera and sets the view matrix.

Precondition:
plyr != NULL, plyr has been initialized with position & velocity info., plyr->view.mode has been set
  • plyr pointer to player data
  • dt time step size
Returns:
none
Author:
jfpatry
Date:
Created: 2000-08-26
Modified: 2000-08-26

Definition at line 337 of file view.cpp.

{
    pp::Vec3d view_pt;
    pp::Vec3d view_dir, up_dir, vel_dir, view_vec;
    double ycoord;
    double course_angle;
    pp::Vec3d axis;
    pp::Matrix rot_mat;
    pp::Vec3d y_vec;
    pp::Vec3d mz_vec;
    pp::Vec3d vel_proj;
    pp::Quat rot_quat;
    double speed;
    pp::Vec3d vel_cpy;
    double time_constant_mult;

    vel_cpy = plyr.vel;
    speed = vel_cpy.normalize();

    time_constant_mult = 1.0 /
       MIN( 1.0, 
            MAX( 0.0, 
                ( speed - NO_INTERPOLATION_SPEED ) /
                ( BASELINE_INTERPOLATION_SPEED - NO_INTERPOLATION_SPEED )));

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

    vel_dir = plyr.vel;
    vel_dir.normalize();

    course_angle = get_course_angle();

    switch( plyr.view.mode ) {

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

       /* Construct vector from player to camera */
       view_vec = pp::Vec3d( 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;

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

       vel_proj.normalize();

       /* Rotate view_vec so that it places the camera behind player */
       rot_quat = pp::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 */
        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 = view_pt - plyr.pos;
       
       axis = y_vec^view_vec;
       axis.normalize();
       
       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 */
           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 = pp::Vec3d( 0.0, 1.0, 0.0 );
           }
       }

        break;
    }

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

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

       /* Construct vector from player to camera */
       view_vec = pp::Vec3d( 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;

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

       vel_proj.normalize();

       /* Rotate view_vec so that it places the camera behind player */
       rot_quat = pp::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 */
        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 = view_pt - plyr.pos;
       
       axis = y_vec^view_vec;
       axis.normalize();
       
       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 */
           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 = pp::Vec3d( 0.0, 1.0, 0.0 );
           }
       }

        break;
    }

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

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


       /* Construct vector from player to camera */
       view_vec = pp::Vec3d( 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 */
        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 = view_pt - plyr.pos;

       rot_mat.makeRotation( PLAYER_ANGLE_IN_CAMERA, 'x' );
       view_dir = -1.0*rot_mat.transformVector( 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 );
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

pp::Vec3d tux_eye_pts[2] [static]

Definition at line 73 of file view.cpp.

Definition at line 74 of file view.cpp.