游戏引擎学习第91天

黑板:澄清线性独立性

首先,提到线性独立时,之前讲解过的"最小"的概念实际上是在表达线性独立。对于二维坐标系来说,两个基向量是最小的,这两个向量是线性独立的。如果超过两个基向量,就会变得冗余,因此在二维空间中,基向量的数量不应超过两个,这就是线性独立的含义。

如果对线性代数感兴趣,可以深入学习其中的细节,线性独立与"最小"的概念实际上是相同的。虽然这并非本次讨论的重点,但仍然值得补充说明一下。

黑板:基

今天讨论的是坐标系统的基础概念,主要聚焦于屏幕空间中的基向量。首先,屏幕的坐标系统已经确定了:y轴向下增长,x轴则是水平的,也就是如果y坐标增大,屏幕上的位置会向下移动。屏幕的原点在左上角,即(0, 0)的位置,而坐标系统的基向量分别是x轴和y轴,通常分别为(1, 0)和(0, 1)。

在屏幕空间中,可以使用这些基向量来表示任何屏幕上的像素位置。例如,屏幕上每个像素可以看作是单位空间,一个像素等于一个单位。如果我们指定某个位置的坐标,就能在屏幕上确定对应的像素点。通过设置不同的坐标系统和基向量,能够灵活地定义坐标系,例如可以选择把原点放在像素的中心,而不是左上角,或者改变y轴的方向,使其向上增长。

无论如何,定义坐标系统时,最关键的是确定原点和基向量的位置。原点就是(0, 0)所代表的点,而基向量则是定义空间方向的两个向量,x轴和y轴的方向分别由(1, 0)和(0, 1)确定。

通过这些基本元素,可以灵活地创建和调整坐标系统,从而使得在不同坐标系中表示图形或位置变得更加灵活和多样化。

黑板:说我们有一个原点是什么意思?

理解坐标系统中的"原点"和"基向量"有时可能会让人感到困惑,尤其是在这些概念是隐式的情况下。例如,当问到"原点在哪里"时,我们通常会回答"在(0, 0)"位置,这是理所当然的,但这背后有更深的含义。

原点并不是固定的,它是在某个特定的空间中定义的。这个空间可能是物理的,如屏幕的原点就是显示器上的实际位置,表示我们想要绘制的像素点的物理位置。而在虚拟空间中,比如游戏世界的坐标系统中,原点则是一个虚拟的点,它没有实际的物理位置,只是为了定义虚拟世界的起始点而存在。因此,虚拟空间中的原点和基向量的定义通常比较模糊,并且不容易感知。

基向量也是如此,它是定义坐标轴方向的向量。例如,x轴基向量通常表示水平方向的线条,它在屏幕上指向显示器的左侧到右侧。但在其他虚拟空间中,基向量的定义可能并不像现实世界中那么明确,因此理解和使用这些基向量时,很多东西是隐式的,需要根据具体上下文来理解。

总的来说,理解这些坐标系的元素需要注意它们的定义背景,是否来自物理世界,还是纯粹的虚拟构建。

黑板:考虑用其他原点和基向量来描述原点和基向量

当开始处理坐标变换和图形操作时,坐标系和基向量的定义变得更加复杂。最初,我们有一个虚拟的世界坐标系,其中定义了原点和基向量,例如:(0, 0)是原点,(1, 0)是x轴基向量,(0, 1)是y轴基向量。这些都是虚拟的定义,它们只存在于我们构建的虚拟空间中。

一旦我们定义了一个坐标系,就可以使用它来描述其他坐标系。这意味着任何一个坐标系的原点和基向量,都可以通过其他坐标系来表示。例如,如果我们创建了一个新的坐标系,其原点可以通过计算从世界坐标系原点开始的偏移量来描述。这个偏移量可以在x轴和y轴上分别移动一定的距离。

一旦定义了新坐标系的原点,就可以在这个新坐标系内定义点的位置。这个新的坐标系的基向量,也可以用现有的坐标系的基向量来表示。例如,如果要定义新的y轴,可以通过测量它相对于现有坐标系的x轴和y轴的方向,计算出它的分量。例如,如果新的y轴大致呈45度角,可以将其单位向量表示为(0.707, 0.707),这表示它在x轴和y轴上的分量。

通过这样的方式,一个坐标系的定义可以依赖于另一个坐标系,从而能够灵活地进行坐标变换和图形计算。

黑板:我为什么要关心这个?

我们关心这些内容是因为它们为旋转和缩放提供了支持。为了实现旋转和缩放,我们需要能够将一个坐标系的定义转换到另一个坐标系。这种转换允许我们在不同的坐标系之间进行坐标变换,从而处理对象的旋转和缩放。例如,旋转一个对象意味着它相对于原点的方向发生了变化,而缩放则意味着它在坐标系中拉伸或收缩。这些操作需要基于坐标变换来实现。通过理解如何定义和转换坐标系,能够更容易地实现这些图形变换。

黑板:旋转和缩放

首先,我们定义了一个虚拟的坐标系,并在其中定义了一个形状,例如一个三角形。在这个坐标系中,三角形的每个顶点都有明确的坐标,例如点A、B、C,它们的坐标可以是某个特定的值。通过定义这些坐标,可以准确地描述这个形状的位置和大小。

然后,我们可以将这个坐标系统中的点通过坐标轴的移动来解释。假设从原点出发,沿着X轴和Y轴分别移动相应的距离,最终会到达三角形的各个点。这样一来,三角形的位置和形状就得到了定义。

这种方式为旋转和缩放形状提供了可能。要实现旋转和缩放,只需要对坐标轴进行旋转和缩放处理。通过调整坐标轴的基准向量,我们可以改变原有坐标系的方向和大小,从而改变形状的位置和比例。最终,我们能够从新的坐标系中读取出三角形的顶点坐标,完成旋转和缩放操作。

黑板:旋转示例

假设进行旋转操作,首先我们旋转坐标系的基准向量,调整X轴和Y轴的方向,然后我们可以重新按照原来的方式计算每个点的位置。对于每个点,例如点A,可以沿着新的X轴和Y轴分别移动相应的距离,最终确定其新的位置。通过这种方式,尽管形状的位置和方向发生了变化,但其形状本身保持不变。

如果进行缩放操作,情况会有所不同。缩放操作会改变坐标轴的长度,使得点沿着新的X轴和Y轴的方向移动的距离发生变化。通过这种缩放处理,形状的大小将会改变,但形状的结构和比例依然是基于原始定义的。

黑板:缩放示例

如果对坐标系进行缩放,假设将Y轴的长度变为原来的两倍,而X轴保持不变,那么沿着X轴的方向,形状的表现不受影响,依然和原来的形状相同。然而,在沿Y轴的方向上,形状会发生显著的变化,因为Y轴的伸展导致形状在垂直方向上的延伸变长,从而形状被拉长。这表明,通过改变坐标系的基准向量(如X轴和Y轴的缩放),可以对在这些基准下定义的形状进行各种变形、扭曲或缩放,达到对形状的操控和变化。

黑板:这在代码中是什么样的?

在代码中,进行坐标变换(如平移、旋转、缩放)是相对简单的。基本操作是从原点出发,沿着指定的轴(X轴和Y轴)移动,基于这些信息来计算新的点的位置。具体来说,给定点的坐标(例如A的X坐标和Y坐标),可以通过从原点出发,沿着X轴和Y轴分别移动相应的距离,得到该点的最终位置。

为了在代码中实现这种变换,可以定义原点和基准向量(X轴和Y轴)。这些向量代表了坐标系的方向和尺度,通过这些定义就能对点进行平移、旋转和缩放等变换。例如,在某个世界坐标系下,如果需要定义一个房屋的坐标系(该房屋在世界坐标系中已被旋转和缩放),可以通过设定该房屋坐标系的原点、X轴和Y轴来描述。

通过这样的变换,我们可以把任何在房屋空间内的点变换到世界坐标系中,保持正确的旋转和缩放效果。因此,基本的平移已经在先前的操作中实现,接下来的任务是引入旋转和缩放的计算方法。

黑板:这是我们现在想要在渲染器中引入的内容

即使目前没有完全实现绘制功能,也可以通过绘制一些点来检查变换是否正确。例如,可以通过绘制一个小三脚来实现,因为我们可以绘制矩形。具体做法是绘制原点、X轴和Y轴的点,这样就能直观地看到这些点是否按照预期进行计算和变换。通过这种方式,可以验证计算是否正确,确保变换的各个部分(如平移、旋转和缩放)都能正确地反映在图形上。

黑板:我们如何定义 X 和 Y 轴?(单位圆)

如何定义X轴和Y轴的起点很简单,因为这就是一个点,移动点的操作大家都很熟悉。至于如何找到X轴和Y轴的方向,利用单位圆是一个非常简单的方法。单位圆的半径为1,通过单位圆,我们可以使用余弦和正弦值来表示角度变化下的坐标。

在单位圆中,当角度变化时,余弦值表示该角度对应的点的X坐标,正弦值表示Y坐标。例如,当角度为0时,单位圆上的点为(1,0),这就是X轴;当角度为90度时,点为(0,1),这就是Y轴。

如果要创建一个旋转的坐标系统,可以通过使用余弦和正弦来表示X轴和Y轴。当角度为0时,X轴就是(1, 0),而当角度为90度时,Y轴就是(0, 1)。要实现旋转,只需要通过余弦和正弦来获取单位圆上的坐标点。

此外,如果要对这些坐标进行缩放,只需将结果乘以一个缩放因子。如果对X轴和Y轴应用相同的缩放因子,则得到均匀缩放;如果使用不同的缩放因子,则得到非均匀缩放,像是拉伸或压缩。这些操作都非常简单易行。

黑板:由于在 2D 中的优化,带来了一个方便的优化

在二维空间中,Y轴的定义非常简单。通过将角度加上90度,我们可以得到Y轴的坐标点。实际上,Y轴的向量是与X轴的向量相同的,只不过是将X轴的向量旋转了90度。因此,我们不需要重新计算一个完全不同的向量,而是可以直接基于X轴的向量来构造Y轴的向量。

通过观察几何关系,可以发现,如果我们已经计算出了X轴上的坐标(例如余弦和正弦值),那么构造Y轴的坐标非常简单。具体来说,Y轴的X坐标就是原来X轴的正弦值,Y轴的Y坐标就是原来X轴的余弦值,只是需要注意符号的变化。

因为在单位圆中,余弦值代表的是X轴的坐标,而正弦值代表的是Y轴的坐标,在旋转90度后,这两个值会交换位置。此外,还需要注意的是,正弦值的符号会发生变化。如果原来的正弦值是正数,在旋转后可能会变成负数,因此需要将这个值取负,以确保得到正确的方向。

总结来说,构造Y轴的过程非常简单,只需要交换X轴和Y轴的坐标,并且调整正弦值的符号。这样就可以有效地生成旋转后的坐标系统。

黑板:你也可以直接代入并计算

另外,还可以直接利用三角恒等式来计算。在三角学中,有一些标准的恒等式可以直接使用。例如,余弦加90度等于负正弦,正弦加90度等于余弦。这些是常见的三角恒等式,如果能记住这些恒等式,就不需要再画图来推导。只需要代入公式,就可以得到正确的值。通过这种方法,可以更加简洁和快速地计算旋转后的坐标,而不需要依赖图形。

黑板:垂直运算符

在二维空间中,有一个概念叫做"垂直操作符"(perp operator),而是指一个将二维向量转换为与其垂直的向量的操作符。具体来说,垂直操作符会对一个二维向量(x,y)进行操作,将其y坐标取负值,并交换x和y坐标的位置。这样就能得到一个与原向量垂直的向量,且两个向量的长度相同。

这个操作很有用,因为无论给定什么向量,都可以通过这一方法快速得到与其垂直的向量。这种方法不仅简单,而且可以在任何二维空间中有效地应用。通过交换和取负坐标,可以轻松地构造出垂直向量,而不需要进行复杂的计算。

黑板:我们所需要做的就是

要创建一个旋转基底(rotated basis)其实是非常简单的。首先,我们的x轴可以通过cos θ和sin θ来表示,而y轴则是x轴的垂直向量(即perp操作)。这就是创建旋转基底的全部步骤。

我们已经知道,cos²(θ) + sin²(θ) 的平方根等于1,所以这两个向量的长度已经是1,因此不需要担心它们的长度。这样,我们就能轻松创建旋转基底。如果需要对基底进行缩放,只需要将这些轴分别乘以所需的缩放因子即可。

这个过程非常简单,适用于任意角度的旋转,而且通过调整缩放因子,可以灵活地控制基底的大小。

进入代码并创建一个旋转的组件

为了创建一个旋转的坐标系示例,可以按照以下步骤进行:

首先,定义一个原点、x轴和y轴。这些将是坐标系的基础。接着,添加一个渲染函数,将坐标系画出来。通过将坐标系的原点和x轴、y轴的方向向量传递给渲染器,可以实现渲染。

为了确保渲染的坐标系能够正确显示,可以为坐标系添加颜色,这样在多个坐标系同时显示时,可以区分不同的坐标系。这里可以将颜色设置为黄色,以便更容易区分。

接下来,修改游戏状态结构,加入一些必要的参数,比如时间和缩放值。在渲染之前,每一帧的时间都会递增,方便控制旋转等效果。

在这过程中,主要处理的是2D坐标系的绘制,因此需要确保渲染函数能够正确处理2D坐标系的原点、x轴和y轴。

通过这种方法,可以验证渲染器是否能够正确识别并绘制坐标系,确保在游戏中能够展示旋转效果。

运行游戏,发现代码出问题了

遇到代码问题时,首先需要排查渲染组的设置和处理是否正确。在渲染流程中,出现了错误,导致代码没有按照预期执行。为了解决问题,可以通过设置调试点来检查流程,尤其是检查清除操作和默认无效情况的处理是否正常。

当发现渲染的默认无效情况未触发时,可能需要检查相关的条件和逻辑,确保所有的检查和错误处理都按顺序执行。通过逐步调试和分析代码,可以找出问题所在,并进行修复。

领悟的时刻:render_entry_coordinate_system 缺少其 Header

在调试过程中,发现问题的根源是忘记添加必要的Header。所有渲染元素需要包含一个Header,虽然目前没有实际内容,但是为了避免未来的错误,决定去掉这个Header,因为它实际上并不需要存在。这是一个短期的解决办法,已经意识到它容易引入错误。虽然目前不打算立即去除,但计划在明天修复,避免这个冗余部分成为潜在的 bug 来源。在当前步骤中,决定继续完成已有的任务,而将这个小问题留待后续处理。

为我们的 coordinate_system 添加一个 case

在调试过程中,决定直接使用像素来显示坐标系统,以便更直观地观察。为了做到这一点,创建了一个矩形绘制函数,定义了颜色值,并设置了矩形的尺寸(例如5x5像素)。然后,通过使用坐标系的原点来计算位置,以便能够在屏幕上看到该坐标系统。

定义 coordinate_system 使其可见

在调试过程中,决定将坐标系的原点设置在屏幕中心,并定义X轴为100像素,尝试绘制矩形。然而,颜色值似乎不正确,经过检查发现,颜色的RGB值被设置为全零,这导致了颜色显示异常。设置了断点后发现,确实是颜色值没有正确传递。解决了这个问题后,继续绘制坐标轴,X轴和Y轴上分别绘制了100像素间距的点,但颜色问题仍然存在,需要进一步检查。

在游戏中查看结果并应用变换

实现了一个简单的坐标系统,接着尝试使用正余弦函数来旋转坐标轴。首先,提到要将轴的长度从外部拉出来进行缩放,并使用正弦和余弦来定义Y轴的垂直方向。然而,发现需要进行一些数学计算,特别是需要使用三角函数。通过引入余弦函数后,基于时间值来旋转坐标轴,达到了预期的效果,坐标系统能够按照预定方式旋转。

实时编辑这个 coordinate system

通过改变缩放值,可以调整坐标系统的大小。例如,可以将其缩小或放大,从而改变旋转坐标轴的大小。同时,任何在该坐标系统中编码的内容,都能按照之前讨论的公式正确地被提取出来。此外,还可以引入非均匀缩放,例如通过调整Y轴的缩放值,得到一个更加拉长的坐标轴。这样,可以将任意点进行旋转和缩放,只需要在这个坐标系统中进行解释。

插入一些在该轴上编码的点

在渲染组中,使用坐标系统来表示一些点,这些点纯粹是用于展示的。假设有16个点,使用之前提到的公式来渲染这些点。具体来说,对于每一个点,使用公式 P.X * x轴 + P.Y * y轴,即从原点出发,根据X轴和Y轴的坐标值计算出新的点的位置,并绘制一个矩形以显示这些点的位置。

为了生成这些点,首先创建一个简单的网格结构,通过在X轴和Y轴上分别按固定间隔增加坐标值来实现网格的分布。之后,这些点将被传入渲染函数,通过给定的坐标系统进行渲染和绘制。

减少点的数量,并在游戏中查看

在调试过程中,发现原本初始化的点数量过多,超出了预期的范围,调整后限制了点的数量为16个。调整后,能够更准确地显示空间的布局。为了进一步简化操作,决定关闭地面缓冲区的重新计算功能,避免不必要的执行重新加载。这样,能够保持程序运行,并继续进行后续调试。

玩弄这些轴

在调整过程中,只有坐标轴发生了变化,而点的定义保持不变。首先,通过将y轴缩放,使其与x轴相同,结果变回正方形。接着,通过增大y轴的比例,看到它在空间中被拉伸。除此之外,还可以尝试让两个轴不再垂直,而是进行偏斜调整。通过改变角度并进行角度添加,可以实现轴的错位,从而获得不同的视觉效果。

我们有派吗?

在调整过程中,尝试使用π来进行计算,然而发现代码中可能没有预定义π的值,因此手动使用1.5来代替。经过调试后,发现问题出在参数为100上,导致计算结果未按预期变化。

继续玩

通过调整坐标轴的角度,可以实现对定义在该坐标系内的所有点进行扭曲或偏移。这种变换不仅可以进行旋转和缩放,还能够通过改变坐标轴的角度来改变点的位置,使其在空间中发生变化。无论是使点在某个轴上挤压,还是通过扭曲来改变整个坐标系,都会影响所有通过这些轴定义的点的位置。通过这种方式,可以灵活地控制点的位置和形状,调整原点和坐标轴,从而实现不同的空间变换。

你通常会非常担心命名方案吗?你似乎总是选一个足够好的名字然后就继续了

通常不太担心命名方案,只要名称合理就行。觉得可以随时更改名称,因此不会花太多时间在这个上面。

这是那个变量吗?

有时必须强调这一点,但那不可能是变量,怎么可能是变量呢?没人见过这样一个变量,连一点可能性都没有,它只是一个旋转的小钻石形状。

你怎么画得这么快?你是用绘图板和笔吗?

使用画板和笔时,通常会用一个小型的Wacom Graphite,类似于Graphite或其他型号。

我只跟着看了一部分,但似乎基本的旋转功能搞起来很容易。我在想,开始通过在平面上采样渲染纹理会需要多少额外工作

基本的旋转功能实现起来相对简单,而要开始通过在平面上采样纹理进行渲染其实并不需要太多额外的工作,这部分的实现相对容易。关于变量的讨论,可能这个变量存在于旋转过程中某个不可见的区域,即它在某个看不见的地方存在,只是我们目前无法看到。

是否有可能在 memory_arena 中进行 realloc 操作?

在内存池(memory arena)中进行realloc是可能的,但这取决于具体的含义。通常,realloc可以返回一个新的内存块,因此可以通过在内存池的末尾分配新的空间并返回该指针来实现这个操作。但是,如果指的是允许内存块的增长,那就不行,因为内存池的内存总是紧凑排列的,这就是内存池的设计目标。因此,内存块只能在内存池的末尾增长,而不会在中间进行扩展。

参数化和极坐标函数以后会用到吗?

极坐标和参数函数将会在稍后的工作中使用,实际上,原点系统(origin systems)本质上就是极坐标函数的扩展版本。通过这种方式,定义了某些事物后,可以根据需要进行旋转。极坐标本身通常不太有用,除非是在构建基底时使用,因为通常是使用极坐标来构建基底,实际上这就是极坐标的应用。因此,通常并不会专门以极坐标来思考问题。

至于参数函数,实际上我们到目前为止所做的工作都可以看作是参数化的。所以,这取决于是否讨论某个特定的内容。

在探索阶段,软件渲染器会包括子像素定位和抗锯齿吗?

抗锯齿(anti-aliasing)将会成为渲染器的一部分,尽管目前正在处理的是渲染器本身,而不是探索阶段。渲染器中包括了抗锯齿和位置调整的实现,它们会一并完成。在编程方面,目前没有更多的问题。可能由于延迟的原因,问题暂时没有显示出来,可能有人正在准备提出一些问题,但此时尚未看到。

使大小成比例

讨论了让图形的大小与角度成比例变化的想法,例如通过公式 100 + 25.0 * cos(角度) * 0.1 来调整图形的缩放,使其根据角度变化,从而使图形看起来像是根据角度收缩或膨胀。此外,还提到描述"圣诞树三角形"(Triforce)的方式,觉得这个比喻挺有趣的。

尽情玩

讨论了可以继续对图形进行极限调整的可能性,甚至可以进行非常复杂的变化,类似于时间依赖的向量波动(vector bobs)。并且提到问题已经差不多解决。

时间相关的颜色β

讨论了粒子系统的可能性,认为如果目前的工作让人觉得有趣,粒子系统将更加吸引人,因为它涉及大量复杂且有趣的操作。此外,还提到了4k演示的难度,并认为需要更专业的人来帮助实现。

需要更多的点

讨论了粒子系统的话题,但决定暂时不深入,因为这更适合之后进行。提到在当前阶段应该聚焦于其他内容,避免过多分心。

今天就到此为止,并对未来做一个小小的展望γ

后面可能开始实现旋转和缩放的纹理

相关推荐
Fleshy数模25 分钟前
基于机器学习的实时手势识别系统实现
人工智能·机器学习
龙侠九重天25 分钟前
C# 机器学习数据处理
开发语言·人工智能·机器学习·ai·c#
空间机器人8 小时前
自动驾驶 ADAS 器件选型:算力只是门票,系统才是生死线
人工智能·机器学习·自动驾驶
&&Citrus8 小时前
【CPN学习笔记(二)】Chap2 非分层颜色 Petri 网——从一个简单协议开始读懂 CPN
笔记·学习·php·cpn·petri网
小松要进步8 小时前
机器学习1
人工智能·机器学习
泰恒8 小时前
openclaw近期怎么样了?
人工智能·深度学习·机器学习
小橘子8319 小时前
(学习)Claude Code 源码架构深度解析
学习·程序人生·架构
哥布林学者10 小时前
深度学习进阶(五)Vision Transformer
机器学习·ai
罗西的思考11 小时前
【OpenClaw】通过 Nanobot 源码学习架构---(5)Context
人工智能·算法·机器学习
diablobaal11 小时前
云计算学习100天-第102天-Azure入门4
学习·云计算·azure