实验九3D编程基础

使用Opengl库实现

实验一

一、实验目的

1.熟悉3D基本编程。

2.熟悉视点观察函数的设置和使用。3.熟悉投影变换函数的设置和使用。4.熟悉基本3D图元的绘制。

二、实验内容

1.读懂以下3D物体程序,并结合本书内容理解一些新的绘制函数和投影变换函数的含义:3D Cube.cpp(见后面参考程序)为正交投影下的旋转3D立方体,按下鼠标可实现不同方向的旋转,效果图参见实验图9-1,分析3D编程代码与程序结构。

对于以下操作需要记录不同效果图和修改的相应参数:

1)让静止的立方体绕Z轴不停旋转。

修改参数:

  1. // 设置旋转轴:两个三维的点确定的旋转轴
  2. GLfloat axis[][3] = {
  3.    0.5f,0.5f, 0.0f,
  4.    0.5f, 0.5f, 1.0f
  5. };
  6.    // 设置绕给定的轴旋转
  7.    glTranslatef(axis[0][0], axis[0][1], axis[0][2]);
  8.    glRotatef(angle, axis[1][0] - axis[0][0], axis[1][1] - axis[0][1], axis[1][2] - axis[0][2]);
  9.    glTranslatef(-axis[0][0], -axis[0][1], -axis[0][2]);

2)修改不同视点,目标点不变,观看显示效果。

gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, -1, -1, 1); 相当于我们的脑袋位置在(0.0,0.0,5.0)处,眼睛望向(0.0,0.0,0.0),即原点。后面的三个参数(-1, -1, 1),不变

修改:gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, -1, -1, 1);

3)修改目标点,视点不动,观看显示效果。

修改:gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);

为:gluLookAt(2, 2, 2, 0.0, 1, 0.0, -1, -1, 1); 修改目标点,视点不动

结果如下:

4)视点与目标点同时修改,观看显示效果。

修改:gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);

为:gluLookAt(1, 2, 0, 0.0, 1, 0.0, -1, -1, 1);//修改目标点和视点

结果如下:

 

5)视点与目标点不变,修改观察体大小,观看显示效果。

//修改正方体大小即修改顶点位置,代码如下:

  1. static const GLfloat vertex[][3] = {  
  2.     0.0f, 0.0f, 0.0f,  
  3.     1.5f, 0.0f, 0.0f,  
  4.     0.0f, 1.5f, 0.0f,  
  5.     1.5f, 1.5f, 0.0f,  
  6.     0.0f, 0.0f, 1.5f,  
  7.     1.50f, 0.0f, 1.5f,  
  8.     0.0f, 1.5f, 1.5f,  

6)将正交投影观察体改为透视投影观察体,并设置其大小,观察显示效果。

核心代码更改:

void reshape(int w, int h)  
{  
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);  
    glMatrixMode(GL_PROJECTION);//投影矩阵  
    glLoadIdentity();  
    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);  
    glMatrixMode(GL_MODELVIEW);//切换回模型视图矩阵  
    //glLoadIdentity();  
    //gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);  
}  
  
//正交投影  
void reshape_2(int w, int h)  
{  
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);  
    glMatrixMode(GL_PROJECTION);//投影矩阵  
    glLoadIdentity();  
  
    //使用正交投影  
    if (w <= h)  
        glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,  
            2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);  
    else  
        glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,  
            2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);  
  
    glMatrixMode(GL_MODELVIEW);  
}  

两者变化如下:

7)将立方体替换为茶壶,观看显示效果。

核心代码:

  1. void displaytadpot(void)  
    {  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        glColor3f(1.0, 0.0, 0.0); //画笔红色  
        glLoadIdentity();  //加载单位矩阵    
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  
        glRotatef(angle, 0.0f, 1.0f, 0.0f);  
        glRotatef(0.0, 1.0, 0.0, 0.0);  
        glRotatef(0.0, 0.0, 1.0, 0.0);  
        glRotatef(0.0, 0.0, 0.0, 1.0);  
        glutWireTeapot(1.5);  
        //rote += roate;  
        //glRotatef(angle, 0.0, 1.0, 0.0);  
        //angle += 1.0f;  
        glEnd();  
        glutSwapBuffers();  
    }  

实验结果:

8)将立方体替换为圆环,观看显示效果。

核心代码:

  1. //画圆环:  
    void display()  
    {  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        glColor3f(1.0, 0.0, 0.0); //画笔红色  
        glLoadIdentity();  //加载单位矩阵    
        //视角  
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  
        glRotatef(angle, 0.0f, 1.0f, 0.0f);  
        glRotatef(0.0, 1.0, 0.0, 0.0);  
        glRotatef(0.0, 0.0, 1.0, 0.0);  
        glRotatef(0.0, 0.0, 0.0, 1.0);  
        glutWireTorus(0.2, 1.5, 20, 40);  
        glEnd();  
        glutSwapBuffers();  
    }  

实验结果:

⒉.构思绘制茶壶和圆环造型程序Teapot_Torus.cpp。在紧挨着茶壶下方添加一个平行的圆环,茶壶和圆环不停绕中心轴旋转,观看显示效果,效果图参见实验图9-2。

实验结果:

三、最终代码

  1. #include<GL/glut.h>  
    #include<math.h>  
      
    #include<iostream>  
    #define COLOR 8.0  
    #define PIX ((GLfloat)(1.0 / COLOR))  
    #define STEP 1.0f  
    #define PI acos(-1)  
    //此处使用pai的值  
    using namespace std;  
      
    // 旋转初始的角度  
    GLfloat angle = 0.0f;  
    // 设置旋转轴:两个三维的点确定的旋转轴  
    GLfloat axis[][3] = {  
        0.5f,0.5f, 0.0f,  
        0.5f, 0.5f, 1.0f  
    };  
      
      
      
      
    void display_2()  
    {  
        // 设置逆时针排列的点围成的平面为正面  
        glFrontFace(GL_CCW);  
        // 设置不绘制背面,节省算力同时不会出现背面覆盖正面的情况  
        glCullFace(GL_BACK);  
        glEnable(GL_CULL_FACE);  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        // 加载单位阵  
        glLoadIdentity();  
        // 设置相机的位置和视角  
        // 有关gluLookAt:https://blog.csdn.net/Augusdi/article/details/20470813  
        //gluLookAt(2, 2, 2, 0.0, 1, 0.0, -1, -1, 1);//修改目标点  
        //gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, -1, -1, 1);//修改视点  
         //gluLookAt(1, 2, 0, 0.0, 1, 0.0, -1, -1, 1);//修改目标点和视点  
        gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);  
        // 设置绕给定的轴旋转  
        glTranslatef(axis[0][0], axis[0][1], axis[0][2]);  
        glRotatef(angle, axis[1][0] - axis[0][0], axis[1][1] - axis[0][1], axis[1][2] - axis[0][2]);  
        glTranslatef(-axis[0][0], -axis[0][1], -axis[0][2]);  
        // 设置立方体的八个顶点坐标  
      
        static const GLfloat vertex[][3] = {  
            0.0f, 0.0f, 0.0f,  
            1.0f, 0.0f, 0.0f,  
            0.0f, 1.0f, 0.0f,  
            1.0f, 1.0f, 0.0f,  
            0.0f, 0.0f, 1.0f,  
            1.0f, 0.0f, 1.0f,  
            0.0f, 1.0f, 1.0f,  
            1.0f, 1.0f, 1.0f  
        };  
      
        /* 
    //修改正方体大小 
    static const GLfloat vertex[][3] = { 
        0.0f, 0.0f, 0.0f, 
        1.5f, 0.0f, 0.0f, 
        0.0f, 1.5f, 0.0f, 
        1.5f, 1.5f, 0.0f, 
        0.0f, 0.0f, 1.5f, 
        1.50f, 0.0f, 1.5f, 
        0.0f, 1.5f, 1.5f, 
        1.5f, 1.5f, 1.5f 
    }; 
        */  
        // 设置绘制六个面时顶点的顺序  
        static const GLint index[][4] = {  
            0, 2, 3, 1,  
            0, 4, 6, 2,  
            0, 1, 5, 4,  
            4, 5, 7, 6,  
            1, 3, 7, 5,  
            2, 6, 7, 3  
        };  
        // 绘制六个面  
        glBegin(GL_QUADS);  
        for (unsigned int i = 0; i < 6; i++)  
            for (unsigned int j = 0; j < 4; j++) {  
                // 每个顶点的RGB颜色值和其顶点位置坐标一致  
                glColor3fv(vertex[index[i][j]]);  
                glVertex3fv(vertex[index[i][j]]);  
            }  
      
      
        glEnd();  
        // 双缓冲下的刷新帧缓存  
        glutSwapBuffers();  
    }  
    //画茶壶  
    void displaytadpot(void)  
    {  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        glColor3f(1.0, 0.0, 0.0); //画笔红色  
        glLoadIdentity();  //加载单位矩阵    
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  
        glRotatef(angle, 0.0f, 1.0f, 0.0f);  
        glRotatef(0.0, 1.0, 0.0, 0.0);  
        glRotatef(0.0, 0.0, 1.0, 0.0);  
        glRotatef(0.0, 0.0, 0.0, 1.0);  
        glutWireTeapot(1.5);  
        //rote += roate;  
        //glRotatef(angle, 0.0, 1.0, 0.0);  
        //angle += 1.0f;  
        glEnd();  
        glutSwapBuffers();  
    }  
      
    //画圆环:  
      
    void displayTorus()  
    {  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        glColor3f(1.0, 0.0, 0.0); //画笔红色  
        glLoadIdentity();  //加载单位矩阵    
        //视角  
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  
        glRotatef(angle, 0.0f, 1.0f, 0.0f);  
        glRotatef(0.0, 1.0, 0.0, 0.0);  
        glRotatef(0.0, 0.0, 1.0, 0.0);  
        glRotatef(0.0, 0.0, 0.0, 1.0);  
        glutWireTorus(0.2, 1.5, 20, 40);  
        glEnd();  
        glutSwapBuffers();  
    }  
      
    //画圆环和茶狐混合绕一个轴旋转  
    void displayTeapot_Torus()  
    {  
        // 设置背景为白色  
        glClearColor(1.0, 1.0, 1.0, 1.0);  
        glClear(GL_COLOR_BUFFER_BIT);  
        glColor3f(1.0, 0.0, 0.0); //画笔红色  
        glLoadIdentity();  //加载单位矩阵    
        //视角  
        gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);  
        glRotatef(angle, 0.0f, 1.0f, 0.0f);  
        glRotatef(0.0, 1.0, 0.0, 0.0);  
        glRotatef(0.0, 0.0, 1.0, 0.0);  
        glRotatef(0.0, 0.0, 0.0, 1.0);  
        glutWireTorus(0.2, 1.5, 20, 40);  
        glRotatef(90, 1, 0, 0);//旋转  
        glTranslatef(0, 0.9, 0);//平移  
        glutWireTeapot(1);  
        glEnd();  
        glutSwapBuffers();  
    }  
    // 绘制圆环  
    // 大半径Radius,小半径TubeRadius,边数Sides, 环数Rings  
      
      
      
    // 动画所需的定时器回调函数  
    // 有关定时器回调函数:https://blog.csdn.net/shimazhuge/article/details/17894883  
    void timer_function(GLint value)  
    {  
        // 旋转角度增加  
        angle += STEP;  
        // 若角度大于360转完一圈则清零  
        if (angle > 360.0) angle -= 360.0;  
        glutPostRedisplay();  
        glutTimerFunc(50, timer_function, value);  
    }  
      
    // 窗口大小自适应函数,使得窗口大小改变时仍保持图形的比例不变  
    // 有关窗口自适应函数:http://blog.sina.com.cn/s/blog_5497dc110102w8qh.html  
    //透视投影  
    void reshape(int w, int h)  
    {  
        glViewport(0, 0, (GLsizei)w, (GLsizei)h);  
        glMatrixMode(GL_PROJECTION);//投影矩阵  
        glLoadIdentity();  
        gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);  
        glMatrixMode(GL_MODELVIEW);//切换回模型视图矩阵  
        //glLoadIdentity();  
        //gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);  
    }  
      
    //正交投影  
    void reshape_2(int w, int h)  
    {  
        glViewport(0, 0, (GLsizei)w, (GLsizei)h);  
        glMatrixMode(GL_PROJECTION);//投影矩阵  
        glLoadIdentity();  
      
        //使用正交投影  
        if (w <= h)  
            glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,  
                2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);  
        else  
            glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,  
                2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);  
      
        glMatrixMode(GL_MODELVIEW);  
    }  
      
      
    int main(int argc, char** argv)  
    {  
        glutInit(&argc, argv);  
        // 设置双缓冲和RGB颜色模式  
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);  
        // 设置窗口大小、位置和名称  
        glutInitWindowSize(500, 500);  
        glutInitWindowPosition(100, 100);  
        glutCreateWindow("实验九");  
        // 设置绘制函数、窗口大小自适应函数和定时器回调函数  
        glutDisplayFunc(displayTeapot_Torus);  
        glutReshapeFunc(reshape);  
        //glEnable(GL_DEPTH_TEST); //使用了深度缓存这行不能掉  
        glutTimerFunc(500, timer_function, 1);  
        // 进入主循环  
        glutMainLoop();  
        return 0;  
    } 

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值