`
java-mans
  • 浏览: 11342387 次
文章分类
社区版块
存档分类
最新评论

基于OPENGL使用C++实现相机类

 
阅读更多
// GLCamera.h: interface for the CGLCamera class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_GLCAMERA_H__FEC26F62_2C54_4EDE_A31D_42B35E396D80__INCLUDED_)
#define AFX_GLCAMERA_H__FEC26F62_2C54_4EDE_A31D_42B35E396D80__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define ZOOM_ANGLE 0
#define ZOOM_SCALE 1
#define FILM_DIAGONAL 43.267 //相片对角线长度
class CGLCamera {    
public:    
	GLvoid DrawUV();//绘制局部坐标的单位矢量    
	GLvoid LookAround(GLdouble HAngle,GLdouble VAngle);//环视    
	GLvoid Telescope(GLboolean Switch);//望远镜效果开/关    
	GLvoid Init(GLvoid);//初始化    
	//设置视点    
	GLvoid SetViewPoint(GLdouble x,GLdouble y,GLdouble z );    
	GLvoid SetViewPoint(CVector p);    
	//设置位置    
	GLvoid SetPosition(CVector p);    
	GLvoid SetPosition(GLdouble x,GLdouble y,GLdouble z );    
	//平移    
	GLvoid Transfer(GLdouble Vx,GLdouble Vy,GLdouble Vz);    
	GLvoid Transfer(CVector V);    
	//视角    
	GLdouble GetViewAngle(void);    
	GLboolean SetViewAngle(GLdouble Value);    
	//扭角,以垂直于画面的轴旋转角    
	GLdouble GetScrewAngle(void);    
	GLvoid SetScrewAngle(GLdouble Value);    
	//焦距    
	GLdouble GetLens(void);    
	GLboolean SetLens(GLdouble Value);        
	GLsizei ViewLeft;    
	GLsizei ViewTop;    
	GLsizei ViewHeight;    
	GLsizei ViewWidth;    
	//开拍    
	GLvoid Camera(GLvoid);    
	GLdouble TeleMultiple;//望远倍数        
	//变焦    
	GLboolean Zoom(int Mode,GLdouble Value);        
	CGLCamera();    
	virtual ~CGLCamera();    
	CVector _EyePosition,_ViewPoint;    
	CVector _Ux,_Uy,_Uz;private:    
	GLvoid FixUV(GLvoid);    
	void Focus2Angle(void);    
	void Angle2Focus(void);    
	GLboolean FixViewAngle(GLvoid);    
	GLdouble _ViewAngle,_CVM;    
	GLdouble _LensFocus;    
	GLdouble _ScrewAngle;    
	GLdouble _ViewFar;        
	GLdouble _LookLength,_LookVAngle,_LookHAngle;            
	CMatrix _M;
};

#endif // !defined(AFX_GLCAMERA_H__FEC26F62_2C54_4EDE_A31D_42B35E396D80__INCLUDED_)

//源文件


// Camera.cpp: implementation of the CCamera class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GLCamera.h"
#include "math.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//构造函数,初始化视界距离
CGLCamera::CGLCamera()
{
    _ViewFar=10000000.0f;
    _CVM=1.0f;//视角放大系数,小于1时就缩小视角,相当于放大画面,大于1时相当于广角镜头
    this->Init();
}

CGLCamera::~CGLCamera()
{

}
//初始化
GLvoid CGLCamera::Init(GLvoid)
{
    ViewWidth=640;//视口宽度
    ViewHeight=480;//视口高度
    ViewLeft=0;//相对投影面的左边距离
    ViewTop=0;//相对投影面的上边距离
    _LensFocus=50.0f;//镜头焦距,这个是我自己设计的一个参数,3D中的视角不方便理解,用照相机镜头就比较有概念了。
    this->Focus2Angle();//焦距转换为角度。
    _EyePosition.z=10.0;//相机位置的Z坐标
    _EyePosition.w=1.0;//设置为坐标
    _ViewPoint.w=1.0;//设置为坐标,这个是视点的
    //相机方向矢量(单位矢量)
    _Uy.y=1.0;
    _Ux.x=1.0;
    _Uz.z=1.0;

    _ScrewAngle=0.0;//视角扭角,正为向右倾斜,负数为向左倾斜,模拟人头(相机)左右摇摆Z轴角度
    TeleMultiple=10.0f;//最大放大倍数
}
//开拍,实际就是使用参数设置相机位置方向和视点。游戏循环每次绘制前调用一次,就可以使画面得到正确的视图。
GLvoid CGLCamera::Camera(GLvoid)
{
    glMatrixMode(GL_PROJECTION);// 选择投影矩阵

    glViewport(ViewLeft, ViewTop, ViewWidth, ViewHeight);// 设置视口
    glLoadIdentity();// 重置投影矩阵
    
    // 设置视景体
    gluPerspective(
        _ViewAngle*_CVM,//视角参数与系数相乘得到实际视角
        (GLdouble)(ViewWidth-ViewLeft)/
        (GLdouble)(ViewHeight-ViewTop),
.5f,
        _ViewFar
        );

    gluLookAt(
        _EyePosition.x,_EyePosition.y,_EyePosition.z,
        _ViewPoint.x,_ViewPoint.y,_ViewPoint.z,
        _Uy.x,_Uy.y,_Uy.z);
}
//变焦,根据不同模式递增/递减视角或按比例放大/缩小视角
GLboolean CGLCamera::Zoom(int Mode,GLdouble Value)
{
    GLboolean tmp;
    switch(Mode)
    {
    case ZOOM_ANGLE:
        _ViewAngle+=Value;
        break;
    case ZOOM_SCALE:
    default:
        _ViewAngle*=Value;
        break;
    }

    tmp= FixViewAngle();
    Angle2Focus();//同步焦距
    return tmp;

}
//限定最大最小视角
GLboolean CGLCamera::FixViewAngle(GLvoid)
{
    if (_ViewAngle<1.0f){_ViewAngle=1.0f;return false;}
    if (_ViewAngle>180){_ViewAngle=180.0f;return false;}
    return true;
}
//角度转焦距
void CGLCamera::Angle2Focus()
{
    _LensFocus=FILM_DIAGONAL/2/tan(_ViewAngle*RAD_UNIT/2);
}
//焦距转角度
void CGLCamera::Focus2Angle()
{
    _ViewAngle=atan(FILM_DIAGONAL/_LensFocus/2.0f)*2/RAD_UNIT;
}
//设置视角
GLboolean CGLCamera::SetViewAngle(GLdouble Value)
{
    GLboolean tmp;
    _ViewAngle=Value;
    tmp= FixViewAngle();
    Angle2Focus();
    return tmp;
}

GLdouble CGLCamera::GetViewAngle()
{
    return _ViewAngle;
}
//设置镜头焦距
GLboolean CGLCamera::SetLens(GLdouble Value)
{
    _LensFocus=Value;
    Focus2Angle();
    return FixViewAngle();
}

GLdouble CGLCamera::GetLens()
{
    return _LensFocus;
}

//设置相机位置(坐标对象)
GLvoid CGLCamera::SetPosition(CVector p)
{
    CVector t;
    _EyePosition=p;
    this->FixUV();

}
//设置相机位置(坐标分量)
GLvoid CGLCamera::SetPosition(GLdouble x,GLdouble y,GLdouble z )
{
    CVector v;
    v.x=x;
    v.y=y;
    v.z=z;
    v.w=1.0;
    SetPosition(v);
}
//设置视点(坐标对象)
GLvoid CGLCamera::SetViewPoint(CVector p)
{
    p.w=1.0;
    _ViewPoint=p;
    FixUV();
}

//设置视点(坐标分量)
GLvoid CGLCamera::SetViewPoint(GLdouble x,GLdouble y,GLdouble z)
{
    CVector t;
    t.x=x;
    t.y=y;
    t.z=z;
    SetViewPoint(t);
}
//相机与视点一起平移(平移矢量分量)
GLvoid CGLCamera::Transfer(GLdouble Vx,GLdouble Vy,GLdouble Vz)
{
    
    CVector t;
    this->FixUV();
    t=_Ux*Vx+_Uy*Vy+_Uz*Vz;
    _M.SetTransfer(t.x,t.y,t.z);
    _EyePosition=_M.Transform(_EyePosition);
    _ViewPoint=_M.Transform(_ViewPoint);

}
//相机与视点一起平移(平移矢量对象)
GLvoid CGLCamera::Transfer(CVector V)
{
    Transfer(V.x,V.y,V.z);
}
//设置扭角
GLvoid CGLCamera::SetScrewAngle(GLdouble Value)
{
    _ScrewAngle=Value;
    
    _Uy.Clear();
    _Uy.y=1.0;
    FixUV();
    _M.SetRotateAngle(Value,_Uz);
    _Uy=_M.Transform(_Uy);
    _Ux=_M.Transform(_Ux);
    
}

GLdouble CGLCamera::GetScrewAngle()
{
    return _ScrewAngle;
}

//望远镜效果,当主程序接收到望远镜按键后循环调用此函数,产生逐步变焦效果,释放按键后立刻恢复到50MM标准镜效果。Switch参数就是按键按下标志
//如果望远镜按键按住不放,递减放大系数,步进值0.1,直到系数达到TeleMultiple的倒数位置并锁定在0.1,就是视角缩小到当前视角参数_ViewAngle的1/10,画面放大当前设定值的10倍。
GLvoid CGLCamera::Telescope(GLboolean Switch)
{
    if (Switch)
    {
        if (_LensFocus!=50.0f)
        {
            _LensFocus=50.0f;
            this->Focus2Angle();
        }
        if (_CVM>(1/TeleMultiple))_CVM-=0.1f;
    }
    else
        _CVM=1.0f;
}

//环视效果(水平旋转角和垂直旋转角)
GLvoid CGLCamera::LookAround(GLdouble HAngle, GLdouble VAngle)
{
    CVector v;
    if (HAngle!=0.0)
    {
    v=_ViewPoint-_EyePosition;
    _M.SetRotateAngle(HAngle,_Uy);
    _ViewPoint=_M.Transform(v)+_EyePosition;
    this->FixUV();
    }
    if (VAngle!=0.0)
    {
    v=_ViewPoint-_EyePosition;
    _M.SetRotateAngle(VAngle,_Ux);
    _ViewPoint=_M.Transform(v)+_EyePosition;
    this->FixUV();
    }
    
}
//这个函数是用来绘制三维十字线的,只是为了调试观察用。
GLvoid CGLCamera::DrawUV()
{
CVector t;
    glBegin(GL_LINES);
/*
        glColor3f(1.0f,1.0f,0.0f);
        glVertex3f(_ViewPoint.x,_ViewPoint.y,_ViewPoint.z);
        t=_Ux+_ViewPoint;
        glVertex3f(t.x,t.y,t.z);
    
        glColor3f(0.0f,1.0f,0.0f);
        t=_Uy+_ViewPoint;
        glVertex3f(_ViewPoint.x,_ViewPoint.y,_ViewPoint.z);
        glVertex3f(t.x,t.y,t.z);
*/
        glColor3f(1.0f,1.0f,0.0f);
        glVertex3f(0,0,0);
        t=_Ux;
        glVertex3f(t.x,t.y,t.z);
    
        glColor3f(0.0f,1.0f,0.0f);
        t=_Uy;
        glVertex3f(0,0,0);
        glVertex3f(t.x,t.y,t.z);

        glColor3f(0.0f,1.0f,1.0f);
        t=_Uz;
        glVertex3f(0,0,0);
        glVertex3f(t.x,t.y,t.z);

        glEnd();

}

GLvoid CGLCamera::FixUV(GLvoid)
{
    CVector t;
    t=_EyePosition-_ViewPoint;
    _Uz=t.UnitOperation();

    _Ux=_Uy.GetCrossMultiply(_Uz);
    _Ux=_Ux.UnitOperation();

    _Uy=_Uz.GetCrossMultiply(_Ux);
    _Uy=_Uy.UnitOperation();
}


  


  
分享到:
评论

相关推荐

    《Visual C++范例大全》随书光盘 第十七章

    实例392——使用OpenGL实现绘制三维图形 实例393——使用OpenGL通过动态调整观察点位置实现三维动画 实例394——在OpenGL中,使用纹理显示图形 实例395——用MessageBeep播放WAV文件 实例396——使用PlaySound...

    实战OpenGL三维可视化系统开发与源码精解.part08

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part07.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part10

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part09

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part01.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part02.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part03.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part05.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part06.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    实战OpenGL三维可视化系统开发与源码精解.part04.rar

    设计了屏幕图形打印类,实现了对OpenGL屏幕图形的打印,在此基础上,设计录制屏幕图像模块,实现了将OpenGL动画录制为一系列图像并保存到硬盘中。  第14章 主要对所建立的三维可视化设计系统的主要特点和功能进行...

    dryGL:适用于 iOS Android 的轻量级 C++ OpenGL ES 2.0 框架

    C++ OpenGL ES 2.0 框架 dryGL是一个轻量级的 OpenGL ES 2.0 引擎,适用于移动和 ES 设备。 它现在仅适用于iOS ,但我们打算让它跨平台,并且Android版本目前在我们的路线图上(未来可能会更多?Raspberry-Pi、Ouya...

    3Dev:3Dev是一个简单的3D引擎。 它使用OpenGL,SFML,Assimp

    相机类 小类,用于简单形状 天盒 3Dev编辑器(很快) 去做 使其跨平台 添加灯光(3Dev编辑器) 添加形状(3Dev编辑器) 添加导出功能(3Dev编辑器) 添加简单的物理(可选,如果高级物理可以快速工作) 添加...

    Android应用程序开发教程PDF电子书完整版、Android开发学习教程

    • 3D3D3D3D libraries libraries libraries libraries - 基于 OpenGL ES 1.0 APIs 实现;该库可以使用硬件 3D 加速(如果可用)或者使用高 度优化的3D 软加速。 • FreeType FreeType FreeType FreeType -位图...

    Android应用开发揭秘pdf高清版

    16.3.2 使用C\C++实现本地 方法 16.3.3 Android.mk实现 16.3.4 Application.mk实现 16.3.5 编译C\C++代码 16.4 AndroidNDK中使用0penGL 16.5小结 第17章 Android脚本环境 17.1 Android脚本环境简介 17.2 Android...

    《Android应用开发揭秘》附带光盘代码.

     16.3.2 使用C\C++实现本地  方法  16.3 编译C\C++代码  16.4 AndroidNDK中使用0penGL  16.5小结  第17章 Android脚本环境  17.1 Android脚本环境简介  17.2 Android脚本环境安装  17.3如何编写Android脚本...

    《Android应用开发揭秘》源码

     16.3.2 使用C\C++实现本地方法  16.3 编译C\C++代码  16.4 AndroidNDK中使用0penGL  16.5小结  第17章 Android脚本环境  17.1 Android脚本环境简介  17.2 Android脚本环境安装  17.3如何编写Android脚本...

    cafelRenderer:一款基于C ++的仿Mitsuba渲染器

    使用tinnyxml读取xml文件,物体信息读入后,由相应的工程类生成对应对象,交由kd树进行组织和管理。 2.opengl预览:opengl预览采用glfw,为每个相应的几何体和bsdf定义尖端和片元着色器。相机移

Global site tag (gtag.js) - Google Analytics