【OpenGL】计算机图形学实验五: 图形变换实验(二维、三维图形的变换)

实验五: 图形变换实验

(二维、三维图形的变换)

1、实验目的和要求

理解二维、三维图形变换的数学原理原理,并能利用OpenGL绘制简单的二维、三维图形,调用OpenGL命令实现基本的图形变换。

2、实验设备

PC机、CodeBlocks\VS系列\OpenGL安装包

3、实验内容及原理

  1. 通过一个正弦曲线,来进行平移变换。
  2. 参照Autocad的交互式方式,实现交互式放缩、旋转和对称变换

实验原理(基本知识)

1)    键盘回调函数:glutKeyboardFunc(void(*func)(unsigned char key, int x, int y));
key表示键盘上按下的键,如’w’, ‘a’, ‘s’, ‘d’等。
2)    鼠标回调函数:glutMouseFunc(void(*func)(int button, int state, int x, int y)); 
button表示鼠标上的按键,有三种取值:
GLUT_LEFT_BUTTON, GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON,分别表示鼠标左键、右键和中键。
state表示按键的状态,有两种取值:
GLUT_UP, GLUT_DOWN,分别表示弹起或按下。
x, y表示当前鼠标的位置。
3)    鼠标动作回调函数:glutMotionFunc(void(*func)(int x, int y));
x, y表示当前鼠标的位置。
4)    图形变换函数:
①    glTranslate{f/d},平移变换。以glTranslatef为例,void glTranslatef(GLfloat x, GLfloat y, GLfloat z); 表示在X, Y, Z轴方向上平移x, y, z单位。
②    glRotate{f/d},旋转变换。以glRotatef为例,void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 表示以(0, 0, 0)到(x, y, z)的向量为轴,逆时针旋转angle度(以度为单位)。
③    glScale{f/d},缩放变换。以glScalef为例,void glScalef(GLfloat x, GLfloat y, GLfloat z); 表示X, Y, Z轴分别缩放至原来的x, y, z倍。
 

4、实验源程序代码、运行结果

4.1 sin函数的图形变换

4.1.1源程序代码

#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <cmath>
#include <vector>
#include <iostream>

using namespace std;

void resize(int w, int h) {
    if (h == 0) {
        h = 1;
    }

    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    if (w <= h) {
        glOrtho(0.0f, 400.0f, 0.0f, 400.f * h / w, 1.0f, -1.0f);
    } else {
        glOrtho(0.0f, 400.0f * w / h, 0.0f, 400.0f, 1.0f, -1.0f);
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void DrawSin() {
    // sin
    glBegin(GL_LINE_STRIP);
    for (float x = 0; x < 80; x += 0.1) {
        glVertex2f(x * 10, sin(x) * 40 + 40);
    }
    glEnd();
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3d(1, 0, 0);
    DrawSin();

    glTranslatef(0, 100, 0);
    glColor3d(0, 0, 1);
    DrawSin();

    glLoadIdentity();
    glTranslatef(0, 200, 0);
    glScaled(1.5f, 1.0f, 1.0f);
    glColor3d(0, 0, 0);
    DrawSin();

    glLoadIdentity();
    glTranslatef(-50, 300, 0);
    DrawSin();

    glutSwapBuffers();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitWindowSize(400, 400);
    glutInitWindowPosition(10, 10);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

    glutCreateWindow("sin");

    glutReshapeFunc(resize);
    glutDisplayFunc(display);

    // SetRC
    glClearColor(1, 1, 1, 1);

    glutMainLoop();

    return 0;
}

4.1.2运行结果

4.2绘制立方体

4.2.1源程序代码

源代码中,正方体的顶点下标设置如图所示:

 源代码如下:

#ifdef __APPLE__
#include <GLUT/glut.h>
#else

#include <GL/glut.h>

#endif

#include <cmath>
#include <vector>
#include <iostream>

using namespace std;

float mouse[2] = {0};              // 鼠标当前的位置, [x, y]轴
float r[2] = {0};                  // 旋转的角度, [x, y]轴方向上
float trans[2] = {0};              // 平移,[x, y]轴
float scale = 1.0f;                // 整体缩放比
bool isMouseLeftDown = false;      // 鼠标左键是否按下
bool isMouseRightDown = false;     // 鼠标右键是否按下

float vertices[][3] = { // 正方体的顶点
        -0.5, -0.5, -0.5,
        -0.5, -0.5, 0.5,
        -0.5, 0.5, -0.5,
        -0.5, 0.5, 0.5,
        0.5, -0.5, -0.5,
        0.5, -0.5, 0.5,
        0.5, 0.5, -0.5,
        0.5, 0.5, 0.5,
};

int indices[][4] = { // 六个面的下标
        0, 1, 5, 4,
        2, 3, 7, 6,
        4, 5, 7, 6,
        0, 1, 3, 2,
        1, 3, 7, 5,
        0, 2, 6, 4,
};

void keyboardEvent(unsigned char key, int x, int y) {
    if (key == 'w') {           // 上移
        trans[1] += 0.1f;
    } else if (key == 's') {    // 下移
        trans[1] -= 0.1f;
    } else if (key == 'a') {    // 左移
        trans[0] -= 0.1f;
    } else if (key == 'd') {    // 右移
        trans[0] += 0.1f;
    }

    if (key == 'z') {           // 缩小
        scale -= 0.1f;
    } else if (key == 'x') {    // 放大
        scale += 0.1f;
    } else if (key == 'c') {    // 复原
        scale = 1.0f;
    }
}

void mouseEvent(int button, int state, int x, int y) {
    mouse[0] = x;
    mouse[1] = y;

    switch (button) {
        case GLUT_LEFT_BUTTON:
            if (state == GLUT_DOWN) {
                isMouseLeftDown = true;
                // cout << "mouse_left_button down!" << endl;
            } else {
                isMouseLeftDown = false;
            }

            break;
        case GLUT_RIGHT_BUTTON:
            if (state == GLUT_DOWN) {
                isMouseRightDown = true;
            } else {
                isMouseRightDown = false;
            }
            break;
        case GLUT_MIDDLE_BUTTON:
            break;
        default:
            break;
    }
}

void mouseMotionEvent(int x, int y) {
    if (isMouseLeftDown) { // 鼠标左键按下时,进行旋转变换
//        cout << "previous x,y: " << mouse[0] << ' ' << mouse[1] << endl;
//        cout << "current x, y: " << x << ' ' << y << endl;
        r[0] += (y - mouse[1]) * 0.25f;
        r[1] += (x - mouse[0]) * 0.25f;
        mouse[0] = x;
        mouse[1] = y;
    }

    if (isMouseRightDown) {
        mouse[0] = x;
        mouse[1] = y;
    }
}

void drawCube() {
    glBegin(GL_QUADS);
    // 绘制正方体的6个面
    for (int i = 0; i < 6; i++) {
        // 每个面的4个顶点
        for (int j = 0; j < 4; j++) {
            glVertex3fv(vertices[indices[i][j]]);
        }
    }
    glEnd();
}

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glPushMatrix();

    // w, a, s, d 控制平移变换
    glTranslatef(trans[0], trans[1], 0);

    // z, x, c键控制缩放: z 缩小,x 放大, c 复原
    glScalef(scale, scale, 1);

    // 鼠标左键控制旋转变换
    glRotatef(r[0], 1, 0, 0);
    glRotatef(r[1], 0, 1, 0);

    // 仅绘制线框
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glColor3f(0, 0, 0);
    drawCube();

    glPopMatrix();
    glutSwapBuffers();
}

int main(int argc, char *argv[]) {
    glutInit(&argc, argv);
    glutInitWindowSize(400, 400);
    glutInitWindowPosition(10, 10);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

    glutCreateWindow("Cube");

    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutKeyboardFunc(keyboardEvent);    // 设置键盘的回调函数
    glutMouseFunc(mouseEvent);          // 设置鼠标的回调函数
    glutMotionFunc(mouseMotionEvent);   // 设置鼠标动作的回调函数

    // SetRC
    glClearColor(1, 1, 1, 1);

    glutMainLoop();

    return 0;
}

 

4.2.2运行结果

使用键盘上的W, A, S, D控制立方体上、左、下、右移动(平移变换)。

 鼠标左键按下时移动时,立方体进行旋转(旋转变换)。

 使用键盘的Z, X, C控制缩放变换:

 

 

  • 8
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验中,我们学习了基于OpenGL的三维变换和投影。通过这个实验,我们能够更好地理解和掌握OpenGL图形库的基本概念和使用方法。 首先,我们学习了OpenGL的三维变换。三维变换包括平移、旋转和缩放。平移是将物体沿着某个向量进行移动,旋转是将物体围绕某个轴旋转,而缩放是改变物体在不同方向上的尺寸。通过OpenGL提供的变换函数,我们可以实现这些三维变换操作。 其次,我们学习了OpenGL的投影。投影是将三维物体投影到二维屏幕上的过程。在实验中,我们主要学习了透视投影和正交投影两种投影方式。透视投影使远处的物体显得较小,近处的物体显得较大,而正交投影则使物体在不同位置保持相同的大小。通过设置视角、视口和投影矩阵,我们可以实现不同的投影效果。 通过实验,我们了解到OpenGL可以通过设置不同的变换和投影来实现各种复杂的图形效果。例如,可以通过组合平移、旋转和缩放操作,将一个简单的物体变换为复杂的状。同时,通过调整投影参数,可以实现不同的视觉效果,如近大远小或保持物体大小不变。 总之,实验基于OpenGL的三维变换与投影,帮助我们更好地理解和掌握了OpenGL图形库的相关概念和使用方法。这些知识对于我们在计算机图形学和计算机游戏开发中的应用非常重要。通过实践和练习,我们可以进一步提升对OpenGL的理解和运用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值