opengl繪製齒輪

1. 概述

高級計算機三維建模第二次小實習,利用opengl在提供的基礎代碼上繪製完整的齒輪。繪製思路如下圖:
在這裏插入圖片描述

2. 注意事項

  1. p0,p7,p6,p3p_0,p_7,p_6,p_3這四點所組成的平面採取了三角形繪製的方式,繪製順序爲p7p0p6p3p_7\rightarrow p_0\rightarrow p_6\rightarrow p_3,每一次循環中一次順序繪製面,到下一次循環中的第一個點則爲p5p4pip_5\rightarrow p_4\rightarrow p_i,這樣,使用GL_TRIANGLE_STRIP進行繪製,即可連續繪製出齒輪一個面;
  2. 當使用glEnable(GL_CULL_FACE)時,繪製齒輪的反面時,重點需要注意,繪製點的順序要由原來的逆時針變爲順時針(注:opengl繪製時,默認逆時針爲正面),即順序變爲p0p7p3p6p_0\rightarrow p_7\rightarrow p_3\rightarrow p_6,這樣,當翻轉齒輪時,才能夠看見齒輪背面;或者不使用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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章