Show kcamera.cpp syntax highlighted
/*
Copyright (C) 2003, 2004, 2005 by Luca Cappa
Written by Luca Cappa groton@users.sourceforge.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cssysdef.h"
#include "csutil/sysfunc.h"
#include "cstool/csview.h"
#include "cstool/initapp.h"
#include "cstool/collider.h"
#include "csutil/cmdhelp.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/natwin.h"
#include "ivideo/txtmgr.h"
#include "ivideo/fontserv.h"
#include "imesh/sprite2d.h"
#include "imesh/ball.h"
#include "imesh/object.h"
#include "iengine/mesh.h"
#include "iengine/engine.h"
#include "iengine/sector.h"
#include "iengine/camera.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "iengine/mesh.h"
#include "imesh/thing.h"
#include "igraphic/imageio.h"
#include "csutil/cscolor.h"
#include "csutil/cmdhelp.h"
#include "csutil/cspmeter.h"
#include "csutil/csstring.h"
#include "csutil/scfstr.h"
#include "iutil/vfs.h"
#include "iutil/eventq.h"
#include "iutil/event.h"
#include "iutil/eventh.h"
#include "iutil/objreg.h"
#include "iutil/csinput.h"
#include "iutil/virtclk.h"
#include "iutil/plugin.h"
#include "iutil/string.h"
#include "iutil/comp.h"
#include "iengine/sector.h"
#include "iengine/engine.h"
#include "iengine/camera.h"
#include "iengine/light.h"
#include "iengine/texture.h"
#include "iengine/mesh.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "imesh/thing.h"
#include "imesh/object.h"
#include "imesh/sprite3d.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/natwin.h"
#include "ivideo/txtmgr.h"
#include "ivideo/texture.h"
#include "ivideo/material.h"
#include "ivideo/fontserv.h"
#include "igraphic/imageio.h"
#include "imap/loader.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "ivaria/conout.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "ivaria/collider.h"
#include "csgeom/quaterni.h"
#include "csgeom/transfrm.h"
#include "csgeom/math3d_d.h"
#include "csgeom/math3d.h"
#include "igeom/polymesh.h"
#include "imap/loader.h"
#include "iaws/aws.h"
#include "iaws/awscnvs.h"
#include "ske.h"
#include "kutil.h"
#include "kplayer.h"
#include "movement3d.h"
#include "kcamera.h"
KCamera::KCamera () :
m_pos (0.0f, 1.5f, 0.0f), //?? HARDCODED VALUE!
m_distance (5.0f),
mCameraVel (0, 0, 0), m_zoomingIn (false), m_zoomingOut (false),
mCameraAcc (0, 0, 0)
{
mEngine = CS_QUERY_REGISTRY (g_objReg, iEngine);
mG3d = CS_QUERY_REGISTRY (g_objReg, iGraphics3D);
m_view.AttachNew (new csView (mEngine, mG3d));
SetPanoramic (false);
mCamera = m_view->GetCamera ();
m_kbd = CS_QUERY_REGISTRY (g_objReg, iKeyboardDriver);
m_joy = CS_QUERY_REGISTRY (g_objReg, iJoystickDriver);
m_friction = 1.8f;
m_accK = 6.7f;
m_xAngle = 0;
m_yAngle = 0.457f;
m_zAngle = 0;
m_zoomingIn = false;
m_zoomingOut = false;
m_rotateX = 0;
m_rotateY = 0;
m_rotateZ = 0;
}
KCamera::~KCamera ()
{
//??
}
void KCamera::setViewport (csVector2 const& pPoint, csVector2 const& pSize)
{
m_view->SetRectangle (pPoint.x, pPoint.y, pSize.x, pSize.y);
mCamera = m_view->GetCamera ();
}
void KCamera::ZoomIn (bool p_val)
{
m_zoomingIn = p_val;
}
void KCamera::ZoomOut (bool p_val)
{
m_zoomingOut = p_val;
}
void KCamera::SetSector (iSector* p_sector)
{
mCamera->SetSector (p_sector);
}
void KCamera::SetPositionRotation (const csVector3& p_vector,
const csMatrix3& p_matrix)
{
csOrthoTransform& l_oT = mCamera->GetTransform ();
l_oT.SetOrigin (p_vector);
l_oT.SetT2O (p_matrix);
mCamera->SetTransform (l_oT);//?? is this needed???
}
//"state" is "THIRD" or "FIRST" person view, "POINTINGBEFOREWALKING",
// or "EDITING";
void KCamera::SetState (int p_state)
{
m_state = p_state;
}
int KCamera::GetState ()
{
return m_state;
}
int KCamera::SwitchPersonState ()
{
switch (m_state)
{
case FIRST:
m_state = THIRD;
break;
case THIRD:
m_state = FIRST;
break;
}//switch
return m_state;
}
iCamera* KCamera::GetCamera ()
{
return mCamera;
}
void KCamera::MoveForward (bool p_val)
{
if (p_val)
mCameraAcc.z = +m_accK;
else
mCameraAcc.z = 0;
}
void KCamera::MoveBack (bool p_val)
{
if (p_val)
mCameraAcc.z = -m_accK;
else
mCameraAcc.z = 0;
}
void KCamera::MoveLeft (bool p_val)
{
if (p_val)
mCameraAcc.x = -m_accK;
else
mCameraAcc.x = 0;
}
void KCamera::MoveRight (bool p_val)
{
if (p_val)
mCameraAcc.x = +m_accK;
else
mCameraAcc.x = 0;
}
/**
Clamp an radiant angle.
*/
static inline void AddAndClampAngle (float& p_value, float p_addedValue)
{
if (p_addedValue > 0)
{
p_value += p_addedValue;
if (p_value > K_2PI)
p_value = p_value - K_2PI;
}//if
else
{
p_value += p_addedValue;
if (p_value < 0.0f)
p_value = K_2PI + p_value;
}//else
}
//
//0 no rotation, +1 clockwise, -1 counterclockwise.
void KCamera::RotateX (int p_val)
{
m_rotateX = p_val;
}
//
//0 no rotation, +1 clockwise, -1 counterclockwise.
void KCamera::RotateY (int p_val)
{
m_rotateY = p_val;
}
//
//0 no rotation, +1 clockwise, -1 counterclockwise.
void KCamera::RotateZ (int p_val)
{
m_rotateZ = p_val;
}
void KCamera::SetDistance (float p_distance)
{
m_distance = p_distance;
if(m_distance <= 0.2f)//?? hardcoded value.
m_distance = 0.2f;
}
void KCamera::SetAngles (float p_xAngle, float p_yAngle, float p_zAngle)
{
m_xAngle = p_xAngle;
m_yAngle = p_yAngle;
m_zAngle = p_zAngle;
}
void KCamera::SetTracked (KPlayer* p_player)
{
m_tracked = p_player;
}
void KCamera::SetFOVAngle (float p_angle, int p_width)
{
mCamera->SetFOVAngle (p_angle, p_width);
}
void KCamera::Draw ()
{
m_view->Draw ();
}
//
//p_timePassed is in msecs.
void KCamera::HandleRotation (float p_timePassed)
{
static const float s_constant = (1.0f / 10000.0f) * (0.03f * 7.f);
//
//handle the 3 angles here.
float l_incrX = 0.0f, l_incrY = 0.0f, l_incrZ = 0.0f;
if (m_rotateX == 1)
l_incrX = (p_timePassed * s_constant);
if (m_rotateX == -1)
l_incrX = -(p_timePassed * s_constant);
AddAndClampAngle (m_xAngle, l_incrX);
if (m_rotateY == 1)
l_incrY = (p_timePassed * s_constant);
if (m_rotateY == -1)
l_incrY = -(p_timePassed * s_constant);
AddAndClampAngle (m_yAngle, l_incrY);
if (m_rotateZ == 1)
l_incrZ = (p_timePassed * s_constant);
if (m_rotateZ == -1)
l_incrZ = -(p_timePassed * s_constant);
AddAndClampAngle (m_zAngle, l_incrZ);
}
void KCamera::UpdatePosition (float p_msecs)
{
float l_seconds = p_msecs / 1000.0f;
//
//handle the distance here.
float l_acc = 0; //acceleration
if (m_zoomingIn)
l_acc = -7.8f;
else if (m_zoomingOut)
l_acc = 7.8f;
SetDistance (m_distance += m_mov1d.GetMovement (l_seconds, l_acc, 1.5f));
switch (m_state)
{
case EDITING:
{
HandleRotation (p_msecs);
csVector3 l_movement (0, 0, 0);
KQuaternion l_q2;
l_q2.SetWithEuler (csVector3 (RAD2DEG (m_xAngle),
RAD2DEG (m_yAngle), RAD2DEG (m_zAngle)));//this call requires DEGREE angles.
l_q2.Normalize();
csVector3 l_zAxis (0, 0, 1.0f);
csVector3 l_aheadDirection = l_q2.Rotate (l_zAxis);
l_aheadDirection.y = 0;//Project it to the XZ plane
l_aheadDirection.Normalize ();
l_aheadDirection *= mCameraAcc.z;
csVector3 l_xAxis (1.0f, 0, 0);
csVector3 l_rightDirection = l_q2.Rotate (l_xAxis);
l_rightDirection.y = 0;//Project it to the XZ plane
l_rightDirection.Normalize ();
l_rightDirection *= mCameraAcc.x;
csVector3 l_accWorldSpace = l_aheadDirection + l_rightDirection;
float l_accNorm = l_accWorldSpace.Norm ();
if (ABS (l_accNorm) < SMALL_EPSILON)//??? WTF
l_accWorldSpace = 0;
else
l_accWorldSpace = l_accWorldSpace.Unit () * l_accNorm;
mCameraVel.x = mCameraVel.x + l_accWorldSpace.x * l_seconds;//v = v0 + a*t
mCameraVel.z = mCameraVel.z + l_accWorldSpace.z * l_seconds;//v = v0 + a*t
if (mCameraVel.Norm() > SMALL_EPSILON)
{
csVector3 l_frictionVector = mCameraVel * m_friction * l_seconds;
if (l_frictionVector.Norm () > mCameraVel.Norm())
mCameraVel.Set (0,0,0);
else
mCameraVel -= l_frictionVector;
}//if
else
mCameraVel.Set (0,0,0);
l_movement.x = mCameraVel.x * l_seconds + 0.5f *
l_accWorldSpace.x * l_seconds * l_seconds;//x = v0*t +0.5*a*t*t
l_movement.z = mCameraVel.z * l_seconds + 0.5f *
l_accWorldSpace.z * l_seconds * l_seconds;//x = v0*t +0.5*a*t*t
m_pos += l_movement;
csVector3 l_v (0, 0, 1.0f);//default viewing is along Z axis.
csVector3 l_up (0, 1.0f, 0);
KQuaternion l_q;
l_q.SetWithEuler (csVector3 (RAD2DEG (m_xAngle), RAD2DEG (m_yAngle),
RAD2DEG (m_zAngle)));//this call requires DEGREE angles.
l_q.Normalize();
csVector3 l_vRotated = l_q.Rotate (l_v);
csVector3 l_upRotated = l_q.Rotate (l_up);
/*printf ("%7.3f,%7.3f,%7.3f ", l_vRotated.x, l_vRotated.y, l_vRotated.z);
csVector3 k = l_tr.This2Other (l_v);
printf ("%7.3f,%7.3f,%7.3f\n", k.x, k.y, k.z);//???*/
//set the new position and orientation of the camera.
csVector3 camera_pos (m_pos - m_distance * l_vRotated);
csVector3 look_at_pos (m_pos);
csOrthoTransform l_oT;
l_oT.LookAt (look_at_pos - camera_pos, l_upRotated);
SetPositionRotation (camera_pos, l_oT.GetT2O ());
//set the FOV on the camera.
SetFOVAngle (m_tracked->m_FOVAngle, m_tracked->m_FOVWidth);
}
break;
case THIRD:
{
HandleRotation (p_msecs);
//Set the new position and orientation of the camera.
//We get the position from the tracked object.
csVector3 l_pos = m_tracked->GetPosition ();
l_pos.y += m_tracked->GetHeight ();
KQuaternion l_camQ;
l_camQ.SetWithEuler (csVector3 (RAD2DEG (m_xAngle), RAD2DEG (m_yAngle),
RAD2DEG (m_zAngle)));
csVector3 l_v = csVector3 (0, 0, 1.0f);//default viewing is along X axis.
csVector3 l_up = csVector3 (0, 1.0f, 0);
csVector3 l_vRotated = l_camQ.Rotate (l_v);
csVector3 l_upRotated = l_camQ.Rotate (l_up);
csVector3 camera_pos (l_pos - m_distance * l_vRotated);
csVector3 look_at_pos (l_pos);
csOrthoTransform l_oT;
l_oT.LookAt (look_at_pos - camera_pos, l_upRotated);
SetPositionRotation (camera_pos, l_oT.GetT2O ());
//set the FOV on the camera.
//?? use the values used for the players configuration!
SetFOVAngle (m_tracked->m_FOVAngle, m_tracked->m_FOVWidth);
}//case
break;
case FIRST:
{
csVector3 l_pos = m_tracked->GetPosition ();
l_pos.y += m_tracked->GetHeight ();
csVector3 l_for(0,0,1), l_up(0,1,0);
l_up = m_tracked->GetHeadAngles ().Rotate (l_up);
l_up = m_tracked->GetBodyAngle ().Rotate (l_up);
l_for = m_tracked->GetHeadAngles ().Rotate (l_for);
l_for = m_tracked->GetBodyAngle ().Rotate (l_for);
csMatrix3 m;
csVector3 v(0,0,0);
csReversibleTransform l_rT (m, v);
l_rT.LookAt (l_for, l_up);
SetPositionRotation (l_pos, l_rT.GetT2O ());
//set the FOV on the camera.
SetFOVAngle (m_tracked->m_FOVAngle, m_tracked->m_FOVWidth);
}//case
break;
case POINTINGBEFOREWALKING:
{
//set the new position and orientation of the camera.
//we get the position from the tracked object.
csVector3 l_pos = m_tracked->GetPosition ();
l_pos.y += m_tracked->GetHeight ();
//
//Set the new position and orientation of the camera.
csVector3 camera_pos (l_pos);
csMatrix3 l_headM (m_tracked->GetHeadAngles ().GetMatrix ());
csMatrix3 l_bodyM (m_tracked->GetBodyAngle ().GetMatrix ());
SetPositionRotation (l_pos, l_bodyM * l_headM);
//set the FOV on the camera.
SetFOVAngle (m_tracked->m_FOVAngle, m_tracked->m_FOVWidth);
break;
}//case
default:
{
CS_ASSERT(false);
}//case
}//switch
}
bool KCamera::IsPanoramic () const
{
return mPanoramic;
}
void KCamera::SetPanoramic (bool pPan)
{
mPanoramic = pPan;
if (mPanoramic)
{
setViewport (csVector2 (0, mG3d->GetDriver2D ()->GetHeight () / 4),
csVector2 (mG3d->GetDriver2D ()->GetWidth (), mG3d->GetDriver2D ()->GetHeight () / 2));
}//if
else
{
setViewport (csVector2 (0, 0), csVector2
(mG3d->GetDriver2D ()->GetWidth (), mG3d->GetDriver2D ()->GetHeight ()));
}//else
}
See more files for this project here