/***************************************************************************
 *                                                                         *
 * Module  : pip2model.h                                                   *
 *                                                                         *
 * Purpose : Pipe structure definition                                     *
 *                                                                         *
 **************************************************************************/


#ifndef PIP2MODEL_H
#define PIP2MODEL_H

/****************************************************************************
 Includes
 */

#include "batypes.h"
#include "bavector.h"
#include "bacolor.h"
#include "drvmodel.h"

/* RWPUBLIC */

/**
 * \defgroup corep2sky2 PS2
 * \ingroup rwcorepowerpipe
 *
 * PS2
 */


/****************************************************************************
 Global Defines
 */

#define RXHEAPPLATFORMDEFAULTSIZE  (1 << 12) /* 4k */

/****************************************************************************
 Global Types
 */

/**
 * \ingroup corep2sky2
 * \typdef RxColorUnion
 * Typedef for an RxColorUnion union
 */
typedef union RxColorUnion RxColorUnion;
/**
 * \ingroup corep2sky2
 * \union RxColorUnion 
 * Union shared between immediate mode and retained mode object-space
 * vertices. Immediate mode vertices have vertex color whereas retained
 * mode vertices have preLitColor.
 */
union RxColorUnion
{
    RwRGBA              preLitColor;    /**< Vertex pre-lighting values */
    RwRGBA              color;          /**< Immediate mode vertex color */
};

/**
 * \ingroup corep2sky2
 * \typedef RxObjSpace3DVertex
 * Typedef for an RxObjSpace3DVertex structure
 */
typedef struct RxObjSpace3DVertex RxObjSpace3DVertex;
/**
 * \ingroup corep2sky2
 * \struct RxObjSpace3DVertex 
 * Structure representing an object space vertex
 */
struct RxObjSpace3DVertex
{
    RwV3d               objVertex;      /**< Object space vertex position */
    RxColorUnion        c;              /**< Object space color */ 
    RwV3d               objNormal;      /**< Object space normal */
    RwReal              u;              /**< Vertex tex coord */
    RwReal              v;              /**< Vertex tex coord */
};

/* The 3D immediate mode one is the same */
/**
 * \ingroup corep2sky2
 * \typedef RxObjSpace3DLitVertex
 * Typedef for an RxObjSpace3DLitVertex structure
 */
typedef RxObjSpace3DVertex RxObjSpace3DLitVertex;

/* This vertex format is non-truncatable */
#define RxObjSpace3DVertexNoUVsNoNormalsSize                \
    (offsetof(RxObjSpace3DVertex,objNormal))

#define RxObjSpace3DVertexNoUVsSize                         \
    (offsetof(RxObjSpace3DVertex,u))

#define RxObjSpace3DVertexFullSize                          \
    (sizeof(RxObjSpace3DVertex))

/* Defined in the driver: (eventually should be true of the above/below) */
/**
 * \ingroup corep2sky2
 * \typedef RxScrSpace2DVertex
 * Typedef for an RxScrSpace2DVertex structure
 */
typedef RwIm2DVertex RxScrSpace2DVertex;

/****************************************************************************
 Object-space 3D vertex macros
 */

#if defined (__MWERKS__)

#if (0 && ( __MWERKS__ >= 0x2401) )

#if (defined(RWVERBOSE))
#pragma message (__FILE__ "/" _SKY_EXPAND(__LINE__) ": __MWERKS__ == " _SKY_EXPAND(__MWERKS__))
#endif /* (defined(RWVERBOSE)) */

#define RxRGBAAssign(_target, _source)          \
MACRO_START                                     \
{                                               \
    RwRGBA * const dst = (_target);             \
    const RwRGBA * const src = (_source);       \
    dst->red = src->red;                        \
    dst->green = src->green;                    \
    dst->blue = src->blue;                      \
    dst->alpha = src->alpha;                    \
}                                               \
MACRO_STOP

#define RxV3dAssign(_target, _source)           \
MACRO_START                                     \
{                                               \
    RwV3d * const dst = (_target);              \
    const RwV3d * const src = (_source);        \
    dst->x = src->x;                            \
    dst->y = src->y;                            \
    dst->z = src->z;                            \
}                                               \
MACRO_STOP

#pragma message (__FILE__ "/" _SKY_EXPAND(__LINE__) ": Workarounds for __MWERKS__ == " _SKY_EXPAND(__MWERKS__))
#elif (defined(RWVERBOSE))
#pragma message (__FILE__ "/" _SKY_EXPAND(__LINE__) ": __MWERKS__ == " _SKY_EXPAND(__MWERKS__))

#endif /* (0 && ( __MWERKS__ >= 0x2401) ) */
#endif /* defined (__MWERKS__) */

#if (!defined(RxRGBAAssign))
#define RxRGBAAssign(_target, _source) RwRGBAAssign(_target, _source)
#endif /* (!defined(RxRGBAAssign)) */

#if (!defined(RxV3dAssign))
#define RxV3dAssign(_target, _source) RwV3dAssign(_target, _source)
#endif /* (!defined(RxV3dAssign)) */

/* Vertex positions */
#define RxObjSpace3DVertexGetPos(_vert, _pos)               \
    RxV3dAssign(_pos, &(_vert)->objVertex)

#define RxObjSpace3DVertexSetPos(_vert, _pos)               \
    RxV3dAssign(&(_vert)->objVertex, _pos)

/* Pre-lighting colours */
#define RxObjSpace3DVertexGetPreLitColor(_vert, _col)       \
    RxRGBAAssign(_col, &(_vert)->c.preLitColor)

#define RxObjSpace3DVertexSetPreLitColor(_vert, _col)       \
    RxRGBAAssign(&(_vert)->c.preLitColor, _col)

/* This uses the same slot as color (they are mutually exclusive) */
#define RxObjSpace3DVertexGetColor RxObjSpace3DVertexGetPreLitColor

/* Normals */
#define RxObjSpace3DVertexGetNormal(_vert, _normal)         \
    RxV3dAssign(_normal, &(_vert)->objNormal)

#define RxObjSpace3DVertexSetNormal(_vert, _normal)         \
    RxV3dAssign(&(_vert)->objNormal, _normal)

/* Us and Vs */
#define RxObjSpace3DVertexGetU(_vert)                       \
    ((_vert)->u)

#define RxObjSpace3DVertexGetV(_vert)                       \
    ((_vert)->v)

#define RxObjSpace3DVertexSetU(_vert, _imu)                 \
    ((_vert)->u = (_imu))

#define RxObjSpace3DVertexSetV(_vert, _imv)                 \
    ((_vert)->v = (_imv))

/**
 * \ingroup corep2sky2
 * \typedef RwIm3DVertex
 * Typedef for an RwIm3DVertex 
 */
typedef RxObjSpace3DLitVertex RwIm3DVertex;
/* LEGACY-SUPPORT macro */
#define RWIM3DVERTEX RwIm3DVertex

/* RWPUBLICEND
 * Correctly emulated ones
 * RWPUBLIC */
#define RwIm3DVertexSetU   RxObjSpace3DVertexSetU
#define RwIm3DVertexSetV   RxObjSpace3DVertexSetV
#define RwIm3DVertexGetNext(_vert)      ((_vert) + 1)

#define RwIm2DCameraVertexSetU(_devvert, _camvert, _u, _recipz) \
MACRO_START                                                     \
{                                                               \
    RwReal _uLocal = _u;                                        \
    _camvert->u = _uLocal;                                      \
    RwIm2DVertexSetU(_devvert, _uLocal, _recipz);               \
}                                                               \
MACRO_STOP

#define RwIm2DCameraVertexSetV(_devvert, _camvert, _v, _recipz) \
MACRO_START                                                     \
{                                                               \
    RwReal _vLocal = _v;                                        \
    _camvert->v = _vLocal;                                      \
    RwIm2DVertexSetV(_devvert, _vLocal, _recipz);               \
}                                                               \
MACRO_STOP

/* RWPUBLICEND
 * painfully emulated ones - option revert your macros to set-by-value
 * RWPUBLIC */
#define RwIm3DVertexSetPos(_vert, _imx, _imy, _imz)         \
MACRO_START                                                 \
{                                                           \
    RwV3d _packed;                                          \
    _packed.x = _imx;                                       \
    _packed.y = _imy;                                       \
    _packed.z = _imz;                                       \
    RxObjSpace3DVertexSetPos(_vert, &_packed);              \
}                                                           \
MACRO_STOP

#define RwIm3DVertexSetRGBA(_vert, _r, _g, _b, _a)          \
MACRO_START                                                 \
{                                                           \
    RwRGBA * const _col = &(_vert)->c.color;                \
    _col->red = (_r);                                       \
    _col->green = (_g);                                     \
    _col->blue = (_b);                                      \
    _col->alpha = (_a);                                     \
}                                                           \
MACRO_STOP

#define RwIm3DVertexSetNormal(_vert, _imx, _imy, _imz)      \
MACRO_START                                                 \
{                                                           \
    RwV3d _packed;                                          \
    _packed.x = _imx;                                       \
    _packed.y = _imy;                                       \
    _packed.z = _imz;                                       \
    RxObjSpace3DVertexSetNormal(_vert, &_packed);           \
}                                                           \
MACRO_STOP

/* RWPUBLICEND
 * Wrongly emulated ones !!! HAVE TO FIX !!!
 * RWPUBLIC */
#define RwIm3DVertexGetPos(_vert) (&((_vert)->objVertex))
#define RwIm3DVertexGetNormal(_vert) (&((_vert)->objNormal))

#define RwIm3DVertexCopyRGBA(dst,src)                       \
    RxRGBAAssign(&((dst)->c.color) , &((src)->c.color))

/* LEGACY-SUPPORT macros */
#define RWIM2DCAMERAVERTEXSetU(_devvert, _camvert, _u, _recipz) \
    RwIm2DCameraVertexSetU(_devvert, _camvert, _u, _recipz)
#define RWIM2DCAMERAVERTEXSetV(_devvert, _camvert, _v, _recipz) \
    RwIm2DCameraVertexSetV(_devvert, _camvert, _v, _recipz)
#define RWIM3DVERTEXGetNext(vert)               RwIm3DVertexGetNext(vert)
#define RWIM3DVERTEXSetPos(vert, imx, imy, imz) \
    RwIm3DVertexSetPos(vert, imx, imy, imz)
#define RWIM3DVERTEXGetPos(vert)                RwIm3DVertexGetPos(vert)
#define RWIM3DVERTEXSetU(vert, imu)             RwIm3DVertexSetU(vert, imu)
#define RWIM3DVERTEXSetV(vert, imv)             RwIm3DVertexSetV(vert, imv)
#define RWIM3DVERTEXSetRGBA(vert, r, g, b, a) \
    RwIm3DVertexSetRGBA(vert, r, g, b, a)
#define RWIM3DVERTEXSetNormal(vert, imx, imy, imz) \
    RwIm3DVertexSetNormal(vert, imx, imy, imz)
#define RWIM3DVERTEXCopyRGBA(dst,src)           RwIm3DVertexCopyRGBA(dst,src)
#define RXOBJSPACE3DVERTEXGetPos(_vert, _pos) \
    RxObjSpace3DVertexGetPos(_vert, _pos)
#define RXOBJSPACE3DVERTEXSetPos(_vert, _pos) \
    RxObjSpace3DVertexSetPos(_vert, _pos)
#define RXOBJSPACE3DVERTEXGetPreLitColor(_vert, _col) \
    RxObjSpace3DVertexGetPreLitColor(_vert, _col)
#define RXOBJSPACE3DVERTEXSetPreLitColor(_vert, _col) \
    RxObjSpace3DVertexSetPreLitColor(_vert, _col)
#define RXOBJSPACE3DVERTEXGetColor              RxObjSpace3DVertexGetColor
#define RXOBJSPACE3DVERTEXGetNormal(_vert, _normal) \
    RxObjSpace3DVertexGetNormal(_vert, _normal)
#define RXOBJSPACE3DVERTEXSetNormal(_vert, _normal) \
    RxObjSpace3DVertexSetNormal(_vert, _normal)
#define RXOBJSPACE3DVERTEXGetU(_vert)           RxObjSpace3DVertexGetU(_vert)
#define RXOBJSPACE3DVERTEXGetV(_vert)           RxObjSpace3DVertexGetV(_vert)
#define RXOBJSPACE3DVERTEXSetU(_vert, _imu) \
    RxObjSpace3DVertexSetU(_vert, _imu)
#define RXOBJSPACE3DVERTEXSetV(_vert, _imv) \
    RxObjSpace3DVertexSetV(_vert, _imv)

/* RWPUBLICEND */

/* LEGACY-SUPPORT for old objvert names - NB does NOT guarantee the
 * app will work, because the old IM3DVERTEX macros are NOT correctly
 * abstracted - 'Get' will return pointers to RwV3ds inside the
 * ObjVert, but you can't assume there are any RwV3ds inside an
 * opaque vertex type */

#if (0)

#define RwIm3DVertexSetPos(vert, imx, imy, imz)         \
    ((vert)->objVertex.x = (imx));                      \
    ((vert)->objVertex.y = (imy));                      \
    ((vert)->objVertex.z = (imz))

#define RwIm3DVertexGetPos(vert)                        \
    (&((vert)->objVertex))

#define RwIm3DVertexSetU(vert, imu)                     \
    ((vert)->u = (imu))

#define RwIm3DVertexSetV(vert, imv)                     \
    ((vert)->v = (imv))

#define RwIm3DVertexSetRGBA(vert, r, g, b, a)           \
    ((vert)->color.red = (r));                          \
    ((vert)->color.green = (g));                        \
    ((vert)->color.blue = (b));                         \
   ((vert)->color.alpha = (a))

#define RwIm3DVertexSetNormal(vert, imx, imy, imz)      \
    ((vert)->objNormal.x = (imx));                      \
    ((vert)->objNormal.y = (imy));                      \
    ((vert)->objNormal.z = (imz))*/

#endif /* (0) */

#endif /* PIP2MODEL_H */
