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

		I3DExConstraint.h

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

		I3DExConstraint definition

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		09/17/99	Mathieu		ResetConstraint(), needed so the object won't move when we change the axis
		09/09/99	Guillaume	Changed the class and file names
		08/26/99	cph			Added family ids

*****************************************************************************************/
#ifndef __I3DEXCONSTRAINT__
#define __I3DEXCONSTRAINT__

#if CP_PRAGMA_ONCE
#pragma once
#endif

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

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

MCDEFINE_GUID_H(IID_I3DExConstraint);
MCDEFINE_GUID_H(IID_I3DExNewConstraint);
MCDEFINE_GUID_H(IID_I3DExNewConstraint2);

//****** Family Id *************************************************

const FourCharT kConstraintFamilyID = kRID_ConstraintFamilyID;


/*****************************************************************************\
*  I3DExConstraint                                                            *
*                                                                             *
*  Constraints between Tree Elements                                          *
*                                                                             *
\*****************************************************************************/

enum ELimitType
{
	eLocked = 0,
	eLimited = 1,
	eFree = 2,
	eMax = 0x7FFF
};

enum EFreedomDegree
{
	eXTranslation		= 0x10,
	eYTranslation		= 0x11,
	eZTranslation		= 0x12,
	eXRotation			= 0x13,
	eYRotation			= 0x14,
	eZRotation			= 0x15,
	eMaxFreedomDegree	= 0x7FFF
};

/// \addtogroup ExternalInterface
/// \{

/// I3DExConstraint provides constraints between Tree Elements. A constraint, known as a link in RDS,
/// defines motion links between Tree Elements. It allows you to define "mechanical" constrains (degrees of freedom)
/// between one Tree Element and its father.
///
struct I3DExConstraint: public IMCUnknown
{
	/// Returns the number of degrees of freedom. Because the freedom value can be limited,
	/// you have to give the range of values. This range is defined as a range of increment/decrement
	/// around the value.
	virtual int16 MCCOMAPI GetNbrFreedom() const = 0;

	/// Modify the value of a degree of freedom by adding an increment
	///
	/// \param index The degree of freedom \see EFreedomDegree
	/// \param increment The increment value
	///
	virtual MCCOMErr MCCOMAPI IncrementFreedomValue(int16 index, real& increment) = 0;

	/// Returns the constraint for a given degree of freedom.
	///
	virtual MCCOMErr MCCOMAPI GetMotionLimit (int16 index, ELimitType& limit) const = 0;

	/// Returns the maximum range of increment and decrement for a given degree of freedom.
	///
	/// \param index The index of the degree of freedom
	/// \param min The minimum value
	/// \param max The maximum value
	///
	virtual MCCOMErr MCCOMAPI GetFreedomRange(int16 index, real& min, real& max) const = 0;


	/// Get the current value of the given freedom
	///
	/// \param index	The degree of freedom \see EFreedomDegree
	/// \param outValue The value of the freedom
	///
	virtual MCCOMErr MCCOMAPI GetFreedomValue(int16 index, real& outValue) const = 0;

	///Returns the order used to apply the different rotations
	virtual MCCOMErr MCCOMAPI GetRotationsOrder	(EEulerAnglesOrder& outOrder) const = 0;

	///Fix for the axis constraint that rotates its Gimbal coordinates.
	virtual MCCOMErr MCCOMAPI GetGimbalToLocalRotation	(TMatrix33& outRotation) const = 0;

	/// Returns the rotation matrix and translation vector due to the freedom values.
	/// \note When the freedom values are initialized the function GetTransform must return
	/// the identity matrix for the rotation and a null vector for the translation.
	///
	/// \param transform A reference to a transform.
	///
	virtual MCCOMErr MCCOMAPI GetTransform(TTransform3D& transform) const = 0;

	/// To allow the inverse kinematics mechanism to work with a constraint, implement the
	/// GetTransfromPartialDerivate() function. A partial derivative transformation is a transformation
	/// where each element is derived by a freedom degree.
	///
	/// \param index The degree of freedom used to derivate the transform.
	/// \param transform The partial derivative of the transform.
	///
	virtual MCCOMErr MCCOMAPI GetTransformPartialDerivate(int16 index, TTransform3D& transform) const = 0;

	/// Returns the second order partial derivative of the transform. A partial derivative
	/// transformation is a transformation where each element is derived by a freedom degree.
	///
	/// \param index1 The first degree of freedom used to derivate the transform.
	/// \param index2 The second degree of freedom used to derivate the transform.
	/// \param transform The partial derivative of the transform.
	///
	virtual MCCOMErr MCCOMAPI GetTransformSecondPartialDerivative (int16 index1, int16 index2, TTransform3D& transform) const = 0;

	/// Sets the transformation matrix.
	///
	virtual MCCOMErr MCCOMAPI SetTransform(TTransform3D& transform) = 0;
};



struct I3DExNewConstraint : public IMCUnknown
{
	/// Returns the number of degrees of freedom. Because the freedom value can be limited,
	/// you have to give the range of values. This range is defined as a range of increment/decrement
	/// around the value.
	virtual int16 MCCOMAPI GetNbrFreedom() const = 0;

	/// Modify the value of a degree of freedom by adding an increment
	///
	/// \param index The degree of freedom \see EFreedomDegree
	/// \param increment The increment value
	///
	virtual MCCOMErr MCCOMAPI IncrementFreedomValue(int16 index, real& increment) = 0;

	/// Returns the constraint for a given degree of freedom.
	///
	virtual MCCOMErr MCCOMAPI GetMotionLimit (int16 index, ELimitType& limit) const = 0;

	/// Returns the maximum range of increment and decrement for a given degree of freedom.
	///
	/// \param index The index of the degree of freedom
	/// \param min The minimum value
	/// \param max The maximum value
	///
	virtual MCCOMErr MCCOMAPI GetFreedomRange(int16 index, real& min, real& max) const = 0;

	/// Get the current value of the given freedom
	///
	/// \param index	The degree of freedom \see EFreedomDegree
	/// \param outValue The value of the freedom
	///
	virtual MCCOMErr MCCOMAPI GetFreedomValue(int16 index, real& outValue) const = 0;

	/// To allow the inverse kinematics mechanism to work with a constraint, implement the
	/// GetTransfromPartialDerivate() function. A partial derivative transformation is a transformation
	/// where each element is derived by a freedom degree.
	///
	/// \param index The degree of freedom used to derivate the transform.
	/// \param transform The partial derivative of the transform.
	///
	virtual MCCOMErr MCCOMAPI GetTransformPartialDerivate(int16 index, TTransform3D& transform) const = 0;

	/// Returns the second order partial derivative of the transform. A partial derivative
	/// transformation is a transformation where each element is derived by a freedom degree.
	///
	/// \param index1 The first degree of freedom used to derivate the transform.
	/// \param index2 The second degree of freedom used to derivate the transform.
	/// \param transform The partial derivative of the transform.
	///
	virtual MCCOMErr MCCOMAPI GetTransformSecondPartialDerivative (int16 index1, int16 index2, TTransform3D& transform) const = 0;

	/// Modify the tree transform to apply the contraints.
	///
	/// \param transform	A reference to a tree transform (this parameter is in and out).
	///
	virtual void		MCCOMAPI ConstrainsTransform(TTreeTransform& transform) const = 0;
};

// Temporary interface for Carrara 6
struct I3DExNewConstraint2 : public IMCUnknown
{
	/// Modify the tree transform to apply the contraints to a transform before setting it
	/// to the tree element when this transform is changed because of UI events from the
	/// user.
	///
	/// \param prevTransform	Previous transform
	/// \param transform		A reference to a tree transform (this parameter is in and out).
	///
	virtual void		MCCOMAPI ConstrainsInputTransform(const TTreeTransform& prevTransform, TTreeTransform& transform) const = 0;
};

/// \}


#endif
