详解OpenGL的坐标系、投影和几何变换

合集下载

opengl相关3点成面和4点成面的原理

opengl相关3点成面和4点成面的原理

opengl相关3点成面和4点成面的原理OpenGL是一个用于渲染2D和3D图形的开放式图形库。

它使用一组API来处理图形渲染,包括几何图形的创建和变换,光照,纹理和着色等等。

在OpenGL中,可以通过3点或4点来创建一个面(或称为三角形或四边形)。

1.三点成面的原理:在OpenGL中,一个面是由三个顶点组成的。

这三个顶点将创建一个三角形,而该三角形也是计算机图形学中最基本的几何图形。

创建三角形的步骤如下:步骤1:定义顶点坐标首先,需要定义三个顶点的坐标。

顶点坐标是一个三维坐标(x,y,z),其中x、y表示顶点在屏幕上的位置,z表示顶点的深度,即相对于屏幕观测点的距离。

步骤2:创建缓冲区并绑定需要创建一个缓冲区对象,并将其绑定到OpenGL的上下文中。

缓冲区对象用于存储顶点数据。

步骤3:将顶点数据传输到缓冲区将定义好的顶点坐标数据传输到缓冲区对象中。

可以使用glBufferData函数来传输数据。

步骤4:创建着色器程序着色器程序用于定义顶点和片元的处理逻辑。

在这里,需要创建一个顶点着色器和一个片元着色器。

顶点着色器负责处理顶点的位置,而片元着色器负责处理像素的颜色。

步骤5:设置顶点属性指针需要告诉OpenGL如何解释顶点数据。

可以使用glVertexAttribPointer函数设置顶点属性指针。

步骤6:绘制三角形最后,使用glDrawArrays函数或glDrawElements函数将三角形绘制在屏幕上。

2.四点成面的原理:在OpenGL中,一个面也可以由四个顶点组成。

创建四边形的步骤与创建三角形的步骤类似,只不过多了一个顶点。

步骤1:定义顶点坐标同样,需要定义四个顶点的坐标。

步骤2:创建缓冲区并绑定与三角形的创建步骤相同,需要创建一个缓冲区对象,并将其绑定到OpenGL的上下文中。

步骤3:将顶点数据传输到缓冲区将定义好的顶点坐标数据传输到缓冲区对象中。

步骤4:创建着色器程序同样需要创建一个顶点着色器和一个片元着色器。

计算机图形学-变换

计算机图形学-变换
1
第3章 变换
基本的二维几何变换 二维复合变换 其他二维变换 三维几何变换 OpenGL几何变换函数 三维图形的显示流程 投影 裁剪
2
几何变换
应用于对象几何描述并改变它的位置、方 向或大小的操作称为几何变换(geometric transformation) 基本的二维几何变换包括平移、旋转和缩 放
8
矩阵表示和齐次坐标
许多图形应用涉及到几何变换的顺序 需要用一个通式来表示平移、旋转和缩放
P M1 P M 2
将2×2矩阵扩充为3×3矩阵,可以把二维几 何变换的乘法和平移项组合为单一矩阵表示
9
二维平移矩阵
x 1 0 t x x y 0 1 t y y 1 0 0 1 1
三维坐标轴旋转
X轴坐标不变,循环替代x、y、z三个 轴可以得到绕x轴旋转的公式
z
y ' y cos z sin
y
z ' y sin z cos x' x
x
35
三维坐标轴旋转
y轴坐标不变,循环替代x、y、z三个 轴可以得到绕y轴旋转的公式
x
z
y
z ' z cos x sin x' z sin x cos y' y
glMatrixMode (GL_MODELVIEW); glColor3f (0.0, 0.0, 1.0); glRecti (50, 100, 200, 150); //显示蓝色矩形
glColor3f (1.0, 0.0, 0.0); glTranslatef (-200.0, -50.0, 0.0); glRecti (50, 100, 200, 150); //显示红色、平移后矩形

OpenGL编程指南

OpenGL编程指南

OpenGL基础图形编程- 总目录出处:中国游戏开发者[ 2001-09-20 ]作者:总目录第一章OpenGL与三维图形世界1.1 OpenGL使人们进入三维图形世界1.2 OpenGL提供直观的三维图形开发环境1.3 OpenGL称为目前三维图形开发标准第二章OpenGL概念建立2.1 OpenGL基本理解2.2 OpenGL工作流程2.3 OpenGL图形操作步骤第三章Windows NT环境下的OpenGL3.1 Windows NT下的OpenGL函数3.2 OpenGL基本功能3.3 Windows NT下OpenGL结构第四章OpenGL基本程序结构第五章OpenGL数据类型和函数名第六章OpenGL辅助库的基本使用6.1 辅助库函数分类6.2 辅助库应用示例第七章OpenGL建模7.1 描述图元7.1.1 齐次坐标7.1.2 点7.1.3 线7.1.4 多边形7.2 绘制图元7.2.1 定义顶点7.2.2 构造几何图元第八章OpenGL变换8.1 从三维空间到二维平面8.1.1 相机模拟8.1.2 三维图形显示流程8.1.3 基本变换简单分析8.2 几何变换8.2.1 两个矩阵函数解释8.2.2 平移8.2.3 旋转8.2.4 缩放和反射8.2.5 几何变换举例8.3 投影变换8.3.1 正射投影8.3.2 透视投影8.4 裁剪变换8.5 视口变换8.6 堆栈操作第九章OpenGL颜色9.1 计算机颜色9.1.1 颜色生成原理9.1.2 RGB色立体9.2 颜色模式9.2.1 RGBA模式9.2.2 颜色表模式9.2.3 两种模式应用场合9.3 颜色应用举例第十章OpenGL光照10.1 真实感图形基本概念10.2 光照模型10.2.1 简单光照模型10.2.2 OpenGL光组成10.2.3 创建光源10.2.4 启动光照10.3 明暗处理10.4 材质10.4.1 材质颜色10.4.2 材质定义10.4.3 材质RGB值和光源RGB值的关系10.4.4 材质改变第十一章OpenGL位图和图像11.1 位图11.1.1 位图和字符11.1.2 当前光栅位置11.1.3 位图显示11.2 图像11.2.1 象素读写11.2.2 象素拷贝11.2.3 图像缩放11.2.4 图像例程第十二章OpenGL纹理12.1 基本步骤12.2 纹理定义12.3 纹理控制12.3.1 滤波12.3.2 重复与约简12.4 映射方式12.5 纹理坐标12.5.1 坐标定义12.5.2 坐标自动产生第十三章OpenGL复杂物体建模13.1 图元扩展13.1.1 点和线13.1.2 多边形13.2 法向计算13.2.1 法向基本计算方法13.2.2 法向定义13.3 曲线生成13.3.1 曲线绘制举例13.3.2 曲线定义和启动13.3.3 曲线坐标计算13.3.4 定义均匀间隔曲线坐标值13.4 曲面构造13.4.1 曲面定义和坐标计算13.4.2 定义均匀间隔的曲面坐标值13.4.3 纹理曲面13.4.4 NURBS曲面第十四章OpenGL特殊光处理14.1 光照模型14.1.1 全局环境光14.1.2 近视点与无穷远视点14.1.3 双面光照14.2 光源位置与衰减14.3 聚光与多光源14.3.1 聚光14.3.2 多光源与例程14.4 光源位置与方向的控制14.5 辐射光第十五章OpenGL效果处理15.1 融合15.1.1 Alpha值与融合15.1.2 融合因子15.1.3 融合实例15.2 反走样15.2.1 行为控制函数15.2.2 点和线的反走样15.2.3 多边形的反走样15.3 雾15.3.1 雾的概论和例程15.3.2 雾化步骤第十六章OpenGL显示列表16.1 显示列表概论16.1.1 显示列表的优势16.1.2 显示列表的适用场合16.2 创建和执行显示列表16.2.1 创建显示列表16.2.2 执行显示列表16.3 管理显示列表16.4 多级显示列表第十七章OpenGL帧缓存和动画17.1 帧缓存17.1.1 帧缓存组成17.1.2 缓存清除17.2 动画【下页】【打印】【关闭】[ 字号:大·中·小]OpenGL基础图形编程- OpenGL与3D图形世界出处:中国游戏开发者[ 2001-09-20 ]作者:目录1.1 OpenGL使人们进入三维图形世界1.2 OpenGL提供直观的三维图形开发环境1.3 OpenGL成为目前三维图形开发标准1.1、OpenGL使人们进入三维图形世界我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体。

opengles 顶点理解 -回复

opengles 顶点理解 -回复

opengles 顶点理解-回复“opengles 顶点理解”OpenGL ES(Open Graphics Library for Embedded Systems)是一套跨平台的图形库,用于在嵌入式系统中渲染2D和3D图形。

在OpenGL ES 中,顶点(vertex)是构建图形模型的基本元素之一,理解顶点对于理解和使用OpenGL ES来说非常重要。

本文将一步一步地回答如何理解OpenGL ES中的顶点,帮助读者更好地掌握该概念。

第一步:顶点的基本概念顶点是OpenGL ES中构成图形模型的基本单位。

对于二维图形,一个顶点通常由两个分量组成,即X和Y坐标。

对于三维图形,一个顶点通常由三个分量组成,即X、Y和Z坐标。

顶点也可以包含其他属性,例如颜色、法线、纹理坐标等,这些属性在渲染过程中对于图形的外观起到重要的作用。

第二步:顶点的坐标系在OpenGL ES中,通常使用右手坐标系。

X轴指向右侧,Y轴指向上方,Z轴指向屏幕内部。

通过指定每个顶点在坐标系中的位置,可以确定图形模型的形状和大小。

第三步:顶点的索引在绘制复杂的图形模型时,可能会存在大量的顶点。

为了减少内存占用和提高渲染效率,OpenGL ES引入了顶点索引的概念。

顶点索引是一个数组,其中存储了顶点的索引顺序。

通过使用顶点索引,可以使用较少的顶点来构建复杂的图形模型。

第四步:顶点的绘制过程在绘制图形模型之前,首先需要将顶点数据传递给OpenGL ES。

这些顶点数据可以存储在内存中的数组中,也可以从外部文件加载。

在传递顶点数据之后,需要创建一个顶点缓冲区(vertex buffer),将顶点数据存储在其中。

然后,需要创建一个顶点数组对象(vertex array object),这个对象关联了顶点缓冲区和OpenGL ES的渲染管线。

在绘制过程中,首先需要使用顶点着色器(vertex shader)处理顶点数据。

顶点着色器通常采用自定义的程序,用于对顶点进行变换和处理。

OpenGL 函数 gluLookAt

OpenGL 函数 gluLookAt

OpenGL 函数gluLookAt()glScalef() glTranslatef()glRotatef() glFrustum()glPerspective() 的使用1.gluLookAt()——视图变换函数把自己的眼睛当成是照相机,前三个参数表示眼睛的坐标,中间三个参数表示要拍照的物体的中心位置,可以理解成焦点吧,后三个参数表示头顶的朝向,比如说头可以歪着(哈哈)。

但是我测试过,如果歪的不对,原来的正前方现在已经不是正前方了,那么就看不见物体了。

举个例子:gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);//这个就表示头顶是朝着y方向gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0);//这个表示头歪了45度,头顶朝着(1.0,1.0,0.0)这个方向2.glScalef() ——模型变换函数缩放void glScalef(GLfloat x, GLfloat y, GLfloat z);模型变换的目的是设置模型的位置和方向,例如可以对模型进行旋转、移动和缩放,或者联合这几种操作。

这个函数表示模型在各轴上是如果进行缩放的。

举个例子:glScalef (1.0, 2.0, 1.0);//表示y坐标值扩大两倍,这样原本方的物体就变成长的了。

3.glTranslatef() ——模型变换函数移动void glTranslatef(GLfloat x, GLfloat y, GLfloat z);这个函数表示模型是怎样移动的。

举个例子:glTranslatef(-1.0,0.0,-2.0);//表示物体沿x负方向移动1.0,沿z轴负方向移动2.0。

所以就好像能看见侧面一样4.glRotatef()——模型变换函数旋转void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);angle表示旋转的角度(注意单位不是弧度),(x,y,z)表示转轴。

OpenGL编程低级错误及常见问题解答

OpenGL编程低级错误及常见问题解答

OpenGL编程低级错误及常见问题解答低级错误1.没有glDisable(GL_TEXTURE_2D),导致基本几何作图全部失败。

2.镜头位置没调好,导致所有物体不可见.3.物体位置数据错误,导致物体大大超出镜头显示范围.4.纹理没有GL_CLAMP导致边界拼接出现缝线.5.纹理没有GL_REPEA T导致使用超出1.0纹理坐标技巧失败,显示单色插值.6.没有glEnable(GL_TEXTURE_2D)导致全白纹理.7.glEnable(GL_TEXTURE_2D)后没有使用纹理顶点导致如glColor效果的纯单色.8.应该在作图循环设置灯光位置,因为The?position?is?transformed?by?the?modelview?matrix?when?glLight?is?called?(just?as?if?it?w ere?a?point),?and?it?is?stored?in?eye?coordinates.?9.灯光位置应该是4个float,3个float程序不出错,但结果完全扭曲。

10.打开灯光却没设置顶点法线,到头一场空。

11.Window Class 没有CS_OWNDC,导致glDrawPixels失败,如在子窗口V iew上进行象素写入操作.12.没有设置PIXELFORMA TDESCRIPTOR的cAlphaBits=8,导致glReadPixels读取alpha通道数据失败,统统为0.13.手动实现的多层纹理闪烁,出现线带,没有使用glPolygonOffset.14.glDrawPixels格式GL_RGB或GL_BGR_EXT的数据时崩溃,且数据有效,没有使用glPixelStorei(GL_UNPACK_ALIGNMENT, 1);导致图像行默认4字节对齐,导致OpenGL数据读取越界崩溃.相应的要为glReadPixels设置glPixelStorei(GL_PACK_ALIGNMENT, 1); 15.glReadPixel读取被覆盖的OpenGL窗口部分的图像数据时,读出数据混乱无效,OpenGL Pixel Ownership检测导致,标准如此.使用PixelBuffer,或强制置前OpenGL窗口解决.16.glReadPixels读取总是从FrameBuffer的左下往右上读取,毫无参数可设置改变方向,真是笨到家了. 载入图像一般还是从上到下比较容易理解.17.使用glDepthMask(GL_FALSE)后不打开,glClear无法清除深度缓冲,导致现象:场景起始静止正常,一旦移动出现不规则的透明无渲染区域,深度缓存逻辑混乱.18.gluPerspective(45.0f, (GLfloat)cxPixels/(GLfloat)cyPixels, 0.1f, 2000.0f);这里的0.1f将导致物体和地面的相交处闪烁,原因待查,至少取1.0f.19.没有显示定义shiniess或shiniess为0,在shader中对gl_FrontMaterial.shininess使用pow 计算,结果不可测,黑色条带闪烁,quite not understand.常见错误问:OpenGL中的Stencil Buffer是什么东西?答:模板缓存(Stencil Buffer)。

OpenGL使用手册.

OpenGL函数使用手册(一)OpenGL函数库格式:<库前缀><根命令><可选的参数个数><可选的参数类型> 库前缀有 gl、glu、aux、glut、wgl、glx、agl 等等,1,核心函数库主要可以分为以下几类函数:(1) 绘制基本的几何图元函数。

如:glBegain().(2) 矩阵操作、几何变换和投影变换的函数。

如:矩阵入栈glPushMatrix(),还有矩阵的出栈、转载、相乘,此外还有几何变换函数glTranslate*(),投影变换函数glOrtho()和视口变换函数glViewport()等等。

(3) 颜色、光照和材质函数。

(4) 显示列表函数,主要有创建、结束、生成、删除和调用显示列表的函数glNewList()、glEndList()、glGenLists()、glDeleteLists()和glCallList()。

(5) 纹理映射函数,主要有一维和二维纹理函数,设置纹理参数、纹理环境和纹理坐标的函数glTexParameter*()、glTexEnv*()和glTetCoord*()等。

(6) 特殊效果函数。

(7) 选着和反馈函数。

(8) 曲线与曲面的绘制函数。

(9) 状态设置与查询函数。

(10) 光栅化、像素函数。

2,OpenGL实用库(The OpenGL Utility Library)(GLU)包含有43个函数,函数名的前缀名为glu.(1) 辅助纹理贴图函数。

(2) 坐标转换和投影变换函数。

(3) 多边形镶嵌工具。

(4) 二次曲面绘制工具。

(5) 非均匀有理B样条绘制工具。

(6) 错误反馈工具,获取出错信息的字符串gluErrorString() 3,OpenGL辅助库包含有31个函数,函数名前缀名为aux这部分函数提供窗口管理、输入输出处理以及绘制一些简单的三维物体。

4,OpenGL工具库(OpenGL Utility Toolkit)包含大约30多个函数,函数前缀名为glut,此函数由glut.dll来负责解释执行。

OpenGL ES入门

OpenGL ES入门一、前言OpenGL ES是Khronos Group创建的一系列API中的一种(官方组织是:/)。

在桌面计算机上有两套标准的3DAPI:Direct3D和OpenGL。

Direct3D实际上是运行在windows操作系统上的标准3DAPI,而OpenGL则是跨平台的,适用于Linux、多种UNIX、MAC OS X和windows。

由于OpenGL得到了广范围的认可,所以,基于嵌入式的3DAPI---OpenGL ES也就应运而生。

沃Phone使用的芯片高通7227,它能很好的提供对OpenGL ES的支持,了解OpenGL ES 的种种特性,不仅能开发出很好的适用于沃Phone的3D游戏、3D应用等。

借助于OpenGL ES的平台无关性,只要稍微修改EGL,理论上就可以将开发的3D游戏、3D应用移植到任何支持OpenGL ES的平台上去。

本篇文档就从零开始,深入简出,跟大家介绍一下OpenGL ES的原理和开发。

OpenGL ES简介什么是OpenGL ESOpenGL ES是一套适用于手持嵌入式设备的3DAPI。

比如手机、PDA、汽车、航空等等上面都可以使用到OpenGL ES。

OpenGL ES是免授权费的、跨平台的、功能完善的2D和3D 图形应用程序接口API,它是桌面OpenGL的子集,是从OpenGL裁剪定制而来的。

由于手持设备的相关局限性,OpenGL ES相对于OpenGL不可避免的进行了相关的精简。

去除了OpenGL中比如glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POL YGONS)等复杂图元等许多非绝对必要的特性。

但是OpenGL方面的很多知识,OpenGL ES都是可以借鉴的。

OpenGL ES其实是一个状态机(State machine),它保存一种状态直至其改变。

每个状态都有本身默认的缺省值,可以通过相关的查询和设置函数进行相关的查询和设置。

OpenGL介绍

OpenGL实用库
glaux.h: OpenGL扩展库 glut.h: OpenGL实用工具包 #include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h> #include <GL/glut.h>
此外,OpenGL还提供了反走样技术,能够实现深度暗示(Depth Cue)、运动模糊(Motion Blur)、雾化(Fog)等特殊效果。
6.1.3 OpenGL的绘制流程和原理
点数据 评价器 逐点操作 基元匹配 基片 操作
显示 列表
像素 数据 像素操作
光栅化
帧缓冲区
纹理存储器
OpenGL指令从左侧进入OpenGL,有两类数据,分别是由顶点描述的几何模 型和由像素描述的位图、影像等模型,其中后者经过像素操作后直接进入光栅 化。评价器(Evaluator)用于处理输入的模型数据,例如对顶点进行转换、光照, 并把图元剪切到视景体中,为下一步光栅化做好准备。显示列表(Display List) 用于存储一部分指令,留待合适时间以便于快速处理。光栅化将图元转化成二 维操作,并计算结果图像中每个点的颜色和深度等信息,产生一系列图像的帧 缓存描述值,其生成结果称为基片(Fragment)。基片操作主要的有帧缓存的更 新、测试、融合和屏蔽操作,以及基片之间的逻辑操作和抖动(Dithering)。
第6章 OpenGL
6.1 基本介绍
6.1.1 背景情况
OpenGL(Open Graphics Library,即开放性图形库)是以SGI的 GL三维图形库为基础制定的一个开放式三维图形标准。SGI在 1992年7月发布了1.0版。 OpenGL 规 范 由 ARB(OpenGL Architecture Review Board, OpenGL结构评审委员会)负责管理,目前加入OpenGL ARB的 成员有SGI、Microsoft、Intel、IBM、SUN、Compaq、HP等公 司,它们均采用了OpenGL图形标准,许多软件厂商以OpenGL 为基础开发自己的产品,硬件厂商提供对OpenGL的支持。由 于OpenGL的广泛应用,它已经成为一个工业标准。

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)

openGL三维网格坐标,旋转,缩放,灯光设置,纹理读取,模型读取(MFC单文档)在我的MFC单文档项目中enableview.h和enableview.cpp负责上面的窗口建立,myopenglview.h和myopenglView.cpp主要是功能的实现1.三维网格建立:void GLGrid(float pt1x, float pt1y, float pt1z, float pt2x, float pt2y, float pt2z, int num){const float _xLen = (pt2x - pt1x) / num;const float _yLen = (pt2y - pt1y) / num;const float _zLen = (pt2z - pt1z) / num; glLineWidth(2.f);glLineStipple(1, 0x0303);//线条样式glBegin(GL_LINES);glEnable(GL_LINE_SMOOTH);int xi = 0;int yi = 0;int zi = 0;//绘制平行于X的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;glVertex3f(pt1x, y, z);glVertex3f(pt2x, y, z);}}//绘制平行于Y的直线for (zi = 0; zi <= num; zi++){float z = _zLen * zi + pt1z;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, pt1y, z);glVertex3f(x, pt2y, z);}}//绘制平行于Z的直线for (yi = 0; yi <= num; yi++){float y = _yLen * yi + pt1y;for (xi = 0; xi <= num; xi++){float x = _xLen * xi + pt1x;glVertex3f(x, y, pt1z);glVertex3f(x, y, pt2z);}}glEnd();}void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH);}我们在ordination()函数中增加绘制x,y,z坐标的代码void CmyopenglView::ordination() {glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH); //设置反走样glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); //设置反走样glEnable(GL_LINE_SMOOTH);glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);glEnable(GL_POL YGON_SMOOTH);glHint(GL_POL YGON_SMOOTH_HINT, GL_NICEST);glRotatef(-45, 0.0, 1.0, 0.0);//网格glPushMatrix();glColor3f(0.9f, 0.9f, 0.9f);glTranslatef(-4, -4, -4);GLGrid(0,0,0,8,0,8,20);glPopMatrix();glPushMatrix();glTranslated(-4,4, -4);glRotatef(90, 1.0, 0.0, 0.0);glColor3f(0.9f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();glPushMatrix();glTranslatef(-4, -4, -4);glRotatef(90, 0.0, 0.0, 1.0);glColor3f(0.0f, 0.9f, 0.0f);GLGrid(0, 0, 0, 8, 0, 8, 20);glPopMatrix();//x//glTranslatef(-2, -2, -2);glColor3f(1.0f, 0.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(3.5, 0.0f, 0.0f);glEnd();glPushMatrix();glTranslatef(3.5, 0.0f, 0.0f);glRotatef(90.0f, 0.0f, 1.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//yglColor3f(0.0f, 1.0f, 0.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 3.5, 0.0f);glEnd();glPushMatrix();glTranslatef(0.0, 3.5, 0.0f);glRotatef(90.0f, -1.0f, 0.0f, 0.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();//zglColor3f(0.0f, 0.0f, 1.0f);glBegin(GL_LINES);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0, 0.0f, 3.5);glEnd();glPushMatrix();glTranslatef(0.0, 0.0f, 3.5);glRotatef(90.0f, 0.0f, 0.0f, 1.0f);glutWireCone(0.027, 0.09, 10, 10);glPopMatrix();glDisable(GL_BLEND);glDisable(GL_LINE_SMOOTH);glDisable(GL_POINT_SMOOTH);glDisable(GL_POL YGON_SMOOTH); }、2.基本三维图形创建点模型/线模型/面模型glColor3f(1.0f, 1.0f, 1.0f);if (model == 1){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidCube(4);}if (model == 2){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if(type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);auxSolidSphere(3.0);}if (model == 3){glPushMatrix();glRotatef(90, -1.0, 0.0, 0.0);if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidCone(3, 3, 100, 100);glPopMatrix();}if (model == 4){if (type == 1)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);if (type == 2)glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);if (type == 3)glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);glutSolidTeapot(2.5);}3.鼠标相应旋转缩放BOOL enableview::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){// TODO: 在此添加消息处理程序代码和/或调用默认值double a = zDelta / 120;if ((scale + a * 0.1) < 10)scale += a * 0.1;this->InvalidateRect(NULL, FALSE);return CView::OnMouseWheel(nFlags, zDelta, pt);}void enableview::OnMouseMove(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值if (nFlags & MK_LBUTTON == TRUE) {//MessageBox("mouse move function triggered!", "attentino", MB_OK);du += point.x - oldmx; //鼠标在窗口x轴方向上的增量加到视点绕y轴的角度上,这样就左右转了h += 0.03f*(point.y - oldmy); //鼠标在窗口y轴方向上的改变加到视点的y坐标上,就上下转了if (h>15.0f) h = 15.0f; //视点y坐标作一些限制,不会使视点太奇怪else if (h<-5.0f) h = -5.0f;oldmx = point.x, oldmy = point.y; //把此时的鼠标坐标作为旧值,为下一次计算增量做准备/*CString debug;debug.Format(_T("h,du= %0.3f %3d\n"), h, du);OutputDebugString(debug);*///OnPaint();this->OnDraw(this->GetDC()); //重绘界面}else if (nFlags & MK_RBUTTON == TRUE){oldmx += point.x - oldmx;oldmy += point.y - oldmy;glTranslatef(oldmx, oldmy, -0.1f);this->OnDraw(this->GetDC());oldmx = point.x, oldmy = point.y;}else {oldmx = point.x, oldmy = point.y;//OutputDebugString(_T("mouse up\n"));}//CView::OnMouseMove(nFlags, point);}4.键盘相应旋转缩放BOOL CmyopenglView::PreTranslateMessage(MSG* pMsg){if (pMsg->message == WM_KEYDOWN) // If a keydown message{if (pMsg->wParam == _T('W')){this->rotate_x += 6.0;if (this->rotate_x > 360)this->rotate_x = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('X')){this->rotate_x += 6.0;if (this->rotate_x < -360)this->rotate_x = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('A')){this->rotate_y -= 6.0;if (this->rotate_y < -360)this->rotate_y = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('D')){this->rotate_y += 6.0;if (this->rotate_y > 360)this->rotate_y = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Z')){this->rotate_z -= 6.0;if (this->rotate_z < -360)this->rotate_z = 360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('E')){this->rotate_z += 6.0;if (this->rotate_z > 360)this->rotate_z = -360;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('Q')){if ((scale + 2) < 10)scale += 2;this->InvalidateRect(NULL, FALSE);}if (pMsg->wParam == _T('R')){scale -= 2;this->InvalidateRect(NULL, FALSE);}}return CView::PreTranslateMessage(pMsg);}5.灯光设置:单方位灯光/多方位光/多种类型光效果// 设置材质颜色GLfloat mat_ambient[] = { 0.6f, 0.6f, 0.6f, 1.0f }; // 蓝色的材质环境光GLfloat mat_diffuse[] = { 0.6f, 0.6f, 0.9f, 1.0f }; // 蓝色的材质漫反射光GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // 全白色的材质镜面反射光GLfloat mat_emission[] = { 0.5f, 0.5f, 0.5f, 1.0f }; // 淡白色的材质辐射光GLfloat no_mat[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 无光(黑色光),用于关闭某种属性光时应用GLfloat no_shininess[] = { 0.0f }; // 无镜面反射GLfloat low_shininess[] = { 5.0f }; // 低镜面反射指数GLfloat high_shininess[] = { 70.0f }; // 高镜面反射指数void CmyopenglView::InitalLigt(){GLfloat light_position1[4] = { -52, -16, -50, 0 };GLfloat light_position2[4] = { -26, -48, -50, 0 };GLfloat light_position3[4] = { 16, -52, -50, 0 };GLfloat direction1[3] = { 52, 16, 50 };GLfloat direction2[3] = { 26, 48, 50 };GLfloat direction3[3] = { -16, 52, 50 };GLfloat light_position4[4] = { 52, 16, 50, 0 };GLfloat light_position5[4] = { 26, 48, 50, 0 };GLfloat light_position6[4] = { -16, 52, 50, 0 };GLfloat direction4[3] = { -52, -16, -50 };GLfloat direction5[3] = { -26, -48, -50 };GLfloat direction6[3] = { 16, -52, -50 };GLfloat color1[4], color2[4], color3[4], color4[4], color5[4], color6[4];glClearColor(1, 1, 1, 0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);if (color_type == 0) { //彩色灯光color1[0] = 1; color1[1] = 0; color1[2] = 0; color1[3] = 1;color2[0] = 0.5; color2[1] = 1; color2[2] = 0; color2[3] = 1;color3[0] = 0; color3[1] = 0; color3[2] = 1; color3[3] = 1;color4[0] = 1; color4[1] = 0; color4[2] = 0; color4[3] = 1;color5[0] = 0.5; color5[1] = 1; color5[2] = 0; color5[3] = 1;color6[0] = 0; color6[1] = 0; color6[2] = 1; color6[3] = 1;GLfloat ambient[4] = { 0.3f, 0.3f, 0.3f, 1.0f };GLfloat material_color[4] = { 1, 1, 1, 0.5f };GLfloat material_specular[4] = { 0.5f, 0.5f, 0.5f, 0.5f };GLfloat material_ambient[4] = { 0.0, 0.0, 0.0, 0.0 };glLightfv(GL_LIGHT3, GL_POSITION, light_position4);glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, direction4);glLightfv(GL_LIGHT3, GL_DIFFUSE, color4);glLightfv(GL_LIGHT3, GL_SPECULAR, color4);glLightfv(GL_LIGHT4, GL_POSITION, light_position5);glLightfv(GL_LIGHT4, GL_SPOT_DIRECTION, direction5);glLightfv(GL_LIGHT4, GL_DIFFUSE, color5);glLightfv(GL_LIGHT4, GL_SPECULAR, color5);glLightfv(GL_LIGHT5, GL_POSITION, light_position6);glLightfv(GL_LIGHT5, GL_SPOT_DIRECTION, direction6);glLightfv(GL_LIGHT5, GL_DIFFUSE, color6);glLightfv(GL_LIGHT5, GL_SPECULAR, color6);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_color);glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128);glDisable(GL_LIGHT0);glDisable(GL_LIGHTING);glEnable(GL_LIGHTING);glEnable(GL_LIGHT3);glEnable(GL_LIGHT4);glEnable(GL_LIGHT5);glDisable(GL_COLOR_MATERIAL);return;}if (color_type == 1){//白色灯光glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);GLfloat m_LightPostion[4] = { 0.0f, 10.0f, 10.0f, 1.0f };GLfloat ambientLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };GLfloat diffuseLight[] = { 0.5, 0.5f, 0.5f, 1.0f };GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glEnable(GL_LIGHT0);glEnable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);}else {glDisable(GL_LIGHT3);glDisable(GL_LIGHT4);glDisable(GL_LIGHT5);glDisable(GL_LIGHTING);glDisable(GL_COLOR_MATERIAL);glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);//glDisable(GL_LIGHTING);GLfloat no_ambientLight[] = { 0.0f, 0.0f, 0.0f, 1.0f }; // 用于关掉默认的全局环境光// 设置光源的颜色GLfloat ambientLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色环境光GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色漫射光GLfloat specularLight[] = { 0.8f, 0.8f, 0.8f, 1.0f }; // 白色镜面反射光GLfloat m_LightPostion[] = { 0.0f, 0.0f, 1.0f, 0.0f }; // 光源起始位置// 1.仅漫射光if (color_type == 12) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); // 关闭材质的环境反射光颜色glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); // 设置mat_diffuse的材质漫反射光glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); //关闭材质的镜面反射光颜色glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); // 设置材质的镜面反射指数为0glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); // 关闭材质的辐射光glEnable(GL_LIGHT0);}// 2.仅镜面光if (color_type == 13) {glEnable(GL_LIGHTING);//glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 3.漫射光与低镜面光if (color_type == 16) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);glEnable(GL_LIGHT0);}// 4.辐射光与低镜面光if (color_type == 18) {glEnable(GL_LIGHTING);glLightModelfv(GL_LIGHT_MODEL_AMBIENT, no_ambientLight); // 关掉默认的全局环境光glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);glLightfv(GL_LIGHT0, GL_POSITION, m_LightPostion);glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);glMaterialfv(GL_FRONT, GL_DIFFUSE, no_mat);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);glEnable(GL_LIGHT0);}}}6.纹理载入映射BOOL CmyopenglView::LoadImageResources() {FILE *File = NULL;AUX_RGBImageRec* textrue_Resource[6];if (model == 5 && type == 51)resource_path[0] = "shuijing.bmp";if(model == 5 && type == 52 )resource_path[0] = "earth.bmp";if (model == 5 && type == 53)resource_path[0] = "painting1.bmp";if (model == 5 && type == 54)resource_path[0] = "5.bmp";/*resource_path[1] = "image/2.bmp";resource_path[2] = "image/3.bmp";resource_path[3] = "image/4.bmp";resource_path[4] = "image/5.bmp";resource_path[5] = "image/6.bmp";*///装载图像文件资源for (int i = 0; i < 6; i++)//如果只需要一张贴图其实resource_path数组只需要一个元素就可以了{File = fopen(resource_path[0], "r");if (!File){//MessageBox(NULL, "加载图像资源文件失败!", "Fail", MB_OK);return FALSE;}fclose(File);CString str = CString(resource_path[0]);USES_CONVERSION;LPCWSTR wszClassName = A2CW(W2A(str));textrue_Resource[i] = auxDIBImageLoad(wszClassName);File = NULL;}//生成纹理glGenTextures(6, texture);for (int i = 0; i < 6; i++){glBindTexture(GL_TEXTURE_2D, texture[i]);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//Use the mipmap textureglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, \textrue_Resource[i]->sizeX, textrue_Resource[i]->sizeY, \GL_RGB, GL_UNSIGNED_BYTE, textrue_Resource[i]->data);//删除堆上的临时图像delete textrue_Resource[i]->data;delete textrue_Resource[i];}return TRUE;}void CmyopenglView::Draw_textrue() {GLUquadricObj* qobj;glClearColor(0.0, 0.0, 0.0, 0.0);glShadeModel(GL_FLAT);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);InitalLigt(); ///初始化光照信息glEnable(GL_TEXTURE_2D);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);glPushMatrix();glTranslatef(0.0f, 0.0f, scale); //滚轮缩放gluLookAt(r*cos(c*du), h, r*sin(c*du), 0, 0, 0, 0, 1, 0); //从视点看远点,y轴方向(0,1,0)是上方向,鼠标拖动glRotatef(this->rotate_x, 1.0, 0.0, 0.0);glRotatef(this->rotate_y, 0.0, 1.0, 0.0);glRotatef(this->rotate_z, 0.0, 0.0, 1.0);if (iao)ordination();glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);qobj = gluNewQuadric();//画球体glBindTexture(GL_TEXTURE_2D, texture[0]);glEnable(GL_TEXTURE_2D);gluQuadricTexture(qobj, GL_TRUE);//纹理函数if (type == 51){glBegin(GL_QUADS);// Front FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);// Back FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, -3.0f);// Top FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, 3.0f, -3.0f);// Bottom FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, -3.0f, 3.0f);// Right faceglTexCoord2f(0.0f, 0.0f); glVertex3f(3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(3.0f, 3.0f, -3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(3.0f, -3.0f, 3.0f);// Left FaceglTexCoord2f(0.0f, 0.0f); glVertex3f(-3.0f, -3.0f, -3.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f(-3.0f, -3.0f, 3.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f(-3.0f, 3.0f, 3.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-3.0f, 3.0f, -3.0f);glEnd();}if( type == 52 )gluSphere(qobj, 4, 60, 60);//二次曲面qobjif( type == 53 )gluCylinder(qobj, 3.5, 3.5, 6, 26, 23);if( type == 54 )gluCylinder(qobj, 3.5, 0.0, 6, 26, 23);glPopMatrix();glDisable(GL_TEXTURE_2D);}6.读取obj模型我只是简单的读取vt,vn,f等基本参数void CmyopenglView::ReadObj(char* Filename) {VN.clear();V.clear();VT.clear();F.clear();FQ.clear();ifstream in(Filename);string aline; //逐行读入string erase;while (getline(in, aline)){if (aline[0] == 'v'){if (aline[1] == 'n') //vn{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;VN.push_back(v);}else if (aline[1] == 't')//vt{istringstream sin(aline);Texture v;sin >> erase >> v.s >> v.t;VT.push_back(v);}else //v{istringstream sin(aline);V ertex v;sin >> erase >> v.x >> v.y >> v.z;V.push_back(v);}}else if (aline[0] == 'f'){istringstream sin(aline);sin >> erase;vector<string> strvector;string temp;while (sin >> temp) {strvector.push_back(temp);}if (strvector.size() == 3) {//三角面片Face fff;for (int count = 0; count < 3; count++) {string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}F.push_back(fff);}else if (strvector.size() == 4){FaceQ fff;for (int count = 0; count < strvector.size(); count++) { string kkk = strvector[count];int i = 0;int num = 0;//顶点索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.v[count] = num;i++;num = 0;//vtnum = 0;for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vt[0] = num;i++;num = 0;//法向量索引for (; i < kkk.size() && kkk[i] != '/'; i++)num = num * 10 + kkk[i] - '0';fff.vn[count] = num;}FQ.push_back(fff);}}}}绘制obj模型:void CmyopenglView::OnReadobj(){model = 6;wchar_t filters[] =L"3D模型文件(*.obj)\|*.obj|所有文件(*.*)|*.*||";CFileDialog fileDlg(TRUE, NULL, NULL,OFN_HIDEREADONL Y, filters);if (fileDlg.DoModal() == IDOK){CString strBuf = fileDlg.GetPathName();USES_CONVERSION;char *Filename = T2A(strBuf.GetBuffer(0));ReadObj(Filename);}stringstream ss;ss <<"OK!";string str;ss >> str;CString s;s = str.c_str();MessageBox(s);float min_x, min_y, min_z, max_x, max_y, max_z;min_x = min_y = min_z = 10000000;max_x = max_y = max_z = -1000000;for (int i = 0; i < V.size(); i++){min_x = min(min_x, V[i].x);min_y = min(min_y, V[i].y);min_z = min(min_z, V[i].z);max_x = max(max_x, V[i].x);max_y = max(max_y, V[i].y);max_z = max(max_z, V[i].z);}worldx = (min_x + max_x) / 2;worldy = (min_y + max_y) / 2;worldz = (min_z + max_z) / 2;type = 1;Invalidate();CDC* ppDC = GetWindowDC();OnDrawGL(ppDC);// TODO: 在此添加命令处理程序代码}void CmyopenglView::Draw_obj(){if (type == 1) {if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else {for (int i = 0; i < F.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glBegin(GL_LINE_LOOP);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}else if (type == 3) {glBegin(GL_POINTS);for (int i = 0; i < V.size(); i++)glV ertex3f(V[i].x, V[i].y, V[i].z);glEnd();}else{if (!VN.empty()) {for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glNormal3f(VN[F[i].vn[j] - 1].x, VN[F[i].vn[j] - 1].y, VN[F[i].vn[j] - 1].z);glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glNormal3f(VN[FQ[i].vn[j] - 1].x, VN[FQ[i].vn[j] - 1].y, VN[FQ[i].vn[j] - 1].z);glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}else{for (int i = 0; i < F.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_TRIANGLES);for (int j = 0; j < 3; j++) {glV ertex3f(V[F[i].v[j] - 1].x, V[F[i].v[j] - 1].y, V[F[i].v[j] - 1].z);}glEnd();}for (int i = 0; i < FQ.size(); i++) {glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);glBegin(GL_QUADS);for (int j = 0; j < 4; j++) {glV ertex3f(V[FQ[i].v[j] - 1].x, V[FQ[i].v[j] - 1].y, V[FQ[i].v[j] - 1].z);}glEnd();}}}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

详解OpenGL的坐标系、投影和几何变换 作者:charlee 按:我也是在迷茫中走过来的,初学OpenGL时,略微了解了一些有关变换的基本知识,但是却不知道具体的使用方法,因此经常需要在布置场景时反复调整各种参数。当我终于有一天明白了它们的用法时,就觉得应该把这些心得体会写下来,让那些和我一样曾经迷茫过的人能够迅速地找到出路。本文的读者对象为那些初学OpenGL,了解了一些坐标系、几何变换等基本知识,但是又不知道具体应该如何运用这些操作的人。如果你对OpenGL一无所知,建议你先去学学OpenGL的基本知识。

1 坐标系 OpenGL中使用的坐标系有两种,分别为世界坐标系和屏幕坐标系。世界坐标系即OpenGL内部处理时使用的三维坐标系,而屏幕坐标系即为在计算机屏幕上绘图时使用的坐标系。 通常,OpenGL所使用的世界坐标系为右手型,如下图所示。

从计算机屏幕的角度来看,x轴正方向为屏幕从左向右,y轴正方向为屏幕从下向上,z轴正方向为屏幕从里向外。而进行旋转操作时需要指定的角度θ的方向则由右手法则来决定,即右手握拳,大拇指直向某个坐标轴的正方向,那么其余四指指向的方向即为该坐标轴上的θ角的正方向(即θ角增加的方向),在上图中用圆弧形箭头标出。

2 投影 将世界坐标系中的物体映射到屏幕坐标系上的方法称为投影。投影的方式包括平行投影和透视投影两种。 平行投影的投影线相互平行,投影的结果与原物体的大小相等,因此广泛地应用于工程制图等方面。 透视投影的投影线相交于一点,因此投影的结果与原物体的实际大小并不一致,而是会近大远小。因此透视投影更接近于真实世界的投影方式。

A B A' B' 平行投影 投影面(屏幕) A B A'

B' 透视投影 投影面(屏幕) 投影中心

x z

y 0 2.1 平行投影 OpenGL中使用下面的函数来设置投影方式为平行投影。 glOrtho(xleft, xright, ybottom, ytop, znear, zfar); 各参数的含义如下图所示。

注意,只有位于立方体之内的物体才可见。 2.2 透视投影 OpenGL中使用下面的函数来设置投影方式为透视投影。 gluPerspective(fovy, aspect, znear, zfar); 各参数的含义如下图所示。

fovy为四棱台的顶角,aspect为投影面的纵横比,znear和zfar为四棱台的顶面和底面到视点的距

离(注意不是z坐标)。 注意,只有位于四棱台之内的物体才可见。

3 几何变换 OpenGL中可以使用的几何变换有平移、旋转、缩放三种。 glTranslatef(x, y, z); 该函数可以实现平移变换,x、y、z为各坐标轴上的平移量。 glRotatef(θ, x, y, z); 该函数实现旋转变换。θ为旋转角度,x、y、z为旋转轴。旋转方向由右手法则决定(参见第一节“坐

投影面 投影立方体的六个面分别为: 左:z=znear(投影面) 右:z=zfar 上:y=ytop 下:y=ybottom 前:x=xright 后:x=xleft

w h

znear zfar

fovy

视点 (投影中心)

aspect=w/h 标系”)。 glScalef(x, y, z); 该函数实现缩放变换。x、y、z为各轴方向的扩大量。若为负值,则沿着坐标轴的反方向进行缩放。

实际上,几何变换并不是针对坐标系中的某个物体进行变换,而是对整个坐标系进行变换。进行绘图时,世界坐标系上的点将以如下的方式被投影到屏幕坐标系上:





11'''12zyxAAAPzyx

n

其中(x y z 1)T为该点在世界坐标系中的坐标,(x' y' z' 1)T为该点在屏幕坐标系上的投影的坐标。P为投影变换矩阵,An为几何变换矩阵。在处理变换和投影时,OpenGL先把几何变换矩阵A1、A2、„、An

从左侧依次与点坐标矩阵相乘,最后再将投影矩阵从左侧与经过几何变换之后的点坐标相乘,即得到该点

的屏幕坐标。也就是说,在OpenGL中进行几何变换的方式为,首先通过glTranslatef、glRotatef、glScalef等函数设置好几何变换矩阵(相当于对坐标系进行了变换),然后再进行绘图,那么图形的投影坐标将受到设置好的几何变换矩阵所影响而显现出几何变换的效果;而并不是首先进行绘图然后再通过几何变换函数对已经存在的图形进行变换。 变换的一般形式如下式所示:





111'''44434241343332312423222114131211zyxAzyxaaaaaaaaaaaaaaaazyx

常见的变换矩阵如下。 (1)平移变换





1000100010001zyxttt

(2)旋转变换 沿x轴旋转





10000cossin00sincos00001

xxxx



沿y轴旋转 



10000cos0sin00100sin0cos

yyyy



 沿z轴旋转 

1000010000cossin00sincos

zzzz





(3)缩放变换 



1000000000000zyxsss

(4)平行投影(投影到xy平面的情况) 



1000010000100001

(5)透视投影(投影到xy平面的情况。投影中心为z轴上的点(0, 0, R))





10000000000000zRRzRR

在实际编程中,为了保存几何变换和投影变换的操作,OpenGL维护两个栈,即投影变换栈和几何变换栈。栈中保存的元素即为投影变换和几何变换的变换矩阵。使用下面的函数可以在两个栈之间进行切换: 切换当前操作的栈为投影变换栈:glMatrixMode(GL_PROJECTION); 切换当前操作的栈为几何变换栈:glMatrixMode(GL_MODELVIEW); 此外,下面的函数可以清除当前操作的栈中的内容,并向栈中压入一个单位矩阵: glLoadIdentity();

两个栈之间的关系如下图所示:

一般情况下,我们在进行OpenGL初始化时都要执行下面的命令: glMatrixMode(GL_PROJECTION); // 切换到投影变换栈

P 投影变换栈 1'''zyx× An„A2A1 „ 几何变换栈 „ × 



1zyxglLoadIdentity(); // 初始化投影变换栈 gluPrespective(30.0, aspect, 1.0, 50.0); // 压入透视投影矩阵 glMatrixMode(GL_MODELVIEW); // 切换到几何变换栈

另外,在调用glMatrixMode(GL_MODELVIEW)时,系统会自动将几何变换栈清空并压入单位矩阵,因此不必再调用glLoadIdentity()函数。 对于几何变换栈,还有以下两个常用的操作: glPushMatrix(); // 保存当前坐标系 glPopMatrix(); // 恢复当前坐标系 在调用几何变换操作时,OpenGL将该几何变换操作的变换矩阵与当前栈的栈顶元素相乘,得到一个新的矩阵并将其作为几何变换栈的栈顶。

作为例子,我们来看下面的这段程序。 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0, aspect, 1.0, 50.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(0.0, 0.0, -20.0); glPushMatrix(); glTranslatef(0.0, 1.0, 0.0); myWireCylinder(1.0, 2.0, 12); glTranslatef(0.0, 1.0, 0.0); glRotatef(-90.0, 1.0, 0.0, 0.0); glutWireCone(1.0, 2.0, 12, 3); glPopMatrix(); glTranslatef(0.0, -1.0, 0.0); myWireCylinder(1.0, 2.0, 12); glPopMatrix();

下面我们来分析一下该程序执行过程中两个栈的变化情况。图中左侧的栈为透视变换栈,右侧的栈为几何变换栈。黄色表示当前操作栈。I表示单位矩阵,P表示投影变换矩阵,T为平移变换矩阵,R为旋转变换矩阵,S为缩放变换矩阵。 glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluPerspective(30.0, aspect, 1.0, 50.0); P

I

相关文档
最新文档