SGO.TXT

SGO.TXT


Remove Frame

Copyright  1993, Silicon Graphics, Inc. All rights reserved.
Silicon Graphics and the Silicon Graphics logo are registered
trademarks, and SGO is a trademark of Silicon Graphics.
Specifications are subject to change without notice.




    SGO File Format

    SGO = (Silicon Graphics Object)

    SGO format is a format slightly more complicated that Spin format,
    but still quite simple.  It allows lists of quadrilaterals, lists
    of triangles and triangle meshes.

    The first word in the file is the SGO magic number:

    word 1: 0x5424  (4 bytes)

    Following next is a set of objects:

    <object type 1 token>
    <data for object 1>
    <object type 2 token>
    <data for object 2>
    .
    .
    .
    <object type n token>
    <data for object n>
    <end data token>

    Each of the tokens is 4 bytes long.  The tokens are:

    OBJ_QUADLIST    (= 1)
    OBJ_TRILIST     (= 2)
    OBJ_TRIMESH     (= 3)
    OBJ_END         (= 4)   the end of data token.

    The next word following any of the three object types is the number
    of longs in the data for that object.

    For OBJ_QUADLIST and OBJ_TRILIST (quadrilateral list and triangle
    list), there are 9 floats of data for each vertex.  The first three
    are the components of the normal vector at the vertex; the next
    three are the color components (R, G, B), all between 0.0 and 1.0,
    and finally there are the components of the vertex itself.

    For the OBJ_QUADLIST, the points are simply taken 4 at a time, so
    there are 9*4 = 36 floats of data for each quadrilateral.  For the
    OBJ_TRILIST, the points are used 3 at a time, making 9*3 = 27
    floats per triangle.

    The triangle mesh (OBJ_TRIMESH) is the most complicated of the
    three.  The data consist of a set of vertices followed by a set of
    mesh control commands.  The data for each vertex is the same as
    above -- 9 floats.  The mesh controls consist of:

    OP_BGNTMESH             (= 1)
    OP_SWAPTMESH            (= 2)
    OP_ENDBGNTMESH          (= 3)
    OP_ENDTMESH             (= 4)

    Following the number of longs required for the entire triangle mesh
    data is the number of floats required for the vertex data (at 9
    floats per vertex).  Next comes the vertex data, and the rest of
    the data are longs containing triangle mesh controls.

    For example, a file containing a single triangle mesh object with
    four vertices, and nine mesh controls would look like this:

    word 1: 0x5424
    word 2: OBJ_TRIMESH
    word 3: 42 = 4*9 + 1 + 5
    word 4: 36 (length of data for 4 vertices)
    word 5-40: vertex data
    word 41-49: mesh controls
    word 50: OBJ_END

    When the triangle mesh is drawn, the controls are interpreted one
    at a time.  The first control is assumed to be an OP_BGNTMESH.
    After each control is a long indicating how many vertex indices
    will follow.  The vertex indices are in byte offsets. For example,
    vertex n is offset by n*9*4.

    To understand triangle meshes, consider the following example.
    Suppose there are 6 points arranged as follows:

    0-----2-----4 
     \   / \   / \
      \ /   \ /   \
       1-----3-----5

    To draw the triangles 012, 123, 234, and 345, the control sequence
    (the mesh controls) would be:

    OP_BGTMESH 6 0*9*4 1*9*4 2*9*4 3*9*4 4*9*4 5*9*4 OP_ENDTMESH

    Two vertices are recorded in the hardware.  As each new vertex is
    sent, a triangle is output with the two saved vertices and the new
    one.  Then the oldest vertex is discarded and is replaced by the
    second oldest, and the new vertex replaces the second oldest.  For
    the sequence above, the state looks like this:

			    Saveold         Savenew         Output Triangle
			    -------         -------         ------
    OP_BGNTMESH:            invalid         invalid         nothing
    point 0:                invalid         point 0         nothing
    point 1:                point 0         point 1         nothing
    point 2:                point 1         point 2         0-1-2
    point 3:                point 2         point 3         1-2-3
    point 4:                point 3         point 4         2-3-4
    point 5:                point 4         point 5         3-4-5
    OP_ENDTMESH:            invalid         invalid         nothing

    This is great if all you want to do is go down a ribbon outputting
    triangles.  If you want to turn a corner, or to have multiple
    sequences, OP_SWAPTMESH reverses the contents of the Saveold and
    Savenew registers, and OP_ENDBGNTMESH is ends the current sequence
    and begins a new one.

    One final example should illustrate this:


    0-----2-----4 
     \   / \   / \
      \ /   \ /   \
       1-----3-----5

	   14-----13
	   / \   / \
	  /   \ /   \
   6-----8----10-----12
    \   / \   / \   /
     \ /   \ /   \ /
      7-----9-----11

    To draw the pattern above, use the following mesh control sequence:

    OP_BGNTMESH, 6, 0*9*4, 1*9*4, 2*9*4, 3*9*4, 4*9*4, 5*9*4,
    OP_ENDBGNTMESH, 6, 6*9*4, 7*9*4, 8*9*4, 9*9*4, 10*9*4, 11*9*4,
    OP_SWAPTMESH, 1, 12*9*4, OP_SWAPTMESH, 1, 13*9*4, OP_SWAPTMESH, 2,
    14*9*4, 8*9*4, OP_ENDTMESH

			    Saveold         Savenew         Output Triangle
			    -------         -------         ------
    OP_BGNTMESH:	    invalid         invalid         nothing
    point 0:                invalid         point 0         nothing
    point 1:                point 0         point 1         nothing
    point 2:                point 1         point 2         0-1-2
    point 3:                point 2         point 3         1-2-3
    point 4:                point 3         point 4         2-3-4
    point 5:                point 4         point 5         3-4-5
    OP_ENDBGNTMESH:         invalid         invalid         nothing
    point 6:                invalid         point 6         nothing
    point 7:                point 6         point 7         nothing
    point 8:                point 7         point 8         6-7-8
    point 9:                point 8         point 9         7-8-9
    point A:                point 9         point A         8-9-A
    point B:                point A         point B         9-A-B
    OP_SWAPTMESH:           point B         point A         nothing
    point C:                point A         point C         B-A-C
    OP_SWAPTMESH:           point C         point A         nothing
    point D:                point A         point D         C-A-D
    OP_SWAPTMESH:           point D         point A         nothing
    point E:                point A         point E         D-A-E
    point 8:                point E         point 8         A-E-8
    OP_ENDTMESH:            invalid         invalid         nothing
     
*/

#include <stdio.h>

#define OBJ_QUADLIST        1
#define OBJ_TRILIST	    2
#define OBJ_TRIMESH         3
#define OBJ_END             4

#define OP_BGNTMESH         1
#define OP_SWAPTMESH        2
#define OP_ENDBGNTMESH      3
#define OP_ENDTMESH         4

FILE        *fp;

long        meshctl[27] = {
    OP_BGNTMESH, 6, 0, 1*9*4, 2*9*4, 3*9*4, 4*9*4, 5*9*4, OP_ENDBGNTMESH,
    6, 6*9*4, 7*9*4, 8*9*4, 9*9*4, 10*9*4, 11*9*4, OP_SWAPTMESH,
    1, 12*9*4, OP_SWAPTMESH,
    1, 13*9*4, OP_SWAPTMESH, 2, 14*9*4, 8*9*4, OP_ENDTMESH };

float       meshdata[15][3] = {
    {3, 11, 0}, {5, 8, 0}, {7, 11, -1}, {9, 8, 0}, {11, 11, 0}, {13, 8, -1},
    {2, 3, 0}, {4, 0, 0}, {6, 3, -1}, {8, 0, 0}, {10, 3, 1}, {12, 0, -1},
    {14, 3, 3}, {12, 6, 2}, {8, 6, -2}
};

float meshnorm[15][3] = {
    {0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0},
    {0, 0, 1}, {0, 1, 0}, {1, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0},
    {0, 0, 1}, {0, 1, 0}, {1, 0, 0}
};

float       cube[8][3] = {
    {-1.0, -1.0, -1.0},
    {-1.0, -1.0, 1.0},
    {-1.0, 1.0, 1.0},
    {-1.0, 1.0, -1.0},
    {1.0, -1.0, -1.0},
    {1.0, -1.0, 1.0},
    {1.0, 1.0, 1.0},
    {1.0, 1.0, -1.0},
};

float       ncube[6][3] = {
    {1.0, 0.0, 0.0},
    {-1.0, 0.0, 0.0},
    {0.0, 1.0, 0.0},
    {0.0, -1.0, 0.0},
    {0.0, 0.0, 1.0},
    {0.0, 0.0, -1.0},
};

float nullcolor[3] = { 0.0, 0.0, 0.0 };

writesgomesh()
{
    long    typeandcount[3];
    long    i;
    
    typeandcount[0] = OBJ_TRIMESH;
    typeandcount[1] = 15*9 + 1 + 27;
    typeandcount[2] = 15*9;
    fwrite(&typeandcount[0], 4, 3, fp);
    for (i = 0; i < 15; i++) {
    fwrite(&meshnorm[i][0], 4, 3, fp);
    fwrite(&nullcolor[0], 4, 3, fp);
    fwrite(&meshdata[i][0], 4, 3, fp);
    }
    for (i = 0; i < 27; i++)
    fwrite(&meshctl[i], 4, 1, fp);
}

writesgocube()
{
    long    typeandcount[2];
    
    typeandcount[0] = OBJ_QUADLIST;
    typeandcount[1] = 6*36;
    fwrite(&typeandcount[0], 4, 2, fp);
    
    nw(0); vw(4); nw(0); vw(5); nw(0); vw(6); nw(0); vw(7);
    nw(1); vw(0); nw(1); vw(1); nw(1); vw(2); nw(1); vw(3);
    nw(2); vw(2); nw(2); vw(3); nw(2); vw(7); nw(2); vw(6);
    nw(3); vw(0); nw(3); vw(1); nw(3); vw(5); nw(3); vw(4);
    nw(4); vw(1); nw(4); vw(2); nw(4); vw(6); nw(4); vw(5);
    nw(5); vw(0); nw(5); vw(3); nw(5); vw(7); nw(5); vw(4);
}

vw(n)
long n;
{
    fwrite(&cube[n][0], 4, 3, fp);
}

nw(n)
long n;
{
    fwrite(&ncube[n][0], 4, 3, fp);
   fwrite(&nullcolor[0], 4, 3, fp);
}

octvert(n)
long        n;
{
    fwrite(&ncube[n][0], 4, 3, fp);
    fwrite(&nullcolor[0], 4, 3, fp);
    fwrite(&ncube[n][0], 4, 3, fp);
}

sgotri(a, b, c)
long        a, b, c;
{
    octvert(a); octvert(b); octvert(c);
}

writesgooct()
{
    long    typeandcount[2];
    
    typeandcount[0] = OBJ_TRILIST;
    typeandcount[1] = 8*27;
    fwrite(&typeandcount[0], 4, 2, fp);
    sgotri(0, 2, 5);
    sgotri(0, 5, 3);
    sgotri(0, 3, 4);
    sgotri(0, 4, 2);
    sgotri(1, 2, 5);
    sgotri(1, 5, 3);
    sgotri(1, 3, 4);
    sgotri(1, 4, 2);
}

main()
{
    long end = OBJ_END;
    
    /* comment out all but one of the next three lines */
    writesgoheader();
    /*writesgocube();*/
    /*writesgooct();*/
    writesgomesh();
    fwrite(&end, 4, 1, fp);
    fclose(fp);
}

writesgoheader(polycount)
long        polycount;
{
    long    magic;
    
    magic = 0x5424;
    
    fp = fopen("sgoout", "w");
    fwrite(&magic, 4, 1, fp);
}