【循序渐进学图形学之】OpenGL使用多边形近似模拟法构建表面

环境:VS2008

首先创建一个二十面体:

代码:

#include <GL/glut.h> #define X .525731112119133606 #define Z .850650808352039932 static GLfloat vdata[12][3] = {//各顶点坐标 {-X,0.0,Z},{X,0.0,Z},{-X,0.0,-Z},{X,0.0,-Z}, {0.0,Z,X},{0.0,Z,-X},{0.0,-Z,X},{0.0,-Z,-X}, {Z,X,0.0},{-Z,X,0.0},{Z,-X,0.0},{-Z,-X,0.0}, }; static GLuint tindices[20][3] = {//构成各面(三角形)的顶点索引 {1,4,0},{4,9,0},{4,5,9},{8,5,4},{1,8,4}, {1,10,8},{10,3,8},{8,3,5},{3,2,5},{3,7,2}, {3,10,7},{10,6,7},{6,11,7},{6,0,11},{6,1,0}, {10,1,6},{11,0,9},{2,11,9},{5,2,9},{11,2,7}, }; void display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); for(int i = 0;i < 20;++i) { glColor3f(1.0,1.0,i * 1.0 / 20);//颜色设置 glVertex3fv(&vdata[tindices[i][0]][0]); glVertex3fv(&vdata[tindices[i][1]][0]); glVertex3fv(&vdata[tindices[i][2]][0]); } glEnd(); glFlush(); } void init() { glClearColor(0.0,0.0,0.0,0.0); } int main(int argc,char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(250,250); glutInitWindowPosition(100,100); glutCreateWindow("Polygon"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }运行结果:


使用二十面体来模拟着色球体。需修改代码:

glBegin(GL_TRIANGLES); for(int i = 0;i < 20;++i) { glColor3f(1.0,1.0,i * 1.0 / 20); glNormal3fv(&vdata[tindices[i][0]][0]); glVertex3fv(&vdata[tindices[i][0]][0]); glNormal3fv(&vdata[tindices[i][1]][0]); glVertex3fv(&vdata[tindices[i][1]][0]); glNormal3fv(&vdata[tindices[i][2]][0]); glVertex3fv(&vdata[tindices[i][2]][0]); } glEnd();但是效果并不好。

我们可以对三角形进行细分。下面对上述成语执行一次细分,创建一个80个面的模拟球体

代码:

#include <GL/glut.h> #include <iostream> #include <cmath> using namespace std; #define X .525731112119133606 #define Z .850650808352039932 static GLfloat vdata[12][3] = { {-X,0.0,Z},{X,0.0,Z},{-X,0.0,-Z},{X,0.0,-Z}, {0.0,Z,X},{0.0,Z,-X},{0.0,-Z,X},{0.0,-Z,-X}, {Z,X,0.0},{-Z,X,0.0},{Z,-X,0.0},{-Z,-X,0.0}, }; static GLuint tindices[20][3] = { {1,4,0},{4,9,0},{4,5,9},{8,5,4},{1,8,4}, {1,10,8},{10,3,8},{8,3,5},{3,2,5},{3,7,2}, {3,10,7},{10,6,7},{6,11,7},{6,0,11},{6,1,0}, {10,1,6},{11,0,9},{2,11,9},{5,2,9},{11,2,7}, }; static GLuint count = 0;//全局静态变量 void normalize(float v[3]) { GLfloat d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); if(d == 0) { cout<<"zero length vector!"; return; } v[0] /= d; v[1] /= d; v[2] /= d; } void drawtriangle(float *v1,float *v2,float *v3)//绘制三角形的操作 { count += 1; glBegin(GL_TRIANGLES); //颜色设置 :给不同小三角形设置不同颜色,便于查看 if(count % 3 == 0) glColor3f(0.0,1.0,1.0); else if(count % 3 == 1) glColor3f(1.0,0.0,1.0); else glColor3f(1.0,1.0,0.0); glNormal3fv(v1); glVertex3fv(v1); glNormal3fv(v2); glVertex3fv(v2); glNormal3fv(v3); glVertex3fv(v3); glEnd(); } void subdivide(float *v1,float *v2,float *v3) { GLfloat v12[3],v23[3],v31[3]; for(int i = 0;i < 3;++i) { v12[i] = (v1[i] + v2[i]) / 2.0; v23[i] = (v2[i] + v3[i]) / 2.0; v31[i] = (v3[i] + v1[i]) / 2.0; } normalize(v12); normalize(v23); normalize(v31); drawtriangle(v1,v12,v31); drawtriangle(v2,v23,v12); drawtriangle(v3,v31,v23); drawtriangle(v12,v23,v31); } void display() { glClear(GL_COLOR_BUFFER_BIT); for(int i = 0;i < 20;++i) { subdivide(&vdata[tindices[i][0]][0],&vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0]); } glFlush(); } void init() { glClearColor(0.0,0.0,0.0,0.0); } int main(int argc,char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(250,250); glutInitWindowPosition(100,100); glutCreateWindow("Polygon"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }运行结果:

继续对程序进修改,用递归的方法对三角形进行划分,以获得适当的深度。如果深度为0,则停止划分。

只需修改subdivide函数:

//采用递归细分方法:depth为深度值,控制划分的次数 void subdivide(float *v1,float *v2,float *v3,long depth) { GLfloat v12[3],v23[3],v31[3]; if(depth == 0) { drawtriangle(v1,v2,v3); return; } for(int i = 0;i < 3;++i) { v12[i] = (v1[i] + v2[i]) / 2.0; v23[i] = (v2[i] + v3[i]) / 2.0; v31[i] = (v3[i] + v1[i]) / 2.0; } normalize(v12); normalize(v23); normalize(v31); subdivide(v1,v12,v31,depth - 1); subdivide(v2,v23,v12,depth - 1); subdivide(v3,v31,v23,depth - 1); subdivide(v12,v23,v31,depth - 1); }运行结果:

可以看出获得了比较好的效果。

转载于:https://www.cnblogs.com/xiajun/archive/2011/10/21/2298643.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值