首页 > 技术文章 > OpenGL实验(二三代码整理)桌子

BirdCage 2017-04-08 23:56 原文

终于把桌子都搞定了(虽然还是有点丑?)算是把一开始想做的都做了吧

table.h

//@author Birdy&C 2017.4.7
#pragma once
#define GLUT_DISABLE_ATEXIT_HACK
#include <stdio.h>
#include<windows.h>
#include <gL\GLAUX.H>
#include <gl\GLUT.H>  

//函数声明

//===========main.cpp============//

void init();

//===========event.cpp============//
void timer(int p);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);
void special(int key, int x, int y);
void keyboard(unsigned char key, int x, int y);
void setProjection(int width, int height);
void reshape(int w1, int h1);

//===========render.cpp============//
AUX_RGBImageRec *LoadBMP(CHAR *Filename); 
int LoadGLTextures();
void Draw_Leg();
void Draw_Table();
void drawMain();
void renderScene(); 
void renderScenesw1();
void renderScenesw2(); 
void renderScenesw3();
void renderSceneAll();



//全局变量

extern bool mouseisdown, loopr;
extern int mainWindow, subWindow1, subWindow2, subWindow3, rx, ry, rz, tx, ty, w, h;
extern int time, state;
extern const int border;
extern float  mx, mz;
extern GLuint  texture[1]; 

render.cpp

// render.cpp : 绘制函数
//@author Birdy&C 2017.4.7

#include "table.h"


AUX_RGBImageRec *LoadBMP(CHAR *Filename)    // 载入位图图象
{
    FILE *File = NULL;                      // 文件句柄
    int check;
    if (!Filename)                          // 确保文件名已提供
    {
        return NULL;                        // 如果没提供,返回 NULL
    }
    check = fopen_s(&File, Filename, "r");      // 尝试打开文件
    if (check == 0)                             // 文件存在
    {
        fclose(File);                           // 关闭句柄
        return auxDIBImageLoadA(Filename);      // 载入位图并返回指针
    }
    return NULL;                                // 如果载入失败,返回 NULL
}

int LoadGLTextures()         // 载入位图(调用上面的代码)并转换成纹理
{
    int Status = FALSE;                             // 状态指示器
    AUX_RGBImageRec *TextureImage[1];               // 创建纹理的存储空间
    memset(TextureImage, 0, sizeof(void *) * 1);    // 将指针设为 NULL
    TextureImage[0] = LoadBMP("wood.bmp");          // 载入位图,检查有无错误,如果位图没找到则退出

    if (NULL != TextureImage[0])
    {
        Status = TRUE;                              // 将 Status 设为 TRUE
        printf("LOAD SUCCESS\n");
        glGenTextures(1, &texture[0]);              // 创建纹理

        glBindTexture(GL_TEXTURE_2D, texture[0]);   // 使用来自位图数据生成 的典型纹理

        // 生成纹理
        glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 线形滤波
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 线形滤波
    }

    if (TextureImage[0])                    // 纹理是否存在
    {
        if (TextureImage[0]->data)          // 纹理图像是否存在
        {
            free(TextureImage[0]->data);    // 释放纹理图像占用的内存
        }
        free(TextureImage[0]);              // 释放图像结构
    }
    return Status;                          // 返回 Status
}

void Draw_Leg() // This function draws a triangle with RGB colors
{
    //四面
    glBegin(GL_QUADS);

    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-0.5f, 0.5f, 0.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-0.5f, 0.5f, 3.0f); // 纹理和四边形的左下
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(0.5f, 0.5f, 3.0f); // 纹理和四边形的右下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(0.5f, 0.5f, 0.0f); // 纹理和四边形的右上

    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-0.5f, -0.5f, 0.0f); // 纹理和四边形的右上
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(0.5f, -0.5f, 0.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(0.5f, -0.5f, 3.0f); // 纹理和四边形的左下
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-0.5f, -0.5f, 3.0f); // 纹理和四边形的右下

    glTexCoord2f(1.0f, 0.0f);   glVertex3f(0.5f, -0.5f, 0.0f); // 纹理和四边形的右下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(0.5f, 0.5f, 0.0f); // 纹理和四边形的右上
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(0.5f, 0.5f, 3.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(0.5f, -0.5f, 3.0f); // 纹理和四边形的左下

    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-0.5f, 0.5f, 0.0f); // 纹理和四边形的左下
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-0.5f, -0.5f, 0.0f); // 纹理和四边形的右下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-0.5f, -0.5f, 3.0f); // 纹理和四边形的右上
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-0.5f, 0.5f, 3.0f); // 纹理和四边形的左上

    //底边
    glTexCoord2f(0.4f, 0.0f); glVertex3f(-0.5f, -0.5f, 0); // 纹理和四边形的右下
    glTexCoord2f(0.4f, 0.4f); glVertex3f(-0.5f, 0.5f, 0); // 纹理和四边形的右上
    glTexCoord2f(0.0f, 0.4f); glVertex3f(0.5f, 0.5f, 0); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.4f); glVertex3f(0.5f, -0.5f, 0); // 纹理和四边形的左下

    glEnd();
}

void Draw_Table() // This function draws a triangle with RGB colors
{
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);            //空心
    //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);        //实心
    glBindTexture(GL_TEXTURE_2D, texture[0]);      // 选择纹理
    //glColor3f(1.0f, 1.0f, 1.0f);                      //选择颜色
    //上下
    glBegin(GL_QUADS);

    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-2.5f, 2.0f, 4.0f);// 纹理和四边形的左上
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(2.5f, 2.0f, 4.0f);// 纹理和四边形的右上
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(2.5f, -2.0f, 4.0f); // 纹理和四边形的右下
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-2.5f, -2.0f, 4.0f);// 纹理和四边形的左下

    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-2.5f, -2.0f, 3.0f); // 纹理和四边形的右下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-2.5f, 2.0f, 3.0f);// 纹理和四边形的右上
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(2.5f, 2.0f, 3.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(2.5f, -2.0f, 3.0f); // 纹理和四边形的左下     


    //四面
    glTexCoord2f(0.5f, 0.0f);   glVertex3f(2.5f, -2.0f, 4.0f); // 纹理和四边形的左下
    glTexCoord2f(0.5f, 1.0f);   glVertex3f(2.5f, 2.0f, 3.0f); // 纹理和四边形的右下
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(2.5f, -2.0f, 3.0f); // 纹理和四边形的右上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(2.5f, 2.0f, 4.0f); // 纹理和四边形的左上

    glTexCoord2f(0.5f, 0.0f);   glVertex3f(-2.5f, 2.0f, 3.0f); // 纹理和四边形的左上
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-2.5f, -2.0f, 3.0f);// 纹理和四边形的左下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-2.5f, -2.0f, 4.0f); // 纹理和四边形的右下
    glTexCoord2f(0.5f, 1.0f);   glVertex3f(-2.5f, 2.0f, 4.0f); // 纹理和四边形的右上


    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-2.5f, 2.0f, 3.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.5f);   glVertex3f(-2.5f, 2.0f, 4.0f); // 纹理和四边形的左下
    glTexCoord2f(1.0f, 0.5f);   glVertex3f(2.5f, 2.0f, 4.0f); // 纹理和四边形的右下
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(2.5f, 2.0f, 3.0f); // 纹理和四边形的右上


    glTexCoord2f(1.0f, 0.5f);   glVertex3f(-2.5f, -2.0f, 3.0f);// 纹理和四边形的右上
    glTexCoord2f(0.0f, 0.5f);   glVertex3f(2.5f, -2.0f, 3.0f); // 纹理和四边形的左上
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(2.5f, -2.0f, 4.0f); // 纹理和四边形的左下
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-2.5f, -2.0f, 4.0f); // 纹理和四边形的右下



    glEnd();

    //画桌子腿
    glPushMatrix();
    glTranslatef(1.5f, 1.0f, 0.0f);
    Draw_Leg();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(1.5f, -1.0f, 0.0f);
    Draw_Leg();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-1.5f, 1.0f, 0.0f);
    Draw_Leg();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-1.5f, -1.0f, 0.0f);
    Draw_Leg();
    glPopMatrix();


    glFlush();


}

void drawMain()
{
    glPushMatrix();

    if (loopr)
    {
        switch (state)
        {
        case 1:
            mz = 0.1 * time;
            state = 1;
            break;
        case 2:
            rx = 12 * time;
            break;
        case 3:
            glScalef(1 + 0.01*time, 1 + 0.01*time, 1 + 0.01*time);
            break;
        }
    }
    glTranslatef(mx, 0.0f, mz);     // 平移

    //旋转
    glRotatef(rx, 1, 0, 0); 
    glRotatef(ry, 0, 1, 0);
    glRotatef(rz, 0, 0, 1);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存

    Draw_Table();                       // Draw table   

    glPopMatrix();

}

// Display func for main window
void renderScene() {
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glutSwapBuffers();
    glutSetWindow(mainWindow);
    glClear(GL_COLOR_BUFFER_BIT);
    glutPostRedisplay();
}

// Display func for sub window 1
void renderScenesw1() {

    glutSetWindow(subWindow1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    gluLookAt(0, 15.0f, 0, 0, 0, 0, 0.0f, 0.0f, 1.0f);
    glPushMatrix();
    drawMain();
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();

}

// Display func for sub window 2
void renderScenesw2() {

    glutSetWindow(subWindow2);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    gluLookAt(15.0f, 0, 0, 0, 0, 0, 0.0f, 0.0f, 1.0f);
    glPushMatrix();
    drawMain();
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();
}

// Display func for sub window 3
void renderScenesw3() {

    glutSetWindow(subWindow3);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0, 0, 15.0f, 0, 0, 0, 0, -1, 0);
    glPushMatrix();
    drawMain();
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();

}

// Global render func
void renderSceneAll()
{
    renderScene();
    renderScenesw1();
    renderScenesw2();
    renderScenesw3();
}

event.cpp

// event.cpp : 处理事件
//@author Birdy&C 2017.4.7
#include "table.h"

void timer(int p)
{
    time++;
    if (time >= 30)  
        time = 0;
    if (loopr)
    {
        glutTimerFunc(200, timer, 0);//循环
    }
}

void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            mouseisdown = true; 
            loopr = false;
            tx = x;
            ty = y;
        }
        else
        {
            mouseisdown = false;
        }
    }

    if (button == GLUT_RIGHT_BUTTON)
        if (state == GLUT_DOWN)
        {
            loopr = true;
            glutTimerFunc(200, timer, 0);
        }
}

void motion(int x, int y)
{
    if (mouseisdown == true)        //如果是鼠标左键按下拖动
    {
    rz += x - tx;                   //偏移量记录
    rx += y - ty;               
    tx = x;                         //更新坐标
    ty = y;
    glutPostRedisplay();
    }
}

void special(int key, int x, int y)
{
    //上下左右键盘控制xz坐标方向上的平移
    switch (key)
    {
    case GLUT_KEY_LEFT:
        mx += 0.2;
        glutPostRedisplay();
        break;
    case GLUT_KEY_RIGHT:
        mx -= 0.2;
        glutPostRedisplay();
        break;
    case GLUT_KEY_UP:
        mz += 0.2;
        glutPostRedisplay();
        break;

    case GLUT_KEY_DOWN:
        mz -= 0.2;
        glutPostRedisplay();
        break;
    }
}

void keyboard(unsigned char key, int x, int y)
{
    //123改变自动移动方式
    //接收事件的时候改变坐标位置(使得满足作业要求)
    switch (key)
    {
    case '1':
        rx = ry = rz = 0;
        mx = mz = 0;
        mx = 5;
        state = 1;
        break;
    case '2':
        rx = ry = rz = 0;
        mx = mz = 0;
        state = 2;
        break;
    case '3':
        rx = ry = rz = 0;
        mx = mz = 0;
        mx = -5;
        state = 3;
        break;
    }
}

void setProjection(int width, int height)
{
    glViewport(0, 0, width, height);                        // Reset The Current Viewport
    glMatrixMode(GL_PROJECTION);                            // Select The Projection Matrix
    glLoadIdentity();                                       // Reset The Projection Matrix
    // Calculate The Aspect Ratio Of The Window
    gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);                             // Select The Modelview Matrix
    glLoadIdentity();                                       // Reset The Modelview Matrix
}

void reshape(int w1, int h1) {

    if (h1 == 0)
        h1 = 1;

    // we're keeping these values cause we'll need them latter
    w = w1;
    h = h1;

    // set subwindow 1 as the active window
    glutSetWindow(subWindow1);
    // resize and reposition the sub window
    glutPositionWindow(border, border);
    glutReshapeWindow(w - 2 * border, h / 2 - border * 3 / 2);
    setProjection(w - 2 * border, h / 2 - border * 3 / 2);

    // set subwindow 2 as the active window
    glutSetWindow(subWindow2);
    // resize and reposition the sub window
    glutPositionWindow(border, (h + border) / 2);
    glutReshapeWindow(w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);
    setProjection(w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);

    // set subwindow 3 as the active window
    glutSetWindow(subWindow3);
    // resize and reposition the sub window
    glutPositionWindow((w + border) / 2, (h + border) / 2);
    glutReshapeWindow(w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);
    setProjection(w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);
}

main.cpp

// main.cpp : 定义控制台应用程序的入口点。
//@author Birdy&C 2017.4.7

#include "table.h"

//子窗口
int mainWindow, subWindow1, subWindow2, subWindow3;
//旋转记录
int rx = 0;
int ry = 0;
int rz = 0;
//平移记录
float mx = 0;
float mz = 0;
//鼠标位置
int tx, ty;
//边界宽度
const int border = 6;
//主窗口大小
int w, h;
//自动事件控制
bool mouseisdown = false;
bool loopr = false;
int state = 1;
int time = 0;
//存储纹理
GLuint  texture[1]; 



//初始化
void init()
{
    //纹理控制部分

    //glCullFace(GL_BACK);              //背面裁剪(背面不可见)
    //glEnable(GL_CULL_FACE);           //启用裁剪
    glEnable(GL_DEPTH_TEST);            //深度测试
    glEnable(GL_TEXTURE_2D);
    LoadGLTextures();                   //载入纹理贴图


    //事件处理部分
    glutIgnoreKeyRepeat(0);             //确认是否忽略自动的连续击键
    glutMouseFunc(mouse);               //鼠标点击事件
    glutMotionFunc(motion);             //鼠标拖动事件
    glutKeyboardFunc(keyboard);         //键盘事件
    glutSpecialFunc(special);           //特殊键盘 没有ASCII值 如上下左右


    //光照控制部分
    GLfloat DiffuseLightn[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat light_position1[] = { 10.0, 20.0, 30.0, 0.0 };
    GLfloat light_position2[] = { 10.0, 10.0, -30.0, 0.0 };

    glLightfv(GL_LIGHT0,  GL_DIFFUSE, DiffuseLightn);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position1);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, DiffuseLightn);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position2);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glDepthFunc(GL_LESS);

}


int main (int argc,  char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(640,480);
    mainWindow = glutCreateWindow("Birdy");
    LoadGLTextures();            //载入纹理贴图

    glutDisplayFunc(renderSceneAll);
    glutReshapeFunc(reshape);
    init();


    //子窗口建立
    subWindow1 = glutCreateSubWindow(mainWindow, border, border, w - 2 * border, h / 2 - border * 3 / 2);
    glutDisplayFunc(renderScenesw1);
    init();

    subWindow2 = glutCreateSubWindow(mainWindow, border, (h + border) / 2, w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);
    glutDisplayFunc(renderScenesw2);
    init();

    subWindow3 = glutCreateSubWindow(mainWindow, (w + border) / 2, (h + border) / 2, w / 2 - border * 3 / 2, h / 2 - border * 3 / 2);
    glutDisplayFunc(renderScenesw3);
    init();


    glutMainLoop();

    return 0;
}

推荐阅读