第6章代码-三维造型
时间:2022-07-25
本文章向大家介绍第6章代码-三维造型,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
6.3.4编程实例-简单实体构建
本实例参考了著名的Nehe OpenGL示例构建了四棱锥和立方体的实体模型,这两个模型的顶点位置如图6.13所示。可见,四棱锥的四个侧面的顶点序列分别为v0v1v2、v0v2v3、v0v3v4、v0v4v1,底面为v1v2v3v4。传递顶点信息时使用了glVertex3fv函数,以顶点首地址作为参数,比glVertex3f函数直接用顶点坐标作为参数的方式更为方便、直观。在坐标系原点建好的实体可以通过几何变换放置在任意不同的位置。在本示例中,四棱锥被放置在左侧,立方体被放置在右侧。
#include <gl/glut.h>
#include<iostream>
using namespace std;
float rtri;
float rquad;
GLfloat points0[5][3] ={{ 0, 1, 0}, {-1, -1, 1}, { 1, -1, 1}, { 1, -1, -1},{-1, -1,-1}};
GLfloat points1[8][3]={ { 1, 1, -1 }, {-1, 1, -1}, {-1, 1, 1}, { 1, 1, 1},
{ 1, -1, 1 }, {-1, -1, 1}, {-1,-1,-1}, { 1, -1, -1}};
GLfloat Colors0[4][3]={{1,0,0},{0,1,0}, {0,0,1},{1,1,0}}; //四棱锥的颜色
//下行是立方体的颜色
GLfloat Colors1[6][3]={{0,1,0},{1,0.5,0},{1,0,0},{1,1,0},{0,0,1},{1,0,1}};
int vertice0[4][3]={{0,1,2},{0,2,3},{0,3,4},{0,4,1}}; //四棱锥的顶点号序列
//下行是立方体的顶点号序列
int vertice1[6][4]={{0,1,2,3},{4,5,6,7},{3,2,5,4},{7,6,1,0},{2,1,6,5}, {0,3,4,7}};
void InitGL ( GLvoid )
{
glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable ( GL_COLOR_MATERIAL );
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void CreatePyramid()
{
glBegin(GL_TRIANGLES);
for(int i=0;i<4;i++)
{
glColor3fv(Colors0[i]);
for(int j=0;j<3;j++)
{
int VtxId=vertice0[i][j];
glVertex3fv(points0[VtxId]);
}
}
glEnd();
glBegin( GL_QUADS); //构建底面
glColor3f(1.0f, 1.0f, 1.0f );
for(i=0;i<4;i++)
glVertex3fv(points0[i]);
glEnd();
}
void CreateCube()
{
glBegin(GL_QUADS);
for(int i=0;i<6;i++)
{
glColor3fv(Colors1[i]);
for(int j=0;j<4;j++)
{
int VtxId=vertice1[i][j];
glVertex3fv(points1[VtxId]);
}
}
glEnd();
}
void display ( void )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glTranslatef(-1.5f,0.0f,-6.0f); //平移至左侧
glRotatef(rtri,0.0f,1.0f,0.0f); //旋转一个角度
CreatePyramid(); //创建三角塔
glLoadIdentity(); //将矩阵归一化回原样
glTranslatef(1.5f,0.0f,-6.0f); //平移到右侧
glRotatef(rquad,1.0f,0.0f,0.0f); //旋转一个角度
CreateCube(); //创建立方体
glPopMatrix();
rtri+=0.2f; //修改三角塔旋转角度
rquad-=0.15f; //修改立方体的旋转角度
glutSwapBuffers ( );
}
void reshape ( int width , int height )
{
if (height==0)
height=1;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void main ( int argc, char** argv )
{
glutInit ( &argc, argv );
glutInitDisplayMode ( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize ( 600, 400 );
glutCreateWindow ( "Pyramid and cube" );
InitGL();
glutDisplayFunc ( display );
glutReshapeFunc ( reshape );
glutIdleFunc ( display );
glutMainLoop ( );
}
6.4.3 Bezier曲线曲面
1. 调和函数方式绘制Bezier曲线
//绘制由p0,p1,p2,p3确定的Bezier曲线
//参数区间[0,1]被离散为count份
class Point //点类
{
Double x,y;
Point(double vx, double vy)
{
This.x=vx;
This.y=vy;
}
void BezierCurve(Point p0,Point p1,Point p2,Point p3,int count)
{
double t = 0.0;
dt = 1.0 / count;
moveto(p1.x,p1.y); //设置起点
for(int i=0; i<count+1; i++)
{
double F1,F2,F3,F4,x,y; //调和函数
double u = 1.0 – t ;
F1 = u * u * u ;
F2 = 3 * t * u * u;
F3 = 3 * t * t * u;
F4 = t * t * t;
x = p0.x * F1 + p1.x * F2 + p2.x * F3 + p3.x * F4;
y = p0.y * F1 + p1.y * F2 + p2.y * F3 + p3.y * F4;
lineto(x,y);
t+=dt;
}
}
2. 离散方式绘制Bezier曲线
void Casteljau(Point p0, Point p1, Point p2, Point p3)
{
double t=0;
int count=20;
double dt=1.0/count;
MoveTo(p0);
for(int i=0;i<count;i++)
{
Point p01,p11,p21,p02,p12,p03;
p01.x=(1-t)*p0.x+t*p1.x;
p01.y=(1-t)*p0.y+t*p1.y;
p11.x=(1-t)*p1.x+t*p2.x;
p11.y=(1-t)*p1.y+t*p2.y;
p21.x=(1-t)*p2.x+t*p3.x;
p21.y=(1-t)*p2.y+t*p3.y;
p02.x=(1-t)*p01.x+t*p11.x;
p02.y=(1-t)*p01.y+t*p11.y;
p12.x=(1-t)*p11.x+t*p21.x;
p12.y=(1-t)*p11.y+t*p21.y;
p03.x=(1-t)*p02.x+t*p12.x;
p03.y=(1-t)*p02.y+t*p12.y;
dc->LineTo(p03);
t+=dt;
}
}
6.4.6 编程实例-OpenGL曲线曲面生成
1.绘制Bezier曲线
#include <GL/glut.h>
GLfloat ctrlpoints[4][3] =
{{ -4.0, -4.0, 0.0}, { -2.0, 3.0, 0.0},
{2.0, 4.5, 0.0}, {3.0, -3.0, 0.0}};
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glShadeModel(GL_FLAT);
//下行用于定义曲线函数
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3); //将当前曲线函数激活
}
void display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
//下面用求值器按20等分计算Bezier曲线上的点
glColor3f(0.0, 0.0, 0.0);
glLineWidth(2);
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 20; i++)
glEvalCoord1f((GLfloat) i/20.0); //相当于调用了glVertex*()
glEnd();
//下面绘制控制多边形
glLineWidth(1);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINE_STRIP);
for (i = 0; i < 4; i++)
glVertex3fv(&ctrlpoints[i][0]);
glEnd();
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
else
glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 5.0*(GLfloat)w/(GLfloat)h,
-5.0, 5.0, -5.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
2.绘制Bezier曲面
#include <GL/glut.h>
GLfloat ctrlpoints[4][4][3] = {
{{-3, 0, 4.0}, {-2, 0, 2.0}, {-1, 0, 0.0}, {0, 0, 2.0}},
{{-3, 1, 1.0}, {-2, 1, 3.0}, {-1, 1, 6.0}, {0, 1, -1.0}},
{{-3, 2, 4.0}, {-2, 2, 0.0}, {-1, 2, 3.0}, {0, 2, 4.0}},
{{-3, 3, 0.0}, {-2, 3, 0.0}, {-1, 3, 0.0}, {0, 3, 0.0}}
};
void display(void)
{
int i, j;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glPushMatrix ();
glRotatef(85.0, 1.0, 1.0, 1.0);
for (j = 0; j <= 20; j++)
{
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 20; i++)
glEvalCoord2f((GLfloat)i/20.0, (GLfloat)j/20.0); //调用求值器
glEnd();
glBegin(GL_LINE_STRIP);
for (i = 0; i <= 20; i++)
glEvalCoord2f((GLfloat)j/20.0, (GLfloat)i/20.0); //调用求值器
glEnd();
}
glPopMatrix ();
glFlush();
}
void init(void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
//下行的代码用控制点定义Bezier曲面函数
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &ctrlpoints[0][0][0]);
glEnable(GL_MAP2_VERTEX_3); //激活该曲面函数
glOrtho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0); //构造平行投影矩阵
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
- 在 Go 语言中,正确的使用并发
- Injectify:一款执行MiTM攻击的工具
- 看我如何发现Google云平台漏洞并获得$7500赏金
- Go语言写Web 应用程序
- 小萝莉说Crash(一):Unrecognized selector sent to instance xxxx
- 游戏服务器之多线程发送(上)
- 游戏服务器之多线程发送(中)
- 游戏服务器之多线程发送(下)
- 【团队分享】手机QQ:升级iOS8.3后,发图就崩,为哪般?
- golang 字符串操作实例
- 【团队分享】刀锋铁骑:常见Android Native崩溃及错误原因
- OpenShift企业版安装:单Master集群
- http线程池的设计与实现(c++)
- iOS崩溃堆栈符号化,定位问题分分钟搞定!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php实现根据身份证获取精准年龄
- php 使用ActiveMQ发送消息,与处理消息操作示例
- php使用gearman进行任务分发操作实例详解
- laravel框架select2多选插件初始化默认选中项操作示例
- PHP pthreads v3在centos7平台下的安装与配置操作方法
- laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
- PHP Beanstalkd消息队列的安装与使用方法实例详解
- 解决windows上php xdebug 无法调试的问题
- php7 图形用户界面GUI 开发示例
- Django开发的简易留言板案例详解
- php使用redis的有序集合zset实现延迟队列应用示例
- PHP使用openssl扩展实现加解密方法示例
- php使用redis的几种常见操作方式和用法示例
- 使用memory_profiler监测python代码运行时内存消耗方法
- php 多进程编程父进程的阻塞与非阻塞实例分析