/* Power Render Object Builder Macros */

#ifndef _PRBUILD_
#define _PRBUILD_

#ifdef __cplusplus
  extern "C" {
#endif

/* Object Builder Variables */
PR_OBJECT *       PRBUILD_object;
PR_SEGMENT *      PRBUILD_segment;
PR_FACE *         PRBUILD_face;
PR_VERTEX *       PRBUILD_vertex;
PR_VERTEX_DATA *  PRBUILD_vertex_data;

PR_DWORD          PRBUILD_front_material;
PR_DWORD          PRBUILD_back_material;
PR_DWORD          PRBUILD_face_flags;
PR_REAL           PRBUILD_face_uscale;
PR_REAL           PRBUILD_face_vscale;
PR_REAL           PRBUILD_face_cscale;


/* 
Build Functions:

PRBUILD_BeginObject(obj, name, numseg);
   PR_OBJECT *obj   - Pointer to object
   char *name       - Name of object
   PR_DWORD numseg  - Number of segments 

PRBUILD_BeginSegment(name, numfaces, numverts);
   char *name       - Name of segment
   int numfaces     - Number of faces
   int numvert      - Number of vertices 

PRBUILD_SetSegmentFlags(flags);
   int flags        - Segment flags

PRBUILD_SetVertex(x, y, z);
   PR_REAL x        - x coordinate
   PR_REAL y        - y coordinate
   PR_REAL z        - z coordinate

PRBUILD_SetFaceFrontMaterial(mat);
   int mat          - Front material number

PRBUILD_SetFaceBackMaterial(mat);
   int mat          - Back material number

PRBUILD_SetFaceFlags(flags);
   int flags        - Face flags
                #define FFLAG_FRONT_VISIBLE 2
                #define FFLAG_BACK_VISIBLE  4

PRBUILD_SetFaceVertices(v0, v1, v2);
   int v0           - First vertex number
   int v1           - Second vertex number
   int v2           - Third vertex number

PRBUILD_SetFaceUV(u0, v0, u1, v1, u2, v2);
   PR_REAL u0, v0   - Texture coordinate (0.0f to 1.0f) for vertex 1 
   PR_REAL u1, v1   - Texture coordinate (0.0f to 1.0f) for vertex 2
   PR_REAL u2, v2   - Texture coordinate (0.0f to 1.0f) for vertex 3

PRBUILD_SetFaceShades(c0, c1, c2)
   PR_REAL c0, c1, c2 - Precalculated shade values (0.0f to 1.0f)

PRBUILD_EndFace();

PRBUILD_EndSegment();

PRBUILD_EndObject()
*/



#define PRBUILD_BeginObject(obj, name, numseg) {                                    \
  PRBUILD_object = PR_AllocObject();                                                \
  (obj) = PRBUILD_object;                                                           \
  PRBUILD_object->num_segments = numseg;                                            \
  PRBUILD_object->segment_list = (PR_SEGMENT *)calloc(numseg, sizeof (PR_SEGMENT)); \
  PRBUILD_object->num_frames = -1;                                                  \
  PRBUILD_segment = PRBUILD_object->segment_list; }

#define PRBUILD_BeginSegment(name, numfaces, numverts) {                     \
  PRBUILD_segment->flags = 0;                                                \
  PRBUILD_segment->num_faces = numfaces;                                     \
  PRBUILD_segment->face_list = calloc (numfaces, sizeof (PR_FACE));          \
  PRBUILD_segment->num_vertices = numverts;                                  \
  PRBUILD_segment->vertex_list = calloc (numverts, sizeof (PR_VERTEX));      \
  PRBUILD_segment->vertex_data = calloc (numverts, sizeof (PR_VERTEX_DATA)); \
  PRBUILD_face = PRBUILD_segment->face_list;                                 \
  PRBUILD_vertex = PRBUILD_segment->vertex_list;                             \
  PRBUILD_vertex_data = PRBUILD_segment->vertex_data; }

#define PRBUILD_SetSegmentFlags(flag) { PRBUILD_segment->flags = flag; }

#define PRBUILD_SetVertex(cx, cy, cz) {                       \
  PRBUILD_vertex->x = cx;                                     \
  PRBUILD_vertex->y = cy;                                     \
  PRBUILD_vertex->z = cz;                                     \
  PRBUILD_vertex->vdata = PRBUILD_vertex_data;                \
  PRBUILD_vertex++;  PRBUILD_vertex_data++; }

#define PRBUILD_SetFaceFrontMaterial(matnum) {               \
  PRBUILD_front_material = matnum; }

#define PRBUILD_SetFaceBackMaterial(matnum) {                \
  PRBUILD_back_material = matnum; }

#define PRBUILD_SetFaceFlags(flags) {                        \
  PRBUILD_face_flags = flags; }

#define PRBUILD_SetFaceVertices(v0, v1, v2) {                                     \
  PRBUILD_face->vertex1 = PR_GetVertexPointer (PRBUILD_segment->vertex_list, v0); \
  PRBUILD_face->vertex2 = PR_GetVertexPointer (PRBUILD_segment->vertex_list, v1); \
  PRBUILD_face->vertex3 = PR_GetVertexPointer (PRBUILD_segment->vertex_list, v2); }

#define PRBUILD_BeginFace()

#define PRBUILD_SetFaceUV(u0, v0, u1, v1, u2, v2) {                                                  \
  if (PR_Settings.RealUV)                                                                            \
    {                                                                                                \
     PRBUILD_face_uscale = 255.0f *                                                               \
              PR_WorldTextures[PR_ObjectMaterialList[PRBUILD_front_material].texture_number].xscale; \
     PRBUILD_face_vscale = 255.0f *                                                               \
              PR_WorldTextures[PR_ObjectMaterialList[PRBUILD_front_material].texture_number].yscale; \
                                                                                                     \
     *((PR_REAL *)&PRBUILD_face->face_data.u[0]) = u0 * PRBUILD_face_uscale;                         \
     *((PR_REAL *)&PRBUILD_face->face_data.v[0]) = v0 * PRBUILD_face_vscale;                         \
                                                                                                     \
     *((PR_REAL *)&PRBUILD_face->face_data.u[1]) = u1 * PRBUILD_face_uscale;                         \
     *((PR_REAL *)&PRBUILD_face->face_data.v[1]) = v1 * PRBUILD_face_vscale;                         \
                                                                                                     \
     *((PR_REAL *)&PRBUILD_face->face_data.u[2]) = u2 * PRBUILD_face_uscale;                         \
     *((PR_REAL *)&PRBUILD_face->face_data.v[2]) = v2 * PRBUILD_face_vscale;                         \
    }                                                                                                \
  else                                                                                               \
    {                                                                                                \
     PRBUILD_face_uscale = 65536.0f *                                                             \
              PR_WorldTextures[PR_ObjectMaterialList[PRBUILD_front_material].texture_number].width;  \
     PRBUILD_face_vscale = 65536.0f *                                                             \
              PR_WorldTextures[PR_ObjectMaterialList[PRBUILD_front_material].texture_number].height; \
                                                                                                     \
     PR_FLOAT_TO_INT (u0 * PRBUILD_face_uscale, PRBUILD_face->face_data.u[0]);                       \
     PR_FLOAT_TO_INT (v0 * PRBUILD_face_vscale, PRBUILD_face->face_data.v[0]);                       \
     PR_FLOAT_TO_INT (u1 * PRBUILD_face_uscale, PRBUILD_face->face_data.u[1]);                       \
     PR_FLOAT_TO_INT (v1 * PRBUILD_face_vscale, PRBUILD_face->face_data.v[1]);                       \
     PR_FLOAT_TO_INT (u2 * PRBUILD_face_uscale, PRBUILD_face->face_data.u[2]);                       \
     PR_FLOAT_TO_INT (v2 * PRBUILD_face_vscale, PRBUILD_face->face_data.v[2]);                       \
    }                                                                                                \
  }

#define PRBUILD_SetFaceShades(c0, c1, c2) {                                      \
  if (PR_Settings.RealUV)                                                        \
    {                                                                            \
     *((PR_REAL *)&PRBUILD_face->face_data.col[0]) = c0;                         \
     *((PR_REAL *)&PRBUILD_face->face_data.col[1]) = c1;                         \
     *((PR_REAL *)&PRBUILD_face->face_data.col[2]) = c2;                         \
    }                                                                            \
  else                                                                           \
    {                                                                            \
     PRBUILD_face_cscale = 65536.0 *                                             \
            PR_ObjectMaterialList[PRBUILD_front_material].render_shades;         \
                                                                                 \
	 PRBUILD_face->face_data.col[0] = c0 * PRBUILD_face_cscale;                  \
	 PRBUILD_face->face_data.col[1] = c1 * PRBUILD_face_cscale;                  \
	 PRBUILD_face->face_data.col[2] = c2 * PRBUILD_face_cscale;                  \
    }                                                                            \
  }


#define PRBUILD_EndFace() {                               \
  PRBUILD_face->flags = PRBUILD_face_flags;               \
  PRBUILD_face->material = PRBUILD_front_material;        \
  PRBUILD_face->backmaterial  = PRBUILD_back_material;    \
  PRBUILD_face++; }

#define PRBUILD_EndSegment() {                            \
  PRBUILD_segment++; }

#define PRBUILD_EndObject() {                             \
  PR_ObjectCalcBoundingBox (PRBUILD_object);              \
  PR_InitializeFaceNormals (PRBUILD_object);              \
  PR_InitializeVertexNormals (PRBUILD_object); }


#ifdef __cplusplus
}
#endif

#endif
