Матрицы в Cinema 4D

Матрица — это тип для представления линейных преобразований в Cinema 4D. Матрица состоит из четырех компонентов:

  • v1 — ось X или базисный вектор i кадра линейного преобразования, определенного экземпляром Matrix.

  • v2 — ось Y или базисный вектор j кадра линейного преобразования, определенного экземпляром Matrix.

  • v3 — ось z или базисный вектор k кадра линейного преобразования, определенного экземпляром Matrix.

  • off — дополнительный компонент перемещения.

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

# Matrix(v1: (1, 0, 0); v2: (0, 1, 0); v3: (0, 0, 1); off: (0, 0, 0))
defaultMatrix = c4d.Matrix() # без параметров создаст дефолтную матрицу

# создаст стандартну матрицу повернутую на 90 градусов против часовой стрелки по оси Z
m = c4d.Matrix(v1=c4d.Vector( 0, 1, 0),
               v2=c4d.Vector(-1, 0, 0),
               v3=c4d.Vector( 0, 0, 1))

Матрицы достаточно, чтобы хранить все три важных свойства объекта: положение, вращение и масштаб. (Положение хранится в первом векторе, вращение определяется направлением трех осевых векторов, а масштаб определяется их длиной.) Поэтому каждый объект имеет матрицу, которую вы можете получить с помощью BaseObject.GetMl().

Чтобы понять как набор из трех векторов (v1, v2, v3) определяет вращение и масштаб объектов сцены - нужно представить что к каждому объекту прикреплены три единичных вектора (взаимно перпендикулярных). Каждый из этих векторов имеет проекцию на оси X,Y и Z, поэтому имеем набор из 3x3 = 9 чисел. Изначально, каждый из трех векторов параллелен одной из осей и имеет максимальное значение проекции на эту ось равное 1, и две проекции на другие оси со значениями 0. Имеем:

_____ X__Y__Z
X v1: 1, 0, 0
Y v2: 0, 1, 0
Z v3: 0, 0, 1

Если мы начнем вращать объект вокруг оси Z то увидим как меняются проекции векторов v1 и v2 на оси X и Y


После поворота, на последнем кадре будет:

_________ X_____Y____Z
X v1:  0.759, 0.652, 0
Y v2: -0.652, 0.759, 0
Z v3:  0,     0,     1

Чтобы сравнить два объекта в разных иерархиях, нам нужен способ получить их глобальные координаты. Здесь на помощь приходит умножение матриц. Умножение двух матриц — это не просто умножение соответствующих чисел; это гораздо сложнее. Фактически, умножение матриц даже не коммутативно: a*b — это не то же самое, что b*a . К счастью, для этого не обязательно знать, как умножать две матрицы.

Если матрица Mp является матрицей родительского элемента, а Mc — матрицей дочернего элемента, то произведение Mp*Mc дает матрицу, которая представляет положение и вращение дочернего элемента, но в системе координат родительского элемента. Это означает, что получение глобальной матрицы дочернего элемента — это всего лишь вопрос умножения ее на каждую из матриц его родителей.

К счастью, нам не придется делать это умножение самостоятельно. Каждый объект имеет следующие предопределенные функции:

GetMl()      # Возвращает матрицу в локальных координатах
GetMg()      # Возвращает матрицу в глобальных координатах
GetUpMg()    # Возвращает родительскую матрицу в глобальных координатах

Например, если у вас есть объект с именем «MyObject», спрятанный глубоко в иерархии объектов, следующий код напечатает его глобальную позицию:

obj = doc.SearchObject("MyObject")
mat = obj.GetMg()        # глобальная матрица
globalPos = mat.off      # получаем позицию из матрицы
print ("Global pos= ", globalPos)

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

p1 = op1.GetMg().off
p2 = op2.GetMg().off
dist = (p2-p1).GetLength()

Если вы хотите написать плагин средней точки, безопасный для иерархии, вы можете сделать следующее:

p1 = op1.GetMg().off # глобальная позиция 1-го объекта
p2 = op2.GetMg().off # глобальная позиция 2-го объекта

mid = (p1 + p2) / 2.0 # средняя точка

m = obj.GetMg() # Глобальная матрица объекта, который нужно поместить между
m.off = mid # установим ему положение средней точки

obj.SetMg(m) # установим глобальную матрицу

Last updated