OpenGL系列教程(3)——由简单的三角形到美丽的圆锥体

9938阅读 0评论2009-10-07 zieckey
分类:C/C++

上一篇:OpenGL系列教程(2)——从点到线,绘制我们自己的绚丽曲线

三维场景中,所有的物体都是由基本的元素构成的。基本的元素有点、线、面。而面都是三角形面,因为无论如何,一个由三个顶点组成的面永远都在一个平面上。下面我们从画三角形开始。
 
1、绘制一个简单的三角形
 

// Purpose: To show how to draw triangles

// Author: zieckey

// Date: 2009/10/7


#include "GL/glut.h"
#include <math.h>


void RenderScene()
{
    //清空颜色缓冲区,填充的颜色由 glClearColor( 0, 0.0, 0.0, 1 ); 指定为黑色

    glClear( GL_COLOR_BUFFER_BIT );


    glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式

    glPolygonMode(GL_BACK, GL_LINE); // 设置反面为线形模式


    //绘制一个三角形

    {
        glColor3f( 1.0f, 0.0f, 0.0f );//指定颜色,红色

        glBegin( GL_TRIANGLES );//开始画三角形

        {
            glVertex3f( 0.0f, 0.0f, 0.0f );
            glVertex3f( 25.f, 25.f, 0 );
            glVertex3f( 50.f, 0, 0 );

            glVertex3f( -50.f, 0.0f, 0.0f );
            glVertex3f( -25.f, 0, 0 );
            glVertex3f( -75.f, 50.f, 0 );
        }
        glEnd();//结束

    }

    glutSwapBuffers();
}

void SetupRC()
{
    glClearColor( 0, 0.0, 0.0, 1 );
    glColor3f( 1.0f, 0.0f, 0.0f );
}

void ChangeSize( GLsizei w, GLsizei h )
{
    GLfloat nRange = 200.0f;

    // Prevent a divide by zero

    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions

    glViewport(0, 0, w, h);

    // Reset projection matrix stack

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right, bottom, top, near, far)

    if (w <= h)
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    // Reset Model view matrix stack

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (800, 600);
    glutInitWindowPosition (100, 100);
    glutCreateWindow( "Triangles Example" );
    glutDisplayFunc( RenderScene );
    glutReshapeFunc( ChangeSize );
    SetupRC();
    glutMainLoop();

    return 1;
}

运行结果:


 2、添加上键盘响应和坐标系

根据上一篇文章,很容易添加上键盘响应和坐标系。

 

// Purpose: To show how to draw triangles and Pyramid

// Author: zieckey

// Date: 2009/10/7


#include "GL/glut.h"
#include <math.h>

// Rotation amounts

static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

void SpecialKeys(int key, int x, int y);
void DrawAxis();


void RenderScene()
{
    //清空颜色缓冲区,填充的颜色由 glClearColor( 0, 0.0, 0.0, 1 ); 指定为黑色

    glClear( GL_COLOR_BUFFER_BIT );

    // Save matrix state and do the rotation

    glPushMatrix();
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);

    glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式

    glPolygonMode(GL_BACK, GL_LINE); // 设置反面为线形模式


    //绘制一个三角形

    {
        glColor3f( 1.0f, 0.0f, 0.0f );//指定颜色,红色

        glBegin( GL_TRIANGLES );//开始画三角形

        {
            glVertex3f( 0.0f, 0.0f, 0.0f );
            glVertex3f( 25.f, 25.f, 0 );
            glVertex3f( 50.f, 0, 0 );

            glVertex3f( -50.f, 0.0f, 0.0f );
            glVertex3f( -25.f, 0, 0 );
            glVertex3f( -75.f, 50.f, 0 );
        }
        glEnd();//结束

    }

    DrawAxis();

    // Restore transformations

    glPopMatrix();

    glutSwapBuffers();
}

void SetupRC()
{
    glClearColor( 0, 0.0, 0.0, 1 );
    glColor3f( 1.0f, 0.0f, 0.0f );
}

void ChangeSize( GLsizei w, GLsizei h )
{
    GLfloat nRange = 200.0f;

    // Prevent a divide by zero

    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions

    glViewport(0, 0, w, h);

    // Reset projection matrix stack

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right, bottom, top, near, far)

    if (w <= h)
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    // Reset Model view matrix stack

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (800, 600);
    glutInitWindowPosition (100, 100);
    glutCreateWindow( "Triangles Example" );
    glutDisplayFunc( RenderScene );
    glutReshapeFunc( ChangeSize );
    glutSpecialFunc( SpecialKeys );
    SetupRC();
    glutMainLoop();

    return 1;
}




void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP)
        xRot-= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

    if(xRot > 356.0f)
        xRot = 0.0f;

    if(xRot < -1.0f)
        xRot = 355.0f;

    if(yRot > 356.0f)
        yRot = 0.0f;

    if(yRot < -1.0f)
        yRot = 355.0f;

    // Refresh the Window

    glutPostRedisplay();// this will refresh the window, so, it works the same to call RenderScene() directly

}






void DrawAxis()
{
    //绘制x、y、z坐标轴

    {
        glColor3f( 0.0f, 0.0f, 1.0f );//指定线的颜色,蓝色

        glBegin( GL_LINES );
        {
            // x-axis

            glVertex3f( 0.0f, 0.0f, 0.0f);
            glVertex3f( 200.0f, 0.0f, 0.0f);

            // x-axis arrow

            glVertex3f( 200.0f, 0.0f, 0.0f);
            glVertex3f( 193.0f, 3.0f, 0.0f);
            glVertex3f( 200.0f, 0.0f, 0.0f);
            glVertex3f( 193.0f,-3.0f, 0.0f);
        }
        glEnd();

        glColor3f( 0.0f, 1.0f, 0.0f );//指定线的颜色,绿色

        glBegin( GL_LINES );
        {
            // y-axis

            glVertex3f( 0.0f, 0.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( 3.0f, 193.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( -3.0f, 193.0f, 0.0f);
        }
        glEnd();


        glColor3f( 1.0f, 0.0f, 0.0f );//指定线的颜色,红色

        glBegin( GL_LINES );
        {
            // z-axis

            glVertex3f( 0.0f, 0.0f, 0.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, 3.0f, 193.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, -3.0f, 193.0f);
        }
        glEnd();
    }
}

3、通过三角扇形来绘制圆锥


 

// Purpose: To show how to draw triangles and Pyramid

// Author: zieckey

// Date: 2009/10/7


#include "GL/glut.h"
#include <math.h>

// Rotation amounts

static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;

void SpecialKeys(int key, int x, int y);
void ChangeSize( GLsizei w, GLsizei h );
void DrawAxis();
void SetupRC();

void RenderScene()
{
    //清空颜色缓冲区,填充的颜色由 glClearColor( 0, 0.0, 0.0, 1 ); 指定为黑色

    glClear( GL_COLOR_BUFFER_BIT );

    // Save matrix state and do the rotation

    glPushMatrix();
    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);

    DrawAxis();

    //绘制三角扇形

    {
        glBegin( GL_TRIANGLE_FAN );
        {
            glVertex3f( 0, 0, 125.f );//圆锥的锥顶点是三角扇形的公共的顶点,在z轴上


            #define PI 3.14159f
            #define RADIUS 75.f
            GLint faceFlag = 0;
            GLfloat x = 0, y = 0, angle = 0;
            for ( ; angle <= 2.0f * PI; angle += 0.1f, faceFlag++ )
            {
                x = RADIUS * sin( angle );
                y = RADIUS * cos( angle );
                if ( faceFlag % 2 == 0 )
                {
                    glColor3f( 1, 1, 1 );
                } else {
                    glColor3f( 0.5, 0.5, 0.5 );
                }
                glVertex3f( x, y, 0 );
            }

            //最后一个扇形

            x = RADIUS * sin( 0.f );
            y = RADIUS * cos( 0.f );
            glVertex3f( x, y, 0 );
        }
        glEnd();


        //绘制圆锥体的底面

        {
            glBegin( GL_TRIANGLE_FAN );
            {
                glVertex3f( 0, 0, 0 );//底面的顶点是三角扇形的公共的顶点,在(0,0,0)坐标原点处

                #define PI 3.14159f
                #define RADIUS 75.f
                GLint faceFlag = 0;
                GLfloat x = 0, y = 0, angle = 0;
                for ( ; angle <= 2.0f * PI; angle += 0.1f, faceFlag++ )
                {
                    x = RADIUS * sin( angle );
                    y = RADIUS * cos( angle );
                    if ( faceFlag % 2 == 0 )
                    {
                        glColor3f( 1, 1, 1 );
                    } else {
                        glColor3f( 0.5, 0.5, 0.5 );
                    }
                    glVertex3f( x, y, 0 );
                }
            }
            glEnd();
        }
    }

    // Restore transformations

    glPopMatrix();

    glutSwapBuffers();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (800, 600);
    glutInitWindowPosition (100, 100);
    glutCreateWindow( "Triangles Example" );
    glutDisplayFunc( RenderScene );
    glutReshapeFunc( ChangeSize );
    glutSpecialFunc( SpecialKeys );
    SetupRC();
    glutMainLoop();

    return 1;
}


void SetupRC()
{
    glClearColor( 0, 0.0, 0.0, 1 );
    glColor3f( 1.0f, 0.0f, 0.0f );
    glShadeModel( GL_FLAT );//把着色模式设置为单调着色

    glFrontFace( GL_CW );//把顺时针方向的面作为正面(逆时针方向为 GL_CCW )

}

void ChangeSize( GLsizei w, GLsizei h )
{
    GLfloat nRange = 200.0f;

    // Prevent a divide by zero

    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions

    glViewport(0, 0, w, h);

    // Reset projection matrix stack

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right, bottom, top, near, far)

    if (w <= h)
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    // Reset Model view matrix stack

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP)
        xRot -= 5.0f;

    if(key == GLUT_KEY_DOWN)
        xRot += 5.0f;

    if(key == GLUT_KEY_LEFT)
        yRot -= 5.0f;

    if(key == GLUT_KEY_RIGHT)
        yRot += 5.0f;

    if(xRot > 356.0f)
        xRot = 0.0f;

    if(xRot < -1.0f)
        xRot = 355.0f;

    if(yRot > 356.0f)
        yRot = 0.0f;

    if(yRot < -1.0f)
        yRot = 355.0f;

    // Refresh the Window

    glutPostRedisplay();// this will refresh the window, so, it works the same to call RenderScene() directly

}


void DrawAxis()
{
    //绘制x、y、z坐标轴

    {
        glColor3f( 0.0f, 0.0f, 1.0f );//指定线的颜色,蓝色

        glBegin( GL_LINES );
        {
            // x-axis

            glVertex3f( 0.0f, 0.0f, 0.0f);
            glVertex3f( 200.0f, 0.0f, 0.0f);

            // x-axis arrow

            glVertex3f( 200.0f, 0.0f, 0.0f);
            glVertex3f( 193.0f, 3.0f, 0.0f);
            glVertex3f( 200.0f, 0.0f, 0.0f);
            glVertex3f( 193.0f,-3.0f, 0.0f);
        }
        glEnd();

        glColor3f( 0.0f, 1.0f, 0.0f );//指定线的颜色,绿色

        glBegin( GL_LINES );
        {
            // y-axis

            glVertex3f( 0.0f, 0.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( 3.0f, 193.0f, 0.0f);
            glVertex3f( 0.0f, 200.0f, 0.0f);
            glVertex3f( -3.0f, 193.0f, 0.0f);
        }
        glEnd();


        glColor3f( 1.0f, 0.0f, 0.0f );//指定线的颜色,红色

        glBegin( GL_LINES );
        {
            // z-axis

            glVertex3f( 0.0f, 0.0f, 0.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, 3.0f, 193.0f );
            glVertex3f( 0.0f, 0.0f, 200.0f );
            glVertex3f( 0.0f, -3.0f, 193.0f);
        }
        glEnd();
    }
}

运行结果:

4、着色模式

glShadeModel( GL_FLAT );//把着色模式设置为单调着色,最后一个顶点的颜色就是整个多边形的颜色

glShadeModel( GL_SMOOTH );//把着色模式设置为渐变着色,对相邻顶点的颜色进行匀和

上一篇:OpenGL系列教程(2)——从点到线,绘制我们自己的绚丽曲线
下一篇:OpenGL系列教程(4)——几何转换,从球体到酷炫的太阳系