OpenGL学习笔记之坐标变换学习
Posted clever101
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL学习笔记之坐标变换学习相关的知识,希望对你有一定的参考价值。
作者:朱金灿
来源:clever101的专栏
GDI、Qt和OpenGL三者之间的绘图区别
开始学习OpenGL踩过一些坑。因为以前学过GDI和Qt绘图。GDI和Qt绘图都是比较直观的。如下图中就是使用GDI绘制一条从(0,0)到(100,100)的直线:
绘图代码如下:
HPEN g_hPen = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_CREATE:
g_hPen = CreatePen(PS_SOLID,2,RGB(255,0,0));
break;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
SelectPen(hdc, g_hPen);
//从(0,0)到(100,100)画直线
::MoveToEx(hdc, 0, 0, NULL);
::LineTo(hdc, 100, 100);
//以(100, 100)为圆心绘制一个半径为4的圆
::Ellipse(hdc,96,96,104,104);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
DeletePen(g_hPen);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
return 0;
可以看到GDI绘图中坐标(0,0)是在窗口的左上角。我们再试试使用Qt绘图,Qt绘图的效果图如下:
绘图代码如下:
void QtDraw::paintEvent(QPaintEvent *)
QPainter painter(this);
painter.setPen(QPen(Qt::red, 4));//设置画笔形式
painter.drawLine(0, 0, 100, 100);//从(0,0)到(100,100)画直线
painter.drawEllipse(100, 100, 4, 4);//以(100,100)为圆心,半径为4画圆
可以看到Qt绘图中坐标(0,0)是在窗口的左上角。我们再看看OpenGL的绘图函数。表面上看,OpenGL的绘制直线的代码也很简单,如下:
glBegin(GL_LINES);
glVertex2f(0, 0);
glVertex2f(100, 100);
glEnd();
但是上面这段代码并不能实现在窗口上绘制从(0,0)到(100,100)的直线。就是说glVertex2f函数的参数接受的并不是窗口坐标系的坐标。这个是跟GDI和Qt有着根本区别的。
OpenGL的坐标转换流程
从上一节我们知道glVertex2f函数的参数接受的并不是窗口坐标系的坐标。那么问题来了,glVertex2f函数的参数值是在哪个坐标系的呢?经过研究我们发现,glVertex2f函数的参数值是在物体坐标下。问题又来了,物体坐标是经过怎么的流程转换到窗口坐标系的呢?经过阅读《OpenGL编程指南》,发现流程如下:
问题又来了,假使我们要用OpenGL在窗口上绘制一条从(0,0)到(100,100)的直线,应该怎么做呢?根据上面的流程,就是说要将(0,0)和(100,100)进行一个逆变换,将这两个点从窗口坐标转变为物体坐标。代码如下:
void DrawGLScene(GLvoid)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
glColor3f(1.0f, 0.0f, 0.0f);
GLint viewport[4];
//获取当前视口的范围
glGetIntegerv(GL_VIEWPORT, viewport);
GLdouble modelview[16];
GLdouble projection[16];
GLdouble winStartX = 0.0;
GLdouble winStartY = 0.0;
GLdouble winEndX = 100.0;
GLdouble winEndY = 100.0;
GLdouble objStartX, objStartY, objStartZ;
GLdouble objEndX, objEndY, objEndZ;
//获取视图和模型变换矩阵
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
//获取投影矩阵
glGetDoublev(GL_PROJECTION_MATRIX, projection);
//将窗口坐标转化为物体坐标
gluUnProject(winStartX, winStartY, 0.0, modelview, projection, viewport, &objStartX, &objStartY, &objStartZ);
gluUnProject(winEndX, winEndY, 0.0, modelview, projection, viewport, &objEndX,&objEndY,&objEndZ);
//执行绘制
glBegin(GL_LINES);
glVertex2f(objStartX, objStartY);
glVertex2f(objEndX, objEndY);
glEnd();
效果图如下:
OpenGL绘图中窗口坐标(0,0)是在窗口的左下角,可以看出我们的代码绘制是正确的。
以上是关于OpenGL学习笔记之坐标变换学习的主要内容,如果未能解决你的问题,请参考以下文章