用glTranslate,glRotate来模拟gluLookAt

本文介绍了如何使用glTranslate和glRotate来模拟gluLookAt的功能,通过示例展示了如何设置视点和参考点,然后进行旋转和平移操作,以达到相同的效果。同时,代码中包含了一个简单的OpenGL窗口应用程序,用于演示这些变换的实际应用。
摘要由CSDN通过智能技术生成

glTranslate,glRotate来模拟gluLookAt,gluLookAt的模视矩阵能由glTranslate,glRotate实现:

 

float t= pow( 3, 0.5);

 

 

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存

   glLoadIdentity();                            //重置当前的模型观察矩阵

   gluLookAt( t* 3, 2.0f, 3.0f, 0.0f, 8.0f, 0.0f, 0.0f, 1.0f, 0.0f);

 

   double adModelMatrix[ 10][ 16];

 

   glGetDoublev( GL_MODELVIEW_MATRIX, adModelMatrix[ 0]);//模視矩陣

 

   glLoadIdentity();                            //重置当前的模型观察矩阵

glRotatef(-45,1.0f,0.0f,0.0f);//y轴旋转三角形

glRotatef(-60,0.0f,1.0f,0.0f);//y轴旋转三角形

 

   glTranslatef(-t* 3,-2.0,-3.0);                  //左移1.5单位,并移入屏幕6.0

 

   glGetDoublev( GL_MODELVIEW_MATRIX, adModelMatrix[ 1]);//模視矩陣

 

///

 

RRT(任意角度,R表示旋转glRotate,T表示平移glTranslate)

   Vec3 ptEye, ptRef, ptDir;

 

   //视点和参考点任意(取随机数)

   ptEye.x= ( rand()% 1000+ 1)/ 10;

   ptEye.y= ( rand()% 1000+ 1)/ 10;

   ptEye.z= ( rand()% 1000+ 1)/ 10;

 

   ptRef.x= ( rand()% 1000+ 1)/ 10;

   ptRef.y= ( rand()% 1000+ 1)/ 10;

   ptRef.z= ( rand()% 1000+ 1)/ 10; 

 

   ptDir.x= ptRef.x- ptEye.x;

   ptDir.y= ptRef.y- ptEye.y;

   ptDir.z= ptRef.z- ptEye.z; 

 

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存

   glLoadIdentity();                            //重置当前的模型观察矩阵

   gluLookAt( ptEye.x, ptEye.y, ptEye.z, ptRef.x, ptRef.y, ptRef.z, 0, 1.0f, 0.0f);

 

   glGetDoublev( GL_MODELVIEW_MATRIX, adModelMatrix[ 0]);//获取模視矩陣

 

 

   glLoadIdentity();                        //重置当前的模型观察矩阵

 

   constdouble PI= 3.14159265358979;

   double a1= 90- acos( ptDir.y/ sqrt(ptDir.z* ptDir.z+ ptDir.x* ptDir.x+ ptDir.y* ptDir.y))

      * 180/ PI;//竖直角度

   double dx= -ptDir.x, dz= -ptDir.z;

   double a2= acos( dz/ sqrt( dz* dz+ dx* dx)) * 180/ PI;//水平角度

   if ( dx < 0)

   {

      a2= -a2;

   }

   glRotatef(-a1,1.0f,0.0f,0.0f);//x轴旋转-a1,-45

 

   glRotatef(-a2,0.0f,1.0f,0.0f);//y轴旋转-a2,-60

 

   glTranslatef(-ptEye.x, -ptEye.y, -ptEye.z);//反向平移

 

   glGetDoublev( GL_MODELVIEW_MATRIX, adModelMatrix[ 1]);//模視矩陣

   

 

 

   for (int i= 0; i< 16; ++i)

   {

      if ( abs(adModelMatrix[ 1][ i] - adModelMatrix[ 0][ i] ) >= 1e-4)

      {

          float t= 0;

          ++t;

      }

   }

   //经验证,gluLookAt的模视矩阵确实能由glTranslate,glRotate实现,glRotate旋转时对角度有误差,

   //但不是很大,一般可在e-4.

 

―――――

获取模视矩阵:

glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    gluLookAt( -2.0f, 0.0f, 0.0f, -2.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);

 

    double adModelMatrix[ 16];

 

    glGetDoublev( GL_MODELVIEW_MATRIX, adModelMatrix);//获取模視矩陣

/*此例中的模视矩阵为:

1 0 0 2

0 1 0 0

0 0 1 0

0 0 0 1

*/

如下图:

可以看出gluLookAt()将视点由(0,0,0)向左移动到(-2,0,0),相当于模视矩阵MV为向右移动2个单位。模视矩阵MV是作用于物体点的,对点p,它在视点坐标系下的新点p=MV*p,相当于把物体向右移动2个单元,也即视点向左移动2个单元。就是说,对视点(及其局部opengl坐标系)经过先平移T、再旋转R后,得到的综合变换矩阵为A(如A=T*R),则最终设置的视图矩阵实际为setViewMatrix(A~)。

 

附:

OpenGL中的矩阵:
m[0]  m[4]  m[8]  m[12]  
m[1]  m[5]  m[9]  m[13]  
m[2]  m[6]  m[10]  m[14]  
m[3]  m[7]  m[11]  m[15] 

//

完整源代码如下:

#include<windows.h>

#include<cmath>

 

//my addings

#include<gl/gl.h>

#include<gl/glu.h>

#pragmacomment(lib,"opengl32.lib")

#pragmacomment(lib,"glu32.lib")

 

HDC       g_hDC=NULL;      // 窗口着色描述表句柄

HGLRC     g_hRC=NULL;      // OpenGL渲染描述表句柄

HWND      g_hWnd=NULL;     // 保存我们的窗口句柄

HINSTANCE g_hInstance;

 

static TCHAR szAppName[] = TEXT ("HelloWin") ;   //程序标题

struct Vec3

{

   float x;

   float y;

   float z;

};

 

//#include <GL/glaux.h>

//#include <gl/glut.h>     //包含OpenGL实用库

//#pragma comment(lib, "glaux.lib")

//my addings

 

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

ATOM RegistWnd( HINSTANCE hInstance);//注册窗口

BOOL InitWnd( HINSTANCE hInstance,int iCmdShow);//窗口初始化

 

GLvoid ReSizeGLScene(GLsizei width, GLsizei height);   //重置OpenGL窗口大小

int InitGL(GLvoid)                    ;            // 此处开始对OpenGL进行所有设置

int DrawGLScene(GLvoid)               ;            // 从这里开始进行所有的绘制

GLvoid KillGLWindow(GLvoid)    ;                   // 正常销毁窗口

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值