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

\[\mathbf{p} + u \mathbf{u} + v\mathbf{v} + w\mathbf{w}
\]

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;
}

课件矩阵

这个矩阵只要注意可以将 任意向量 分解为 垂直于旋转轴和平行于旋转轴的两个向量。平行于旋转轴的分量不会改变。只需要关注垂直于旋转轴的那个分量即可。

关于画出三角形为倒置的情况。

假设:

  1. 老师讲的p2o矩阵完全适配代码,以及其他所有的知识完全正确(Fov aspect)。
  2. 世界坐标系 x y 与地面平行且重合, z 指向天空。我们是这个世界坐标系的观测者,右手系下 x →, y ↑。
  3. get_view_matrix() 完全正确
  4. 我们按照老师的 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的更多相关文章

  1. 软光栅-uraster代码阅读(入门极品)

    软光栅-uraster代码阅读(入门极品) 代码链接:https://github.com/Steve132/uraster 所有的代码都在uraster.hpp中.代码非常简单,适合初学者学习软光栅 ...

  2. Book of Shaders 02 - 矩阵:二维仿射变换练习

    0x00 一些废话 如果要深入学习 CG (Computer Graphics,计算机图形学),必然要学习相关的数学知识.CG 涉及到多个不同的领域,根据所研究领域的不同,也会涉及到不同的数学分支.但 ...

  3. SQL SERVER 中如何用脚本管理作业

    在SQL SERVER中用脚本管理作业,在绝大部分场景下,脚本都比UI界面管理作业要高效.简洁.打个简单的比方,如果你要查看作业的运行时长,如果用UI界面查看,100个作业,你就得在历史记录里面至少查 ...

  4. ACM: SGU 101 Domino- 欧拉回路-并查集

    sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Desc ...

  5. SGU 101.Domino( 欧拉路径 )

    求欧拉路径...直接dfs即可,时间复杂度O(N) -------------------------------------------------------------------------- ...

  6. Hadoop作业提交之TaskTracker获取Task

    [Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ...

  7. python新手 实践操作 作业

    #有如下值集合 [11,22,33,44,55,66,77,88,99],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k1': 大于66的所 ...

  8. java作业—3

    动手动脑: 一.编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数. 方法1(数据类型)(最小值+Math.random()*(最大值-最小值+1)) 例:(int)(1+Math.r ...

  9. 【1414软工助教】团队作业2——需求分析&原型设计 得分榜

    题目 团队作业2--需求分析&原型设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...

  10. 【1414软工助教】团队作业3——需求改进&系统设计 得分榜

    题目 团队作业3--需求改进&系统设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...

随机推荐

  1. Python语言中当前工作目录(Current Working Directory, cwd)与模块搜索第一路径都是指什么???

    相关: 查看并添加python中库的搜索路径 [python]自问自答:python -m参数? ( python3.7 版本 ) 本文主要解释Python语言中的两个基本概念: 当前工作目录(Cur ...

  2. 哈希基础知识学习-python版

    哈希 哈希表 根据key直接进行访问的无序数据结构,复杂度为O(1) 哈希表的实现---字典 初始化 d1 = dict() 查找 #使用中括号[]进行查找,括号内为特定的键, 键-值 dic = { ...

  3. 为了给Javaer落地DDD,我们不得不写开源组件

    本文上回书接<这是DDD建模最难的部分(其实很简单)>,欢迎关注我的同名公众号. https://mp.weixin.qq.com/s/HZKMLF0_I10iczzp2mAR-w   故 ...

  4. AOP(代理模式)

    利用特性Attribute+反射+代理类实现AOP 一.定义自定义特性 /// <summary> /// 自定义特性,方法执行前调用 /// </summary> publi ...

  5. 【测试平台开发】——01后端web开发框架Flask

    官方中文地址:https://flask.net.cn/ 官方英文地址:https://flask.palletsprojects.com/en/2.1.x/ github地址:https://git ...

  6. 【FFmpeg】之Mac系统爬取所有M3U8视频下载方法

    前言 由于有的网站不允许下载视频,到了有效期就不能看了,但是我想以后反复看,怎么办呢? 前提准备 操作系统:Mac 浏览器:谷歌浏览器 抓取m3u8工具:猫爪 视频处理工具:ffmpeg 需要安装工具 ...

  7. docker系列教程:docker图形化工具安装及docker系列教程总结

    通过前面的学习,我们已经掌握了docker-compose容器编排及实战了.高级篇也算快完了.有没有相关,我们前面学习的时候,都是通过命令行来操作docker的,难道docker就没有图形化工具吗?答 ...

  8. Java面试集锦(一)

    计算机网络 摘要:1. 在浏览器中输入url地址 显示主页的过程,整个过程会使用哪些协议 image.jpeg总体来说分为以下几个过程: DNS解析 TCP连接 发送HTTP请求 服务器处理请求并返回 ...

  9. 【YashanDB知识库】ODBC驱动类问题定位方法

    [标题]ODBC驱动类问题定位方法 [需求分类]故障分析 [关键字]ODBC [需求描述]由于我们的ODBC接口目前尚不完善,经常会遇见ODBC接口能力不足导致应用功能无法运行的问题,需要定位手段确定 ...

  10. 痛定思痛,好好做人,从头过一遍PyTorch框架(一)(1.深度学习简介、2.预备知识)

    现在是2024年2月24日,13:59,从研一就开始断断续续说要过一遍框架,到现在博一下学期,还一直拖着呢,拖延症太可怕啦,决定好好做人,不拖了,就从现在开始,好好过一遍,呜呜呜呜呜呜呜呜,(罪该万死 ...