
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {

/// \brief This is the base class for all nodes that are transformable objects in the Mudbox scene.
///
/// For example, cameras, lights, and geometry are all derived from GroupNode.  In the
/// Mudbox scene hierarchy, each GroupNode is the child of a Transformation node, which provides
/// its positional and size information.
class MBDLL_DECL GroupNode : virtual public TreeNode
{
	DECLARE_CLASS;

public:
	/// This method returns the Transformation node attached to this node (i.e., its Parent in
	/// the scene hierarchy).  Use this returned Transformation node to scale, rotate, or
	/// translate this node.
	class Transformation *Transformation( void ) const;
};

/// \brief A Transformation is a node in the Mudbox scene that controls the size
/// and position of other nodes, such as lights, cameras, or polygon meshes.
///
/// It represents transformations as a combination of scaling, rotation, and
/// translation, applied in that order.
///
/// The position of a GroupNode is determined solely by the matrix of its
/// parent Transformation node.  In other words, while it is possible to arrange
/// scene objects into a hierarchy, the transformation matrices up the hierarchy
/// are NOT composited together to produce a final transformation.
class MBDLL_DECL Transformation : virtual public GroupNode
{
	DECLARE_CLASS;

public:
	/// Transforms a Vector from local space into world space.
	///
	/// The Vector class in this SDK is used to represent both points in 3d
	/// space, and true vectors (which have directional, but no positional information.)
	/// By default, this method assumes that you are transforming a point, and
	/// so sets the W value to 1.0.  If you are in fact transforming a true vector, 
	/// you should set fW to 0.
	virtual Vector TransformToWorld(
		const Vector &vL,	///< [in] The point or vector to be transformed
		float fW = 1.0f		///< [in] The "W" value.  Leave as 1.0 for points, set to 0.0 for vectors
		);

	/// Transforms a Vector from world space into local space.
	///
	/// The Vector class in this SDK is used to represent both points in 3d
	/// space, and true vectors (which have directional, but no positional information.)
	/// By default, this method assumes that you are transforming a point, and
	/// so sets the W value to 1.0.  If you are in fact transforming a true vector, 
	/// you should set fW to 0.
	virtual Vector TransformToLocal(
		const Vector &vW,	///< [in] The point or vector to be transformed
		float fW = 1.0f		///< [in] The "W" value.  Leave as 1.0 for points, set to 0.0 for vectors
		);

	/// Returns a Matrix that can transform points or vectors
	/// from local space into world space.
	virtual Matrix LocalToWorldMatrix( void );

	/// Returns a Matrix that can transform points or vectors
	/// from world space into local space.
	virtual Matrix WorldToLocalMatrix( void );

	/// Sets the Matrix for this object that will
	/// transform points and vectors from local space to world space.
	virtual void SetLocalToWorldMatrix(
		const Matrix &mMatrix	///< [in] A 4x4 transformation matrix
		);

	/// Returns the rotation component of the current transformation
	/// as yaw-pitch-roll (x,y,z) values in a Vector.  The return values are 
	/// in degrees.
	virtual Vector Rotation( void ) const;

	/// Sets the rotation component of the current transformation.
	/// The scaling and translation remain unaffected.
	virtual void SetRotation(
		const Vector &vYawPitchRoll	///< [in] The new rotation value specified as yaw-pitch-roll (x,y,z), in degrees.
		);

	/// Sets the rotation component of the current transformation
	/// by specifying a rotation matrix.  The scaling and translation remain unaffected.
	virtual void SetRotation(
		const Matrix &mRotation	///< [in] A 4x4 rotation matrix
		);

	/// Adds additional rotation to the current transformation.
	/// The scaling and translation remain unaffected.
	virtual void AddRotation(
		const Vector &vYawPitchRoll,	///< [in] The rotation value to be added, specified as yaw-pitch-roll (x,y,z), in degrees.
		bool bAfter = false				///< [in] If true, the new rotation will be applied AFTER the existing one.  If false, the new rotation will be applied \a before the existing one.
		);

	/// Returns the current position (translation) of the object.
	/// (That is, the position of the origin after being transformed from
	/// local space to world space.)
	virtual Vector Position( void ) const;

	/// Sets the position (translation) of the object.
	virtual void SetPosition(
		const Vector &vVector	///< [in] The new translation value
		);

	/// Returns the scale factors of the current transformation.
	virtual Vector Scale( void ) const;

	/// Sets the scale factors of the current transformation.
	virtual void SetScale(
		const Vector &vScale	///< [in] The new scale factors in x, y, and z.
		);
};

/// \brief This object provides additional transformations for a mesh (skinning)
///
/// When an object whose class is derived from this interface is properly added
/// as child to a Geometry object in the scene, the rendering uses the transformations
/// returned by this object as additional transformations during rendering, if the current
/// material supports skinning. The vertices of the mesh first transformed by these
/// additional transformations, then the local transformation provided by the Transformation
/// class. In other words, the transformations provided by this object supposed to transform
/// within object space. In order to use this object, additional vertex information must be
/// supplied by using the VertexDataProvider class (bone indices and weights)
class MBDLL_DECL TransformationPalette : virtual public TreeNode
{

    DECLARE_CLASS;

public:
	/// Returns the number of transformations (bones). 
	/// If this value is zero, skinning won't be used.	 \see TransformationPalette::Type()
    virtual int TransformationCount( void ) const;

	/// Possible types of the transformations provided by an object.
	enum TransformationType
	{
		eMatrix,
		eDualQuaternion
	};

	/// This function informs the renderer about the type of the transformations.
	/// Using dual quaternions gives better quality blending result, but can only 
	/// hold rigid transformations (translation and rotation only)
	virtual TransformationType Type( void ) const;

	/// Returns a transformation as a matrix. This is only called when Type() returns eMatrix.
    virtual Matrix AsMatrix( 
		int iIndex ///< [in] Index of the transformation.
		) const;

	/// Returns a transformation as a dual quaternion. This is only called when Type() returns eDualQuaternion.
    virtual DualQuaternion AsDualQuaternion( 
		int iIndex ///< [in] Index of the transformation.
		) const;

	/// \brief This function sets up the vertex processing of the rendering pipeline to properly skin the vertices
	/// The bone indices must be in TEXCOORD3, the weights must be in TEXCOORD4
	virtual void SetupVertexProcessing( void ) const;

	/// This function restores the vertex processing pipeline to the fixed function pipeline after a SetupVertexProcessing call
	virtual void RestoreVertexProcessing( void ) const;
};

}; // end of namespace mudbox
