本节将演示在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. ZOJ 3962 Seven Segment Display 16进制的八位数加n。求加的过程中所有的花费。显示[0,F]有相应花费。

    Seven Segment Display Time Limit: Seconds Memory Limit: KB A seven segment display, or seven segment ...

  2. wchar与char字符转换的探究

    在Xcode 模拟器环境下.測试wchar_t与char的转换: void convert_test() { setlocale(LC_ALL, "zh_CN.UTF-8"); c ...

  3. In the shell, what does “ 2>&1 ” mean?

    In a Unix shell, if I want to combine stderr and stdout into the stdout stream for further manipulat ...

  4. OpenCV学习笔记二:OpenCV模块一览

    注:本系列博客基于OpenCV 2.9.0.0 一,一览图: 二,模块: /* 基础库 */ 1,opencv_core(链接) ,opencv最基础的库.包含exception,point,rect ...

  5. Scrapy爬虫笔记

    Scrapy是一个优秀的Python爬虫框架,可以很方便的爬取web站点的信息供我们分析和挖掘,在这记录下最近使用的一些心得. 1.安装 通过pip或者easy_install安装: 1 sudo p ...

  6. 如何通过sequel pro导入.sql脚本

    1.参考地址     https://zhidao.baidu.com/question/985373253463808219.html

  7. Machine Learning第十周笔记:大规模机器学习

    博客已经迁移到Marcovaldo's blog (http://marcovaldong.github.io/) 刚刚完毕了Andrew Ng在Cousera上的Machine Learning的第 ...

  8. IOS开发之----常用加密方法

    本文转载至 http://blog.csdn.net/wildfireli/article/details/23191983 (AES.MD5.Base64) 分类: iPhone 2014-04-0 ...

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

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

  10. if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary

    if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary