[Day11] 2D的数学世界 (三) - 位移、旋转、缩放

今日目标

  • 位移、旋转、缩放

以下位移、旋转、缩放仅是补充,又或着是说个人笔记(?),阅读这篇单纯的看算式结果就可以知道,为什麽他的矩阵是长这样了。

位移、缩放

把这两个放在一起讲是因为真的没有甚麽要多补充的,只是单纯少了一轴-Z而已,并且看起来更简单了。

/*
Translate:
   1  0  0  x
   0  1  0  y
   0  0  1  z
   0  0  0  1
*/
Mat4 Mat4Translate(Mat4 origin, float x, float y) {
    Mat4 translate = MAT4_IDENTITY;

    translate.ary2d[3][0] = x;
    translate.ary2d[3][1] = y;

    return Mat4MulMat4(origin, translate);
}

/*
Scale: 
    x  0  0  0
    0  y  0  0
    0  0  z  0
    0  0  0  1
*/
Mat4 Mat4Scale(Mat4 origin, float x, float y) {
    Mat4 scale = MAT4_IDENTITY;

    scale.ary2d[0][0] = x;
    scale.ary2d[1][1] = y;

    return Mat4MulMat4(origin, scale);
}

旋转

好在是2D,要旋转的话,我们只需要Z轴

/*
Rotate:
    s = sin(angle), c = cos(angle)

    c   -s   0   0
    s    c   0   0
    0    0   1   0
    0    0   0   1
*/
Mat4 Mat4EulerRotate(Mat4 origin, float angle) {
    Mat4 rotate = MAT4_IDENTITY;

    float rad = DegToRad(angle);
    float s = sinf(rad), c = cosf(rad);

    rotate.ary2d[0][0] = c;
    rotate.ary2d[0][1] = s;

    rotate.ary2d[1][0] = -s;
    rotate.ary2d[1][1] = c;

    return Mat4MulMat4(origin, rotate);
}

单独拿出来讲是这里,使用的尤拉角(Eular Angle)的旋转,每个轴的旋转都是分开算的,如果是3D的话,每个轴都要可以转360的话,会出现**万向锁(Gimbal Lock)**(这个连结会到YT)。这时就会需要另一种旋转的表示方式,四元数了。这边没有要继续讲四元数,因为我不是特别理解四元数是怎麽运作的,可能会在之後再来补充 :(。

请注意顺序

昨天提过一件事

矩阵运算是从右到左

原因是矩阵的的顺序调换会影响结果。

所以模型矩阵(Model Matrix) x 透视矩阵(Projection Matrix)事实上会是

// Mat4MulMat4是我制作的矩阵相乘的function
MVP = Mat4MulMat4(Projection, Model);

那...模型矩阵,是要先位移呢?还是缩放?还是旋转,这个蛮有趣的,我个人试过的结果会是:**位移

旋转 > 缩放**这个顺序,才会看起来比较正常。

补充: 随着世界改动

如果自由地缩放视窗会发现,里头的矩形没有随着视窗的大小变化进行缩放,这是因为我们缩放了视窗大小,但没有缩放OpenGL的视窗大小,需要使用法宝:

glViewport(int x, int y, int width, int height)

然後glfw也有提供「当视窗大小有变化时」的Callback,一样在CreateWindow加上新的处理

// framebuffer size callback
void FramebufferSizeCallback(GLFWwindow* window, int w, int h) {
    glViewport(0, 0, w, h);
}

// in `CreateWindow`
glfwSetFramebufferSizeCallback(WINDOW.wnd, FramebufferSizeCallback);

就这样,我们的矩形跟贴图就会跟着视窗大小变化了。

参考

然後这是今日的成果,明天(应该)会开始处理时间相关的功能...


<<:  21.unity简易对话介面设计概念

>>:  【第二十一天 - Graph 题目分析】

【day21】创建对象列表(下)

昨天我们已经按照时间去新增我们的资料了,也得到列表啦,那麽我们今天就要来建立点击事件,因为如果只有...

Day 17 管道的应用

Kernel里面除了前述几种物件之外,我们以下介绍其他几种比较重要的物件,首先我们来看所谓的pipe...

Annotation 介绍

Annotation 很常写 Java 或是 Kotlin 的朋友对 annotation 大概不陌...

Day24_Annex A & Statement Ofapplicability (SOA) 附录A与适用性声明书文件-2021/10/07

▉适用性声明书范例(适用或不适用都要提出说明) └这个是老师给的范例…我记得不适用也是要写啦。 ▉估...

学习Python纪录Day16 - 使用Matplotlib绘制图表

使用Matplotlib绘制图表 安装matplotlib套件的命令列指令 pip install ...