// MESHDumpNodesTEP.cpp: implementation of the CMESHDumpNodesTEP class.
//
//////////////////////////////////////////////////////////////////////

#include "MESHDumpNodesTEP.h"

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

#include "MESHExportClass.h"

CMESHDumpNodesTEP::CMESHDumpNodesTEP()
{

}

CMESHDumpNodesTEP::~CMESHDumpNodesTEP()
{

}

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

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

	// Get node's parent
	INode* pParentNode = pNode->GetParentNode();
	BOOL bRootNode = pParentNode->IsRootNode();

	// Get pre-stored "index"
	int nNode = ::GetIndexOfINode(pNode);
	int nParentNode = ::GetIndexOfINode(pParentNode, !bRootNode);

	// Convenient time to cache this
	CMESHExportClass* pExportClass = (CMESHExportClass*) m_pExportClass;
	CMaxKeyNode* pMaxKeyNode = pExportClass->GetMeshFrame()->GetKeyNode(nNode);
	if (!pMaxKeyNode)
		return TREE_ABORT;

	pMaxKeyNode->SetParent(bRootNode ? UNDESIRABLE_NODE_MARKER : nParentNode);

	// Root node has no parent, thus no translation
	if (bRootNode)
		pMaxKeyNode->SetParent(-1);


	// Get Node's time-zero Transformation Matrices
	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;

	///////////////////////////////////////////////////////////////////////////////////////////////

	// Quaternion
	ClipRotations(&rotate);
	AngleQuaternion(&rotate, &pMaxKeyNode->m_kinematics.quaternion);

	// Translate
	CopyVector(&translate, &pMaxKeyNode->m_kinematics.translate);


	// Rotation
	pMaxKeyNode->m_rotate.x = rotate.x * (180.0f / Q_PI);
	pMaxKeyNode->m_rotate.y = rotate.y * (180.0f / Q_PI);
	pMaxKeyNode->m_rotate.z = rotate.z * (180.0f / Q_PI);
	
	///////////////////////////////////////////////////////////////////////////////////////////////

	return TREE_CONTINUE;
}
