本节将演示在3D空间中绘制图形的几个简单实例:

    (1)在3D空间内绘制圆锥体:

#include <GL/glut.h>
#include <math.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#define PI 3.1416
GLfloat xRot = ;
GLfloat yRot = ;
GLfloat zRot = ; void Init(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 1.0f, 0.0f);
// 把着色模式设置为单调着色
glShadeModel(GL_FLAT); //glShadeModel(GL_SMOOTH);
// 把顺时针环绕的多边形设为正面,这与默认是相反的,因为我们使用的是三角形扇
glFrontFace(GL_CW);
glOrtho(-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
}
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP)
xRot -= 5.0f; if (key == GLUT_KEY_DOWN)
xRot += 5.0f; if (key == GLUT_KEY_LEFT)
yRot -= 5.0f; if (key == GLUT_KEY_RIGHT)
yRot += 5.0f; if (key> 356.0f)
xRot = 0.0f; if (key< -1.0f)
xRot = 355.0f; if (key> 356.0f)
yRot = 0.0f; if (key< -1.0f)
yRot = 355.0f; if (key==GLUT_KEY_F1) //绕着z轴旋转
zRot+= 5.0f; // 使用新的坐标重新绘制场景
glutPostRedisplay();
}
void RenderScene()
{
// 存储坐标和角度
GLfloat x, y, z, angle,x1,y1;
// 用于三角形颜色的交替设置
int iPivot = ;
// 用默认颜色设置背景色,并清除深度缓冲区(必须的,因为3D空间有视景深度)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//打开剔除功能(背面剔除,它用于消除一个表面的背面)
//glEnable(GL_CULL_FACE);
// 打开深度测试,如果不打开深度测试,3D锥体的显示就会与现实情况不符合
glEnable(GL_DEPTH_TEST); // 保存矩阵状态并旋转
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f); glBegin(GL_TRIANGLE_FAN);
// 三角形扇的共享顶点,z轴中心点上方
glVertex3f(0.0f,0.0f,0.75);
for (angle = 0.0f; angle < (2.0f * PI + PI / 8.0f); angle += (PI / 8.0f)) {
// 计算下一个顶点的位置
x = 0.50f * sin(angle);
y = 0.50f * cos(angle);
if ((iPivot % ) == ) {
glColor3f(1.0f, 1.0f, 0.0f);
}
else{
glColor3f(0.0f, 1.0f, 1.0f);
}
// 增加基准值,下次改变颜色
++iPivot;
// 指定三角形扇的下一个顶点
glVertex2f(x, y);
}
glEnd(); // 绘制一个新的三角形扇,作为覆盖圆锥的底
glBegin(GL_TRIANGLE_FAN);
// 三角形扇的共享顶点,中心位于原点
glVertex3f(0.0f, 0.0f,0.0f);
for (angle = 0.0f; angle < (2.0f * PI + PI / 8.0f); angle += (PI / 8.0f)) {
// 计算下一个顶点的位置
x = 0.50f * sin(angle);
y = 0.50f * cos(angle);
if ((iPivot % ) == ) {
glColor3f(0.5f, 0.0f, 0.5f);
}
else{
glColor3f(1.0f, 0.0f, 1.0f);
}
// 增加基准值,下次改变颜色
++iPivot;
// 指定三角形扇的下一个顶点
glVertex2f(x, y);
}
glEnd();
glPopMatrix();
glutSwapBuffers();
}
int main(int argv,char *argc[]){ glutInit(&argv,argc);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutInitWindowSize(,);
glutInitWindowPosition(,);
glutCreateWindow("3D空间绘制圆锥面");
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
Init();
glutMainLoop();
}

按F1键绕z轴旋转,按方向键绕x轴或y轴旋转:

    (2)在3D空间中模拟地球环绕太阳旋转:

#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.1416
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
static int year = ; void init(void)
{
glClearColor(0.2, 0.2, 0.2, 1.0);
glShadeModel(GL_FLAT);
}
void paintLoopPlant()
{
GLfloat x, z; int i;
glColor3f(0.0f,1.0f,0.5f);
glLineWidth(2.0f);
glBegin(GL_LINE_LOOP);
for (i = ; i < ;i++)
{
x = 0.35*sin(i * * PI / -PI);
z = 0.35*cos(i * * PI / -PI);
glVertex3f(x,,z);
}
glEnd(); glLineWidth(5.0f);
glColor3f(0.5,,);
glBegin(GL_LINE_LOOP);
for (i = ; i < ; i++)
{
x = 3.5*sin(i * * PI / )-3.5;
z = 3.5*cos(i * * PI / );
glVertex3f(x, , z);
}
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(, 0.0, 0.0);//设置太阳的颜色
glPushMatrix();

glPointSize(1.0f);
//在坐标系中央画太阳
glutWireSphere(0.8, , );
//给太阳进平移
glRotatef((GLfloat)year, 0.0, 1.0, 0.0);
glTranslatef(3.5, 0.0, 0.0);
//画地球
glColor3f(, 0.2, 1.0);
glutWireSphere(0.15, , );
paintLoopPlant(); glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(, , (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 6.0, 5.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 'y':
year = (year + ) % ;
break;
case 'Y':
year = (year - ) % ;
break;
case :
exit();
break;
default:
break;
}
glutPostRedisplay();
} int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(, );
glutInitWindowPosition(, );
glutCreateWindow("RotateAroundSun");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop(); return ;
}

    (3)在3D空间用OpenGL自带的库函数绘制立方体:

#include <GL/glut.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"") GLfloat yRot = ; //用来画一个坐标轴的函数
void axis(double length)
{
glColor3f(1.0f, 1.0f, 1.0f);
glPushMatrix();
glBegin(GL_LINES);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, length);
glEnd();
//将当前操作点移到指定位置
glTranslated(0.0, 0.0, length - 0.2);
glColor3f(1.0, 0.0, 0.0);
glutWireCone(0.04, 0.3, , );
glPopMatrix();
}
void paint(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glOrtho(-2.0, 2.0, -2.0, 2.0, -, );
glPointSize();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.3, 1.6, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //画坐标系
axis(); glPushMatrix();
glRotated(90.0, , 1.0, );//绕y轴正方向旋转90度
axis();
glPopMatrix(); glPushMatrix();
glRotated(-90.0, 1.0, 0.0, 0.0);//绕x轴负方向旋转
axis();
glPopMatrix(); glPushMatrix();//旋转除坐标轴之外的物体
glRotated(yRot, 0.0, yRot, 0.0);
glPushMatrix();
glColor3f(0.0f, 0.0f, 1.0f);
glTranslated(0.125, 0.125, 0.125);
glutWireCube(0.25);
glPopMatrix(); glPushMatrix();
glTranslated(1.125,0.125,0.125);
glutWireTeapot(0.25);
glPopMatrix(); glPushMatrix();
glTranslated(0.125, 0.125, 1.125);
glutWireSphere(0.25, , );
glPopMatrix(); glPushMatrix();
glTranslated(1.125,0.125,1.125);
glRotated(-, 1.0, 0.0, 0.0);
glutWireTorus(0.1, 0.25, , );
glPopMatrix(); glPushMatrix();
glTranslated(0.125, 1.125, 0.125);
glScaled(0.5*0.25, 0.5*0.25, 0.5*0.25);
glRotated(-, 0.0, 0.0, 1.0);
glutWireDodecahedron();
glPopMatrix(); glPushMatrix();
glTranslated(0.0, 1.0, 1.0);
GLUquadricObj * quadricObj = gluNewQuadric();
gluQuadricDrawStyle(quadricObj, GLU_LINE);
gluCylinder(quadricObj, 0.2, 0.2, 0.3, , );
glRotated(-, 0.0, 0.0, 0.0);
glPopMatrix(); glPopMatrix();//用来整体绕y轴旋转
glutSwapBuffers();
}
void Init()
{
glClearColor(0.8,0.8,0.8,1.0);
}
void reshape(int w, int h)
{
glViewport(, , (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.3, 1.6, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_LEFT)
yRot -= 5.0f; if (key == GLUT_KEY_RIGHT)
yRot += 5.0f; if (key> 356.0f)
yRot = 0.0f; if (key< -1.0f)
yRot = 355.0f;
glutPostRedisplay();
}
int main(int argv, char *argc[])
{
glutInit(&argv, argc);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(, );
glutInitWindowPosition(, );
glutCreateWindow("3D空间绘制各种系统自带立方体");
Init();
glutDisplayFunc(paint);
glutReshapeFunc(reshape);
glutSpecialFunc(SpecialKeys);
glutMainLoop();
}

在这个例子下按左右方向键也是可以让立方体绕y轴旋转的,在此不做演示。

    (4)相关知识:

1)OpenGL中的空间变换:(http://www.cnblogs.com/chengmin/archive/2011/09/12/2174004.html)

在使用OpenGL的三维虚拟程序中,当我们指定了模型的顶点之后,在屏幕上显示它们之前,一共会发生3种类型的变换:

视图变换、模型变换、投影变换。
1.视图变换:指定观察者(摄像机)的位置;
2.模型变换:在场景中移动物体;
3.投影变换:改变可视区域的大小;
视口变换:这是一种伪变换,它对窗口上的最终输出进行缩放。

1.视觉坐标:

  它表示一种虚拟的固定坐标系统,通常作为一种参考系使用。它是根据观察者(摄像机)的角度而言的,与可能发生的变换无关。我们接下来所讨论的所有变换都是根据它们相对于视觉坐标的效果进行描述的。

  用OpenGL在3D空间中进行绘图时,使用的是笛卡尔坐标系统。在不进行任何变换的情况下,这个坐标系统与视觉坐标系相同。

2.视图变换:

这是场景中所应用的第一个变换,它用于确定场景的观察点(拍摄点)。视图变换允许把观察点放在自己所希望的任何位置(观察点的位置任意),并允许在任何方向上观察场景(观察点的朝向任意)。确定视图变换就像在场景中放置照相机并让它指向某个方向。

  作为总体原则,在进行任何其他变换之前必须先指定视图变换。因为视图变换的效果相当于根据视觉坐标系统来移动当前所使用的坐标系统。然后,根据最新修改的坐标系统,进行其它所有的后续变换。

3.模型变换

  它可以移动物体,对它们进行旋转、平移或者缩放。并且,缩放可以是非一致的(物体的各个方向根据不同的数值进行伸缩)。 场景或物体的最终外观很大程度上取决于模型变换的应用顺序。因为每次变换都是在上次变换执行的基础上进行的。

4.投影变换:

  它是在模型视图变换之后应用于物体的顶点之上的。它实际上定义了可视区域,并建立了裁剪平面。其中,投影又有两种不同的类型:正投影(平行投影)和透视投影。正投影通常用于2D绘图,此时你所需要的是像素和绘图单位之间的准确对应。透视投影则用于渲染那些包含了需要应用透视缩短的物体的场景。并且在大多数情况下,3D图形所使用的都是透视投影。

下面是2D投影变换与3D透视投影变换的对比:

5.视口变换

  最终,场景的二维投影将被映射到屏幕上的某个窗口。这种到物理窗口坐标的映射是最后一个完成的变换,称为视口变换。

2)Win窗口坐标二维坐标与OpenGl的世界坐标:

1.Win的屏幕坐标的坐标系: 左上为坐标系原点,正右为X轴正方向, 正下方为Y轴正方向。视图类的窗口是这样的,如果是FrameWork的绘图区,则需要包含工具栏和状态栏的区域,二者是不一样的。

2.OpenGL中的屏幕坐标:以左下角为原点,正右方为x轴正方向,正上方为y轴正方向。

墨卡托坐标变换

      OPENGL-----3D到2D坐标变换 

      OPENGL-----2D到3D坐标变换

OpenGL学习进程(9)在3D空间的绘制实例的更多相关文章

  1. OpenGL学习进程(12)第九课:矩阵乘法实现3D变换

    本节是OpenGL学习的第九个课时,下面将详细介绍OpenGL的多种3D变换和如何操作矩阵堆栈.     (1)3D变换: OpenGL中绘制3D世界的空间变换包括:模型变换.视图变换.投影变换和视口 ...

  2. OpenGL学习进程(10)第七课:四边形绘制与动画基础

        本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图 ...

  3. OpenGL学习进程(8)第六课:点、边和图形(三)绘制图形

    本节是OpenGL学习的第六个课时,下面介绍OpenGL图形的相关知识:     (1)多边形的概念: 多边形是由多条线段首尾相连而形成的闭合区域.OpenGL规定,一个多边形必须是一个“凸多边形”. ...

  4. OpenGL学习进程(7)第五课:点、边和图形(二)边

    本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概 ...

  5. OpenGL学习进程(11)第八课:颜色绘制的详解

        本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...

  6. OpenGL学习进程(6)第四课:点、边和图形(一)点

    本节是OpenGL学习的第四个课时,下面介绍OpenGL点的相关知识:     (1)点的概念:     数学上的点,只有位置,没有大小.但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点 ...

  7. OpenGL学习进程(4)第二课:绘制图形

    本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) ...

  8. OpenGL学习进程(5)第三课:视口与裁剪区域

    本节是OpenGL学习的第三个课时,下面介绍如何运用显示窗体的视口和裁剪区域:     (1)知识点引入:     1)问题现象: 当在窗体中绘制图形后,拉伸窗体图形形状会发生变化: #include ...

  9. OpenGL学习进程(3)第一课:初始化窗体

        本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:     (1)显示一个有蓝色背景的窗体: #include <GL/glut.h> #include <st ...

随机推荐

  1. 6.5安装nagios

    最近因为,科研需要,接触上了Nagios,这里,我将安装笔记做个详解.为自己后续需要和博友们学习! VMware workstation 11 的下载 VMWare Workstation 11的安装 ...

  2. 使用.NET JustDecompile来反编译你的程序代码

    前言 在项目的进行中有时会碰到需要去了解由第三方所开发的程序代码或者因为年久已经遗失原始码的程序,由于因为是别人写的所以我们并没有原始码可以直接阅读,碰到这种情况我们就需要去反编译这些程序及 DLL ...

  3. OBS (open boardcast server)结构分析

    一,简介 OBS(open boardcast server),是一个用于直播的开源软件. 官方网站:https://obsproject.com/ 代码托管地址:https://github.com ...

  4. JDK之ThreadLocal分析

    ThreadLocal是在是Thread的一个局部变量,今天我来分析了一下这个类 先看ThreadLocal的set方法 public void set(T value) { Thread t = T ...

  5. NetBeans执行项目报错

    1.错误描写叙述 严重: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start ...

  6. 1878: [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4420  Solved: 2199[Submit][Statu ...

  7. QL 获取当前日期,年、月、日、周、时、分、秒

    ?select GETDATE() as '当前日期', DateName(year,GetDate()) as '年', DateName(month,GetDate()) as '月', Date ...

  8. C#设计模式-单实例

    单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点. 1.经典的模式 namespace singleClass { class ...

  9. <2013 06 29> In Deutschland. Thinking in Mechanism, EE, CS, etc.

    一 在德国近一个月了,主要去了慕尼黑周边的几个景点,天鹅城堡啊,国王湖啊,然后就是在市区逛,玛丽安广场,伊萨河,英国公园,德意志博物馆... ... 总体的印象是非常好的,只是自己不怎么懂德语,但这里 ...

  10. 小白学linux命令

    小白是景女神全栈开发股份有限公司的一名财务实习员工,经过3个月的实习期,小白是过五关斩六将啊!终于成为了公司的一名正式员工,而且收到了景总亲自发来贺喜的邮件:“欢迎你加入大家庭,公司也本着员工全面发展 ...