使用三角形绘制3D模型



三角形是基本的多边形,任何多变形都能由三角形组成。三角形是由三个顶点的连线组成。三个点分别是v0;v1;v2。

1、绕法

从某个顶点开始,有两种连线的方法,顺时针和逆时针,这是两种不同的绕法。

2、连接多个三角形

三角形能拼出任何多边形平面或曲面。所以对于平面或曲面,我们只需要保存组成这个面的所有三角形的顶点以及拼法即可。例如某个面有n个三角形组成,我们需要保存3n个顶点。如果我们我比较好的方法,可以减少保存顶点的个数,那么将大大减少内存。以下两种方法能够实现我们的想法。

(1)三角条



如上图,该面由三个三角形组成,假设我们以逆时针为正方形的绕法。

绘制第一个三角形式,我们需要知道三个顶点v0;v1;v2;绘制第二个三角形是,由于应用到第一个三角形的两个顶点v1;v2;所以我们只需要知道(保存)一个顶点(v3)即可;同样的方法绘制第三个三角形。理想情况下,按这种方法,一个面如果由n个三角形拼接成,那么我们只需要保存n+2个顶点即可。

这种方法是以新绘制的三角形利用到前面最后一次绘制的三角形的最后两个顶点。

(2)三角扇形



这种方法跟上面的方法不同的地方是,这里的新绘制的三角形利用到前面已经绘制三角形的顶点是v0(初始顶点)和前面最后一次增加的顶点。如上图所示。

与第一种方法一样,这种方法在理想的情况向,需要保存的顶点个数为n+2。

3、使用三角扇形绘制一个锥体

(1)以锥体的顶点为原点,通过三角扇形的方法绘制锥体的侧面

a)设置以顺时针的方向为正方向:

glFrontFace(GL_CW);

b)设置以三角扇的绘制方法:

glBegin(GL_TRIANGLE_FAN);

c)绘制侧面

glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 75.0f); int ipvot = 0;
for(angle = 0.0f; angle < (2.0f * PI); angle += (PI / 8.0f))
{
x = 50.0f * sin(angle);
y = 50.0f * cos(angle); if(ipvot % 2 == 0) glColor3f(0.0f, 1.0f, 0.0f);
else glColor3f(1.0f, 0.0f, 0.0f); ipvot++; glVertex3f(x, y, 0.0f); }
glEnd();

d)绘制底面

glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 0.0f); for(angle = 0; angle < (2.0f * PI); angle += (PI / 8.0f))
{
x = 50.0f * sin(angle);
y = 50.0f * cos(angle); if(ipvot % 2 == 0) glColor3f(0.0f, 1.0f, 0.0f);
else glColor3f(1.0f, 0.0f, 0.0f); ipvot++; glVertex3f(x, y, 0.0f);
} glEnd();

前面的操作得到的效果图如下:

这个图是以直代曲的方法,上面使用的是16个三角形去模拟侧面,当以100个或者更多个三角形去模拟侧面时,想过会更好,当然执行时间也需要花费更多。

3)通过注册上下左右按钮空时模型旋转

if(key == GLUT_KEY_UP)
xRot -= 5.0f; else if(key == GLUT_KEY_DOWN)
xRot += 5.0f; else if(key == GLUT_KEY_LEFT)
yRot -= 5.0f; else if(key == GLUT_KEY_RIGHT)
yRot += 5.0f; if(xRot < 0) xRot = 355.0f;
if(xRot > 360.0f) xRot = 0.0f; if(yRot < 0) yRot = 355.0f;
if(yRot > 360.0f) yRot = 0.0f;
//改变模型角度后需要从新绘画到窗口上去
glutPostRedisplay();

效果图如下图所示:

4、感想

太久没做OpenGL实验了,很多基本知识忘记了。这次的实验原理很简单,但在实验的过程中还是有遇到了一点小困难,经过查找资料和思考,顺利完成这次实验。编程需要多练习,很多知识,你似乎很容易就看明白了,可是在实验的过程中,你会发现很多小细节在实验前你没注意到。

5、完整代码

#include <windows.h>
#include <gl/glut.h>
#include<math.h> const GLfloat PI = 3.1415f;
GLfloat xRot = 0.0f;
GLfloat yRot = 0.0f; void rendererScene(void);
void changeWindowSize(GLsizei w, GLsizei h);
void setupRC(void);
void rotateMode(int key, int x, int y); int main(int argc, char* argv[])
{
//设置显示模式
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //设置窗口大小
glutInitWindowSize(300, 300); //设置窗口在屏幕上的位置
glutInitWindowPosition(200, 200); //创建窗口标题
glutCreateWindow("三角形绘3D模型"); //注册显示窗口时回调渲染函数
glutDisplayFunc(rendererScene); glOrtho(-100.0f, 100.0f, -100.0f, 100.0f, -100.0f, 100.0f); //注册窗口大小改变时回调函数
glutReshapeFunc(changeWindowSize); //注册点击上下左右方向按钮时回调rotateMode函数
glutSpecialFunc(rotateMode); setupRC(); //消息循环(处理操作系统等的消息,例如键盘、鼠标事件等)
glutMainLoop();
return 0;
} /**
渲染函数
*/
void rendererScene(void)
{
GLfloat x, y, angle;
glClear(GL_COLOR_BUFFER_BIT); glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f); glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 75.0f); int ipvot = 0;
for(angle = 0.0f; angle < (2.0f * PI); angle += (PI / 8.0f))
{
x = 50.0f * sin(angle);
y = 50.0f * cos(angle); if(ipvot % 2 == 0) glColor3f(0.0f, 1.0f, 0.0f);
else glColor3f(1.0f, 0.0f, 0.0f); ipvot++; glVertex3f(x, y, 0.0f); }
glEnd(); glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 0.0f); for(angle = 0; angle < (2.0f * PI); angle += (PI / 8.0f))
{
x = 50.0f * sin(angle);
y = 50.0f * cos(angle); if(ipvot % 2 == 0) glColor3f(0.0f, 1.0f, 0.0f);
else glColor3f(1.0f, 0.0f, 0.0f); ipvot++; glVertex3f(x, y, 0.0f);
} glEnd(); glPopMatrix(); glutSwapBuffers(); } /**
改变窗口大小时回调函数
*/
void changeWindowSize(GLsizei w, GLsizei h)
{
GLfloat length = 100.0f;
if(h == 0) h = 1;
glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); if(w <= h) glOrtho(-length, length, -length, length * h / w, -length, length);
else glOrtho(-length, length * h / w, -length, length, -length, length); glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
} /**
设置
*/
void setupRC(void)
{
//背景颜色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glShadeModel(GL_FLAT); glFrontFace(GL_CW);
} /**
旋转
*/
void rotateMode(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
xRot -= 5.0f; else if(key == GLUT_KEY_DOWN)
xRot += 5.0f; else if(key == GLUT_KEY_LEFT)
yRot -= 5.0f; else if(key == GLUT_KEY_RIGHT)
yRot += 5.0f; if(xRot < 0) xRot = 355.0f;
if(xRot > 360.0f) xRot = 0.0f; if(yRot < 0) yRot = 355.0f;
if(yRot > 360.0f) yRot = 0.0f; glutPostRedisplay(); }

OpenGL编程(六)通过三角形绘画出3D模型的更多相关文章

  1. OpenGL编程-第一个程序-画出一个正方形

    账号是:qq876.......   pwd:bky.13....................... 程序如下 #include <GL/glut.h> // #pragma comm ...

  2. OpenGL编程(七)3D模型的深度(z轴)检测

    下图是我们要修改后的效果图: 一.深度检测 1.模型Z轴显示有问题: 上一次试验中,如果认真留意,会发现一个问题.当控制锥体在左右或上下旋转时,你会发现锥体看起来是在+-180度之间来回摆动,而不是3 ...

  3. 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图

    在Jerry写这篇文章时,通过Google才知道,SAP其实是有自己的3D模型视图显示解决方案的. 故事要从Right Hemisphere说起,这是一家专业的企业级2D/3D模型浏览及转换的软件供应 ...

  4. OpenGL编程(八)3D数学与坐标变换

    笛卡尔坐标 一维坐标系 以一个点为原点,选定一个方向为正方向(相反的方向为反方向),以一定的距离为标尺建立一维坐标系.一维坐标系一般应用于描述在一维空间中的距离. 举个例子:一维坐标系好比一条拉直的电 ...

  5. 用MFC实现OpenGL编程

    一.OpenGL简介 众所周知,OpenGL原先是Silicon Graphics Incorporated(SGI公司)在他们的图形工作站上开发高质量图像的接口.但最近几年它成为一个非常优秀的开放式 ...

  6. OpenGL编程逐步深入(二)在窗口中显示一个点

    准备知识 在本文中我们将会接触到OpenGl的扩展库GLEW( OpenGL Extension Wrangler Library),GLEW可以帮助我们处理OpenGl中繁琐的扩展管理.一旦初始化后 ...

  7. OpenGl 导入读取多个3D模型 并且添加鼠标控制移动旋转

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11627508.html 前言: 因为接下来的项目需求是要读取多个3D模型,并且移动拼接,那么我 ...

  8. OpenGL编程指南(第七版)

    OpenGL编程指南(第七版) 转自:http://blog.csdn.net/w540982016044/article/details/21287645 在接触OpenGL中,配置显得相当麻烦,特 ...

  9. Linux OpenGL 实践篇-3 绘制三角形

    本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用. 顶点数组对象 顶点数组对象负责管理一组顶点属性,顶点属性包括位置.法线.纹理坐标等. OpenGL缓存 OpenGL缓存实质上 ...

随机推荐

  1. SVN——Jenkins自动发布

    最近公司项目处于开发阶段,很多功能开发完后就需要发布到测试环境等待测试去验收,这个时候如果手动更新网站的话,是很费时费力的. 于是乎,我们做成了自动发布,这样我们只管提交代码到SVN就行了,发布由软件 ...

  2. week7_notebooke

    回顾:类:具有相同属相和技能的一类事物对象:类的具体表现class A: country = 'China' #静态变量,静态字段 def __init__(self): #动态变量,方法 self. ...

  3. 判断是否是Ajax请求

    Request.IsAjaxRequest()判断是否是ajax请求原理:Http协议上有个X-Requested-With:XML HttpRequest属性判断的 mvc后台通过Request可以 ...

  4. sql导出到excel

    1.先查询数据ID,别名  导出到excel 2.增加标准名称,标识错误数据,导入sqlServer select distinct [StandardName] from [GMSOA].[dbo] ...

  5. line-height与间距总总

    一点说明(个人吐槽,可以略过) 之所以想写这篇文章,是因为自己工作的经验总结.以前的页面编写极度不注重间距大小,特别是行级元素间距.认为只要差不多好就行了,没必要花那么大的精力去抠几px的小细节.事实 ...

  6. 开发工具 | 利用 deployd 搭建个人博客

    前端er,通过利用deployd + mongodb,实现可视化的接口编写,自定义mock数据,数据存储在mongodb中:deployd目前还没有中文网,更多信息请参考http://deployd. ...

  7. Usaco 滑雪比赛 Bobsledding, 2009 Dec(dp)

    Description 滑雪比赛bobsled 贝西参加了一场高山急速滑雪比赛,滑道总长度为 L.出发时,她的初速度为 1,贝西可以加速 或减速,每过 1 米,她能将速度增加 1.减少 1 或保持不变 ...

  8. CorelDRAW简单绘制的一杯满满的橙汁教程

    CorelDRAW怎么画一杯橙汁?方法很简单,首先绘制一个闭合路径,执行线性渐变,填充颜色:复制图形,使用刻刀工具裁剪两半,更改不透明度:然后为橙汁增加底部椭圆:修剪橙子片:绘制吸管:最后加上一层橙子 ...

  9. 第三章 Python函数

    函数 如果在开发程序时,需要某块代码多次,但是为了提⾼编写的效率以及代码的重⽤,所以把具有独⽴功能的代码块组织为⼀个⼩模块,这就是函数 函数的定义 函数定义的三种方式:无参函数,有参函数,空函数 #无 ...

  10. 第二章 Python数据类型详解

    基本概念 迭代(iteration):如果给定一个list或tuple,我们可以通过for循环来遍历,这种遍历我们称为迭代(iteration) 可变:value改变,id不变,可变类型是不可hash ...