视频加载失败

课程

858 字
约 3 分钟

5.4 三菱形状

计算机图形学labs/lab05-geometric-transformations·更新于 2026-09-15

5.4 三菱形状

1. 任务描述

本关任务

  1. 理解并掌握 OpenGL 二维平移、旋转、缩放变换的方法。
  2. 阅读实验原理,掌握 OpenGL 程序平移、旋转、缩放变换的方法。
  3. 利用虚拟机进行编程,以 OpenGL 为开发平台设计程序,设计二维几何变换图形。

预期输出

预期输出

具体要求

  1. 背景色为黑色,用 glClearColor 来完成。
  2. 三个菱形图形通过二维平移和旋转完成。颜色分别为红色 (1.0, 0.0, 0.0)、蓝色 (0.0, 0.0, 1.0) 和绿色 (0.0, 1.0, 0.0)
  3. 三个菱形的长对角线长度为 4.0,短对角线长度为 2.0,三个菱形的交点为原点 (0.0, 0.0)
  4. 红色菱形的长对角线与 Y 轴重合,每个菱形的长对角线夹角为 120 度。

本关提示

  1. 可将绘制原始的图形设置成一个单独的函数便于调用,这样可以省去反复绘制原始图形的步骤。
  2. 画一个凸多边形可以调用 glBegin(GL_POLYGON),后边用 glVertex2f(x, y) 指定顶点坐标,需要注意凸多边形的顶点指定需要按逆时针方向。
  3. 保留原始图形可以看做调用平移函数并且平移的距离为 (0.0, 0.0, 0.0)
  4. 每进行一个矩阵操作时,需要先保存这个矩阵,调用 glPushMatrix() 函数,把当前矩阵压入堆栈。当需要恢复最近一次的保存时,调用 glPopMatrix() 函数,它相当于从堆栈栈顶弹出一个矩阵为当前矩阵。

相关知识

为了完成本关任务,你需要掌握:OpenGL 二维平移、旋转、缩放变换的方法。


开始你的任务吧,祝你成功!

2. 我的回答

文件 step4/test4.cpp:

#include <GL/freeglut.h>
#include<stdio.h>

// 评测代码所用头文件-开始
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
// 评测代码所用头文件-结束

void init(void)
{  
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
    glMatrixMode(GL_MODELVIEW);
}

void drawDiamond(void)                      //绘制一个基础菱形
{
   // 请在此添加你的代码
   /**** Begin **/
    // 按逆时针顺序指定顶点,绘制基础凸多边形(菱形)
    // 将菱形的底部顶点放在原点 (0,0)
    glBegin(GL_POLYGON);
    glVertex2f(0.0f, 4.0f);  // 顶部顶点 (位于Y轴,距原点4.0)
    glVertex2f(-1.0f, 2.0f); // 左侧顶点 (位于X轴偏上,距Y轴1.0)
    glVertex2f(0.0f, 0.0f);  // 底部顶点 (就在原点)
    glVertex2f(1.0f, 2.0f);  // 右侧顶点 (位于X轴偏上,距Y轴1.0)
    glEnd();
   /** End **/
}


void myDraw(void)                           //二维几何变换
{
   // 请在此添加你的代码
   /**** Begin **/
    // 1. 每次绘制前清空颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);

    // 2. 绘制红色菱形(原始方向,长对角线与Y轴重合)
    glPushMatrix();                     // 压入当前矩阵
    glTranslatef(0.0f, 0.0f, 0.0f);      // 象征性平移(距离为0)
    glColor3f(1.0f, 0.0f, 0.0f);         // 设置为红色
    drawDiamond();                      // 调用绘制基础菱形的函数
    glPopMatrix();                      // 弹出矩阵,恢复回原点状态

    // 3. 绘制绿色菱形(逆时针旋转120度)
    glPushMatrix();                     // 再次压入矩阵
    glRotatef(120.0f, 0.0f, 0.0f, 1.0f); // 绕Z轴逆时针旋转120度
    glColor3f(0.0f, 1.0f, 0.0f);         // 设置为绿色
    drawDiamond();
    glPopMatrix();                      // 弹出矩阵

    // 4. 绘制蓝色菱形(顺时针旋转120度)
    glPushMatrix();
    glRotatef(-120.0f, 0.0f, 0.0f, 1.0f);// 绕Z轴顺时针旋转120度
    glColor3f(0.0f, 0.0f, 1.0f);         // 设置为蓝色
    drawDiamond();
    glPopMatrix();

   /** End **/                          
    glFlush();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(400, 400);
    glutCreateWindow("几何变换示例");
    
    init();
    glutDisplayFunc(&myDraw);
    glutMainLoopEvent();     
     
    /***以下为评测代码,与本次实验内容无关,请勿修改****/
    GLubyte* pPixelData = (GLubyte*)malloc(400 * 400 * 3);
    GLint viewport[4] = {0};
    glReadBuffer(GL_FRONT);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glGetIntegerv(GL_VIEWPORT, viewport);
    glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGB, GL_UNSIGNED_BYTE, pPixelData);

    cv::Mat img;
    std::vector<cv::Mat> imgPlanes;
    img.create(400, 400, CV_8UC3);
    cv::split(img, imgPlanes);
 
    for(int i = 0; i < 400; i++) {
        unsigned char* plane0Ptr = imgPlanes[0].ptr<unsigned char>(i);
        unsigned char* plane1Ptr = imgPlanes[1].ptr<unsigned char>(i);
        unsigned char* plane2Ptr = imgPlanes[2].ptr<unsigned char>(i);
        for(int j = 0; j < 400; j++) {
            int k = 3 * (i * 400 + j);
            plane2Ptr[j] = pPixelData[k];
            plane1Ptr[j] = pPixelData[k+1];
            plane0Ptr[j] = pPixelData[k+2];
        }
    }
    cv::merge(imgPlanes, img);
    cv::flip(img, img, 0); 
    cv::namedWindow("openglGrab");
    cv::imshow("openglGrab", img);
    cv::imwrite("../img_step4/test.jpg", img);
    return 0;
}

Profile Image of the Author
Sonder
好想要技术
这是公告标题
这只是一个公告
分类
标签
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.16.7
文章许可
CC BY-NC-SA 4.0
文章目录