Соединение твердых тел с помощью пружин

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

Возвратимся к теме. Эти соединенные между собой твердые тела представляют собой кукольный персонаж. Вы знаете, как все устроено - кости кисти присоединены к руке, кость руки присоединена к .... Ну, вы поняли идею. Твердые тела соединяются между собой так же, как и кости в скелетном меше присоединяются к родительским костям (конечно, за исключением корневой кости).

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

Как вы можете видеть на рис. 7.9, пружины создаются для каждой точки соединения костей в исходной скелетной структуре.

Когда вы начнете перемещать твердые тела, вам будет необходимо вычислить силы, необходимые каждой пружине для сохранения начальной формы структуры тела. Пружины просто создают силы, двигающие каждый объект в заданном направлении. Но в отличие от упомянутых ранее сил, пружинам необходимо соединить тело не немедленно, а за определенный интервал времени. Это можно реализовать, непосредственно изменяя положение и угловой момент каждого тела.

Соединение твердых тел с помощью пружин

Рис. 7.9. Пружины соединяют твердые тела в точках сочленения костей

Сначала о главном, вам необходимо узнать точки соединения костей. Когда вы создаете ограничивающие параллелепипеды, вам необходимо добавить точку, которая определяет место соединения параллелепипеда с параллелепипедом родительской кости. Вам также необходимо добавить точку, представляющую собой смещение от центра родительской кости до точки соединения. Эти две точки показаны на рис. 7.10.

Помните, ранее в этой главе, вы определили восемь векторов, представляющих собой углы твердого тела? Было два набора по восемь вершин, один для определения локальных координат, а другой для определения этих же самых точек в мировых координатах. Теперь вам необходимо добавить еще две точки в список.

Первая точка является смещением от центра кости до точки соединения с родительской костью. Эта точка, имеющая название точка смещения соединения (или просто смещение соединения), представляет собой один конец создаваемой пружины, которая будет соединять твердые тела после их перемещений.

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

Соединение твердых тел с помощью пружин

Рис. 7.10. Каждая кость определяется размерами ограничивающего параллелепипеда и точкой соединения с родительской костью.

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

БЗБХУЕСТОРЗ хесЬоса1Ро1ПС8[9]; БЗБХУЕСТОРЗ хес1*ог1о!Ро1ПС8[10] ;

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

Вектор смещения соединения хранится в объекте ВЗБХУЕСКЖЗ, имеющем название уес1от1(Ж8е1, в то время как вектор родительского смещения хранится в уесРагегЛС^е!. Первое, что необходимо сделать, это сохранить вектор смещения соединения в соответствующем векторе локального пространства.

хесЬоса1Ро1псв[8] = vecJointOffset;

Теперь вы можете преобразовывать девять точек из локального пространства в мировое, как вы делали это ранее. После чего, точка 8 будет содержать координаты в мировом пространстве точки присоединения кости к родителю.

Что же касается вектора родительского смещения, вам необходимо поместить его в один из векторов уесХУогкСРоіпз. Чтобы сделать это, используйте преобразования родительской кости. Если ориентация родителя кости хранится в виде матрицы преобразования таїРагепЮгіепІаиоп, а положение в векторе уесРагепі-Ро8Шоп, вы можете вычислить координаты преобразованной точки так:

D3DXVec3TгansfoгmCooгd(&vecWoгldPoints[9], \ &vecPaгentOffset, \ &matPaгentOгientation); vecWoгldPoints[9] += vecPaгentPosition;

После преобразования координат точек в мировое пространство вы можете использовать их для создания пружины, показанной на рис. 7.11.

Соединение твердых тел с помощью пружин

Рис. 7.11. Вы создаете вектор пружины, соединяя точки смещения соединения и родительского смещения. Обе точки задаются в мировых координатах

// vecPosition = положение тела

// Получить положение смещения соединения в мировых координатах D3DXVECTOR3 vecBonePos = vecWoгldPoints[8];

// Получить вектор из точки в центр тела

/ / Он используется для вычисления момента D3DXVECTOR3 vecPtoC = vecPosition - vecBonePos;

// Получить положение родительского смещения в мировых координатах D3DXVECTOR3 vecParentPos = vecWorldPoints[9];

// Вычислить вектор пружины из точек соединения и родительской D3DXVECTOR3 vecSpring = vecBonePos - vecParentPos,•

Теперь вектор уесБргіп§ содержит разницу координат, которую вы используете для перемещения кости для соединения ее с родителем. По аналогии с реальным человеком, при соединении с родителем двигаются только дочерние кости. (В качестве примера: ваша рука повторяет движение груди.) Таким образом, при движении корневой кости (представляющей грудь персонажа или центр масс) будут двигаться и все присоединенные к ней кости (вместо того, чтобы двигать корневую кость для сохранения соединения с дочерними).

Т. к. вы просто хотите переместить кость для воссоединения с родительской, вы можете просто добавить вектор уесБргіп§ непосредственно к положению вашего тела (игнорируя таким образом константы пружины). Также вы можете вычислить векторное произведение разницы положения точки и положения смещения вращения и пружины для получения углового момента кости, таким образом повернув ее, чтобы убедиться, что существуют точки касания.

vecPosition += vecSpring,• D3DXVECTOR3 vecCross;

D3DXVec3Cross(&vecCross, &vecBtoC, &vecSpring); vecAngularMoment += vecCross,•

После изменения момента вы можете преобразовать его, используя обратную матрицу тензора инерции кости, и сохранить результат в векторе угловой скорости.

D3DXVECTOR3 vec

D3DXVec3TransformCoord(&vecAngularVelocity, \ &vecAngularMomentum, \ &matInvWorldInertiaTensor);

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

Вектор из центра ограничивающего параллелепипеда в координаты кости является смещением соединения. Смещение от координат родительской кости (которые изменяются при помощи обратной матрицы преобразования кости) до координат кости дает вектор родительского смещения. Вы узнаете об этом более подробно чуть позже. Пока что вы научились накладывать силы на линейную скорость и угловой момент и заставлять кости воссоединяться. Что далее? Обработка столкновений, вот что!

Использование сил для создания движения || Оглавление || Обеспечение обнаружения столкновений и ответной реакции