【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换
总览
- 到目前为止,我们已经学习了如何使用矩阵变换来排列二维或三维空间中的对象。所以现在是时候通过实现一些简单的变换矩阵来获得一些实际经验了。在接下来的三次作业中,我们将要求你去模拟一个基于CPU 的光栅化渲染器的简化版本。
- 本次作业的任务是填写一个旋转矩阵和一个透视投影矩阵。给定三维下三个点v0(2.0, 0.0,−2.0), v1(0.0, 2.0,−2.0), v2(−2.0, 0.0,−2.0), 你需要将这三个点的坐标变换为屏幕坐标并在屏幕上绘制出对应的线框三角形。简而言之,我们需要进行模型、视图、投影、视口等变换来将三角形显示在屏幕上
- get_model_matrix(float rotation_angle)
逐个元素地构建模型变换矩阵并返回该矩阵。在此函数中,你只需要实现三维中绕 z 轴旋转的变换矩阵,而不用处理平移与缩放。 - get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
使用给定的参数逐个元素地构建透视投影矩阵并返回该矩阵。 - 当你在上述函数中正确地构建了模型与投影矩阵,光栅化器会创建一个窗口显示出线框三角形。由于光栅化器是逐帧渲染与绘制的,所以你可以使用A 和D 键去将该三角形绕z 轴旋转
基础与提高
- [5 分] 正确构建模型矩阵。
- [5 分] 正确构建透视投影矩阵。
- [10 分] 你的代码可以在现有框架下正确运行,并能看到变换后的三角形。
- [10 分] 当按A 键与D 键时,三角形能正确旋转。或者正确使用命令行得到旋转结果图像。
- [提高项5 分] 在main.cpp 中构造一个函数,该函数的作用是得到绕任意过原点的轴的旋转变换矩阵。
Eigen::Matrix4f get_rotation(Vector3f axis, float angle)
实现
投影变换矩阵
模型任意轴旋转
代码
创建 AActor 派生类 AActor_Assignmen1
AActor_Assignmen1.h
UCLASS()
class GAMES101_API AActor_Assignmen1 : public AActor
{
GENERATED_BODY() public:
// Sets default values for this actor's properties
AActor_Assignmen1(); protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override; public:
// Called every frame
virtual void Tick(float DeltaTime) override;
void DrawTriangleIn3D(); //主要函数
FMatrix get_view_matrix(FVector eye_pos);
FMatrix get_model_matrix(float rotation_angle);
FMatrix get_model_matrix_anyAxis(FVector axis, float angle);
FMatrix get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar); void RasterizerDraw(); public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (MakeEditWidget))
FTransform ponitA;
UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (MakeEditWidget))
FTransform ponitB;
UPROPERTY(EditAnywhere,BlueprintReadWrite, meta = (MakeEditWidget))
FTransform ponitC; UPROPERTY()
USceneComponent* root; UPROPERTY()
TArray<FVector> Points;
int32 width, height;
FVector eye_loc;
float angle; FMatrix modelMatrix;
FMatrix viewMatrix;
FMatrix projectionMatrix;
};
AActor_Assignmen1.cpp
#include "Actor_Assignmen1.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Kismet/KismetMathLibrary.h"
#include "GameFramework/HUD.h"
#include "Kismet/GameplayStatics.h"
#include "MyHUD.h" // Sets default values
AActor_Assignmen1::AActor_Assignmen1()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
root = CreateDefaultSubobject<USceneComponent>("root");
SetRootComponent(root); // 三个点v0(2.0, 0.0,−2.0), v1(0.0, 2.0,−2.0), v2(−2.0, 0.0,−2.0),
Points.Add(FVector(2.0f, 0, -2.0f));
Points.Add(FVector(0, 2.0f,-2.0f));
Points.Add(FVector(-2.0f, 0,-2.0f)); // 初始化
width = height = 700;
eye_loc = FVector(0, 0, 5);
angle = 0; modelMatrix.SetIdentity();
viewMatrix.SetIdentity();
projectionMatrix.SetIdentity(); ponitA.SetTranslation(Points[0]);
ponitB.SetTranslation(Points[1]);
ponitC.SetTranslation(Points[2]);
} // Called every frame
void AActor_Assignmen1::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector2D ViewportSize;
GetWorld()->GetGameViewport()->GetViewportSize(ViewportSize);
width = height = ViewportSize.X / 2; // 绕z轴
//modelMatrix = get_model_matrix(angle); //绕任意轴
modelMatrix = get_model_matrix_anyAxis(FVector(0, 0, 5), angle);
viewMatrix = get_view_matrix(eye_loc);
projectionMatrix = get_projection_matrix(45, 1, 0.1, 50); RasterizerDraw();
angle += 0.5;
root->SetWorldRotation(FRotator(0, angle, 0));
} FMatrix AActor_Assignmen1::get_view_matrix(FVector eye_pos)
{
FMatrix view = FMatrix::Identity; FMatrix translate = FMatrix(
FPlane(1, 0, 0, -eye_pos.X),
FPlane(0, 1, 0, -eye_pos.Y),
FPlane(0, 0, 1, -eye_pos.Z),
FPlane(0, 0, 0, 1)); view = translate * view;
return view;
} // 绕 Z 轴旋转
FMatrix AActor_Assignmen1::get_model_matrix(float rotation_angle)
{
FMatrix model = FMatrix::Identity; // TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
float fcos = UKismetMathLibrary::DegCos(rotation_angle);
float fsin = UKismetMathLibrary::DegSin(rotation_angle);
FMatrix rotate = FMatrix(
FPlane(fcos, -fsin, 0, 0),
FPlane(fsin, fcos, 0, 0),
FPlane( 0, 0, 1, 0),
FPlane( 0, 0, 0, 1)); model = rotate * model; return model;
} // 任意轴旋转
FMatrix AActor_Assignmen1::get_model_matrix_anyAxis(FVector axis, float rotation_angle)
{
FMatrix model = FMatrix::Identity; axis.Normalize(0.0001);
FMatrix N = FMatrix(
FPlane(0, -axis.Z, axis.Y, 0),
FPlane(axis.Z, 0, -axis.X, 0),
FPlane(-axis.Y, axis.X, 0, 0),
FPlane(0, 0, 0, 0)); FMatrix rotate4f = FMatrix::Identity * UKismetMathLibrary::DegCos(rotation_angle); // nnt = axis x axis的转置
FMatrix nnT = FMatrix(
FPlane(axis.X*axis.X, axis.X*axis.Y, axis.X*axis.Z, 0),
FPlane(axis.Y*axis.X, axis.Y*axis.Y, axis.Y*axis.Z, 0),
FPlane(axis.Z*axis.X, axis.Z*axis.Y, axis.Z*axis.Z, 0),
FPlane(0, 0, 0, 0)); rotate4f += nnT * (1 - UKismetMathLibrary::DegCos(rotation_angle)); rotate4f += N * UKismetMathLibrary::DegSin(rotation_angle); rotate4f.M[3][3] = 1;
model = rotate4f * model;
return model;
} FMatrix AActor_Assignmen1::get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
// Students will implement this function
FMatrix projection = FMatrix::Identity; float t = zNear * UKismetMathLibrary::DegTan(eye_fov / 2);
float b = -t;
float r = t * aspect_ratio;
float l = -r; FMatrix translate = FMatrix(
FPlane(2 * zNear / (r - l), 0, -(r + l) / (r - l), 0),
FPlane(0, 2 * zNear / (t - b), -(t + b) / (t - b), 0),
FPlane(0, 0, -(zNear + zFar) / (zNear - zFar), 2 * zNear * zFar / (zNear - zFar)),
FPlane(0, 0, 1, 0));
projection = translate * projection; return projection;
} void AActor_Assignmen1::RasterizerDraw()
{
FMatrix mvp = projectionMatrix * viewMatrix * modelMatrix; float f1 = (100 - 0.1) / 2.0;
float f2 = (100 + 0.1) / 2.0;
TArray<FVector4> v;
for (FVector& p : Points) {
v.Add(mvp.GetTransposed().TransformFVector4(FVector4(p.X, p.Y, p.Z, 1.0f)));
} for (FVector4& vert : v) {
vert *= 1/vert.W;
vert.X = 0.5 * width * (vert.X + 1.0);
vert.Y = 0.5 * height * (vert.Y + 1.0);
vert.Z = vert.Z * f1 + f2;
} TArray<FVector> triangleVerts;
for (FVector4& vert : v) {
triangleVerts.Add(UKismetMathLibrary::Conv_Vector4ToVector(vert));
} // 调用AHUD 屏幕绘制函数
AMyHUD* myHUD = Cast<AMyHUD>(UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetHUD());
if (myHUD) {
myHUD->rasterize_wireframe(triangleVerts);
}
/*
UKismetSystemLibrary::PrintString(GetWorld(), triangleVerts[0].ToString());
UKismetSystemLibrary::PrintString(GetWorld(), triangleVerts[1].ToString());
UKismetSystemLibrary::PrintString(GetWorld(), triangleVerts[2].ToString());
UKismetSystemLibrary::PrintString(GetWorld(), TEXT("----------"));
*/
} // 场景里的绘线
void AActor_Assignmen1::DrawTriangleIn3D() {
UKismetSystemLibrary::DrawDebugLine(GetWorld(), Points[0], Points[1], FLinearColor::Green, 0.02f, .2f);
UKismetSystemLibrary::DrawDebugLine(GetWorld(), Points[1], Points[2], FLinearColor::Green, 0.02f, .2f);
UKismetSystemLibrary::DrawDebugLine(GetWorld(), Points[2], Points[0], FLinearColor::Green, 0.02f, .2f);
}
创建蓝图派生类,添加面片
创建 AHUD 派生类 AMyHUD
自创建gamemode 并指定HUD,用于绘制屏幕上的线段
MyHUD.h
UCLASS()
class GAMES101_API AMyHUD : public AHUD
{
GENERATED_BODY() public:
virtual void DrawHUD() override;
// 重载用于绘制
void rasterize_wireframe(TArray<FVector>& t);
// 存储三角形的三个点
TArray<FVector> TriangleVerts;
};
MyHUD.cpp
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
if (TriangleVerts.IsValidIndex(0)) {
DrawLine(TriangleVerts[0].X, TriangleVerts[0].Y, TriangleVerts[1].X, TriangleVerts[1].Y,FLinearColor::Red);
DrawLine(TriangleVerts[1].X, TriangleVerts[1].Y, TriangleVerts[2].X, TriangleVerts[2].Y,FLinearColor::Red);
DrawLine(TriangleVerts[2].X, TriangleVerts[2].Y, TriangleVerts[0].X, TriangleVerts[0].Y,FLinearColor::Red);
}
} void AMyHUD::rasterize_wireframe(TArray<FVector>& t)
{
TriangleVerts = t;
}
效果
【UE4】GAMES101 图形学作业1:mvp 模型、视图、投影变换的更多相关文章
- WebGL简易教程(六):第一个三维示例(使用模型视图投影变换)
目录 1. 概述 2. 示例:绘制多个三角形 2.1. Triangle_MVPMatrix.html 2.2. Triangle_MVPMatrix.js 2.2.1. 数据加入Z值 2.2.2. ...
- three.js中的矩阵变换(模型视图投影变换)
目录 1. 概述 2. 基本变换 2.1. 矩阵运算 2.2. 模型变换矩阵 2.2.1. 平移矩阵 2.2.2. 旋转矩阵 2.2.2.1. 绕X轴旋转矩阵 2.2.2.2. 绕Y轴旋转矩阵 2.2 ...
- WebGL或OpenGL关于模型视图投影变换的设置技巧
目录 1. 具体实例 2. 解决方案 1) Cube.html 2) Cube.js 3) 运行结果 3. 详细讲解 1) 模型变换 2) 视图变换 3) 投影变换 4) 模型视图投影矩阵 4. 存在 ...
- 【UE4】GAMES101 图形学作业3:Blinn-Phong 模型与着色
总览 在这次编程任务中,我们会进一步模拟现代图形技术.我们在代码中添加了Object Loader(用于加载三维模型), Vertex Shader 与Fragment Shader,并且支持了纹理映 ...
- 【UE4】GAMES101 图形学作业2:光栅化和深度缓存
总览 在上次作业中,虽然我们在屏幕上画出一个线框三角形,但这看起来并不是那么的有趣.所以这一次我们继续推进一步--在屏幕上画出一个实心三角形,换言之,栅格化一个三角形.上一次作业中,在视口变化之后,我 ...
- 【UE4】GAMES101 图形学作业5:光线与物体相交(球、三角面)
总览 在这部分的课程中,我们将专注于使用光线追踪来渲染图像.在光线追踪中最重要的操作之一就是找到光线与物体的交点.一旦找到光线与物体的交点,就可以执行着色并返回像素颜色. 在这次作业中,我们要实现两个 ...
- 【UE4】GAMES101 图形学作业4:贝塞尔曲线
总览 Bézier 曲线是一种用于计算机图形学的参数曲线. 在本次作业中,你需要实现de Casteljau 算法来绘制由4 个控制点表示的Bézier 曲线(当你正确实现该算法时,你可以支持绘制由更 ...
- 【UE4】GAMES101 图形学作业0:矩阵初识
作业描述 给定一个点P=(2,1), 将该点绕原点先逆时针旋转45◦,再平移(1,2), 计算出变换后点的坐标(要求用齐次坐标进行计算). UE4 知识点 主要矩阵 FMatrix FBasisVec ...
- OpenGL(五) 三维变换之模型视图矩阵
计算机三维图形学中,一个基本的任务是如何描述三维空间中一个物体位置的变化,也就是如何 描述物体的运动.通常情况下,物体位置的变化包含三个基本的变化:平移.旋转和缩放,物体的运动也可以用这三个基本的运动 ...
随机推荐
- 20210716考试-NOIP16
考场时Prim的 $i$ 写成 $k$ 100->0 rank1->rank23 T1 Star Way To Heaven 考场正解:假设你要二分答案,则几个圆组成几道"屏障& ...
- Codeforces 1365D Solve The Maze
### 题目大意: 在一个 $n * m$ 的矩阵中,有空地.坏人.好人和墙.你可以将空地变成墙来堵住坏人.$(n, m)$为出口,是否存在一个方案使得矩阵中所有好人能够走到出口,而所有坏人不能通过出 ...
- redis存取数据sortedSet
有序比无序的更耗性能 一.存取元素 1.添加元素,value存在则替换score值,不存在则添加: 2.获取某个元素的分数 3. 4.获取一定索引区间元素value值,默认按照对应score升序排序: ...
- ajax获取图片
<img id="contents2_img" alt="" src="images/hope.png" style="wi ...
- k8s架构与组件详解
没有那么多花里胡哨,直接进行一个K8s架构与组件的学习. 一.K8s架构 k8s系统在设计是遵循c-s架构的,也就是我们图中apiserver与其余组件的交互.在生产中通常会有多个Master以实现K ...
- HCNP Routing&Switching之IS-IS邻居建立、LSDB同步、拓扑计算和路由形成
前文我们了解了IS-IS的报文结构和类型相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15260670.html:今天我们来聊一聊IS-IS建立邻居. ...
- 远程桌面连接(mstsc)全攻略
打算从今天开始,写一写我经常用的,有长时间使用经验的东西,与大家分享,就从mstsc开始吧! mstsc应该是在Windows中,除了calc.cmd.notepad.mspaint,我使用率最高的系 ...
- 日期SQL 脚本
一个月第一天的 SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)本周的星期一 SELECT DATEADD(wk, DATEDIFF(wk,0,g ...
- JSON,XML设计模式详解
JSON在Java中的应用: Json概念: json 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式用来存储和表示数据.JSON的语言简洁清晰,广为大众所欢迎,是一种理想的数据交换语言 ...
- Zookeeper分布式安装部署
1. 解压安装 1.1 解压Zookeeper安装包到/opt/module/目录下 tar -zxvf /opt/software/apache-zookeeper-3.6.2-bin.tar.gz ...