#pragma ident "@(#)api.txt 1.12 99/04/26 SMI"


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



The following is a breif description of the geometry compression
utility API.  The definition of the compressed geometry buffer is
subject to change in future revisions.


Compression Utility API:

cgGetError()
        Returns current error.  Operates just like glGetError().
        The following are the valid error codes:

        CG_NO_ERROR
                No error has occurred.  This value is guaranteed
                to be zero.

        CG_DATA_INCONSISTENT
                Inconsistent data between cgBegin - cgEnd pairs.
                All vertices must be the same or a subset of the first
                vertex.  For instance the following would generate a
                CG_DATA_INCONSISTENT error:
                        cgBegin(CG_TRIANGLE)
                                cgVertex(..)
                                cgVertex(..)
                                cgNormal(..)
                                cgVertex(..)
                        cgEnd() 

                An attempt was made to mix different primitive classes
                (see cgBegin) within the same compressed geometry buffer.
                Mixing cgColor3 and cgColor4 within a cgBegin/cgEnd pair
                will also result in a CG_DATA_INCONSISTENT error.

        CG_INVALID_ENUM
                An unacceptable value has been specified for an enumerated
                argument.

        CG_OUT_OF_MEMORY
                Ran out of memory.  The state of the compression library
                is undefined after this error occurs.

        CG_INVALID_OPERATION
                Invalid operation performed during a cgBegin - cgEnd pair.

                cgEnd called before the corresponding cgBegin is called.

                Any cg command called outside a cgBeginCompressedGeometryStream


cgBeginCompressedGeometryStream(CGint geomQuant, CGint normalquant,
                                CGint colorQuant, 
                                CGenum quantEnforcement)

        geomquant, colorQuant - number of bits to compress geometry/color.
                16 bits maximum.
        normalQuant - number of bits to compress normals. 18 bits maximum.

        quantEnforcement - is the compression routine allowed to increase
                quantization to reduce quantization errors?  Applies
                to position quantization only.

        Initiates the building of a compressed geometry buffer.


cgEndCompressedGeometryStream(CGubyte** data, CGint size, CGviewport *viewport)

        CGubyte**    data     - will point to the compressed geometry buffer
        CGint        size     - size (in bytes) of entire buffer
        CGviewport*  viewport - viewport needed to reposition data to
                                original location

        Terminates the building of the compressed geometry buffer.  If
        there were no errors while entering in the points, the compressed
        geometry buffer will be allocated (using malloc) by the compression
        routine.  The caller is responsible for freeing this memory.

        All compressed data must be in the range of -1.0 to 1.0.  If data
        is not in this range, the compression routine will perform the
        necessary steps to place it within the -1.0 to 1.0 range. The
        viewport parameter is filled in with the necessary scale and offset
        values to return the data to it's original position.

        typedef struct {
                float scale;
                float ox, oy, oz;
        } CGviewport

        See the description of glDrawCompressedGeometrySUN for details on
        how to use this for proper rendering.

cgBegin, cgEnd
        Delimit the vertices that define a primitive or a group of like
        primitives.  cgBegin accepts a single argument that specifies which
        way the vertices are interpreted, as follows:

                CG_POINTS
                        a.g.a GL_POINTS

                CG_LINES
                        a.k.a GL_LINES

                CG_LINE_STRIP
                        a.k.a GL_LINE_STRIP

                CG_LINE_LOOP
                        a.k.a GL_LINE_LOOP

                CG_TRIANGLES
                        a.k.a GL_TRIANGLES

                CG_TRIANGLE_STRIP
                        a.k.a GL_TRIANGLE_STRIP

                CG_TRIANGLE_FAN
                        a.k.a GL_TRIANGLE_FAN

                CG_QUADS
                        a.k.a GL_QUADS

                CG_QUAD_STRIP
                        a.k.a GL_QUAD_STRIP

                CG_POLYGON
                        a.k.a GL_POLYGON

        A compressed geometry buffer must consist of only one "class" of
        primitive.  The primitives are divided up into 3 classes:
                Point Class - CG_POINTS
                Line Class  - CG_LINES, CG_LINE_STRIP, CG_LINE_LOOP
                Fill Class  - CG_TRIANGLES, CG_TRIANGLE_STRIP,
                                CG_TRIANGLE_FAN, CG_QUADS, CG_QUAD_STRIP,
                                CG_POLYGON
        An attempt to put primitives of different classes into the same
        compressed geometry buffer is an error (CG_DATA_INCONSISTENT).

        The following are the commands which are valid between
        a cgBegin - cgEnd pair: cgVertex, cgColor and cgNormal.
        Functions as glBegin and glEnd, respectively with the following
        restriction: all data between a cgBegin - cgEnd pair must be
        subset of the data type of the first vertex.  For instance,
        if the first vertex is:
                cgNormal()
                cgVertex()
        then all subsequent vertices must be either:
                cgVertex()
        or:
                cgNormal()
                cgVertex()
        a point with color information:
                cgColor()
                cgVertex()
        would be an error and the CG_DATA_INCONSISTENT error would
        be set.  The inconsistent data would be ignored but processing
        would continue.  If a vertex is encountered that is a subset of
        the first vertex then any color or normal information needed will
        be copied from the last color or normal value set.


cgColor
        cgColor3[b,d,f,i,s,ub,ui,us][v]
        cgColor4[b,d,f,i,s,ub,ui,us][v]

        Changes current color as glColor.  Can be called  at anytime after
        cgBeginCompressedGeometryStream() is called.  The color is clamped
        to the range [0.0..1.0] before being compressed.  The default color
        is: (1.0, 1.0, 1.0, 1.0) (r,g,b,a).

        Index colors are not supported.

cgNormal
        cgNormal3[b,d,f,i,s][v]

        Changes current normal as glNormal - all normals must be
        normalized.  Can be called  at anytime after
        cgBeginCompressedGeometryStream() is called.  The default
        normal is (0.0, 0.0, 1.0).

cgVertex
        cgVertex3[d,f,i,s][v]

        Specifies polygon vertices as glVertex

cgGeomFrontFace
        CG_CW, CG_CCW, the default is CG_CCW

        Specifies the orientation of front-facing polygons.  During
        decompression, this attribute is combined with glFrontFace to come
        up with the proper winding value.  If the orientation is CG_CCW,
        then glFrontFace is used unchanged; if the orientation is CG_CW,
        then glFrontFace is inverted: GL_CW becomes GL_CCW and GL_CCW
        becomes GL_CW.  The state of glFrontFace is not affected for
        non-compressed geometry.

        This function should only be called between cgBeginCompressedGeometryStream()
	and cgEndCompressedGeometryStream() and before any cgBegin()/cgEnd() pair.
	Its value applies to all primitives within a compressed geometry buffer.

Vertex Arrays

        For this release there will be no vertex array equivalent for the
        cg routines.



Decompression Utility API:

        cgDecompressGeometryStream(cgData, ugData, ugSize)

        CGubyte** cgData   - pointer to the compressed geometry buffer
        CGuint*  ugData   - pointer to the uncompressed data buffer.
                            This buffer is created (via malloc) and it is the
                            user's responsibility to free it.

        CGuint* ugSize   - will hold the size of the uncompressed buffer
                                        in 32-bit words.

       Takes the compressed geometry buffer, and decompresses
        it into a buffer with the format:

        CGuint type   /* data type */
        variable length data

        type is one of:
                CG_LINE_STRIP
                CG_POINTS
                CG_SET_COLOR3
                CG_SET_COLOR4
                CG_SET_FRONTFACE
                CG_SET_NORMAL
                CG_TRIANGLE_FAN
                CG_TRIANGLE_STRIP

        The following are the formats for all of the various objects:

        CG_LINE_STRIP
                CGuint  type;   /* CG_LINE_STRIP */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_POINTS
                CGuint  type;   /* CG_POINTS */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_SET_COLOR3
                CGuint  type;   /* CG_SET_COLOR3 */
                CGfloat red;
                CGfloat green;
                CGfloat blue;

        CG_SET_COLOR4
                CGuint  type;   /* CG_SET_COLOR4 */
                CGfloat red;
                CGfloat green;
                CGfloat blue;
                CGfloat alpha;

        CG_SET_FRONTFACE
                CGuint  type;   /* CG_SET_FRONTFACE */
                CGuint  val;    /* stick with CG_CW/CCW */

        CG_SET_NORMAL
                CGuint  type;   /* CG_SET_NORMAL*/
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;

        CG_TRIANGLE_FAN
                CGuint  type;   /* CG_TRIANGLE_FAN */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */

        CG_TRIANGLE_STRIP
                CGuint  type;   /* CG_TRIANGLE_STRIP */
                CGuint  ptType; /* CG_COLOR | CG_ALPHA | CG_NORMAL */
                CGuint  numPts;

                /* followed by numPts vertices of type ptType */


        Point formats

        Vertex3d
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Normal Vertex3d
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Color Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        ColorAlpha Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat alpha;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        Color Normal Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;

        ColorAlpha Normal Vertex3d
                CGfloat r;
                CGfloat g;
                CGfloat b;
                CGfloat alpha;
                CGfloat nx;
                CGfloat ny;
                CGfloat nz;
                CGfloat x;
                CGfloat y;
                CGfloat z;


OpenGL API:

When geometry compression is present in the library the extension string
GL_SUNX_geometry_compression will be listed in the GL_EXTENSIONS string.

glDrawCompressedGeometrySUNX(data, size)

        GLubyte*   data;
        GLuint     size;  /* size of data in bytes */

        Draws compressed geometry.  When drawing with glPolygonMode
        set to GL_LINE, all edges are considered to be external. All
        current attributes are inherited (ex: glMaterial, current glColor...).
        Upon return, the current color and current normal are undefined.

        For this release, texture attributes are not allowed.

        All data in a compressed geometry stream is in the range of
        -1.0 to 1.0.  To place the compressed geometry back to its
        original position in the scene a scale and offset value may need
        to be appended to the modelview matrix.

        For example:

                glPushAttrib(GL_MATRIX_MODE);   // If modelview not current mx
                glMatrixMode(GL_MODELVIEW);     // If modelview not current mx
                glPushMatrix();                 // If not a leaf matrix
                glTranslatef(xo, yo, zo);
                glScalef(scale, scale, scale);
                glDrawCompressedGeometrySUNX(data, size);
                glPopMatrix();                  // If not a leaf matrix
                glPopAttrib();                  // If modelview not current mx
                

        One problem - normals.

        When OpenGL computes the inverse transpose of the modelview matrix
        (needed to transform the normals), it does not rescale the normals.
        This can result in incorrect lighting.  To correct this problem
        there are three possible solutions:

                Set GL_RESCALE_NORMAL_EXT if present.

                If the above extension is not present then set
                GL_NORMALIZE.


glGetString(GL_COMPRESSED_GEOM_ACCELERATED_SUNX);

        Used to check for the presence of hardware that supports compressed
        geometry.  Returns either the highest version number supported by
        the hardware or NULL if the hardware does not support compression
        at all.  The version number is major.minor.minor-minor.

glGetString(GL_COMPRESSED_GEOM_VERSION_SUNX);

        Returns the highest version number of the compressed geometry buffer
        format supported by the software library. The version number is
        major.minor.minor-minor.
                 
Format of compressed geometry buffer:
        The compressed geometry buffer is a byte stream of data.

        The first 48 bytes are header info:
                1 byte major number
                1 byte minor version number
                1 byte minor-minor version number
                1 byte buffer type field
                1 byte data present field
                23 bytes reserved (must be 0)
                4  byte floating point scale (big endian)
                4  byte floating point xoffset
                4  byte floating point yoffset
                4  byte floating point zoffset
                4  byte Size (in bytes) of compressed geometry (including
                    header)
                        byte 1 - bits 31..24
                        byte 2 - bits 23..16
                        byte 3 - bits 15..8
                        byte 4 - bits  7..0

        The valid values for the buffer type field are:
                0x01    Point buffer
                0x02    Line buffer
                0x04    Triangle buffer

        The valid values for the data present field are:
                0x01    normal present in buffer
                0x02    color present in buffer
                0x04    color alpha present in buffer

        The next Size - header bytes is the compressed geometry buffer.


        The valid formats for the compressed geometry are:

        (Note the first 8 bits of an instruction are called the instrucion's
         header)

        Vertex
        
        +-------------------------------+   +---------------------------- ~ +
        |   |   |   |   |   |   |   |   |   |   |   |   |                   |
        | 0 | 1 |  Pos Bits n - (n -5)  |   |  rep  |mbp| Pos (n - 6) - 0   | 
        +-------------------------------+   +---------------------------- ~ +

         +- - - - - - - - - - - - - - ~ -+   +- - - - - - - - - - - - - - ~ -+
         |                               |   |                               |
         |       Normal Bits n - 0       |   |        Color Bits n - 0       | 
         +- - - - - - - - - - - - - - ~ -+   +- - - - - - - - - - - - - - ~ -+

                rep - vertex replacement (this field ignored for points)
                 00 - Restart clockwise (move for lines)
                 01 - Restart counter-clockwise (move for lines)
                 10 - Replace middle (draw for lines)
                 11 - Replace oldest (draw for lines)

                mbp - mesh buffer push
                  0 - No push
                  1 - Push

                The position is a variable length Huffman tag (0 - 6 bits)
                followed by three fields of variable but equal length for
                the X, Y, and Z components, which are either absolute or
                delta values.  The format for the position data is s.15 (less
                than 15 bits can be used for greater compression).

                If the bnv bit is set (via a Set State call) a normal is
                included.  The encoded normal has a Huffman tag followed by
                either two variable length data fields for delta u and
                delta v or a fixed length field consisting of 3 bits for
                the sextant and 3 bits for the octant followed by two variable
                length fields of up to 6 bits each for u and v (or delta-u and
                delta-v).  u and v are used as indices into the normal look-up
                table.

                If the bcv bit is set (via a Set State call) a color is
                included with the vertex.  A Huffman tag is followed by
                three equal but variable length fields for R, G, and B.  The
                cap bit (set via a Set State call) indicates if a field for
                Alpha is included.  The format for the color data is
                s.15 (less than 15 bits can be used for greater compression).
                

        Normal

        +-------------------------------+   +---------------------------- ~ +
        |   |   |   |   |   |   |   |   |   |                               |
        | 1 | 0 | Norm Bits n - (n - 5) |   |   Normal Bits (n - 6) - 0     | 
        +-------------------------------+   +---------------------------- ~ +


                The Set Normal instruction sets the value of the current
                normal.  The encoded normal has a Huffman tag followed by
                either two variable length data fields for delta u and
                delta v or a fixed length field consisting of 3 bits for
                the sextant and 3 bits for the octant followed by two variable
                length fields of up to 7 bits each for u and v (or delta-u and
                delta-v).  u and v are used as indices into the normal look-up
                table.  The value of u and the value of v must be less than
                or equal to 64.


        Color

        +-------------------------------+   +---------------------------- ~ +
        |   |   |   |   |   |   |   |   |   |                               |
        | 1 | 1 | Color Bits n - (n - 5)|   |    Color Bits (n - 6) - 0     | 
        +-------------------------------+   +---------------------------- ~ +

                The Set Color instruction sets the value of the current
                color.  The color data is encoded the same as the color
                data in the Vertex command. The format for the color data is
                s.15 (less than 15 bits can be used for greater compression).


        Mesh Buffer Reference

        +-------------------------------+   +---+
        |   |   |   |   |   |   |   |   |   |   |
        | 0 | 0 | 1 |     Index     |rep|   |rep| 
        +-------------------------------+   +---+

                rep - vertex replacement
                 00 - Restart clockwise
                 01 - Restart counter-clockwise
                 10 - Replace middle
                 11 - Replace oldest

                This instruction causes data from an entry in the mesh
                buffer to be used.  The index indicates the entry from
                the mesh buffer to send.  The newest entry in the mesh
                buffer has index 0, and the oldest has index 15.  If more
                than 16 entries are pushed onto the mesh buffer, the oldest
                entry is discarded.

                If the bnv (or bcv) bit is set and a Set Normal (or
                Set Color) command is issued, then the next Mesh Buffer
                Reference will use the current normal (or color) 
                and not the mesh buffer normal. If a Vertex or Set State
                instruction comes between the Set Normal or Set Color
                instruction and the Mesh Buffer Reference instruction,
                the data will come from the mesh buffer.

                Ex:
                        V, N0 (mesh buffer push)
                        V, N1
                        Set Normal N2
                        MBR 0 (uses normal N2)
                        Set Normal N3
                        V, N4
                        MBR 0 (uses normal N0)
                        


        Set State

        +-------------------------------+   +-----------+
        |   |   |   |   |   |   |   |   |   |   |   |   |
        | 0 | 0 | 0 | 1 | 1 |rsv|rsv|bnv|   |bcv|cap|rsv| 
        +-------------------------------+   +-----------+

                rsv - reserved must be set to 0
                bnv - bundle normals with vertices
                bcv - bundle colors with vertices
                cap - color alpha present

                Sets the indicated value(s).


        Set Table

        +---------------------------------------------------------------------+
        |   |   |   |   |   |   |   |   |   |   |   |   |   |   |             |
        | 0 | 0 | 0 | 1 | 0 |  tbl  |           Address         |Entry(9 bits)|
        +---------------------------------------------------------------------+

                tbl - table selection
                 00 - Position table
                 01 - Color table
                 10 - Normal table
                 11 - undefined

                Sets entries in the Huffman table.  The Huffman tables are
                used to decode the Huffman tags preceding the compressed data.
                In order to send down any data, the Huffman tables must be
                initialized to their proper values.  Not initializing the
                Huffman tables will yield unpredictable results.

                Table settings are made in aligned power of two ranges; the
                position of the first '1' bit in the address field indicates
                how many entries are to be consecutively set; the remaining
                bits after the first '1' are the upper address bits of the
                base table entries to be set.  This also sets the length of
                the "tag" that this entry defines as equal to the number of
                leading zero bits (if any) before the first '1' bit.

                Address Semantics                       Tag Length
                1xxxxxx set table entry xxxxxx                  6
                01aaaaa set table entries xxxxx0-xxxxx1         5
                001xxxx set table entries xxxx00-xxxx11         4
                0001xxx set table entries xxx000-xxx111         3
                00001xx set table entries xx0000-xx1111         2
                000001x set table entries x00000-x11111         1
                0000001 set table entries 000000-111111         0

                The tables entries look like:

                +-----------------------------------------------+
                |   |   |   |   |   |   |   |   |   |   |   |   |
                |  tag_len  |   data_len    |a/r|    Shift      | 
                +-----------------------------------------------+

                 tag_len  - length of the Huffman tag.  The tag_len and
                                data_len field must add to a minimum of 6.
                 data_len - length of the data fields that follow the
                                huffman tag.  For color and position data,
                                a zero in this field means the data is 16 bits
                                in length.  The data_len value for normals is
                                the length of either an u/v entry or a du/dv
                                entry.  For the absolute case, the
                                sextant/octant bits are not counted in the
                                data_len field.  This length is the length
                                from the first significant bit to the end.
                                The tag_len and data_len field must add to
                                a minimum of 6.
                 a/r      - absolute data (1) or relative to previous value (0)
                 Shift    - quantization level (number of trailing zeroes)

                The tag_len field is derived from the address.  The address
                is a variable length Huffman code.


        VNOP

        +-------------------------------+   +---------------------------- ~ +
        |   |   |   |   |   |   |   |   |   |   |   |   |   |   |           |
        | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |   |      Bit Count    |    0's    | 
        +-------------------------------+   +---------------------------- ~ +

                Encodes a variable number of 0 bits into the data stream.
                The bit count field specifies the number of 0 bits that follow.
                This instruction can be used to align data to 64-bit word
                boundaries.  An implicit VNOP header is always assumed to start
                a compressed geometry buffer.


        Reserved

        +-------------------+
        |   |   |   |   |   |
        | 0 | 0 | 0 | 0 | 1 |
        +-------------------+

                This op-code is reserved for future use.


Building a Compressed Geometry Buffer

        A compressed geometry buffer stream has the format of:

                header (first 8 bits) of instrucion N
                data (remaining bits after header) for instruction N - 1
                header for instruction N + 1
                data for instruction N
                ...

        Further, a compressed geometry buffer is always assumed to start
        with an implicit VNOP header so the start of a compressed geometry
        buffer looks like:

                header of first user instruction
                data for implicit VNOP instruction
                header of next user instruction
                data for first user instruction


        Whenever color or normal information is bundled with a vertex, the
        first 6 bits of the color/normal data are treated as the instruction
        header:

                vtx header
                data for previous instruction
                color/normal header (first 6 bits)
                vtx data
                header for next instruction
                color/normal data

        A buffer must always end on a 64 bit boundary and with a vnop
        header with no data field:

                VNOP header
                data for previous instruction
                VNOP header (the empty VNOP command)
                VNOP data (with 0's to align data to 64 bit boundary)

        The minimum value of: tag_length + (data_length - data_shift) is
        6.
