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

opengl:绘制球体

2017-05-03 09:53 260 查看


数学基础


球面参数方程

球面的参数曲线可以用球坐标表示,引入参数u,v,其中v是球面点与原点的连线与z轴正向的夹角,u表示连线在xy平面的投影与x轴正向的夹角,如下图所示:



则球面参数方程可以表示为:




球面法向量

已知球面的参数方程以后,很容易求得给定点的法向量,分别对u和v方向求偏导数,然后对两个所得向量进行叉积即可: 




实现细节

已知参数方程以后,需要进行离散,分别设定u和v的步长:ustep、vstep。然后通过不同的u和v,求得坐标系中点的实际坐标(x,y,z),在实现中有一点需要注意的是:



u=0与u=v这两条线上点的是球体的两个上下极点,所以进行渲染时需要区分,其中如图中间段的离散点可以按照四边形进行渲染,而上下两段则需要按照三角形进行渲染。


代码描述:

这里只是绘制了球面,如果想绘制球体,只用在渲染时,加入点的法向量即可。


点的数据结构:

class Point
{
public:
Point(){};
Point(double a,double b,double c):x(a),y(b),z(c){};
public:
double x;
double y;
double z;
};
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10


参数坐标(u,v)转换成时机坐标(x,y,z)函数

Point getPoint(double u,double v)
{
double x = sin(PI*v)*cos(PI2*u);
double y = sin(PI*v)*sin(PI2*u);
double z = cos(PI*v);
return Point(x,y,z);
}
1
2
3
4
5
6
7
1
2
3
4
5
6
7


绘制球面

void drawWire()
{
double ustep = 1/(double)uStepsNum, vstep = 1/(double)vStepNum;
double u = 0,v = 0;
//绘制下端三角形组
for(int i = 0;i<uStepsNum;i++)
{
glBegin(GL_LINE_LOOP);
Point a = getPoint(0,0);
glVertex3d(a.x,a.y,a.z);
Point b = getPoint(u,vstep);
glVertex3d(b.x,b.y,b.z);
Point c = getPoint(u+ustep,vstep);
glVertex3d(c.x,c.y,c.z);
u += ustep;
glEnd();
}
//绘制中间四边形组
u = 0, v = vstep;
for(int i=1;i<vStepNum-1;i++)
{
for(int j=0;j<uStepsNum;j++)
{
glBegin(GL_LINE_LOOP);
Point a = getPoint(u,v);
Point b = getPoint(u+ustep,v);
Point c = getPoint(u+ustep,v+vstep);
Point d = getPoint(u,v+vstep);
glVertex3d(a.x,a.y,a.z);
glVertex3d(b.x,b.y,b.z);
glVertex3d(c.x,c.y,c.z);
glVertex3d(d.x,d.y,d.z);
u += ustep;
glEnd();
}
v += vstep;
}
//绘制下端三角形组
u = 0;
for(int i=0;i<uStepsNum;i++)
{
glBegin(GL_LINE_LOOP);
Point a = getPoint(0,1);
Point b = getPoint(u,1-vstep);
Point c = getPoint(u+ustep,1-vstep);
glVertex3d(a.x,a.y,a.z);
glVertex3d(b.x,b.y,b.z);
glVertex3d(c.x,c.y,c.z);
glEnd();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51


初始化设置与绘图函数

#define PI 3.14159265358979323846
#define PI2 6.28318530717958647692

GLsizei width = 600,height = 600;

int uStepsNum = 50,vStepNum = 50;
1
2
3
4
5
6
1
2
3
4
5
6
void init()
{
glClearColor(0,1,1,1);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0,1,1,1);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat light_position [ ] = { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat light_ambient  [ ] = { 0.2f, 0.2f, 0.2f, 0.2f };
GLfloat light_diffuse  [ ] = { 0.5f, 0.5f, 0.5f, 0.2f };
GLfloat light_specular [ ] = { 0.5f, 0.5f, 0.5f, 0.2f };
glLightfv(GL_LIGHT0, GL_POSITION,  light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT,   light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE,   light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR,  light_specular);

glEnable (GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable (GL_NORMALIZE);
glEnable(GL_DEPTH_TEST);
glDepthFunc (GL_LESS);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void displayFunc()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
glPointSize(1.0);
glRotated(30,1,0,0);
glRotated(60,0,1,0);
glRotated(90,0,0,1);
drawWire();
glutSwapBuffers();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13


主函数

int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowPosition(100,100);
glutInitWindowSize(width,height);
glutCreateWindow("Sphere");

init();
glutDisplayFunc(displayFunc);
glutMainLoop();
}
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12


效果展示

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: