Pull to refresh

Comments 47

это наверное те самые кватернионы? А кубики почему работали нормально с тремя координатами?

Разрабы говорят, что четыре координаты нужны для "better alignment", наверно для работы с кватернионами там им удобнее, когда сразу 4x1, чтобы память не перекладывать.

Кубики работали, потому что у них интерфейс без этих выкрутасов с векторами, просто задаются размеры куба, и готово: proc createBox*(space: dSpaceID; lx: dReal; ly: dReal; lz: dReal): dGeomID. Ошибиться сложно, даже для меня :)

Возможно так проще множить на четырехмерные матрицы (чтобы операцию трансляции сделать линейной из аффинной)

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

просто в четвертой координате надо поставить мусор

Меня смутила, так как четвертая компонента имеет важный смысл в однородной системе координат

Вот тоже подумал, что с "мусором", конечно, странный момент, но совершенно не ожидать однородных координат из четырёх чисел как-то странно - можно быть поверхностно знакомым с трёхмерной графикой и не понимать, нахера они нужны, но если пилить движки на основе чужих движков, то точно с ними столкнёшься, рано или поздно. Возможно, в описанном случае четвёртая координата вообще движком игнорируется (т. е., как бы принимается за 1, несмотря на "мусор" в массиве координат), но, по счастливой случайности, в используемых автором операциях ни на что не влияет?

Сишный код, конечно, оформлен херово - не говорю даже про dReal* Vertices, но с какого перепугу dVector3[4] - при том что, зачастую, в библиотеках используются и трёх-, и четырёхмерные вектора, сколько помню, обычно их отдельно определяют: dVector3 для "простых" координат, dVector4 для однородных.

Но, вообще, страдания автора понятны: тоже, бывало, надо перемножить туда-сюда десяток матриц трансформации, в вычислении какого-нибудь одного коэффициента чуть-чуть ошибёшься, а на конечном результате это отражается совсем не "чуть-чуть", трёхмерный объект улетает куда-нибудь в бесконечность, что на экране не найдёшь, и, как говорится, happy debugging!

ну да, теперь укладывается в теорию. SIMD + то же самое при перемножении на 4x4 матрицу аналогично применяется. Красиво закинул сразу вектор в регистр без дополнительных операций

Как уже было отмечено ранее это связано с понятием "однородных координат". В общем случае модификации (изменение положения и формы геометрических объектов в пространстве) векторов и точек требуется выполнять простейшие операции: сдвиг (трансляция), поворот, симметрия, масштабирование и т.п. Модификаторы поворота, симметрии и масштабирования описываются формулами, имеющими одинаковый вид:
p = q + A * (p0 ‑ q) = A * p0 + t, где
p — результирующая точка,
A — матрица аффинных преобразований,
t = q - A * q — преобразованный вектор сдвига,
q — радиус-вектор точки, определяющей плоскость симметрии или оси-вращения.
Так сдвиг (трансляцию, перемещение) можно описать единичной матрицей A и вектором t.

Но хотелось бы обобщить эту формулу на любые модификации и это можно сделать. Для этого нужно увеличить размерность векторов и матриц на единицу. Вектор теперь будет называться расширенным вектором. И его компоненты теперь будут называться однородными координатами P = {px, py, pz, 1}. Индекс матрицы A_t будет говорит, что она расширенная - та же матрица А, окаймленная снизу нулями, а справа стоящий вектор сдвига t.
Поэтому общая формула примет вид P = A_t * P0.
При этом можно ввести вес w и строить рациональные кривые
R = {R1, R2, R3, R4} = {w * rx, w * ry, w * rz, w * 1}. Вычисления теперь будут проводиться в однородных координатах, что уменьшит их сложность, а декартовы координаты будут определены на последнем этапе как ri = Ri / R4, где i = 1, 2, 3.

Итогом всего будет являться тот факт, что для точек имеющих вес, сдвиг, поворот, симметрия, масштабирование и другие модификаторы опишутся одной единственной общей формулой. Также это можно применить в операциях в 2D пространстве, при этом формула остается прежней. Именно поэтому использование однородных координат оказывается полезным там, где дополнительная компонента точки отсутствует или наоборот требуется.

This problem may be overcome by use of a fourth gimbal, actively driven by a motor so as to maintain a large angle between roll and yaw gimbal axes. Another solution is to rotate one or more of the gimbals to an arbitrary position when gimbal lock is detected and thus reset the device.

Modern practice is to avoid the use of gimbals entirely. In the context of inertial navigation systems, that can be done by mounting the inertial sensors directly to the body of the vehicle (this is called a strapdown system)[3] and integrating sensed rotation and acceleration digitally using quaternion methods to derive vehicle orientation and velocity. Another way to replace gimbals is to use fluid bearings or a flotation chamber.

Gimbal lock - Wikipedia

Много причин, если кратко, очень многие типы операций требуют четырехмерных векторов, потому что матрица 3д вида 4-х мерная.
Ну и да, для кватернионов можно использовать

Вероятно, автору интереснее работа с трехмерной графикой, чем гейм-дизайн. "Игровой движок" в таких контекстах лично я уже понимаю как движок "интерактивной трехмерной графики"

Что значит интерактивная 3д?

Грубо говоря, реагирующая на действия пользователя(например, нажатия клавиш = модель двигается влево/вправо).

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

Во времена MS-DOS каждый уважающий себя программист был обязан написать свою оконную библиотеку :)

Потому что ТС не хочет делать игры, он хочет ковыряться в движке :)

Как тот батя с разобранной шахой.
Отличное хобби, так то )

В многих случаях батя в гараж к шохе уходит чтобы просто из дома свалить ))

Это теперь называется «родительское собрание» :-( у нас, таких крутых-молодых в 200х выросли собственные дети и, зачастую, коренным образом сменились хобби

Он ещё пишет на ноунейм языке - NIM

Ну прям совсем ноунейм не добавили бы в репозитории убунты и, в особенности, дебиана :) Но да, там маленькое коммьюнити. Питон, знаете, тоже когда-то был ноунейм)

Как 3D-принтер. Всегда разобран. Если не разобран, то печатает апгрейды для самого себя.

Это ж вы описали какой-то SCP объект, а именно [УДАЛЕНО].

Там же одно из первых предложений про это - чтобы развлечься написанием собственного движка.

Я конечно дилетант в скалолазании, но почему бы не подняться на гору на вертолете?

Пока вы заведете вертолет, четкий скалолаз успеет пожарить шашлыки на вершине =)

представьте, что какой-то разраб через 20 лет будет в нём разбираться, и, пожалуйста, постарайтесь сделать жизнь этого чувака хоть чутоку легче

Мне кажется ваши статьи и через 20 лет будут читаться так же легко. Вы показываете абсолютно обыденные вещи, с которыми разработчики сталкиваются по сто раз на дню, но всегда удивительно красиво и романтично. Как если бы Бианки или Паустовский писали свои записки о природе IT.

Николай Дроздов : Мы видим синий экран смерти, это нормальное состояние компьютера для разработчика драйверов. Разработчики драйверов - хитрые и ловкие программисты .Давайте посмотрим, что он предпримет сейчас...

О, а игровой движок 15-летнего возраста, на котором мы сейчас делаем игру, как раз использует для физики ODE. Привет "заводчикам динозавров" от коллег по увлечению :)

Почему unreal engine 5 не возьмёшь просто?

Программирование графики всегда веселее, чем просто программирование. Т.к. картинка на экране - это уже своего рода дебаг, сразу видно если что-то не то. Если одно видимое, конечно.

Скорее это иллюстрация что происходит с любым специалистом, возвращающимся в область своих знаний 30 лет спустя.

Сейчас 4-х мерный вектор для описания точки в пространстве какой-то связанной системы координат - сейчас это НОРМА. Такая норма, что первокурсник это знает. Это практически аппаратный стандарт на данный момент. Три координаты и 4й компонент - своего рода квалификатор: 0 - это вектор направления (если единичный) или сдвига, 1 - точка в пространстве, != 1 точка в каком-то масштабе или неоднородный масштаб.

Изменение с `Vector3d` на `dReal` скорее всего было связано с обновлениями стандарта и портом движка на что-нибудь... браузерное. Дело в том что с 98 стандарта Си++ и с 99 Си преобразовать массив структур `struct{ dReal[4] v;}` в массив dReal формально нельзя. Си или Си++ могут быть реализованы на виртуальной платформе со сборщиком мусора и тогда меду этими блоками может быть что-то еще... А вот API для 3d графики стало активно использовать именно массивы для передачи их драйверу.

4й компонент - своего рода квалификатор: 0 - это вектор направления (если единичный) или сдвига, 1 - точка в пространстве, != 1 точка в каком-то масштабе или неоднородный масштаб

Это в какой области? Вроде, последние годы писал графику - ни разу не сталкивался, если 4-мерный вектор для описания координат - значит, координаты однородные, и только. Шейдеры и пр., правда, я не писал - определил геометрию и отдал какой-нибудь графической библиотеке, типа, нарисуй мне там как-нибудь - ну, так вроде и автор статьи примерно тем же занимается, и в качестве "квалификаторов" у него там эти четвёртые компоненты не используются.

преобразовать массив структур struct{ dReal[4] v;} в массив dReal формально нельзя

Так там же не структуры были, а от массива массивов перешли на "плоский" массив? Вот такое, что, запрещено стало с C++ 98, или undefined behavior теперь?

#include <iostream>

typedef float dReal;
typedef dReal dVector3[4];

int main()
{
    dVector3 vectors[] = { {1, 2, 3}, {4, 5, 6} };
    dReal *array = (dReal*)vectors; // UB??

    for (int i = 0; i < 8; ++i) std::cout << array[i] << '\t';
    std::cout << '\n';

    return EXIT_SUCCESS;
}

ODE вообще довольно заброшенный движок, по ощущениям. Как-то написал с его использованием машинку, которая ездила по ландшафту, потом долго удивлялся мелко дрожащим колёсам (а я их сделал "честными" цилиндрами, а не просто вектором-сенсором) и иногда ловил проблему на резком повороте, когда вся система улетала в небеса (где-то в процессе вычислений вылезал NaN, который потом разваливал всю симуляцию). В общем, физический сыроватый в лучшие годы и околозаброшенный к текущему времени.

Вы использовали double precision и фиксированный шаг симуляции? Если да, и при этом всё равно словили глюки, то это печально

Да, по обоим пунктам. Мелкое дрожание ещё худо-бедно полечилось настройкой перехода объекта в неподвижное состояние (~засыпание при отсутствии внешних воздействий, не помню сейчас, как именно это называется в ODE), а вот где вылезал NaN дебажить уже лень было.

"мелкое дрожание" - сразу вызывает флешбэки по бюджетным играм нулевых, для которых небольшие группы разработчиков собственные движки писали.

Кидайте в меня чем-нибудь тяжёлым, но проблемы бы не было, если бы параметр назвали paQuadVertices (pointer to array of quad vertices).

Конечно, так компилятор ничего не проверит, но любая попытка решить проблему через типы или алиасы в системах с прямым доступом к памяти только сделает хуже (что мы и видели).

Написано хорошо. Но вообще вы тут оба молодцы. У одного vector3 имеет 4 координаты, а другой видя const dReal* Vertices решил методом тыка угадывать формат, вместо того чтобы посмотреть в документацию/код.

Ну как бы да, мануал наше всё, но я ещё примеры от других людей смотрю, туториалы там всякие почитываю. И везде эта ошибка встречается.

Вот, например, неправильная подсказка, потому что автор забыл про то, что это 4D вектор:

кому интересно формат вот такой
Vertices[count]={x1,y1,z1,x2,y2,z2,x3,y3,z3................................}

Или вот чел наступил на те же грабли, что и я:

Ok, so I decided to use the test_trimesh trimesh to make sure everything was working ok.
So everything seems to work fine, but I get an error in my collide callback
I get a fat access violation.
Urrrrrrrrrrrrrgh this triangle collider is really making me mad ><

И вот ещё один погорелец:

float vertices[vCount * 3] = {
0,0,0,
20*30,0,0,
20*30,0,20*30,
0,0,20*30
};
Sign up to leave a comment.