opengl绘制齿轮

1. 概述

高级计算机三维建模第二次小实习,利用opengl在提供的基础代码上绘制完整的齿轮。绘制思路如下图:
在这里插入图片描述

2. 注意事项

  1. p 0 , p 7 , p 6 , p 3 p_0,p_7,p_6,p_3 p0,p7,p6,p3这四点所组成的平面采取了三角形绘制的方式,绘制顺序为 p 7 → p 0 → p 6 → p 3 p_7\rightarrow p_0\rightarrow p_6\rightarrow p_3 p7p0p6p3,每一次循环中一次顺序绘制面,到下一次循环中的第一个点则为 p 5 → p 4 → p i p_5\rightarrow p_4\rightarrow p_i p5p4pi,这样,使用GL_TRIANGLE_STRIP进行绘制,即可连续绘制出齿轮一个面;
  2. 当使用glEnable(GL_CULL_FACE)时,绘制齿轮的反面时,重点需要注意,绘制点的顺序要由原来的逆时针变为顺时针(注:opengl绘制时,默认逆时针为正面),即顺序变为 p 0 → p 7 → p 3 → p 6 p_0\rightarrow p_7\rightarrow p_3\rightarrow p_6 p0p7p3p6,这样,当翻转齿轮时,才能够看见齿轮背面;或者不使用glEnable((GL_CULL_FACE);
  3. 记得添加法线,否则由于默认正面的原因,齿轮背面看起来是黑的,法线信息根据z轴(垂直于屏幕)来决定,齿轮正面朝外(即为+),背面朝内(即为-);
  4. 齿轮齿的法线比较麻烦,因为是旋转一周的,无法指定固定朝向。

3. 绘制结果与代码

3.1 齿轮结果图

在这里插入图片描述

3.2 完整代码

#include <GL/freeglut.h>
#include <stdlib.h>
#include <math.h>

const double PI=3.14159265;

GLfloat g_rotx = 20.0, g_roty = 30.0, g_rotz = 0.0, g_angle=0.0;
GLfloat g_modelPos[3] = {0, 0, -20};
GLfloat g_lightPos[4] = {15.0, 15.0, 10.0, 0.0};
GLfloat g_color1[4] =  {0.8, 0.1, 0.0, 1.0};
GLfloat g_color2[4] =  {0.0, 0.8, 0.2, 1.0};
GLfloat g_color3[4] =  {0.2, 0.2, 1.0, 1.0};

bool g_bStartAnim = true;

static void resize(int w, int h)
{
    glViewport(0,0,(GLsizei)w,(GLsizei)h);
    glMatrixMode(GL_PROJECTION) ;
    glLoadIdentity() ;
    gluPerspective(45.0,(GLfloat)w/(GLfloat)h,0.2,100.0) ;
    glMatrixMode(GL_MODELVIEW) ;
    glLoadIdentity() ;
}

void init(void)
{
    glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);
    //glEnable(GL_CULL_FACE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
}


/*Input:  inner_radius - radius of hole at center
          outer_radius - radius at center of teeth
          width - width of gear
          teeth - number of teeth
          tooth_depth - depth of tooth */
void DrawGear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
{
    GLint i;
    GLfloat r0, r1, r2;
    GLfloat angle, da;
    GLfloat u, v, len;

    r0 = inner_radius;
    r1 = outer_radius - tooth_depth / 2.0;
    r2 = outer_radius + tooth_depth / 2.0;

    da = 2.0 * PI / teeth / 4.0;

    glShadeModel(GL_FLAT);
    glNormal3f(0.0, 0.0, 1.0);
    //Draw front face
    glBegin(GL_TRIANGLE_STRIP);
    for (i = 0; i <= teeth; i++)
    {
        angle = i * 2.0 * PI / teeth;
        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r0 * cos(angle + 3 * da), r0 * sin(angle + 3 * da), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
        glNormal3f(0,0,1);

    }
    glEnd();


    //Draw front sides of teeth
    glBegin(GL_QUADS);
    da = 2.0 * PI / teeth / 4.0;
    for (i = 0; i < teeth; i++)
    {
        angle = i * 2.0 * PI / teeth;
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
        glNormal3f(0,0,1);
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
        glNormal3f(0,0,1);
    }
    glEnd();

    //Draw back face
    glBegin(GL_TRIANGLE_STRIP);
    for (i = 0; i <= teeth; i++)
    {
        angle = i * 2.0 * PI / teeth;
        /*glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r0 * cos(angle + 3 * da), r0 * sin(angle + 3 * da), width * 0);
        glNormal3f(0,0,-1);*/

         glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r0 * cos(angle + 3 * da), r0 * sin(angle + 3 * da), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0);
        glNormal3f(0,0,-1);

    }
    glEnd();

    //Draw back sides of teeth
    glBegin(GL_QUADS);
    da = 2.0 * PI / teeth / 4.0;
    for (i = 0; i < teeth; i++)
    {
        angle = i * 2.0 * PI / teeth;

        glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0);
        glNormal3f(0,0,-1);
        glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0);
        glNormal3f(0,0,-1);
    }
    glEnd();

    //xiaoyuan
    glBegin(GL_QUAD_STRIP);
    for(i = 0; i <= teeth; i++)
    {
         angle = i * 2.0 * PI / teeth;
         glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0);

        glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);

        glVertex3f(r0 * cos(angle+3*da), r0 * sin(angle+3*da), width * 0);

        glVertex3f(r0 * cos(angle+3*da), r0 * sin(angle+3*da), width * 0.5);

    }
    glEnd();
    //dayuan
    glBegin(GL_QUAD_STRIP);
    for(i = 0; i <= teeth; i++)
    {
         angle = i * 2.0 * PI / teeth;
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0);
        glVertex3f(r1 * cos(angle+3*da), r1 * sin(angle+3*da), width * 0.5);
        glVertex3f(r1* cos(angle+3*da), r1 * sin(angle+3*da), width * 0);

    }
    glEnd();
    //shangchi
    glBegin(GL_QUADS);
    for(i = 0; i < teeth; i++)
    {
        angle = i * 2.0 * PI / teeth;
        glVertex3f(r2 * cos(angle+da), r2 * sin(angle+da), width * 0.5);
        glNormal3f(1,0,0);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
        glNormal3f(1,0,0);
        glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0);
        glNormal3f(1,0,0);
        glVertex3f(r2* cos(angle+da), r2 * sin(angle+da), width * 0);
        glNormal3f(1,0,0);
    }
    glEnd();
    //xiachi
    glBegin(GL_QUADS);
    for(i = 0; i < teeth; i++)
    {
         angle = i * 2.0 * PI / teeth;
         glVertex3f(r2* cos(angle+2*da), r2 * sin(angle+2*da), width * 0);
         glVertex3f(r1 * cos(angle+3*da), r1 * sin(angle+3*da), width * 0);
         glVertex3f(r1 * cos(angle+3*da), r1 * sin(angle+3*da), width * 0.5);
         glVertex3f(r2 * cos(angle+2*da), r2 * sin(angle+2*da), width * 0.5);
    }
    glEnd();
    //zuiwaimian
    glBegin(GL_QUADS);
    for(i = 0; i < teeth; i++)
    {
         angle = i * 2.0 * PI / teeth;

        glVertex3f(r2 * cos(angle+2*da), r2 * sin(angle+2*da), width * 0.5);
        glVertex3f(r2 * cos(angle+1*da), r2 * sin(angle+1*da), width * 0.5);
        glVertex3f(r2* cos(angle+1*da), r2 * sin(angle+1*da), width * 0);
        glVertex3f(r2 * cos(angle+2*da), r2 * sin(angle+2*da), width * 0);
    }
    glEnd();

}

static void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(g_bStartAnim)
        g_angle = 30*glutGet(GLUT_ELAPSED_TIME) / 1000.0;

    glLoadIdentity() ;
    glTranslatef(g_modelPos[0], g_modelPos[1], g_modelPos[2]);

    glPushMatrix();
        glRotatef(g_rotx, 1.0, 0.0, 0.0);
        glRotatef(g_roty, 0.0, 1.0, 0.0);
        glRotatef(g_rotz, 0.0, 0.0, 1.0);

        glPushMatrix();
            glTranslatef(-3.0, -2.0, 0.0);
            glRotatef(g_angle, 0.0, 0.0, 1.0);
            glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, g_color1);
            DrawGear(1.0, 4.0, 1.0, 20, 0.7);
        glPopMatrix();
    glPopMatrix();

    glutSwapBuffers();
}

static void key(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27 :
        exit(0);
        break;
    case 'w':
        g_rotx += 5;
        break;
    case 's':
        g_rotx -= 5;
        break;
    case 'a':
        g_roty += 5;
        break;
    case 'd':
        g_roty -= 5;
        break;
    case 'q':
        g_rotz += 5;
        break;
    case 'e':
        g_rotz -= 5;
        break;
    case 'z':
        g_modelPos[2] += 1;
        break;
    case 'x':
        g_modelPos[2] -= 1;
        break;
    case ' ':
        g_bStartAnim = !g_bStartAnim;
        break;
    }
    glutPostRedisplay();
}

static void idle(void)
{
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(800, 600);
    glutInitWindowPosition(10,10);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("Shapes");

    glutReshapeFunc(resize);
    glutDisplayFunc(display);
    glutKeyboardFunc(key);
    glutIdleFunc(idle);

    glClearColor(1, 1, 1, 1);

    init();

    glutMainLoop();

    return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值