/*! Draws a fog plane at the far clipping plane to mask out clipping of terrain. \return none \author jfpatry \date Created: 2000-08-31 \date Modified: 2000-08-31 */ void draw_fog_plane() { plane_t left_edge_plane, right_edge_plane; plane_t left_clip_plane, right_clip_plane; plane_t far_clip_plane; plane_t bottom_clip_plane; plane_t bottom_plane, top_plane; scalar_t course_width, course_length; scalar_t course_angle, slope; point_t left_pt, right_pt, pt; point_t top_left_pt, top_right_pt; point_t bottom_left_pt, bottom_right_pt; vector_t left_vec, right_vec; scalar_t height; GLfloat *fog_colour; if ( is_fog_on() == False ) { return; } set_gl_options( FOG_PLANE ); get_course_dimensions( &course_width, &course_length ); course_angle = get_course_angle(); slope = tan( ANGLES_TO_RADIANS( course_angle ) ); left_edge_plane = make_plane( 1.0, 0.0, 0.0, 0.0 ); right_edge_plane = make_plane( -1.0, 0.0, 0.0, course_width ); far_clip_plane = get_far_clip_plane(); left_clip_plane = get_left_clip_plane(); right_clip_plane = get_right_clip_plane(); bottom_clip_plane = get_bottom_clip_plane(); /* Find the bottom plane */ bottom_plane.nml = make_vector( 0.0, 1, -slope ); height = get_terrain_base_height( 0 ); /* Unoptimized version pt = make_point( 0, height, 0 ); bottom_plane.d = -( pt.x * bottom_plane.nml.x + pt.y * bottom_plane.nml.y + pt.z * bottom_plane.nml.z ); */ bottom_plane.d = -height * bottom_plane.nml.y; /* Find the top plane */ top_plane.nml = bottom_plane.nml; height = get_terrain_max_height( 0 ); top_plane.d = -height * top_plane.nml.y; if(get_player_data(local_player())->view.mode == TUXEYE) { bottom_clip_plane.nml = make_vector( 0.0, 1, -slope ); height = get_terrain_base_height( 0 ) - 40; bottom_clip_plane.d = -height * bottom_clip_plane.nml.y; } /* Now find the bottom left and right points of the fog plane */ if ( !intersect_planes( bottom_plane, far_clip_plane, left_clip_plane, &left_pt ) ) return; if ( !intersect_planes( bottom_plane, far_clip_plane, right_clip_plane, &right_pt ) ) return; if ( !intersect_planes( top_plane, far_clip_plane, left_clip_plane, &top_left_pt ) ) return; if ( !intersect_planes( top_plane, far_clip_plane, right_clip_plane, &top_right_pt ) ) return; if ( !intersect_planes( bottom_clip_plane, far_clip_plane, left_clip_plane, &bottom_left_pt ) ) return; if ( !intersect_planes( bottom_clip_plane, far_clip_plane, right_clip_plane, &bottom_right_pt ) ) return; left_vec = subtract_points( top_left_pt, left_pt ); right_vec = subtract_points( top_right_pt, right_pt ); /* Now draw the fog plane */ set_gl_options( FOG_PLANE ); fog_colour = get_fog_colour(); glColor4fv( fog_colour ); #ifdef __APPLE__DISABLED__ #undef glEnableClientState #undef glDisableClientState #undef glVertexPointer #undef glColorPointer #undef glDrawArrays point_t pt1,pt2,pt3,pt4; pt1 = move_point( top_left_pt, left_vec ); pt2 = move_point( top_right_pt, right_vec ); pt3 = move_point( top_left_pt, scale_vector( 3.0, left_vec ) ); pt4 = move_point( top_right_pt, scale_vector( 3.0, right_vec ) ); const GLfloat verticesFog []= { bottom_left_pt.x, bottom_left_pt.y, bottom_left_pt.z, bottom_right_pt.x, bottom_right_pt.y, bottom_right_pt.z, left_pt.x, left_pt.y, left_pt.z, right_pt.x, right_pt.y, right_pt.z, top_left_pt.x, top_left_pt.y, top_left_pt.z, top_right_pt.x, top_right_pt.y, top_right_pt.z, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y, pt3.z, pt4.x, pt4.y, pt4.z }; const GLfloat colorsFog []= { fog_colour[0], fog_colour[1], fog_colour[2], fog_colour[3], fog_colour[0], fog_colour[1], fog_colour[2], fog_colour[3], fog_colour[0], fog_colour[1], fog_colour[2], fog_colour[3], fog_colour[0], fog_colour[1], fog_colour[2], fog_colour[3], fog_colour[0], fog_colour[1], fog_colour[2], 0.9 , fog_colour[0], fog_colour[1], fog_colour[2], 0.9 , fog_colour[0], fog_colour[1], fog_colour[2], 0.3 , fog_colour[0], fog_colour[1], fog_colour[2], 0.3 , fog_colour[0], fog_colour[1], fog_colour[2], 0.0 , fog_colour[0], fog_colour[1], fog_colour[2], 0.0 , }; glEnableClientState (GL_VERTEX_ARRAY); // glEnableClientState (GL_COLOR_ARRAY); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer (3, GL_FLOAT , 0, verticesFog); glColorPointer(4, GL_FLOAT, 0, colorsFog); glDrawArrays(GL_TRIANGLE_STRIP, 0, 10); //glDisableClientState(GL_COLOR_ARRAY_POINTER); #else glBegin( GL_QUAD_STRIP ); glVertex3f( bottom_left_pt.x, bottom_left_pt.y, bottom_left_pt.z ); glVertex3f( bottom_right_pt.x, bottom_right_pt.y, bottom_right_pt.z ); glVertex3f( left_pt.x, left_pt.y, left_pt.z ); glVertex3f( right_pt.x, right_pt.y, right_pt.z ); glColor4f( fog_colour[0], fog_colour[1], fog_colour[2], 0.9 ); glVertex3f( top_left_pt.x, top_left_pt.y, top_left_pt.z ); glVertex3f( top_right_pt.x, top_right_pt.y, top_right_pt.z ); glColor4f( fog_colour[0], fog_colour[1], fog_colour[2], 0.3 ); pt = move_point( top_left_pt, left_vec ); glVertex3f( pt.x, pt.y, pt.z ); pt = move_point( top_right_pt, right_vec ); glVertex3f( pt.x, pt.y, pt.z ); glColor4f( fog_colour[0], fog_colour[1], fog_colour[2], 0.0 ); pt = move_point( top_left_pt, scale_vector( 3.0, left_vec ) ); glVertex3f( pt.x, pt.y, pt.z ); pt = move_point( top_right_pt, scale_vector( 3.0, right_vec ) ); glVertex3f( pt.x, pt.y, pt.z ); glEnd(); #endif }
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 ); }