/****************************************************************************************************

		I3DExSkinningAlgorithm.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Pierre-Sylvain
		Date:	01/05/2007

****************************************************************************************************/

#ifndef __I3DExSkinningAlgorithm__
#define __I3DExSkinningAlgorithm__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "APITypes.h"
#include "IExtension.h"
#include "InterfaceIDs.h"
#include "Vector3Fwd.h"


//****** Globally Unique Ids *************************************************

MCDEFINE_GUID_H(IID_I3DExSkinningAlgorithm);
MCDEFINE_GUID_H(IID_I3DExSkinningAlgorithmContext);


struct I3DExSkinningAlgorithm;
struct I3DShJoint;
struct I3DShInstance;
class  TVertexSkinInfo;
class  TBitArray;


struct IGlobalDeformerHelper
{
	// ****************************************************************************
	//								DeformPointInGlobal
	//
	// Apply the global deformers to the given point in global coordinates
	//
	virtual void			MCCOMAPI DeformPointInGlobal(TVector3& point) = 0;
};


struct I3DExSkinningAlgorithmContext : public IMCUnknown
{
	// ****************************************************************************
	//								GetSkinningAlgorithm
	//
	// Returns the skinning algorithm associated with this context.
	//
	virtual I3DExSkinningAlgorithm*	MCCOMAPI GetSkinningAlgorithm() = 0;

	virtual void			MCCOMAPI ValidateSkinContext() = 0;
	virtual boolean			MCCOMAPI IsSkinContextValid(TBitArray* invalidJoints = NULL) = 0;
	virtual void			MCCOMAPI DestroySkinContext() = 0;

	// ****************************************************************************
	//								SkinVertex
	//
	// Skin a given vertex.
	//
	// \param vertexInfo		The vertex skin infos (the weights)
	// \param vertex			The position in local space.
	// \param globalDeformer	A helper to allow the function to apply the global deformers.
	//							If this pointer is null that means that no deformers need
	//							to be applyied to the vertex.
	//
	virtual void			MCCOMAPI SkinVertex(const TVertexSkinInfo& vertexInfo, TVector3& vertex, IGlobalDeformerHelper* globalDeformer) = 0;

	// ****************************************************************************
	//								GetJoints
	//
	// Returns the array of joints associated with this skinning context.
	//
	virtual const TMCPtrArray<I3DShJoint>&	MCCOMAPI GetJoints() = 0;

	// ****************************************************************************
	//								GetInstance
	//
	// Returns the instance associated with this skinning context.
	//
	virtual I3DShInstance*	MCCOMAPI GetInstance() = 0;

	// ****************************************************************************
	//								GetFatherJointIndex
	//
	// Returns father joint index of the given joint index
	//
	// \param jointIndex	joint index of the son
	//
	virtual const int32		MCCOMAPI GetFatherJointIndex(int32 jointIndex) = 0;

};


struct I3DExSkinningAlgorithm : public IMCUnknown
{
	// ****************************************************************************
	//								Initialize
	//
	// Initialize the skinning algorithm.
	//
	// \param instance		Instance of the skinned object
	// \param joints		Array of joints to use
	//
	virtual void			MCCOMAPI Initialize(I3DShInstance* instance, const TMCPtrArray<I3DShJoint>& joints) = 0;

	// ****************************************************************************
	//								Reset
	//
	// Resets the skinning algorithm and cleanup any stored information.
	//
	virtual void			MCCOMAPI Reset() = 0;

	virtual void			MCCOMAPI GetJointsInverseReferenceTransforms(TMCArray<TTransform3D>& outTransforms)	= 0;
	virtual void			MCCOMAPI SetJointsInverseReferenceTransforms(const TMCArray<TTransform3D>& inTransforms) = 0;
	virtual void			MCCOMAPI GetInstanceGlobalReferenceTransform(TTransform3D& outTransform) = 0;
	virtual void			MCCOMAPI SetInstanceGlobalReferenceTransform(const TTransform3D& inTransform) = 0;

	// ****************************************************************************
	//								CreateSkinningAlgorithmContext
	//
	// Creates a skinning algorithm context for the given instance and joint array.
	//
	// \param context		The created context.
	// \param instance		The instance
	// \param joints		The joint array
	//
	virtual void			MCCOMAPI CreateSkinningAlgorithmContext(I3DExSkinningAlgorithmContext** context, I3DShInstance* instance, const TMCPtrArray<I3DShJoint>& joints) = 0;

	// ****************************************************************************
	//								ConvertSkinningData
	//
	// Converts the vertex weight to the standard format which is one weight per joint.
	//
	// \param vertexInfo		The current vertex weights
	// \param outConvertedData	The converted weights
	//
	virtual void			MCCOMAPI ConvertSkinningData(const TVertexSkinInfo& vertexInfo, TVertexSkinInfo& outConvertedData) = 0;

	virtual void			MCCOMAPI PreInitilizeSkinningData(boolean forceRecompute=false) = 0;
	virtual void			MCCOMAPI InitilizeSkinningData(const TVector3& vertex, TVertexSkinInfo& vertexInfo) = 0;
	virtual void			MCCOMAPI PostInitilizeSkinningData() = 0;

	// ****************************************************************************
	//								CanRecomputeVertexWeights
	//
	// Return true if the algorithm is able to recompute the vertex weights.
	//
	virtual boolean			MCCOMAPI CanRecomputeVertexWeights() = 0;
};


#endif
