Движение твердого тела имеет два вида - линейное движение и угловое вращение. Линейное движение это перемещение тела вдоль прямой линии в любом направлении, а угловое вращение это вращение твердого тела вдоль осей. Просто, не правда ли?
Все движения являются результатом действия сил на твердое тело. Если вы прикладываете силу к телу, то оно в результате этого линейно движется и/или вращается. Линейное движение легко вычисляется; просто перемещайте телов направлении действия силы. Вращение чем-то похоже - вы прикладываете силу, в результате чего тело вращается. Направление и величина вращения зависят от точки приложения силы.
Давайте рассмотрим каждый тип движения более подробно.
Движение твердых тел
Линейное движение является результатом того, что объект толкнули или потянули в одном направлении. По мере приложения различных сил может меняться направление и скорость движения. Все зависит от силы, приложенной к телу. Для упрощения, все силы, действующие на тело, сводятся к одной, с которой вы и работаете.
Сами силы хранятся в виде векторов (D3DXVECTOR3), которые определяют направление и величину прикладываемой силы (амплитуду). Для наших целей, сила представляет собой значение ускорения, прикладываемого к телу массой 1. А что же с объектами, масса которых не равна 1, или с теми силами, которые ускоряют объекты независимо от их масс? Здесь вам поможет второй закон Ньютона.
Второй закон Ньютона связывает величину силы (F), которую вы должны приложить к телу массой (m) для достижения им заданного ускорения (а). Например, вы хотите определить гравитацию, как силу, ускоряющую все объекты на 9.8 м/с в отрицательном направлении оси у, независимо от их массы. Используя второй закон Ньютона, умножим массу (т) на ускорение (а) для получения силы. Таким образом, для определения гравитации, используя массу объекта, хранимую в переменной Mass, вы можете использовать следующий код:
D3DXVECTOR3 vecGravity = D3DXVECTOR3(0.0f, -9.8f, 0.0f) * Mass;
А как насчет тех сил, которые ускоряют объекты без компенсирования их масс? Например, вы можете объявить следующую силу, ускоряющую объект массой 1 на 5.0 м/с2 в положительном направлении оси х:
D3DXVECTOR3 vecImplied = D3DXVECTOR3(5.0f, 0.0f, 0.0f);
Если вы попробуете приложить ту же силу к объекту массой 2, вы получите ускорение 2.5 м/с2 в положительном направлении х. Как я определил 2.5 м/с2? Просто - перевернул формулу F=ma:
а = F/m
Для расчета ускорения, накладываемого на скорость объекта, вам необходимо разделить вектор силы на массу объекта. Т. к. сила была 5.0 м/с , а масса была 2, тогда ускорение будет а = 5/2.
Подытожим: все прикладываемые силы представляют собой ускорение объекта единичной массы. Если вы хотите убедиться, что ускорение не зависит от массы объекта, умножьте вектор силы на массу объекта.
Двигаясь далее в примере, теперь вы имеете два вектора сил (гравитации и прикладываемой силы), которые вы хотите использовать для перемещения объекта.
D3DXVECTOR3 vecGravity = D3DXVECTOR3(0.0f, -9.8f, 0.0f) * Mass; D3DXVECTOR3 vecImplied = D3DXVECTOR3(5.0f, 0.0f, 0.0f);
Прежде чем вы наложите эти две силы на любое тело, соедините их в одну.
D3DXVECTOR3 vecForce = vecGravity + vecImplied;
Вы хотите работать с этой комбинированной силой? Далее в этой главе вы прочитаете о разнообразных силах и их вычислении. А пока что давайте предполагать, что мы преодолели все трудности и объединили силы в один вектор.
Как я замечал ранее, приложение силы к любой точке тела заставит его двигаться. На самом деле вам не нужно знать точку приложения силы, потому что тело в любом случае будет двигаться в направлении действия силы (или замедлятся, если сила противодействует движению).
Итак, используя две силы, объединенные в одну, вы можете линейно двигать твердое тело, прикладывая объединенную силу к вектору положения объекта. Предположим, что положение твердого объекта хранится в векторе vecPosition.
// Добавить вектор силы к вектору положения yecPosition += vecForce;
Я знаю, что некоторые из вас собираются остановить меня здесь. А что же с ускорением, о котором я говорил ранее? После того как я обратил на это внимание, как насчет того, чтобы принять время и скорость во внимание? Я знаю, что упоминал про физику, так что пришло время прояснить ситуацию.
У объекта есть линейная скорость, которая характеризуется быстротой и направлением движения. Разнообразные силы являются причиной ускорения. Модуль силы характеризует величину ускорения, в то время как направление вектора определяет, куда она приложена. Из-за того что объекты имеют массу, для получения "настоящего" значения ускорения необходимо соответственно масштабировать силы (или скорее равнодействующую всех сил). Таким образом, объекты с большей массой ускоряются меньше, чем менее массивные. Помните F=ma и a=F/m?
Возвращаясь к вектору силы тяжести, вы можете увидеть, что требуется ускорение 9.8 м/с , независимо от массы объекта. Это означает, что масштабирование силы на массу объекта, в соответствии с формулой a=F/m, так изменит силу тяжести, что ускорение не будет равным 9.8 м/с . Что же касается прикладываемой силы (5.0 м/с ), она также масштабируется в соответствии с a=F/m, так что если объект будет иметь массу отличную от 1, ускорение также будет отличаться от 5.0 м/с2.
Итак, возвращаясь к проблеме приложения сил к твердому телу, вы делите равнодействующую силу на массу и добавляете результат к линейной скорости твердого тела. Подождите - я забыл использовать время! Вы не просто масштабируете силу на массу, но и умножаете результирующий вектор (ускорения) на время, в которое вычисляется скорость. После этого можно применять эту линейную скорость, вычисленную с использованием времени, к телу для его перемещения (или замедления, в зависимости от направления прикладываемых сил).
Сохраните скорость в векторе vecVelocity и массу в вещественной переменной Mass. Ускорение не требует переменной, потому что вы непосредственно используете ее в скорости в сочетании с массой. Вам еще необходимо учитывать время (также хранимое в вещественной переменной Time), которое определяет изменение скорости за интервал времени (измеряемый в секундах), и сколько скорости применять к телу.
// vecVelocity = объект D3DXVECTOR3 // Mass = вещественная переменная
// vecForce = объект D3DXVECTOR3, содержащий вектор действующий силы
// Масштабировать силу (представляющую ускорение) на массу и // добавить ее непосредственно к скорости vecVelocity += Time * (vecForce / Mass) ;
// Применить скорость к перемещению vecPosition += Time * vecVelocity;
Теперь резюмируем все вышесказанное. Найдите равнодействующую всех прикладываемых сил. Масштабируйте ее вектор на массу объекта, умножьте на прошедшее время и добавьте результирующий вектор к вектору скорости объекта. Умножьте скорость на то же самое время и добавьте результат к вектору положения. Вот и все линейное движение!
А теперь пришло время перейти к рассмотрению вращательного движения.
Вращение твердых тел
Как и линейное, вращательное движение имеет скорость, ускорение и импульс, определяющие направление и быстроту вращения твердого тела. Но в отличие от линейного движения, использующего линейные силы для определения направления движения, вращательные силы используют так называемый угловой момент (или, для краткости, момент) для определения вращения тела в зависимости от приложенной силы. Момент, определяемый как вектор, непосредственно влияет на угловую скорость, которая в свою очередь влияет на угловой момент.
Масса объекта влияет на количество скорости, накладываемой на фактическое движение тела, и также используется при вращении объектов. Это объявляет тему -инерция. Инерция определяет величину силы, прикладываемой для вращения объекта вокруг осей относительно точки приложения силы.
Все правильно; та же самая сила, которая являлась причиной линейного движения, является причиной вращательного. Единственное различие состоит в том, что имеет значение точка приложения силы. По мере добавления сил, действующих на тело, вам необходимо следить за точками их приложения и за изменением осей вращения тела.
Например, если толкнуть один угол тела, оно будет вращаться в одном направлении; если же толкнуть другой угол - то в другом. Как же узнать в каком направлении и как быстро будет вращаться тело? Помните, ранее в этой главе я рассказывал об использовании кватернионов? Вы будете использовать их для слежения за направлением и углом объектов! Вы просто сойдете с ума, когда увидите насколько удобно их использовать.
Предположим, вы хотите приложить силу к твердому телу - линейную силу, создающую вращательный момент. Этот момент является направляющим вектором, но вместо того чтобы указывать направление движения, фактически задает направление вращательной оси (совсем как кватернионы используют осевые векторы для ориентирования объектов). По мере того как вы будете добавлять силы, вектор момента может менять направление, таким образом меняя оси. Это замечательно работает, потому что результирующая величина момента (результирующего момента), влияющего на тело, является простой комбинацией всех моментов, совсем как с линейными силами.
Единственным возникающим вопросом является вопрос: а как преобразовать силу в момент? Посмотрите на рис. 7.7, на котором изображено простое твердое тело. Стрелочкой показана линейная сила, приложенная к точке твердого тела.
Конечно же, твердое тело, изображенное на рис. 7.7, будет двигаться в направлении действия приложенной силы, а что же с вращением? Тело определенно будет вращаться, потому что сила приложена не к центральной точке тела.

Рис. 7.7. Приложенная сила влияет не только на линейное, но и на вращательное движение
Для расчета вектора момента вычислите векторное произведение линейного вектора силы и вектора, соединяющего центр тела с точкой приложения силы. Результирующий вектор направлен в том же направлении, что и ось вращения, прямо как в кватернионах! Посмотрите на рис. 7.8, чтобы понять, что я имею ввиду. Используя то же самое тело, что и на рис. 7.7, я считаю векторное произведение, которое определяет ось, относительно которой будет вращаться объект.
Рис. 7.8. Вектор силы и вектор, соединяющий центр с точкой приложения, используются для вычисления оси вращения путем векторного умножения
После того как вы определили ось вращения, как узнать сколько приложить силы для вращения тела? Совсем как масса объекта определяла величину прилагаемой силы для фактического движения объекта, инерция тела используется для определения вращательного момента.

На самом деле инерция состоит из трех компонентов, по одному для каждой оси вращения (х, у и z). Эти три компонента называются скалярами инерции и используются для определения еще трех значений, обычно называемых моментами инерции.
Эти значения моментов инерции являются аналогами масс тела - чем большее значение, тем меньший момент применяется к телу. Чем меньше масса твердого тела, тем больший момент накладывается на него.
Значения скаляров и моментов инерции зависят от формы и размеров твердого тела. Мы уже решили использовать ограничивающие параллелепипеды для представления твердых тел, так что нам необходимо следить только за шириной, глубиной и высотой тела. Т. к. для хранения размера твердого тела используется вектор (vecSize), можно говорить, что компонента х это ширина, у - высота, z - глубина.
Используя эти три компоненты (х, у и z) и массу объекта (Mass), можно определить скаляры инерции следующим образом:
/ / Скаляр инерции по оси X
float xs = vecSize.x * vecSize.x;
// Скаляр инерции по оси Y
float ys = vecSize.y * vecSize.y;
// Скаляр инерции по оси Z
float zs = vecSize.z * vecSize.z;
После этого вы можете вычислить значения моментов инерции, используя только что полученные скаляры инерции. Эти скаляры моментов инерции представляют расширение вашего тела по каждой оси, масштабированное на массу тела. Например, момент инерции для оси х является комбинацией скаляров инерции у и z, умноженной на массу тела. Вот как вычислять значения этих трех моментов инерции:
// Ixx = момент инерции по оси х float Ixx = Mass * (ys + zs);
// Iyy = момент инерции по оси у float Iyy = Mass * (xs + zs) ;
// Izz = момент инерции по оси z float Izz = Mass * (xs + yz);
Набор этих трех моментов тензоров инерции известен как тензор момента инерции2, или для краткости - тензор инерции. Тензор инерции составляется при помощи матрицы 3x3, которая имеет следующий вид:
2. Тензор — некое обобщенное понятие вектора. Вектор — тензор первого порядка, скаляр — тензор нулевого порядка. Величина, которая при повороте системы координат преобразуется как произведение двух компонент вектора, называется тензором второго ранга. Таким образом, тензор инерции является тензором второго порядка. - Примеч. науч. ред.
0 Іуу 0
0 0
Хотя тензор инерции и является важным аспектом определения накладываемого момента инерции, на самом деле вам необходимо использовать обратный тензор (по причинам, о которых я расскажу позже). Обратный тензор инерции имеет следующий вид:
1/1хх 0 0 0 1/1уу 0
0 0
Вы же знаете, что вся эта теория инерции рассказывается вам с умыслом, не так ли? Конечно знаете! После объединения всех векторов моментов, действующих на тело, в один результирующий, вы добавляете его к угловому моменту объекта (принимая во внимание значение времени). Этот угловой момент, также как и вращательный, задан в мировых координатах. К сожалению, вы не можете использовать мировые координаты, вам необходимо преобразовать их к локальным координатам тела.
Это одна из причин, по которой я использую обратную матрицу тензора инерции. Видите ли, необходимо задавать угловую скорость в пространстве тела. (Другими словами, тело должно вращаться относительно своего а не центра мира.) Дляпреобразования координат углового момента (из мировых координат) в координаты угловой скорости (которые в пространстве тела), учитывая момент инерции, вам необходимо умножить обратный тензор инерции на положение твердого тела. После этого умножьте полученную матрицу на транспонированное положение твердого тела, получая таким образом преобразование, учитывающее преобразования пространств тела и мира и моментов инерции. Используя полученное преобразование вы можете перевести вектор углового момента в угловую скорость.
После этого вы используете полученную угловую скорость для вычисления вращения, которое прикладывается к твердому телу. Совсем как линейная скорость масштабируется по времени для вычисления конечной скорости через определенный интервал времени, угловой момент также масштабируется. Вектор, преобразованный в угловую скорость, масштабируется по времени и применяется к значениям углового вращения кватерниона (который представляет вращение тела).
Хорошо, я уже достаточно долго не приводил Никаких кодов, так что позвольте мне рассказать, как создавать обратную матрицу тензора инерции и использовать ее для вращения твердого тела.
II vecSize = вектор, содержащий размер ограничивающего параллелепипеда твердого тела II Mass = масса тела
II Вычислить скаляры инерции float xScalar = vecSize.x * vecSize.x; float yScalar = vecSize.y * vecSize.y; float zScalar = vecSize.z * vecSize.z;
II Создать матрицу и вычислить обратный тензор инерции D3DXMATRIX matlnvInertiaTensor; D3DXMatrixIdentity(&matInvInertiaTensor);
matInvInertiaTensor._11 = 1.0f I (Mass * (yScalar + zScalar)); matInvInertiaTensor._22 = 1.0f I (Mass * (xScalar + zScalar)); matInvInertiaTensor._33 = 1.0f I (Mass * (xScalar + yScalar)) ;
Теперь предположим, что у вас есть вектор, содержащий трехмерные координаты тела и кватернион, представляющий его ориентацию. Сперва необходимо приложить силу к одному из углов. Давайте приложим вектор силы (10,0, 40) к пятой точке твердого тела. Необходимо сразу заметить, что координаты пятой точки являются мировыми, так что используйте вектор положения из массива vecWorldPoints в следующих вычислениях.
// уесРогсе = вектор прикладываемой силы (в данном случае 10,0,40) // уесМотепРшп = угловой момент тела
// дшаРОгіепРаРіоп = кватернион, содержащий ориентацию объекта // matInvIneгtiaTensoг = обратная матрица тензора инерции
// Получить координаты точки приложения силы (точка 5) РЗРХУЕСТОРЗ vecPos = vecWoгldPoints[5];
// Вычислить вектор их центра тела к точке приложения РЗРХУЕСТОРЗ уесР^С = vecPos - vecPosition,•
// Вычислить векторное произведение вектора силы и vecPtoC. // Результирующий вектор является моментом. РЗРХУЕСТОРЗ vecToгque,•
D3DXVec3Cгoss(&vecToгque, &vecPtoC, &vecРoгce) ;
// Добавить момент к угловому моменту vecMomentum += vecToгque,•
// Создать вращательную матрицу преобразования из кватерниона D3DXMATRIX matOгientation,•
D3DXMatгixRotationQuateгnion(&matOгientation, \ &quatOгientation);
// Транспонировать преобразование, чтобы сделать его левосторонним D3DXMatгixTгanspose(&matOгientation, &matOгientation);
// Создать матрицу, переводящую из мирового пространства в
// пространство тела. Используется для вычисления угловой скорости
D3DXMATRIX mat-Conversion, matTransposedOrientation; D3DXMatrixTranspose(&matTransposedOrientation,&matOrientation) ; matConversion = matOrientation * \
matlnvInertiaTensor * \
matTransposedOrientation;
Теперь вы имеете преобразование, используемое для перевода углового момента в угловую скорость. Вы можете наложить это преобразование на момент для получения скорости:
// Использовать матрицу преобразования для перевода момента в скорость D3DXVec3TransformCoord(&vecAngularVelocity, \ &vecMomentom, &matConversion) ;
Возвращаясь к работе со временем в предыдущих вычислениях, вам необходимо умножить вращательный момент, накладываемый на момент, на количество прошедшего времени.
vecMomentum += (Time * vecTorque) ;
Используя только что посчитанный момент, вычислите угловую скорость, используя виденный вами длинный кусок кода. Имея угловую скорость, вы можете вычислить ориентацию, также масштабированную по времени.
// Масштабировать угловую скорость на величину прошедшего времени D3DXVECTOR3 vecVelocity = Time * vecAngularVelocity;
// Применить скорость к ориентации quatOrientation.w -= 0.5f *
quatOrientation.x * vecVelocity.x +
quatOrientation.y * vecVelocity.y +
quatOrientation.z * vecVelocity.z); quatOrientation.x += 0.5f *
quatOrientation.w * vecVelocity.x -
quatOrientation.z * vecVelocity.y +
quatOrientation.y * vecVelocity.z); quatOrientation.y += 0.5f *
quatOrientation.z * vecVelocity.x +
quatOrientation.w * vecVelocity.y -
quatOrientation.x * vecVelocity.z); quatOrientation.z += 0.5f *
quatOrientation.x * vecVelocity.y -
quatOrientation.y * vecVelocity.x +
quatOrientation.w * vecVelocity.z);
Я вычисляю ориентацию, учитывая скорость, основанную на времени. Помните, что скорость была посчитана из момента, а он в свою очередь из вращательного момента. Вращательный момент содержал ось вращения, совсем как кватернион. Обычно вы просто перемножаете скорость и кватернион, после чего разделяете результат на такие части:
ql = 1|2 vt q
Наконец, после приложения силы к твердому телу вы можете вычислить угол и ось вращения. Теперь вы знаете достаточно, чтобы двигать и вращать твердые тела!
Хорошо, я признаю, что немного быстро и в вольном стиле излагал материал в данном разделе. Но у меня были веские причины - я не хотел загружать вас множеством формул и вычислений. Раздел физики твердого тела существует уже давно, и по нему написано множество литературы. Я думаю, что немногие используют физику твердого тела из-за сложности ее математики. Я хочу, чтобы любой мог понять основы динамики твердого тела, не углубляясь в математику. По этой причине я пропустил большинство формул, которые могли бы пригодиться знающим читателям. Как я уже замечал, этот раздел существует долгое время, за которое было написано несколько замечательных книг и статей о нем. Особенно полезен набор статей Chris Hecker'a Behind the Screen series on physics. Вы можете найти эти статьи на домашней странице Chris'a, http://www.d6.com/users/checker.
Теперь идет самая забавная часть - создание набора сил, действующих на твердое тело и заставляющих его двигаться.
⇐Расположение и ориентирование твердых тел || Оглавление || Использование сил для создания движения⇒