Matrix3 и Matrix4: умножение, инверсия, транспонирование

В библиотеке Three.js для работы с преобразованиями в 3D-пространстве используются объекты Matrix3 и Matrix4. Они обеспечивают возможность представления, комбинирования и применения линейных преобразований, включая повороты, масштабирование, перенос и перспективные преобразования. Основное отличие заключается в размерности: Matrix3 — 3×3, обычно используется для нормалей и двумерных преобразований, Matrix4 — 4×4, применяются для 3D-трансформаций с переносом.


Создание и инициализация матриц

Matrix3 создаётся стандартно через конструктор:

const m3 = new THREE.Matrix3();

По умолчанию создаётся единичная матрица. Для явной установки значений можно использовать метод set:

m3.set(
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
);

Для Matrix4 подход аналогичный:

const m4 = new THREE.Matrix4();
m4.set(
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
);

Единичная матрица создаётся по умолчанию и может быть восстановлена через identity():

m4.identity();

Умножение матриц

Умножение матриц позволяет комбинировать преобразования. В Three.js существуют методы multiply и premultiply:

const a = new THREE.Matrix4().makeRotationX(Math.PI / 4);
const b = new THREE.Matrix4().makeTranslation(10, 0, 0);

const result = new THREE.Matrix4();
result.multiplyMatrices(a, b); // result = a * b

multiply применяется справа: this = this * m. premultiply — слева: this = m * this.

Для Matrix3 синтаксис аналогичен:

const m1 = new THREE.Matrix3().set(
    1, 2, 3,
    0, 1, 4,
    5, 6, 0
);

const m2 = new THREE.Matrix3().set(
    -1, 2, 0,
     0, 1, 3,
     4, 0, 1
);

m1.multiply(m2); // m1 = m1 * m2

Важно учитывать порядок умножения: в 3D-преобразованиях порядок матриц критически влияет на результат.


Инверсия матриц

Инверсия позволяет «отменить» преобразование. Для Matrix3 используется метод invert():

const m3 = new THREE.Matrix3().set(
    2, 0, 1,
    1, 1, 0,
    0, 0, 1
);

const m3Inverse = new THREE.Matrix3();
m3Inverse.copy(m3).invert();

Для Matrix4 также используется invert():

const m4 = new THREE.Matrix4().makeRotationY(Math.PI / 2);
const m4Inverse = new THREE.Matrix4();
m4Inverse.copy(m4).invert();

При инверсии важно проверять, что матрица невырожденная. Если определитель равен нулю, метод возвращает null или выбрасывает предупреждение.


Транспонирование

Транспонирование меняет строки и столбцы матрицы местами. В Three.js выполняется через transpose():

const m3 = new THREE.Matrix3().set(
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
);

m3.transpose();

Для Matrix4 принцип аналогичный:

const m4 = new THREE.Matrix4().set(
    1, 0, 0, 0,
    0, 1, 2, 0,
    0, 3, 4, 0,
    0, 0, 0, 1
);

m4.transpose();

Транспонирование особенно полезно при работе с нормалями: при применении нелинейного масштабирования к объекту нормали преобразуются с помощью транспонированной обратной матрицы.


Применение матриц к векторам

Matrix3 применяется к Vector3 для нормалей и 3D-векторов без переноса:

const normal = new THREE.Vector3(1, 0, 0);
normal.applyMatrix3(m3);

Matrix4 учитывает перенос и полное 3D-преобразование:

const position = new THREE.Vector3(1, 2, 3);
position.applyMatrix4(m4);

Для комбинированных трансформаций матрица объекта сцены обычно строится через методы makeRotationX, makeTranslation, makeScale и умножается друг на друга для получения итоговой матрицы объекта.


Оптимизация и особенности

  • Matrix3 часто используется для вычисления нормалей (normalMatrix), чтобы ускорить расчёты освещения.
  • Matrix4 применяется для всех видовых, мировых и проекционных преобразований.
  • Методы setFromMatrix4() позволяют извлекать 3×3 матрицу из 4×4 для нормалей:
const normalMatrix = new THREE.Matrix3();
normalMatrix.setFromMatrix4(m4);
  • Множество методов Three.js поддерживает цепочку вызовов, что упрощает построение сложных преобразований:
const m = new THREE.Matrix4()
    .makeRotationX(Math.PI / 2)
    .multiply(new THREE.Matrix4().makeTranslation(5, 0, 0))
    .scale(new THREE.Vector3(2, 2, 2));

Практическое использование

  1. Комбинирование трансформаций объектов — умножение матриц для получения итогового положения.
  2. Обработка нормалей для освещенияMatrix3 с транспонированием и инверсией.
  3. Обратные преобразования — инверсия матрицы для перевода координат из мировых в локальные.
  4. Анимации и физика — обновление матриц объектов в реальном времени.

Three.js обеспечивает полное управление матрицами через удобные методы для создания, умножения, инверсии и транспонирования, что позволяет эффективно работать с любыми линейными и аффинными преобразованиями в 3D-пространстве.