Basis

用于表示 3D 旋转和缩放的 3×3 矩阵。

描述

The Basis built-in Variant type is a 3×3 matrix) used to represent 3D rotation, scale, and shear. It is frequently used within a Transform3D.

A Basis is composed by 3 axis vectors, each representing a column of the matrix: x, y, and z. The length of each axis (Vector3.length) influences the basis’s scale, while the direction of all axes influence the rotation. Usually, these axes are perpendicular to one another. However, when you rotate any axis individually, the basis becomes sheared. Applying a sheared basis to a 3D model will make the model appear distorted.

A Basis is orthogonal if its axes are perpendicular to each other. A basis is normalized if the length of every axis is 1. A basis is uniform if all axes share the same length (see get_scale). A basis is orthonormal if it is both orthogonal and normalized, which allows it to only represent rotations. A basis is conformal if it is both orthogonal and uniform, which ensures it is not distorted.

For a general introduction, see the Matrices and transforms tutorial.

Note: Godot uses a right-handed coordinate system, which is a common standard. For directions, the convention for built-in types like Camera3D is for -Z to point forward (+X is right, +Y is up, and +Z is back). Other objects may use different direction conventions. For more information, see the 3D asset direction conventions tutorial.

Note: The basis matrices are exposed as column-major order, which is the same as OpenGL. However, they are stored internally in row-major order, which is the same as DirectX.

备注

通过 C# 使用该 API 时会有显著不同,详见 C# API 与 GDScript 的差异

教程

属性

Vector3

x

Vector3(1, 0, 0)

Vector3

y

Vector3(0, 1, 0)

Vector3

z

Vector3(0, 0, 1)

构造函数

Basis

Basis()

Basis

Basis(from: Basis)

Basis

Basis(axis: Vector3, angle: float)

Basis

Basis(from: Quaternion)

Basis

Basis(x_axis: Vector3, y_axis: Vector3, z_axis: Vector3)

方法

float

determinant() const

Basis

from_euler(euler: Vector3, order: int = 2) static

Basis

from_scale(scale: Vector3) static

Vector3

get_euler(order: int = 2) const

Quaternion

get_rotation_quaternion() const

Vector3

get_scale() const

Basis

inverse() const

bool

is_conformal() const

bool

is_equal_approx(b: Basis) const

bool

is_finite() const

Basis

looking_at(target: Vector3, up: Vector3 = Vector3(0, 1, 0), use_model_front: bool = false) static

Basis

orthonormalized() const

Basis

rotated(axis: Vector3, angle: float) const

Basis

scaled(scale: Vector3) const

Basis

slerp(to: Basis, weight: float) const

float

tdotx(with: Vector3) const

float

tdoty(with: Vector3) const

float

tdotz(with: Vector3) const

Basis

transposed() const

运算符

bool

operator !=(right: Basis)

Basis

operator (right: Basis)

Vector3

operator (right: Vector3)

Basis

operator (right: float)

Basis

operator (right: int)

Basis

operator /(right: float)

Basis

operator /(right: int)

bool

operator ==(right: Basis)

Vector3

operator [](index: int)


常量

IDENTITY = Basis(1, 0, 0, 0, 1, 0, 0, 0, 1) 🔗

单位基。这是一个没有旋转、没有剪切的基,其缩放为 1。这意味着:

  1. var basis := Basis.IDENTITY
  2. print("| X | Y | Z")
  3. print("| %s | %s | %s" % [basis.x.x, basis.y.x, basis.z.x])
  4. print("| %s | %s | %s" % [basis.x.y, basis.y.y, basis.z.y])
  5. print("| %s | %s | %s" % [basis.x.z, basis.y.z, basis.z.z])
  6. # 输出:
  7. # | X | Y | Z
  8. # | 1 | 0 | 0
  9. # | 0 | 1 | 0
  10. # | 0 | 0 | 1

这与创建没有任何参数的 Basis 相同。该常量可用于使你的代码更清晰,并与 C# 保持一致。

FLIP_X = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1) 🔗

当任意基被 FLIP_X 相乘时,它会取负 x 轴(X 列)的所有分量。

FLIP_X 被任意基相乘时,它会取负所有轴(X 行)的 Vector3.x 分量。

FLIP_Y = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1) 🔗

当任意基被 FLIP_Y 相乘时,它会取负 y 轴(Y 列)的所有分量。

FLIP_Y 被任意基相乘时,它会取负所有轴(Y 行)的 Vector3.y 分量。

FLIP_Z = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1) 🔗

当任意基被 FLIP_Z 相乘时,它会取负 z 轴(Z 列)的所有分量。

FLIP_Z 被任意基相乘时,它会取负所有轴(Z 行)的 Vector3.z 分量。


属性说明

Vector3 x = Vector3(1, 0, 0) 🔗

该基的 X 轴和矩阵的 0 列。

在单位基上,该向量指向右侧(Vector3.RIGHT)。


Vector3 y = Vector3(0, 1, 0) 🔗

该基的 Y 轴和矩阵的第 1 列。

在单位基上,该向量指向上方(Vector3.UP)。


Vector3 z = Vector3(0, 0, 1) 🔗

该基的 Z 轴和矩阵的第 2 列。

在单位基上,该向量指向后面(Vector3.BACK)。


构造函数说明

Basis Basis() 🔗

构造一个与 IDENTITY 相同的 Basis


Basis Basis(from: Basis)

构造给定 Basis 的副本。


Basis Basis(axis: Vector3, angle: float)

构造仅表示旋转的 Basis,给定的 angle 以弧度为单位,表示围绕 axis 轴的旋转量。这个轴必须是归一化的向量。

注意:与对 IDENTITY 基使用 rotated 一致。多角度旋转请改用 from_euler


Basis Basis(from: Quaternion)

根据给定的 Quaternion 构造仅表示旋转的 Basis

注意:四元数存储旋转,不会存储缩放。因此,BasisQuaternion 的转换并不一定可逆。


Basis Basis(x_axis: Vector3, y_axis: Vector3, z_axis: Vector3)

根据 3 个轴向量构造 Basis。这些是基矩阵的列向量。


方法说明

float determinant() const 🔗

返回基矩阵的行列式。在高等数学中,这个数可以用来确定一些性质:

  • 如果行列式为 0,则基不可逆(见 inverse)。

  • 如果行列式为负数,则基表示负缩放。

注意:如果基的每个轴缩放都相同,那么这个行列式始终为 2 的该缩放次幂。


Basis from_euler(euler: Vector3, order: int = 2) static 🔗

根据给定的 Vector3 构造 Basis,这个向量为 欧拉角,单位为弧度。

  • Vector3.x 应包含围绕 x 轴的角度(俯仰)。

  • Vector3.y 应包含围绕 y 轴的角度(偏摆)。

  • Vector3.z 应包含围绕 z 轴的角度(翻滚)。

GDScriptC#

  1. # 创建 Z 轴向下的 Basis。
  2. var my_basis = Basis.from_euler(Vector3(TAU / 4, 0, 0))
  3. print(my_basis.z) # 输出 (0, -1, 0)。
  1. // 创建 Z 轴向下的 Basis。
  2. var myBasis = Basis.FromEuler(new Vector3(Mathf.Tau / 4.0f, 0.0f, 0.0f));
  3. GD.Print(myBasis.Z); // 输出 (0, -1, 0)。

连续旋转的顺序可以通过 order 修改(见 EulerOrder 常量)。默认使用 YXZ 约定(@GlobalScope.EULER_ORDER_YXZ):基首先围绕 Y 轴旋转(偏摆),然后围绕 X 轴旋转(俯仰),最后围绕 Z 轴旋转(翻滚)。这个顺序在相对的函数 get_euler 中是相反的。


Basis from_scale(scale: Vector3) static 🔗

根据给定的 scale 向量构造仅表示缩放的 Basis,不包含旋转和切变。

GDScriptC#

  1. var my_basis = Basis.from_scale(Vector3(2, 4, 8))
  2. print(my_basis.x) # 输出 (2, 0, 0).
  3. print(my_basis.y) # 输出 (0, 4, 0).
  4. print(my_basis.z) # 输出 (0, 0, 8).
  1. var myBasis = Basis.FromScale(new Vector3(2.0f, 4.0f, 8.0f));
  2. GD.Print(myBasis.X); // 输出 (2, 0, 0).
  3. GD.Print(myBasis.Y); // 输出 (0, 4, 0).
  4. GD.Print(myBasis.Z); // 输出 (0, 0, 8).

注意:在线性代数中,这种基矩阵也被称作对角矩阵


Vector3 get_euler(order: int = 2) const 🔗

Vector3 的形式返回基的旋转,这个向量为 欧拉角,单位为弧度。

  • Vector3.x 包含围绕 x 轴的角度(俯仰)。

  • Vector3.y 包含围绕 y 轴的角度(偏摆)。

  • Vector3.z 包含围绕 z 轴的角度(翻滚)。

连续旋转的顺序可以通过 order 修改(见 EulerOrder 常量)。默认使用 YXZ 约定(@GlobalScope.EULER_ORDER_YXZ):首先计算围绕 Z 轴的旋转(翻滚),然后计算围绕 X 轴的旋转(俯仰),最后计算围绕 Y 轴旋转(偏摆)。这个顺序在相对的函数 from_euler 中是相反的。

注意:欧拉角更符合直觉,但是并不适合 3D 数学。因此请考虑改用返回 Quaternionget_rotation_quaternion

注意:在检查器面板中,基的旋转通常是以欧拉角的形式显示的(单位为度),与 Node3D.rotation 属性相同。


Quaternion get_rotation_quaternion() const 🔗

Quaternion 的形式返回基的旋转。

注意:四元数更适合 3D 数学,但是并不那么符合直觉。用户界面相关的场合请考虑使用返回欧拉角的 get_euler 方法。


Vector3 get_scale() const 🔗

返回该基的每个轴的长度,作为一个 Vector3。如果该基没有被剪切,这就是缩放系数。它不受旋转的影响。

GDScriptC#

  1. var my_basis = Basis(
  2. Vector3(2, 0, 0),
  3. Vector3(0, 4, 0),
  4. Vector3(0, 0, 8)
  5. )
  6. # 以任何方式旋转基都会保持其缩放。
  7. my_basis = my_basis.rotated(Vector3.UP, TAU / 2)
  8. my_basis = my_basis.rotated(Vector3.RIGHT, TAU / 4)
  9. print(my_basis.get_scale()) # 输出 (2, 4, 8)。
  1. var myBasis = new Basis(
  2. Vector3(2.0f, 0.0f, 0.0f),
  3. Vector3(0.0f, 4.0f, 0.0f),
  4. Vector3(0.0f, 0.0f, 8.0f)
  5. );
  6. // 以任何方式旋转基都会保持其缩放。
  7. myBasis = myBasis.Rotated(Vector3.Up, Mathf.Tau / 2.0f);
  8. myBasis = myBasis.Rotated(Vector3.Right, Mathf.Tau / 4.0f);
  9. GD.Print(myBasis.Scale); // 输出 (2, 4, 8)。

注意:如果 determinant 返回的值为负数,则缩放也为负数。


Basis inverse() const 🔗

返回 该基矩阵的逆矩阵


bool is_conformal() const 🔗

如果该基是共形的,则返回 true。共形的基既是正交的(轴彼此垂直)又是均匀的(轴共享相同长度)。该方法在物理计算过程中特别有用。


bool is_equal_approx(b: Basis) const 🔗

如果该基和 b 近似相等,则返回 true,判断方法是在每个向量分量上调用 @GlobalScope.is_equal_approx


bool is_finite() const 🔗

如果该基是有限的,则返回 true,判断方法是在每个向量分量上调用 @GlobalScope.is_finite


Basis looking_at(target: Vector3, up: Vector3 = Vector3(0, 1, 0), use_model_front: bool = false) static 🔗

创建一个带有旋转的新 Basis,使向前轴(-Z)指向 target 的位置。

默认情况下,-Z 轴(相机向前)被视为向前(意味着 +X 位于右侧)。如果 use_model_fronttrue,则 +Z 轴(资产正面)被视为向前(意味着 +X 位于左侧)并指向 target 的位置。

向上轴(+Y)尽可能靠近 up 向量,同时保持垂直于向前轴。返回的基是正交归一化的(参见 orthonormalized)。targetup 向量不能是 Vector3.ZERO,并且不能彼此平行。


Basis orthonormalized() const 🔗

返回该基的正交归一化版本。正交归一化基既是正交的(轴彼此垂直)又是归一化的(轴长度为 1),这也意味着它只能代表旋转。

调用该方法通常很有用,以避免旋转基上的舍入错误:

GDScriptC#

  1. # 每帧旋转该 Node3D。
  2. func _process(delta):
  3. basis = basis.rotated(Vector3.UP, TAU * delta)
  4. basis = basis.rotated(Vector3.RIGHT, TAU * delta)
  5. basis = basis.orthonormalized()
  1. // 每帧旋转该 Node3D。
  2. public override void _Process(double delta)
  3. {
  4. Basis = Basis.Rotated(Vector3.Up, Mathf.Tau * (float)delta)
  5. .Rotated(Vector3.Right, Mathf.Tau * (float)delta)
  6. .Orthonormalized();
  7. }

Basis rotated(axis: Vector3, angle: float) const 🔗

返回围绕给定 axis 旋转 angle(单位为弧度)的基。axis 必须是归一化的向量(请参阅 Vector3.normalized)。

正值绕该轴顺时针旋转该基,而负值则逆时针旋转该基。

GDScriptC#

  1. var my_basis = Basis.IDENTITY
  2. var angle = TAU / 2
  3. my_basis = my_basis.rotated(Vector3.UP, angle) # 绕向上轴旋转(偏航)。
  4. my_basis = my_basis.rotated(Vector3.RIGHT, angle) # 绕向右轴旋转(俯仰)。
  5. my_basis = my_basis.rotated(Vector3.BACK, angle) # 绕向后轴旋转(滚动)。
  1. var myBasis = Basis.Identity;
  2. var angle = Mathf.Tau / 2.0f;
  3. myBasis = myBasis.Rotated(Vector3.Up, angle); // 绕向上轴旋转(偏航)。
  4. myBasis = myBasis.Rotated(Vector3.Right, angle); // 绕向右轴旋转(俯仰)。
  5. myBasis = myBasis.Rotated(Vector3.Back, angle); // 绕向后轴旋转(滚动)。

Basis scaled(scale: Vector3) const 🔗

返回该基,其中每个轴的分量都按给定的 scale 的分量缩放。

该基矩阵的行乘以 scale 的分量。该操作是全局缩放(相对于父级)。

GDScriptC#

  1. var my_basis = Basis(
  2. Vector3(1, 1, 1),
  3. Vector3(2, 2, 2),
  4. Vector3(3, 3, 3)
  5. )
  6. my_basis = my_basis.scaled(Vector3(0, 2, -2))
  7. print(my_basis.x) # 输出 (0, 2, -2).
  8. print(my_basis.y) # 输出 (0, 4, -4).
  9. print(my_basis.z) # 输出 (0, 6, -6).
  1. var myBasis = new Basis(
  2. new Vector3(1.0f, 1.0f, 1.0f),
  3. new Vector3(2.0f, 2.0f, 2.0f),
  4. new Vector3(3.0f, 3.0f, 3.0f)
  5. );
  6. myBasis = myBasis.Scaled(new Vector3(0.0f, 2.0f, -2.0f));
  7. GD.Print(myBasis.X); // 输出 (0, 2, -2).
  8. GD.Print(myBasis.Y); // 输出 (0, 4, -4).
  9. GD.Print(myBasis.Z); // 输出 (0, 6, -6).

Basis slerp(to: Basis, weight: float) const 🔗

使用 to 基在给定 weight 的情况下执行球面线性插值。该基和 to 两者都应该代表一个旋转。

示例:使用 Tween 随时间平滑地将 Node3D 旋转到目标基。

  1. var start_basis = Basis.IDENTITY
  2. var target_basis = Basis.IDENTITY.rotated(Vector3.UP, TAU / 2)
  3. func _ready():
  4. create_tween().tween_method(interpolate, 0.0, 1.0, 5.0).set_trans(Tween.TRANS_EXPO)
  5. func interpolate(weight):
  6. basis = start_basis.slerp(target_basis, weight)

float tdotx(with: Vector3) const 🔗

返回 withx 轴之间的转置点积(请参阅 transposed)。

这相当于 basis.x.dot(vector)


float tdoty(with: Vector3) const 🔗

返回 withy 轴之间的转置点积(请参阅 transposed)。

这相当于 basis.y.dot(vector)


float tdotz(with: Vector3) const 🔗

返回 withz 轴之间的转置点积(请参阅 transposed)。

这相当于 basis.z.dot(vector)


Basis transposed() const 🔗

返回该基的转置版本。这会将基矩阵的列转换为行,并将其行转换为列。

GDScriptC#

  1. var my_basis = Basis(
  2. Vector3(1, 2, 3),
  3. Vector3(4, 5, 6),
  4. Vector3(7, 8, 9)
  5. )
  6. my_basis = my_basis.transposed()
  7. print(my_basis.x) # 输出 (1, 4, 7).
  8. print(my_basis.y) # 输出 (2, 5, 8).
  9. print(my_basis.z) # 输出 (3, 6, 9).
  1. var myBasis = new Basis(
  2. new Vector3(1.0f, 2.0f, 3.0f),
  3. new Vector3(4.0f, 5.0f, 6.0f),
  4. new Vector3(7.0f, 8.0f, 9.0f)
  5. );
  6. myBasis = myBasis.Transposed();
  7. GD.Print(myBasis.X); // 输出 (1, 4, 7).
  8. GD.Print(myBasis.Y); // 输出 (2, 5, 8).
  9. GD.Print(myBasis.Z); // 输出 (3, 6, 9).

运算符说明

bool operator !=(right: Basis) 🔗

如果两个 Basis 矩阵的分量不相等,则返回 true

注意:由于浮点精度误差,请考虑改用 is_equal_approx,这样更可靠。


Basis operator *(right: Basis) 🔗

由该基转换(乘以) right 基。

这是父级和子级 Node3D 之间执行的操作。


Vector3 operator *(right: Vector3) 🔗

由该基变换(乘以)right 向量,返回一个 Vector3

GDScriptC#

  1. # 交换 X/Z 轴并使缩放加倍的基。
  2. var my_basis = Basis(Vector3(0, 2, 0), Vector3(2, 0, 0), Vector3(0, 0, 2))
  3. print(my_basis * Vector3(1, 2, 3)) # 输出 (4, 2, 6)
  1. // 交换 X/Z 轴并使缩放加倍的基。
  2. var myBasis = new Basis(new Vector3(0, 2, 0), new Vector3(2, 0, 0), new Vector3(0, 0, 2));
  3. GD.Print(myBasis * new Vector3(1, 2, 3)); // 输出 (4, 2, 6)

Basis operator *(right: float) 🔗

Basis 的所有分量乘以给定的 float。这会均匀地影响该基矩阵的缩放,并通过 right 值调整所有 3 个轴的大小。


Basis operator *(right: int) 🔗

将该 Basis 的所有分量乘以给定的 int。这会均匀地影响该基的缩放,并通过 right 值调整所有 3 个轴的大小。


Basis operator /(right: float) 🔗

Basis 的所有分量除以给定的 float。这会均匀地影响该基的缩放,并通过 right 值调整所有 3 个轴的大小。


Basis operator /(right: int) 🔗

Basis 的所有分量除以给定的 int。这会均匀地影响该基的缩放,并通过 right 值调整所有 3 个轴的大小。


bool operator ==(right: Basis) 🔗

如果两个 Basis 矩阵的分量完全相等,则返回 true

注意:由于浮点精度误差,请考虑改用 is_equal_approx,这样更可靠。


Vector3 operator [](index: int) 🔗

通过索引访问该基的每个轴(列)。索引 0x 相同,索引 1y 相同,索引 2z 相同。

注意:在 C++ 中,该运算符访问基础矩阵的行,而是列。对于与脚本语言相同的行为,请使用 set_columnget_column 方法。