Комментарии 12
Очень рад развитию вашего блога! Продолжайте в том же духе!
Спасибо, классная шпаргалка получилась! Пробежался мысленно по этим темам, приятно было по быстрому освежить в памяти. Не поскажите, а какими программами в совокупности вы пользовались, чтобы нарисовать рисунки к вашей статье?
Шпаргалка-шпаргалкой, а очень хороший (понятный) курс линейной алгебры есть у 3Blue1Brown: Essence of linear algebra. Вышел в моём случае, увы, уже после окончания ВУЗа.
Да, я видел. Очень легко смотрится даже на английском и кое-что по новому там изложено (видел на ютубе даже переводы на русский). Но в любом случае нужна практика. Много практики + рефлексия. Ну и такие концентрированные статьи, чтобы пробежаться и освежить в памяти: вдруг будет написано словами, смысл которых позволяет по другому взглянуть на уже давно известную формулу?
Простите - я не просто так спросил про редакторы. Не смотря на широкое распространение 3D всё ещё остаётся очень далёким от ежедневного применения типа офисных пакетов Word/Excel. Даже в случае с иллюстрациями к статье. Согласитесь - подобрать рисунки в 3D по многим вопросам к статье потребовало определённого труда, в некоторых случаях даже ручного? Очень подозрительно )))
С стоимостью операций всё не так просто. Деление занимает 1-2 тика, если оно не имеет зависимостей по данным, и 20, если имеет. Т.е. если в цикле делить
while ...
x = x/something
то это примерно в 10-20 раз медленее, чем если поделить 20 чисел в массиве на указанное значение.
Вы правы, производительность вещественных операций в современных процессорах указаны в статье очень приблизительно. На практике, ознакомиться с производительностью разных команд можно в справочном руководстве от Agner Fog :
https://www.agner.org/optimize/instruction_tables.pdf
Так, например, для ядра Coffe Lake время выполнения команд вещественной арифметики составляет
Сложение, вычитание 4 такта
Умножение 4 такта
Деление 11 тактов
Вычисление квадратного корня 12 тактов
Минимум, максимум двух чисел, внезапно 4 такта
Есть даже аппаратно реализованное скалярное произведение векторов, 13 тактов.
И это довольно значительно отличается от значений. приведенных автором в статье.
Кратко. чотко и по делу. Спасибо.
cross product появляется в 3D-пространстве. Это операция над двумя векторами, результатом которой является вектор, перпендикулярный исходным двум
Вообще говоря, это не верно. Векторное произведение не является вектором, это — псевдовектор (или ещё он называется аксиальный вектор). Это довольно принципиальный момент, в частности результат подсчёта векторного произведения зависит от того какую систему отсчёта вы выберете. Смена правой на левую приведёт к инвертированию результата векторного произведения в пространстве. Также в силу разной природы полярных (обычных) и аксиальных векторов их, например, нельзя складывать.
Отсюда также следует, что упомянутое смешанное произведение тоже не скаляр, а — псевдоскаляр. Его знак также будет зависеть от ориентации системы отсчёта.
vec3 new_dir = dir - normal * dir(dir, normal);
Во первых функция не dir, а dot. Во вторых умножение на два забыли, иначе получится вектор параллельный плоскости отражения (не совсем понятно что имелось в виду).
vec3 new_dir = dir - 2 * dot
(dir, normal) * normal;
Если хотели сделать направление по плоскости то нужно не забыть нормализовать его, или восстановить скорость/длину вектора.
Очень крутое можно делать с cross product в проективном пространстве: можно найти пересечение двух прямых! Всегда мечтал это сделать, так как изначально cross product выглядит как функция для нахождения пересечения, и по прошествии многих лет после ознакомления с векторным произведением, приобретением некоторых знаний о проективной геометрии, я смог это наконец-то сделать. Cross product стала функцией для поиска пересечения двух прямых в двумерном пространстве!
public static bool isLinesCrossed(Vector3 a1, Vector3 b1, Vector3 a2, Vector3 b2, ref Vector3 itr, float USEEPS) {
var d1 = b1 - a1;
var d2 = b2 - a2;
var n1 = new Vector3(d1.y, -d1.x);
var n2 = new Vector3(d2.y, -d2.x);
n1.z = -Vector3.Dot(a1, n1);
n2.z = -Vector3.Dot(a2, n2);
itr = Vector3.Cross(n1, n2);
if(Mathf.Abs(itr.z) < USEEPS) return false;
itr.x /= itr.z;
itr.y /= itr.z;
itr.z = 0f;
return true;
}
Математика для 3D-приложений. Урок 1