home *** CD-ROM | disk | FTP | other *** search
- /*
- * flame.c
- *
- * Projektarbeit '94
- *
- * written by Reto Mani
- *
- */
-
- #include "geom.h" /* Definition of Vector, ... */
- #include "../libsurf/surface.h" /* Definition of SurfaceCreate() */
- #include "../libtext/texture.h" /* Definition of Chaos() */
- #include "flame.h" /* Definition of Flame functions */
- #include "../liblight/light.h" /* Definition of LightCreate()
- #include "../liblight/point.h" /* Definition of LightPointCreate() */
-
- #define FLAMERATIO 0.2 /* Flamelength/Flamewidth */
- /*#define SPEED 5.0 */ /* movement speed of flame */
-
- static Methods *iFlameMethods = NULL;
- static char flameName[] = "flame";
-
- unsigned long FlameTests=0, FlameHits=0;
-
-
- /* Create & return reference to a flame */
- Geom *FlameCreate(size,pos,lightswitch,speed) /* Create a Geom Object! */
- Float size,speed;
- Vector *pos;
- int lightswitch;
- {
- Geom *nob;
- Surface *nsurf;
- Float delta;
- Vector vec;
- Color col;
- Light *ltmp;
-
- nsurf=SurfaceCreate();
- nsurf->noshadow=TRUE;
-
- nob=GeomCreate((GeomRef)FlameObjCreate(size,pos,speed,nsurf),FlameMethods());
-
- if(!nob) return (Geom *) NULL; /* degenerate problem */
-
- nob->surf=nsurf;
-
- if (lightswitch)
- {
- /* Create the lights */
- col.r=.8;col.g=.7;col.b=.5;
- delta=size*FLAMERATIO;
- vec.x=pos->x+delta;
- vec.y=pos->y+delta;
- vec.z=pos->z+size/2;
- ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
- LightAddToDefined(ltmp);
- vec.x=pos->x-delta;
- vec.y=pos->y-delta;
- ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
- LightAddToDefined(ltmp);
- vec.x=pos->x+delta;
- vec.y=pos->y-delta;
- ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
- LightAddToDefined(ltmp);
- vec.x=pos->x-delta;
- vec.y=pos->y+delta;
- ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
- LightAddToDefined(ltmp);
- }
-
- NoiseInit();
-
- return nob;
- }
-
-
- Flame *FlameObjCreate(size,pos,speed,newsurf) /* Create the Flame Object */
- Float size,speed;
- Vector *pos;
- Surface *newsurf;
- {
- Flame *flame;
-
- if (fabs(size)<EPSILON)
- {
- RLerror(RL_WARN,"Degenerate flame.\n");
- return (Flame *)NULL;
- }
-
- flame = (Flame *)share_malloc(sizeof(Flame));
-
- flame->size = size;
- flame->x = pos->x;
- flame->y = pos->y;
- flame->z = pos->z;
- flame->surface = newsurf;
- flame->speed = speed;
-
- return flame;
- }
-
-
- Methods *FlameMethods()
- {
- if (iFlameMethods == (Methods *)NULL)
- {
- iFlameMethods = MethodsCreate();
- iFlameMethods->create = (GeomCreateFunc *)FlameObjCreate;
- iFlameMethods->methods = FlameMethods;
- iFlameMethods->name = FlameName;
- iFlameMethods->intersect = FlameIntersect;
- iFlameMethods->normal = FlameNormal;
- iFlameMethods->uv = FlameUV;
- iFlameMethods->enter = FlameEnter;
- iFlameMethods->bounds = FlameBounds;
- iFlameMethods->stats = FlameStats;
- iFlameMethods->checkbounds = TRUE;
- iFlameMethods->closed = TRUE;
- }
- return iFlameMethods;
- }
-
-
- /* Ray/Flame intersection test */
- int FlameIntersect(flame, ray, mindist, maxdist)
- Flame *flame;
- Ray *ray;
- Float mindist, *maxdist;
- {
- Float xadj,yadj,zadj,lambda;
- Float u,v; /* Coord in Flameplane */
- Color color;
-
- FlameTests++;
-
- xadj=ray->pos.x - flame->x;
- yadj=ray->pos.y - flame->y;
- zadj=ray->pos.z - flame->z;
-
- /* calculate coordinates of ray in the flame plane */
- lambda=-xadj*ray->dir.x-yadj*ray->dir.y;
- lambda/=ray->dir.x*ray->dir.x+ray->dir.y*ray->dir.y;
- u=xadj+lambda*ray->dir.x;
- v=yadj+lambda*ray->dir.y;
- if (u<0.0)
- u=-sqrt(u*u+v*v);
- else
- u=sqrt(u*u+v*v);
- v=zadj+lambda*ray->dir.z;
-
- if (v<0.0)
- return FALSE;
-
- if (FlameCalcColor(flame,u,v,ray->time))
- if (lambda > mindist && lambda < *maxdist)
- {
- *maxdist=lambda;
- FlameHits++;
- return TRUE;
- }
- return FALSE;
- }
-
-
- /* set the color of the flame depending on coordinates and time */
- int FlameCalcColor(flame,u,v,ftime)
- Flame *flame;
- Float u,v,ftime;
- {
- Float rad,uf,vf,chval,turb,tmpv,speed;
- Vector vec;
- Color color;
-
- /* calculate the radius of point (u,v) on the flame */
-
-
- vf=flame->size*flame->size;
- uf=vf*FLAMERATIO*FLAMERATIO;
- vf*=0.25;
- tmpv=v-flame->size*0.5;
- rad=u*u/uf+tmpv*tmpv/vf;
-
- if (rad<1.0)
- {
- /* This is the color-function */
- color.r=(rad < 0.333) ? 1.0 : 1.33-rad;
- color.g=1.0-0.9*rad;
- color.b=(rad < 0.666) ? 1.0-rad*1.5 : 0.0;
-
- /* adding turbulence */
- speed=flame->speed*10.0;
- vec.x=flame->x+u;
- vec.y=flame->y+v-ftime/speed; /* motion in vertical direction! */
- vec.z=flame->z+ftime/speed;
- chval = Chaos(&vec,4); /* calling the turbulence function */
- turb=(3.0*v/flame->size)*(chval-.5);
- color.r+=turb;
- color.g+=turb;
- color.b+=turb;
-
- if (color.r<0.0) color.r=0.0; else if (color.r>1.0) color.r=1.0;
- if (color.g<0.0) color.g=0.0; else if (color.g>1.0) color.g=1.0;
- if (color.b<0.0) color.b=0.0; else if (color.b>1.0) color.b=1.0;
-
- if (color.r==0.0 && color.g==0.0 && color.b==0.0) return FALSE;
-
- /* setting the color */
- flame->surface->amb.r=color.r;
- flame->surface->amb.g=color.g;
- flame->surface->amb.b=color.b;
-
- flame->surface->diff.r=color.r;
- flame->surface->diff.g=color.g;
- flame->surface->diff.b=color.b;
-
- return TRUE;
- }
- else
- return FALSE;
- }
-
-
- /* Compute normal to flame at pos */
- int FlameNormal(flame, pos, nrm, gnrm)
- Flame *flame;
- Vector *pos, *nrm, *gnrm;
- {
- nrm->x=(pos->x - flame->x);
- nrm->y=(pos->y - flame->y);
- nrm->z=0.0;
- (void)VecNormalize(nrm);
- *gnrm=*nrm;
- return FALSE;
- }
-
-
- /* Determine if ray enters (TRUE) or leaves (FALSE) flame at pos */
- int FlameEnter(flame, ray, mind, hitd)
- Flame *flame;
- Ray *ray;
- Float mind, hitd;
- {
- return TRUE;
- }
-
-
- /* ARGSUSED */
- void FlameUV(flame, pos, norm, uv, dpdu, dpdv)
- Flame *flame;
- Vector *pos, *norm, *dpdu, *dpdv;
- Vec2d *uv;
- {
- }
-
-
- void FlameBounds(flame, bounds)
- Flame *flame;
- Float bounds[2][3];
- {
- Float diff=flame->size * FLAMERATIO;
-
- bounds[LOW][X] = flame->x-diff;
- bounds[HIGH][X] = flame->x+diff;
- bounds[LOW][Y] = flame->y-diff;
- bounds[HIGH][Y] = flame->y+diff;
- bounds[LOW][Z] = flame->z;
- bounds[HIGH][Z] = flame->z+flame->size;
- }
-
-
- char *FlameName()
- {
- return flameName;
- }
-
-
- void FlameStats(tests, hits)
- unsigned long *tests, *hits;
- {
- *tests = FlameTests;
- *hits = FlameHits;
- }
-
-
- void FlameMethodRegister(meth)
- UserMethodType meth;
- {
- if (iFlameMethods)
- iFlameMethods->user = meth;
- }
-
-