//================================================================
// E3D library
//
// Transforms
//
// AUTHOR:  Gabor Nagy
// DATE:    2019-Jun-23 15:37:29
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_Transform_h
#define _E3D_Transform_h


#ifndef _E3D_Object_h
#include <E3D/Object.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif



// Note that "typedef struct E3dModel_S	E3dModel;" is in Object.h, because
// this file includes it and E3dObject needs E3dModel
//

#define E3dTransform_core\
	EObjectCore(E3dTransform);  /* Name is used for targetting by animations  */\
	const char*  Semantic       /* A value from a fly-weight list (don't free it!), e.g.: E3dTransformSemantic_Translate  */

typedef struct E3dTransform_S       E3dTransform;
typedef struct E3dTransformClass_S  E3dTransformClass;

typedef void  (*E3dTransformProc)(E3dTransform* PTransform);
typedef void  (*E3dTransformMatrixProc)(const E3dTransform* PTransform, E3dMatrix PMatrix);

struct E3dTransformClass_S
{
	EBaseClassCore(E3dTransform);

//E3dTransformProc        Init,           // Constructor
//	                      Free;           // Destructor
	E3dTransformProc        Reset;          // Reset Transform to identity (Scale 1,1,1, Translate 0,0,0 etc.).
	E3dTransformMatrixProc  ApplyToMatrix;  // Apply Transform to a Matrix
};


struct E3dTransform_S
{
	E3dTransform_core;
};


typedef struct
{
	E3dTransform_core;

	E3dCoord3  Value;
} E3dTranslate;


typedef struct
{
	E3dTransform_core;

	E3dRotation  Value;
} E3dRotate;


typedef struct
{
	E3dTransform_core;

	E3dCoord3  Value;
} E3dScale;

#define E3dTransformSetCore\
	E3dCoord3         Translation,\
	                  Scaling;\
	E3dEulerRotation  EulerRotation  /* Euler rotation  */

typedef struct
{
	E3dTransformSetCore;
} E3dTransformSetBase;


typedef struct
{
	E3dTransformSetCore;

	EList(, E3dTransform*, Transforms);  // Arbitrary list of transforms
} E3dTransformSet;


//================================================================================
// Create a new E3dTransform
//
// pType      The type of the Object. For example E3dMesh
// pResult    The variable in which to put the result
//
// Description
//  Allocates memory for a new Object and initializes it.
//
// See also
//  EClass.h/E_Delete
//================================================================================
#define E3d_TransformNew(pType, pResult) do\
{\
	pType*  lObject;ENew(lObject);if(lObject)\
	{\
		EM_ObjectInit(E3dTransform, lObject, pType##_class);\
	}\
	pResult = lObject;\
} while(0)



extern E3dTransformClass  E3dTransform_class[];

extern E3dTransformClass  E3dScale_class[];
extern const char*        E3dTransformSemantic_Scale;

extern E3dTransformClass  E3dRotate_class[];
extern const char*        E3dTransformSemantic_Rotate;

extern E3dTransformClass  E3dTranslate_class[];
extern const char*        E3dTransformSemantic_Translate;


extern const char*   E3dTransformSemantic_JointOrient;
extern const char*   E3dTransformSemantic_RotateAxis;


extern void  E3dTransformSet_Reset(E3dTransformSet* PTransformSet, const EBool PFreeTransformList);
extern void  E3dTransformSet_Init(E3dTransformSet* PTransformSet);
extern void  E3dTransformSet_Copy(const E3dTransformSet* PSrcTransformSet, E3dTransformSet* PDstTransformSet);
extern void  E3dTransformSet_Print(const E3dTransformSet* PTransformSet);
extern void  E3dTransformSet_FreeTransforms(E3dTransformSet* PTransformSet);

extern void  E3dTransformSet_RotationInit(E3dTransformSet* PTransformSet);
extern void  E3dTransformSet_MatrixToRotation(const E3dMatrix PMatrix, E3dTransformSet* PTransformSet);
extern void  E3dTransformSet_RotateMatrix(E3dMatrix PMatrix, const E3dTransformSet* PTransformSet);

extern void  E3dMatrix_DecomposeToScaleRotateTranslate(const E3dMatrix PMatrix, const E3dMatrix PParentMatrix, const char PRotOrder,  E3dTransformSet* PTransformSet);
extern void  E3dMatrix_DecomposeToRotateTranslate(const E3dCoordinate* const PMatrix, const E3dCoordinate* const PParentMatrix, const char PRotOrder,  E3dTransformSet* PTransformSet);

extern EBool E3dTransformList_IsStandard(const char* PTransformOrderString, const char* PRotationOrderString, uint8_t* PRotationOrderP);
extern int   E3dTransformSet_ToTraditional(const E3dTransformSet* PSrcTransformSet, const uint8_t PRotationOrder, E3dTransformSet* PDstTransformSet);

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _E3D_Transform_h
