LOD地形根据视点的变化决定是否进行网格分割,因此系统应设计一个视点类,来管理视点相关的数据。这节介绍的视点类是通用的,在很多网站都可下到这个类的代码,它可以用在OPENGL编程的各个场合,当然朋友也可根据需要自己增加相应功能!
/***********************************************************************
* Copyrights Reserved by QinGeSoftware
* Author : Qinge
* Filename : Camera.h 1.0
* Date: 2008-1-10
************************************************************************/
#pragma once
#include "Vector3.h"
class Camera
{
public:
Camera(void);
virtual ~Camera(void);
public:
CVector3 GetPosition(){return m_vPosition;} //获得摄像机位置
CVector3 GetView(){return m_vView;} //获得视线目标点
CVector3 GetUpVector() {return m_vUpVector;} //获得向上方向
CVector3 GetStrafe() {return m_vStrafe;} //获得平移方向的单位向量
void PosotionCamera(float positionX, float positionY, float positionZ,
float viewX, float viewY, float viewZ,
float upVectorX, float upVectorY, float upVectorZ); //初始化摄像机
void RotateView(float angle, float X, float Y, float Z); //绕(x,y,z)旋转angle
void SetViewByMouse(); //通过鼠标旋转场景
void RotateAroundPoint(CVector3 vCenter, float X, float Y, float Z); //绕点旋转
void StrafeCamera(float speed); //平移摄像机
void MoveCamera(float speed); //沿视线方向移动摄像机
void Look(); //设置视点相当于glLookAt()
void Update(); //更新视点位置。
void CheckForMovement(); //检查是否有视点变量更新
private:
CVector3 m_vPosition; //摄像机视点
CVector3 m_vView; //摄像机视线
CVector3 m_vUpVector; //摄像机向上方向
CVector3 m_vStrafe; //摄像机平移
const float fSpeed; //摄像机移动速度
};
/***********************************************************************
* Copyrights Reserved by QinGeSoftware
* Author : Qinge
* Filename : Camera.cpp 1.0
* Date: 2008-1-10
************************************************************************/
#include "StdAfx.h"
#include "Camera.h"
Camera::Camera(void):fSpeed(5.0f)
{
m_vPosition = CVector3(0,0,0);
m_vView = CVector3(0.0,1.0,0.5);
m_vUpVector = CVector3(0.0,0.0,1.0);
}
Camera::~Camera(void)
{
}
void Camera::PosotionCamera(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ)
{
m_vPosition = CVector3(positionX, positionY+200, positionZ);
m_vView = CVector3(viewX, viewY, viewZ);
m_vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);
}
void Camera::SetViewByMouse()
{
CPoint m_CurPt,m_PrePt;
HDC hDC = ::GetDC(NULL);
float angleY, angleZ;
CVector3 m_uAixs, m_vViewDire;
unsigned long WIDTH, HEIGHT;
WIDTH =::GetDeviceCaps(hDC,HORZRES); //获得屏幕分辨率
HEIGHT =::GetDeviceCaps(hDC,VERTRES); //
::GetCursorPos(&m_CurPt);
m_PrePt.x = WIDTH >>1; //分辨率/2
m_PrePt.y = HEIGHT >> 1;
::SetCursorPos(m_PrePt.x, m_PrePt.y); //固定光标在屏幕中心
angleY = (m_CurPt.x - m_PrePt.x )/1000.0; //根据鼠标移动距离确定旋转角度
angleZ = (m_CurPt.y - m_PrePt.y )/1000.0; //
m_vViewDire = m_vView - m_vPosition;
m_uAixs = m_vViewDire.CrossProduct(m_vViewDire,m_vUpVector); //得到平移向量
m_uAixs = m_uAixs.Normalize(m_uAixs);
RotateView(angleZ, m_uAixs.x, m_uAixs.y, m_uAixs.z); //绕任意轴旋转
RotateView(angleY,0,1,0); //绕y轴旋转
}
void Camera::RotateView(float angle, float x, float y, float z)
{
CVector3 vNewView;
CVector3 vView = m_vView - m_vPosition; //视线方向
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);
//下面就是一个数学公式
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
m_vView = m_vPosition + vNewView; //视点+新向量=新视线目标点
}
void Camera::StrafeCamera(float speed)
{
//给视线目标点,视点增加一个增量
m_vPosition.x += m_vStrafe.x * speed;
m_vPosition.z += m_vStrafe.z * speed;
m_vView.x += m_vStrafe.x * speed;
m_vView.z += m_vStrafe.z * speed;
}
void Camera::MoveCamera(float speed)
{
CVector3 vVector = m_vView - m_vPosition;
vVector = vVector.Normalize(vVector);
m_vPosition.x += vVector.x * speed; //沿视线方向移动
m_vPosition.z += vVector.z * speed; //
m_vView.x += vVector.x * speed; //
m_vView.z += vVector.z * speed; //
}
void Camera::Update()
{
CVector3 vCross =m_vView.CrossProduct(m_vView - m_vPosition, m_vUpVector);
m_vStrafe = vCross.Normalize(vCross);
SetViewByMouse();
CheckForMovement();
}
void Camera::CheckForMovement() // 上下左右移动视点
{
if(GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80)
{
MoveCamera(fSpeed);
}
if(GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80)
{
MoveCamera(-fSpeed);
}
if(GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80)
{
StrafeCamera(-fSpeed);
}
if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80)
{
StrafeCamera(fSpeed);
}
}
void Camera::Look() //等于gluLookAt()
{
gluLookAt(m_vPosition.x, m_vPosition.y, m_vPosition.z,
m_vView.x, m_vView.y, m_vView.z,
m_vUpVector.x, m_vUpVector.y, m_vUpVector.z);
}