Games 101 作业1
1 坐标系
关于坐标系,坐标系其实就是空间信息。有了坐标系我们可以非常详细的描述这个世界,为了方便一般为一个观测者生成一个坐标系。
坐标系以观测者所在的位置为原点。就像我们常说的前面三米,我们对世界的描述通常是以自己为基础的。
而这个世界可能存在许多观测者,所以这个世界有点混乱。
每个人都在描述这个世界,说一些坐标,eg.一个飞机
A:飞机在我前面3m
B:飞机在我后面3m
C:飞机在我左边3m
那么飞机到底在哪里呢?如果这时另外一个观测者(World)用全局的眼光看这个飞机,这是显而易见的,飞机只有一个,只在一个地方,只有一个坐标。
所以一个个人坐标系的描述如何转化为世界坐标系就是所有人都认可的一个公共坐标系就是非常重要的。
ref1:5th 7.5 Coordinate Transormation
When managing multiple coordinate systems, it’s easy to get confused and wind up with objects in the wrong coordinates, causing them to show up in unexpected places. But with systematic thinking about transformations between coordinate systems, you can reliably get the transformations right.
Geometrically, a coordinate system, or coordinate frame, consists of an origin and a basis—a set of three vectors. Orthonormal bases are so convenient that In 2D, of course, there are two basis vectors.
we’ll normally assume frames are orthonormal unless otherwise specified. In a frame with origin p and basis {\(\mathbf{u}\), \(\mathbf{v}\), \(\mathbf{w}\)}, the coordinates (u, v, w) describe the point
\]
When we store these vectors in the computer, they need to be represented in terms of some coordinate system. To get things started, we have to designate some canonical coordinate system, often called “global” or “world” coordinates, which is used to describe all other systems. In the city example, we might adopt the street grid and use the convention that the x-axis points along Main Street, the y-axis points up, and the z-axis points along Central Avenue. Then, when we write the origin and basis of the car frame in terms of these coordinates, it is clear what we mean.
In 2D our convention, it is to use the point o for the origin, and x and y for the right-handed orthonormal basis vectors x and y (Figure 7.20)
1.2 向量
向量的定义:就是只有大小与方向。我们对于向量的很多认识都是从原点开始进行一个方向的指向。
不过起点放在哪里对某一向量完全没有任何影响。
也就是说一旦我们在世界坐标系下定义了一个向量 \(\mathbf{a}\)。只要在不改变其大小方向的情况下,我们可以拿着他随便乱跑 \(\mathbf{a}\) 还是 \(\mathbf{a}\)。
local-to-world(Frame-to-canonical):
这里的 \(\mathbf{o}, \mathbf{e}, \mathbf{u}, \mathbf{v}\)均是以世界坐标系为基础的向量。
ref2 5th 7.5 Coordinate Transormation
ref3 5th 7.5 Coordinate Transormation
世界坐标系到局部坐标系以及其逆转换。
Hw1 作业片段 main.cpp
意思很明确,camrea coordinate 的坐标原点为 e, 基向量与世界坐标系无异。
所以相机向着着 z轴 负方向看着这个世界。
Eigen::Vector3f eye_pos = {0, 0, 5};
Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos)
{
Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
Eigen::Matrix4f translate;
translate << 1, 0, 0, -eye_pos[0], 0, 1, 0, -eye_pos[1], 0, 0, 1,
-eye_pos[2], 0, 0, 0, 1;
view = translate * view;
return view;
}
课件矩阵
这个矩阵只要注意可以将 任意向量 分解为 垂直于旋转轴和平行于旋转轴的两个向量。平行于旋转轴的分量不会改变。只需要关注垂直于旋转轴的那个分量即可。
关于画出三角形为倒置的情况。
假设:
- 老师讲的p2o矩阵完全适配代码,以及其他所有的知识完全正确(Fov aspect)。
- 世界坐标系 x y 与地面平行且重合, z 指向天空。我们是这个世界坐标系的观测者,右手系下 x →, y ↑。
- get_view_matrix() 完全正确
- 我们按照老师的 z 轴负向 正确实现了透视投影所需矩阵。
推出:
代码给出的三角形是一个等腰三角形,有一致的z轴坐标,三角形所在平面与地面平行。深入地下2m。
给出的相机坐标放在离地面5m 的地方,基础向量与 x y z 一致,所以看向地面即 -z 方向。相机即画面的竖直方向为 y 水平方向为 x。这时候如果把你放在那看,就已经是一个正三角型了。
可以得出在相机坐标系三角形 z 坐标都为 -7m。
很多人的问题是,程序自带的(zNear=0.1 zFar=50),以及相关参数规定了一个处于 z 轴正半轴的视锥,即可视空间。而三角形明明在 z 负半轴 为什么还可以画出三角形,并且三角形向下?
首先我要说明,老师给的所有透视投影矩阵 p2o otho 所有的参数都是基于 n f 为 负数的情况。
所谓透视投影,就是近大远小。所以远处(z 负方向)的物体要乘以一个比例 \(y'=(n/z)*y\),我们很清楚的看到由于除法的关系 (n/z) 是一个正数, 缩小的同时,不会改变原来的位置关系,在上面永远在上面。在下面永远在下面。透视投影(老师所给)变换后,z' = n+f - nf/z 坐标还是在负半轴。并且保持原来的远近关系。
程序自带(zNear=0.1 zFar=50)把这个 y'=(n/z)*y 由于除法的关系 (n/z) 是一个负数,缩小之后还要进行上下的颠倒。这就是症结所在。我们再看 z' = n+f - nf/z, 当 z属于[-0.1,-50]时,即三角形所在的视锥里(三角形 z=-49.38) 被变化到 z'属于[0.1+50-5/(-0.1)=100.1 ,0.1+50-5/(-50)=50.2](三角形 z=50.81)。即正半轴了。
而othor矩阵接受正数(zNear=0.1 zFar=50),刚好不会把三角形变化到正方体里。所以这里也是问题,按三角形缩小反转了并且被放到了 z 正轴。但不在正方体里,我们为什么还可以看见?
是因为在othor之后还应该有一步操作Clipping,就是将不在视锥中的东西切掉。
Clipping in Homogeneous Coordinates (Option 2)
Surprisingly, the option usually implemented is that of clipping in homogeneous
coordinates before the divide.
5th P191
而代码中没有这么做,直接进行齐次坐标化简后 vert /= vert.w(), 然后进行了视口变化。视口变化主要对 x y 坐标 进行,但是代码中还给出 z 的变换,这里没有太懂。视口变化可以看作是先不考虑 z 坐标,然后把图像挤在屏幕上,考虑遮挡关系的时候需要考虑 z 坐标。
所以还是可以看到三角形,而且是倒着的。
因此结论是在假设成立的情况下,将(zNear=0.1 zFar=50)变为负号即可。
关于 opencv Mat 显示问题
mat的显示其实就是二维数组,左上角为(0,0) 右下角为(n-1,n-1)。
而我们人眼比较喜欢左下角为(0,0)。
所以我们看到
void rst::rasterizer::set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color)
{
//old index: auto ind = point.y() + point.x() * width;
// up left = (0,0)
if (point.x() < 0 || point.x() >= width ||
point.y() < 0 || point.y() >= height) return;
// down left = (0, 0)
auto ind = (height-point.y())*width + point.x();
frame_buf[ind] = color;
}
将c点 c.x += 50
将c点 c.x=c.y=0
但是这个算法有问题,我真的是服辣。很容易就数组越界。
eg.x=0 y=0 则 ind=49000, 但是整个 frame_buf.size()=49000。下标取值范围[0,49000)。49000是越界的。但是vector越界不会报错,我真的是服辣。
对这个算法进行修改。
auto ind = (height-1-point.y())*width + point.x();
3.5 今天一天都在看这个代码框架。
3.6 今天看作业二,这个溢出问题已经修改了。视口变化的代码中还给出 z 的变换,这是为了 z-buffer算法 将 z 变化到了正半轴。
Games 101 作业1的更多相关文章
- 软光栅-uraster代码阅读(入门极品)
软光栅-uraster代码阅读(入门极品) 代码链接:https://github.com/Steve132/uraster 所有的代码都在uraster.hpp中.代码非常简单,适合初学者学习软光栅 ...
- Book of Shaders 02 - 矩阵:二维仿射变换练习
0x00 一些废话 如果要深入学习 CG (Computer Graphics,计算机图形学),必然要学习相关的数学知识.CG 涉及到多个不同的领域,根据所研究领域的不同,也会涉及到不同的数学分支.但 ...
- SQL SERVER 中如何用脚本管理作业
在SQL SERVER中用脚本管理作业,在绝大部分场景下,脚本都比UI界面管理作业要高效.简洁.打个简单的比方,如果你要查看作业的运行时长,如果用UI界面查看,100个作业,你就得在历史记录里面至少查 ...
- ACM: SGU 101 Domino- 欧拉回路-并查集
sgu 101 - Domino Time Limit:250MS Memory Limit:4096KB 64bit IO Format:%I64d & %I64u Desc ...
- SGU 101.Domino( 欧拉路径 )
求欧拉路径...直接dfs即可,时间复杂度O(N) -------------------------------------------------------------------------- ...
- Hadoop作业提交之TaskTracker获取Task
[Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ...
- python新手 实践操作 作业
#有如下值集合 [11,22,33,44,55,66,77,88,99],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k1': 大于66的所 ...
- java作业—3
动手动脑: 一.编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 方法1(数据类型)(最小值+Math.random()*(最大值-最小值+1)) 例:(int)(1+Math.r ...
- 【1414软工助教】团队作业2——需求分析&原型设计 得分榜
题目 团队作业2--需求分析&原型设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...
- 【1414软工助教】团队作业3——需求改进&系统设计 得分榜
题目 团队作业3--需求改进&系统设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...
随机推荐
- Singleton bean creation not allowed while singletons of this factory are in destruction
1.背景 一直都是正常运行的程序,检查日志发现有一条报错如下: org.springframework.beans.factory.BeanCreationNotAllowedException: E ...
- 一些八股:1.fetch 的理解。2.let、const、var
一. 说说你对 Fetch 的理解,它有哪些优点和不足? Fetch API 是现代 JavaScript 中用于进行网络请求的接口,旨在替代传统的 XMLHttpRequest.它提供了一种更简单. ...
- # Apache SeaTunnel 究竟是什么?
作者 | Shawn Gordon 翻译 | Debra Chen 原文链接 | What the Heck is Apache SeaTunnel? 我在2023年初开始注意到Apache SeaT ...
- [学习笔记] 丢番图方程 & 同余 & 逆元 - 数论
首先,他们几个有着极大的相似性.另外,他们的各自的思想都能够很好的服务于另外几个,有助于加深理解. 文中有些letax公式抽风了,全屏之后应该能看得见-- 线性丢番图方程 丢番图不是个图啊!他是个ma ...
- nginx配置请求头防止点击劫持
在返回index.html配置中加入add_header X-Frame-Options DENY; location / {undefined root /data/nginx/html/dist/ ...
- zabbix资产清单inventory管理
概述 监控的设备越来越多,有时候搞不清楚哪台服务器是什么配置,大多公司有自己的资产清单,要去专门的系统查询显得多少有点麻烦.为此,zabbix专门设置了设备资产管理功能.我们创建或者编辑主机的时候,可 ...
- 网站接入qq登录
网站接入qq登录可以省去注册账号,增加网站的体验度.那么要实现我自己搭建的站点天天博客的qq单点登录需要以下几个步骤:1,申请appid和appkey 首先要去https://connect.qq.c ...
- UDT(一):概览
1. 参考链接 官网 https://udt.sourceforge.io/ 谷博士对UDT的简单介绍 https://udt.sourceforge.io/doc/udt-2009.ppt 获取UD ...
- c程序设计语言 by K&R(一)一些c语言基础知识
出自<c程序设计语言> by K&R: 一.导言 二.类型.运算符与表达式 三.控制流 1. 字符输入与输出 getchar() 和 putchar(),输入一个字符.输出一个字符 ...
- JavaScript – 单线程 与 执行机制 (event loop)
前言 因为在写 RxJS 系列,有一篇要介绍 Scheduler.它需要对 JS 执行机制有点了解,于是就有了这里篇. 参考 知乎 – 详解JavaScript中的Event Loop(事件循环)机制 ...