opengl:绘制球体

数学基础

球面参数方程

球面的参数曲线可以用球坐标表示,引入参数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

效果展示

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值