Помоги мне с физикой твердого тела / трансформации - PullRequest
3 голосов
/ 22 февраля 2009

Я хочу создать ограничение ползунка, которое позволяет телу скользить между точкой A и точкой B. В качестве примера ограничения я назначаю два тела для ограничения, в данном случае одно динамическое тело, ограниченное статическим миром, например раздвижной дверью. Третьим и четвертым параметрами являются преобразования, опорный кадр A и опорный кадр B . Для создания и управления преобразованиями библиотека поддерживает кватернионы, матрицы и углы Эйлера.

Ограничение ползунка по умолчанию перемещает тело вдоль оси X. Мой вопрос: Как настроить два преобразования, чтобы тело B скользило вдоль оси, заданной своим собственным началом и дополнительной точкой в ​​пространстве?

Наивно я пытался:

frameA.setOrigin(origin_of_point); //since the world itself has origin (0,0,0)
frameA.setRotation(Quaternion(directionToB, 0 rotation));

frameB.setOrigin(0,0,0); //axis goes through origin of object
frameB.setRotation(Quaternion(directionToPoint,0))

Однако кватернионы, похоже, не работают так, как я ожидал. Мои математические знания о них не очень хороши, поэтому, если кто-то сможет объяснить мне, почему это не работает, я буду благодарен. Что происходит, так это то, что тело скользит вдоль оси, ортогональной направлению. Когда я изменяю вращательную часть в конструкторе Quaternion, тело вращается вокруг этого направления скольжения.

Edit: Основой является физика пули. Эти два преобразования показывают, как соединение ползунка прикрепляется к каждому телу по отношению к локальной системе координат каждого тела.

Edit2 Я мог бы также установить вращательные части преобразований через ортогональный базис, но тогда мне пришлось бы надежно построить ортогональный базис из одного вектора. Я надеялся, что кватернионы предотвратят это.

Edit3 У меня ограниченный успех в следующей процедуре:

btTransform trafoA, trafoB;
trafoA.setIdentity();
trafoB.setIdentity();

vec3 bodyorigin(entA->getTrafo().col_t);
vec3 thisorigin(trafo.col_t);
vec3 dir=bodyorigin-thisorigin;
dir.Normalize();

mat4x4 dg=dgGrammSchmidt(dir);
mat4x4 dg2=dgGrammSchmidt(-dir);

btMatrix3x3 m(
    dg.col_x.x, dg.col_y.x, dg.col_z.x,
    dg.col_x.y, dg.col_y.y, dg.col_z.y,
    dg.col_x.z, dg.col_y.z, dg.col_z.z);
btMatrix3x3 m2(
    dg2.col_x.x, dg2.col_y.x, dg2.col_z.x,
    dg2.col_x.y, dg2.col_y.y, dg2.col_z.y,
    dg2.col_x.z, dg2.col_y.z, dg2.col_z.z);


trafoA.setBasis(m);
trafoB.setBasis(m2);

trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
btSliderConstraint* sc=new btSliderConstraint(*game.worldBody, *entA->getBody(), trafoA, trafoB, true);

Однако GramSchmidt всегда переворачивает некоторые оси матрицы trafoB, и дверь появляется вверх ногами или справа налево. Я надеялся на более элегантный способ решить эту проблему. Edit4 Я нашел решение, но я не уверен, приведет ли это к сингулярности в решателе ограничений, если верхний вектор будет совпадать с направлением скольжения:

btTransform rbat = rba->getCenterOfMassTransform();
btVector3 up(rbat.getBasis()[0][0], rbat.getBasis()[1][0], rbat.getBasis()[2][0]);
btVector3 direction = (rbb->getWorldTransform().getOrigin() - btVector3(trafo.col_t.x, trafo.col_t.y, trafo.col_t.z)).normalize();

btScalar angle = acos(up.dot(direction));
btVector3 axis = up.cross(direction);
trafoA.setRotation(btQuaternion(axis, angle));
trafoB.setRotation(btQuaternion(axis, angle));
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));

Ответы [ 3 ]

1 голос
/ 03 марта 2009

Возможно ли, что вы делаете этот путь слишком сложным? Похоже, что простой параметрический перевод (x = p*A+(1-p)*B) сделает это. Вся вещь о вращении / ориентации - красная сельдь, если ваша аналогия с раздвижной дверью верна.

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

- MarkusQ

0 голосов
/ 22 февраля 2009

Возможно, вы ищете slerp ?

Slerp - сокращение от сферического линейная интерполяция, введенная Кен Шумейк в контексте кватернионная интерполяция для Цель анимации трехмерного вращения. Это относится к постоянной скорости движения вдоль единица радиуса большой круг дуги, учитывая концы и интерполяция параметр между 0 и 1.

В конце концов, вам все еще нужна традиционная матрица вращения, чтобы вращать вещи.

Редактировать : Итак, я все еще догадываюсь, но я предполагаю, что инфраструктура заботится о slerping, и вы хотите два преобразования, которые описывают состояние начала и состояние конца?

Вы можете размещать аффинные преобразования поверх других. За исключением того, что вы должны думать назад. Например, допустим, что раздвижная дверь расположена в точке (1, 1, 1), обращенной на восток, в начальном состоянии, и вы хотите сдвинуть ее к северу на (0, 1, 0). Дверь будет в конечном итоге в (1, 1, 1) + (0, 1, 0).

Для начального состояния поверните дверь на восток. Затем вы применяете другую матрицу перевода, чтобы переместить дверь в (1, 1, 1). Для конечного состояния вы снова поворачиваете дверь на восток, затем перемещаете дверь в (1, 1, 1), снова применяя матрицу перевода. Далее вы применяете матрицу перевода (0, 1, 0).

0 голосов
/ 22 февраля 2009

Было бы полезно, если бы вы могли сказать, какую платформу или API вы используете, или скопировать и вставить документацию для функции, которую вы вызываете. Без таких деталей я могу только догадываться:

Фон: кватернион представляет 3-мерное вращение в сочетании со шкалой. (Обычно вам не нужны сложности, связанные с управлением шкалой, поэтому вы работаете с единичными кватернионами, представляющими только вращения.) Матрицы и углы Эйлера являются двумя альтернативными способами представления вращений.

Система отсчета - это позиция плюс поворот. Подумайте об объекте, помещенном в определенном месте в пространстве, а затем повернутом в определенном направлении.

Таким образом, кадр А, вероятно, должен быть начальной позицией и вращением объекта (когда ползунок находится на одном конце), а кадр В - конечной позицией и вращением объекта (когда ползунок находится на другом конце). В частности, два поворота, вероятно, должны быть одинаковыми, поскольку вы хотите, чтобы объект скользил жестко.

Но, как я уже сказал, это всего лишь предположение.

Обновление: это Bullet Physics ? Похоже, документация не слишком полезна, не так ли?

...