您的位置:首页 > 运维架构

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

2011-10-21 20:24 387 查看
环境: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);
}
运行结果:



可以看出获得了比较好的效果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐