CCL Home Page
sColor X%type sVector X%type sInt X%type sString X%token tADAPTIVE tAPERTURE X%token tBACKGROUND tBLOTCH tBOX tBUMP tCONE tCYL tDIRECTIONAL X%token tENDDEF tEXTENDED tEYEP tFBM tFBMBUMP tFOCALDIST tFOG tFOV tGLOSS tGRID X%token tHEIGHTFIELD tJITTERED tLIGHT tLIST tLOOKP tMARBLE tMAXDEPTH tMIST X%token tOBJECT tOUTFILE X%token tPLANE tPOINT tPOLY tROTATE tSAMPLES X%token tSCALE tSCREEN tSPHERE tSTARTDEF tSUPERQ tSURFACE tRESOLUTION X%token tTHRESH tTRANSLATE tTRANSFORM tTRIANGLE tUP tENDFILE X%token tTEXTURE tCHECKER tWOOD tCONTRAST tCUTOFF X%% XItems : /* empty */ X | Items Item X ; XItem : Eyep X | Lookp X | Up X | Fov X | Screen X | Aperture X | Focaldist X | Maxdepth X | Samples X | Jittered X | Adaptive X | Contrast X | Cutoff X | Background X | Light X | Primitive X | Child X | Surface X | Outfile X | List X | Grid X | Object X | Fog X | Mist X | Hashthing X | ENDFILE /* For backward compatibility */ X ; XHashthing : tHASHTHING X { X WriteVerbatim("\n#"); X WriteVerbatim($1); X WriteNewline(); X }; XList : LIST X { X NEWLINE(); X } X ; XGrid : GRID X { X NEWLINE(); X } X ; XPrimitive : Prim Textures X ; XPrim : Primtype Transforms X ; XPrimtype : Plane X | Sphere X | Box X | Triangle X | Cylinder X | Cone X | Superq X | Poly X | HeightField X ; XObject : Objectdef Textures X { X NEWLINE(); X } X ; XObjectdef : Startdef Objdefs ENDDEF X ; XStartdef : STARTDEF X /* X * define X */ X { X NEWLINE(); X } X ; XObjdefs : Objdefs Objdef X | X ; XObjdef : Primitive X | Surface X | Child X | List X | Grid X | Object X ; XTextures : Textures Texture X | X ; XTexture : TEXTURE Texturetype Transforms X { X NEWLINE(); X } X ; XTexturetype : CHECKER String X { X NEWLINE(); X } X | BLOTCH Fnumber String X { X NEWLINE(); X } X | BUMP Fnumber X { X NEWLINE(); X } X | MARBLE X { X NEWLINE(); X } X | MARBLE String X { X NEWLINE(); X } X | FBM Fnumber Fnumber Fnumber Fnumber Int Fnumber X { X NEWLINE(); X } X | FBM Fnumber Fnumber Fnumber Fnumber Int Fnumber String X { X NEWLINE(); X } X | FBMBUMP Fnumber Fnumber Fnumber Fnumber Int X { X NEWLINE(); X } X | WOOD X { X NEWLINE(); X } X | GLOSS Fnumber X { X NEWLINE(); X } X ; XChild : Childdef Textures X { X NEWLINE(); X } X ; XChilddef : OBJECT String Transforms X { X NEWLINE(); X } X ; XTransforms : Transforms Transform X | /* empty */ X ; XTransform : TRANSLATE Vector X { X NEWLINE(); X } X | ROTATE Vector sFnumber X { X WriteFloat(-$3); X NEWLINE(); X } X | SCALE Fnumber Fnumber Fnumber X { X NEWLINE(); X } X | TRANSFORM sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X { X /* have to transpose... */ X WriteFloat($2); WriteFloat($5); WriteFloat($8); X WriteFloat($3); WriteFloat($6); WriteFloat($9); X WriteFloat($4); WriteFloat($7); WriteFloat($10); X NEWLINE(); X } X | TRANSFORM sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X { X /* transpose it */ X WriteFloat($2); WriteFloat($5); WriteFloat($8); X WriteFloat($3); WriteFloat($6); WriteFloat($9); X WriteFloat($4); WriteFloat($7); WriteFloat($10); X WriteFloat($11); WriteFloat($12); WriteFloat($13); X NEWLINE(); X } X ; XEyep : EYEP Vector Transforms X { X NEWLINE(); X } X ; XLookp : LOOKP Vector X { X NEWLINE(); X } X ; XUp : UP Vector X { X NEWLINE(); X } X ; XFov : FOV Fnumber Fnumber X { X NEWLINE(); X } X | FOV Fnumber X { X NEWLINE(); X } X ; XSamples : SAMPLES Int X { X NEWLINE(); X } X ; XAdaptive : ADAPTIVE sInt X { X WriteFloat((Float)($2+1)); X NEWLINE(); X } X ; XContrast : CONTRAST Fnumber Fnumber Fnumber X { X NEWLINE(); X } X ; XCutoff : CUTOFF Fnumber X { X NEWLINE(); X } X ; XJittered : JITTERED X { X NEWLINE(); X } X ; XScreen : SCREEN Int Int X { X NEWLINE(); X } X | RESOLUTION Int Int X { X NEWLINE(); X } X ; XAperture : APERTURE Fnumber X { X NEWLINE(); X } X ; XFocaldist : FOCALDIST Fnumber X { X NEWLINE(); X } X ; XMaxdepth : MAXDEPTH Int X { X NEWLINE(); X } X ; XBackground : BACKGROUND Color X { X NEWLINE(); X } X ; XLight : Lightdef POINT Vector X { X NEWLINE(); X } X | Lightdef DIRECTIONAL Vector X { X NEWLINE(); X } X | Lightdef EXTENDED sVector sFnumber X { X WriteFloat($4); X WriteVector(&$3); X NEWLINE(); X } X ; XLightdef : LIGHT Fnumber X { X NEWLINE(); X } X | LIGHT Color X { X NEWLINE(); X } X ; XSurface : SURFACE String X sColor sColor sColor X sFnumber sFnumber sFnumber sFnumber X { X if ($3.r || $3.g || $3.b) { X WriteString("\tambient"); X WriteColor(&$3); X WriteNewline(); X } X if ($4.r || $4.g || $4.b) { X WriteString("\tdiffuse"); X WriteColor(&$4); X WriteNewline(); X } X if ($5.r || $5.g || $5.b) { X WriteString("\tspecular"); X WriteColor(&$5); X WriteNewline(); X if ($6) { X WriteString("\tspecpow"); X WriteFloat($6); X WriteNewline(); X } X } X if ($7) { X WriteString("\treflect"); X WriteFloat($7); X WriteNewline(); X } X if ($8) { X WriteString("\ttransp"); X WriteFloat($8); X WriteString("index"); X WriteFloat($9); X WriteNewline(); X } X } X | SURFACE String sColor sColor sColor X sFnumber sFnumber sFnumber sFnumber sFnumber sFnumber X { X if ($3.r || $3.g || $3.b) { X WriteString("\tambient"); X WriteColor(&$3); X WriteNewline(); X } X if ($4.r || $4.g || $4.b) { X WriteString("\tdiffuse"); X WriteColor(&$4); X WriteNewline(); X } X if ($5.r || $5.g || $5.b) { X WriteString("\tspecular"); X WriteColor(&$5); X WriteNewline(); X if ($6) { X WriteString("\tspecpow"); X WriteFloat($6); X WriteNewline(); X } X } X if ($7) { X WriteString("\treflect"); X WriteFloat($7); X WriteNewline(); X } X if ($8) { X WriteString("\ttransp"); X WriteFloat($8); X WriteString("index"); X WriteFloat($9); X WriteNewline(); X } X if ($10) { X WriteString("\ttranslu"); X WriteFloat($10); X WriteString("1 1 1"); X WriteFloat($11); X WriteNewline(); X } X } X ; XHeightField : HEIGHTFIELD String String X { X NEWLINE(); X } X ; XPoly : POLY String Polypoints X { X NEWLINE(); X } X ; XPolypoints : /* empty */ X | Polypoints Polypoint X ; XPolypoint : Vector X { X NEWLINE(); X } X ; XCone : CONE String sVector sVector sFnumber sFnumber X { X /* Radii now precede points */ X WriteFloat($5); X WriteVector(&$3); X WriteFloat($6); X WriteVector(&$4); X NEWLINE(); X } X ; XCylinder : CYL sString sVector sVector sFnumber X { X Vector tmp; X X WriteString($2); X /* Radius now goes first */ X WriteFloat($5); X WriteVector(&$3); X WriteVector(&$4); X NEWLINE(); X WriteVerbatim("#ifdef ENDCAPS\n"); X VecSub($3, $4, &tmp); X WriteVerbatim("disc "); X WriteString($2); X WriteFloat($5); /* radius */ X WriteVector(&$3); /* pos */ X WriteVector(&tmp); X WriteVerbatim("\ndisc "); X WriteString($2); X VecScale(-1, tmp, &tmp); X WriteFloat($5); /* radius */ X WriteVector(&$4); /* pos */ X WriteVector(&tmp); X WriteVerbatim("\n#endif\n"); X } X ; XSphere : SPHERE String Fnumber Vector X { X NEWLINE(); X } X ; XBox : BOX String X sFnumber sFnumber sFnumber X sFnumber sFnumber sFnumber X { X /* give box corners */ X WriteFloat($3 - $6); X WriteFloat($4 - $7); X WriteFloat($5 - $8); X WriteFloat($3 + $6); X WriteFloat($4 + $7); X WriteFloat($5 + $8); X NEWLINE(); X } X ; XTriangle : TRIANGLE String Vector Vector Vector X { X NEWLINE(); X } X | TRIANGLE String Vector Vector Vector Vector Vector Vector X { X NEWLINE(); X } X ; XSuperq : SUPERQ String X Fnumber Fnumber Fnumber X Fnumber Fnumber Fnumber X Fnumber X { X WriteVerbatim("*/"); X NEWLINE(); X } X ; XPlane : PLANE String sVector sVector X { X /* reverse order of point/normal */ X WriteVector(&$4); X WriteVector(&$3); X NEWLINE(); X } X ; XOutfile : OUTFILE String X { X NEWLINE(); X } X ; XMist : MIST Color Color Fnumber Fnumber X { X NEWLINE(); X } X ; XFog : FOG sFnumber sColor X { X WriteColor(&$3); X WriteFloat($2); WriteFloat($2); WriteFloat($2); X NEWLINE(); X } X ; XColor : Fnumber Fnumber Fnumber X ; XsColor : sFnumber sFnumber sFnumber X { X $$.r = $1; $$.g = $2; $$.b = $3; X } X ; XVector : Fnumber Fnumber Fnumber X ; XsVector : sFnumber sFnumber sFnumber X { X $$.x = $1; $$.y = $2; $$.z = $3; X } X ; XFnumber : tFLOAT X { WriteFloat($1); } X | tINT X { WriteFloat((Float)$1); } X ; XInt : tINT X { WriteFloat((Float)$1); }; XsInt : tINT X { $$ = (int)$1; }; XsFnumber : tFLOAT X | tINT X { $$ = (double)$1; } X ; XString : tSTRING X { WriteString($1); } XsString : tSTRING X { $$ = $1; } XADAPTIVE : tADAPTIVE { WriteString("samples"); } XAPERTURE : tAPERTURE { WriteString("aperture"); } XBACKGROUND : tBACKGROUND { WriteString("background"); } XBLOTCH : tBLOTCH { WriteString("blotch"); } XBOX : tBOX { WriteString("box"); } XBUMP : tBUMP { WriteString("bump"); } XCONE : tCONE { WriteString("cone"); } XCYL : tCYL { WriteString("cylinder"); } XDIRECTIONAL : tDIRECTIONAL { WriteString("directional"); } XENDDEF : tENDDEF { EndDefine(); } XEXTENDED : tEXTENDED { WriteString("extended"); } XEYEP : tEYEP { WriteString("eyep"); } XFBM : tFBM { WriteString("fbm"); } XFBMBUMP : tFBMBUMP { WriteString("fbmbump"); } XFOCALDIST : tFOCALDIST { WriteString("focaldist"); } XFOG : tFOG { WriteString("atmosphere fog"); } XFOV : tFOV { WriteString("fov"); } XGLOSS : tGLOSS { WriteString("gloss"); } XGRID : tGRID tINT tINT tINT { SetTypeGrid($2,$3,$4); } XHEIGHTFIELD : tHEIGHTFIELD { WriteString("heightfield"); } XJITTERED : tJITTERED { WriteString("jittered"); } XLIGHT : tLIGHT { WriteString("light"); } XLIST : tLIST { SetTypeList(); } XLOOKP : tLOOKP { WriteString("lookp"); } XMARBLE : tMARBLE { WriteString("marble"); } XMAXDEPTH : tMAXDEPTH { WriteString("maxdepth"); } XMIST : tMIST { WriteString("atmosphere mist"); } XOBJECT : tOBJECT { WriteString("object"); } XOUTFILE : tOUTFILE { WriteString("outfile"); } XPLANE : tPLANE { WriteString("plane"); } XPOINT : tPOINT { WriteString("point"); } XPOLY : tPOLY { WriteString("poly"); } XROTATE : tROTATE { WriteString("rotate"); } XSAMPLES : tSAMPLES { WriteString("samples"); } XSCALE : tSCALE { WriteString("scale"); } XSCREEN : tSCREEN { WriteString("screen"); } XSPHERE : tSPHERE { WriteString("sphere"); } XSTARTDEF : tSTARTDEF tSTRING { StartDefine($2); } XSUPERQ : tSUPERQ { WriteString("/* superq"); } XSURFACE : tSURFACE { WriteString("surface"); } XRESOLUTION : tRESOLUTION { WriteString("resolution"); } XTRANSLATE : tTRANSLATE { WriteString("translate"); } XTRANSFORM : tTRANSFORM { WriteString("transform"); } XTRIANGLE : tTRIANGLE { WriteString("triangle"); } XUP : tUP { WriteString("up"); } XENDFILE : tENDFILE { /* Don't do a thing. */ } XTEXTURE : tTEXTURE { WriteString("texture"); } XCHECKER : tCHECKER { WriteString("checker"); } XWOOD : tWOOD { WriteString("wood"); } XCONTRAST : tCONTRAST { WriteString("contrast"); } XCUTOFF : tCUTOFF { WriteString("cutoff"); } X%% X X#define STARTBUFSIZ (1 << 18) X Xtypedef struct db { X int bufsiz, curpos; X int type, x, y, z; X char *name; X struct db *next; X char *memory; X} DefBuf; X XDefBuf *defbuf = NULL; X Xyyerror(s) X{ X fprintf(stderr,"rsconvert: %s, line %d: %s \n", X yyfilename[0] ? yyfilename : "stdin", X yylineno, s); X} X XStartDefine(name) Xchar *name; X{ X DefBuf *new; X /* X * Push new buffer onto define stack. X */ X new = (DefBuf *)Malloc(sizeof(DefBuf)); X new->bufsiz = STARTBUFSIZ; X new->type = LIST; X new->curpos = 0; X new->name = name; X new->memory = (char *)Calloc(new->bufsiz, sizeof(char)); X new->next = defbuf; X defbuf = new; X} X XEndDefine() X{ X char buf[BUFSIZ]; X DefBuf *old; X X old = defbuf; X defbuf = defbuf->next; X if (old->type == LIST) { X sprintf(buf, "name %s list", old->name); X } else { X sprintf(buf, "name %s grid %d %d %d", old->name, X old->x, old->y, old->z); X } X /* X * dump goodies X */ X WriteVerbatim(buf); X WriteVerbatim(old->memory); X WriteVerbatim("end"); X free((voidstar)old->memory); X free((voidstar)old); X X} X XWriteString(str) Xchar *str; X{ X WriteVerbatim(str); X WriteChar(' '); X} X XWriteVerbatim(str) Xchar *str; X{ X int n; X X for (n = strlen(str); n; n--) X WriteChar(*(str++)); X} X XWriteChar(c) Xchar c; X{ X if (defbuf) { X if (defbuf->curpos == defbuf->bufsiz -1) { X defbuf->bufsiz *= 2; X defbuf->memory = (char *)realloc(defbuf->memory, X defbuf->bufsiz * sizeof(char)); X if (defbuf->memory == (char *)NULL) { X fprintf(stderr,"realloc failed!\n"); X exit(-1); X } X } X defbuf->memory[defbuf->curpos++] = c; X defbuf->memory[defbuf->curpos] = (char)NULL; X } else X putchar(c); X} X XWriteVector(v) XVector *v; X{ X WriteFloat(v->x); X WriteFloat(v->y); X WriteFloat(v->z); X} X XWriteFloat(x) XFloat x; X{ X char buf[BUFSIZ]; X sprintf(buf, "%g ", x); X WriteVerbatim(buf); X} X XWriteNewline() X{ X WriteVerbatim("\n"); X} X XSetTypeList() X{ X if (defbuf) X defbuf->type = LIST; X /* else set world type */ X} X XSetTypeGrid(x,y,z) Xint x, y, z; X{ X if (defbuf) { X defbuf->type = GRID; X defbuf->x = x; defbuf->y = y; defbuf->z = z; X } /* else set world type */ X} X XWriteColor(c) XColor *c; X{ X WriteFloat(c->r); X WriteFloat(c->g); X WriteFloat(c->b); X} END_OF_FILE if test 14099 -ne `wc -c <'etc/rsconvert/yacc.y'`; then echo shar: \"'etc/rsconvert/yacc.y'\" unpacked with wrong size! fi chmod +x 'etc/rsconvert/yacc.y' # end of 'etc/rsconvert/yacc.y' fi if test -f 'libray/libobj/hf.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/hf.c'\" else echo shar: Extracting \"'libray/libobj/hf.c'\" \(17433 characters\) sed "s/^X//" >'libray/libobj/hf.c' <<'END_OF_FILE' X/* X * hf.c X * X * Copyright (C) 1989, 1991, Craig E. Kolb X * All rights reserved. X * X * This software may be freely copied, modified, and redistributed X * provided that this copyright notice is preserved on all copies. X * X * You may not distribute this software, in whole or in part, as part of X * any commercial product without the express consent of the authors. X * X * There is no warranty or other guarantee of fitness of this software X * for any purpose. It is provided solely "as is". X * X * $Id: hf.c,v 4.0.1.1 91/09/29 15:44:53 cek Exp Locker: cek $ X * X * $Log: hf.c,v $ X * Revision 4.0.1.1 91/09/29 15:44:53 cek X * patch1: Error messages missing newline. X * X * Revision 4.0 91/07/17 14:38:15 kolb X * Initial version. X * X */ X#include "geom.h" X#include "hf.h" X Xstatic Methods *iHfMethods = NULL; Xstatic char hfName[] = "heighfield"; X Xstatic void integrate_grid(), QueueTri(); Xstatic int DDA2D(), CheckCell(); Xstatic Float intHftri(); Xstatic float minalt(), maxalt(); X Xtypedef struct { X int stepX, stepY; X Float tDX, tDY; X float minz, maxz; X int outX, outY; X Vector cp, pDX, pDY; X} Trav2D; X XhfTri *CreateHfTriangle(), *GetQueuedTri(); X Xunsigned long HFTests, HFHits; X XHf * XHfCreate(filename) Xchar *filename; X{ X Hf *hf; X FILE *fp; X float val, *maxptr, *minptr; X int i, j; X X fp = fopen(filename, "r"); X if (fp == (FILE *)NULL) { X RLerror(RL_ABORT, "Cannot open heightfield file \"%s\".\n", X filename); X return (Hf *)NULL; X } X X hf = (Hf *)Malloc(sizeof(Hf)); X /* X * Make the following an option someday. X */ X hf->BestSize = BESTSIZE; X /* X * Store the inverse for faster computation. X */ X hf->iBestSize = 1. / (float)hf->BestSize; X /* X * Get HF size. X */ X if (fread((char *)&hf->size, sizeof(int), 1, fp) == 0) { X RLerror(RL_ABORT, "Cannot read height field size.\n"); X return (Hf *)NULL; X } X X hf->data = (float **)share_malloc(hf->size * sizeof(float *)); X for (i = 0; i < hf->size; i++) { X hf->data[i] = (float *)share_malloc(hf->size * sizeof(float)); X /* X * Read in row of HF data. X */ X if (fread((char *)hf->data[i],sizeof(float),hf->size,fp) X != hf->size) { X RLerror(RL_ABORT, "Not enough heightfield data.\n"); X return (Hf *)NULL; X } X for (j = 0; j < hf->size; j++) { X val = hf->data[i][j]; X if (val <= HF_UNSET) { X hf->data[i][j] = HF_UNSET; X /* X * Don't include the point in min/max X * calculations. X */ X continue; X } X if (val > hf->maxz) X hf->maxz = val; X if (val < hf->minz) X hf->minz = val; X } X } X (void)fclose(fp); X /* X * Allocate levels of grid. hf->levels = log base BestSize of hf->size X */ X for (i = hf->size, hf->levels = 0; i > hf->BestSize; i /= hf->BestSize, X hf->levels++) X ; X hf->levels++; X hf->qsize = CACHESIZE; X hf->q = (hfTri **)Calloc((unsigned)hf->qsize, sizeof(hfTri *)); X hf->qtail = 0; X X hf->lsize = (int *)share_malloc(hf->levels * sizeof(int)); X hf->spacing = (float *)share_malloc(hf->levels * sizeof(float)); X hf->boundsmax = (float ***)share_malloc(hf->levels * sizeof(float **)); X hf->boundsmin = (float ***)share_malloc(hf->levels * sizeof(float **)); X X hf->spacing[0] = hf->size -1; X hf->lsize[0] = (int)hf->spacing[0]; X hf->boundsmax[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *)); X hf->boundsmin[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *)); X /* X * Compute initial bounding boxes X */ X for (i = 0; i < hf->lsize[0]; i++) { X hf->boundsmax[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float)); X hf->boundsmin[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float)); X maxptr = hf->boundsmax[0][i]; X minptr = hf->boundsmin[0][i]; X for (j = 0; j < hf->lsize[0]; j++) { X *maxptr++ = maxalt(i, j, hf->data) + EPSILON; X *minptr++ = minalt(i, j, hf->data) - EPSILON; X } X } X X for (i = 1; i < hf->levels; i++) { X hf->spacing[i] = hf->spacing[i-1] * hf->iBestSize; X hf->lsize[i] = (int)hf->spacing[i]; X if ((Float)hf->lsize[i] != hf->spacing[i]) X hf->lsize[i]++; X hf->boundsmax[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *)); X hf->boundsmin[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *)); X for (j = 0; j < hf->lsize[i]; j++) { X hf->boundsmax[i][j] = (float *)share_malloc(hf->lsize[i] * X sizeof(float)); X hf->boundsmin[i][j] = (float *)share_malloc(hf->lsize[i] * X sizeof(float)); X } X integrate_grid(hf, i); X } X X hf->boundbox[LOW][X] = hf->boundbox[LOW][Y] = 0; X hf->boundbox[HIGH][X] = hf->boundbox[HIGH][Y] = 1; X hf->boundbox[LOW][Z] = hf->minz; X hf->boundbox[HIGH][Z] = hf->maxz; X X return hf; X} X XMethods * XHfMethods() X{ X if (iHfMethods == (Methods *)NULL) { X iHfMethods = MethodsCreate(); X iHfMethods->create = (GeomCreateFunc *)HfCreate; X iHfMethods->methods = HfMethods; X iHfMethods->name = HfName; X iHfMethods->intersect = HfIntersect; X iHfMethods->normal = HfNormal; X iHfMethods->uv = HfUV; X iHfMethods->bounds = HfBounds; X iHfMethods->stats = HfStats; X iHfMethods->checkbounds = TRUE; X iHfMethods->closed = FALSE; X } X return iHfMethods; X} X X/* X * Intersect ray with height field. X */ Xint XHfIntersect(hf, ray, mindist, maxdist) XHf *hf; XRay *ray; XFloat mindist, *maxdist; X{ X Vector hitpos; X Float offset; X Trav2D trav; X X HFTests++; X X /* X * Find where we hit the hf cube. X */ X VecAddScaled(ray->pos, mindist, ray->dir, &hitpos); X if (OutOfBounds(&hitpos, hf->boundbox)) { X offset = *maxdist; X if (!BoundsIntersect(ray, hf->boundbox, mindist, &offset)) X return FALSE; X hitpos.x = ray->pos.x + ray->dir.x * offset; X hitpos.y = ray->pos.y + ray->dir.y * offset; X hitpos.z = ray->pos.z + ray->dir.z * offset; X } else X hitpos = ray->pos; X /* X * Find out in which cell "hitpoint" is. X */ X if (equal(hitpos.x, 1.)) X hitpos.x -= EPSILON; X if (equal(hitpos.y, 1.)) X hitpos.y -= EPSILON; X X if (ray->dir.x < 0.) { X trav.stepX = trav.outX = -1; X trav.tDX = -1. / (ray->dir.x * hf->spacing[hf->levels -1]); X } else if (ray->dir.x > 0.) { X trav.stepX = 1; X trav.outX = hf->lsize[hf->levels -1]; X /* X * (1./size) / ray X */ X trav.tDX = 1. / (ray->dir.x * hf->spacing[hf->levels -1]); X } X X if (ray->dir.y < 0.) { X trav.stepY = trav.outY = -1; X trav.tDY = -1. / (ray->dir.y * hf->spacing[hf->levels -1]); X } else if (ray->dir.y > 0.) { X trav.stepY = 1; X trav.outY = hf->lsize[hf->levels -1]; X trav.tDY = 1. / (ray->dir.y * hf->spacing[hf->levels -1]); X } X X trav.pDX.x = ray->dir.x * trav.tDX; X trav.pDX.y = ray->dir.y * trav.tDX; X trav.pDX.z = ray->dir.z * trav.tDX; X trav.pDY.x = ray->dir.x * trav.tDY; X trav.pDY.y = ray->dir.y * trav.tDY; X trav.pDY.z = ray->dir.z * trav.tDY; X X trav.cp = hitpos; X trav.minz = hf->minz; X trav.maxz = hf->maxz; X if (DDA2D(hf, &ray->pos, &ray->dir, hf->levels -1, &trav, maxdist)) { X HFHits++; X return TRUE; X } X return FALSE; X} X X/* X * Traverse the grid using a modified DDA algorithm. If the extent of X * the ray over a cell intersects the bounding volume defined by the X * four corners of the cell, either recurse or perform ray/surface X * intersection test. X */ Xstatic int XDDA2D(hf, pos, ray, level, trav, maxdist) XHf *hf; XVector *pos, *ray; Xint level; XTrav2D *trav; XFloat *maxdist; X{ X int x, y, size, posZ; X float **boundsmin, **boundsmax, spacing; X Float tX, tY; X Trav2D newtrav; X Vector nxp, nyp; X X size = hf->lsize[level]; X spacing = hf->spacing[level]; X X posZ = (ray->z > 0.); X X x = trav->cp.x * hf->spacing[level]; X if (x == size) X x--; X y = trav->cp.y * hf->spacing[level]; X if (y == size) X y--; X boundsmax = hf->boundsmax[level]; X boundsmin = hf->boundsmin[level]; X X if (trav->outX > size) trav->outX = size; X if (trav->outY > size) trav->outY = size; X if (trav->outX < 0) trav->outX = -1; X if (trav->outY < 0) trav->outY = -1; X X if (ray->x < 0.) { X tX = (x /spacing - trav->cp.x) / ray->x; X } else if (ray->x > 0.) X tX = ((x+1)/spacing - trav->cp.x) / ray->x; X else X tX = FAR_AWAY; X if (ray->y < 0.) { X tY = (y /spacing - trav->cp.y) / ray->y; X } else if (ray->y > 0.) X tY = ((y+1)/spacing - trav->cp.y) / ray->y; X else X tY = FAR_AWAY; X X nxp.x = trav->cp.x + tX * ray->x; X nxp.y = trav->cp.y + tX * ray->y; X nxp.z = trav->cp.z + tX * ray->z; X X nyp.x = trav->cp.x + tY * ray->x; X nyp.y = trav->cp.y + tY * ray->y; X nyp.z = trav->cp.z + tY * ray->z; X X do { X if (tX < tY) { X if ((posZ && trav->cp.z <= boundsmax[y][x] && X nxp.z >= boundsmin[y][x]) || X (!posZ && trav->cp.z >= boundsmin[y][x] && X nxp.z <= boundsmax[y][x])) { X if (level) { X /* X * Recurse -- compute constants X * needed for next level. X * Nicely enough, this just X * involves a few multiplications. X */ X newtrav = *trav; X newtrav.tDX *= hf->iBestSize; X newtrav.tDY *= hf->iBestSize; X newtrav.maxz = boundsmax[y][x]; X newtrav.minz = boundsmin[y][x]; X if (ray->x < 0.) X newtrav.outX=hf->BestSize*x-1; X else X newtrav.outX=hf->BestSize*(x+1); X if (ray->y < 0.) X newtrav.outY=hf->BestSize*y-1; X else X newtrav.outY=hf->BestSize*(y+1); X newtrav.pDX.x *= hf->iBestSize; X newtrav.pDX.y *= hf->iBestSize; X newtrav.pDX.z *= hf->iBestSize; X newtrav.pDY.x *= hf->iBestSize; X newtrav.pDY.y *= hf->iBestSize; X newtrav.pDY.z *= hf->iBestSize; X if (DDA2D(hf,pos,ray,level-1, X &newtrav, maxdist)) X return TRUE; X } else if (CheckCell(x,y,hf,ray,pos,maxdist)) X return TRUE; X } X x += trav->stepX; /* Move in X */ X if (*maxdist < tX || x == trav->outX) X /* If outside, quit */ X return FALSE; X tX += trav->tDX; /* Update position on ray */ X trav->cp = nxp; /* cur pos gets next pos */ X nxp.x += trav->pDX.x; /* Compute next pos */ X nxp.y += trav->pDX.y; X nxp.z += trav->pDX.z; X } else { X if ((posZ && trav->cp.z <= boundsmax[y][x] && X nyp.z >= boundsmin[y][x]) || X (!posZ && trav->cp.z >= boundsmin[y][x] && X nyp.z <= boundsmax[y][x])) { X if (level) { X /* Recurse */ X newtrav = *trav; X newtrav.tDX *= hf->iBestSize; X newtrav.tDY *= hf->iBestSize; X newtrav.maxz = boundsmax[y][x]; X newtrav.minz = boundsmin[y][x]; X if (ray->x < 0.) X newtrav.outX=hf->BestSize*x-1; X else X newtrav.outX=hf->BestSize*(x+1); X if (ray->y < 0.) X newtrav.outY=hf->BestSize*y-1; X else X newtrav.outY=hf->BestSize*(y+1); X newtrav.pDX.x *= hf->iBestSize; X newtrav.pDX.y *= hf->iBestSize; X newtrav.pDX.z *= hf->iBestSize; X newtrav.pDY.x *= hf->iBestSize; X newtrav.pDY.y *= hf->iBestSize; X newtrav.pDY.z *= hf->iBestSize; X if (DDA2D(hf,pos,ray,level-1, X &newtrav, maxdist)) X return TRUE; X } else if (CheckCell(x,y,hf,ray,pos,maxdist)) X return TRUE; X } X y += trav->stepY; X if (*maxdist < tY || y == trav->outY) X return FALSE; X tY += trav->tDY; X trav->cp = nyp; X nyp.x += trav->pDY.x; X nyp.y += trav->pDY.y; X nyp.z += trav->pDY.z; X } X } while ((trav->cp.x <= 1. && trav->cp.y <= 1.) && X ((posZ && trav->cp.z <= trav->maxz) || X (!posZ && trav->cp.z >= trav->minz))); X X /* X * while ((we're inside the horizontal bounding box) X * (usually caught by outX & outY, but X * it's possible to go "too far" due to X * the fact that our levels of grids do X * not "nest" exactly if gridsize%BestSize != 0) X * and X * ((if ray->z is positive and we haven't gone through X * the upper bounding plane) or X * (if ray->z is negative and we haven't gone through X * the lower bounding plane))); X */ X X return FALSE; X} X X/* X * Check for ray/cell intersection X */ Xstatic int XCheckCell(x, y, hf, ray, pos, maxdist) Xint x, y; XHf *hf; XVector *ray, *pos; XFloat *maxdist; X{ X hfTri *tri1, *tri2; X Float d1, d2; X X d1 = d2 = FAR_AWAY; X X if (tri1 = CreateHfTriangle(hf, x, y, x+1, y, x, y+1, TRI1)) X d1 = intHftri(ray, pos, tri1); X if (tri2 = CreateHfTriangle(hf, x+1, y, x+1, y+1, x, y+1, TRI2)) X d2 = intHftri(ray, pos, tri2); X X if (d1 == FAR_AWAY && d2 == FAR_AWAY) X return FALSE; X X if (d1 < d2) { X if (d1 < *maxdist) { X hf->hittri = *tri1; X *maxdist = d1; X return TRUE; X } X return FALSE; X } X X if (d2 < *maxdist) { X hf->hittri = *tri2; X *maxdist = d2; X return TRUE; X } X return FALSE; X} X Xstatic hfTri * XCreateHfTriangle(hf, x1, y1, x2, y2, x3, y3, which) XHf *hf; Xint x1, y1, x2, y2, x3, y3, which; X{ X hfTri *tri; X Float xid, yid; X Vector tmp1, tmp2; X X /* X * Don't use triangles with "unset" vertices. X */ X if (hf->data[y1][x1] == HF_UNSET || X hf->data[y2][x2] == HF_UNSET || X hf->data[y3][x3] == HF_UNSET) X return (hfTri *)0; X X xid = (Float)x1 / (Float)(hf->size -1); X yid = (Float)y1 / (Float)(hf->size -1); X X if ((tri = GetQueuedTri(hf, xid, yid, which)) != (hfTri *)0) X return tri; X X tri = (hfTri *)Malloc(sizeof(hfTri)); X X tri->type = which; X tri->v1.x = xid; X tri->v1.y = yid; X tri->v1.z = hf->data[y1][x1]; X tri->v2.x = (Float)x2 / (Float)(hf->size-1); X tri->v2.y = (Float)y2 / (Float)(hf->size-1); X tri->v2.z = hf->data[y2][x2]; X tri->v3.x = (Float)x3 / (Float)(hf->size-1); X tri->v3.y = (Float)y3 / (Float)(hf->size-1); X tri->v3.z = hf->data[y3][x3]; X X tmp1.x = tri->v2.x - tri->v1.x; X tmp1.y = tri->v2.y - tri->v1.y; X tmp1.z = tri->v2.z - tri->v1.z; X tmp2.x = tri->v3.x - tri->v1.x; X tmp2.y = tri->v3.y - tri->v1.y; X tmp2.z = tri->v3.z - tri->v1.z; X X (void)VecNormCross(&tmp1, &tmp2, &tri->norm); X X tri->d = -dotp(&tri->v1, &tri->norm); X X QueueTri(hf, tri); X return tri; X} X X/* X * Intersect ray with right isoscoles triangle, the hypotenuse of which X * has slope of -1. X */ Xstatic Float XintHftri(ray, pos, tri) XhfTri *tri; XVector *pos, *ray; X{ X Float u, v, dist, xpos, ypos; X X u = dotp(&tri->norm, pos) + tri->d; X v = dotp(&tri->norm, ray); X X if ((u <= 0. || v > -EPSILON) && (u >= 0. && v < EPSILON)) X return FAR_AWAY; X X dist = -u / v; X X if (dist < EPSILON) X return FAR_AWAY; X X xpos = pos->x + dist*ray->x; X ypos = pos->y + dist*ray->y; X X if (tri->type == TRI1 && xpos >= tri->v1.x && ypos >= tri->v1.y && X xpos + ypos <= tri->v2.x + tri->v2.y) X return dist; X if (tri->type == TRI2 && xpos <= tri->v2.x && ypos <= tri->v2.y && X xpos + ypos >= tri->v1.x + tri->v1.y) X return dist; X return FAR_AWAY; X} X X/* X * Compute normal to height field. X */ X/*ARGSUSED*/ Xint XHfNormal(hf, pos, nrm, gnrm) XHf *hf; XVector *pos, *nrm, *gnrm; X{ X *gnrm = *nrm = hf->hittri.norm; X return FALSE; X} X X/*ARGSUSED*/ Xvoid XHfUV(hf, pos, norm, uv, dpdu, dpdv) XHf *hf; XVector *pos, *norm, *dpdu, *dpdv; XVec2d *uv; X{ X uv->u = pos->x; X uv->v = pos->y; X if (dpdu) { X dpdu->x = 1.; X dpdu->y = dpdv->z = 0.; X dpdv->x = dpdv->z = 0.; X dpdv->y = 1.; X } X} X X/* X * Compute heightfield bounding box. X */ Xvoid XHfBounds(hf, bounds) XHf *hf; XFloat bounds[2][3]; X{ X /* X * By default, height fields are centered at (0.5, 0.5, 0.) X */ X bounds[LOW][X] = bounds[LOW][Y] = 0; X bounds[HIGH][X] = bounds[HIGH][Y] = 1; X bounds[LOW][Z] = hf->minz; X bounds[HIGH][Z] = hf->maxz; X} X X/* X * Build min/max altitude value arrays for the given grid level. X */ Xstatic void Xintegrate_grid(hf, level) XHf *hf; Xint level; X{ X int i, j, k, l, ii, ji; X float max_alt, min_alt; X float **maxinto, **mininto, **frommax, **frommin, *minptr, *maxptr; X int insize, fromsize, fact; X X maxinto = hf->boundsmax[level]; X mininto = hf->boundsmin[level]; X insize = hf->lsize[level]; X frommax = hf->boundsmax[level-1]; X frommin = hf->boundsmin[level-1]; X fact = hf->BestSize; X fromsize = hf->lsize[level-1]; X X ii = 0; X X for (i = 0; i < insize; i++) { X ji = 0; X for (j = 0; j < insize; j++) { X max_alt = HF_UNSET; X min_alt = -HF_UNSET; X for (k = 0; k <= fact; k++) { X if (ii+k >= fromsize) X continue; X maxptr = &frommax[ii+k][ji]; X minptr = &frommin[ii+k][ji]; X for (l = 0; l <= fact; l++,maxptr++,minptr++) { X if (ji+l >= fromsize) X continue; X if (*maxptr > max_alt) X max_alt = *maxptr; X if (*minptr < min_alt) X min_alt = *minptr; X } X } X maxinto[i][j] = max_alt + EPSILON; X mininto[i][j] = min_alt - EPSILON; X ji += fact; X } X ii += fact; X } X} X X/* X * Place the given triangle in the triangle cache. X */ Xstatic void XQueueTri(hf, tri) XHf *hf; XhfTri *tri; X{ X if (hf->q[hf->qtail]) /* Free old triangle data */ X free((voidstar)hf->q[hf->qtail]); X hf->q[hf->qtail] = tri; /* Put on tail */ X hf->qtail = (hf->qtail + 1) % hf->qsize; /* Increment tail */ X} X X/* X * Search list of cached trianges to see if this triangle has been X * cached. If so, return a pointer to it. If not, return null pointer. X */ Xstatic hfTri * XGetQueuedTri(hf, x, y, flag) XHf *hf; XFloat x, y; Xint flag; X{ X register int i; X register hfTri **tmp; X X for (i = 0, tmp = hf->q; i < hf->qsize; i++, tmp++) { X if (*tmp && (*tmp)->v1.x == x && (*tmp)->v1.y == y && X (*tmp)->type == flag) X return *tmp; /* vertices & flag match, return it */ X } X X return (hfTri *)0; X} X X/* X * Return maximum height of cell indexed by y,x. This could be done X * as a macro, but many C compliers will choke on it. X */ Xstatic float Xminalt(y,x,data) Xint x, y; Xfloat **data; X{ X float min_alt; X X min_alt = min(data[y][x], data[y+1][x]); X min_alt = min(min_alt, data[y][x+1]); X min_alt = min(min_alt, data[y+1][x+1]); X return min_alt; X} X X/* X * Return maximum cell height, as above. X */ Xstatic float Xmaxalt(y,x,data) Xint x, y; Xfloat **data; X{ X float max_alt; X X max_alt = max(data[y][x], data[y+1][x]); X max_alt = max(max_alt, data[y][x+1]); X max_alt = max(max_alt, data[y+1][x+1]); X return max_alt; X} X Xchar * XHfName() X{ X return hfName; X} X Xvoid XHfStats(tests, hits) Xunsigned long *tests, *hits; X{ X *tests = HFTests; X *hits = HFHits; X} X Xvoid XHfMethodRegister(meth) XUserMethodType meth; X{ X if (iHfMethods) X iHfMethods->user = meth; X} END_OF_FILE if test 17433 -ne `wc -c <'libray/libobj/hf.c'`; then echo shar: \"'libray/libobj/hf.c'\" unpacked with wrong size! fi # end of 'libray/libobj/hf.c' fi echo shar: End of archive 16 \(of 19\). cp /dev/null ark16isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 19 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0
Up Directory CCL Part16
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh 'Doc/Guide/objects.tex' <<'END_OF_FILE'
X\chapter{Object Definition}
X
XObjects in {\rayshade} are composed of relatively simple {\em primitive}
Xobjects.  These primitives may be used by themselves, or they
Xmay be combined to form more complex objects known as {\em aggregates}.
XA special family of aggregate objects,
X{\em Constructive Solid Geometry} or CSG
Xobjects, are the result of a boolean operations applied to
Xprimitive, aggregate, or CSG objects.
X
XThis chapter describes objects from a strictly geometric point of
Xview.  Later chapters on surfaces, textures, and shading describe
Xhow object appearances are defined.
X
XAn {\em instance} is an object that has optionally been transformed
Xand
Xtextured.  They are the entities that are actually rendered by
X{\rayshade}; when you specify that, for example, a textured
Xsphere is to be rendered, you are said to be instantiating
Xthe textured sphere.
XAn instance
Xis specified as a primitive, aggregate, or CSG object that
Xis followed by optional transformation and texturing information.
XTransformations and textures are described in Chapters 7 and 8 respectively.
X
X\section{The World Object}
X
XWriting a {\rayshade} input file is principally
Xa matter of defining a special aggregate object, the World object,
Xwhich is a list of the objects in the scene.  When writing a {\rayshade}
Xinput file, all objects that are instantiated outside of object-definition
Xblocks are added to the World object; you need not (nor should you)
Xdefine the World object explicitly in the input file.
X
X\section{Primitives}
X
XPrimitive objects are the building box with which other objects are
Xcreated.  Each primitive type has associated with it specialized
Xmethods for
Xcreation,
Xintersection with a ray,
Xbounding box calculation,
Xsurface normal calculation,
Xray enter/exit classification,
Xand for the computation 2D texture coordinates termed {\em u-v}
Xcoordinates.
XThis latter method is often referred to as the {\em inverse mapping}
Xmethod.
X
XWhile most of these methods should be of little concern to you, the
Xinverse mapping methods
Xwill affect the way in which certain textures are applied to primitives.
XInverse mapping is a matter of computing normalized $u$ and $v$ coordinates
Xfor a given point on the surface of the primitive.  For planar objects,
Xthe $u$ and $v$ coordinates of a point are computed
Xby linear interpolation based upon the $u$ and $v$ coordinates assigned
Xto vertices or other known points on the primitive.  For non-planar
Xobjects, $uv$ computation can be considerably more involved.
X
XThis section briefly describes each primitive and
Xthe syntax that should be used to create an instance of the primitive.
XIt also describes the inverse mapping method, if any, for each type.
X
X\begin{defprim}{blob}{{\em thresh st r} \evec{p} [{\em st r} \evec{p} \ldots]}
X	Defines a blob with consisting of a threshold equal to {\em thresh},
X	and a
X	group of one or more metaballs.  Each metaball is defined by 
X	its position \evec{p}, radius {\em r}, and strength {\em st}.
X\end{defprim}
XThe metaballs affect each other according to a superimposed
Xdensity distribution:
X\[
XF(x,y,z) = \sum_{i=0}^n b_{i}e^{-d_{i}} - T = 0
X\]
XThere is no inverse mapping method for blobs.
X
X\begin{defprim}{box}{\evec{corner1} \evec{corner2}}
X	Creates an axis-aligned box
X	which has \evec{corner1} and \evec{corner2} as
X	opposite corners.
X\end{defprim}
XTransformations may be applied to the box if a non-axis-aligned instance
Xis required.  There is no inverse mapping method for boxes.
X
X\begin{defprim}{sphere}{{\em radius} \evec{center}}
X	Creates a sphere with the given {\em radius} and centered at the
X	given position.
X\end{defprim}
XNote that ellipsoids may be created by applying the proper scaling
Xto a sphere.  Inverse mapping on the sphere is accomplished
Xby computing the longitude and latitude of the point on the sphere,
Xwith the $u$ value corresponding to longitude and $v$ to latitude.
XOn an untransformed sphere, the $z$ axis defines the poles, and the
X$x$ axis intersects the sphere at $u = 0$, $v = 0.5$.  There are
Xdegeneracies at the poles: the south pole contains all points of
Xlatitude 0., the north all points of latitude 1.
X
X\begin{defprim}{torus}{{\em rmajor rminor} \evec{center} \evec{up}}
X	Creates a torus centered at \evec{center} by rotating
X	a circle with the given minor radius around the center
X	point at a distance equal to the major radius. 
X\end{defprim}
XIn tori inverse mapping,
Xthe $u$ value is computed using the angle of rotation about the
Xup vector, and the $v$ value is computing the angle of rotation
Xaround the tube, with $v=0$ occuring on the innermost point of the tube.
X
X\begin{defprim}{triangle}{\evec{p1} \evec{p2} \evec{p3}}
X	Creates a triangle with the given vertices.
X\end{defprim}
X
X\begin{defprim}{triangle}{\evec{p1} \evec{n1} \evec{p2} \evec{n2}
X	\evec{p3} \evec{n3}}
X	Creates a Phong-shaded triangle with the given vertices and
X	vertex normals.
X\end{defprim}
XFor both Phong- and flat-shaded triangles, the $u$ axis is the
Xvector from \evec{p1} to \evec{p2}, and the $v$ axis the vector
Xfrom \evec{p1} to \evec{p3}.  There is a degeneracy at
X\evec{p3}, which contains all points with $v = 1.0$.  This default
Xmapping may be modified using the {\tt triangleuv} primitive described
Xbelow.
X
X\begin{defprim}{triangleuv}{\evec{p1} \evec{n1} \evec{uv1}
X  \evec{p2} \evec{n2} \evec{uv2}
X  \evec{p3} \evec{n3} \evec{uv3}}
X	Creates a Phong-shaded triangle with the given vertices,
X	vertex normals.  When performing texturing, the
X	{\em uv} given for each vertex are used instead of the
X	default values.
X\end{defprim}
XWhen computing $uv$ coordinates within the interior of the
Xtriangle, linear interpolation of the coordinates associated with
Xeach triangle vertex is used.
X
X\begin{defprim}{poly}{\evec{p1} \evec{p2} \evec{p3} [\evec{p4} \ldots ]}
X	Creates a polygon with the given vertices. The vertices
X	should be given in counter-clockwise order as one is
X	looking at the ``front'' side of the polygon.  The number of
X	vertices in a polygon is limited only by available memory.
X\end{defprim}
XInverse mapping for arbitrary polygons is problematical.
X{\Rayshade}
Xpunts and equates $u$ with the $x$ coordinate of the point of intersection,
Xand $v$ with the $y$ coordinate.
X
X\begin{defprim}{heightfield}{{\em file}}
X	Creates a height field defined by the altitude data stored
X	in the named {\em file}.  The height field is based upon
X	perturbations of the unit square in the $z=0$ plane, and is
X	rendered as a surface tessellated by right isosceles triangles.
X\end{defprim}
XSee Appendix C for a discussion of the format of a height field file.
XHeight field inverse mapping is straight-forward:  $u$ is the
X$x$ coordinate of the point of intersection, $v$ the $y$ coordinate.
X
X\begin{defprim}{plane}{\evec{point} \evec{normal}}
X	Creates a plane that passes through the given point and
X	has the specified normal.
X\end{defprim}
XInverse mapping on the plane is identical to polygonal inverse mapping.
X
X\begin{defprim}{cylinder}{{\em radius} \evec{bottom} \evec{top}}
X	Creates a cylinder that extends from \evec{bottom} to \evec{top}
X	and has the indicated {\em radius}.  Cylinders are rendered
X	{\em without} endcaps.
X\end{defprim}
XThe cylinder's axis defines the $v$ axis.  The $u$ axis wraps around the
Xcylinder, with $u=0$ dependent upon the orientation of the cylinder.
X
X
X\begin{defprim}{cone}{$rad_{bottom}$ \evec{bottom} $rad_{top}$ \evec{top}}
X	Creats a (truncated) cone that extends from \evec{bottom} to
X	\evec{top}.  The cone will have a radius of $rad_{bottom}$ at
X	\evec{bottom} and a radius of $rad_{top}$ at \evec{top}.
X	Cones are rendered {\em without} endcaps.
X\end{defprim}
XCone inverse mapping is analogous to cylinder mapping.
X
X\begin{defprim}{disc}{{\em radius} \evec{pos} \evec{normal}}
X	Creates a disc centered at the given position and with the
X	indicated surface normal.
X\end{defprim}
XDiscs are useful for placing
Xendcaps on cylinders and cones.
XInverse mapping for the disc is based on the computation of the
Xnormalized polar coordinates of the point of intersection.  The
Xnormalized radius
Xof the point of intersection is assigned to $u$, while the normalized angle
Xfrom a reference vector is assigned to $v$.
X
X\section{Aggregate Objects}
X
XAn aggregate is a collection of primitives, aggregate, and CSG
Xobjects.  An aggregate, once defined, may be instantiated at will,
Xwhich means that
Xcopies that are optionally transformed and textured may be made.
XIf a scene calls for the presence of many geometrically identical
Xobjects, only one such object need be defined; the one defined object
Xmay then be instantiated many times.
X
XAn aggregate is one of several possible types.  These aggregate types
Xare differentiated by the type of ray/aggregate intersection algorithm
X(often termed an {\em acceleration technique} or {\em efficiency scheme})
Xthat is used.
X
XAggregates are defined by giving a keyword that defines the
Xtype of the aggregate, followed by
Xa series of object instantiations and
Xsurface definitions, and terminated using the {\tt end} keyword.
XIf a defined object contains no instantiations, a warning message
Xis printed.
X
XThe most basic type of aggregate, the {\em list}, performs
Xintersection testing in the simplest possible way:  Each object in the
Xlist is tested for intersection with the ray in turn, and the closest
Xintersection is returned.
X
X\begin{defkey}{list}{\ldots {\tt end}}
X	Create a List object containing those objects instantiated between
X	the {\tt list}/{\tt end} pair.
X\end{defkey}
X
XThe {\em grid} aggregate
Xdivides the region of space it occupies into a number of discrete
Xbox-shaped
Xvoxels.  Each of these voxels contains a list of the objects that
Xintersect the voxel.  This discretization makes it possible to
Xrestrict the objects
Xtested for intersection to those that are likely to hit the ray,
Xand to test
Xthe objects in nearly ``closest-first'' order.
X
X\begin{defkey}{grid}{{\em xvox yvox zvox} \ldots {\tt end}}
X	Create a Grid objects composed of {\em xvox} by {\em yvox} by
X	{\em zvox} voxels containing those objects
X	instantiated between the {\tt grid}/{\tt end} pair.
X\end{defkey}
XIt is usually only worthwhile to ``engrid'' rather large,
Xcomplex collections of objects.  Grids also use a great deal more
Xmemory than List objects.
X
X\section {Constructive Solid Geometry}
X
XConstructive Solid Geometry is
Xthe process of building solid objects from other solids.
XThe three CSG
Xoperators are Union, Intersection, and Difference.  Each operator
Xacts upon two objects and produces a single object result.
XBy combining multiple levels of CSG operators, complex
Xobjects can be produced from simple primitives.
X
XThe union of two objects results in an
Xobject that encloses the space occupied by the two given objects.
XIntersection results in an object that encloses the space where the two
Xgiven objects overlap.  Difference is an order dependent operator; it
Xresults in the
Xfirst given object minus the space where the second intersected
Xthe first.
X
X\subsection{CSG in {\Rayshade}}
X
XCSG in {\rayshade} will generally operate properly when applied to
Xconjunction with
Xon boxes, spheres,
Xtori, and blobs.
XThese primitives are by nature consistent, as they all
Xenclose a portion of space (no hole from the ``inside'' to the
X``outside''), have surface normals which point outward (they
Xare not ``inside-out''), and do not have any extraneous surfaces.
X
XCSG objects may also be constructed from aggregate objects.
XThese aggregates contain
Xwhatever is listed inside, and may therefore be inconsistent.
XFor example, an object which contains a single triangle will not
Xproduce correct results in CSG models, because the triangle does not enclose
Xspace.  However, a collection of four triangles which form a pyramid
Xdoes enclose space, and if the triangle normals
Xare oriented correctly,
Xthe CSG operators should work correctly on the pyramid.
X
XCSG objects are specified by surrounding the objects upon
Xwhich to operate, as well as any associated surface-binding commands,
Xby the operator verb on one side and the {\tt end}
Xkeyword on the other:
X
X\begin{defkey}{union}{$<${\em Object}$>$ $<${\em Object}$>$
X[$<${\em Object}$>$ \ldots] {\tt end}}
X	Specify a new object defined as the union of the
X	given objects.
X\end{defkey}
X
X\begin{defkey}{difference}{$<${\em Object}$>$ $<${\em Object}$>$ 
X[$<${\em Object}$>$ \ldots] {\tt end}}
X	Specify a new object defined as the difference of the
X	given objects.
X\end{defkey}
X
X\begin{defkey}{intersect}{$<${\em Object}$>$ $<${\em Object}$>$
X[$<${\em Object}$>$ \ldots] {\tt end}}
X	Specify a new object defined as the intersection of the
X	given objects.
X\end{defkey}
X
XNote that the current implementation does not support more that two
Xobjects in a CSG list (but it is planned for a future version).
X
X% The following aren simple CSG objects using the four consistent
X% primitives:
X% 
X% union box ... difference ...
X
X\subsection{Potential CSG Problems}
X
XA consistent CSG model is one which is made
Xup of solid objects with no dangling surfaces.  In {\rayshade},
Xit is quite easy to construct inconsistent models, which will usually
Xappear incorrect in the final images.
XIn {\rayshade}, CSG is implemented by maintaining
Xthe tree structure of the CSG operations.  This tree is traversed,
Xand the operators therein applied, on a per-ray basis.
XIt is therefore difficult to verify the consistency of
Xthe model ``on the fly.''
X
XOne class of CSG problems occur when
Xsurfaces of objects being operated upon
Xcoincide.  For example, when subtracting a box from another box to make a
Xsquare cup, the result will be wrong if the tops of the two boxes
Xcoincide.  To correct this, the inner box should be made
Xslightly taller than the outer box.
XA related problem that must be
Xavoided occurs when two coincident surfaces are assigned
Xdifferent surface properties.
X
XIt may seem that the union operator is unnecessary, since
Xlisting two objects together in an aggregate results
Xin an image that appears to be the same.
XWhile the result of such a short-cut
Xmay appear the same on the exterior, the interior
Xof the resulting object will contain
Xextraneous surfaces.
XThe following examples show this quite clearly.
X
X\begin{verbatim}
X    difference
X      box -2 0 -3  2 3 3
X      union  /* change to list; note bad internal surfaces */
X        sphere 2 1 0 0
X        sphere 2 -1 0 0
X      end
X    end rotate 1 0 0 -40  rotate 0 0 1 50
X\end{verbatim}
X
XThe visual evidence of an inconsistent CSG object varies depending
Xupon the operator being used.
XWhen subtracting a consistent object from and
Xinconsistent one, the resulting object will appear to be
Xthe union of the two objects, but the shading will be incorrect.
XIt will appear to be inside-out in places, while correct
Xin other places.  The inside-out sections indicate the areas
Xwhere the problems occur.
XSuch problems are often caused by
Xpolygons with incorrectly specified
Xnormals, or by surfaces that exactly coincide (which
Xappear as partial ``Swiss cheese'' objects).
X
XThe following example illustrates an attempt to subtract a sphere from
Xa pyramid defined using an incorrectly facing triangle.  Note
Xthat the resulting image obviously points to which triangle is
Xreversed.
X
X\begin{verbatim}
X    name pyramid list
X        triangle 1 0 0  0 1 0  0 0 1
X        triangle 1 0 0  0 0 0  0 1 0
X        triangle 0 1 0  0 0 0  0 0 1
X        triangle 0 0 1  1 0 0  0 0 0  /* wrong order */
X    end
X
X    difference
X        object pyramid scale 3 3 3 rotate 0 0 1 45
X            rotate 1 0 0 -30 translate 0 -3.5 0
X        sphere 2.4 0 0 0
X    end
X\end{verbatim}
X
XBy default, cylinders and cones do not have end caps, and thus
Xare not consistent primitives.  One must usually
Xadd endcaps by listing the
Xcylinder or cone with (correctly-oriented) endcap discs in an aggregate.
X
X\section {Named Objects}
X
XA name may be associated with any primitive, aggregate, or CSG
Xobject through the use of the {\tt name}
Xkeyword:
X
X\begin{defkey}{name}{{\em objname} $<${\em Instance\/}$>$}
X	Associate {\em objname} with the given object.  The
X	specified object is not actually instantiated; it
X	is only stored under the given name.
X\end{defkey}
X
XAn object thus named may then be instantiated (with possible
Xadditional transforming and texturing) via the {\tt object} keyword:
X
X\begin{defkey}{object}{{\em objname} [$<$Transformations$>$] [$<$Textures$>$]}
X	Instantiate a copy of the object associated with {\em objname}.
X	If given, the transformations and textures are composed
X	with any already associated with
X	the object being instantiated.
X\end{defkey}
END_OF_FILE
if test 16473 -ne `wc -c <'Doc/Guide/objects.tex'`; then
    echo shar: \"'Doc/Guide/objects.tex'\" unpacked with wrong size!
fi
# end of 'Doc/Guide/objects.tex'
fi
if test -f 'etc/rsconvert/yacc.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'etc/rsconvert/yacc.y'\"
else
echo shar: Extracting \"'etc/rsconvert/yacc.y'\" \(14099 characters\)
sed "s/^X//" >'etc/rsconvert/yacc.y' <<'END_OF_FILE'
X/* yacc.y								   */
X/*									   */
X/* Copyright (C) 1989, 1991, Craig E. Kolb				   */
X/* All rights reserved.							   */
X/*									   */
X/* This software may be freely copied, modified, and redistributed,	   */
X/* provided that this copyright notice is preserved on all copies.	   */
X/*									   */
X/* You may not distribute this software, in whole or in part, as part of   */
X/* any commercial product without the express consent of the authors.      */
X/* 									   */
X/* There is no warranty or other guarantee of fitness of this software	   */
X/* for any purpose.  It is provided solely "as is".			   */
X/* $Id: yacc.y,v 4.0.1.3 92/02/07 11:05:21 cek Exp Locker: cek $ */
X%{
X#include 
X#include "libcommon/common.h"
X
X#define NEWLINE()	WriteNewline()
X/*#define NEWLINE()	printf("\n")*/
X#define LIST	0
X#define GRID	1
Xchar yyfilename[BUFSIZ];
Xextern int yylineno;
X%}
X%union {
X	char *c;
X	int i;
X	double d;
X	Color col;
X	Vector v;
X};
X%token  tFLOAT
X%token  tSTRING tHASHTHING
X%token  tINT
X%type  Fnumber sFnumber
X%type 
Modified: Wed Dec 11 17:00:00 1996 GMT
Page accessed 1224 times since Sat Apr 17 21:59:35 1999 GMT