ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/lib/mg/rib/mgribtoken.c

This is mgribtoken.c in view mode; [Download] [Up]

/*
 * NOTES:
 * 1. mrti() assumes unsigned short is 2 bytes, MSB first
 *    this may have to change for other architecture
 * 2. will it be possible to increase the encoded float array length
 *    by "adding l" to create 256 aggregates of 3 or 4 floats each, as
 *    opposed to 256 straight floats? (see appendix C, pg 163 of the
 *    'big' renderman manual)
 * 3. the name mrti should be changed to mgri (it sounds better)
 */

#include "mgribtoken.h"
#include <stdio.h>

#include "mg.h"
#include "mgribP.h"
#include "mgrib.h"

#ifdef test
#include <stdio.h>
#endif

#define BUFFERSIZE 1024*128    /* 128k buffer */
#define TMPSIZE 8192
#define SECTIONWIDTH 70        /* width of a section header */

#define STRINGDEF	0315
#define STRINGREF	0317
#define LNGSTRINGENCODE	0241   /* length follows, is unsigned short */
#define STRINGENCODE	0220
#define RIREQDEF	0314
#define RIREQREF	0246
#define FLOATARRAYDEF	0310
#define INTEGER		0201   /* unsigned short */
#define FLOAT		0244

void binary_token(int a1, va_list *alist);
void ascii_token(int a1, va_list *alist);

unsigned char *tokenbuffer=NULL;
unsigned char *limit;
unsigned char *ptr;

/* following is the table: see mgribtoken.h (struct) for desc of fields */
static struct _table table[] = {
    {"", 0, 0, 0},		/* mr_NULL */

    /* Ri Requests */
    {"AttributeBegin",		14,  0, 0},
    {"AttributeEnd",		12,  1, 0},
    {"TransformBegin",		14,  2, 0},
    {"TransformEnd",		12,  3, 0},
    {"Identity",		 8,  4, 0},
    {"ConcatTransform",		15,  5, 0},
    {"Surface",			 7,  6, 0},
    {"ShadingInterpolation",	20,  7, 0},
    {"Color",		 	 5,  8, 0},
    {"Opacity",			 7,  9, 0},
    {"Polygon",			 7, 10, 0},
    {"PatchMesh",		 9, 11, 0},
    {"Format",			 6, 12, 0},
    {"Projection",		10, 13, 0},
    {"Clipping",		 8, 14, 0},
    {"WorldBegin",		10, 15, 0},
    {"WorldEnd",		 8, 16, 0},
    {"Display",			 7, 17, 0},
    {"ScreenWindow",		12, 19, 0},
    {"LightSource",		11, 20, 0},
    {"Sphere",			 6, 21, 0},
    {"Translate",		 9, 22, 0},
    {"Rotate",			 6, 23, 0},
    {"Cylinder",		 8, 24, 0},
    {"NuPatch",			 7, 25, 0},
    {"ShadingRate",		11, 26, 0},
    {"Option",			 6, 27, 0},
    {"Illuminate",		10, 28, 0},
    {"FrameBegin",		10, 29, 0},
    {"FrameEnd",		 8, 30, 0},

    /* following are reserved - do not add */
    /* or remove fields, just change them! */
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},
    {"", 0, 255, 0},

    /* Strings - we start these out at position 50 */
    {"P",			 1,  0, 0},
    {"N",			 1,  1, 0},
    {"Cs",            	 	 2,  2, 0},
    {"Pw",			 2,  3, 0},
    {"Os",			 2,  4, 0},
    {"st",			 2,  5, 0},
    {"plastic",			 7,  6, 0},
    {"hplastic",		 8,  7, 0},
    {"eplastic",		 8,  8, 0},
    {"heplastic",		 9,  9, 0},
    {"constant",		 8,  10, 0},
    {"ambientlight",		12, 11, 0},
    {"lightcolor",		10, 12, 0},
    {"distantlight",		12, 13, 0},
    {"intensity",		 9, 14, 0},
    {"file",			 4, 15, 0},
    {"rgb",			 3, 16, 0},
    {"rgba",			 4, 17, 0},
    {"Ka",			 2, 18, 0},
    {"Kd",			 2, 19, 0},
    {"Ks",			 2, 20, 0},
    {"specularcolor",		13, 21, 0}, 
    {"roughness",		 9, 22, 0},
    {"fov",			 3, 23, 0},
    {"perspective",		11, 24, 0},
    {"to",			 2, 25, 0},
    {"framebuffer",		 11, 26, 0}
};

/* initialize tokenbuffer */
void mrti_init()
{
    if(tokenbuffer) free(tokenbuffer);
    tokenbuffer = (unsigned char *)malloc(BUFFERSIZE);
    tokenbuffer[0] = (char)0;
    limit = (unsigned char *)(tokenbuffer + BUFFERSIZE);
    ptr = tokenbuffer;
}

/* reset the ptr & tokenbuffer */
void mrti_reset()
{
	ptr = tokenbuffer;
	tokenbuffer[0] = (char)0;
}

/* quick copy routine w/ ptr update */
void cat(unsigned char *s, char *a)
{
    while(*(s++)=(*(a++))) ptr++;
}


/* routine will check buffer for possible overun, will realloc if needed */
/* generally, "worst case" values should be passed to check_buffer       */
void check_buffer(int length)
{
    if((unsigned char *)(ptr+length)>(unsigned char *)limit) {
        /* optinally check for maximum buffer allocation here */
	long used = ptr - tokenbuffer;
	long avail = limit - tokenbuffer;
	    /* Buffer grows exponentially, by factor of 1.5 each time */
	do { avail += avail>>1; } while(used+length >= avail);
	tokenbuffer = (unsigned char *)realloc(tokenbuffer, avail);
	ptr = tokenbuffer + used;
	limit = tokenbuffer + avail;
    }
}

/* process variable size token list */
void mrti(int a1, ... )
{
    va_list alist;

    va_start(alist, a1);
 
    switch((int)(_mgribc->render_device & (RMD_BINARY|RMD_ASCII)))
    {
	case (int)RMD_BINARY: binary_token(a1, &alist); break;
	case (int)RMD_ASCII:  ascii_token(a1, &alist); break;
    }
    va_end(alist);
}

/* return 1 when supplied token requires its own (ascii) line, 0 otherwise */
int line_initializer(int token)
{
    /* THIS IS HACKISH - IT WILL CREATE A LINE FEED BEFORE */
    /* IT CREATES THE NEW LINE, WHICH ISN'T ALWAYS GOOD!!  */
    if(token<STRINGBASE||token==mr_comment||token==mr_section||
       (token>=mr_P && token<=mr_Os)) return 1;
    else return 0;
}

/* ASCII SUBPROCESSING */
void ascii_token(int token, va_list *alist)
{
int i;
int count, number;
int subsize;
static int arraysize;
static int expectSubArray=0;
static char astring[128];
double nextfloat; /* va_arg converts floats to doubles */
float *floatptr;
char *s;
int len, add;

    do {
    
    if(expectSubArray && (token!=mr_subarray3)) {
    	/* ERROR */
    }
    
    /* check to see if we need to start a new line */
    if(line_initializer(token) && *(ptr-1)!='\n') *(ptr++)='\n';
    
    switch(token) {
	
    case mr_section:
	check_buffer(SECTIONWIDTH); /* should not exceed this */
        s = va_arg(*alist, char*);
        len = strlen(s);
	if(len+3>SECTIONWIDTH) len = SECTIONWIDTH-3; /* 3 added characters */
	*(ptr++)='\n';
	cat(ptr,"# ");
        cat(ptr,s);
	cat(ptr," ");
	
	len = SECTIONWIDTH - 3 - len;
        while((len--)>0) *(ptr++)='*';
	break;

    case mr_comment:
	s = va_arg(*alist, char*);
	len = strlen(s);
	check_buffer(len+2);
	cat(ptr,"# ");
	cat(ptr,s);
	break;

    case mr_header:
    	s = va_arg(*alist, char*);
	len = strlen(s);
	check_buffer(len+2);
	cat(ptr,"##");
	cat(ptr,s);
	break;
	
    case mr_nl:
    	/* check for space */
	check_buffer(2);
	if(*(ptr-1)==' ') ptr--;
    	*(ptr++)='\n';
	break;
	
    case mr_array:
    	arraysize = va_arg(*alist, int);
	check_buffer(arraysize*16+4); /* how else can we do this? */
	*(ptr++)='[';
	for(i=0;i<arraysize;i++) {
	    nextfloat = va_arg(*alist, double);
	    sprintf(astring,"%g ",nextfloat);
	    cat(ptr, astring);
	}
	*(--ptr)=0; /* get rid of space */
	cat(ptr,"] ");
	break;
	
    case mr_buildarray:
    	arraysize = va_arg(*alist, int);
	check_buffer(1);
	expectSubArray = 1;
	*(ptr++)='[';
	break;

    case mr_parray:
    {
    	int size;
    	size = va_arg(*alist, int);
	check_buffer(2+16*size);
	*(ptr++)='[';
	/* if arraysize<0 then ERROR */
	floatptr = va_arg(*alist, float*);
	for(i=0;i<size;i++) {
	    sprintf(astring,"%g ",*(floatptr++));
	    cat(ptr,astring);
	}
	*(--ptr)=0; /* get rid of unwanted space */
	cat(ptr,"] ");
	break;
    }
    
    case mr_subarray3:
	check_buffer(16*3+7);
	arraysize-=3;
	/* if arraysize<0 then ERROR */
    	floatptr = va_arg(*alist, float*);
    	sprintf(astring,"%g %g %g   ",
	    *(floatptr),*(floatptr+1),*(floatptr+2));
	cat(ptr,astring);
	if(arraysize<=0) {
	    expectSubArray = 0;
	    *(ptr-=3)=0; /* get rid of unwanted spaces */
	    cat(ptr,"] ");
	}
	break;

    case mr_int:
        number = va_arg(*alist, int);
	check_buffer(16);
	sprintf(astring,"%d ",number);
	cat(ptr,astring);
	break;

    case mr_float:
        nextfloat = va_arg(*alist, double);
	check_buffer(16);
	sprintf(astring,"%g ",nextfloat);
	cat(ptr,astring);
	break;
	
    case mr_intseq:
    	/* OBSOLETE */
    	count = va_arg(*alist, int);
	check_buffer(count*16);
	for(i=0;i<count;i++) {
	    number = va_arg(*alist, int);
	    sprintf(astring,"%d ",number);
	    cat(ptr,astring);
	}
	*(--ptr)=0;
	break;

    case mr_string:
    {
    	char *string;
	string = va_arg(*alist, char *);
	len = strlen(string);
	check_buffer(len+3);
	*(ptr++)='"';
	cat(ptr,string);
	*(ptr++)='"';
	*(ptr++)=' ';
	break;
    }

    case mr_embed:
    {
    	/* directly embed a string */
        char *string;
	string = va_arg(*alist, char *);
	len = strlen(string);
	check_buffer(len);
	cat(ptr,string);
	break;
    }
    /* these requests require a trailing line feed */
    case mr_attributebegin:
    case mr_attributeend:
    case mr_transformbegin:
    case mr_transformend:
    case mr_identity:
    case mr_polygon:
    case mr_worldbegin:
    case mr_worldend:
    case mr_frameend:
	check_buffer(table[token].len);
	cat(ptr,table[token].name);
	/*
	*(ptr++) = '\n';
	*/
	break;

    /* these requests require a trailing space */
    case mr_color:
    case mr_opacity:
    case mr_format:
    case mr_display:
    case mr_screenwindow:
    case mr_clipping:
    case mr_concattransform:
    case mr_projection:
    case mr_lightsource:
    case mr_illuminate:
    case mr_surface:
    case mr_sphere:
    case mr_patchmesh:
    case mr_rotate:
    case mr_translate:
    case mr_cylinder:
    case mr_nupatch:
    case mr_option:
    case mr_shadinginterpolation:
    case mr_shadingrate:
    case mr_framebegin:
	check_buffer(table[token].len+1);
    	cat(ptr,table[token].name);
	*(ptr++)=' ';
	break;
	
    /* anything left over should be a string  */
    /* which requires quotes & trailing space */
    /* (THIS SHOULD BE MOVED OUT OF SWITCH)  */
    default:
	check_buffer(table[token].len+3);
        *(ptr++)='"';
    	cat(ptr,table[token].name);
	*(ptr++)='"';
	*(ptr++)=' ';
	break;

    }
    		
    } while ((token=va_arg(*alist, int))!=mr_NULL);
}


/* BINARY SUBPROCESSING */
/* NOTE: some hardware will not support copying data types > 1 byte into an
 * arbitrary (unaligned) location. e.g.
 *    *(unsigned short *)ptr = anUnsignedVariable
 * may be an illegal instruction. Therefore, macros which will copy these
 * values one byte at a time follow here and are used where needed. These
 * macros will work only with float sizes of 4 bytes (IEEE) & unsigned short
 * int sizes of 2 bytes
 */

#define COPYUSHORT( value )	*ptr++ = ((char *)&value)[0];\
				*ptr++ = ((char *)&value)[1]
#define COPYFLOAT( value )	*ptr++ = ((char *)&value)[0];\
				*ptr++ = ((char *)&value)[1];\
				*ptr++ = ((char *)&value)[2];\
				*ptr++ = ((char *)&value)[3]

void binary_token(int token, va_list *alist)
{
int i;
static int expectSubArray=0;
static int arraysize;
float *floatptr;

    if(expectSubArray && (token!=mr_subarray3)) {
    	/* ERROR */
    }

    do {
    
    if(token>=STRINGBASE & token<mr_array) {
    	/* The token is a string defintion/request */
	if(!table[token].defined) {
	    check_buffer(7 + table[token].len);
	    *(ptr++)=STRINGDEF;
	    *(ptr++)=table[token].reqn;
	    if(table[token].len<16) {
	    	*(ptr++)=STRINGENCODE+table[token].len;
	    } else {
	    	unsigned short length;
		length = (unsigned short) table[token].len;
	    	*(ptr++)=LNGSTRINGENCODE;
		COPYUSHORT(length);
	    }
	    cat(ptr,table[token].name);
	    table[token].defined = 1;
	}
	*(ptr++)=STRINGREF;
	*(ptr++)=table[token].reqn;
    }
    
    else switch(token) {
    
    /* THESE SHOULD BE MOVE BEFORE SWITCH */
    /* AND TURNED INTO A SPECIAL CASE    */
    case mr_attributebegin:
    case mr_attributeend:
    case mr_transformbegin:
    case mr_transformend:
    case mr_identity:
    case mr_polygon:
    case mr_worldbegin:
    case mr_worldend:
    case mr_color:
    case mr_format:
    case mr_display:
    case mr_screenwindow:
    case mr_clipping:
    case mr_concattransform:
    case mr_projection:
    case mr_lightsource:
    case mr_illuminate:
    case mr_surface:
    case mr_sphere:
    case mr_patchmesh:
    case mr_translate:
    case mr_rotate:
    case mr_cylinder:
    case mr_nupatch:
    case mr_option:
    case mr_shadinginterpolation:
    case mr_shadingrate:
    case mr_framebegin:
    case mr_frameend:
    	check_buffer(7+table[token].len);
	if(!table[token].defined) {
	    /* we must define it */
	    *(ptr++)=RIREQDEF;
	    *(ptr++)=table[token].reqn;
	    if(table[token].len<16) {
	    	*(ptr++)=STRINGENCODE+table[token].len;
	    } else {
	    	unsigned short length;
		length = (unsigned short) table[token].len;
		*(ptr++)=LNGSTRINGENCODE;
		COPYUSHORT(length);
	    }
	    cat(ptr,table[token].name);
	    table[token].defined = 1;
	}
	*(ptr++)=RIREQREF;
	*(ptr++)=table[token].reqn;
    	break;
    
    case mr_array:
    {
        unsigned char arraycount;
	unsigned char *p;
	float f;
    	arraycount = (unsigned char)va_arg(*alist, int);
	check_buffer(2+4*arraycount);
	*(ptr++)=FLOATARRAYDEF;
	*(ptr++)=arraycount;
	for(i=0;i<arraycount;i++) {
	    /* will float be the same on each platform? (ieee?)*/
	    /* IS THIS NEXT STEP LEGAL?!? */
	    f = (float) va_arg(*alist, double);
	    COPYFLOAT(f);
	}
	break;
    }
    
    case mr_buildarray:
    {
    	unsigned char arraycount;
	arraysize = va_arg(*alist, int);
	arraycount = (unsigned char)arraysize;
	check_buffer(2);
	*(ptr++)=FLOATARRAYDEF;
	*(ptr++)=arraycount;
	expectSubArray = 1;
	break;
    }
    
    case mr_subarray3:
    {
    	arraysize-=3;
	if(arraysize<0) /* ERROR */;
	check_buffer(12); /* 3*sizeof(float) */
    	floatptr = va_arg(*alist, float*);
	bcopy((char *)floatptr, (char *)ptr, 3*sizeof(float));
	ptr+=3*sizeof(float);
	if(arraysize<=0) {
	    expectSubArray = 0;
	}
	break;
    }
  
    case mr_parray:
    {
    	unsigned char arraycount;
	arraycount = (unsigned char)va_arg(*alist, int);
	check_buffer(2+arraycount*4);
	*(ptr++)=FLOATARRAYDEF;
	*(ptr++)=arraycount;
	floatptr = va_arg(*alist, float*);
	bcopy((char *)floatptr, (char *)ptr, arraycount*sizeof(float));
	ptr+=arraycount*sizeof(float);
	if(arraysize<=0) {
	    expectSubArray = 0;
	}
	break;
    }

    case mr_int:
    {
    	unsigned short number;
	check_buffer(3);
        number = (unsigned short)va_arg(*alist, int);
	*(ptr++) = INTEGER;
	COPYUSHORT(number);
	break;
    }

    case mr_float:
    {
    	float afloat;
	check_buffer(5);
        afloat = (float)va_arg(*alist, double);
	*(ptr++) = FLOAT;
	COPYFLOAT(afloat);
	break;
    }
	
    case mr_intseq:
    {
    	/* OBSOLETE */
    	unsigned short number;
	int  count;
	count = va_arg(*alist, int);
	check_buffer(number*2);
	for(i=0;i<count;i++) {
	    number = (unsigned short)va_arg(*alist, int);
	    *(ptr++) = INTEGER;
	    COPYUSHORT(number);
	}
	break;
    }

    case mr_string:
    {
        unsigned short length;
	char *string;
	string = va_arg(*alist, char *);
	length = (unsigned short) strlen(string);
	check_buffer(3+length);
	if(length<16) {
	    *(ptr++)=STRINGENCODE+(char)length;
	} else {
	    *(ptr++)=LNGSTRINGENCODE;
	    COPYUSHORT(length);
	}
	cat(ptr,string);
	break;
    }
    
    case mr_embed:
    {
        /* no attempt is made to encode this becuase it's so general */
	char *string;
	int length;
	string = va_arg(*alist, char *);
	length = strlen(string);
	check_buffer(length);
        cat(ptr,string);
	break;
    }
    
    case mr_nl:
    	/* temporary for debugging (puts tokens on spereate lines) */
        /* printf("\n"); */
	break;
    
    } /* switch */    
    } while ((token=va_arg(*alist, int))!=mr_NULL);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.