Basis

Матрица 3×3 для представления трехмерного вращения и масштаба.

Описание

Встроенный тип Variant Basis — это матрица размером 3×3, используемая для представления вращения, масштаба и сдвига в 3D. Она часто используется в Transform3D.

Basis состоит из 3 векторов осей, каждый из которых представляет столбец матрицы: x, y и z. Длина каждой оси (Vector3.length()) влияет на масштаб базиса, а направление всех осей влияет на вращение. Обычно эти оси перпендикулярны друг другу. Однако при повороте любой оси по отдельности базис становится сдвинутым. Применение сдвинутого базиса к 3D-модели приведет к тому, что модель будет выглядеть искаженной.

Basis— это:

  • Ортогональный, если его оси перпендикулярны друг другу.

  • Нормализовано, если длина каждой оси равна 1.0.

  • Равномерно, если все оси имеют одинаковую длину (см. get_scale()).

  • Ортонормальный, если он одновременно ортогонален и нормализован, что позволяет ему представлять только вращения (см. orthonormalized()).

  • Конформный, если он одновременно ортогонален и однороден, что гарантирует отсутствие искажений.

Для общего введения см. учебник Матрицы и преобразования.

Примечание: Godot использует правостороннюю систему координат, что является общепринятым стандартом. Для направлений соглашение для встроенных типов, таких как Camera3D, заключается в том, что -Z указывает вперед (+X — направо, +Y — вверх, а +Z — назад). Другие объекты могут использовать другие соглашения о направлении. Для получения дополнительной информации см. Соглашения о направлении 3D-активов учебник.

Примечание: Базисные матрицы представлены в порядке column-major, что совпадает с порядком OpenGL. Однако внутри они хранятся в порядке row-major, что совпадает с порядком DirectX.

Примечание

Существуют заметные различия при использовании данного API с C#. Подробнее см. API различия C# и 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

scaled_local(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) 🔗

Тождество Basis. Это ортонормальный базис без вращения, без сдвига и масштабом Vector3.ONE. Это также означает, что:

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])
# Выводит:
# | X | Y | Z
# | 1 | 0 | 0
# | 0 | 1 | 0
# | 0 | 0 | 1

Если Vector3 или другой Basis преобразуется (умножается) на эту константу, то преобразование не происходит.

Примечание: В GDScript эта константа эквивалентна созданию Basis без каких-либо аргументов. Ее можно использовать для того, чтобы сделать ваш код более понятным и для согласованности с C#.

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

Когда любой базис умножается на FLIP_X, он инвертирует все компоненты оси x (столбец X).

Когда FLIP_X умножается на любой базис, он инвертирует компонент Vector3.x всех осей (строка X).

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

Когда любой базис умножается на FLIP_Y, он инвертирует все компоненты оси y (столбец Y).

Когда FLIP_Y умножается на любой базис, он инвертирует компонент Vector3.y всех осей (строка Y).

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

Когда любой базис умножается на FLIP_Z, он инвертирует все компоненты оси z (столбец Z).

Когда FLIP_Z умножается на любой базис, он инвертирует компонент Vector3.z всех осей (строка 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() 🔗

Создает Basis, идентичный IDENTITY.

Примечание: В C# это создает Basis, все компоненты которого установлены в Vector3.ZERO.


Basis Basis(from: Basis)

Создает Basis как копию заданного Basis.


Basis Basis(axis: Vector3, angle: float)

Создает Basis, который представляет только вращение, повернутое вокруг axis на заданный angle в радианах. Ось должна быть нормализованным вектором.

Примечание: Это то же самое, что использовать rotated() на IDENTITY основе. При наличии более одного угла рассмотрите возможность использования from_euler() вместо этого.


Basis Basis(from: Quaternion)

Создает Basis, который представляет только вращение из заданного Quaternion.

Примечание: Кватернионы только хранят вращение, а не масштаб. Из-за этого преобразования из Basis в Quaternion не всегда могут быть обратными.


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

Создает Basis из 3-х векторов осей. Это столбцы матрицы базиса.


Описания метода

float determinant() const 🔗

Возвращает https://en.wikipedia.org/wiki/Определитель матрицы этого базиса. В высшей математике это число можно использовать для определения нескольких атрибутов:

  • Если определитель равен точно 0.0, базис необратим (см. inverse()).

  • Если определитель — отрицательное число, базис представляет собой отрицательный масштаб.

Примечание: Если масштаб базиса одинаков для всех осей, его определитель всегда равен этому масштабу в степени 3.


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

Создает новый Basis, который представляет только вращение из заданного Vector3 углов Эйлера в радианах.

  • Vector3.x должен содержать угол вокруг оси x (тангаж);

  • Vector3.y должен содержать угол вокруг оси y (рыскание);

  • Vector3.z должен содержать угол вокруг оси z (крен).

# Создает базис, ось z которого направлена вниз.
var my_basis = Basis.from_euler(Vector3(TAU / 4, 0, 0))

print(my_basis.z) # Выводит (0.0, -1.0, 0.0)

Порядок каждого последовательного вращения можно изменить с помощью order (см. константы EulerOrder). По умолчанию используется соглашение YXZ (@GlobalScope.EULER_ORDER_YXZ): базис сначала вращается вокруг оси Y (рыскание), затем вокруг оси X (тангаж) и, наконец, вокруг оси Z (крен). При использовании противоположного метода get_euler() этот порядок меняется на обратный.


Basis from_scale(scale: Vector3) static 🔗

Создает новый Basis, который представляет только масштаб, без вращения или сдвига, из заданного вектора scale.

var my_basis = Basis.from_scale(Vector3(2, 4, 8))

print(my_basis.x) # Выводит (2.0, 0.0, 0.0)
print(my_basis.y) # Выводит (0.0, 4.0, 0.0)
print(my_basis.z) # Выводит (0.0, 0.0, 8.0)

Примечание: В линейной алгебре матрица этого базиса также известна как диагональная матрица.


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() этот порядок меняется на обратный.

Примечание: Чтобы этот метод возвращал правильный результат, базис должен быть ортонормальным (см. orthonormalized()).

Примечание: Углы Эйлера гораздо более интуитивны, но не подходят для 3D-математики. Из-за этого рассмотрите возможность использования метода get_rotation_quaternion(), который возвращает Quaternion.

Примечание: В доке Inspector вращение базиса часто отображается в углах Эйлера (в градусах), как в случае со свойством Node3D.rotation.


Quaternion get_rotation_quaternion() const 🔗

Возвращает вращение этого базиса как Quaternion.

Примечание: Кватернионы гораздо больше подходят для 3D-математики, но менее интуитивно понятны. Для пользовательских интерфейсов рассмотрите возможность использования метода get_euler(), который возвращает углы Эйлера.


Vector3 get_scale() const 🔗

Возвращает длину каждой оси этого базиса как 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()) # Выводит (2.0, 4.0, 8.0)

Примечание: Если значение, возвращаемое determinant(), отрицательное, масштаб также будет отрицательным.


Basis inverse() const 🔗

Возвращает обратную матрицу данного базиса.


bool is_conformal() const 🔗

Возвращает true, если этот базис конформный. Конформный базис является как ортогональным (оси перпендикулярны друг другу), так и равномерным (оси имеют одинаковую длину). Этот метод может быть особенно полезен при физических расчетах.


bool is_equal_approx(b: Basis) const 🔗

Возвращает true, если этот базис и b приблизительно равны, вызывая @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_front равно true, ось +Z (ассет спереди) рассматривается как прямая (подразумевается, что +X находится слева) и указывает на позицию target.

Верхняя ось (+Y) указывает как можно ближе к вектору up, оставаясь перпендикулярной прямой оси. Возвращаемый базис ортонормализован (см. orthonormalized()).

target и up не могут быть Vector3.ZERO и не должны быть коллинеарными, чтобы избежать непреднамеренного поворота вокруг локальной оси Z.


Basis orthonormalized() const 🔗

Возвращает ортонормированную версию этого базиса. Ортонормированный базис является как ортогональным (оси перпендикулярны друг другу), так и нормализованным (оси имеют длину 1.0), что также означает, что он может представлять только поворот.

Часто бывает полезно вызывать этот метод, чтобы избежать ошибок округления на основе поворота:

# Вращайте этот Node3D каждый кадр.
func _process(delta):
    basis = basis.rotated(Vector3.UP, TAU * delta)
    basis = basis.rotated(Vector3.RIGHT, TAU * delta)
    basis = basis.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)    # Вращение вокруг вертикальной оси (рыскание).
my_basis = my_basis.rotated(Vector3.RIGHT, angle) # Вращение вокруг правой оси (тангаж).
my_basis = my_basis.rotated(Vector3.BACK, angle)  # Вращение вокруг задней оси (крен).

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) # Выводит (0.0, 2.0, -2.0)
print(my_basis.y) # Выводит (0.0, 4.0, -4.0)
print(my_basis.z) # Выводит (0.0, 6.0, -6.0)

Basis scaled_local(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_local(Vector3(0, 2, -2))

print(my_basis.x) # Выводит (0.0, 0.0, 0.0)
print(my_basis.y) # Выводит (4.0, 4.0, 4.0)
print(my_basis.z) # Выводит (-6.0, -6.0, -6.0)

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

Выполняет сферически-линейную интерполяцию с базисом to, заданным weight. И этот базис, и to должны представлять поворот.

Пример: Плавно повернуть Node3D к целевому базису с течением времени с 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(vector).


float tdoty(with: Vector3) const 🔗

Возвращает транспонированное скалярное произведение между with и осью y (см. transposed()).

Это эквивалентно basis.y.dot(vector).


float tdotz(with: Vector3) const 🔗

Возвращает транспонированное скалярное произведение между with и осью z (см. transposed()).

Это эквивалентно basis.z.dot(vector).


Basis transposed() const 🔗

Возвращает транспонированную версию этого базиса. Это превращает столбцы матрицы базиса в строки, а ее строки в столбцы.

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) # Выводит (1.0, 4.0, 7.0)
print(my_basis.y) # Выводит (2.0, 5.0, 8.0)
print(my_basis.z) # Выводит (3.0, 6.0, 9.0)

Описания оператора

bool operator !=(right: Basis) 🔗

Возвращает true, если компоненты обеих матриц Basis не равны.

Примечание: Из-за ошибок точности с плавающей точкой рассмотрите возможность использования is_equal_approx(), который более надежен.


Basis operator *(right: Basis) 🔗

Преобразует (умножает) базис right на этот базис.

Это операция, выполняемая между родительским и дочерним Node3D.


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)) # Выводит (4.0, 2.0, 6.0)

Basis operator *(right: float) 🔗

Умножает все компоненты Basis на заданный float. Это влияет на масштаб базиса равномерно, изменяя размер всех 3 осей на значение right.


Basis operator *(right: int) 🔗

Умножает все компоненты Basis на заданное int. Это влияет на масштаб базиса равномерно, изменяя размер всех 3 осей на значение right.


Basis operator /(right: float) 🔗

Делит все компоненты Basis на заданный float. Это влияет на масштаб базиса равномерно, изменяя размер всех 3 осей на значение right.


Basis operator /(right: int) 🔗

Делит все компоненты Basis на заданное int. Это влияет на масштаб базиса равномерно, изменяя размер всех 3 осей на значение right.


bool operator ==(right: Basis) 🔗

Возвращает true, если компоненты обеих матриц Basis в точности равны.

Примечание: Из-за ошибок точности с плавающей точкой рассмотрите возможность использования is_equal_approx(), который более надежен.


Vector3 operator [](index: int) 🔗

Доступ к каждой оси (столбцу) этого базиса по их индексу. Индекс 0 такой же, как x, индекс 1 такой же, как y, а индекс 2 такой же, как z.

Примечание: В C++ этот оператор обращается к строкам матрицы базиса, не к столбцам. Для того же поведения, что и в языках сценариев, используйте методы set_column и get_column .