XGL/XPXGL Developer's Guide, version 1.1 for XGLv6
This document last modified:
Important Note: The master version of this document was created and is maintained with Adobe Go Live as HTML. Other formats are derived from the master document and may not look the same and/or links may not work. You may reach the most up-to-date master document, other information, downloads, and other formats of this document online at http://www.DSpotts.com
Table of Contents (toc)
XGL Overview
The XGL Header
XGL_FORMAT_TOKEN
XGL_VERSION_TOKEN
XGL_CURRENT_VERSION_VALUE
XGL_BOUNDING_BOX
General Purpose Tokens
XGL_FLOAT_ARRAY
XGL_INT_ARRAY
XGL_CHARS_ARRAY
XGL_RESET_MATERIAL
XGL_MATERIAL
XGL_SHAPE
Parsing XGL
The DrawShape Routines
Processing the ShapeHint Token
XGL Specification (IXGL.h)
XPXGL Extensions
03.03.19 - Version 1.1 - XGLv6 now includes the VRML CCW shape field (XGL_SHAPE_CCW_TOKEN), a new token (XGL_TEXTURE_INDICES_TOKEN) that defines the texture indices, and a modification of the data following an XGL_SHAPE to support additional VRML.
03.03.19 - Initial verison of this guide
XGL, or eXtensible Graphis Language, is a way of compactly expressing 3D modeling, scenery, and geo-spatial information in a platform independent manner.
XGL is currently a limited subset of VRML, and is compiled into a binary, "big-endian" format that is extremely fast to parse/load/render.
XPXGL, or X-Plane eXtensible Graphics Language adds additional tokens specific to X-Plane (hard surfaces, lights, etc.), and, most importantly, implements the single texture optimization and requirement for hi frame rates.
The purpose of this document is to document XGL (.xgl) and XPXGL (.xpxgl) and provide a guide for developers wishing to read, parse, render from, (or write) this format.
Throughout the rest of this document, I will refer to both as XGL, and point out specifics applicable to XPXGL (.xpxgl) files.
Tokens
XGL files consist at the simplest level of integer (4 byte) tokens, always followed by an integer (4 byte) token byte count indicating how many bytes follow, followed by the data itself (which can be other tokens). This is true for all tokens, even those that are "enclosed by" or "embedded in" other tokens.
All tokens and data are big-endian, which means this data can be read directly into memory on the Macintosh and other big-endian systems, but must be endian-swapped on Windows.
The simplest possible parser would be:
while(!eof) {
int sToken = readInteger();
int sTokenDataBytes = readInteger();
skipBytes(sTokenDataBytes);
}
This makes it possible to easily extend the format with new tokens. If you come across a token you don't know or care about, you simply use the technique above to skip over it's data.
Shapes
XGL files utilize the VRML model of Shapes, and currently supports the most important object type used in 3D modeling, which is an IndexedFaceSet. Unless otherwise specified, all shape-related tokens/data related to a shape occurr prior to the XGL_SHAPE primitive that they are associated with.
Prior to version 6 of the XGL spec, and before having access to VRML generated by other applications in addition to LightWave and/or more complex models, I believed that the first IndexedFaceSet (Shape) was always used to hold all of the vertices that define the geometry of the object (3 floats per vertex). These vertices are then referred to with indexes.
This is not always the case.
As it turns out there can be 2 VRML Shape objects per "Shape", and of course multiple Shapes (many polygons) per object... One shape holding the vertices for the shape, and another holding the indices (into the vertex list).
Prior to this discovery, XGL always used a single global vertex list (which is still supported) using an XGL_FLOAT_ARRAY after the first XGL_SHAPE command.
This array stored the global vertex list once in the XGL file to avoid duplication and bloating the file size, then simply indexed into this list with subsequent XGL_INT_ARRAY tokens along with each shape.
For backwards compatibility with existing XGL files (and code), I have modified XGL slightly to accommodate this new finding. Basically each XGL_SHAPE can now have it's own XGL_FLOAT_ARRAY. If it does, that float array (vertex list) should be loaded and used. If it does not, the previous (usually global) vertex array should be used.
This makes parsing a little tricker, but not terribly (you basically back up if the shape does not have it's own XGL_FLOAT_ARRAY)..
Like VRML, this is a very compact way of storing and referencing these vertices, but XGL has the advantage of storing these vertices in binary form, which (on the Mac), means you can read all of these vertices in using a single binary read (as well as other arrays, discussed later).
Materials
VRML (and XGL) allow the use of material specifications, which, depending on the modeling package and VRML export, are the following in VRML:
All of these have OpenGL equivalents. With the exception of shininess, there are 3 floats ranging from 0.0 to 1.0 for the red, green, and blue component.
Materials always come before an XGL_SHAPE.
Here is a code snippet to use them when rendering:
void XGLMaterial(int pType, float pFloats[]){
// pType is an OpenGL type such as GL_DIFFUSE, GL_SHININESS, GL_EMISSION, GL_SPECULAR
// pFloats is an array of 3 floats
float sFloats[] = {pFloats[0], pFloats[1], pFloats[2], 1.0};
if (pType == GL_SHININESS) {
glMaterialf(GL_FRONT, GL_SHININESS, 128.0 * sFloats[0]);
} else {
glMaterialfv(GL_FRONT, pType, sFloats);
}
}
The way materials work in OpenGL is that the currently selected material is automatically used for subsequent drawing commands bound to the current color. It is therefore important to RESET the materials to a non-visible state when mixing materials and textures.
In XGL, a XGL_RESET_MATERIAL tokens preceds each shape, followed by the materials for that shape.
The following has been found to work in my viewers:
void XGLResetMaterial(){
// black
float sColor[] = { 0.0, 0.0, 0.0, 1.0 };
glColor3f(sColor[0], sColor[1], sColor[2]);
glMaterialfv(GL_FRONT, GL_AMBIENT, sColor);
glMaterialfv(GL_FRONT, GL_DIFFUSE, sColor);
glMaterialfv(GL_FRONT, GL_SPECULAR, sColor);
glMaterialfv(GL_FRONT, GL_EMISSION, sColor);
glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
}
Textures
Most 3D modeling packages that we are aware of use separate texture files when building a model. Exporting VRML does not change this.
Each shape that uses a texture has a texture name (texture.png, .bmp, etc.), as well as texture floats (S&T parameters). As part of each shape that uses textures, there is an array of texture floats (2 floats per vertex in the shape) that define the S&T parameters to use for that vertex.
Lightwave always exported a texture index list that went from 0 to the number of vertices in the shape, so it was unnecessary to store this information in XGL.
Other VRML does not always do this, so we added the XGL_TEXTURE_INDICES_TOKEN to store the texture indices (0.. numTextureFloats/2) for the upcoming shape.
By either automatically merging textures or using an industry standard HTML image map, we have been able to modify these texture floats so that they refer to a portion of one large texture holding all textures for an object, needed for hi frame rates. Files ending in .xpxgl utilize this mechanism.
Below is a code snippet for parsing XGL from my xglutil tool:
///////////////////////////////////////////////////////////////////////////////////
// MAIN PARSER CODE
///////////////////////////////////////////////////////////////////////////////////
int xgl_process_next_token(){
int sToken;
int sType;
int sCount;
float sFloats[3];
if (!gReadHeader) {
sToken = getFirstToken();
printf("XGL_VERSION=%d\n",gXGLVersion);
if (gXGLVersion > XGL_CURRENT_VERSION_VALUE) {
gXGLResult = XGL_VERSION_ERROR;
cleanUp();
return(gXGLResult);
}
} else {
sToken = readNextToken();
gTotalTokens++;
}
switch(sToken) {
case XGL_TEXTURE_FILE_TOKEN:
debugln("XGL_TEXTURE_FILE_TOKEN\n");
int sNumTextures = readInt();
char sTextureName[XGL_MAX_STR_SIZE];
printf("sNumTextures=%d\n", sNumTextures);
for(int i = 0; i < sNumTextures; i++) {
readNextToken(); // XGL_CHAR_ARRAY
int sNumBytes = readInt();
int j;
for(j=0; j < sNumBytes; j++) {
sTextureName[j] = readChar();
}
sTextureName[j] = 0x00;
printf("texture[%d]=%s\n", i, gTextureNames[i]);
}
//XGLLoadTextures( gTextureNames, gTotalTextures);
break;
case XGL_TEXTURE_INDEX:
debugln("XGL_TEXTURE_INDEX");
int sIndex = readInt();
XGLSetTextureIndex(sIndex);
gCurrentTextureIndex = sIndex;
break;
case XGL_TEXTURE_FLOATS:
debugln("XGL_TEXTURE_FLOATS");
readNextToken(); // XGL_FLOAT_ARRAY
sCount = readInt();
readFloats(gTextureFloats, sCount);
XGLSetTextureFloats(gTextureFloats, sCount);
break;
case XGL_BOUNDING_BOX:
debugln("XGL_BOUNDING_BOX");
readNextToken(); // XGL_FLOAT_ARRAY
sCount = readInt();
// Always 3 floats for a bounding box
gBoundingBox[0] = readFloat();
gBoundingBox[1] = readFloat();
gBoundingBox[2] = readFloat();
debugFloats(gBoundingBox, 3);
printf("XGL_BOUNDING_BOX=[%f][%f][%f]\n",gBoundingBox[0], gBoundingBox[1], gBoundingBox[2]);
break;
case XGL_RESET_MATERIAL:
debugln("XGL_RESET_MATERIAL");
XGLResetMaterial();
break;
case XGL_MATERIAL:
debugln("XGL_MATERIAL");
gTotalMaterials++;
sType = readInt();
readNextToken(); // XGL_FLOAT_ARRAY
sCount = readInt();
// Always 3 floats for a material
sFloats[0] = readFloat();
sFloats[1] = readFloat();
sFloats[2] = readFloat();
XGLMaterial(sType, sFloats);
break;
case XGL_SHAPE:
debugln("XGL_SHAPE");
gTotalShapes++;
if (!gHaveFloats) {
readNextToken(); // XGL_FLOAT_ARRAY
sCount = readInt();
gTotalVertexes += sCount / 3;
gTotalFloats += sCount;
if(xgl_outOfBounds(sCount, XGL_MAX_FLOATS)){
return(gXGLResult);
}
readFloats(gFloats, sCount);
gFloatsInArray = sCount;
debugFloats(gFloats, sCount);
gHaveFloats = 1;
//cleanUp();
//return;
}
readNextToken(); // XGL_FLOAT_ARRAY
sCount = readInt();
if(xgl_outOfBounds(sCount, XGL_MAX_INTS)){
return(gXGLResult);
}
readInts(sCount);
XGLDrawShape(gFloats, gInts, sCount);
gTotalPolys += xgl_gShapeObjectCount;
break;
case XGL_END_OF_STREAM:
debugln("XGL_END_OF_STREAM");
return(XGL_FINISHED);
break;
case XGL_SHAPE_HINT_TOKEN:
printf("XGL_SHAPE_HINT_TOKEN\n");
int sHintData = readInt();
printf("HintData=0x%x\n", sHintData);
int sHint = sHintData & 0xff;
HandleHint(sHint, sHintData);
break;
default:
printf("Unknown token = %d, %d bytes\n", sToken, gLastTokenDataSize);
fseek(gFP , gLastTokenDataSize, SEEK_CUR);
break;
}
return(XGL_NO_ERROR);
}
int xgl_parse(char *pFileName){
debugln("Opening file\n");
gFP = fopen((const char*)pFileName, "rb");
if (gFP == NULL || ferror(gFP)) {
printf("error opening file %s\n", pFileName);
return(XGL_OPEN_ERROR);
}
gWeOpenedFile = 1;
while(!feof(gFP)) {
gXGLResult = xgl_process_next_token();
if (gXGLResult != XGL_NO_ERROR) {
break;
}
}
cleanUp();
if (gXGLResult == XGL_FINISHED) {
gXGLResult = XGL_NO_ERROR;
}
return(gXGLResult);
}
Below is a code snippet for the very important DrawShape routine, which, in this example, is used to write OBJv7:
///////////////////////////////////////////////////////////////////////////////////
// MAIN DRAW/OUTPUT CODE
///////////////////////////////////////////////////////////////////////////////////
void drawNextObject(float pPoints[], int pPointIndexes[], int pStartIndex, int pNumVertices) {
// Not outputting OBJ, nothing to do
if (gObjOutputFile == NULL) {
return;
}
int i;
// Guard against invalid objects
if (pNumVertices == 0) {
return;
}
// No texture index and skipping materials, nothing to do
if (xgl_gCurrentTexture == -1 && gSkipMaterials) {
return;
}
if (gDebug) {
#if _PRINTF_DEBUG_
sprintf(gTDS, "\nNumVertices=%d\n", pNumVertices);
myprintf(gTDS);
#endif
}
int sLight = 0;
switch(pNumVertices){
case 3:
// Our convention is to use a triangle with a texture name like light_99_99_99 to
// represent a light in XGL
if (gShapeHint == XPXGL_SHAPE_LIGHT || gShapeHint == XPXGL_SHAPE_LIGHT_BLINK) {
fprintf(gObjOutputFile, "light\n");
sLight = 1;
debugln("LIGHT");
} else {
if (xgl_gCurrentTexture == -1) {
// tri with materials only
fprintf(gObjOutputFile, "tri_mat\n");
} else {
fprintf(gObjOutputFile, "tri\n");
}
debugln("GL_TRIANGLES");
}
break;
case 4:
// Handle the various kinds of quads
if (gShapeHint == XPXGL_SHAPE_HARD){
fprintf(gObjOutputFile, "quad_hard\n");
} else if (gShapeHint == XPXGL_SHAPE_SMOKE1){
fprintf(gObjOutputFile, "quad_smoke1\n");
} else if (gShapeHint == XPXGL_SHAPE_SMOKE2){
fprintf(gObjOutputFile, "quad_smoke2\n");
} else {
if (xgl_gCurrentTexture == -1) {
// quad with materials only
fprintf(gObjOutputFile, "quad_mat\n");
} else {
fprintf(gObjOutputFile, "quad\n");
}
}
debugln("GL_QUADS");
break;
default:
if (xgl_gCurrentTexture == -1) {
// poly with materials only
fprintf(gObjOutputFile, "polygon_mat %d\n", pNumVertices);
} else {
fprintf(gObjOutputFile, "polygon %d\n", pNumVertices);
}
debugln("GL_POLYGON");
break;
}
int sDidLight = 0;
for(i = pStartIndex; i< pStartIndex + pNumVertices ; i++) {
int j = pPointIndexes[i];
j = j * 3; // 3 floats per index
float sX = pPoints[j];
float sY = pPoints[j+1];
float sZ = pPoints[j+2];
float sS = 0, sT = 0;
if (xgl_gCurrentTexture != -1) {
int sSTIndex = xgl_gShapeVertexIndex * 2;
sS = xgl_gTextureFloats[sSTIndex];
sT = xgl_gTextureFloats[sSTIndex+1];
}
if (sLight && !sDidLight) {
// For a light, we output the xyz and rgb values
// We should calculate center of triangle, are just using first vertext for now
fprintf(gObjOutputFile, "%f %f %f %d %d %d\n", sX, sY, sZ, gLightRed, gLightGreen, gLightBlue);
sDidLight = 1;
}
if (!sLight) {
if (xgl_gCurrentTexture != -1) {
// output xyz st
fprintf(gObjOutputFile, "%f %f %f %f %f\n", sX, sY, sZ, sS, sT);
} else {
// Poly with no textures, just output vertices
fprintf(gObjOutputFile, "%f %f %f\n", sX, sY, sZ);
}
}
xgl_gShapeVertexIndex++;
}
fprintf(gObjOutputFile, "\n");
}
void drawOneShape(float pPoints[], int pPointIndexes[], int pNumIndexes){
/*
Like VRML, we get an array of floats (3 per vertex), and an array of ints
The ints are of the form:
0,1,2,3,-1,2,3,4,-1,8,9,10,11,12,-1
This would be:
0,1,2,3,-1 ==> quad
2,3,4,-1 ==> tri
8,9,10,11,12,-1 ==> poly
*/
xgl_gShapeObjectCount = 0;
xgl_gShapeVertexIndex = 0;
int i;
int sNumVertices = 0;
int sObjectStart = 0;
for( i =0; i < pNumIndexes; i++) {
if (gDebug) {
#if _PRINTF_DEBUG_
sprintf(gTDS, "drawshape %d\n", i);
myprintf(gTDS);
#endif
}
int sIndex = pPointIndexes[i];
if (sIndex == -1) {
xgl_gShapeObjectCount++;
drawNextObject(pPoints, pPointIndexes, sObjectStart, sNumVertices);
sObjectStart =i+1;
sNumVertices = 0;
continue;
} else {
sNumVertices++;
}
}
if (gDebug) {
#if _PRINTF_DEBUG_
sprintf(gTDS, "\nxgl_gShapeObjectCount=%d\n", xgl_gShapeObjectCount);
myprintf(gTDS);
#endif
}
}
void XGLDrawShape(float pFloats[], int pIndices[], int pNumIndices){
/*
Simple yet powerful mechanism to draw complex shapes
This is totally based on the VRML "shape" and IndexedFaceSet model
*/
drawOneShape(pFloats, pIndices, pNumIndices);
gShapeHint = 0;
}
Processing the ShapeHint Token
By using special texture names, we have added the ability to support special xplane objects such as hard, smoke, and light... Below is the HandleHint routine (called from the parser) from xglutil:
void HandleHint(int pHint, int pHintData){
printf("HH hint = %d, data = %d\n", pHint, pHintData);
gShapeHint = pHint;
switch(pHint) {
case XPXGL_SHAPE_LIGHT:
gLightRed = (pHintData >> 24) & 0xff;
gLightGreen = (pHintData >> 16) & 0xff;
gLightBlue = (pHintData >> 8) & 0xff;
printf("r=%d,g=%d,b=%d\n", gLightRed, gLightGreen, gLightBlue);
break;
case XPXGL_SHAPE_LIGHT_BLINK:
gLightRed = (pHintData >> 24) & 0xff;
gLightGreen = (pHintData >> 16) & 0xff;
gLightBlue = (pHintData >> 8) & 0xff;
gLightRed = -gLightRed;
gLightGreen = -gLightGreen;
gLightBlue = -gLightBlue;
printf("r=%d,g=%d,b=%d\n", gLightRed, gLightGreen, gLightBlue);
break;
default:
break;
}
}
toc
#ifndef _I_XGL_H_ #define _I_XGL_H_ /** * IXGL - interface defining the [X]Plane/e[X]tensible [G]raphics [L]anguage * * This is a "work in progress" and will be growing as we add support for * additional primitivies, tokens, etc., etc. * * Unless othewise specified, each of the IDs/tokens/commands begining with XGL_ * are followed by data as document with the token. * * VERY IMPORTANT NOTE: * ==================== * Beginning with XGLv5, we have implemented a new strategy for XGL that will * make it much, much easier for parsers, and for us to add new tokens * without changing the XGL version again (hopefully!) * * ALL TOKENS are immediately followed by an INTEGER bytecount containing * the number of bytes encapsulated by that token (0 if there is no data associated * with the token). * * This ALSO applies to ALL tokens that are "inside" other tokens, such as XGL_SHAPE, * MATERIAL, and most others that contain tokens to represent their data (XGL_FLOAT_ARRAY, * XGL_INT_ARRAY, XGL_CHARS_ARRAY). * * SUMMARY: When you read an integer token, ALWAYS read an integer bytecount after * the token. If you do not care about or handle that token, simply SKIP the * number of bytes. * * @author dspotts */ /////////////////////////////////////////////////////////////////////////// /* * Current XGL Version - NOT a token! * * @since v2 */ const int XGL_CURRENT_VERSION_VALUE = 5; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Format token * * ALWAYS the FIRST token in an XGL stream so that * applications can easily tell if the stream is XGL. * * No data follows * * @since v2 */ const int XGL_FORMAT_TOKEN = 0x5858474C; // 'XXGL' /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Version token * * Always the SECOND token in an XGL stream/file followed by an integer * defining the version of the data. * * @since v2 */ const int XGL_VERSION_TOKEN = 0xffff; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Float array token * * An array of floats, preceded by an integer count * * @since v1 */ const int XGL_FLOAT_ARRAY = 0x0000; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Integer array token * * An array of ints, preceded by an integer count * * @since v1 */ const int XGL_INT_ARRAY = 0x0001; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * CHARS token * * Followed by an integer indicating the number of characters, and * the characters themselves (individual byte for each char, not unicode). * * @since v4 * */ const int XGL_CHARS_ARRAY = 0x0013; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Reset material command, all shapes should be preceded by this command, which * is used to reset the materials back to default values * * @since v1 */ const int XGL_RESET_MATERIAL = 0x0003; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * OpenGL Material token * * This command is followed by an integer material type ID, such as * GL_DIFUSE, etc., then a 3 element XGL_FLOAT_ARRAY representing the RGB values * for this material. * * Material commands should be issued prior to geometry commands. * * @since v1 */ const int XGL_MATERIAL = 0x0004; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * A token similar to a VRML shape object. * * We currently only support the geometry of a shape in a very compact form, * similar to VRML. * * VRML generally begins with a "global" vertex list (3 floats per vertex), * and we currently represent a shape by including this global point list * within the FIRST shape object within an XGL file. * * So the first shape command is followed by an XGL_FLOAT_ARRAY, then that * shape's indices using an XGL_INT_ARRAY. * * Subsequent shapes avoid duplicating the point array, and are followed * ONLY by a single XGL_INT_ARRAY defining the indices for this shape's * vertices. * * Like VRML, the index list is a list of integers that index into the float * array (3*index = [x][y][z]) to define a vertex. * * Like VRML, this is one large list of indexes, with "-1" indicating the end * of a polygon and separating each polygon. * * Examples: * ========= * * 0, 1, 2, -1 ==> a triangle with vertices 0, 1, 2 * * 0, 1, 2, -1, 0, 1, 2, 3, -1 ==> triangle and a quad * * @since v1 */ const int XGL_SHAPE = 0x0005; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Bounding box of the XGL object * * The bounding box defines the outside dimensions of the object contained * within an XGL file. This is especially handy for viewers/renderers, and * may have additional benefits. * * These dimensions only define the SIZE of the object: width, height, depth * (zero-based, always positive). * * Followed by an XGL_FLOAT_ARRAY of 3 floats (x, y, z) */ const int XGL_BOUNDING_BOX = 0x0006; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Texture File token * * Defines all texture files used within an XGL object. A single * XGL_TEXTURE_FILE_TOKEN will be at the start of the file for easy/fast * finding and loading, texture prioritization, etc. * * This token is followed by an integer count of the number of unique * texture files. * * Following this are multiple XGL_CHAR_ARRAY objects, one for each texture * name. * * The files are placed in XGL in the order that is consistent with the * XGL_TEXTURE_INDEX token. * */ const int XGL_TEXTURE_FILE_TOKEN = 0x0007; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Texture to bind to * * This is be a zero-based index from the textures associated with this * XGL file. It will be up to the application to convert this to a "real" * OpenGL texture index. * * This token will be followed by an integer, and *always* preceed any shape * that uses textures. * * @since v3 * */ const int XGL_TEXTURE_INDEX = 0x0008; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Texture floats (S and T) parameters. * * For any shape that has a texture associated with it, that shape will be * preceded by XGL_TEXTURE_FLOATS. * * The number of floats will be 2* the number of vertices in the upcoming * shape, and be represented by an XGL_FLOAT_ARRAY. * * @since v3 * */ const int XGL_TEXTURE_FLOATS = 0x0009; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * End of stream token * * This token signifies the end of an XGL stream. * * @since v4 * */ const int XGL_END_OF_STREAM = 0x0010; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * OPTIONAL shape HINT token * * This token, which, if present, precedes an XGL_SHAPE, is followed by * an integer that can be used to signify any "special" information regarding * the upcoming shape object. * * Please see http://www.dspotts.com/xgl.html for details on this token as * well as the modeler's guidelines for texture naming so that these * tokens can be added to the XGL file(s). * * @since v4 * */ const int XGL_SHAPE_HINT_TOKEN = 0x0011; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * OPTIONAL shape hint DATA token * * If a particular shape hint requires more data than a single integer, * it can be followed by this token. * * @since v4 * */ const int XGL_SHAPE_HINT_DATA_TOKEN = 0x0012; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /* * Number of bytes of various data types used in XGL */ const int SIZEOF_INT = 4; const int SIZEOF_FLOAT = 4; const int SIZEOF_TOKEN = 4; const int SIZEOF_BYTE = 1; /////////////////////////////////////////////////////////////////////////// /* * OpenGL constants for material specifications */ #ifndef GL_AMBIENT const int GL_AMBIENT = 0x1200; const int GL_DIFFUSE = 0x1201; const int GL_SHININESS = 0x1601; const int GL_EMISSION = 0x1600; const int GL_SPECULAR = 0x1202; #endif #endif
The following constants define the various XPXGL shape hint data values (an integer) - note from the above handle hint code that for light(s), the rgb values are stored in the upper 3 bytes of the data (NN, NN, NN) and must be masked off for these 2 tokens.
/////////////////////////////////////////////////////////////////////////// /* * Current XGL_SHAPE_HINT_TOKEN values */ const int XPXGL_SHAPE_HARD = 0x0001; const int XPXGL_SHAPE_LIGHT = 0x0002; const int XPXGL_SHAPE_LIGHT_BLINK = 0x0003; const int XPXGL_SHAPE_SMOKE1 = 0x0004; const int XPXGL_SHAPE_SMOKE2 = 0x0005; ///////////////////////////////////////////////////////////////////////////