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

В разделе "Обработка движений твердого тела" вы видели, как прикладывать векторы силы и моменты к линейной скорости и угловому моменту для создания движения. В функции cRagdoll::Resolve я просто повторяю все прочитанное вами в том разделе.

Вы заметите, что значения положения, ориентации, скорости и момента хранятся в классе состояния кости cRagdollBoneState. Эти векторы используются при разрешении. Для вызова Integrate необходимо задать в качестве параметров обрабатываемую кость и время обработки (прошедшее время).

void cRagdoll::Integrate(DWORD BoneNum, float Elapsed) {

// Получить указатель на кость cRagdollBone *Bone = Sm_Bones[BoneNum] ;

// Получить указатели на состояния cRagdollBoneState *State = &Bone->m_State;

После того как вы получили указатель на класс кости (и указатель на объект состояния кости), вы вычисляете новое положение кости, основываясь на линейной скорости, изменение углового момента, основываясь на моменте, и изменение линейной скорости, основываясь на величине силы (масштабированной на массу объекта).

/ / Сложить положения

State->m_vecPosition += (Elapsed*State->m_vecLinearVelocity); // Сложить угловой момент

State->m_vecAngularMomentum += (Elapsed * Bone->m_vecTorque); // Сложить линейную скорость

State->m_vecLinearVelocity += Elapsed * Bone->m_vecForce / \ Bone->m_Mass;

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

// Сложить ориентацию кватернионов

D3DXVECTOR3 vecVelocity = Elapsed * State->m_vecAngularVelocity;

State->m_quatOrientation.w -= 0.5f *

(State->m_quatOrientation.x * vecVelocity.x + State->m_quatOrientation.y * vecVelocity.y + State->m_quatOrientation.z * vecVelocity.z);

State->m_quatOrTentation.x += 0.5f *

(State->m_quatOrientation.w * vecVelocity.x -State->m_quatOrientation.z * vecVelocity.y + State->m_quatOrientation.y * vecVelocity.z);

State->m_quatOrientation.y += 0.5f *

(State->m_quatOrientation.z * vecVelocity.x + State->m_quatOrientation.w * vecVelocity.y -State->m_quatOrientation.x * vecVelocity.z);

State->m_quatOrientation.z += 0.5f *

(State->m_quatOrientation.x * vecVelocity.y -State->m_quatOrientation.y * vecVelocity.x + State->m_quatOrientation.w * vecVelocity.z);

// Нормализовать кватернион (получая единичный кватернион) D3DXQuaternionNormalize(SState->m_quatOrientation, &State->m_quatOrientation) ;

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

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

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

// Заставить разрешение вращения

if(BoneNum && Bone->m_ResolutionRate != 0.0f) {

// сферическая интерполяция от текущей ориентации к начальной D3DXQUATERNION quatOrientation = \

Bone->m_ParentBone->m_State.m_quatOrientation * \ Bone->m_quatOrientation; D3DXQuaternionSlerp(&State->m_quatOrientation, \ &State->m_quatOrientation, \ &quatOrientation, \ Bone->m_ResolutionRate) ;

}

Двигаемся дальше. Оставшийся код функции Integrate создает матрицу преобразования, которая потом используется для преобразования точек костей твердого тела и создания угловой скорости. Т. к. мы работаем с левосторонней системой координат, после создания матрицы преобразования необходимо ее транспонировать при помощи функции D3DXMatrixRotationQuaternion. Этот шаг обсуждался ранее.

// Вычислить новую ориентацию при помощи матрицы преобразования // полученной из только что посчитанного кватерниона D3DXMatrixRotationQuaternion(&State->m_matOrientation,

&State->m_quatOrientation); D3DXMatrixTranspose(&State->m_matOrientation,

&State->m_matOrientation);

// Вычислить суммарный тензор мировой инерции D3DXMATRIX matTransposedOrientation;

D3DXMatrixTransposw(&matTransposedOrientation, &State->m_matOrientation);

State->m_matInvWorldInertiaTensor = State->m_matOrientation * Bone->m_matInvInertiaTensor * matTransposedOrientation;

/ / Вычислить новую угловую скорость State->m_vecAngularVelocity = Transform(&State->m_vecAngularMomentum,

&State->m_matInvWorldInertiaTensor);

}

На данный момент мы рассчитали движение твердого тела, а теперь пришло время обрабатывать столкновения.

Установка сил || Оглавление || Обработка столкновений