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

  1. /*
  2.  * projector.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  * 
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * Projector light source itself written and copyrighted by Greg Spencer and 
  17.  * given to the Public Domain, with the above conditions.
  18.  *
  19.  * projector.c,v 4.1 1994/08/09 07:57:14 explorer Exp
  20.  *
  21.  * projector.c,v
  22.  * Revision 4.1  1994/08/09  07:57:14  explorer
  23.  * Bump version to 4.1
  24.  *
  25.  * Revision 1.1.1.1  1994/08/08  04:52:04  explorer
  26.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  27.  *
  28.  */
  29. #include "light.h"
  30. #include "projector.h"
  31. #ifdef __SASC
  32. #define M_PI PI
  33. #endif
  34.  
  35. static LightMethods *iProjectorMethods = NULL;
  36.  
  37. Projectorlight *
  38. ProjectorCreate(from, to, up, image, uangle, vangle, falloff)
  39. Vector *from, *to, *up;
  40. ImageText *image;
  41. Float uangle,vangle;
  42. int falloff;
  43. {
  44.     Projectorlight *projector; /* pointer for projector object */
  45.  
  46.     /* allocate space for projector */
  47.     projector = (Projectorlight *)share_malloc(sizeof(Projectorlight));
  48.  
  49.     projector->pos = *from;
  50.     VecSub(*to, *from, &projector->dir);
  51.     if (VecNormalize(&projector->dir) == 0.) {
  52.         RLerror(RL_ABORT,"Invalid projectorlight specification.\n");
  53.         return (Projectorlight *)NULL;
  54.     }
  55.  
  56.     /*
  57.      * If angles are zero, set it to 0.5 degrees -- just to keep from
  58.      * exploding...
  59.      */
  60.     if ((uangle==0.0)||(vangle==0.0)) uangle=vangle=0.5;
  61.  
  62.     /* note: these are solid angles, not spherical coords */
  63.     projector->uangle = ((uangle*M_PI)/180.0);
  64.     projector->vangle = ((vangle*M_PI)/180.0);
  65.     projector->v = *up;
  66.  
  67.     /* find a u direction for the projector from v and direction */
  68.     VecNormCross(up,&projector->dir,&projector->u);
  69.  
  70.     /* if falloff is true, then use r^2 falloff, otherwise ignore it */
  71.     projector->falloff=falloff;
  72.  
  73.     projector->image = image;
  74.     return projector;
  75. }
  76.  
  77. LightMethods *
  78. ProjectorMethods()
  79. {
  80.     if (iProjectorMethods == (LightMethods *)NULL) {
  81.         iProjectorMethods = LightMethodsCreate();
  82.         iProjectorMethods->intens = ProjectorIntens;
  83.         iProjectorMethods->dir = ProjectorDirection;
  84.     }
  85.     return iProjectorMethods;
  86. }
  87.  
  88. /*
  89.  * Calculate intensity ('color') of light reaching 'pos' from light 'lp'.
  90.  * The projectorlight is 'dist' units from 'pos' along 'dir'.
  91.  *
  92.  * Returns TRUE if non-zero illumination, FALSE otherwise.
  93.  */
  94. int
  95. ProjectorIntens(projector, lcolor, cache, ray, dist, noshadow, color)
  96. Projectorlight *projector;
  97. ShadowCache *cache;
  98. Ray *ray;
  99. Color *lcolor, *color;
  100. int noshadow;
  101. Float dist;
  102. {
  103.     Color imagecolor;
  104.     extern Float ProjectorAtten();
  105.     Float dist2;
  106.  
  107.     color->r = lcolor->r;
  108.     color->g = lcolor->g;
  109.     color->b = lcolor->b;
  110.  
  111.     /*
  112.      * Compute projectorlight color -- return if outside image
  113.      */
  114.     if (ProjectorImageApply(projector, ray, &imagecolor)
  115.     == FALSE) return FALSE;
  116.     /*
  117.      * If outside of projector, return FALSE.
  118.      */
  119.     if (imagecolor.r+imagecolor.g+imagecolor.b == 0.)
  120.     return FALSE;
  121.     if (Shadowed(color, lcolor, cache, ray, dist, noshadow))
  122.     return FALSE;
  123.  
  124.     if (projector->falloff) {
  125.     dist2= dist*dist;
  126.     if (dist2 < 1.0) dist2=1.0; /* below 1.0, falloff is closer to 1:1 */
  127.     color->r *= imagecolor.r/dist2;
  128.     color->g *= imagecolor.g/dist2;
  129.     color->b *= imagecolor.b/dist2;
  130.     }
  131.     else {
  132.     color->r *= imagecolor.r;
  133.     color->g *= imagecolor.g;
  134.     color->b *= imagecolor.b;
  135.     }
  136.     return TRUE;
  137. }
  138.  
  139. /*
  140.  * Map Image to the 'dir' direction
  141.  * adapted from ImageTextApply.
  142.  */
  143. int
  144. ProjectorImageApply(pl, ray, imagecolor)
  145. Projectorlight *pl;
  146. Ray *ray;
  147. Color *imagecolor;
  148. {
  149.     Float fx, fy; /* sub-pixel coords */
  150.     ImageText *text; /* imagetext input */
  151.     Float outval[4], outval_u[4], outval_v[4]; /* returned color values */
  152.     Float u, v; /* whole-valued u-v coords */
  153.     Float rdotu, rdotv, rdotp; /* dot products */
  154.     int ix, iy; /* integer u-v components */
  155.     int rchan, gchan, bchan; /* position of channels in input */
  156.     Vector rdir; /* ray direction */
  157.  
  158.     text=pl->image;
  159.     rdir.x= -ray->dir.x;
  160.     rdir.y= -ray->dir.y;
  161.     rdir.z= -ray->dir.z;
  162.     rdotp = dotp(&rdir, &pl->dir);
  163.     /*
  164.      * Check to see if ray is behind projectorlight.
  165.      * also eliminates the possibility of a divide by zero
  166.      * later on (if we come in exactly at 90 degrees from
  167.      * light direction)
  168.      */
  169.     if (rdotp <= 0.000001) return FALSE;
  170.  
  171.     /*
  172.      * pos is position of origin of the ray
  173.      * pl->pos is the position of the projector
  174.      * pl->dir is the direction the projector points in
  175.      * dir is the direction from the ray origin to the projector
  176.      */
  177.  
  178.     rdotu= dotp(&rdir,&pl->u);
  179.     rdotv= dotp(&rdir,&pl->v);
  180.  
  181.     u= text->tileu/2.0+atan(rdotu/rdotp)/pl->uangle;
  182.     v= text->tilev/2.0+atan(rdotv/rdotp)/pl->vangle;
  183.  
  184.     /*
  185.      * Handle tiling at this point.
  186.      * (merely checks to see if we're outside the tile space)
  187.      */
  188.  
  189.     if (TileValue(text->tileu, text->tilev, u, v)) return FALSE;
  190.  
  191.     u -= floor(u); /* remove all but fractional portion */
  192.     v -= floor(v);
  193.     fx = u * (Float) text->image->width; /* multiply by size */
  194.     fy = v * (Float) text->image->height;
  195.     ix = fx; /* round to integer */
  196.     iy = fy;
  197.     fx = fx - (Float) ix; /* find out sub-pixel address */
  198.     fy = fy - (Float) iy;
  199.  
  200.     /* handle alpha */
  201.     if (text->image->has_alpha) {
  202.         /* Alpha channel is 0 */
  203.         rchan = 1;
  204.         gchan = 2;
  205.         bchan = 3;
  206.     } else {
  207.         rchan = 0;
  208.         gchan = 1;
  209.         bchan = 2;
  210.     }
  211.  
  212.     /* handle grey-scale */
  213.     if (text->image->chan == 1) {
  214.         gchan = rchan;
  215.         bchan = rchan;
  216.     }
  217.  
  218.     /* interpolate a sub-pixel value from the image */
  219.     ImageIndex(text->image, ix, iy, fx, fy, text->smooth, outval);
  220.  
  221.     /*
  222.      * escape when alpha is zero, 'cause there is no change
  223.      */
  224.     if (text->image->has_alpha && (outval[0] < 0.001))
  225.         return FALSE;
  226.  
  227.     imagecolor->r=outval[rchan];
  228.     imagecolor->g=outval[gchan];
  229.     imagecolor->b=outval[bchan];
  230.     return TRUE;
  231. }
  232.  
  233. void
  234. ProjectorDirection(lp, pos, dir, dist)
  235. Projectorlight *lp;
  236. Vector *pos, *dir;
  237. Float *dist;
  238. {
  239.     /*
  240.      * Calculate dir from position to center of light source.
  241.      */
  242.     VecSub(lp->pos, *pos, dir);
  243.     *dist = VecNormalize(dir);
  244. }
  245.  
  246. ProjectorMethodRegister(meth)
  247. UserMethodType meth;
  248. {
  249.     if (iProjectorMethods)
  250.         iProjectorMethods->user = meth;
  251. }
  252.