#ifndef _SKINSKY_H
#define _SKINSKY_H

/*===========================================================================*
 *--- Include files ---------------------------------------------------------*
 *===========================================================================*/
#include "rwcore.h"
#include "rpworld.h"

#include "rpskin.h"

/*===========================================================================*
 *--- Private Defines -------------------------------------------------------*
 *===========================================================================*/
#define rpSKINMAXNUMBEROFMATRICES 64

#define UV FALSE
#define UV2 TRUE

#define SKINTRANSTRI  (TRANSTRI  >> 0)
#define SKINTRANSLINE (TRANSLINE >> 2)
#define SKINTRANSPER  (TRANSPER  >> 0)
#define SKINTRANSISO  (TRANSISO  >> 2)
#define SKINTRANSNCL  (TRANSNCL  >> 0)
#define SKINTRANSCULL (TRANSCULL >> 5)

#define SKINSKYTRANSFORMALIGMENT rwFRAMEALIGNMENT

#define _rpSkinSkyGeometryGetSkin(_geometry)                            \
    (*RPSKINGEOMETRYGETDATA(_geometry))

#define _rpSkinSkySkinGetNumMatrices(_skin)                             \
    (skin->boneData.numBones)

#if (defined(RWMETRICS))
#define _rpSkinSkyUpdateMeshMetrics(_mesh, _multiplier)                 \
MACRO_START                                                             \
{                                                                       \
    RwUInt32 numIndices;                                                \
                                                                        \
    numIndices = _mesh->mesh->numIndices;                               \
                                                                        \
    if(dmaSessionRec->transType & TRANSLIST)                            \
    {                                                                   \
        RWSRCGLOBAL(metrics)->numProcTriangles +=                       \
            (numIndices / 3) * (_multiplier - 1);                       \
    }                                                                   \
    else                                                                \
    {                                                                   \
        RWSRCGLOBAL(metrics)->numProcTriangles +=                       \
            (numIndices - 2) * (_multiplier - 1);                       \
    }                                                                   \
}                                                                       \
MACRO_STOP

#define _rpSkinSkyUpdateAtomicMetrics(_atomic, _multiplier)             \
MACRO_START                                                             \
{                                                                       \
    RpGeometry *geometry;                                               \
                                                                        \
    RwUInt32 numVertices;                                               \
    RwUInt32 numTriangles;                                              \
                                                                        \
    geometry = RpAtomicGetGeometry(_atomic);                            \
    RWASSERT(NULL != geometry);                                         \
                                                                        \
    numVertices = RpGeometryGetNumVertices(geometry);                   \
    numTriangles = RpGeometryGetNumTriangles(geometry);                 \
                                                                        \
    RWSRCGLOBAL(metrics)->numVertices +=                                \
        numVertices * (_multiplier - 1);                                \
    RWSRCGLOBAL(metrics)->numTriangles +=                               \
        numTriangles * (_multiplier - 1);                               \
}                                                                       \
MACRO_STOP

#else /* (defined(RWMETRICS)) */
#define _rpSkinSkyUpdateMeshMetrics(_mesh, _multiplier)
#define _rpSkinSkyUpdateAtomicMetrics(_atomic, _multiplier)
#endif /* (defined(RWMETRICS)) */


#define _rpSkinPS2ManagerPipeline(pipeline)                             \
    (_rpSkinGlobals.platform.managerPipelines[pipeline])

#define _rpSkinPS2AllMaterialPipeline(pipeline)                         \
    (_rpSkinGlobals.platform.allMaterialPipelines[pipeline])

#define _rpSkinPS2AllPipeline(pipeline)                                 \
    (_rpSkinGlobals.platform.allPipelines[pipeline])

#define _rpSkinPS2AllLightFunc()                                        \
    (_rpSkinGlobals.platform.lightingCallBack)

/*===========================================================================*
 *--- Global Types ----------------------------------------------------------*
 *===========================================================================*/
enum SkinSkyPipeline
{
    rpSKINSKYPIPELINEGENERIC  = 0,
    rpSKINSKYPIPELINEMATFX    = 1,
    rpSKINSKYPIPELINEMATFXUV2 = 2,
    rpSKINSKYPIPELINEMAX
};
typedef enum SkinSkyPipeline SkinSkyPipeline;

struct SkinGlobalPlatform
{
    RxPipeline *managerPipelines[rpSKINSKYPIPELINEMAX];
    RxPipeline *allPipelines[rpSKINSKYPIPELINEMAX];
    RxPipeline *allMaterialPipelines[rpSKINSKYPIPELINEMAX];
    RxWorldLightingCallBack lightingCallBack;
};

typedef long SkinSkyVUCode;

typedef void * RWALIGN( SkinSkyTransforms[VU1CODEARRAYSIZE],
                        SKINSKYTRANSFORMALIGMENT );

struct SkinPlatformData { RwUInt32 empty; };

/*===========================================================================*
 *--- Private Global Variables ----------------------------------------------*
 *===========================================================================*/

/*===========================================================================*
 *--- Private Functions -----------------------------------------------------*
 *===========================================================================*/

#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _SKINSKY_H */
