/*
 *  ctdef.h
 *
 *  Private data. Public data defined in rpcollis.h
 */

/******************************************************************************
 *  Types 
 */

enum RpCollisionDataFlags
{
    rpNACOLLISIONDATAFLAG = 0x00, 
    rpCOLLISIONDATASINGLEMALLOC = 0x01, 
    rpCOLLISIONDATAFLAGSFORCEENUMSIZEINT = RWFORCEENUMSIZEINT
};
typedef enum RpCollisionDataFlags RpCollisionDataFlags;


typedef struct RpCollisionData RpCollisionData;
struct RpCollisionData 
{
    RwInt32         flags;
    RpCollBSPTree   *tree;
    RwInt32         numTriangles;
    RwUInt16        *triangleMap;
};

typedef struct RpCollisionGlobals RpCollisionGlobals;
struct RpCollisionGlobals
{
    RwInt32     collisionRef;
};

/******************************************************************************
 *  Global variables
 */
extern RwInt32 _rpCollisionNumInstances;
extern RwInt32 _rpCollisionGlobalsOffset;         /* Instance globals offset */
extern RwInt32 _rpCollisionAtomicDataOffset;      /* Offset in RpAtomic      */
extern RwInt32 _rpCollisionGeometryDataOffset;    /* Offset in RpGeometry    */
extern RwInt32 _rpCollisionWorldSectorDataOffset; /* Offset in RpWorldSector */

/******************************************************************************
 *  Macros
 */
#define RPWORLDSECTORCOLLISIONDATA(sector)          \
    RWPLUGINOFFSET(RpCollisionData *, (sector),     \
        _rpCollisionWorldSectorDataOffset)

#define RPGEOMETRYCOLLISIONDATA(geometry)           \
    RWPLUGINOFFSET(RpCollisionData *, (geometry),   \
        _rpCollisionGeometryDataOffset)

#define RPCOLLISIONGLOBAL(var)                      \
    (RWPLUGINOFFSET(RpCollisionGlobals, RwEngineInstance, \
        _rpCollisionGlobalsOffset)->var)

#define RPATOMICCOLLISIONREF(atomic)                \
    (*RWPLUGINOFFSET(RwInt32, (atomic), _rpCollisionAtomicDataOffset))

#define _rpSphereBBoxMacro(box, sphere)                         \
MACRO_START                                                     \
{                                                               \
    (box)->inf = (box)->sup = (sphere)->center;                 \
    (box)->inf.x -= (sphere)->radius;                           \
    (box)->inf.y -= (sphere)->radius;                           \
    (box)->inf.z -= (sphere)->radius;                           \
    (box)->sup.x += (sphere)->radius;                           \
    (box)->sup.y += (sphere)->radius;                           \
    (box)->sup.z += (sphere)->radius;                           \
}                                                               \
MACRO_STOP

#define _rpTriangleNormalMacro(normal, v0, v1, v2)              \
MACRO_START                                                     \
{                                                               \
    RwV3d               vTmp, vTmp2;                            \
    RwReal              recipLength;                            \
    RwReal              lengthSq;                               \
                                                                \
    RwV3dSubMacro(&vTmp, (v1), (v0));                           \
    RwV3dSubMacro(&vTmp2, (v2), (v0));                          \
    RwV3dCrossProductMacro((normal), &vTmp, &vTmp2);            \
    lengthSq = RwV3dDotProduct((normal), (normal));             \
    rwInvSqrtMacro(recipLength, lengthSq);                      \
    RwV3dScaleMacro((normal), (normal), recipLength);           \
}                                                               \
MACRO_STOP

/******************************************************************************
 *  Functions
 */

extern void
_rpCollisionDataDestroy(RpCollisionData *data);

extern RpCollisionData *
_rpCollisionDataBuild(
    RwInt32             numVertices,
    RwV3d               *vertices,
    RwInt32             numTriangles, 
    RpCollBSPTriangle   *triangles);

