@inf1k

Импорт SMD анимации, как получить нужный кватернион?

Настраиваю импорт\экспорт .smd файлов в 3д редактор. Удалось импортировать reference файл, и получить верные координаты костей в глобальном мире. Фрагмент кода:

fscanf(pFile, "%i %f %f %f %f %f %f",
		&iBoneIndex, &vecBonePos.x, &vecBonePos.z, &vecBonePos.y,
		&vAngles.x, &vAngles.z, &vAngles.y);
				
	vecBonePos.z = -vecBonePos.z;
	vAngles.z = -vAngles.z;

	vAngles = vec3(DEGREES(vAngles.x), DEGREES(vAngles.y), DEGREES(vAngles.z));
	vec3 vBonePos = vec3(vecBonePos.x, vecBonePos.y, vecBonePos.z);
	matrix mX, mY, mZ;
	mX.setAngles(vec3(vAngles.x, 0, 0));
	mY.setAngles(vec3(0, vAngles.y, 0));
	mZ.setAngles(vec3(0, 0, vAngles.z));
	matrix mRot; // local matrix
	mRot = mY * mZ * mX; //YZX rotation order
	mRot.setPos(vBonePos);
	aLocalMatrices.add(mRot);
				
	if (GetBoneAt(i)->m_iParent == -1)
		aGlobalMatrices[i] = mRot;
	else
		aGlobalMatrices[i] = aGlobalMatrices[GetBoneAt(i)->m_iParent] * mRot;
	//set position
	GetBoneAt(i)->m_vPos = Vector(aGlobalMatrices[i].getPos().x, aGlobalMatrices[i].getPos().y, aGlobalMatrices[i].getPos().z);

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

Анимация у меня происходит следующим образом:
matrix m = getBoneMatrix(aBones[i], g_pAnimationEditor->m_flAnimPos );  // тут происходит интерполяция
		vec3 vRootOffset = getRootOffset(g_pAnimationEditor->m_flAnimPos); // root bone offset 
		if (aBones[i]->m_iParent != -1)
		{
			vec3 vPos = g_pAnimationEditor->m_aRefPoses[i]; //bone pos in global space
			vec3 vParentPos = vec3(aBones[aBones[i]->m_iParent]->m_vPos.x, aBones[aBones[i]->m_iParent]->m_vPos.y, aBones[aBones[i]->m_iParent]->m_vPos.z); //parent bone pos in global space
			vec3 vLocalPos = g_pAnimationEditor->m_aRefPoses[i] - g_pAnimationEditor->m_aRefParentPoses[i]; // local bone pos in parent space
			matrix mParent = m_aCurrentState[aBones[i]->m_iParent]; // parent rotation matrix
			mParent.setPos(vec3()); //remove pos
			m = mParent * m;
			vPos = m * vPos;
			vec3 vNewBonePos = vParentPos + mParent * vLocalPos; // new  bone location 
		        aBones[i]->m_vPos = Vector(vNewBonePos.x, vNewBonePos.y, vNewBonePos.z); //adding root offset here because it resends data to gpu

			m.setPos(vNewBonePos - vPos); //offset
		}
		m.setPos(m.getPos() + vRootOffset); //add root offset


И при рендере конечная позиция кости расчитывается так:
m = m_aCurrentState[i];
    glVertex3fv(m * m_aRefPoses[i]); // RefPos -> initial bone pos in global space


Проблема в том, что мне не удается получить нужный кватернион из углов Эйлера. Мне для моей анимации нужны всего лишь reference bone pos и кватернион для поворота в local space.

P.S.
Редактирование кадра производится следующим образом:

vec3 vFrontAxis = (vEnd - vStart).getNormalized();
	matrix mBoneMatrix = m_aCurrentState[pSelectedBone->m_iParent];
	mBoneMatrix.setPos(vec3());
	mBoneMatrix.invert();
	vFrontAxis = mBoneMatrix * vFrontAxis;
	int iCurFrame = m_iCurrentFrame;
	m_aFrames[iCurFrame].Get(pSelectedBone)->m_quat = m_aFrames[iCurFrame].Get(pSelectedBone)->m_quat * quat().fromAxisAngle(vFrontAxis, flDeltaX); // flDeltaX = mouse.x - lastmouse.x
  • Вопрос задан
  • 43 просмотра
Пригласить эксперта
Ответы на вопрос 1
@AlexSku
Программист по автоматике
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы