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. 如何拉取指定CPU架构并且指定ubuntu版本并且指定cuda和cudnn版本的docker镜像

    本篇讲的重点是如何拉取带有cuda和cudnn的docker镜像,因此这些的镜像源的频道为NVIDIA: 官方地址: https://hub.docker.com/r/nvidia/cuda 根据官方 ...

  2. 如何在X86_64系统上运行arm架构的docker容器——(异构/不同架构)CPU下的容器启动

    近期使用华为的人工智能集群,其中不仅要求异构加速端需要使用昇腾的硬件,更是要求CPU是arm架构的,因此就导致在本地x86电脑上难以对云端的arm版本的镜像进行软件安装和打包操作,为此我们需要在x86 ...

  3. volatile重要特性-可见性,避免指令重排序-案例讲解

    1.背景 volatile 修饰的作用???? 什么是可见性?? 什么是指令重排序?? 2.可见性-案例 package com.my.aqs; /** * @Copyright (C) XXXXX技 ...

  4. List按需转换Map

    需求 : Mybatis的<select>返回一个List,想按照实体类其中的属性转换成Map<String, String>实现过程: 其实有很多方式,可以使用普通for循环 ...

  5. 9. 从0学ARM Cortex-A9 LED汇编、C语言驱动编写

    0. 前言 一般我们购买一个开发板,厂家都会给出对应的电路图文件,我们可以通过搜索对应名称来查找到对应的外设.对于驱动工程师来说,我们只需要知道外设与SOC交互的一些数据线和信号线即可. 用主控芯片控 ...

  6. 【粉丝问答19】Linux内核中为啥变量没初始化就用了?你确定了解宏定义?

    @ 目录 一.问题 二.分析 三.宏定义的注意点 1. 只占用编译时间 2. 宏替换发生时机 3. 预处理包括哪些工作 四.如何快速展开复杂的宏定义? 第一步 第二步 五.练习 六.15个经典宏定义小 ...

  7. win7安装snmp服务

    一.安装SNMP Win7操作系统默认情况下是不安装SNMP服务的,今天讲解一下在Win7操作系统下安装SNMP,具体安装步骤如下: 打开控制面板--卸载程序 WIN7操作系统下安装SNMP的步骤如下 ...

  8. 海康威视测速&闪速测速

    海康威视64g 闪速128g

  9. 关于安装李沐深度学习d2l包报错的解决办法(保姆教程)

    目录 目录:d2l包安装失败的解决过程 前言 一.李沐提供的安装方式 1. 创建一个新的环境 2. 激活 d2l 环境 3. 安装深度学习框架和d2l软件包 3.1 安装PyTorch的CPU或GPU ...

  10. c程序设计语言 by K&R(一)一些c语言基础知识

    出自<c程序设计语言> by K&R: 一.导言 二.类型.运算符与表达式 三.控制流 1. 字符输入与输出 getchar() 和 putchar(),输入一个字符.输出一个字符 ...