Basis¶
用于表示3D旋转和缩放的3×3矩阵。
描述¶
Basis内置的Variant类型是一个3×3矩阵,用于表示3D旋转、缩放和剪切。它经常在Transform3D中使用。
Basis由3个轴向量组成,每个轴向量代表矩阵的一列:x、y和z。每个轴的长度(Vector3.length())影响基础的比例,而所有轴的方向影响旋转。通常,这些轴相互垂直。但是,当您单独旋转任何轴时,基础会被剪切。将剪切的基础应用于3D模型会使模型看起来扭曲。
Basis是:
-正交如果它的轴彼此垂直。
-如果每个轴的长度为``1.0``,则归一化。
-Uniform如果所有轴共享相同的长度(参见get_scale())。
-Orthonormal如果它既是正交的又是归一化的,这允许它只表示旋转(参见orthonormalized())。
-共形如果它既正交又均匀,这确保它不会被扭曲。
属性¶
构造函数¶
方法¶
determinant() const |
|
from_euler(euler: Vector3, order: int = 2) static |
|
from_scale(scale: Vector3) static |
|
get_rotation_quaternion() const |
|
get_scale() const |
|
inverse() const |
|
is_conformal() const |
|
is_equal_approx(b: Basis) const |
|
is_finite() const |
|
looking_at(target: Vector3, up: Vector3 = Vector3(0, 1, 0), use_model_front: bool = false) static |
|
orthonormalized() const |
|
transposed() const |
运算符¶
operator !=(right: Basis) |
|
operator *(right: Basis) |
|
operator *(right: Vector3) |
|
operator *(right: float) |
|
operator *(right: int) |
|
operator /(right: float) |
|
operator /(right: int) |
|
operator ==(right: Basis) |
|
operator [](index: int) |
常量¶
IDENTITY = Basis(1, 0, 0, 0, 1, 0, 0, 0, 1) 🔗
Identity Basis。这是一个正交基,没有旋转,没有剪切,缩放比例为Vector3.ONE。这也意味着:
x指向右侧(Vector3.RIGHT);
y指向上方(Vector3.UP);
z指向后方(Vector3.BACK)。
var basis = Basis.IDENTITY
print("| X | Y | Z")
print("| %.f | %.f | %.f" % [basis.x.x, basis.y.x, basis.z.x])
print("| %.f | %.f | %.f" % [basis.x.y, basis.y.y, basis.z.y])
print("| %.f | %.f | %.f" % [basis.x.z, basis.y.z, basis.z.z])
# Prints:
# | X | Y | Z
# | 1 | 0 | 0
# | 0 | 1 | 0
# | 0 | 0 | 1
如果一个Vector3或另一个Basis被这个常数变换(被乘),则不会发生任何变换。
注意:在S3Script中,这个常数相当于创建一个没有参数的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) 🔗
属性说明¶
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)。
构造函数说明¶
构造一个与IDENTITY相同的Basis。
注意:在C#中,这构造了一个Basis,其所有组件都设置为Vector3.ZERO。
构造一个Basis作为给定Basis的副本。
Basis Basis(axis: Vector3, angle: float)
构造一个仅表示围绕axis旋转给定angle的弧度的Basis。轴必须是归一化向量。
注意:这与在IDENTITY的基础上使用rotated()相同。如果角度超过一个,请考虑使用from_euler()。
Basis Basis(from: Quaternion)
构造一个仅表示从给定的Quaternion旋转的Basis。
注意:四元数仅存储旋转,而不是比例。因此,从Basis到Quaternion的转换不能总是颠倒。
Basis Basis(x_axis: Vector3, y_axis: Vector3, z_axis: Vector3)
从3个轴向量构造一个Basis。这些是基矩阵的列。
方法说明¶
返回此基础矩阵的行列式。对于高级数学,此数字可用于确定一些属性:
-如果行列式恰好是0.0,则基不可反转(参见inverse())。
-如果行列式是负数,则基数代表负数。
注:如果每个轴的基的刻度相同,则其行列式始终是该刻度的2次方。
Basis from_euler(euler: Vector3, order: int = 2) static 🔗
构建一个新的Basis,该Basis仅代表从给定的Vector3的欧拉角旋转,以弧度为单位。
Basis from_scale(scale: Vector3) static 🔗
使用给定的scale向量构建一个新的Basis,该Basis只代表缩放,没有旋转或剪切。
var my_basis = Basis.from_scale(Vector3(2, 4, 8))
print(my_basis.x) # Prints (2.0, 0.0, 0.0)
print(my_basis.y) # Prints (0.0, 4.0, 0.0)
print(my_basis.z) # Prints (0.0, 0.0, 8.0)
var myBasis = Basis.FromScale(new Vector3(2.0f, 4.0f, 8.0f));
S3.Print(myBasis.X); // Prints (2, 0, 0)
S3.Print(myBasis.Y); // Prints (0, 4, 0)
S3.Print(myBasis.Z); // Prints (0, 0, 8)
注意: 在线性代数中,这种基的矩阵也被称为对角矩阵。
Vector3 get_euler(order: int = 2) const 🔗
以欧拉角的Vector3形式返回此基的旋转,以弧度为单位。对于返回值:
每个连续旋转的顺序可以随order而改变(参见EulerOrder常量)默认情况下,使用YXZ约定(@GlobalScope.EULER_ORDER_YXZ):首先计算Z(滚动),然后计算X(俯仰),最后计算Y(偏航)。当使用相反的方法from_euler()时,此顺序颠倒。
注意:要使此方法正确返回,基需要是正交(参见orthonormalized())。
注意:欧拉角要直观得多,但不适合3D数学。因此,考虑使用get_rotation_quaternion()方法来代替,它返回一个Quaternion。
注意:在检查器停靠区中,基准的旋转通常以欧拉角(以度为单位)显示,就像Item3D.rotation属性一样。
Quaternion get_rotation_quaternion() const 🔗
将此基数的旋转作为Quaternion返回。
注意:四元数更适合3D数学,但不太直观对于用户界面,考虑使用返回欧拉角的get_euler()方法。
返回此基矢量每个轴的长度,作为一个Vector3。如果基矢量没有被剪切,这个值就是缩放因子。它不受旋转的影响。
var my_basis = Basis(
Vector3(2, 0, 0),
Vector3(0, 4, 0),
Vector3(0, 0, 8)
)
# 无论以何种方式旋转基(向量),其尺度都保持不变.
my_basis = my_basis.rotated(Vector3.UP, TAU / 2)
my_basis = my_basis.rotated(Vector3.RIGHT, TAU / 4)
print(my_basis.get_scale()) # Prints (2.0, 4.0, 8.0)
var myBasis = new Basis(
Vector3(2.0f, 0.0f, 0.0f),
Vector3(0.0f, 4.0f, 0.0f),
Vector3(0.0f, 0.0f, 8.0f)
);
// 无论以何种方式旋转基(向量),其尺度都保持不变.
myBasis = myBasis.Rotated(Vector3.Up, Mathf.Tau / 2.0f);
myBasis = myBasis.Rotated(Vector3.Right, Mathf.Tau / 4.0f);
S3.Print(myBasis.Scale); // Prints (2, 4, 8)
注意:如果determinant()返回的值为负数,那么比例也为负数。
返回这个基矩阵的逆。
如果此基是共形的,则返回true。共形基既是正交(轴相互垂直)又是均匀(轴共享相同的长度)。这种方法在物理计算中特别有用。
bool is_equal_approx(b: Basis) const 🔗
如果这个基和b近似相等,则返回true,方法是在所有向量组件上调用@GlobalScope.is_equal_approx()。
如果这个基础是有限的,则返回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_front是true,则+Z轴(资产前端)被视为前进(暗示+X是左)并指向target位置。
向上轴(+Y)指向尽可能靠近up向量,同时保持垂直于向前轴。返回的基是正则化的(参见orthonormalized())。
target和up不能是Vector3.ZERO,并且不应该是共线的,以避免围绕局部Z轴意外旋转。
Basis orthonormalized() const 🔗
返回此基的正交化版本。正交基既正交(各轴相互垂直)又归一化(各轴长度为1.0),这也意味着它只能表示旋转。
通常,调用此方法可以避免旋转基上的舍入误差:
# 每帧都旋转这个 Item3D.
func _process(delta):
basis = basis.rotated(Vector3.UP, TAU * delta)
basis = basis.rotated(Vector3.RIGHT, TAU * delta)
basis = basis.orthonormalized()
// 每帧都旋转这个 Item3D.
public override void _Process(double delta)
{
Basis = Basis.Rotated(Vector3.Up, Mathf.Tau * (float)delta)
.Rotated(Vector3.Right, Mathf.Tau * (float)delta)
.Orthonormalized();
}
Basis rotated(axis: Vector3, angle: float) const 🔗
返回此基绕给定axis旋转给定angle(以弧度为单位)的副本。
axis必须是归一化向量(参见Vector3.normalized())。如果angle为正,则基绕轴逆时针旋转。
var my_basis = Basis.IDENTITY
var angle = TAU / 2
my_basis = my_basis.rotated(Vector3.UP, angle) # Rotate around the up axis (yaw).
my_basis = my_basis.rotated(Vector3.RIGHT, angle) # Rotate around the right axis (pitch).
my_basis = my_basis.rotated(Vector3.BACK, angle) # Rotate around the back axis (roll).
var myBasis = Basis.Identity;
var angle = Mathf.Tau / 2.0f;
myBasis = myBasis.Rotated(Vector3.Up, angle); // Rotate around the up axis (yaw).
myBasis = myBasis.Rotated(Vector3.Right, angle); // Rotate around the right axis (pitch).
myBasis = myBasis.Rotated(Vector3.Back, angle); // Rotate around the back axis (roll).
Basis scaled(scale: Vector3) const 🔗
返回此基,每个轴的分量由给定的scale的分量缩放。
基矩阵的行乘以scale的分量。此操作是全局缩放(相对于父级)。
var my_basis = Basis(
Vector3(1, 1, 1),
Vector3(2, 2, 2),
Vector3(3, 3, 3)
)
my_basis = my_basis.scaled(Vector3(0, 2, -2))
print(my_basis.x) # Prints (0.0, 2.0, -2.0)
print(my_basis.y) # Prints (0.0, 4.0, -4.0)
print(my_basis.z) # Prints (0.0, 6.0, -6.0)
var myBasis = new Basis(
new Vector3(1.0f, 1.0f, 1.0f),
new Vector3(2.0f, 2.0f, 2.0f),
new Vector3(3.0f, 3.0f, 3.0f)
);
myBasis = myBasis.Scaled(new Vector3(0.0f, 2.0f, -2.0f));
S3.Print(myBasis.X); // Prints (0, 2, -2)
S3.Print(myBasis.Y); // Prints (0, 4, -4)
S3.Print(myBasis.Z); // Prints (0, 6, -6)
Basis slerp(to: Basis, weight: float) const 🔗
在给定weight的情况下,使用to基执行球面线性插值。此基和to都应表示旋转。
示例:随着时间的推移平滑地将Item3D旋转到目标基,使用Tween:
var start_basis = Basis.IDENTITY
var target_basis = Basis.IDENTITY.rotated(Vector3.UP, TAU / 2)
func _ready():
create_tween().tween_method(interpolate, 0.0, 1.0, 5.0).set_trans(Tween.TRANS_EXPO)
func interpolate(weight):
basis = start_basis.slerp(target_basis, weight)
float tdotx(with: Vector3) const 🔗
返回with和x轴之间的转置点积(参见transposed())。
这相当于basis.x.dot(向量)。
float tdoty(with: Vector3) const 🔗
返回with和y轴之间的转置点积(参见transposed())。
这相当于basis.y.dot(向量)。
float tdotz(with: Vector3) const 🔗
返回with和z轴之间的转置点积(参见transposed())。
这相当于basis.z.dot(向量)。
返回这个基的转置版本。这将基矩阵的列转换为行,行转换为列。
var my_basis = Basis(
Vector3(1, 2, 3),
Vector3(4, 5, 6),
Vector3(7, 8, 9)
)
my_basis = my_basis.transposed()
print(my_basis.x) # Prints (1.0, 4.0, 7.0)
print(my_basis.y) # Prints (2.0, 5.0, 8.0)
print(my_basis.z) # Prints (3.0, 6.0, 9.0)
var myBasis = new Basis(
new Vector3(1.0f, 2.0f, 3.0f),
new Vector3(4.0f, 5.0f, 6.0f),
new Vector3(7.0f, 8.0f, 9.0f)
);
myBasis = myBasis.Transposed();
S3.Print(myBasis.X); // Prints (1, 4, 7)
S3.Print(myBasis.Y); // Prints (2, 5, 8)
S3.Print(myBasis.Z); // Prints (3, 6, 9)
运算符说明¶
bool operator !=(right: Basis) 🔗
如果两个Basis矩阵的分量不相等,则返回true。
注:由于浮点精度误差,考虑改用is_equal_approx(),这样更可靠。
Basis operator *(right: Basis) 🔗
将right基转换(乘以)此基。
这是父级和子级Item3D之间执行的操作。
Vector3 operator *(right: Vector3) 🔗
将right向量与这个基变换(相乘),返回一个Vector3。
# 交换 X/Z 轴且将尺度加倍的基(向量).
var my_basis = Basis(Vector3(0, 2, 0), Vector3(2, 0, 0), Vector3(0, 0, 2))
print(my_basis * Vector3(1, 2, 3)) # Prints (4.0, 2.0, 6.0)
// 交换 X/Z 轴且将尺度加倍的基(向量).
var myBasis = new Basis(new Vector3(0, 2, 0), new Vector3(2, 0, 0), new Vector3(0, 0, 2));
S3.Print(myBasis * new Vector3(1, 2, 3)); // Prints (4, 2, 6)
Basis operator *(right: float) 🔗
将Basis的所有组件乘以给定的float。这会均匀地影响基础的比例,将所有3个轴的大小调整为right值。
Basis operator *(right: int) 🔗
将Basis的所有组件乘以给定的int。这会均匀地影响基础的比例,将所有3个轴的大小调整为right值。
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) 🔗
通过索引访问此基础的每个轴(列)。索引0与x相同,索引1与y相同,索引2与z相同。
注意:在C++中,此运算符访问基矩阵的行,而不是列。对于与脚本语言相同的行为,请使用set_column和get_column方法。