⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/camera.cpp                       $
// $Revision:: 47                                                             $
//   $Author:: Markd                                                          $
//     $Date:: 11/14/98 2:33a                                                 $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/camera.cpp                            $
// 
// 47    11/14/98 2:33a Markd
// put in some better jump cutting
// 
// 46    11/13/98 11:00p Jimdose
// Took EV_CONSOLE off of fov
// 
// 45    11/13/98 10:50p Markd
// fixed watch camera
// 
// 44    11/10/98 7:06p Markd
// fixed 3rd person camera
// 
// 43    10/24/98 12:42a Markd
// changed origins to worldorigins where appropriate
// 
// 42    10/21/98 1:18a Markd
// took warning out of camera
// 
// 41    10/19/98 12:07a Jimdose
// made all code use fast checks for inheritance (no text lookups when
// possible)
// isSubclassOf no longer requires ::_classinfo()
// 
// 40    10/12/98 5:02p Markd
// Changed fov event
// 
// 39    9/30/98 10:13p Markd
// put in an additional comment line
// 
// 38    9/24/98 1:46a Markd
// fixed camera lerping
// 
// 37    9/20/98 6:49p Markd
// Added Thread ability to cameras when they are looked through
// 
// 36    9/07/98 4:36p Markd
// fixing camera stuff
// 
// 35    8/29/98 9:39p Jimdose
// Added call info to G_Trace
// 
// 34    8/29/98 5:27p Markd
// added specialfx, replaced misc with specialfx where appropriate
// 
// 33    8/27/98 9:01p Jimdose
// Changed grav to a reference
// 
// 32    8/24/98 6:51p Jimdose
// Fixed inverted gravity axis
// 
// 31    8/22/98 9:35p Markd
// When stopping the camera make sure to check if followtime or watchtime are
// non-zero, if so copy over the new states
// 
// 30    8/22/98 8:48p Jimdose
// Started getting camera working with alternate gravity axis
// 
// 29    8/18/98 12:03p Markd
// fixed camera fov stuff
// 
// 28    8/17/98 7:42p Markd
// Added SetOverlay command
// 
// 27    8/17/98 6:05p Markd
// Added nextcamera and overlay, made SetCamera send to all players
// 
// 26    8/17/98 4:33p Markd
// Added new camera stuff
// 
// 25    8/15/98 2:39p Markd
// fixed camera stuff
// 
// 24    8/14/98 8:18p Markd
// reworked camera class
// 
// 23    8/08/98 7:29p Aldie
// Added intermissions for deathmatch
// 
// 22    7/31/98 8:09p Jimdose
// Script commands now include flags to indicate cheats and console commands
// 
// 21    7/25/98 11:49p Markd
// fixed camera startup stuff
// 
// 20    7/22/98 5:28p Markd
// Redid camera stuff
// 
// 19    7/22/98 4:15p Markd
// Redid camera system
// 
// 18    7/20/98 2:38p Markd
// Fixed camera wackiness
// 
// 17    7/18/98 6:14p Markd
// Added optional watchEnt at the end of follow and orbit commands
// 
// 16    7/13/98 12:59p Markd
// Added fixedposition and nofixedposition
// 
// 15    7/12/98 9:43p Markd
// Accidentally commented out some camera following stuff
// 
// 14    7/12/98 8:43p Markd
// Fixed some camera smoothness issues
// 
// 13    7/11/98 6:31p Markd
// removed valid orientation, simplified code
// 
// 12    7/10/98 1:11p Markd
// Added some new camera commands
// 
// 11    7/08/98 12:41p Markd
// Added quaternion support to bsplines and also removed CameraPath
// 
// 10    7/02/98 9:48p Markd
// allowed camera to have orientation support from the bspline
// 
// 9     5/27/98 3:18a Jimdose
// cameras can now watch specific entities
// 
// 8     5/26/98 8:49p Jimdose
// Added yaw commands
// 
// 7     5/26/98 8:17p Jimdose
// added height script command
// fixed fov bug
// 
// 6     5/26/98 7:55p Jimdose
// added scripted cameras
// 
// 5     5/26/98 4:36a Jimdose
// Follow camera no longer clips into walls
// 
// 4     5/13/98 4:57p Jimdose
// now uses SafePtrs
// 
// 3     5/07/98 10:41p Jimdose
// fleshed out functionality a bit more
// 
// 2     5/05/98 2:37p Jimdose
// Created file
// 
// DESCRIPTION:
// Camera.  Duh.
// 

#include "g_local.h"
#include "entity.h"
#include "trigger.h"
#include "camera.h"
#include "bspline.h"
#include "player.h"
#include "camera.h"

cvar_t *sv_showcameras;

Event EV_Camera_FollowingPath( "followingpath" );
Event EV_Camera_StartMoving( "start" );
Event EV_Camera_Pause( "pause" );
Event EV_Camera_Continue( "continue" );
Event EV_Camera_StopMoving( "stop" );
Event EV_Camera_SetSpeed( "speed" );
Event EV_Camera_SetDistance( "distance" );
Event EV_Camera_SetHeight( "height" );
Event EV_Camera_SetYaw( "yaw" );
Event EV_Camera_FixedYaw( "fixedyaw" );
Event EV_Camera_RelativeYaw( "relativeyaw" );
Event EV_Camera_SetFOV( "fov" );
Event EV_Camera_Orbit( "orbit" );
Event EV_Camera_Follow( "follow" );
Event EV_Camera_Watch( "watch" );
Event EV_Camera_LookAt( "lookat" );
Event EV_Camera_TurnTo( "turnto" );
Event EV_Camera_MoveToEntity( "moveto" );
Event EV_Camera_MoveToPos( "movetopos" );
Event EV_Camera_NoWatch( "nowatch" );
Event EV_Camera_IgnoreAngles( "ignoreangles" );
Event EV_Camera_UseAngles( "useangles" );
Event EV_Camera_SplineAngles( "splineangles" );
Event EV_Camera_NormalAngles( "normalangles" );
Event EV_Camera_FixedPosition( "fixedposition" );
Event EV_Camera_NoFixedPosition( "nofixedposition" );
Event EV_Camera_JumpTime( "jumptime" );
Event EV_Camera_JumpCut( "jumpcut" );
Event EV_Camera_Pan( "pan" );
Event EV_Camera_StopPan( "stoppan" );
Event EV_Camera_PanSpeed( "panspeed" );
Event EV_Camera_PanMax( "panmax" );
Event EV_Camera_SetPanAngles( "setpanangles" );
Event EV_Camera_SetNextCamera( "nextcamera" );
Event EV_Camera_SetOverlay( "setoverlay" );
Event EV_Camera_SetThread( "setthread" );

/*****************************************************************************/
/*SINED func_camera (1 0 0) ? ORBIT START_ON PAN

Camera used for cinematic sequences.  Start

"target" points to the target to orbit or follow.  If it points to a path, the camera will follow the path.
"distance" the distance to follow or orbit if the target is not a path. (default 128).
"speed" specifies how fast to move on the path or orbit.  (default 1).
"fov" specifies fov of camera, default 90.
"yaw" specifies yaw of camera, default 0.
"height" specifies height of camera from origin, default 128.
"panspeed" speed at which to pan ( 7 degrees per second )
"panmax" maximum angle offset for panning ( 45 degrees )
"nextcamera" a link to the next camera in a chain of cameras
"overlay" an overlay to use while looking through the camera
"thread" a thread label that will be fired when the camera is looked through

ORBIT tells the camera to create a circular path around the object it points to.  It the camera points to a path, it will loop when it gets to the end of the path.
START_ON causes the camera to be moving as soon as it is spawned.
PAN camera should pan from right to left

/*****************************************************************************/

CLASS_DECLARATION( Entity, Camera, "func_camera" );

ResponseDef Camera::Responses[] =
	{
	   { &EV_Camera_FollowingPath,	( Response )Camera::FollowingPath },
		{ &EV_Activate,					( Response )Camera::StartMoving },
		{ &EV_Camera_StartMoving,		( Response )Camera::StartMoving },
		{ &EV_Camera_StopMoving,		( Response )Camera::StopMoving },
		{ &EV_Camera_Pause,				( Response )Camera::Pause },
		{ &EV_Camera_Continue,			( Response )Camera::Continue },
		{ &EV_Camera_SetSpeed,			( Response )Camera::SetSpeed },
		{ &EV_Camera_SetDistance,		( Response )Camera::SetDistance },
		{ &EV_Camera_SetHeight,			( Response )Camera::SetHeight },
		{ &EV_Camera_SetYaw,				( Response )Camera::SetYaw },
		{ &EV_Camera_FixedYaw,			( Response )Camera::FixedYaw },
		{ &EV_Camera_RelativeYaw,		( Response )Camera::RelativeYaw },
		{ &EV_Camera_SetFOV,				( Response )Camera::SetFOV },
		{ &EV_Camera_Orbit,				( Response )Camera::OrbitEvent },
		{ &EV_Camera_Follow,				( Response )Camera::FollowEvent },
		{ &EV_Camera_Watch,				( Response )Camera::WatchEvent },
		{ &EV_Camera_NoWatch,			( Response )Camera::NoWatchEvent },
		{ &EV_Camera_LookAt,				( Response )Camera::LookAt },
		{ &EV_Camera_TurnTo,				( Response )Camera::TurnTo },
		{ &EV_Camera_MoveToEntity,  	( Response )Camera::MoveToEntity },
		{ &EV_Camera_MoveToPos,			( Response )Camera::MoveToPos },
		{ &EV_Camera_IgnoreAngles,		( Response )Camera::IgnoreAngles },
		{ &EV_Camera_UseAngles,		   ( Response )Camera::UseAngles },
		{ &EV_Camera_SplineAngles,		( Response )Camera::SplineAngles },
		{ &EV_Camera_NormalAngles,		( Response )Camera::NormalAngles },
		{ &EV_Camera_FixedPosition,	( Response )Camera::FixedPosition },
		{ &EV_Camera_NoFixedPosition,	( Response )Camera::NoFixedPosition },
		{ &EV_Camera_JumpCut,	      ( Response )Camera::JumpCut },
		{ &EV_Camera_JumpTime,	      ( Response )Camera::JumpTime },
		{ &EV_Camera_Pan,    	      ( Response )Camera::PanEvent },
		{ &EV_Camera_StopPan,    	   ( Response )Camera::StopPanEvent },
		{ &EV_Camera_PanSpeed,    	   ( Response )Camera::PanSpeedEvent },
		{ &EV_Camera_PanMax,    	   ( Response )Camera::PanMaxEvent },
		{ &EV_Camera_SetPanAngles,    ( Response )Camera::SetPanAngles },
		{ &EV_Camera_SetNextCamera,   ( Response )Camera::SetNextCamera },
		{ &EV_Camera_SetOverlay,      ( Response )Camera::SetOverlay },
		{ &EV_Camera_SetThread,       ( Response )Camera::SetThread },

		{ NULL, NULL }
	};
Camera::Camera()
	{
   Vector ang;

	default_fov = G_GetFloatArg( "fov", 90 );
   if ( default_fov <= 0 ) 
      default_fov = 90;
   default_yaw = G_GetFloatArg( "yaw", 0 );

	default_follow_dist = G_GetFloatArg( "distance", 128 );
   default_height = G_GetFloatArg( "height", 128 );
	default_speed = G_GetFloatArg( "speed", 1 );

	default_pan_speed = G_GetFloatArg( "panspeed", 7 );
	default_pan_max = G_GetFloatArg( "panmax", 45 );

   nextCamera = G_GetStringArg( "nextcamera" );
   overlay = G_GetStringArg( "overlay" );
   thread = G_GetStringArg( "thread" );

	watchTime = 0;
   followTime = 0;

   targetEnt = NULL;
   targetWatchEnt = NULL;

   fov = default_fov;

   jumpTime = 2.0f;

	setSolidType( SOLID_NOT );
	setMoveType( MOVETYPE_NONE );

	ang = G_GetVectorArg( "angles", vec_zero );
   setAngles( ang );
   default_angles = ang;

   InitializeState( currentstate );
   InitializeState( newstate );

	sv_showcameras = gi.cvar( "sv_showcameras", "0", 0 );
	showcamera = sv_showcameras->value;
	if ( showcamera )
		{
		setModel( "xyz.def" );
		showModel();
		}
	else
		{
		hideModel();
		}

	if ( spawnflags & START_ON )
		{
		PostEvent( EV_Activate, FRAMETIME );
		}
	}

void Camera::InitializeMoveState( CameraMoveState &movestate )
	{
   movestate.pos = worldorigin;
	movestate.followEnt = NULL;
	movestate.orbitEnt = NULL;

   movestate.followingpath = false;
   movestate.cameraTime = 0;
   movestate.cameraPath.Clear();

	movestate.fov = default_fov;
   movestate.fixed_position = false;

	movestate.follow_dist = default_follow_dist;
   movestate.follow_mask = MASK_SOLID;
	movestate.height = default_height;
	movestate.speed = default_speed;
   }

void Camera::InitializeWatchState( CameraWatchState &watchstate )
	{
   worldangles.AngleVectors( &watchstate.dir, NULL, NULL );
	watchstate.watchEnt = NULL;

   watchstate.ignoreangles = false;
   watchstate.splineangles = true;
   watchstate.panning = false;

   watchstate.pan_offset = 0;
   watchstate.pan_dir = 1;
   watchstate.pan_max = default_pan_max;
   watchstate.pan_speed = default_pan_speed;
   watchstate.pan_angles = default_angles;

	watchstate.yaw = default_yaw;
	watchstate.fixedyaw = false;
   }

void Camera::InitializeState( CameraState &state )
	{
   InitializeMoveState( state.move );
   InitializeWatchState( state.watch );
   }


#define DELTA 1e-6

void Camera::EvaluatePosition
	(
   CameraState &state
	)
   {
   Vector oldpos, olddir;
   float speed_multiplier;
   Vector prevpos;

	prevpos = state.move.pos;

   olddir = state.watch.dir;

   //
   // evaluate position
   //
   if ( state.move.followingpath )
      {
   	speed_multiplier = state.move.cameraPath.Eval( state.move.cameraTime, oldpos, olddir );

	   state.move.cameraTime += FRAMETIME * state.move.speed * speed_multiplier;

   	if ( state.move.orbitEnt )
	   	{
         oldpos += state.move.orbitEnt->worldorigin;
		   }
      }
   else
      {
	   if ( !state.move.followEnt )
		   {
         oldpos = state.move.pos;
		   }
      else
         {
         trace_t trace;
         Vector start, end, ang, back, temp;
			const gravityaxis_t &grav = gravity_axis[ state.move.followEnt->gravaxis ];

	      start = state.move.followEnt->worldorigin;
	      start[ grav.z ] += state.move.followEnt->maxs[ 2 ];

	      if ( state.watch.fixedyaw )
		      {
		      ang = vec_zero;
		      }
	      else
		      {
		      if ( state.move.followEnt->isSubclassOf( Player ) )
			      {
               Entity * ent;
               ent = state.move.followEnt;
			      ang = ( ( Player * )ent )->v_angle;
			      }
		      else
			      {
			      ang = state.move.followEnt->worldangles;
			      }
		      }
	      ang.y += state.watch.yaw;
	      ang.AngleVectors( &temp, NULL, NULL );
			back[ grav.x ] = temp[ 0 ];
			back[ grav.y ] = temp[ 1 ] * grav.sign;
			back[ grav.z ] = temp[ 2 ] * grav.sign;

	      end = start - back * state.move.follow_dist;
	      end[ 2 ] += 24;

	      trace = G_Trace( start, vec_zero, vec_zero, end, state.move.followEnt, state.move.follow_mask, "Camera::EvaluatePosition" );
	      //dir = start - trace.endpos;
	      //dir.normalize();

	      end = trace.endpos;
         oldpos = end + back * 16;
         }
      }
   //
   // evaluate old orientation
   //
   if ( state.watch.watchEnt )
	   {
      Vector watchPos;

	   watchPos.x = state.watch.watchEnt->worldorigin.x;
	   watchPos.y = state.watch.watchEnt->worldorigin.y;
	   watchPos.z = state.watch.watchEnt->absmax.z;
	   if ( state.move.followEnt == state.watch.watchEnt )
         {
         olddir = watchPos - oldpos;
         }
      else
         {
         olddir = watchPos - worldorigin;
         }
	   }
   else 
	   {
      if ( state.watch.ignoreangles )
         {
         olddir = state.watch.dir;
         }
      else if ( state.move.followingpath )
         {
         if ( !state.watch.splineangles )
            {
   		   olddir = oldpos - prevpos;
            }
         else
            {
            Vector dir;

            dir = olddir;
   	      dir.AngleVectors( &olddir, NULL, NULL );
            }
         }
      else if ( state.move.followEnt )
         {
         Vector start;

	      start = state.move.followEnt->worldorigin;
	      start[ 2 ] += state.move.followEnt->maxs[ 2 ];
         olddir = oldpos - start;
         }
      else if ( state.watch.panning )
         {
         Vector ang;
         state.watch.pan_offset += FRAMETIME * state.watch.pan_speed * state.watch.pan_dir;
         if ( state.watch.pan_offset > state.watch.pan_max )
            {
            state.watch.pan_offset = state.watch.pan_max;
            state.watch.pan_dir = -state.watch.pan_dir;
            }
         else if ( state.watch.pan_offset < -state.watch.pan_max )
            {
            state.watch.pan_offset = -state.watch.pan_max;
            state.watch.pan_dir = -state.watch.pan_dir;
            }

         ang = state.watch.pan_angles;
         ang[ YAW ] += state.watch.pan_offset;
 	      ang.AngleVectors( &olddir, NULL, NULL );
         }
	   }
   olddir.normalize();

   if ( !state.move.fixed_position )
      state.move.pos = oldpos;
   state.watch.dir = olddir;
   }



void Camera::FollowingPath
	(
	Event *ev
	)

	{
   Vector   pos;
   Vector   dir;
   float    len;

   //
   // evaluate position
   //
   if ( followTime || watchTime )
      {
      int i;
      float t;

      EvaluatePosition( currentstate );
      EvaluatePosition( newstate );

      if ( followTime )
         {
		   t = followTime - level.time;
		   if ( t < 0 )
			   {
			   t = 0;
            currentstate.move = newstate.move;
            InitializeMoveState( newstate.move );
			   followTime = 0;
			   }
         //
         // we want the transition to happen over 2 seconds
         //
		   t = ( jumpTime - t ) / jumpTime;

         for ( i = 0; i < 3; i++ )
            {
            pos[ i ] = currentstate.move.pos[ i ] + ( t * ( newstate.move.pos[ i ] - currentstate.move.pos[ i ] ) );
            }
         fov = currentstate.move.fov + ( t * ( newstate.move.fov - currentstate.move.fov ) );
         }
      else
         {
         fov = currentstate.move.fov;
         pos = currentstate.move.pos;
         }

      if ( watchTime )
         {
		   t = watchTime - level.time;
		   if ( t < 0 )
			   {
			   t = 0;
            currentstate.watch = newstate.watch;
            InitializeWatchState( newstate.watch );
			   watchTime = 0;
			   }
         //
         // we want the transition to happen over 2 seconds
         //
		   t = ( jumpTime - t ) / jumpTime;

         dir = LerpVector( currentstate.watch.dir, newstate.watch.dir, t );
         }
      else
         {
         dir = currentstate.watch.dir;
         }
      }
   else
      {
      EvaluatePosition( currentstate );
      fov = currentstate.move.fov;
      pos = currentstate.move.pos;
      dir = currentstate.watch.dir;
      //warning("FollowingPath","%p pos x%.2f y%.2f z%2.f time %.2f", this, pos.x, pos.y, pos.z, level.time );
      }

   setOrigin( pos );

	len = dir.length();
	if ( len > 0.05 )
		{
		dir *= ( 1 / len );
		angles = dir.toAngles();
		angles[ PITCH ] = -angles[ PITCH ];
      setAngles( angles );
      //warning("FollowingPath","%p angles x%.2f y%.2f z%2.f time %.2f", this, angles.x, angles.y, angles.z, level.time );
		}


	if ( sv_showcameras->value != showcamera )
		{
		showcamera = sv_showcameras->value;
		if ( showcamera )
			{
			setModel( "xyz.def" );
			showModel();
			}
		else
			{
			hideModel();
			}
		}

   if ( sv_showcameras->value != showcamera )
	   {
	   showcamera = sv_showcameras->value;
	   if ( showcamera )
		   {
		   setModel( "xyz.def" );
		   showModel();
		   }
	   else
		   {
		   hideModel();
		   }
	   }
	if ( showcamera && currentstate.move.followingpath )
		{
		G_Color3f( 1, 1, 0 );
		if ( currentstate.watch.watchEnt )
			{
			currentstate.move.cameraPath.DrawCurve( currentstate.watch.watchEnt->worldorigin, 10 );
			}
		else
			{
			currentstate.move.cameraPath.DrawCurve( 10 );
			}
		}


	PostEvent( EV_Camera_FollowingPath, FRAMETIME );
	}

void Camera::LookAt
	(
	Event *ev
	)

	{
   Vector pos, delta;
   float len;
   Entity * ent;

	ent = ev->GetEntity( 1 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -