#pragma ident "@(#)cgpvertex.c 1.6 97/11/05 SMI"

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


/******************************************************************************
 * cgpvertex.c
 *
 * This file contains all the vertex compressed geometry routines.
 *
 *  List of functions in this file:
 *      cgVertex3f
 *      cgVertex3fv
 *      cgVertex3d
 *      cgVertex3dv
 *      cgVertex3i
 *      cgVertex3iv
 *      cgVertex3s
 *      cgVertex3sv
 *
 *****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include "cgpi.h"

/* these reside in cgpmisc.c */
extern CGenum           CgError;

extern CGbitfield       CurrentState;           /* state of CG library       */

extern CGenum           CurFrontFace;
extern CGfloat          CurNX;                  /* global normal             */
extern CGfloat          CurNY;
extern CGfloat          CurNZ;
extern CGfloat          CurRed;                 /* global color              */
extern CGfloat          CurGreen;
extern CGfloat          CurBlue;
extern CGfloat          CurAlpha;

extern CGPprimlist*     Prims;                  /* list of primitives        */
extern CGPprimlist*     CurPrim;                /* current primitive         */
extern CGuint           NumPrims;               /* total number of primitives*/

extern CGPptbuffer*     CurPtBuffer;            /* Buffer being filled       */
extern CGPpoint*        CurPt;                  /* Point being processed     */
extern CGuint           NumPts;                 /* number of points in       */
                                                /*  current buffer           */

/* need max/min geom values to compute scale/offset */
extern CGfloat  MaxX;
extern CGfloat  MinX;
extern CGfloat  MaxY;
extern CGfloat  MinY;
extern CGfloat  MaxZ;
extern CGfloat  MinZ;

/*******************
 * cgVertex3f
 *
 *  Used to update the current vertex using CGfloat values.
 *
 *  Input:
 *    CGfloat  x.
 *    CGfloat  y.
 *    CGfloat  z.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3f (CGfloat x, CGfloat y, CGfloat z)
{
    CGbitfield    primFlags;

    /* must be within a BeginStream and a cgBegin for this to be valid */
    if (!(CurrentState & CGP_CS_LIB_IN_BEGIN_STREAM) ||
        !(CurrentState & CGP_CS_LIB_IN_CGBEGIN))
    {
        cgiSetError(CG_INVALID_OPERATION);
        return;
    }

    primFlags = CurPrim->primitive.primFlags;

    /* Can no longer be the first vertex */
    CurrentState &= ~CGP_CS_LIB_NO_VERTEX;

    /* copy point */
    CurPt->x = x;
    CurPt->y = y;
    CurPt->z = z;

    /* compare to min & max values -  for viewport */
    if (x > MaxX)
        MaxX = x;
    if (x < MinX)
        MinX = x;
    if (y > MaxY)
        MaxY = y;
    if (y < MinY)
        MinY = y;
    if (z > MaxZ)
        MaxZ = z;
    if (z < MinZ)
        MinZ = z;

    /* check to see if this point needs any other data */
    if (primFlags & CGP_PT_TYPE_VTX_COLOR &&
        !(CurrentState & CGP_CS_VTX_HAS_COLOR))
    {
        /* add last color value */
        CurPt->r = CurRed;
        CurPt->g = CurGreen;
        CurPt->b = CurBlue;
    }

    if (primFlags & CGP_PT_TYPE_VTX_COLOR_ALPHA &&
        !(CurrentState & CGP_CS_VTX_HAS_ALPHA))
    {
        /* add last color value */
        CurPt->a = CurAlpha;
    }

    if (primFlags & CGP_PT_TYPE_VTX_NORMAL &&
        !(CurrentState & CGP_CS_VTX_HAS_NORMAL))
    {
        /* add last color value */
        CurPt->nX = CurNX;
        CurPt->nY = CurNY;
        CurPt->nZ = CurNZ;
    }

    /* move to next point */
    NumPts++;
    CurPrim->primitive.numPts++;
    CurrentState &=
        ~(CGP_CS_VTX_HAS_COLOR | CGP_CS_VTX_HAS_ALPHA | CGP_CS_VTX_HAS_NORMAL);
 
    /* at end of current point list? */
    if (NumPts == CGP_PT_BUFFER_SIZE)
    {
        /* add another pt list structure */
        CurPtBuffer->nextPtBuffer =
            (CGPptbuffer *) malloc(sizeof(CGPptbuffer));

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

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


        CurPt = &CurPtBuffer->pts[0];
        NumPts = 0;
    }
    else
    {
        /* just inc to next point in current buffer */
        CurPt++;
    }
}


/*******************
 * cgVertex3fv
 *
 *  Used to update the current vertex using a CGfloat array.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGfloat *v.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3fv (const CGfloat *v)
{
    cgVertex3f(*v++, *v++, *v);
}


/*******************
 * cgVertex3d
 *
 *  Used to update the current vertex using CGdouble values.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGdouble  x.
 *    CGdouble  y.
 *    CGdouble  z.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3d (CGdouble x, CGdouble y, CGdouble z)
{
    cgVertex3f((CGfloat) x, (CGfloat) y, (CGfloat) z);
}


/*******************
 * cgVertex3dv
 *
 *  Used to update the current vertex using a CGdouble array.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGdouble *v.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3dv (const CGdouble *v)
{
    cgVertex3f((CGfloat) *v++, (CGfloat) *v++, (CGfloat) *v);
}


/*******************
 * cgVertex3i
 *
 *  Used to update the current vertex using CGint values.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGint  x.
 *    CGint  y.
 *    CGint  z.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3i (CGint x, CGint y, CGint z)
{
    cgVertex3f((CGfloat) x, (CGfloat) y, (CGfloat) z);
}


/*******************
 * cgVertex3iv
 *
 *  Used to update the current vertex using a CGint array.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGint *v.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3iv (const CGint *v)
{
    cgVertex3f((CGfloat) *v++, (CGfloat) *v++, (CGfloat) *v);
}


/*******************
 * cgVertex3s
 *
 *  Used to update the current vertex using CGshort values.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGshort  x.
 *    CGshort  y.
 *    CGshort  z.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3s (CGshort x, CGshort y, CGshort z)
{
    cgVertex3f((CGfloat) x, (CGfloat) y, (CGfloat) z);
}


/*******************
 * cgVertex3sv
 *
 *  Used to update the current vertex using a CGshort array.
 *  Converts values to CGfloat and calls cgVertex3f.
 *
 *  Input:
 *    CGshort *v.
 *
 *  Output:
 *    None.
 *
 */
void
cgVertex3sv (const CGshort *v)
{
    cgVertex3f((CGfloat) *v++, (CGfloat) *v++, (CGfloat) *v);
}

