/*===========================================================================*
 *-                                                                         -*
 *-  Module  :   rpskin.h                                                   -*
 *-                                                                         -*
 *-  Purpose :   General skin handling.                                     -*
 *-                                                                         -*
 *===========================================================================*/

/**
 * \defgroup rpskin RpSkin
 * \ingroup rpplugin
 *
 * Skin Plugin for RenderWare.
 */

#ifndef RPSKIN_H
#define RPSKIN_H

/**
 * \ingroup rpskin
 * \page rpskinoverview RpSkin Plugin Overview
 *
 * The RpSkin plugin has been updated and the animation has been removed.
 * The RpHAnim plugin implements a hierarchical animation system and relies
 * on RpSkin to provide skinning support.
 *
 * \note The RpSkin2 plugin is currently available on Xbox only.
 *
 * For details on interpolating rotation with
 *            Quaternions, see p360
 *            Advanced Animation and Rendering Techniques
 *            Alan Watt and Mark Watt
 *            Addison-Wesley 1993,
 *            ISBN 0-201-54412-1
 *
 * Copyright (c) Criterion Software Limited
 *
 */

/**
 * \defgroup changes RpSkin2 Changes
 * \ingroup rpskin
 *
 * \par Unchanged Functions
 * \li \ref RpSkinDestroy
 * \li \ref RpSkinPluginAttach
 * \li \ref RpSkinGetNumBones
 *
 * \par Changed Functions
 * These function names have changed:
 * \li from \ref RpSkinSetHAnimHierarchy to \ref RpSkinAtomicSetHAnimHierarchy
 * \li from \ref RpSkinGetHAnimHierarchy to \ref RpSkinAtomicGetHAnimHierarchy
 * \li from \ref RpSkinCreate and \ref RpSkinAtomicGetSkin to \ref RpSkinCreate,
 * \ref RpSkinGeometryGetSkin and \ref RpSkinGeometrySetSkin
 *
 * \par Removed Functions
 * \li \ref RpSkeletonCreate
 * \li \ref RpSkeletonDestroy
 * \li \ref RpSkinAddAnimTime
 * \li \ref RpSkinAnimCreate
 * \li \ref RpSkinAnimDestroy
 * \li \ref RpSkinAnimMakeDelta
 * \li \ref RpSkinAnimRead
 * \li \ref RpSkinAnimStreamGetSize
 * \li \ref RpSkinAnimStreamRead
 * \li \ref RpSkinAnimStreamWrite
 * \li \ref RpSkinAnimWrite
 * \li \ref RpSkinAttachFrameToBone
 * \li \ref RpSkinBoneTagToBoneIndex
 * \li \ref RpSkinCreateAtomicFromBoneClump
 * \li \ref RpSkinExtractAnimFromClumpSequence
 * \li \ref RpSkinFrameBlend
 * \li \ref RpSkinFrameInterpolate
 * \li \ref RpSkinGetSkeleton
 * \li \ref RpSkinInvalidateMatrixCache
 * \li \ref RpSkinSetCurrentAnim
 * \li \ref RpSkinSetCurrentAnimTime
 * \li \ref RpSkinSetSkeleton
 * \li \ref RpSkinSkeletonAddTogether
 * \li \ref RpSkinSkeletonBlend
 * \li \ref RpSkinSkeletonCopy
 * \li \ref RpSkinSkeletonCreate
 * \li \ref RpSkinSkeletonDestroy
 * \li \ref RpSkinSkeletonSetCurrentAnim
 * \li \ref RpSkinSkeletonSetCurrentAnimTime
 * \li \ref RpSkinSkeletonAddAnimTime
 * \li \ref RpSkinSkeletonSetAnimCallBack
 * \li \ref RpSkinSkeletonSetAnimLoopCallBack
 * \li \ref RpSkinSkeletonSubAnimTime
 * \li \ref RpSkinSubAnimTime
 * \li \ref RpSkinUpdateMatrices
 */

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

#include "rpcriter.h"
#include "rpskin.rpe"

#include "rphanim.h"

/*===========================================================================*
 *--- Global Types ----------------------------------------------------------*
 *===========================================================================*/
typedef struct RwMatrixWeights RwMatrixWeights;

/* NOT INCLUDED IN DOCS FOR RPSKIN2. WILL BE FOLDED IN AT A LATER DATE.
 * \ingroup rpskin
 * \struct RwMatrixWeights
 * A structure for defining up to four matrix weights per vertex.
 * Not all entries need to be used, (but see the note below).
 *
 * \note
 * Values should be sorted, such that any zero (0.0) entries appear
 * after the valid weights. Any weights that appear after a zero entry
 * will be ignored.
 *
 * \see RpSkinCreate
 */
struct RwMatrixWeights
{
    RwReal w0; /**< The first matrix weight  */
    RwReal w1; /**< The second matrix weight */
    RwReal w2; /**< The third matrix weight  */
    RwReal w3; /**< The fourth matrix weight */
};

typedef struct RpSkin RpSkin;

/*===========================================================================*
 *--- Plugin API Functions --------------------------------------------------*
 *===========================================================================*/
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */

/*---------------------------------------------------------------------------*
 *-   Plugin functions                                                      -*
 *---------------------------------------------------------------------------*/
extern RwBool
RpSkinPluginAttach(void);

/*---------------------------------------------------------------------------*
 *-   Skin Atomic functions                                                 -*
 *---------------------------------------------------------------------------*/
extern RpAtomic *
RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic,
                               RpHAnimHierarchy *hierarchy );

extern RpHAnimHierarchy *
RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic );

/*---------------------------------------------------------------------------*
 *-   Skin Geometry functions                                               -*
 *---------------------------------------------------------------------------*/
extern RpGeometry *
RpSkinGeometrySetSkin( RpGeometry *geometry,
                       RpSkin *skin );

extern RpSkin *
RpSkinGeometryGetSkin( RpGeometry *geometry );

extern RpSkin *
RpSkinCreate( RwUInt32 numVertices,
              RwUInt32 numBones,
              RwUInt32 *boneTags,
              RwMatrixWeights *vertexWeights,
              RwUInt32 *vertexIndices,
              RwMatrix *inverseMatrices );

extern RpSkin *
RpSkinDestroy( RpSkin *skin );

extern RwUInt32
RpSkinGetNumBones( RpSkin *skin );

extern const RwMatrixWeights *
RpSkinGetVertexBoneWeights( RpSkin *skin );

extern const RwUInt32 *
RpSkinGetVertexBoneIndices( RpSkin *skin );

extern const RwMatrix *
RpSkinGetSkinToBoneMatrices( RpSkin *skin );

/*---------------------------------------------------------------------------*
 *-   Skin Platform specific functions                                      -*
 *---------------------------------------------------------------------------*/
#ifdef SKY2_DRVMODEL_H

extern void
RpSkinSetPS2Lighting( RxWorldLightingCallBack newLightingFunc );

extern RxPipeline *
RpSkinGetPS2AllPipeline(void);

extern RxPipeline *
RpSkinGetPS2ManagerPipeline(void);


/* Allows instancing of skin information from within PS2Manager */
extern RwBool
_rxPipelineNodePS2SkinGenericPS2ManagerInstanceCallBack(
    void **clusterData,
    RwUInt32 numClusters );

/* Skinning PS2All callbacks, potentially useful to users */

#if (!defined(_rxPipelineNodePS2SkinGenericPS2AllObjectSetupCallBack))
#define _rxPipelineNodePS2SkinGenericPS2AllObjectSetupCallBack \
        _rxPS2AllObjectSetupCallBack
#endif /* (defined(_rxPipelineNodePS2SkinGenericPS2AllObjectSetupCallBack)) */

#if (!defined(_rxPipelineNodePS2SkinGenericPS2AllMatBridgeCallBack))
#define _rxPipelineNodePS2SkinGenericPS2AllMatBridgeCallBack \
        _rxPS2SkinGenericPS2AllMatBridgeCallBack
#endif /* (defined(_rxPipelineNodePS2SkinGenericPS2AllMatBridgeCallBack)) */

#if (!defined(_rxPipelineNodePS2SkinGenericPS2AllInstanceCallBack))
#define _rxPipelineNodePS2SkinGenericPS2AllInstanceCallBack \
        _rxPS2SkinGenericPS2AllInstanceCallBack
#endif /* (defined(_rxPipelineNodePS2SkinGenericPS2AllInstanceCallBack)) */

extern RwBool
_rxPipelineNodePS2SkinGenericPS2AllObjectSetupCallBack(
    RxPS2AllPipeData *ps2AllPipeData,
    RwMatrix **transform,
    RxWorldApplyLightFunc lightingFunc );

extern RwBool
_rxPipelineNodePS2SkinGenericPS2AllMatBridgeCallBack(
    RxPS2AllPipeData *ps2AllPipeData );

extern RwBool
_rxPipelineNodePS2SkinGenericPS2AllInstanceCallBack(
    RxPS2AllPipeData *ps2AllPipeData,
    void **clusterData,
    RwUInt32 numClusters );

#endif /* SKY2_DRVMODEL_H */

#ifdef __cplusplus
}
#endif /* __cplusplus */

/*---------------------------------------------------------------------------*
 *-   Backwards macros                                                      -*
 *---------------------------------------------------------------------------*/

#define RpSkinAtomicGetSkin(_a)                                         \
    RpSkinGeometryGetSkin(RpAtomicGetGeometry(_a))

#define RxPipelineNodePS2SkinGenericPS2ManagerInstanceCallBack(_c,_n)   \
    _rxPipelineNodePS2SkinGenericPS2ManagerInstanceCallBack(_c, _n)

#define RxPipelineNodePS2SkinPS2AllObjectSetupCallBack(_p, _t, _l)      \
    _rxPipelineNodePS2SkinGenericPS2AllObjectSetupCallBack(_p, _t, _l)

#define RxPipelineNodePS2SkinPS2AllMatBridgeCallBack(_p)                \
    _rxPipelineNodePS2SkinGenericPS2AllMatBridgeCallBack(_p)

#define RxPipelineNodePS2SkinPS2AllInstanceCallBack(_p, _c, _n)         \
    _rxPipelineNodePS2SkinGenericPS2AllInstanceCallBack(_p, _c, _n)

#endif /* RPSKIN_H */
