头歌实践教学平台:投影变换v1.0

第2关:立方体平行投影

一.任务描述

根据提示,在右侧修改代码,并自己绘制出图形。平台会对你编写的代码进行测试。

1.本关任务

学习了解三维图形几何变换原理。 理解掌握OpenGL三维图形几何变换的方法。 理解掌握OpenGL程序的模型视图变换。 掌握OpenGL三维图形显示与观察的原理与实现。

2.预期输出

参考图片

3.具体要求

(1).背景色为黑色,用 glclearcolor 来完成; (2).运用glPushMatrix()函数和glPopMatrix()函数进行矩阵操作,以中心为绘制原点,设置前景色为红色glColor3f(1.0, 0.0, 0.0),绘制单位立方体线框,用glutWireCube(1.0)完成; (3).运用glPushMatrix()函数和glPopMatrix()函数进行矩阵操作,设置前景色为黑色glColor3f(0.0, 1.0, 0.0),设置线宽为2.0用glLineWidth(2.0)完成,将原单位立方体线框沿X轴正方向平移2.0;
(4).运用glPushMatrix()函数和glPopMatrix()函数进行矩阵操作,沿X轴负方向平移2.0,设置前景色为蓝色glColor3f(0.0, 0.0, 1.0),绘制单位立方体实体用glutSolidCube(1.0)完成; (5).进行平行投影调用glOrtho()函数,坐标为(左,右,下,上,近,远),坐标为glOrtho(-3.0, 3.0, -3.0, 3.0,-100.0, 100.0);

二.相关知识

1.实验内容

为了完成本关任务,你需要: (1)阅读教材有关三维图形变换原理,运行示范实验代码,掌握OPENGL程序三维图形变换的方法; (2)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换。 (3)请分别调整观察变换矩阵、模型变换矩阵和投影变换矩阵的参数,观察变换结果; (4)掌握三维观察流程、观察坐标系的确定、世界坐标系与观察坐标系之间的转换、平行投影和透视投影的特点,观察空间与规范化观察空间的概念。理解OpenGL图形库下视点函数、正交投影函数、透视投影函数。理解三维图形显示与观察代码实例。

2.平行投影

投影变换:类似于为照相机选择镜头,将三维模型通过投影方式生成一幅二维投影图,同时确定视野,并确定哪些物体位于视野之内以及它们能够被看到的程度。投影变换主要分为透视投影和平行投影两种。

3.glOrtho()函数

glOrtho(左,右,下,上,近,远)为正投影函数,其中六个参数划分出了一个立方体空间,这个空间里物体将以正投影的模式表现,在移动的过程中,观察到的物体大小不会发生变化,这解释了为什么在正投影中移动物体,不能观察出物体形状变化;

4.注意事项

下面是这些变换函数使用时需要注意内容: (1)在OpenGL程序中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。 (2)确定视图变换之前,应该使用glLoadIdentity函数把当前矩阵设置为单位矩阵,类似于变换初始化。 (3)一般而言,display函数包括:视图变换 + 模型变换 + 绘制图形的函数(如glutWireCube)。display会在窗口被移动或者原来先遮住这个窗口的东西被移开时,被重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。 (4)在调用glFrustum设置投影变换之前,在reshape函数中有一些准备工作:视口变换 + 投影变换 + 模型视图变换。由于投影变换,视口变换共同决定了场景是如何映射到计算机的屏幕上的,而且它们都与屏幕的宽度、高度密切相关,因此应该放在reshape函数中。reshape函数会在窗口初次创建,移动或改变时被调用。

总结起来,OpenGL中矩阵坐标之间的关系为:模型世界坐标→模型视图矩阵→投影矩阵→透视除法→规范化设备坐标→窗口坐标。


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

三.实验代码
// 提示:在合适的地方修改或添加代码
#include <GL/freeglut.h>
#include<stdio.h>

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

GLint winWidth = 400, winHeight =400 ; 	      //设置初始化窗口大小

/*观察坐标系参数设置*/
GLfloat x0 = 0.0, yy = 0.0, z0 = 5.0;	   //设置观察坐标系原点 
GLfloat xref = 0.0, yref = 0.0, zref = 0.0;	//设置观察坐标系参考点(视点) 
GLfloat Vx = 0.0, Vy = 1.0, Vz = 0.0;	   //设置观察坐标系向上向量(y轴) 

/*观察体参数设置 */
GLfloat xwMin = -1.0, ywMin = -1.0, xwMax = 1.0, ywMax = 1.0;//设置裁剪窗口坐标范围
GLfloat dnear = 1.5, dfar = 20.0;	      //设置远、近裁剪面深度范围

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
}
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    glLoadIdentity();
    /*观察变换*/
    gluLookAt(x0, yy, z0, xref, yref, zref, Vx, Vy, Vz);        //指定三维观察参数

    // 请在此添加你的代码
    /********** Begin ********/
    glClearColor(0.0f,0.0f,0.0f,0.0f);//背景色为黑色

    glPushMatrix();
    glColor3f(1.0, 0.0, 0.0);//前景色为红色
    glutWireCube(1.0);//绘制单位立方体线框
    glPopMatrix();

    glPushMatrix();
    glColor3f(0.0, 1.0, 0.0);//前景色为黑色
    glLineWidth(2.0);//线宽为2.0
    glTranslatef(2.0f,0.0f,0.0f);//沿X轴正方向平移2.0
    glutWireCube(1.0);//绘制单位立方体线框
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-2.0f,0.0f,0.0f);//沿X轴负方向平移2.0
    glColor3f(0.0, 0.0, 1.0);//前景色为蓝色
    glutSolidCube(1.0);//单位立方体实体
    glPopMatrix();


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

void reshape(GLint newWidth, GLint newHeight)
{
    /*视口变换*/
    glViewport(0, 0, newWidth, newHeight);	//定义视口大小

    /*投影变换*/
    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    /*平行投影*/
    glOrtho( -3.0,3.0 ,-3.0 ,3.0 ,-100.0 ,100.0 );

    /*模型变换*/
    glMatrixMode(GL_MODELVIEW);
    
    winWidth = newWidth;
    winHeight = newHeight;
}
int main(int argc, char* argv[])
{

    glutInit(&argc, argv);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize( 400 , 400 );        //设置初始化窗口大小
    glutCreateWindow("三维观察");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoopEvent();





    /*************以下为评测代码,与本次实验内容无关,请勿修改**************/
    GLubyte* pPixelData = (GLubyte*)malloc(800 * 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::waitKey();
    cv::imwrite("../img_step3/test.jpg", img);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/584003.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch面试题2

Mapping属性详细介绍/常见的字段数据类型&#xff1a; 映射(mapping)︰mapping是对索引库中文档的约束信息&#xff08;例如字段名、数据类型&#xff09;&#xff0c;类似表的结构约束&#xff1b;每个索引库都应该有自己的映射 数据库一定要先创建表才能去添加数据…

Redis缓存介绍以及常见缓存问题:穿透、雪崩和击穿

概念 缓存就是数据交换的缓冲区&#xff08;Cache&#xff09;&#xff0c;是存贮数据的临时地方&#xff0c;一般读写性能较高。 作用&#xff1a; 降低后端负载 提高读写效率&#xff0c;降低相应时间 成本&#xff1a; 数据一致性成本 代码维护成本 运维成本 缓存更…

JAVA系列 小白入门参考资料 类和对象(3)

温馨提示&#xff1a; 此篇文章需要前两篇文章作为基础。 JAVA系列 小白入门参考资料 类和对象&#xff08;1&#xff09;​​​​​​​ JAVA系列 小白入门参考资料 类和对象&#xff08;2&#xff09; 目录 1. 封装 引入封装 访问修饰符 封装的具体实现 get方法和…

Elasticsearch 索引 blocks:深入探讨数据保护

Elasticsearch 作为搜索和分析数据的首选分布式引擎在技术领域脱颖而出&#xff0c;尤其是在处理日志、事件和综合文本搜索时。 它的与众不同之处在于它如何让你使用各种块选项调整对其索引的访问。 这对于那些负责技术项目的人&#xff08;比如管理员和编码员&#xff09;来说…

计算机系统概述试题(二)

一、单项选择题 01&#xff0e;关于CPU主频、CPI、MIPS、MFLOPS&#xff0c;说法正确的是( )。 A.CPU主频是指CPU系统执行指令的频率&#xff0c;CPI是执行一条指令平均使用的频率 B.CPI是执行一条指令平均使用CPU时钟的个数&#xff0c;MIPS描述一条CPU指令平均使用 的CPU时钟…

微信小程序与web-view网页进行通信的尝试

首先&#xff0c;微信小程序向web-view传递数据一般通过地址栏传参的形式&#xff08;给src赋值或者修改hash&#xff09;&#xff0c;这样一般就已经能够满足实际开发需求了&#xff0c;所以这里主要探讨web-view向微信小程序传参。下面&#xff0c;我们从官方文档入手&#x…

计算机组成实验(4)

实验目的&#xff1a; 1. 初步了解GPIO接口与设备 2. 了解计算机系统的基本结构 3. 了解计算机各组成部分的关系 4. 了解并掌握IP核的使用方法 5. 了解SOC系统并用IP核实现简单的SOC系统 实验环境&#xff1a; 1. 计算机&#xff08;Intel Core i5以上&#xff0c;4GB内存以…

【工具】--- Adobe Illustrator 下载-入门绘图

文章目录 软件下载入门项目可看课程 尝试使用Adobe Illustrator&#xff08;设计师常用软件&#xff09;进行科研绘图。 软件下载 阿里云盘下载 入门项目 绘制一个箭头并保持为SVG&#xff0c; 直线->画线->窗口->描边->选择想要的箭头样式->颜色->改为蓝…

git误操作版本回退的方法

场景&#xff1a;在使用git进行代码提交的时候不小心执行了git reset 命令进行了版本回退但是在这之前进行了git add . git commit -m "提交"等命令&#xff0c;正常情况下就可以直接使用 git reset 版本号 进行代码的回退&#xff0c;但是发现自己不能找打上一个提…

机器学习:逻辑回归

概念 首先&#xff0c;逻辑回归属于分类算法&#xff0c;是线性分类器。我们可以认为逻辑回归是在多元线性回归的基础上把结果给映射到0-1的区间内&#xff0c;hθ&#xff08;x&#xff09;越接近1越有可能是正例&#xff0c;反之&#xff0c;越接近0越有可能是负例。那么&am…

IC设计数据传输 如何能保障安全高效?

IC&#xff08;集成电路&#xff09;设计数据&#xff0c;对于IC设计企业来说&#xff0c;其重要性不言而喻。所以IC设计数据传输过程中&#xff0c;其安全性和效率&#xff0c;也需要有保障。 首先我们来看看IC设计数据为什么重要&#xff0c;其重要性体现在多个方面&#xff…

edge 入门基础了解使用

随着Windows 11的发布&#xff0c;Microsoft Edge也迎来了新的更新和改进。作为一名长期使用Edge的用户&#xff0c;我不仅注意到了这些表面的变化&#xff0c;还深入研究了Edge在Windows 11上的新特性和潜在优势。 快捷方式 查找框 在Microsoft Edge浏览器中&#xff0c;按…

踩坑Mybatis + Mybatis-plus + MyBatis-plus-join

数据库里有两张表 tb_bursary和tb_student tb_bursary里关联了tb_student.id作为外键 由于tb_student表可以单独操作&#xff0c;而tb_bursary需要联合tb_student查询 所以一开始&#xff0c;我是用mybatis-plus mybaits混合的模式 mybatis-plus单独操作tb_student表&…

学习 Rust 第 22 天:mini_grep 第 2 部分

书接上文&#xff0c;在本文中&#xff0c;我们学习了如何通过将 Rust 程序的逻辑移至单独的库箱中并采用测试驱动开发 (TDD) 实践来重构 Rust 程序。通过在实现功能之前编写测试&#xff0c;我们确保了代码的可靠性。我们涵盖了基本的 Rust 概念&#xff0c;例如错误处理、环境…

小程序SSL证书更新指南

随着网络技术的不断发展&#xff0c;小程序已经成为许多企业和个人进行业务推广和服务提供的重要平台。在享受小程序带来的便利和高效的同时&#xff0c;我们也必须重视其安全性问题。SSL证书作为保障小程序数据传输安全的重要手段&#xff0c;其更新工作不容忽视。本文将为大家…

在线教程|零门槛部署 Llama 3,70B 版本只占 1.07G 存储空间,新用户免费体验 8B 版本

4 月 18 日&#xff0c;Meta 宣布开源 Llama 3&#xff0c;这个号称「迄今为止最好的开源大模型」一经发布&#xff0c;立刻引爆科技圈&#xff01; 发布当天恰逢斯坦福大学教授、AI 顶尖专家吴恩达的生日&#xff0c;作为 AI 开源倡导者&#xff0c;他激动地发文表示&#xff…

CogAgent:开创性的VLM在GUI理解和自动化任务中的突破

尽管LLMs如ChatGPT在撰写电子邮件等任务上能够提供帮助&#xff0c;它们在理解和与GUIs交互方面存在挑战&#xff0c;这限制了它们在提高自动化水平方面的潜力。数字世界中的自主代理是许多现代人梦寐以求的理想助手。这些代理能够根据用户输入的任务描述自动完成如在线预订票务…

【doghead】ubuntu构建libuv

按照官方的文档2024年3月的版本。首先构建libuv 最终构建的还得了test 构建过程 zhangbin@DESKTOP-1723CM1:/mnt/d/XTRANS/thunderbolt/ayame/zhb-bifrost$ ls Bifrost-202403 README.md draw player-only worker 大神的带宽估计.png zhangbin@DESKTOP-1723CM1:/mnt/d/XTRANS/…

计算机网络 备查

OSI 七层模型 七层模型协议各层实现的功能 简要 详细 TCP/IP协议 组成 1.传输层协议 TCP 2.网络层协议 IP 协议数据单元&#xff08;PDU&#xff09;和 封装 数据收发过程 数据发送过程 1. 2.终端用户生成数据 3.数据被分段&#xff0c;并加上TCP头 4.网络层添加IP地址信息…

React + 项目(从基础到实战) -- 第十期

目标 学会react 状态管理工具 使用redux管理用户状态 Context 跨层级传递,不像props层层传递类似于Vue的provide/inject用于:切换主题颜色,切换语言 useReducer useState 的替代方案 简化版的redux MobX 1. MobX 介绍 MobX 中文文档 声明式的修改数据 , 像vue state ac…