Математика
Работа с 3D-графикой
Разработка игр
Комментарии 41
-7
Прозвучало как «я не учил математику, не разобрался в кватернионах, поэтому изобрёл их заново».
Может, вообще стоило начать с тензоров и матриц? А кватернионы рассматривать уже как оптимизацию, позволяющую описывать только повороты и масштабирование?
+2
Мы ведь говорим о вращении объекта, какое еще масштабирование?
-1
Насчёт масштабирования — это меня переглючило, давно я в кватернионы игрался (20 лет прошло) и забыл, что там входит обратный кватернион, т.е. масштабирование не получить никак, из 4 «степеней свободы» одна теряется.
-1
Да нет, не подошли. 4 числа в кватернионе — _удобно_ и быстро. В матрице вон вообще 9 (если только вращение/отражение/масштабирование) или 12/16 (если сдвиги и проективное преобразование), однако она удобна и широко используется для представления поворотов.
А, к примеру, углы Эйлера — три числа, без избыточности, но неудобны.
0
Умножение кватерниона на кватернион с нулевой векторной частью дает масштабирование/сжатие
+1
Как я понял, посыл статьи в том, что кватернионы и формулы с ними вводятся без обоснований, и сложно понять почему они работают так, как работают. А если вооружиться школьной геометрией, то автор приходит к кватернионам с пониманием, откуда что берется. Его это знание успокаивает, а большинству практиков достаточно табличных формул для реализации всей геометрии поворотов. Мне лично матрицы поворота более понятны, их и использую. Но кватернионы некотрые задачи решают лучше.
+1
Мне лично матрицы поворота более понятны, их и использую.

Только интерполировать их всё равно нужно через кватернион.
0
Совсем не обязательно. Существуют прямые формулы вычисления экспоненты и логарифма для матриц поворота и они даже удобнее кватернионов т.к. там не возникает проблемы «двойного покрытия» (представимости большинства поворотов двумя разными кватернионами) из-за которой у кватернионов интерполяция может идти по длинной части дуги большого круга. Просто вычисляются они сложнее и дольше, ну и еще народ тупит и не знает про них :). Причем в отличие от кватернионов такие формулы для матриц можно вывести не только для поворотов но и для произвольных движений.
+1

То, что описано в статье, математики зовут «алгеброй Клиффорда». Она определяется следующим набором аксиом:


  • Aссоциативноcть: $$(AB)C = A(BC)$$
  • Дистрибутивность:
    $$A(B + C) = AB + AC \qquad (A + B)C = AC + BC$$
  • Умножение на число: $$(αA)B = A(αB) = α(AB)$$
  • Умножение на единицу: $$1A = A1 = A$$
  • Квардрат вектора: $$aa = a^2 \in \mathbb R$$

Может, вообще стоило начать с тензоров и матриц?

Не может. Алгебра Клиффорда намного более простой и удобный инструмент для подобных вещей.




У меня в черновиках есть статья об алгебре Клиффорда, вдохновлённая книгой «Geometric Algebra for Physicists». Надо бы её наконец дописать и выложить на хабр.

+1

Допишите, допишите.
А кватернионы — часом не частный случай алгебры Клиффорда?


Ну и насчёт удобства — по мне, так для представления поворотов следует разделять абстракцию (для меня это — тензор поворота) и реализацию (матрица, кватернион, ещё что) — чтобы о реализации думать, только когда оптимизируешь программу.

0
А кватернионы — часом не частный случай алгебры Клиффорда?

Именно так.

0
Статьи (не только здесь) начинаются часто с примера, как повернуть вектор на 90 градусов. habr.com/post/426863 Кажется, это ваша статья. Для себя совсем чуть-чуть (едва-едва) я прояснил, что происходит. Но волнует, конечно же, практическое применение и, как мне кажется, для понимания лучше объяснять в двумерном пространстве. Дело в том, что на практике (реальное программирование, я, конечно в основном про игры) поворачивать объект на 90 и даже 45 градусов можно вообще без кватернионов (по крайней мере для 2D плоскости) и матриц поворота, просто составив два массива. Использовать инкремент/декремент -влево/вправо. Не очень понятно и хотелось бы такой пример, когда поворот в 2D происходит, допустим, на 5 градусов, как это реализуется, как это объясняется. В этом случае же уже нет прост смены знака для одной из осей (что, как я понимаю и призваны делать мнимые числа). Извините, если что-то не так написал…
+4
Здесь часть с бивектором соответствует «мнимой» части комплексного числа. Только это не «мнимое» значение, это просто бивектор, который мы по-настоящему можем показать графически!

Вообще-то кватернион — это вектор в четырехмерном пространстве. Его базис [1, i, j, k] образует группу
image
Кроме этого, группа кватернионов (как и комплексных чисел) естественным образом порождает метрику Евклида
Кроме этого, кватернион имеет естественное представление в виде матрицы 4 x 4
image
Если вас смущает название «мнимая часть», то существует альтернативное название — «векторная часть». Если мы работаете в трехмерном пространстве, то существует бесчисленное множество способов его получить из четырехмерного (хотя бы взять скалярную часть равной нулю)
Главное различие в том, что… заменяются на…, но работают они в основном так же

Вы сделали следующее — отбросили скалярную часть (приравняли к нулю) и ввели переобозначение
Кватернион и комплексные числа, — уникальные математические объекты. Их действия (q1 * q2) есть суть преобразования евклидова четырехмерного и двухмерного пространств. Отношения между базисными элементами составляют, если хотите, таблицу логики пространства (плоскости)
0
Что-то я не уловил чем эти роторы (вообще говоря в математике ротором называется кое-что другое) и кватернионы лучше, чем обычная матрица перехода, домножая которую слева или справа на матрицу поворота, можно поворачивать вектор хоть в абсолютных координатах, хоть в относительных.
0
Кватернионы — меньше компонентов и сразу видна ось вращения.
0
Так они и описывают лишь вращение. Для той же камеры в случае с кватернионом нужно как минимум: координаты (3), направление (4), поле зрения (2). Итого: 9 координат. Против 12 значащих чисел у матрицы, которая ещё и относительный наклон осей поддерживает.

А зачем видеть «ось вращения» кватерниона/матрицы? Обычно нужно обратное преобразование: дай мне хреновину, которую можно применить к куче векторов, чтобы повернуть их на такой-то угол.
0
Выигрыш кватернионов в отсутствии вырождения (проблема нулевого угла).
+1
у матрицы поворота тоже не вырождения. оно есть только у углов Эйлера
0
Мне именно матрицы поворота не нужно было интерполировать, но отдельные вектора в 3D и 2D интерполируются просто — сначала линейно, потом результат нормализуется на интерполированный модуль. Для матрицы поворота это нужно сделать для двух векторов (строк) и довычислить третий веторным перемножением, так что тоже все несложно, и интуитивно понятно.
0
Это дает неравномерную скорость движения (которая тем заметнее чем больше угол поворота) а для поворота на 180 вообще ломается.
0
Да, конечно, это нужно учитывать, но для каких-то применений или малых углов, неравномерность не критична.
0
Я делал. Это не очень тривиально но не сильно сложнее чем с кватернионами и имеет свои плюшки в виде применимости к любым движениям (не только чистым вращениям)
+2

Большой плюс кватернионов по сравнению с матрицами — с ними можно делать сферическую линейную интерполяцию (slerp) углов поворота. Это удобно для всякого рода анимаций и плавного вращения камеры.

0
Однако slerp некоммутативен и существенно более ресурсоёмок по сравнению с nlerp, единственным недостатком которого является существенный easing на больших углах (что большая редкость).
+1

Так умножение матриц и кватернионов всё равно некоммутативно.

0
Так nlerp реализуется через сложение матриц с масштабированием в зависимости от номера шага.
0
На матрицах это тоже можно делать, просто это не так хорошо известно.
Это более общее решение чем кватернионы и не имеющее проблем с двойным покрытием, но считается оно дольше
0
Пользуясь случаем, друг интересуется, что за магия тут происходит? Как это можно записать человеческим языком? Как видно по названию переменных код вручную восстановлен при помощи известного дизассемблера. Работает как надо.
  v23 := P15.DotProduct(p21) * -2.0 + P15.DotProduct(P15) + p21.DotProduct(p21) - Radius * Radius;
  v24 := (P18.Z-P15.Z) * (P18.Z-P15.Z) + (P18.X-P15.X) * (P18.X-P15.X) + (P18.Y-P15.Y) * (P18.Y-P15.Y);
  v25 := (P15.X-p21.X) * (P18.X-P15.X) + (P15.Y-p21.Y) * (P18.Y-P15.Y);
  v26 := (P15.Z-p21.Z) * (P18.Z-P15.Z) + v25 +(P15.Z-p21.Z) * (P18.Z-P15.Z) + v25;
  v27 := v26 * v26 - 4.0 * v24 * v23;
0
Часть формулы похожа на пересечение луча со сферой. Что именно здесь происходит можно сказать только при применении ее на месте.

v23 := P15.DotProduct(p21) * -2.0 + P15.DotProduct(P15) + p21.DotProduct(p21) - Radius * Radius;
_P18 := P18 - P15;
_P15 := P15 - p21;
v26 := _P15.DotProduct(_P18);
v27 := ( v26 * v26 - _P18.DotProduct(_P18) * v23 ) * 4.0;
0
Да, всё как вы сказали. Функция называется RaySphere, просто хотелось бы иметь осмысленные переменные, а не безымянные v23..v27.
Полная функция:
function TWarpData.RaySphere(var a1, a2: Double; Radius: Double; P15, P18, p21: TPoint3D): Boolean;
var
  v23, v24, v25, v26, v27, v29, v30, v31: Double;
begin
  Result := false;

  v23 := P15.DotProduct(p21) * -2.0 + P15.DotProduct(P15) + p21.DotProduct(p21) - Radius * Radius;
  v24 := (P18.Z - P15.Z) * (P18.Z - P15.Z) + (P18.X - P15.X) * (P18.X - P15.X) + (P18.Y - P15.Y) * (P18.Y - P15.Y);
  v25 := (P15.X - p21.X) * (P18.X - P15.X) + (P15.Y - p21.Y) * (P18.Y - P15.Y);
  v26 := (P15.Z - p21.Z) * (P18.Z - P15.Z) + v25 + (P15.Z - p21.Z) * (P18.Z - P15.Z) + v25;
  v27 := v26 * v26 - 4.0 * v24 * v23;

  if (v24 >= 0.0) then
  begin
    if (v24 < 0.00001) then
    begin
      a1 := 0;
      a2 := 0;
      Result := false;
      Exit;
    end;
  end
  else if (v24 > -0.00001) then
  begin
    a1 := 0;
    a2 := 0;
    Result := false;
    Exit;
  end;
  if (v27 >= 0.0) then
  begin
    v30 := sqrt(v27);
    v31 := v24 + v24;
    a1 := (v30 - v26) / v31;
    v29 := (-v26 - v30) / v31;
    Result := true;
  end;
  a2 := v29;
end;
0
А вы начните с входных параметров. Результат у вас a1, a2 — это расстояние от точки откуда идет луч до пересечение со сферой. Дальше P15, P18, p21 — должна быть одна из них точка откуда идет луч, сам луч и центр сферы. Далее коэффициенты называться могут как угодно в них мало смысла. Скажем -v26/v31 — это расстояние от точки луча, до перпендикуляра пересекающего центр сферы. v30 * 2.0 / v31 — это длинна отрезка между точками пересечения луча со сферой.

Единственных два условия которые здесь имеют смысл это:
if (v24 < 0.00001) then
if (v27 >= 0.0) then
Потому что v24 не может быть меньше нуля. А v27 это проверка на пересечение луча со сферой. Хотя технически первое тоже имеет малое значение — случай когда точка луча находиться в центре сферы.
0
Спасибо за триггер. Удалось сократить этот мрак до вполне осмыслимого:
  v23 := P15.DotProduct(P21) * -2.0 + P15.DotProduct(P15) + P21.DotProduct(P21) - Radius * Radius;

  P18 := P18 - P15;
  v24 := P18.DotProduct(P18);
  P15 := P15 - P21;
  V26 := P15.DotProduct(P18) * 2;
  v27 := v26 * v26 - 4.0 * v24 * v23;

Да и собственно, как вы сказали, название коэффициентов тут не критично.
зы Жаль карма нулевая… Ну и тысяча извинений, человек не был рожден ни математиком, ни программистом, он бы рождён реверсером. *грустный смайлик*
+5
На этапе 3.4 произошла какая-то магия: взяли и умножили вектор на сумму скаляра и бивектора, притом что такая операция ранее нигде не вводилась.

А под спойлером написан совершенно бессмысленный вывод для x(xy), где сначала используется формула xy = x ∙ y + x ∧ y, а потом x ∧ y заменяется обратно на xy.

И да, совершенно не понятны претензии к приравниванию длины вектора к площади параллелограмма в статье, в которой дальше безо всяких объяснений вектор умножается на параллелограмм два раза, а потом результат снова приравнивается к вектору :-)
+1
И в более высоких измерениях (4D и выше) невозможно определить один вектор нормали к 2D-плоскости (например, в 4D у 2D-плоскости есть два направления нормалей, в 5D есть три направления нормалей)

Другими словами, на плоскости возможен поворот вокруг точки, в 3D пространстве — относительно прямой, в 4D пространстве — относительно плоскости, а в nD пространстве — относительно объекта размерности n - 2. Матрицы поворота вокруг точки и оси хорошо известны: Rotation matrix, Rodrigues' Rotation Formula. Однако матрицы поворота вокруг плоскости и объектов более высоких размерностей тоже выводятся. В 2012 задавался этим вопросом на math.stackexchange.com.

Только полноправные пользователи могут оставлять комментарии. , пожалуйста.