本节将演示在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. Javascript模块规范

    因为有了模块,就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是有一个前提,就是大家必须以同样的方式编写模块. 目前,通行的Javascript模块规范共有两种:CommonJS和AMD ...

  2. Python 安装 MaxMind GeoLite City

    1.先安装 geoip c library  geoip c library >= 1.4.6 installed on your machine. >= 1.4.6 installed ...

  3. git忽略已经被提交的文件,以及如何恢复追踪

    问题描述 之前在提交代码时,.gitignore 没有填写完整,导致idea编辑器的配置文件夹.idea被提交了 然后每次运行本地项目,都会在.idea文件夹下生成一堆文件,这时发现问题,将.idea ...

  4. 集合映射Set(使用xml文件)

    如果持久类具有Set对象,可以在映射文件中使用set元素映射Set集合. set元素不需要索引元素. List和Set之间的区别是: Set只存储唯一的值. 我们来看看我们如何在映射文件中实现集合: ...

  5. oracle定时job

    转载自:http://www.cnblogs.com/hoojo/p/oracle_procedure_job_interval.html Oracle job procedure 存储过程定时任务 ...

  6. Unity官方发布热更新方案性能对照

    孙广东  2016.3.11 Unity应用的iOS热更新 作者:丁治宇 Unity TechnologiesChina Agenda •  什么是热更新 •  为何要热更新 •  怎样在iOS 上对 ...

  7. dll 在进程中怎么区分的

    平时一直没想过这个问题,今天在测试输入法注入的时候才发现windows下dll在进程中是以名字区分的,即使是完全一模一样的DLL. 具体详情,容我慢禀 :   需求是这样的,只能含有一个a.DLL,这 ...

  8. CGAffineTransform函数旋转操作

    本文转载至  http://blog.sina.com.cn/s/blog_923fdd9b0101ahyx.html   首先获取UITableView的CGAffineTransform函数:CG ...

  9. TestClass必须是public的

    运行一个测试类遇到一下问题: namespace TestSample.Sample {     [TestClass]     class CynthiaTest     {         [Te ...

  10. Mybatis+MySql 一个标签中执行多条sql语句 这个坑 ,我心中有一句MMP

    解决办法 转自网友: 亲测 解决了问题@ MySql默认是不支持这种骚操作的,但是并不代表不能实现,只需要在jdbc的配置文件中稍做配置: driver=com.mysql.jdbc.Driverur ...