如何运行opengl红宝书中的源码,傻瓜版

如何运行opengl红宝书中的源码,傻瓜版,第1张

如何运行opengl红宝书中的源码

一、安装GLUT工具包

1下载OpenGL需要的库文件 ,一般可以选择下载glut库(内含所有必须文件)

2解压后将得到的glut.lib和glut32.lib这两个静态函数库复制到文件目录的lib文件夹下

X:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib

3将glut.dll,glut32.dll这两个动态库文件放到 *** 作系统目录下面的C:\Windows\system32文件夹内行枝(32位系统)或‪C:\Windows\SysWOW64(64位系统)。

为了兼容性考虑,最好在这两个目录下都复制相应的文件。

4将解压得到的头文件glut.h复制到目录如下目录下:

X:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\GL

提示:如果在incluce目录下没有GL文件夹,则需要手动创建

二、VS2013中的配置

创建一档燃敏段简个空白的Win32控制台应用程序

在代码最前面添加包含目录

#include <GL/glut.h>

然后就可以编辑自己的OpenGL程序了

例如:复制如下代码到刚配置好的VS中

#include <GL/glut.h>

#include <stdlib.h>

#include <math.h>

#include <stdio.h>

static int year = 0,spin=0, day = 0

static GLint fogMode

const int n = 100

const GLfloat R = 1.0f

const GLfloat Pi = 3.1415926536f

void DrawCircle()

{

int i

glClear(GL_COLOR_BUFFER_BIT)

glBegin(GL_LINE_LOOP)

for (i = 0i <n++i)

{

glColor3f(1.0, 0.0, 0.0)

glVertex2f(R*cos(2 * Pi / n*i), R*sin(2 * Pi / n*i))

}

glEnd()

glFlush()

}

void init(void)

{

GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 }

glEnable(GL_DEPTH_TEST) //防止遮挡

glLightfv(GL_LIGHT0, GL_POSITION, position)

glEnable(GL_LIGHTING)

glEnable(GL_LIGHT0)

{

GLfloat mat[3] = { 0.1745, 0.01175, 0.01175 }

glMaterialfv(GL_FRONT, GL_AMBIENT, mat)

mat[0] = 0.61424mat[1] = 0.04136mat[2] = 0.04136

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat)

mat[0] = 0.727811mat[1] = 0.626959mat[2] = 0.626959

glMaterialfv(GL_FRONT, GL_SPECULAR, mat)

glMaterialf(GL_FRONT, GL_SHININESS, 0.6*128.0)

}

glEnable(GL_FOG)

{

GLfloat fogColor[4] = { 0.5, 0.5, 0.5, 1.0 }

fogMode = GL_EXP

glFogi(GL_FOG_MODE, fogMode)

glFogfv(GL_FOG_COLOR, fogColor)

glFogf(GL_FOG_DENSITY, 0.35)

glHint(GL_FOG_HINT, GL_DONT_CARE)

glFogf(GL_FOG_START, 1.0)

glFogf(GL_FOG_END, 5.0)

}

glClearColor(0.5, 0.9, 0.9, 1.0) /* fog color */

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

glColor3f(0.0, 1.0, 1.0)

glPushMatrix()//记住自己的位置

glutSolidSphere(1.0, 20, 16) /* 画太阳半径、 20经度、16纬度*/

glRotatef(spin, 0.0, 1.0, 0.0) //自转,绕着一个向量以给定角度旋转(正的为逆时针)

glTranslatef(2.0, 1.0, 0.0)

glRotatef(spin, 1.0, 0.0, 0.0)//公转

glRectf(0.1,0.1,0.5,0.5)

glColor3f(0.0, 0.0, 1.0)

glutWireSphere(0.2, 8, 8) /* 画第一颗小行星 */

glColor3f(1.0, 0.0, 0.0)

glTranslatef(2.0, 1.0, 0.0)

glRotatef(2 * spin, 0.0, 1.0, 0.0)

glutSolidSphere(0.5, 16, 8)

glPopMatrix()//回到原来的位置

glutSwapBuffers()

}

void spinDisplay(void)

{

spin = spin + 2

if (spin >360)

spin = spin - 360

glutPostRedisplay()

}

void mouse(int button,int state,int x,int y )

{

switch (button)

{

case GLUT_LEFT_BUTTON:

if (state == GLUT_DOWN)

glutIdleFunc(spinDisplay)

break

case GLUT_MIDDLE_BUTTON:

if (state == GLUT_DOWN)

glutIdleFunc(NULL)

break

default:

break

}

}

void reshape(int w, int h)

{

glViewport(0, 0, (GLsizei)w, (GLsizei)h)

glMatrixMode(GL_PROJECTION)

glLoadIdentity()

gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 0.5, 20.0)

glMatrixMode(GL_MODELVIEW)

glLoadIdentity()

gluLookAt(0.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)

}

void keyboard(unsigned char key, int x, int y)

{

switch (key) {

case 'd':

day = (day + 10) % 360

glutPostRedisplay()

break

case 'D':

day = (day - 10) % 360

glutPostRedisplay()

break

case 'y':

year = (year + 5) % 360

glutPostRedisplay()

break

case 'Y':

year = (year - 5) % 360

glutPostRedisplay()

break

case 27:

exit(0)

break

default:

break

}

}

int main(int argc, char** argv)

{

glutInit(&argc, argv)

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)

glutInitWindowSize(400, 400)

glutInitWindowPosition(100, 100)

glutCreateWindow("OpengGL 程序设计--杨超")

init()

//glutDisplayFunc(DrawCircle)

glutDisplayFunc(display)

glutReshapeFunc(reshape)

//glutKeyboardFunc(keyboard)

glutMouseFunc(mouse)

glutMainLoop()

return 0

}

5编译后能正确运行说明配置成功!

qt

可以通过QGLWidget运行opengl。QGLWidget继承QWidget,能够直接在里面调用opengl的接口。这个在qt文档里有具体说

明,也有相关例子,所以不赘述了。但是无法在正式软件里面执行,为什么?因为正式软件是用QGraphicsScene这个场景类 *** 作和 *** 作一切

item,而用QGraphicsView将其显示出来,而每一个item都是QGraphicsItem的子类。QGLWidget并不是QGraphicsItem类,我曾经尝试用普通的QWidget类那样,通过proxy来加进QGraphicsItem,但是没有成功。或许有方法,但是没有找到。

于是我放弃了用QGLWidget来 *** 作opengl的打算,寻找直接在QGraphicsItem中 *** 作opengl的方法。通过查看文档和示例代码,找到了这个方法:

1 往qt工程文件里添加opengl以及对应的lib。

2

对QGraphicsView进行一个三维对话框的指定,代码如下:

QGLWidget *widget = new

QGLWidget(QGLFormat(QGL::SampleBuffers))

widget->makeCurrent()

QGraphicsView

view

view.setViewport(widget)

上述代码唤唯洞告诉了 QGraphicsView 类当前绘制的对象是支持opengl的。于是所有的场景中的item都将绘制到widget 上。

3

写一个QGraphicsItem的继承类,特别要重写paint函数。代码如下:

void XXX::paint(QPainter

*painter, const QStyleOptionGraphicsItem *option, QWidget

*widget)

{

painter->beginNativePainting()

glColor3f(0.5,1.0,0.2)

glBegin(GL_TRIANGLES)

glVertex3f(100.0,100.0,-100.0)

glVertex3f(150.0, 100.0,

-100.0)

glVertex3f(100.0, 150.0,

-100.0)

glEnd()

painter->endNativePainting()

}

上面这个函数主要是用opengl接口绘制了一个三角形。记住,在opengl绘制之前一定要执行painter->beginNativePainting()以及painter->endNativePainting()这两个语句。

QGraphicsScene、

QGraphicsView和QGraphicsItem的关系可以查阅相关文档,也不赘述了。

不过我按照这个方式画的三角形,怎么也在窗口上显示和枯不出来,找了半天才发现问题在这个函数上QGraphicsItem::boundingRect()。这个函数是

干什么用的呢?主要用来返回该item的初始化大小,这个大小不会轻易改变,后续的改变都可以通过矩山判阵来完成,但是初始大小是不变的。QGraphicsView通过这个矩形来判断当前item是不是需要重绘,如果在重绘区外,则不调用重绘函数了。同时碰撞检测之类,也可以用这个矩形来判断。原来,item本身的矩阵外包框不对,所以才导致了重回不出来,改过来就正确了。

上面说的很潦草,具体怎么改的步骤就不说了。要想正确的绘制,必须得弄清楚坐标系的关系,QGraphicsScene、QGraphicsView以及QGraphicsItem这三个坐标系到底是什么关系。我看了文档,也自己进行了测试,但是感觉文档和测试的结果有些出入。具体出入不说了。说一下自己得心的吧。

先说明:涉及到一切大小和长度,都是像素大小,至少我测试的结果是这样的。

在建立QGraphicsScene

对象的时候,有一个构造函数是矩形,这个矩形是什么含义呢?经过测试,发现这个矩形并没有指定d出窗口的位置,比如,我把矩形的左上角点指定为

-1000,-1000,显示的位置和1000,1000是一样的,而长度则正确指定了(当然,可能会有滚动条)。所以,这个矩形的左上角点并不是显示的

窗口的位置,而是它在逻辑上的左上角点。我们显示一切item,都是以这个逻辑上的坐标系为准来绘制的。比如,左上角点是-1000,-1000,而

item的位置在-500,-500,则这个-500,-500相当于在显示窗口的左上角往下各加500个像素的坐标的位置。

那么 QGraphicsItem的boundingRect是什么意思呢?返回的是什么大小?是以什么坐标系显示的大小?首先,这个大小肯定是以像素为单位的,其次,这个矩形的坐标是以QGraphicsScene的逻辑坐标为准的。当然这个大小是没有任何矩阵叠加的大小。有了矩阵叠加后,实际的矩形可能会发生变化。假如在boundingRect中指定矩形的左上角为100,100,那么最终体现的位置则是QGraphicsScene逻辑坐标100,100的位置,如果QGraphicsScene的左上角点已经指定为-1000,-1000,那么这个位置实际上就是离窗口左上角点1100,1100的位置(由于有滚动条,所以也不一定是这个长度。)

那么在QGraphicsItem的paint函数中进行了opengl绘制用的是什么坐标呢?其实用的也是QGraphicsScene

的逻辑坐标。如上面的例子,绘制的直角三角形直角顶点是0,0,那么显示的位置就是距离显示窗口左上角点1000,1000的位置。不过opengl的所

有绘制都是没有矩阵叠加的基础上,如果用矩阵叠加,则显示的位置肯定和指定的有区别了。比如,我用setPos强制指定一个位置,这个位置将和opengl绘图坐标相叠加,最后显示到窗口上。我推测setPos其实是改变了矩阵,是一个平移矩阵。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12330886.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存