#pragma ident "@(#)cgpmesher.c	1.15 99/04/26 SMI"

/*
 * Copyright (c) 1997 by Sun Microsystems, Inc.
 * All Rights Reserved
 */


/****************************************************************************
 * mesher.c
 *
 * Parts of this file contain routines to take general triangle/quad data and
 * convert it into triangle mesh data.
 *
 * Author: Mike M. Chow
 * Email: mchow@graphics.lcs.mit.edu
 * 
 * The author grants Sun Microsystems the permission to distribute this
 * file for any of its products without fee or license of any form,
 * provided this file heading and notice appears along with this file
 * in all distributions. 
 * 
 *  List of functions in this file:
 *	cgBuildMesh
 *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cgp.h"
#include "cgpi.h"
#include "zdebug.h"

/* functions used only by this module */
static CGvoid cgpProcessLines(CGPprimitive *, CGboolean);
static CGvoid cgpProcessLineSL(CGPprimitive *, CGboolean, CGboolean);
static CGvoid cgpProcessPoints(CGPprimitive *, CGboolean);
static CGvoid cgpProcessQuads(CGPprimitive *, CGboolean);
static CGvoid cgpProcessTriFan(CGPprimitive *, CGboolean);
static CGvoid cgpProcessTriStrip(CGPprimitive *, CGboolean);
static CGvoid cgpProcessTriangles(CGPprimitive *, CGboolean);
extern CGPpoint*         CurPt;                  /* Point being processed*/

extern void
cgpBuildMeshWithMeshify(CGPprimlist *Prims, CGint geomQuant, CGint normalQuant,
			CGint colorQuant,
			CGenum quantEnforcement);

/*******************
 * cgpBuildMeshNoMeshify
 *
 *  Main routine called to construct a triangle mesh buffer.
 *
 *  Input:
 *    CGPprimlist* prims
 *
 *  Output:
 *    None.
 *
 */

void
cgpBuildMeshNoMeshify(CGPprimlist* prims, CGint geomQuant, 
		      CGint normalQuant, CGint colorQuant, 
		      CGenum quantEnforcement)
{
    CGPprimlist*   primlist = prims;
    CGPprimitive*  curPrim;
    CGPptbuffer*   curPtBuff;
    CGPpoint*      curPt;

    /* for now just go through list and add header flags */
    curPrim = &primlist->primitive;

    /* get to point list structures */
    curPtBuff = &curPrim->ptBuff;
    curPt = curPtBuff->pts;

    /* for the first primitive in a buffer it is mandatory to */
    /*  to set the quantization level                         */
    if (curPt->geomQuant == 0)
        curPt->geomQuant = geomQuant;

    if (curPt->colorQuant == 0)
        curPt->colorQuant = colorQuant;

    if (curPt->normalQuant == 0)
        curPt->normalQuant = normalQuant;

    switch (curPrim->primType)
    {
        case CG_POINTS:
            cgpProcessPoints(curPrim, CGP_TRUE);
            break;

        case CG_LINE_LOOP:
            cgpProcessLineSL(curPrim, CGP_TRUE, CGP_TRUE);
            break;

        case CG_LINES:
            cgpProcessLines(curPrim, CGP_TRUE);
            break;

        case CG_LINE_STRIP:
            cgpProcessLineSL(curPrim, CGP_TRUE, CGP_FALSE);
            break;

        case CG_QUADS:
            cgpProcessQuads(curPrim, CGP_TRUE);
            break;

        case CG_TRIANGLES:
            cgpProcessTriangles(curPrim, CGP_TRUE);
            break;

        case CG_TRIANGLE_FAN:
        case CG_POLYGON:
            cgpProcessTriFan(curPrim, CGP_TRUE);
            break;

        case CG_TRIANGLE_STRIP:
        case CG_QUAD_STRIP:
            cgpProcessTriStrip(curPrim, CGP_TRUE);
            break;

        default:
            fprintf(stderr, "cgBuildMesh: unkown primitive type\n");
    }

    /* next primitive */
    primlist = primlist->nextPrimitive;

    /* loop through other primitives */
    while (primlist != NULL)
    {
        curPrim = &primlist->primitive;

        switch (curPrim->primType)
        {
            case CG_POINTS:
                cgpProcessPoints(curPrim, CGP_FALSE);
                break;

            case CG_LINE_LOOP:
                cgpProcessLineSL(curPrim, CGP_FALSE, CGP_TRUE);
                break;

            case CG_LINES:
                cgpProcessLines(curPrim, CGP_FALSE);
                break;

            case CG_LINE_STRIP:
                cgpProcessLineSL(curPrim, CGP_FALSE, CGP_FALSE);
                break;

            case CG_QUADS:
                cgpProcessQuads(curPrim, CGP_FALSE);
                break;

            case CG_TRIANGLES:
                cgpProcessTriangles(curPrim, CGP_FALSE);
                break;

            case CG_TRIANGLE_FAN:
            case CG_POLYGON:
                cgpProcessTriFan(curPrim, CGP_FALSE);
                break;

            case CG_TRIANGLE_STRIP:
            case CG_QUAD_STRIP:
                cgpProcessTriStrip(curPrim, CGP_FALSE);
                break;

            default:
                fprintf(stderr, "cgBuildMesh: unkown primitive type\n");
        }

        /* next primitive */
        primlist = primlist->nextPrimitive;
    } /* while (primlist != NULL) */
}


void
cgpBuildMesh(CGPprimlist* prims, CGint geomQuant, 
	     CGint normalQuant, CGint colorQuant,
	     CGenum quantEnforcement)
{
    CGPprimlist*   primlist = prims;
    CGPprimitive*  curPrim;
    CGPptbuffer*   curPtBuff;
    CGPpoint*      curPt;
    int            noMeshify = 0;

    primlist = prims;

    /* loop through primitives to see if any unsupported primitives
     for meshifying. */
    while ((primlist != NULL) && (!noMeshify))
    {
        curPrim = &primlist->primitive;

        switch (curPrim->primType)
        {
            case CG_QUADS:
                break;
            case CG_TRIANGLES:
                break;
            case CG_POLYGON:
                break;
            default:
	      noMeshify = 1;
	      break;
        }
	
        /* next primitive */
        primlist = primlist->nextPrimitive;
    } /* while (primlist != NULL) */
    if (noMeshify){
      zdo6 printf("Saw an unsupported primitive, inhibiting meshifying...\n");
      cgpBuildMeshNoMeshify(prims, geomQuant, normalQuant, 
			    colorQuant, quantEnforcement);
    }
    else {
      zdo6 printf("Meshify is on \n");
      cgpBuildMeshWithMeshify(prims, geomQuant, normalQuant, 
			     colorQuant, quantEnforcement);
    }
}   


/*******************
 * cgpProcessPoints
 *
 *  Routine called to construct a triangle mesh buffer out of point data.
 *
 *  Input:
 *    CGPprimitive* points
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *
 *  Output:
 *    None.
 *
 */

void
cgpProcessPoints(CGPprimitive *points, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &points->ptBuff;
    curPt = curPtBuff->pts;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }

    for (i = 0, j = 0; i < points->numPts; i++)
    {
        /* just need to set this to something so the build buffer */
        /* routines will be happy                                 */
        curPt->header |= CGP_POINT_HDR_RESTART_CCW;

        /* was there a quantization change? */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }

        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

    } /* for (j = 0, i = 0; i < points->numPts; i++) */

}


/*******************
 * cgpProcessLineSL
 *
 *  Routine called to construct a triangle mesh buffer out of a line loop or
 *  line strip data.
 *
 *  Input:
 *    CGPprimitive* lineSL
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *    CGboolean     lineLoop         - CGP_TRUE when this is a line loop
 *  Output:
 *    None.
 *
 */

void
cgpProcessLineSL(CGPprimitive *lineSL,
                 CGboolean mustUpdateQuant, CGboolean lineLoop)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGPpoint*    firstPt;
    CGuint       i, j;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &lineSL->ptBuff;
    curPt = curPtBuff->pts;

    /* for lines, a move is signified either by CGP_POINT_HDR_RESTART_CCW */
    /*  or CGP_POINT_HDR_RESTART_CW.  A draw is denoted by                */
    /*  CGP_POINT_HDR_REPLACE_OLDEST or CGP_POINT_HDR_REPLACE_MIDDLE      */
    curPt->header |= CGP_POINT_HDR_RESTART_CCW;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }
    else
    {
        /* only flag if different */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }
    }

    if (lineLoop)
    {
        /* save first */
        firstPt = curPt;

        curPt->header |= CGP_POINT_HDR_PUSH;
    }

    for (i = 1, j = 0 ; i < lineSL->numPts ; i++)
    {
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

        curPt->header |= CGP_POINT_HDR_REPLACE_OLDEST;

        /* was there a quantization change? */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }

    } /* for (j = 0, i = 0; i < lineSL->numPts; i++) */

    if (lineLoop)
    {
        /* need to add first point to end of list */

        /* need to add another point list ? */
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff->nextPtBuffer =
              (CGPptbuffer *) malloc(sizeof(CGPptbuffer));


            if (curPtBuff->nextPtBuffer == NULL)
            {
                cgiSetError(CG_OUT_OF_MEMORY);
                return;
            }

            curPtBuff = curPtBuff->nextPtBuffer;
            memset((char *) curPtBuff, 0, sizeof(CGPptbuffer));

            curPt = curPtBuff->pts;
        }
        else
            curPt++;

        curPt->header = CGP_POINT_HDR_REPLACE_OLDEST | CGP_POINT_HDR_REF;
        CGP_SET_POINT_HDR_REF_NUMBER(curPt->header, 0);
        curPt->x = firstPt->x;
        curPt->y = firstPt->y;
        curPt->z = firstPt->z;
        curPt->r = firstPt->r;
        curPt->g = firstPt->g;
        curPt->b = firstPt->b;
        curPt->a = firstPt->a;
        curPt->nX = firstPt->nX;
        curPt->nY = firstPt->nY;
        curPt->nZ = firstPt->nZ;

        lineSL->numPts++;
    }

}



/*******************
 * cgpProcessLines
 *
 *  Routine called to construct a triangle mesh buffer out of line data.
 *
 *  Input:
 *    CGPprimitive* lines
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *  Output:
 *    None.
 *
 */

void
cgpProcessLines(CGPprimitive *lines, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &lines->ptBuff;
    curPt = curPtBuff->pts;

    /* for lines, a move is signified either by CGP_POINT_HDR_RESTART_CCW */
    /*  or CGP_POINT_HDR_RESTART_CW.  A draw is denoted by                */
    /*  CGP_POINT_HDR_REPLACE_OLDEST or CGP_POINT_HDR_REPLACE_MIDDLE      */
    curPt->header |= CGP_POINT_HDR_RESTART_CCW;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }
    else
    {
        /* only flag if different */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }
    }

    curPt++;
    j = 1;

    for (i = 1; i < lines->numPts; i++)
    {
        /* odd values are "draw", even a "move" */
        if (i & 0x1)
            curPt->header |= CGP_POINT_HDR_REPLACE_OLDEST;
        else
            curPt->header |= CGP_POINT_HDR_RESTART_CCW;

        /* was there a quantization change? */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }

        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

    } /* for (j = 0, i = 0; i < lines->numPts; i++) */
}


/*******************
 * cgpProcessTriFan
 *
 *  Routine called to construct a triangle mesh buffer out of triangle fan
 *  data.
 *
 *  Input:
 *    CGPprimitive* tFan
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *  Output:
 *    None.
 *
 */

void
cgpProcessTriFan(CGPprimitive *tFan, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &tFan->ptBuff;
    curPt = curPtBuff->pts;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }

    if (tFan->primFlags & CGP_FRONT_FACE_CW)
        curPt->header |= CGP_POINT_HDR_RESTART_CW;
    else 
        curPt->header |= CGP_POINT_HDR_RESTART_CCW;

    curPt++;

    for (i = 0, j = 1; i < tFan->numPts; i++)
    {
        curPt->header |= CGP_POINT_HDR_REPLACE_MIDDLE;

        /* was there a quantization change? */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }

        /* advance to next point */
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

    }
}



/*******************
 * cgpProcessTriStrip
 *
 *  Routine called to construct a triangle mesh buffer out of triangle strip
 *  data.
 *
 *  Input:
 *    CGPprimitive* tStrip
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *  Output:
 *    None.
 *
 */

void
cgpProcessTriStrip(CGPprimitive *tStrip, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &tStrip->ptBuff;
    curPt = curPtBuff->pts;

    /* set to current facing */
    if (tStrip->primFlags & CGP_FRONT_FACE_CW)
        curPt->header |= CGP_POINT_HDR_RESTART_CW;
    else 
        curPt->header |= CGP_POINT_HDR_RESTART_CCW;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM | 
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }
    else
    {
        /* only flag if different */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }
    }

    curPt++;
    j = 1;

    for (i = 1; i < tStrip->numPts; i++)
    {
        curPt->header |= CGP_POINT_HDR_REPLACE_OLDEST;

        /* was there a quantization change? */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }

        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

    } /* for (j = 0, i = 0; i < tStrip->numPts; i++) */

}


/*******************
 * cgpProcessTriangles
 *
 *  Routine called to construct a triangle mesh buffer out of a list of
 *  individual triangle data.
 *
 *  Input:
 *    CGPprimitive* triangles
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *
 *  Output:
 *    None.
 *
 */

void
cgpProcessTriangles(CGPprimitive *triangles, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;
    CGint        vtxNum;
    CGint        restartWinding ;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &triangles->ptBuff;
    curPt = curPtBuff->pts;

    /* set to current facing */
    if (triangles->primFlags & CGP_FRONT_FACE_CW)
        restartWinding = CGP_POINT_HDR_RESTART_CW;
    else 
        restartWinding = CGP_POINT_HDR_RESTART_CCW;

    curPt->header |= restartWinding ;

    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }
    else
    {
        /* only flag if different */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }
    }

    /* first vertex has been processed */
    curPt++;
    for (i = 1, j = 1, vtxNum = 1; i < triangles->numPts; i++, vtxNum++)
    {
        if (vtxNum != 3)
            curPt->header |= CGP_POINT_HDR_REPLACE_OLDEST;
        else
        {
            vtxNum = 1;
            curPt->header |= restartWinding ;
        }

        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

    } 
}


/*******************
 * cgpProcessQuads
 *
 *  Routine called to construct a triangle mesh buffer out of a list of
 *  individual quads.
 *
 *  Input:
 *    CGPprimitive* quads
 *    CGboolean     mustUpdateQuant  - forces quantization change flag to be
 *                                     set
 *
 *  Output:
 *    None.
 *
 */

void
cgpProcessQuads(CGPprimitive *quads, CGboolean mustUpdateQuant)
{
    CGPptbuffer* curPtBuff;
    CGPpoint*    curPt;
    CGuint       i, j;
    CGint        numQuads;

    /* set to some bogus value */
    static CGint lastGeomQuant = 100;
    static CGint lastColorQuant = 100;
    static CGint lastNormalQuant = 100;

    /* get to point list structures */
    curPtBuff = &quads->ptBuff;
    curPt = curPtBuff->pts;


    if (mustUpdateQuant)
    {
        /* been forced to set quantization parameters */
        curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM |
                         CGP_POINT_HDR_QUANT_CHANGE_COLOR |
                         CGP_POINT_HDR_QUANT_CHANGE_NORMAL;

        lastGeomQuant = curPt->geomQuant;
        lastColorQuant = curPt->colorQuant;
        lastNormalQuant = curPt->normalQuant;
    }
    else
    {
        /* only flag if different */
        if (curPt->geomQuant != 0 && curPt->geomQuant != lastGeomQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_GEOM;
            lastGeomQuant = curPt->geomQuant;
        }

        if (curPt->colorQuant != 0 && curPt->colorQuant != lastColorQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_COLOR;
            lastColorQuant = curPt->colorQuant;
        }

        if (curPt->normalQuant != 0 && curPt->normalQuant != lastNormalQuant)
        {
            curPt->header |= CGP_POINT_HDR_QUANT_CHANGE_NORMAL;
            lastNormalQuant = curPt->normalQuant;
        }
    }

    numQuads = quads->numPts / 4;

    for (j = 0, i = 0; i < numQuads; i++)
    {
        /* first point is a restart (bottom left) */

        /* set to current facing */
        if (quads->primFlags & CGP_FRONT_FACE_CW)
            curPt->header |= CGP_POINT_HDR_RESTART_CW;
        else 
            curPt->header |= CGP_POINT_HDR_RESTART_CCW;

        /* advance to next point */
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

        /* second point is top left */
        curPt->header |= CGP_POINT_HDR_REPLACE_MIDDLE;

        /* advance to next point */
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

        /* third point is top right */
        curPt->header |= CGP_POINT_HDR_REPLACE_MIDDLE;


        /* advance to next point */
        if (++j == CGP_PT_BUFFER_SIZE)
        {
            curPtBuff = curPtBuff->nextPtBuffer;
            curPt = curPtBuff->pts;
            j = 0;   /* used to keep track of points processed in */
                     /*  current pt buffer                        */
        }
        else
            curPt++;

        /* fourth point is bottom right */
        curPt->header |= CGP_POINT_HDR_REPLACE_MIDDLE;

        /* advance to next point */
        if (i != numQuads)
        {
            if (++j == CGP_PT_BUFFER_SIZE)
            {
                curPtBuff = curPtBuff->nextPtBuffer;
                curPt = curPtBuff->pts;
                j = 0;   /* used to keep track of points processed in */
                         /*  current pt buffer                        */
            }
            else
                curPt++;
        }
    }
}





