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

news/2024/11/13 8:55:12/


第4关:视口变换与三视图

一. 任务描述

1. 本关任务

(1) 理解投影变换的方法; (2) 将main函数中的空白部分补充完整。

2. 输入

(1) 代码将自动输入一个边长为1的obj正方体模型,具体模型如下图:

test

(2) 代码自动将模型投影到二维平面,经过模型变换,生成一个长宽高不等的立方体,并将显示窗口一分为四,分为四个视口,每个视口大小均为原窗口大小的一半。红绿两线为四个视口的分隔线; (3) 在第一视口ViewPort中,首先将立方体沿Z轴向XOY平面投影。然后进行视口变换ViewPort,并绘制出一个白色矩形; (4) 在第二视口ViewPort1中,首先将立方体沿X轴向YOZ平面投影。然后沿Y轴顺时针旋转90度,最后进行视口变换ViewPort1,绘制一个绿色矩形; (5) 在第三视口ViewPort2中,首先将立方体沿Y轴向XOZ平面投影。然后沿X轴逆时针旋转90度,最后进行视口变换ViewPort2,绘制一个红矩形; (6) 在第四视口ViewPort3中,首先将立方体沿Y轴顺时针旋转45度,然后进行投影变换,投影变换参数eye和center已给出。最后进行视口变换ViewPort3,绘制一个黄色立方体。

3. 输出

具体结果如下图所示:

test

二. 相关知识

1. 投影变换

投影变换相关知识点,请参考教材与课件或有关资料。

三. 操作说明

(1) 按要求补全代码; (2) 点击窗口右下角"测评"按钮,等待测评结果,如果通过后可进行下一关任务。


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

四.实验代码

#include <vector>
#include <cmath>
#include <algorithm>
#include <iostream>
#include "model.h"
#include "geometry.h"
#include "pngimage.h"
using namespace std;
const double PI = acos(-1.0);
void line(Vec3i p0, Vec3i p1, PNGImage  &image, PNGColor color)
{bool steep = false;if (std::abs(p0.x - p1.x) < std::abs(p0.y - p1.y)){std::swap(p0.x, p0.y);std::swap(p1.x, p1.y);steep = true;}if (p0.x > p1.x){std::swap(p0.x, p1.x);std::swap(p0.y, p1.y);}int dx = p1.x - p0.x;int dy = std::abs(p1.y - p0.y);int y = p0.y;int d = -dx;for (int x = p0.x; x <= p1.x; x++){if (steep)image.set(y, x, color);elseimage.set(x, y, color);d = d + 2 * dy;if (d > 0){y += (p1.y > p0.y ? 1 : -1);d = d - 2 * dx;}}
}
Matrix projection(Vec3f eye, Vec3f center)
{Matrix m = Matrix::identity(4);m[3][2] = -1.f / (eye - center).norm();return m;
}
Matrix viewport(int x, int y, int w, int h, int depth) {Matrix m = Matrix::identity(4);m[0][3] = x + w / 2.f;m[1][3] = y + h / 2.f;m[2][3] = depth / 2.f;m[0][0] = w / 2.f;m[1][1] = h / 2.f;m[2][2] = depth / 2.f;return m;
}
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) {Vec3f z = (eye - center).normalize();Vec3f x = (up^z).normalize();Vec3f y = (z^x).normalize();Matrix res = Matrix::identity(4);for (int i = 0; i < 3; i++) {res[0][i] = x[i];res[1][i] = y[i];res[2][i] = z[i];res[i][3] = -center[i];}return res;
}
Matrix translation(Vec3f v) {Matrix Tr = Matrix::identity(4);Tr[0][3] = v.x;Tr[1][3] = v.y;Tr[2][3] = v.z;return Tr;
}
Matrix scale(float factorX, float factorY, float factorZ)
{Matrix Z = Matrix::identity(4);Z[0][0] = factorX;Z[1][1] = factorY;Z[2][2] = factorZ;return Z;
}
Matrix rotation_x(float angle)
{angle = angle * PI / 180;float sinangle = sin(angle);float cosangle = cos(angle);Matrix R = Matrix::identity(4);R[1][1] = R[2][2] = cosangle;R[1][2] = -sinangle;R[2][1] = sinangle;return R;
}
Matrix rotation_y(float angle)
{angle = angle * PI / 180;float sinangle = sin(angle);float cosangle = cos(angle);Matrix R = Matrix::identity(4);R[0][0] = R[2][2] = cosangle;R[0][2] = sinangle;R[2][0] = -sinangle;return R;
}
Matrix rotation_z(float angle) {angle = angle * PI / 180;float sinangle = sin(angle);float cosangle = cos(angle);Matrix R = Matrix::identity(4);R[0][0] = R[1][1] = cosangle;R[0][1] = -sinangle;R[1][0] = sinangle;return R;
}
int main(int argc, char** argv)
{const PNGColor white = PNGColor(255, 255, 255, 255);const PNGColor black = PNGColor(0, 0, 0, 255);const PNGColor red = PNGColor(255, 0, 0, 255);const PNGColor green = PNGColor(0, 255, 0, 255);const PNGColor blue = PNGColor(0, 0, 255, 255);const PNGColor yellow = PNGColor(255, 255, 0, 255);Model *model = NULL;const int width = 800;const int height = 800;const int depth = 255;//generate some imagePNGImage image(width, height, PNGImage::RGBA); //Error when RGB because lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size() in encodeimage.init(black);model = new Model("cube.obj");Vec3f eye(0, 0, 4);Vec3f center(0, 0, 0);//添加视口变量及正投影变量代码区域/********** Begin ********/Matrix projectionMatrix = projection(eye, center);//正投影变量Matrix ViewPort = viewport(0, width/2, width/2, height/2, depth);//视口变量Matrix ViewPort1 = viewport(width / 2, width/2, width/2 , height/2 , depth);Matrix ViewPort2 = viewport(0,0 , width / 2, height / 2, depth);Matrix ViewPort3 = viewport(width / 2, 0, width / 2, height / 2, depth);/************End**********/// 绘制视口分隔线Vec3f x1(0.f, height / 2, 0.f), x2(width, height / 2, 0.f);Vec3f y1(width / 2, 0.f, 0.f), y2(width / 2, height, 0.f);line(x1, x2, image, red);line(y1, y2, image, green);for (int i = 0; i < model->nfaces(); i++){std::vector<int> face = model->face(i);for (int j = 0; j < (int)face.size(); j++){Vec3f wp0 = model->vert(face[j]);Vec3f wp1 = model->vert(face[(j + 1) % face.size()]);Matrix S0 = scale(0.5, 0.4, 0.3);Vec3f swp0 = S0 * wp0;Vec3f swp1 = S0 * wp1;//添加绘制点及绘制计算区域/********** Begin ********/Matrix ProjectionX = Matrix::identity(4);ProjectionX[0][0]=0.0f;Matrix ProjectionY = Matrix::identity(4);ProjectionY[1][1]=0.0f;Matrix ProjectionZ = Matrix::identity(4);ProjectionZ[2][2]=0.0f;Vec3f p0 = ViewPort*ProjectionZ* swp0;Vec3f p1 = ViewPort*ProjectionZ* swp1;line(p0,p1,image,white);//白色矩形Matrix R = rotation_y(90);Vec3f p0_44 = ViewPort1*R*ProjectionX* swp0;Vec3f p1_44 = ViewPort1*R*ProjectionX* swp1;line(p0_44,p1_44,image,green);//绿色矩形Matrix R1 = rotation_x(-90);Vec3f p0_55 = ViewPort2*R1*ProjectionY* swp0;Vec3f p1_55 = ViewPort2*R1*ProjectionY* swp1;line(p0_55,p1_55,image,red);//红色矩形Matrix R2 = rotation_y(45);Matrix ModelView = lookat(eye, center, Vec3f(0,-1 ,0 ));//投影变换Vec3f p0_66 = ViewPort3*ModelView*projectionMatrix*R2* swp0;Vec3f p1_66 = ViewPort3*ModelView*projectionMatrix*R2* swp1;line(p0_66,p1_66,image,yellow);//黄色立方体/************End**********/}}image.flip_vertically(); // i want to have the origin at the left bottom corner of the imageimage.write_png_file("../img_step4/test.png");delete model;return 0;
}


http://www.ppmy.cn/news/1451930.html

相关文章

在M1芯片安装鸿蒙闪退解决方法

在M1芯片安装鸿蒙闪退解决方法 前言下载鸿蒙系统安装完成后&#xff0c;在M1 Macos14上打开闪退解决办法接下来就是按照提示一步一步安装。 前言 重新安装macos系统后&#xff0c;再次下载鸿蒙开发软件&#xff0c;竟然发现打不开。 下载鸿蒙系统 下载地址&#xff1a;http…

HTTP协议 --中

http状态码 当浏览者访问一个网页时&#xff0c;浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前&#xff0c;此网页所在的服务器会返回一个包含HTTP 状态码的信息头&#xff08; server header &#xff09;用以响应浏览器的请求。 HTTP 状态码的英文为…

UDP_INTRODUCTION_03:介绍 - 挂起的监听调用

测试目的&#xff1a; 验证当数据报到达一个没有挂起监听&#xff08;LISTEN&#xff09;调用的UDP端口时&#xff0c;UDP是否应该发送ICMP端口不可达&#xff08;Port Unreachable&#xff09;消息。 描述&#xff1a; 本测试用例旨在确保当数据报发送到DUT上一个未被监听的…

esp32-cam 2. python opencv 拉取摄像头内容

0. 环境 - win10 python3 - pycharm - esp32-cam http://192.168.4.1 1. 创建工程 File -> Create Project -> -> Location: E:\Workspaces\PycharmProjects\esp32cam_opencv -> Create 2. opencv hello 2.1 添加脚本 File -> New -> Python f…

1.3 Java全栈开发前端+后端(全栈工程师进阶之路)-前置课程CSS,看这一篇就够了

前面我们已经讲了前端三剑客中的html和JavaScript&#xff0c;那么现在我们来看一下CSS CSS核心 0、清除默认样式 * {/* 清除默认样式 */margin: 0;padding: 0; } 1、尺寸操作-内外边距 .box {/* 尺寸操作 *//* 宽度 */width: 500px ; /* 高度 */height: 280px;/* 边框 *…

Java调用GDAL实现postgresql数据生成shp和dxf

需求 由于shp数据存储到postgresql数据库中&#xff0c;前端调用数据库实现数据的渲染&#xff0c;最近有一个新的需求&#xff0c;前端圈选数据&#xff0c;实现数据的下载&#xff0c;数据可以是shp、dxf、excel格式&#xff0c;这里主要记录在后端通过调用gdal来实现这个需…

交叉调制少样本图像生成用于结直肠组织分类

文章目录 Cross-Modulated Few-Shot Image Generation for Colorectal Tissue Classification摘要方法实验结果 Cross-Modulated Few-Shot Image Generation for Colorectal Tissue Classification 摘要 提出问题&#xff1a; 针对罕见癌症组织的组织病理训练数据稀缺问题&…

快速幂笔记

快速幂即为快速求出一个数的幂&#xff0c;这样可以避免TLE&#xff08;超时&#xff09;的错误。 传送门&#xff1a;快速幂模板 前置知识&#xff1a; 1) 又 2) 代码&#xff1a; #include <bits/stdc.h> using namespace std; int quickPower(int a, int b) {int…