#ifndef _PATCHSKY_H
#define _PATCHSKY_H

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

#include "rppatch.h"

/*===========================================================================*
 *--- Private Defines -------------------------------------------------------*
 *===========================================================================*/
#define UV FALSE
#define UV2 TRUE

#define PATCHSKYTRANSFORMALIGMENT rwFRAMEALIGNMENT

typedef union PatchSkyUnion PatchSkyUnion;
union PatchSkyUnion
{
    RwUInt64 uint64;

    struct
    {
        RwUInt32 lower;
        RwUInt32 upper;
    } uint32;

    struct
    {
        RwReal lower;
        RwReal upper;
    } real;
};

#define _rpPatchSkyMakeLOD128(ltmp, lod)                                \
MACRO_START                                                             \
{                                                                       \
    PatchSkyUnion subDiv;                                               \
    PatchSkyUnion tessel;                                               \
                                                                        \
    subDiv.real.lower = ((RwReal)1.0f) / ((RwReal)(lod - 1));           \
    subDiv.uint32.upper = lod;                                          \
                                                                        \
    tessel.real.upper = (subDiv.real.lower * subDiv.real.lower);        \
    tessel.real.lower = (subDiv.real.lower * tessel.real.upper);        \
                                                                        \
    MAKE128(ltmp, subDiv.uint64, tessel.uint64);                        \
}                                                                       \
MACRO_STOP

#define _rpPatchSkyNumTriangles(lod)                                    \
    (((lod - 1)*(lod - 1)) * 2)

#if (defined(RWMETRICS))
#define _rpPatchSkyUpdateMetrics(_lodQW, _mesh, _multiplier)            \
MACRO_START                                                             \
{                                                                       \
    RwUInt32 lod;                                                       \
    RwUInt32 numPatches;                                                \
    RwUInt32 numTriangles;                                              \
                                                                        \
    lod = ((RwUInt32 *)&_lodQW)[3];                                     \
    numPatches = (_mesh->mesh->numIndices >> 4);                        \
    numTriangles = _rpPatchSkyNumTriangles(lod);                        \
                                                                        \
    RWSRCGLOBAL(metrics)->numTriangles +=                               \
         numPatches * _multiplier * numTriangles;                       \
    RWSRCGLOBAL(metrics)->numProcTriangles +=                           \
         numPatches * _multiplier * numTriangles;                       \
    RWSRCGLOBAL(metrics)->numVertices += 16;                            \
}                                                                       \
MACRO_STOP
#else /* (defined(RWMETRICS)) */
#define _rpPatchSkyUpdateMetrics(_lodQW, _mesh, _multiplier)
#endif /* (defined(RWMETRICS)) */

/*===========================================================================*
 *--- Private Types ---------------------------------------------------------*
 *===========================================================================*/
enum PatchSkyPipeline
{
    rpPATCHSKYPIPELINEGENERIC      = 0,
    rpPATCHSKYPIPELINEMATFX        = 1,
    rpPATCHSKYPIPELINEMATFXUV2     = 2,
    rpPATCHSKYPIPELINESKINNED      = 3,
    rpPATCHSKYPIPELINESKINMATFX    = 4,
    rpPATCHSKYPIPELINESKINMATFXUV2 = 5,
    rpPATCHSKYPIPELINEMAX
};
typedef enum PatchSkyPipeline PatchSkyPipeline;

typedef struct PatchPlatform PatchPlatform;
struct PatchPlatform
{
    RxPipeline *pipelines[rpPATCHSKYPIPELINEMAX];
};

typedef long PatchSkyVUCode;

typedef void * RWALIGN( PatchSkyTransforms[VU1CODEARRAYSIZE],
                        PATCHSKYTRANSFORMALIGMENT );

/*===========================================================================*
 *--- Private Global Variables ----------------------------------------------*
 *===========================================================================*/
extern RwUInt128 _rpPatchSkyLodQW;

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


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _PATCHSKY_H */
