home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libobj / flame.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  6.6 KB  |  293 lines

  1. /*
  2.  * flame.c
  3.  *
  4.  * Projektarbeit '94
  5.  *
  6.  * written by Reto Mani
  7.  *
  8.  */
  9.  
  10. #include "geom.h"                 /* Definition of Vector, ... */
  11. #include "../libsurf/surface.h"   /* Definition of SurfaceCreate() */
  12. #include "../libtext/texture.h"   /* Definition of Chaos() */
  13. #include "flame.h"                /* Definition of Flame functions */
  14. #include "../liblight/light.h"    /* Definition of LightCreate()
  15. #include "../liblight/point.h"    /* Definition of LightPointCreate() */
  16.  
  17. #define FLAMERATIO   0.2   /* Flamelength/Flamewidth */
  18. /*#define SPEED 5.0 */ /* movement speed of flame */
  19.  
  20. static Methods *iFlameMethods = NULL;
  21. static char flameName[] = "flame";
  22.  
  23. unsigned long FlameTests=0, FlameHits=0;
  24.  
  25.  
  26. /* Create & return reference to a flame */
  27. Geom *FlameCreate(size,pos,lightswitch,speed)   /* Create a Geom Object! */
  28. Float  size,speed;
  29. Vector *pos;
  30. int lightswitch;
  31. {
  32.    Geom    *nob;
  33.    Surface *nsurf;
  34.    Float   delta;
  35.    Vector  vec;
  36.    Color   col;
  37.    Light   *ltmp;
  38.  
  39.    nsurf=SurfaceCreate();
  40.    nsurf->noshadow=TRUE;
  41.  
  42.    nob=GeomCreate((GeomRef)FlameObjCreate(size,pos,speed,nsurf),FlameMethods());
  43.  
  44.    if(!nob) return (Geom *) NULL; /* degenerate problem */
  45.  
  46.    nob->surf=nsurf;
  47.  
  48.    if (lightswitch)
  49.       {
  50.       /* Create the lights */
  51.       col.r=.8;col.g=.7;col.b=.5;
  52.       delta=size*FLAMERATIO;
  53.       vec.x=pos->x+delta;
  54.       vec.y=pos->y+delta;
  55.       vec.z=pos->z+size/2;
  56.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  57.       LightAddToDefined(ltmp);
  58.       vec.x=pos->x-delta;
  59.       vec.y=pos->y-delta;
  60.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  61.       LightAddToDefined(ltmp);
  62.       vec.x=pos->x+delta;
  63.       vec.y=pos->y-delta;
  64.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  65.       LightAddToDefined(ltmp);
  66.       vec.x=pos->x-delta;
  67.       vec.y=pos->y+delta;
  68.       ltmp=LightCreate((LightRef)PointCreate(&vec),PointMethods(),&col);
  69.       LightAddToDefined(ltmp);
  70.       }
  71.  
  72.    NoiseInit();
  73.  
  74.    return nob;
  75. }
  76.  
  77.  
  78. Flame *FlameObjCreate(size,pos,speed,newsurf)  /* Create the Flame Object */
  79. Float    size,speed;
  80. Vector   *pos;
  81. Surface  *newsurf;
  82. {
  83.    Flame *flame;
  84.  
  85.    if (fabs(size)<EPSILON)
  86.       {
  87.       RLerror(RL_WARN,"Degenerate flame.\n");
  88.       return (Flame *)NULL;
  89.       }
  90.  
  91.    flame = (Flame *)share_malloc(sizeof(Flame));
  92.  
  93.    flame->size    = size;
  94.    flame->x       = pos->x;
  95.    flame->y       = pos->y;
  96.    flame->z       = pos->z;
  97.    flame->surface = newsurf;
  98.    flame->speed   = speed;
  99.  
  100.    return flame;
  101. }
  102.  
  103.  
  104. Methods *FlameMethods()
  105. {
  106.    if (iFlameMethods == (Methods *)NULL)
  107.       {
  108.       iFlameMethods = MethodsCreate();
  109.       iFlameMethods->create = (GeomCreateFunc *)FlameObjCreate;
  110.       iFlameMethods->methods = FlameMethods;
  111.       iFlameMethods->name = FlameName;
  112.       iFlameMethods->intersect = FlameIntersect;
  113.       iFlameMethods->normal = FlameNormal;
  114.       iFlameMethods->uv = FlameUV;
  115.       iFlameMethods->enter = FlameEnter;
  116.       iFlameMethods->bounds = FlameBounds;
  117.       iFlameMethods->stats = FlameStats;
  118.       iFlameMethods->checkbounds = TRUE;
  119.       iFlameMethods->closed = TRUE;
  120.       }
  121.    return iFlameMethods;
  122. }
  123.  
  124.  
  125. /* Ray/Flame intersection test */
  126. int FlameIntersect(flame, ray, mindist, maxdist)
  127. Flame *flame;
  128. Ray *ray;
  129. Float mindist, *maxdist;
  130. {
  131.    Float xadj,yadj,zadj,lambda;
  132.    Float u,v;  /* Coord in Flameplane */
  133.    Color color;
  134.  
  135.    FlameTests++;
  136.  
  137.    xadj=ray->pos.x - flame->x;
  138.    yadj=ray->pos.y - flame->y;
  139.    zadj=ray->pos.z - flame->z;
  140.  
  141.    /* calculate coordinates of ray in the flame plane */
  142.    lambda=-xadj*ray->dir.x-yadj*ray->dir.y;
  143.    lambda/=ray->dir.x*ray->dir.x+ray->dir.y*ray->dir.y;
  144.    u=xadj+lambda*ray->dir.x;
  145.    v=yadj+lambda*ray->dir.y;
  146.    if (u<0.0)
  147.       u=-sqrt(u*u+v*v);
  148.    else
  149.       u=sqrt(u*u+v*v);
  150.    v=zadj+lambda*ray->dir.z;
  151.  
  152.    if (v<0.0) 
  153.       return FALSE;
  154.  
  155.    if (FlameCalcColor(flame,u,v,ray->time))
  156.       if (lambda > mindist && lambda < *maxdist)
  157.          {
  158.          *maxdist=lambda;
  159.          FlameHits++;
  160.          return TRUE;
  161.          }
  162.    return FALSE;
  163. }
  164.  
  165.  
  166. /* set the color of the flame depending on coordinates and time */
  167. int FlameCalcColor(flame,u,v,ftime)
  168. Flame *flame;
  169. Float u,v,ftime;
  170. {
  171.    Float rad,uf,vf,chval,turb,tmpv,speed;
  172.    Vector vec;
  173.    Color color;
  174.    
  175.    /* calculate the radius of point (u,v) on the flame */
  176.  
  177.  
  178.    vf=flame->size*flame->size;
  179.    uf=vf*FLAMERATIO*FLAMERATIO;
  180.    vf*=0.25;
  181.    tmpv=v-flame->size*0.5;
  182.    rad=u*u/uf+tmpv*tmpv/vf;
  183.  
  184.    if (rad<1.0)
  185.       {
  186.       /* This is the color-function */
  187.       color.r=(rad < 0.333) ? 1.0 : 1.33-rad;
  188.       color.g=1.0-0.9*rad;
  189.       color.b=(rad < 0.666) ? 1.0-rad*1.5 : 0.0;
  190.  
  191.       /* adding turbulence */
  192.       speed=flame->speed*10.0;
  193.       vec.x=flame->x+u;
  194.       vec.y=flame->y+v-ftime/speed;  /* motion in vertical direction! */
  195.       vec.z=flame->z+ftime/speed;
  196.       chval = Chaos(&vec,4);         /* calling the turbulence function */
  197.       turb=(3.0*v/flame->size)*(chval-.5);
  198.       color.r+=turb;
  199.       color.g+=turb;
  200.       color.b+=turb;
  201.  
  202.       if (color.r<0.0) color.r=0.0; else if (color.r>1.0) color.r=1.0;
  203.       if (color.g<0.0) color.g=0.0; else if (color.g>1.0) color.g=1.0;
  204.       if (color.b<0.0) color.b=0.0; else if (color.b>1.0) color.b=1.0;
  205.  
  206.       if (color.r==0.0 && color.g==0.0 && color.b==0.0) return FALSE;
  207.  
  208.       /* setting the color */
  209.       flame->surface->amb.r=color.r;
  210.       flame->surface->amb.g=color.g;
  211.       flame->surface->amb.b=color.b;
  212.  
  213.       flame->surface->diff.r=color.r;
  214.       flame->surface->diff.g=color.g;
  215.       flame->surface->diff.b=color.b;
  216.  
  217.       return TRUE;
  218.       }
  219.    else
  220.       return FALSE;
  221. }
  222.  
  223.  
  224. /* Compute normal to flame at pos */
  225. int FlameNormal(flame, pos, nrm, gnrm)
  226. Flame *flame;
  227. Vector *pos, *nrm, *gnrm;
  228. {
  229.    nrm->x=(pos->x - flame->x);
  230.    nrm->y=(pos->y - flame->y);
  231.    nrm->z=0.0;
  232.    (void)VecNormalize(nrm);
  233.    *gnrm=*nrm;
  234.    return FALSE;
  235. }
  236.  
  237.  
  238. /* Determine if ray enters (TRUE) or leaves (FALSE) flame at pos */
  239. int FlameEnter(flame, ray, mind, hitd)
  240. Flame *flame;
  241. Ray *ray;
  242. Float mind, hitd;
  243. {
  244.    return TRUE;
  245. }
  246.  
  247.  
  248. /* ARGSUSED */
  249. void FlameUV(flame, pos, norm, uv, dpdu, dpdv)
  250. Flame *flame;
  251. Vector *pos, *norm, *dpdu, *dpdv;
  252. Vec2d *uv;
  253. {
  254. }
  255.  
  256.  
  257. void FlameBounds(flame, bounds)
  258. Flame *flame;
  259. Float bounds[2][3];
  260. {
  261.    Float  diff=flame->size * FLAMERATIO;
  262.  
  263.    bounds[LOW][X]  = flame->x-diff;
  264.    bounds[HIGH][X] = flame->x+diff;
  265.    bounds[LOW][Y]  = flame->y-diff;
  266.    bounds[HIGH][Y] = flame->y+diff;
  267.    bounds[LOW][Z]  = flame->z;
  268.    bounds[HIGH][Z] = flame->z+flame->size;
  269. }
  270.  
  271.  
  272. char *FlameName()
  273. {
  274.    return flameName;
  275. }
  276.  
  277.  
  278. void FlameStats(tests, hits)
  279. unsigned long *tests, *hits;
  280. {
  281.    *tests = FlameTests;
  282.    *hits = FlameHits;
  283. }
  284.  
  285.  
  286. void FlameMethodRegister(meth)
  287. UserMethodType meth;
  288. {
  289.    if (iFlameMethods)
  290.       iFlameMethods->user = meth;
  291. }
  292.  
  293.