home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / raytrace / rayshade / src / imagetex.c < prev    next >
C/C++ Source or Header  |  1992-04-28  |  6KB  |  236 lines

  1. /*
  2.  * imagetext.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.  * $Id: imagetext.c,v 4.0 91/07/17 14:42:42 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    imagetext.c,v $
  19.  * Revision 4.0  91/07/17  14:42:42  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "texture.h"
  24. #include "image.h"
  25. #include "imagetext.h"
  26.  
  27. #define INTERP(v)    (text->lo + (v)*(text->hi - text->lo))
  28.  
  29. /*
  30.  * Create Image texture.
  31.  * Image texture has so many options that there's usually no
  32.  * nice way to parse without resorting to additional keywords.
  33.  * Thus the ImageTextCreate routine only reads the image to be used;
  34.  * all but ->component must be set by hand.  The routine
  35.  * ImageTextSetComponent is provided to set the component and
  36.  * ensure that the image being used is appropriate. 
  37.  */
  38. ImageText *
  39. ImageTextCreate(imagefile)
  40. char *imagefile;
  41. {
  42.     ImageText *text;
  43.  
  44.     text = (ImageText *)Calloc(1, sizeof(ImageText));
  45.     text->component = COLOR; /* texture all colors by default*/
  46.     /*
  47.      * Only apply one copy of the texture by default
  48.      */
  49.     text->tileu = text->tilev = 0;
  50.     text->lo = 0.; text->hi = 1.;
  51.     text->smooth = FALSE;
  52.     text->mapping = UVMappingCreate();
  53.     text->image = ImageRead(imagefile);
  54.     return text;
  55. }
  56.  
  57. /*
  58.  * Set image texture to apply to given component,
  59.  * ensuring that the image that is being used is compatible.
  60.  */
  61. void
  62. ImageTextSetComponent(text, component)
  63. ImageText *text;
  64. int component;
  65. {
  66.     switch (component) {
  67.     case COLOR: /* usual case, texture on amb, diff, spec, body */
  68.     case AMBIENT:
  69.     case DIFFUSE:
  70.     case SPECULAR:
  71.     case BODY:
  72.         /* all of the above can use 1 or 3 channel images */
  73.         if (text->image->chan != 1 && text->image->chan != 3) {
  74.             RLerror(RL_ABORT,
  75.                 "Image %s must have 1 or 3 channels\n", 
  76.                 text->image->filename);
  77.         }
  78.         break;
  79.     case REFLECT:
  80.     case TRANSP:
  81.     case SPECPOW:
  82.     case BUMP:
  83.     case INDEX:
  84.         /* the above need 1 channel images */
  85.         if (text->image->chan != 1) {
  86.             RLerror(RL_ABORT, "Image %s must have 1 channel\n",
  87.                 text->image->filename);
  88.         }
  89.         break;
  90.     }
  91.     text->component = component;
  92. }
  93.  
  94. void
  95. ImageTextApply(text, prim, ray, pos, norm, gnorm, surf)
  96. ImageText *text;
  97. Geom *prim;
  98. Ray *ray;
  99. Vector *pos, *norm, *gnorm;
  100. Surface *surf;
  101. {
  102.     Float fx, fy;
  103.     Float outval[4], outval_u[4], outval_v[4];
  104.     Float u, v;
  105.     Surface tmpsurf;
  106.     int ix, iy;
  107.     int rchan, gchan, bchan;
  108.     Vector dpdu, dpdv, ntmp;
  109.  
  110.     /*
  111.      * First, find the floating point location in image coords.
  112.      * Then set ix, iy to the integer location in image coords and
  113.      * use fx, fy to represent the subpixel position.
  114.      */
  115.     if (text->component == BUMP)
  116.         TextToUV(text->mapping, prim, pos, gnorm, &u, &v,
  117.              &dpdu, &dpdv);
  118.     else
  119.         TextToUV(text->mapping, prim, pos, gnorm, &u, &v, 
  120.              (Vector *)NULL, (Vector *)NULL);
  121.     /*
  122.      * Handle tiling at this point.
  123.      */
  124.     if (TileValue(text->tileu, text->tilev, u, v))
  125.         return;
  126.     u -= floor(u);
  127.     v -= floor(v);
  128.     fx = u * (Float) text->image->width;
  129.     fy = v * (Float) text->image->height;
  130.     ix = fx;
  131.     iy = fy;
  132.     fx = fx - (Float) ix;
  133.     fy = fy - (Float) iy;
  134.  
  135.     if (text->image->has_alpha) {
  136.         /* Alpha channel is 0 */
  137.         rchan = 1;
  138.         gchan = 2;
  139.         bchan = 3;
  140.     } else {
  141.         rchan = 0;
  142.         gchan = 1;
  143.         bchan = 2;
  144.     }
  145.  
  146.     if (text->image->chan == 1) {
  147.         gchan = rchan;
  148.         bchan = rchan;
  149.     }
  150.  
  151.     ImageIndex(text->image, ix, iy, fx, fy, text->smooth, outval);
  152.  
  153.     /*
  154.      * escape when alpha is zero, 'cause there is no change
  155.      */
  156.     if (text->image->has_alpha && (outval[0] < 0.001))
  157.         return;
  158.  
  159.     if (text->component != COLOR || text->surf == (Surface *)NULL) {
  160.         tmpsurf = *surf;
  161.     } else {
  162.         tmpsurf = *text->surf;
  163.     }
  164.  
  165.     switch (text->component) {
  166.         case COLOR: /* amb, diff, spec */
  167.             tmpsurf.spec.r *= outval[rchan];
  168.             tmpsurf.spec.g *= outval[gchan];
  169.             tmpsurf.spec.b *= outval[bchan];
  170.             tmpsurf.diff.r *= outval[rchan];
  171.             tmpsurf.diff.g *= outval[gchan];
  172.             tmpsurf.diff.b *= outval[bchan];
  173.             tmpsurf.amb.r *= outval[rchan];
  174.             tmpsurf.amb.g *= outval[gchan];
  175.             tmpsurf.amb.b *= outval[bchan];
  176.             break;
  177.          case AMBIENT: /* ambient */
  178.             tmpsurf.amb.r *= INTERP(outval[rchan]);
  179.             tmpsurf.amb.g *= INTERP(outval[gchan]);
  180.             tmpsurf.amb.b *= INTERP(outval[bchan]);
  181.             break;
  182.         case DIFFUSE: /* diffuse */
  183.             tmpsurf.diff.r *= INTERP(outval[rchan]);
  184.             tmpsurf.diff.g *= INTERP(outval[gchan]);
  185.             tmpsurf.diff.b *= INTERP(outval[bchan]);
  186.             break;
  187.         case SPECULAR: /* specular */
  188.             tmpsurf.spec.r *= INTERP(outval[rchan]);
  189.             tmpsurf.spec.g *= INTERP(outval[gchan]);
  190.             tmpsurf.spec.b *= INTERP(outval[bchan]);
  191.             break;
  192.         case BODY: /* transmitted */
  193.             tmpsurf.body.r *= INTERP(outval[rchan]);
  194.             tmpsurf.body.g *= INTERP(outval[gchan]);
  195.             tmpsurf.body.b *= INTERP(outval[bchan]);
  196.             break;
  197.         case REFLECT: /* specular reflectivity */
  198.             tmpsurf.reflect *= INTERP(outval[rchan]);
  199.             break;
  200.         case TRANSP: /* specular transmittance */
  201.             tmpsurf.transp *= INTERP(outval[rchan]);
  202.             break;
  203.         case SPECPOW: /* specpow */
  204.             tmpsurf.srexp *= INTERP(outval[rchan]);
  205.             break;
  206.         case INDEX: /* index of refraction */
  207.             tmpsurf.index *= INTERP(outval[rchan]);
  208.             break;
  209.         case BUMP: /* bump map */
  210.             ImageIndex(text->image, 
  211.                     (ix == text->image->width - 1) ? 0 : ix+1,
  212.                     iy, fx, fy,
  213.                     text->smooth, outval_u);
  214.             ImageIndex(text->image, ix, 
  215.                     (iy == text->image->height - 1) ? 0 : iy+1,
  216.                     fx, fy,
  217.                     text->smooth, outval_v);
  218.             MakeBump(norm, &dpdu, &dpdv, 
  219.                  INTERP(outval_u[rchan] - outval[rchan]),
  220.                  INTERP(outval_v[rchan] - outval[rchan]));
  221.             return;
  222.     }
  223.  
  224.     if (text->image->has_alpha && (outval[0] < 0.999)) {
  225.         /*
  226.          * image partial coverage means blend surf and text->surf
  227.          */
  228.         SurfaceBlend(surf, &tmpsurf, 1. - outval[0], outval[0]);
  229.     } else {
  230.         /*
  231.          * image full coverage means use text->surf
  232.          */
  233.         *surf = tmpsurf;
  234.     }
  235. }
  236.