Хочу сделать себе рэгдолл и начать с самого простого.
Про джойнты и степени свободы читал в статьях Сусликах, но там у него слишком мало информации.
Хочу начать от простого и сделать, например две палки, которые соединены чем-то вроде шарнира и на этом примере понять механику работы.
Подскажите, что еще можно почитать или посмотреть, чтобы предельно ясно было, для тех кто подтормаживает на эту тему.
У тебя свой физический движок или готовый? Потому что если готовый то там в документации обычно есть объяснение, например https://docs.panda3d.org/1.10/python/programming/physics/bullet/constraints
так исходники умных-умных людей читать только.
box2d, bullet. Если да прямо лучшее вытащить надо, то только туда.
В чужие не вникал. И фиг знает, как оно правильно.
В своей импровизации добавлял новый вид решения контактов. То есть, есть решение контакта по нормали и по 2-м осям трения. Новый контакт (назвал его GlueContact), он как бы склеивает 2 тела в заданной точке. При этом центры масс и другие точки могут двигаться друг относительно друга. Этакий контакт нормали наоборот. Этот контакт не вычисляется, а задаётся. Тела при этом вообще могут не пересекаться.
Примерно так:
class CContactGlue
{
int Obj_1;
int Obj_2;
vec3 pRel1; // заданная точка для 1 тела в локальных координатах 1 объекта
vec3 pRel2; // заданная точка для 2 тела в локальных координатах 2 объекта
...
}
Решаем этот контакт примерно также как и контакт нормали. Здесь нормалью при решении будет выступать не нормаль какого-то из тел, а нормализованный вектор между глобальными координатами заданной точки контакта 1 тела и глобальными координатами точки контакта 2 тела. А точкой контакта при решении будет выступать точка в глобальных координатах на полпути между этими заданными двумя точками.
Если задача солвера контакта нормали не дать проникнуть одному телу в другое, то здесь - не дать им разлететься.
Например чтобы создать руку из 2 объектов, которая может гнуться, нужно задать 2 скрепляющих контакта в двух местах сочленения. Если задать 1 скрепляющий контакт, то звенья этой руки будут вращаться вокруг своей оси независимо от вращения друг друга, так можно сделать верёвку.
Чтобы сделать открывающуюся дверь, можно заданием двух скрепляющих контактов - один слева внизу, второй - слева вверху.
Так же делал веревки и ткани.
Машинки - через задание скрепляющих контактов между колесами и платформой. Для поворота колёс, меняем локальные координаты скрепляющих контактов.
Также деревья, которые можно гнуть - это просто куча верёвок с общим стволом.
Также примерно работает и шагоход - меняем координаты контактов - и их солвер подтягивает его ноги куда нужно.
Здесь на на 11:58 примеры работы.

GLoom
> У тебя свой физический движок или готовый?
Свой.
texture3D
> Здесь на на 11:58 примеры работы.
То что нужно.
Похоже, на тебя вся надежда.
Сначала попытаюсь сам что-то сделать на основе того что ты уже написал, если не выйдет - немного подостаю тебя с тупыми вопросами, если ты не против.
Судя по твоим видео, ты явно очень продвинут в области физических движков, круто выглядит.
texture3D
> В своей импровизации добавлял новый вид решения контактов.
Я правильно понял, что в этом случае вармстартинг не нужен?
Или все же нужен?
MikeNew
Пробовал добавить, плюсов не увидел.
Тут, наверное, сыграло то, что, если тела пересекались, а значит и имели обычные контакты нормали и трения, то при их решении их вармстартинг и так успокаивал тела.
Если же тела не пересекались, то система и так быстро сходилась даже без вармстартинга.
Если всё же тела немного дрожали, то слипинг их замораживал.
Зато с вармстартингом их начинало временами колбасить.
Хотя тут, возможно, сыграло то что, при решении я еще увеличивал импульс на величину, равную масштабирующему коэффициенту, умноженному на расстоянию между контактной точкой 1 тела в его локальных координатах и контактной точкой 2 тела в соответствующих координатах. Этакий аналог величине проникновения у псевдоскоростей, чтобы всё же разлетевшиеся тела стремились спружинить обратно (здесь чтобы заданная точка контакта 1 тела не улетала далеко от заданной точки 2 тела ).
А про вармстартинг для псевдоскоростей процитирую Суслика
Если бы убрал эту часть из решения, то вармстартинг может и давал какой-то плюс, но решение и так быстро сходилось. В итоге я забил.
texture3D
> В своей импровизации добавлял новый вид решения контактов. То есть, есть решение контакта по нормали и по 2-м осям трения. Новый контакт (назвал его GlueContact), он как бы склеивает 2 тела в заданной точке
Я правильно понял, что если для контакта столкновений по нормали псевдоскорости нужны для того чтобы тела выталкивались друг из друг при слишком глубоком проникновении, то для GlueContact псевдоскорости необходимы для того чтобы тела притянулись и прилипли друг к другу в точке склеивания?
Если же неправильно, то какую роль псевдоскорости у GlueContact выполняют у тебя?
И еще вопрос - зачем для GlueContact трение? На примере, пожалуйста, если не влом..
Псевдоскорости нужны для исправления ошибки позиции, причем не важно для какого типа связей/контактов.
MikeNew
> для GlueContact псевдоскорости необходимы для того чтобы тела притянулись и прилипли друг к другу в точке склеивания?
Не сами тела, а 2 точки одного glue контакта. Они играют роль пружин/амортизаторов. Сами тела при сближении этих точек могут как сблизиться так и отдалиться.

Вот машинка, её тело - бокс вверху и 4 колеса цилиндра.
Левое заднее колесо с телом скрепляют 2 glue контакта, один с точками a1 и b1, второй с точками a2, b2.
a1 находится в центре левого диска задаётся через локальные координаты ax ay az колеса и здесь он равен (0; -0.5; 0). Соответственно a2 имеет координаты (0; 0.5; 0).
Точка b1 относится к тому же glue контакту, что и a1, но задаётся через локальные координаты верхнего бокса. В его системе координат bx by bz имеет координаты (-5; -1; -5 ). b2 имеет координаты (-4; -1; -5)
Здесь пару колесо - бокс скрепляют 2 glue контакта (a1, b1) и (a2, b2).
Вычисляем координаты a1 в глобальной системе координат и b1 в глобальной СК. Решаем контакт. Далее, если эти точки ушли далеко друг от друга, то подталкиваем их обратно друг к другу.
Сами тела могут и отдаляться при сближении этих точек. Колесо может как провалиться вниз, отдаляясь от тела машины так и подскочить вверх, приближаясь к ней. В обоих случаях задача псевдоскоростей чтобы расстояние между a1 и b1 было в каком-то ограниченном диапазоне.
MikeNew
> зачем для GlueContact трение?
для них трение не использовал. Решал также как обычный контакт нормали, где нормалью для одного контакта выступает нормализованный вектор в глобальной системе координат между вычисляемыми точками a1 и b1.
А глубиной проникновения здесь выступает расстояние между a1 и b1.
}:+()___ [Smile]
> Псевдоскорости нужны для исправления ошибки позиции, причем не важно для какого типа связей/контактов.
Исчерпывающе, я примерно так и полагал.
texture3D
> Не сами тела, а 2 точки одного glue контакта.
Я все-таки сделал базу, с которой можно работать дальше:

Сейчас буду пытаться сделать колесо и тому подобное по твоему описанию.
Кстати, есть вопрос - как сделать подобие сустава с помощью двух контактов - это понятно, а как сделать ограничитель на угол, на который он может изгибаться?
MikeNew
> Я все-таки сделал базу, с которой можно работать дальше
Выглядит нормально.
MikeNew
> а как сделать ограничитель на угол, на который он может изгибаться?
Я сам это не делал, но прикинул что это можно сделать добавив псевдоджоинты - те же GlueContacts, но при их решении решаем только их псевдочасть с отклонением Depth.

Например вот 2-хмерные стена a и дверь b.
Стандартный GlueContact с локальными координатами (a1;b1) держит эту дверь у стены и в то же время не мешает ее проворачивать почти на 360 градусов, мешает только сама стена.
Добавляем псевдоджоинт с координатами (a2;b2). Пусть dist - расстояние от скрепляющего джоинта (a1;b1) (того, вокруг которого мы будем вращать дверь и на чье вращение нам и нужно добавить ограничение) до нового псевдоджоинта (a2;b2).
Допустим, нам нужно сделать так, чтобы дверь нельзя было отвернуть более чем на 70 градусов.
Доходим до решения контактов, решаем обычный джоинт (a1;b1).
Далее решаем псевдоджоинт (a2;b2), находим проекцию вектора b2 - b1 на нормализованный вектор a2 - a1 (на рисунке это Proj b2).
Если эта проекция меньше cos 70 градусов, то ничего не делаем, игнорируем этот псевдоджоинт (считаем отклонение Depth = 0).
Если же нет, то отклонение Depth считаем как ( Proj b2 / dist - cos(70 градусов) ) * dist.
И решаем только псевдочасть этого джоинта с вычисленным Depth.
texture3D
> Выглядит нормально.
Как оказалось - только выглядит. :)
Текущие псевдоскорости у меня не способны преодолеть даже гравитацию (в принципе, понятно почему, они слишком малы и для этого не предназначены - я взял их без изменений из контакта для столкновений), здесь я предварительно закрепил одну из палок в воздухе и включаю-выключаю гравитацию:

В связи с этим вопрос - как у тебя сделаны псевдоскорости для клеевого контакта?
Явно же не так как для контакта столкновений. Или я что-то упускаю.
PS Хм.. псевдоскорости должны быть пропорциональны расстоянию между точками склеивания, плюс должен учитываться момент, когда точки склеивания "залезли друг за друга", тогда у псевдоскорости нужно поменять знак, чтобы она "растолкнула" точки склеивания..
Чтобы был эффект как у пружины с нулевой длиной и бесконечной жесткостью.. как-то так это вижу.
PSS Нашел где у меня проблема, прогресс пошел. Подправлю еще и выложу что получилось.
Ну теперь точно работает:

texture3D
> Выглядит нормально.
Без тебя бы возился намного дальше даже с такой базой, спасибо.
Теперь примусь за колеса всякие и ограничения по углу.
Тема в архиве.