// KINEDumpFrameRotationsTEP.cpp: implementation of the CKINEDumpFrameRotationsTEP class.
//
//////////////////////////////////////////////////////////////////////

#include "KINEDumpFrameRotationsTEP.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

#include "..\..\Rasterizer\MathLibrary.h"

#include "KINEExportClass.h"

CKINEDumpFrameRotationsTEP::CKINEDumpFrameRotationsTEP()
{

}

CKINEDumpFrameRotationsTEP::~CKINEDumpFrameRotationsTEP()
{

}

int CKINEDumpFrameRotationsTEP::callback(INode *lpNode)
{
	INode* pNode = lpNode;
	if (pNode->IsRootNode())
		return TREE_ABORT;

	if (::FNodeMarkedToSkip(pNode))
		return TREE_CONTINUE;


	int nNode = ::GetIndexOfINode(pNode);

	// The model's root is a child of the real "scene root"
	INode *pParentNode = pNode->GetParentNode();

	// Get Node's "Local" Transformation Matrix
	Matrix3 mat3NodeTM	 = pNode->GetNodeTM(m_tvToDump);
	Matrix3 mat3ParentTM = pParentNode->GetNodeTM(m_tvToDump);

	mat3NodeTM.NoScale();		// Clear these out because they apparently
	mat3ParentTM.NoScale();		// screw up the following calculation.

	Matrix3 mat3NodeLocalTM	= mat3NodeTM * Inverse(mat3ParentTM);

	Point3 rowTrans = mat3NodeLocalTM.GetTrans();

	// Get the rotation (via decomposition into "affine parts", then quaternion-to-Euler)
	// Apparently the order of rotations returned by QuatToEuler() is X, then Y, then Z.
	AffineParts affparts;
	float		rgflXYZRotations[3];

	decomp_affine(mat3NodeLocalTM, &affparts);
	QuatToEuler(affparts.q, rgflXYZRotations);

	float xRot = rgflXYZRotations[0];		// in radians
	float yRot = rgflXYZRotations[1];		// in radians
	float zRot = rgflXYZRotations[2];		// in radians

	/////////////////////////////////////////////////////////////////////////////////////
	VECTOR3D translate, rotate;

	// Get rotations in the -2pi...2pi range
	rotate.x = ::FlReduceRotation(xRot);
	rotate.y = ::FlReduceRotation(yRot);
	rotate.z = ::FlReduceRotation(zRot);

	translate.x = rowTrans.x;
	translate.y = rowTrans.y;
	translate.z = rowTrans.z;

	///////////////////////////////////////////////////////////////////////////////////////////////
	// Convenient time to cache this
	CKINEExportClass* pExportClass = (CKINEExportClass*) m_pExportClass;
	CMaxNodeKey* pMaxNodeKey = pExportClass->GetKeyFrame()->GetNodeKey(nNode);
	if (!pMaxNodeKey)
		return TREE_ABORT;
	
	DWORD dwFrame = (m_tvToDump - pExportClass->m_tvStart) / m_dwTicksPerFrame;
	LPKINEMATICS pKinematices = pMaxNodeKey->GetKinematices(dwFrame);

	CopyVector(&translate, &pKinematices->translate);

	ClipRotations(&rotate);
	AngleQuaternion(&rotate, &pKinematices->quaternion);

	///////////////////////////////////////////////////////////////////////////////////////////////
	return TREE_CONTINUE;
}
