C++ VS OpenGL绘制教室三维立体旋转图像

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: C++ VS OpenGL绘制教室三维立体旋转图像
程序示例精选
C++ VS OpenGL绘制教室三维立体旋转图像
如需安装运行环境或远程调试,可点击
博主头像进入个人主页查看博主联系方式,由专业技术人员远程协助!

前言

这篇博客针对《C++ VS OpenGL绘制教室三维立体旋转图像》编写代码,代码整洁,规则,易读。 学习与应用推荐首选。

运行结果

文章目录

一、所需工具软件
二、使用步骤
1. 主要代码
2. 运行结果

三、在线协助

一、所需工具软件

1. VS2019, C++
2. Yolov8, OpenCV

二、使用步骤

代码如下(示例):

#include<windows.h>
#include<math.h>
#include<time.h>
#pragma warning(disable:4996)
/*******************************定义程序中所用的常数变量******************************************/
GLfloat light_position1[] = {
   
    0,28,0,1.0 };
GLfloat model_ambient[] = {
   
    0.05f,0.05f,0.05f,1.0f };
GLfloat mat_specular[] = {
   
    0.8,1.0,1.0,1.0 };
GLfloat mat_shininess[] = {
   
    5.0 };
GLfloat mat_ambient[] = {
   
    0.1,0.1,0.1,1 };
GLfloat white_light[] = {
   
    1.0,1.0,1.0,1.0 };
GLfloat light[] = {
   
    1.0,1.0,1.0,1 };
GLfloat light_position0[] = {
   
    0,28,20,1.0 };

GLUquadricObj* qobj;
int           fantheta = 0;
BOOL          TurnOn = FALSE;

// 当前时间,时 分 秒
float h = 0.0f;
float m = 0.0f;
float s = 0.0f;
const GLfloat PI = 3.141592653f;
/************************定义视点结构*********************************************************/
typedef struct EyePoint
{
   
   
    GLfloat    x;
    GLfloat y;
    GLfloat z;
}EyePoint;
EyePoint     myEye;
EyePoint    vPoint;
EyePoint    up;
GLfloat pro_up_down = 29.0f;
GLfloat vAngle = 0;
/****************************载入位图作为纹理的相关函数************************************/
#define BMP_Header_Length 54

int power_of_two(int n)
{
   
   
    if (n <= 0)
        return 0;
    return (n & (n - 1)) == 0;
}
/****************************载入一副位图作为纹理,返回的是纹理编号**********************************************/
GLuint load_texture(const char* file_name)
{
   
   

    // 读取文件中图象的宽度和高度
    fseek(pFile, 0x0012, SEEK_SET);
    fread(&width, 4, 1, pFile);
    fread(&height, 4, 1, pFile);
    fseek(pFile, BMP_Header_Length, SEEK_SET);
    // 计算每行像素所占字节数,并根据此数据计算总像素字节数
    {
   
   
        GLint line_bytes = width * 3;
        while (line_bytes % 4 != 0)
            ++line_bytes;
        total_bytes = line_bytes * height;
    }
    // 根据总像素字节数分配内存
    pixels = (GLubyte*)malloc(total_bytes);
    if (pixels == 0)
    {
   
   
        fclose(pFile);
        return 0;
    }
    // 读取像素数据
    if (fread(pixels, total_bytes, 1, pFile) <= 0)

        GLint max;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);//获得OpenGL所支持的最大纹理

        if (!power_of_two(width) || !power_of_two(height) || width > max || height > max)
        {
   
   
            const GLint new_width = 256;
            const GLint new_height = 256; // 规定缩放后新的大小为边长的正方形
            GLint new_line_bytes, new_total_bytes;
            GLubyte* new_pixels = 0;
            // 计算每行需要的字节数和总字节数
            new_line_bytes = new_width * 3;
            while (new_line_bytes % 4 != 0)
                ++new_line_bytes;
            new_total_bytes = new_line_bytes * new_height;
            // 分配内存
            new_pixels = (GLubyte*)malloc(new_total_bytes);
            if (new_pixels == 0)
            {
   
   
                free(pixels);
                fclose(pFile);
                return 0;
            }
            // 进行像素缩放
            gluScaleImage(GL_RGB, width, height, GL_UNSIGNED_BYTE, pixels, new_width, new_height, GL_UNSIGNED_BYTE, new_pixels);
            // 释放原来的像素数据,把 pixels 指向新的像素数据,并重新设置 width 和 height
            free(pixels);
            pixels = new_pixels;
            width = new_width;
            height = new_height;
        }

}
/**********************************定义各个纹理对象的名称************************************/
GLuint texblackboard, texwindow, texdesk, texsound;
GLuint texceiling, texdoor, texfloor, texbackwall, texpole;
GLuint texairfro, texairback, texhighland, texsdesk, texclock;
/*******************************绘制相关函数**************************************************/

//绘制教室这个大场景
void drawscence()
{
   
   
    //设置材质相关参数
    /*指定材质对漫射光的反射率,第一个参数决定该材质运用于图元的正面还是反面
    第二个参数表示对何种光进行设置,GL_AMBIENT(环境光)、GL_DIFFUSE(漫射光)、
    GL_AMBIENT_AND_DIFFUSE(环境光和漫射光)、GL_SPECULAR(平行/镜面光,
    第三个参数是一个四维数组,这个数组描述了反光率的RGBA值,每一项取值都为0-1之间*/
    glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse1);
    glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
    glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
    glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

    //首先绘制天花板
    glEnable(GL_TEXTURE_2D);//开启2D纹理功能

    glBindTexture(GL_TEXTURE_2D, texceiling);//绑定纹理
    //glColor3f(0.3, 0.3, 0.3);//设置颜色,黑色
    //glColor3f(255, 255, 255);
    glBegin(GL_QUADS);//画四边形

    glNormal3f(0.0f, -1.0f, 0.0f);//用于定义法线向量
    /*glTexCoord2f绘制图形时指定纹理的坐标,第一个是X轴坐标,0.0是纹理的左侧,0.5是纹理的中点,1.0是纹理的右侧,
    第二个是Y轴坐标,0.0是纹理的底部,0.5是纹理的中点,1.0是纹理的顶部,
    为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角,纹理的左上角映射到四边形的左上角,
    纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下角,纹理的左上坐标是X:0.0,Y:1.0f,四边形的左上顶点是X:-1.0,Y:1.0。*/
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-40.0f, 30.0f, 30.0f);//四边形的点
    glTexCoord2f(0.0f, 3.0f); glVertex3f(-40.0f, 30.0f, -30.0f);
    glTexCoord2f(6.0f, 3.0f); glVertex3f(40.0f, 30.0f, -30.0f);
    glTexCoord2f(6.0f, 0.0f); glVertex3f(40.0f, 30.0f, 30.0f);
    glEnd();
    glDisable(GL_TEXTURE_2D);


    //................................风扇................................................//
    GLuint m = 0;


    qobj = gluNewQuadric();//初始化二次曲面并创建一个指向二次曲面的指针 

//...............................右边的风扇.............................//
    glPushMatrix();//压入堆栈,保证此处坐标变换不影响外部大环境 
    glTranslatef(20.0, 5.0, -10.0 - 40 * m);  //风扇的位置
    if (TurnOn == TRUE)  //如果TurnOn为1
    {
   
   
        fantheta += 10;  //风扇转过的角度fantheta不断增加


    }
    glRotatef(fantheta, 0, 1, 0);        //风扇旋转



    glPushMatrix();//压入堆栈
    glColor3f(0.7, 0.7, 0.7);

    glTranslatef(0, 20, 0.0);//平移变换
    glScalef(1, 0.05, 1);//缩放变换
    glRotatef(240, 0, 1, 0);//绕y周旋转240度    
    gluCylinder(qobj, 1, 3, 10, 20, 20);//绘制一个底面圆半径为1、顶面圆半径为2、高为10的圆锥体
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, light_Diffuse);//定义材质光照
    glPopMatrix();//弹出堆栈
//.............风扇的杆...........................//

    glPushMatrix();//压入堆栈
    glTranslatef(0, 33, 0.0);//平移变换
    glRotatef(90, 1, 0, 0);//缩放变换
    gluCylinder(qobj, 0.5, 0.5, 13, 10, 10);//绘制一个半径为0.5、高为13的圆锥体
    glPopMatrix();//弹出堆栈

    glPopMatrix();//弹出堆栈

//................左边的风扇...........................................//

    glPushMatrix();
    glTranslatef(-20.0, 5.0, -10.0 - 40 * m);
    if (TurnOn == TRUE)
    {
   
   
        fantheta += 10;

    }

    glRotatef(fantheta, 0, 1, 0);
    //..........风扇中间的扁圆形....................//

    glPushMatrix();//风扇中间的扁圆形
    glColor3f(0.7, 0.7, 0.7);
    glTranslatef(0.0, 20.0, 0.0);
    glScalef(1, 0.3, 1);
    gluSphere(qobj, 2, 20, 20);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, light_Diffuse);
    glPopMatrix();
    //............风扇旋转120度的扇叶...............//        

    glPushMatrix();//风扇旋转120度的扇叶
    glColor3f(0.7, 0.7, 0.7);
    glTranslatef(0, 20, 0.0);
    glScalef(1, 0.05, 1);
    glRotatef(120, 0, 1, 0);
    gluCylinder(qobj, 1, 3, 10, 20, 20);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, light_Diffuse);
    glPopMatrix();
    //............风扇不做旋转的扇叶.................//

    glPushMatrix();//风扇不做旋转的扇叶
    glColor3f(0.7, 0.7, 0.7);
    glTranslatef(0, 20, 0.0);
    glScalef(1, 0.05, 1);
    gluCylinder(qobj, 1, 3, 10, 20, 20);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, light_Diffuse);
    glPopMatrix();
    //.............风扇旋转240度的扇叶...............//

    glPushMatrix();//风扇旋转240度的扇叶
    glColor3f(0.7, 0.7, 0.7);
    glTranslatef(0, 20, 0.0);
    glScalef(1, 0.05, 1);
    glRotatef(240, 0, 1, 0);
    gluCylinder(qobj, 1, 3, 10, 20, 20);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, light_Diffuse);
    glPopMatrix();
    //.............风扇的杆...........................//

    glPushMatrix();
    glTranslatef(0, 33, 0.0);
    glRotatef(90, 1, 0, 0);
    gluCylinder(qobj, 0.5, 0.5, 13, 10, 10);
    glPopMatrix();
    glPopMatrix();






    //绘制黑板
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texblackboard);
    glBegin(GL_QUADS);
    glNormal3f(0.0f, 0.0f, 1.0f); //用于定义法线向量
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-20.0, 8.0f, -29.9f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-20.0, 18.0f, -29.9f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(20.0, 18.0f, -29.9f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(20.0, 8.0f, -29.9f);
    glEnd();
    glDisable(GL_TEXTURE_2D);

    //画黑板上方的灯
    GLfloat blacklight[] = {
   
    0.9,0.9,0.9,1 };//颜色(R,G,B,A),A仅用于颜色混合函数激活之后
    glColor3f(1.0f, 1.0f, 1.0f);
    //glColor3f(255, 255, 255);
    glPushMatrix();//把当前的模型视图矩阵压入堆栈中保存下来
    glTranslatef(-15, 20.4, -29.5);//平移函数,参数含义:位移
    glScalef(8.0f, 0.8, 1.0f);//缩放函数,参数含义:倍数
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blacklight);
    glutSolidCube(1.0f);//绘制边长为1的实心立方体,立方体的中心位于原点
    glPopMatrix();
    glPushMatrix();
    glTranslatef(12, 20.4, -29.5);
    glScalef(8.0f, 0.8, 1.0f);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blacklight);
    glutSolidCube(1.0f);
    glPopMatrix();
    //绘制教室前边一块高地并贴纹理
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texhighland);
    //贴上面
    glBegin(GL_QUADS);
    glNormal3f(0.0f, 1.0f, 0.0f); //用于定义法线向量
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-30.0f, 1.5f, -22.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-30.0f, 1.5f, -30.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(30.0f, 1.5f, -30.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(30.0f, 1.5f, -22.0f);
    glEnd();
    //贴左边
    glBegin(GL_QUADS);
    glNormal3f(0.0f, 0.0f, 1.0f); //用于定义法线向量
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-30.0f, 0, -22.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-30.0f, 1.5f, -22.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-30.0f, 1.5f, -30.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-30.0f, 0, -30.0f);
    glEnd();
    //贴前边
    glBegin(GL_QUADS);
    glNormal3f(0.0f, 1.0f, 0.0f); //用于定义法线向量
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-30.0f, 0, -22.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-30.0f, 1.5f, -22.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(30.0f, 1.5f, -22.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(30.0f, 0, -22.0f);
    glEnd();

    //glColor3f(255, 255, 255);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texdoor);
    glBegin(GL_QUADS);
    glNormal3f(-1.0f, 0.0f, 0.0f); //用于定义法线向量
    glTexCoord2f(0.0f, 0.0f); glVertex3f(39.9f, 0.0f, -25.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(39.9f, 14.0f, -25.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(39.9f, 14.0f, -19.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(39.9f, 0.0f, -19.0f);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    //绘制音响
    glColor3f(0.0f, 0.0f, 0.0f);
    //glColor3f(255, 255, 255);
    glPushMatrix();
    glTranslatef(-37.5, 26.25f, -5.5f);
    glScalef(1.0f, 1.5f, 1.0f);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, sound);
    glutSolidCube(1.0f);
    glPopMatrix();
    glPushMatrix();
    glTranslatef(37.5, 26.25f, -5.5f);
    glScalef(1.0f, 1.5f, 1.0f);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, sound);
    glutSolidCube(1.0f);
    glPopMatrix();



}
/**************************************绘制投影仪***********************************************/
void drawprojector()
{
   
   
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_QUADS);
    glNormal3f(1.0f, 0.0f, 1.0f); //用于定义法线向量
    glVertex3f(-40.0f, 30.0f, -30.0 + 10 * sqrt(2));
    glVertex3f(-40.0 + 10 * sqrt(2), 30.0f, -30.0f);//固定的两个点
    glVertex3f(-40.0 + 10 * sqrt(2), pro_up_down, -30.0f);
    glVertex3f(-40.0f, pro_up_down, -30.0 + 10 * sqrt(2));//下降或升起时改变的点
    glEnd();
    glColor3f(0.0f, 0.0f, 0.0f);
    glLineWidth(4.0f);
    glBegin(GL_LINES);
    glVertex3f(-25.0f, 30.0f, -15.0f);
    glVertex3f(-25.0f, 25.0f, -15.0f);
    glEnd();
    glColor3f(0.5f, 0.5f, 0.5f);
    glPushMatrix();
    glTranslatef(-25.0f, 24.0f, -15.0f);
    glScalef(4.0f, 2.0f, 2.0f);
    glutSolidCube(1.0f);
    glPopMatrix();
    glColor3f(0.0, 0.0, 0.0);
    glBegin(GL_LINE_LOOP);//给出的点会绘制为一个环(所有的点首尾相接)
    glVertex3f(-40.0f, 30.0f, -30.0 + 10 * sqrt(2));
    glVertex3f(-40.0 + 10 * sqrt(2), 30.0f, -30.0f);

    }
}
//绘制椅子
void drawchairs()
{
   
   
    GLfloat chair[] = {
   
    1.0f, 1.0f, 0.45f, 1.0f };// { 0.1, 0.67, 0.62 };
    for (int j = 0; j <= 4; j++)
    {
   
   
        for (int i = 0; i <= 1; i++)
        {
   
   
            //画椅子底部
            glColor3f(0.1, 0.67, 0.62);
            glPushMatrix();
            glTranslatef(-20 + i * 40, 3.1, -14.5 + j * 8);
            glScalef(10, 0.2, 3);
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, chair);
            glutSolidCube(1.0f);
            glPopMatrix();
            //画椅子靠背
            glColor3f(0.1, 0.67, 0.62);
            glPushMatrix();
            glTranslatef(-20 + i * 40, 5, -13 + j * 8);
            glScalef(10, 4, 0.2);
            glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, chair);
            glutSolidCube(1.0f);
            glPopMatrix();
            //画椅子腿
            glColor3f(0.0, 0.0, 0.0);
            glBegin(GL_LINES);
            glLineWidth(3.0f);
            glVertex3f(-25 + i * 40, 3.0f, -13 + j * 8);
            glVertex3f(-25 + i * 40, 0.0f, -13 + j * 8);
            glEnd();
            glColor3f(0.0, 0.0, 0.0);
            glBegin(GL_LINES);
            glLineWidth(3.0f);
            glVertex3f(-15.0 + i * 40, 3.0f, -13 + j * 8);
            glVertex3f(-15.0 + i * 40, 0.0f, -13 + j * 8);
            glEnd();
            glColor3f(0.0, 0.0, 0.0);
            glBegin(GL_LINES);
            glLineWidth(3.0f);
            glVertex3f(-25.0 + i * 40, 0.0f, -12.5 + j * 8);
            glVertex3f(-25 + i * 40, 0.0f, -13.5 + j * 8);
            glEnd();
            glColor3f(0.0, 0.0, 0.0);
            glBegin(GL_LINES);
            glLineWidth(3.0f);
            glVertex3f(-15 + i * 40, 0.0f, -12.5 + j * 8);
            glVertex3f(-15 + i * 40, 0.0f, -13.5 + j * 8);
            glEnd();



/*******************************************响应普通键盘操作,w,s,a,d以及退出esc键*******************************/
GLvoid OnKeyboard(unsigned char key, int x, int y)
{
   
   
    switch (key)
    {
   
   
    case 97://a 向左
        myEye.x -= 0.5;
        vPoint.x -= 0.5;
        if (myEye.x <= -38)
            myEye.x = -38;
        break;
    case 100://d 向右
        myEye.x += 0.5;
        vPoint.x += 0.5;
        if (myEye.x >= 38)
            myEye.x = 38;
        break;
    case 119://w 向前
        myEye.z -= 0.5;
        if (myEye.z <= -28)
            myEye.z = -28;
        break;
    case 115://s 向后
        myEye.z += 0.5;
        if (myEye.z >= 28)
            myEye.z = 28;
        break;
    case 27://esc
        exit(0);

    }
    reshape(WinWidth, WinHeight);//窗口刷新
    glutPostRedisplay();

}
/****************************************响应特殊键盘操作******************************************************/
GLvoid OnSpecial(int key, int x, int y)//上下左右
{
   
   
    switch (key)
    {
   
   
    case GLUT_KEY_LEFT:
        vAngle -= 0.05;
        break;
    case GLUT_KEY_RIGHT:
        vAngle += 0.05;
        break;
    case GLUT_KEY_UP:
        myEye.y += 0.05;
        if (myEye.y >= 30)
            myEye.y = 30;

        break;
    case GLUT_KEY_DOWN:
        myEye.y -= 0.5;
        if (myEye.y <= 0)
            myEye.y = 30;
        break;
    case GLUT_KEY_PAGE_DOWN://PageDown键
        myEye.z += 0.5;
        if (myEye.z >= 30)
            myEye.z = 30;
        break;
    case GLUT_KEY_PAGE_UP://PageUp键
        myEye.z -= 0.5;
        if (myEye.z <= -30)
            myEye.z = -30;
        break;
    case GLUT_KEY_F1:
        projectup();
        break;
    case GLUT_KEY_F2:
        projectdown();
        break;
    case GLUT_KEY_F3:
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glEnable(GL_LIGHT1);
        break;
    case GLUT_KEY_F4:
        //glDisable(GL_TEXTURE_2D);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glDisable(GL_LIGHT1);
        break;
    case GLUT_KEY_F5:
        TurnOn = true;
        break;
    case GLUT_KEY_F6:
        TurnOn = false;
        break;
    }
    reshape(WinWidth, WinHeight);
    glutPostRedisplay();
}
GLvoid OnIdle()
{
   
   
    glutPostRedisplay();// 重画
    //当回调函数处理完键盘事件后,显示函数会自动被调用,屏幕会被重绘.这样,GLUT程序会过于频繁的调用显示函数,抢占cpu资源
    //选择性的告诉GLUT去调用显示函数(glutPostRedisplay函数会标记当前窗体来重新显示)
    //目的:节省cpu资源,保持我们的GLUT程序的占用行为不生效.
}
/*************************************初始化函数,对各项参数进行初始化*********************************************/
void initial()
{
   
   
    glClearColor(0, 0, 0, 0);
    glEnable(GL_TEXTURE_2D);

    /*设置纹理跟材质的融合方式,这里是只是用纹理,覆盖模型的材质*/
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    /*********************************************对灯光进行初始化****************************************************/
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);//将背景光设定为全局值
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);//把无限远的观察点改为局部观察点
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);//指定物体前面镜面反射的颜色
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);//指定物体前面镜面反射的指数
    /*设置点光源*/
    /*GL_POSITION指定光源位置,GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度(颜色),
    对背景(环境)光有贡献。GL_DIFFUSE表示光线照射到该材质上,经过漫反射后形成的光线强度(颜色)。
    GL_SPECULAR表示光线照射到该材质上,经过镜面反射后形成的光线强度(颜色)。通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,
    可以达到比较真实的效果。使用GL_AMBIENT_AND_DIFFUSE可以同时设置GL_AMBIENT和GL_DIFFUSE属性。*/
    /*glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
    glLightfv(GL_LIGHT0, GL_AMBIENT, mat_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light);*/

    /*设置平行光源*/
    glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
    glLightfv(GL_LIGHT1, GL_AMBIENT, mat_ambient);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
    glLightfv(GL_LIGHT1, GL_SPECULAR, white_light);


    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT1);
    glEnable(GL_COLOR_MATERIAL);//激活

    /**********************************************************************************************/
    /*glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式,
    GL_SMOOTH(默认)将制定的两点颜色进行插值,绘制之间的其他点*/
    glShadeModel(GL_SMOOTH);
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);    //指定材料着色的面
    //glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);    //指定材料对镜面光的反射
    glEnable(GL_DEPTH_TEST);//    
}
void print()
{
   
   
    printf("**************************************************** \n");
    printf(" \n");
    printf("操作按键信息提示: \n");
    printf("上键和下键分别控制视角向下和向上 \n");
    printf("左键和右键分别控制向左环视和向右环视 \n");
    printf("w,s,a,d键分别表示向前,后,左,右,进行平移(注意键盘大小写)\n");
    printf("pgup和pgdn分别控制向前漫游和向后漫游 \n");
    printf("F5、F6键分别控制风扇的开、关 \n");
    printf("F3、F4键分别控制开灯、关灯 \n");
    printf("F1、F2键分别控制投影仪放下和收起 \n");
    printf("ESC键退出窗口 \n");
    printf(" \n");

}
int main(int argc, char* argv[])
{
   
   
    myEye.x = 0;
    myEye.y = 15;
    myEye.z = 25;
    vPoint.x = 0;
    vPoint.y = 15;
    vPoint.z = -30;
    up.x = 0;
    up.y = 1;
    up.z = 0;
    vAngle = 0;
    /*启用了之后,OpenGL在绘制的时候就会检查,当前像素前面是否有别的像素,
    如果别的像素挡道了它,那它就不会绘制,也就是说,OpenGL就只绘制最前面的一层。*/
    glEnable(GL_DEPTH_TEST);
    glutInit(&argc, argv);
    /*定义显示方式,GLUT_RGBA指定一个RGBA窗口,GLUT_SINGLE.单缓冲区窗口*/
    glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);

    glutInitWindowPosition(400, 0);//设置初始窗口的位置(窗口左上角相对于桌面坐标(x,y))
    glutInitWindowSize(800, 600);//设置窗口大小
    glutCreateWindow("classroom");
    initial();//创建显示窗口
    SetupRC();//(2)
    glutDisplayFunc(&myDisplay);
    glutTimerFunc(1000, timerFunc, 1);//(1)
    //glutDisplayFunc(&myDisplay);//注册显示回调函数,包含重绘场景所需的所有代码
    glutReshapeFunc(reshape);//注册窗口改变回调函数
    glutKeyboardFunc(OnKeyboard);//注册键盘响应事件
    //对键盘上特殊的4个方向按键的响应函数
    glutSpecialFunc(OnSpecial);
    glutIdleFunc(OnIdle);//注册闲置响应函数,该函数调用放在主程序main()中,通常利用它可实现简单动画。
    ///***************************************设置纹理***********************************************/
    texblackboard = load_texture("blackboard.bmp");
    texwindow = load_texture("window.bmp");
    texsound = load_texture("sound.bmp");
    texceiling = load_texture("ceiling.bmp");
    texdoor = load_texture("door.bmp");
    texfloor = load_texture("floor.bmp");
    texbackwall = load_texture("backwall.bmp");
    texpole = load_texture("pole.bmp");
    texairfro = load_texture("airconditionfront.bmp");
    texairback = load_texture("airconditionback.bmp");
    texhighland = load_texture("gaodi.bmp");
    texsdesk = load_texture("sdesk.bmp");
    texclock = load_texture("clock.bmp");
    ///************************************************************************************************/
    print();
    //开始显示
    glutMainLoop();//进入事件处理循环
    return 0;
}

运行结果

三、在线协助:

如需安装运行环境或远程调试,可点击博主头像,进入个人主页查看博主联系方式,由专业技术人员远程协助!

1)远程安装运行环境,代码调试
2)Visual Studio, Qt, C++, Python编程语言入门指导
3)界面美化
4)软件制作

博主个人主页:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主所有文章点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
博主联系方式点这里:https://developer.aliyun.com/profile/expert/rfnzgp3sk3ahc
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
存储 数据采集 数据可视化
【C++】医院PACS医学图像存储和传输系统源码
图像后处理与重建 •MPR\CPR(三维多平面重建) •VRT(三维容积重建) •SSD(三维表面重建) •VE(虚拟内窥镜) •MIP(最大密度投影)、MinIP(最小密度投影) •CalSCore(心脏图像冠脉钙化积分)
32 3
|
3月前
QT4.7版本的OPENGL的3D旋转模型例子
QT4.7版本的OPENGL的3D旋转模型例子
|
3月前
|
存储 数据处理 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机的高速图像保存(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机的高速图像保存(C++)
42 0
|
3月前
|
存储 新制造 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)
41 2
|
3月前
|
数据采集 API 开发工具
Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)
Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)
39 0
Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C++)
|
3月前
|
存储 数据处理 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机图像转换由Mono10转换为Mono8(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机图像转换由Mono10转换为Mono8(C++)
52 0
|
3月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
33 0
|
3月前
|
存储 监控 开发工具
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C++)
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为AVI视频格式(C++)
35 0
|
3月前
|
存储 传感器 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK修改图像像素格式Mono8或者Mono10(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK修改图像像素格式Mono8或者Mono10(C++)
43 0
|
1月前
|
算法 编译器 C语言
【C++ 函数 基本教程 第六篇 】深度解析C++函数符号:GCC与VS的名称修饰揭秘
【C++ 函数 基本教程 第六篇 】深度解析C++函数符号:GCC与VS的名称修饰揭秘
42 1

热门文章

最新文章