home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / rayce27s / imagemap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-02  |  9.4 KB  |  436 lines

  1. /*
  2.  * imagemap.c -- read imagemaps.
  3.  * 
  4.  * (c) 1993, 1994 by Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
  5.  * 
  6.  * This program is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation;
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <string.h>
  21. #include "ray.h"
  22. #include "proto.h"
  23. #include "extern.h"
  24.  
  25. /* save info about previously read maps */
  26. PRIVATE struct {
  27.     struct pixel_data *pic;
  28.     char           *name;
  29. }
  30.  
  31. themaps         [MAXMAPS];
  32.  
  33. PRIVATE int     nextfree = 0;
  34.  
  35.  
  36. /* read in a TGA file. */
  37. PUBLIC struct pixel_data *
  38. get_TGA_pixels(char *fn)
  39. {
  40.     FILE           *f;
  41.     int             header[18];
  42.     long            l,
  43.                     imsiz;
  44.     int             r,
  45.                     g,
  46.                     b,
  47.                     i;
  48.     struct pixel_data *p;
  49.     char           *buf;
  50.     byte           *cp;
  51.  
  52.     for (i = 0; i < nextfree; i++) {
  53.     if (!strcmp(themaps[i].name, fn))
  54.         return themaps[i].pic;
  55.     }
  56.  
  57.     /* open file, buffer it */
  58.     f = fopen(fn, "rb");
  59.     if (f == NULL)
  60.     errormsg("can't open %s", fn);
  61.  
  62.     printf("(%s", fn);
  63.     buf = (char *) malloc(BUFFERSIZE * sizeof(char));
  64.  
  65.     CHECK_MEM(buf, "buffer");
  66.  
  67.  
  68.     p = ALLOC(struct pixel_data);
  69.  
  70.     CHECK_MEM(p, "pixel data");
  71.  
  72.     if (nextfree < MAXMAPS) {
  73.  
  74.     themaps[nextfree].name = malloc(strlen(fn) + 1);
  75.     CHECK_MEM(themaps[nextfree].name, "file name");
  76.     strcpy(themaps[nextfree].name, fn);
  77.     themaps[nextfree].pic = p;
  78.     nextfree++;
  79.     }
  80.     /* read TGA header */
  81.     for (i = 0; i < 18; i++)
  82.     header[i] = getc(f);
  83.  
  84.     /* check file id */
  85.     if (header[2] != 0x02 || header[16] != 24 || header[17] != 32)
  86.     errormsg("Not a valid TGA!");
  87.  
  88.     /* calc resolution */
  89.     p->imagex = header[12] + header[13] * 256;
  90.     p->imagey = header[14] + header[15] * 256;
  91.  
  92.     p->palsize = 0;
  93.     p->pal = NULL;
  94.     imsiz = p->imagex * p->imagey;
  95.  
  96.     cp = p->data = (char *) malloc(sizeof(byte) * imsiz * 3);
  97.  
  98.     CHECK_MEM(cp, "pixel data");
  99.     if (setvbuf(f, buf, _IOFBF, BUFFERSIZE))
  100.     errormsg("cannot buffer TGA input");
  101.  
  102.  
  103.     for (l = 0; l < imsiz; l++) {
  104.     b = getc(f);
  105.     g = getc(f);
  106.     r = getc(f);
  107.     *cp++ = (byte) r;
  108.     *cp++ = (byte) g;
  109.     *cp++ = (byte) b;
  110.     }
  111.  
  112.     fclose(f);
  113.     free((void *) buf);
  114.     printf(")");
  115.  
  116.     return p;
  117. }
  118.  
  119.  
  120. /* read in a GIF file. */
  121. PUBLIC struct pixel_data *
  122. get_GIF_pixels(char *fn)
  123. {
  124.     int             i;
  125.     FILE           *f;
  126.     struct pixel_data *p;
  127.  
  128.     for (i = 0; i < nextfree; i++) {
  129.     if (!strcmp(themaps[i].name, fn))
  130.         return themaps[i].pic;
  131.     }
  132.  
  133.     p = ALLOC(struct pixel_data);
  134.     CHECK_MEM(p, "pixel data");
  135.  
  136.     if (nextfree < MAXMAPS) {
  137.     themaps[nextfree].name = malloc(strlen(fn) + 1);
  138.     CHECK_MEM(themaps[nextfree].name, "file name");
  139.     strcpy(themaps[nextfree].name, fn);
  140.     themaps[nextfree].pic = p;
  141.     nextfree++;
  142.     }
  143.     f = fopen(fn, "rb");
  144.     if (f == NULL)
  145.     errormsg("can't open %s", fn);
  146.     printf("(%s", fn);
  147.  
  148.  
  149.     load_gif(p, f);
  150.  
  151.     printf(")");
  152.     return p;
  153. }
  154.  
  155. /***************************************************************************
  156.  * INVERSE MAPS                                   *
  157.  ***************************************************************************/
  158.  
  159.  
  160. /*
  161.  * give inverse mapping for point, on sphere centered in 0,0,0
  162.  * 
  163.  * z = cos(v * pi), x = cos (u*2pi), y = sin(u*2pi).
  164.  */
  165. PUBLIC void
  166. inverse_spheremap(double *u, double *v, vector x)
  167. {
  168.     norm(x, x);
  169.     *u = acos(x.z) / M_PI;
  170.     *v = safe_arctangent(x.y, x.x) / (2 * M_PI) + 0.5;
  171. }
  172.  
  173. /*
  174.  * maps x onto plane.
  175.  */
  176. PUBLIC void
  177. inverse_planemap(double *u, double *v, vector x)
  178. {
  179.     *u = x.x;
  180.     *v = x.y;
  181. }
  182.  
  183. /*
  184.  * maps x onto torus in XZ plane, major radius 1.0
  185.  */
  186. PUBLIC void
  187. inverse_torusmap(double *u, double *v, vector x)
  188. {
  189.     double          horiz;
  190.  
  191.     *u = safe_arctangent(x.y, x.x) / (2 * M_PI) + 0.5;
  192.     horiz = 1.0 - sqrt(sqr(x.x) + sqr(x.y));
  193.     *v = safe_arctangent(x.y, horiz) / (2 * M_PI) + 0.5;
  194. }
  195.  
  196. /*
  197.  * maps x onto a cylinder with axis along the Z-axis.
  198.  */
  199. PUBLIC void
  200. inverse_cylindermap(double *u, double *v, vector x)
  201. {
  202.     *u = safe_arctangent(x.y, x.x) / (2 * M_PI) + 0.5;
  203.     *v = x.z;
  204. }
  205.  
  206. /*
  207.  * OTHER STUFF
  208.  */
  209.  
  210. /* alloc and init an imagemap */
  211. PUBLIC struct image_map *
  212. get_new_image_map(void)
  213. {
  214.     struct image_map *p;
  215.  
  216.     p = ALLOC(struct image_map);
  217.  
  218.     CHECK_MEM(p, "image map");
  219.     p->inv_map = inverse_planemap;
  220.     p->pic = NULL;
  221.     p->u_range = p->v_range = 1.0;
  222.     p->u_offs = p->v_offs = 0.0;
  223.     p->uvswap = p->once = p->interpolated = FALSE;
  224.     p->usenormal = FALSE;
  225.  
  226.     return p;
  227. }
  228.  
  229. /* kill imagemap. Don't throw away pixels. */
  230. PUBLIC void
  231. free_image_map(struct image_map *p)
  232. {
  233.     free((void *) p);
  234. }
  235.  
  236. PRIVATE color   interpolate_pic(struct pixel_data *pic, double u, double v);
  237. PRIVATE void    color_in_pixmap(byte *r, byte *g, byte *b, struct pixel_data *pic, int x, int y);
  238.  
  239.  
  240. /* lookup the color in an image map. */
  241. PUBLIC color
  242. get_image_map_color(struct image_map *p, struct intersect i)
  243. {
  244.     double          u,
  245.                     v,
  246.                     w;
  247.     byte            r,
  248.                     g,
  249.                     b;
  250.     struct pixel_data *pic;
  251.     color           c;
  252.     int             x_pix,
  253.                     y_pix;
  254.  
  255.  
  256.  
  257.     /* find the u and v for the desired point */
  258.     p->inv_map(&u, &v, i.x);
  259.  
  260.     /* swap them? */
  261.     if (p->uvswap) {
  262.     w = u;
  263.     u = v;
  264.     v = w;
  265.     }
  266.     /* transformations */
  267.     u *= p->u_range;
  268.     v *= p->v_range;
  269.     u -= p->u_offs;
  270.     v -= p->v_offs;
  271.  
  272.     if (p->once && (u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0)) {
  273.     setcolor(c, 0, 0, 0);
  274.     return c;
  275.     }
  276.     /* truncate, only the fractional part remains */
  277.     u -= ceil(u);
  278.     if (u < 0)
  279.     u += 1.0;
  280.  
  281.     v -= ceil(v);
  282.     if (v < 0)
  283.     v += 1.0;
  284.  
  285.     v = 1.0 - v;        /* 0,0 is left upper with pictures. */
  286.  
  287.     pic = p->pic;
  288.     if (p->interpolated) {
  289.     c = interpolate_pic(pic, u, v);
  290.     } else {
  291.     x_pix = (u) * pic->imagex;
  292.     y_pix = (v) * pic->imagey;
  293.  
  294.     color_in_pixmap(&r, &g, &b, pic, x_pix, y_pix);
  295.     c.r = r / 255.0;
  296.     c.g = g / 255.0;
  297.     c.b = b / 255.0;
  298.     }
  299.  
  300.     return c;
  301. }
  302.  
  303.  
  304. /*
  305.  * Bilinear interpolation (thanks to Advanced Animation and Rendering
  306.  * Techniques by Watt & Watt)
  307.  */
  308. PRIVATE color
  309. interpolate_pic(struct pixel_data *pic, double u, double v)
  310. {
  311.     color           up,
  312.                     down,
  313.                     leftup,
  314.                     leftdown,
  315.                     rightup,
  316.                     rightdown,
  317.                     final;
  318.     int             right_coord,
  319.                     up_coord;
  320.     byte            r,
  321.                     g,
  322.                     b;
  323.     double          pixu,
  324.                     pixv;
  325.  
  326.     assert(u > 0.0 && v > 0.0 && v < 1.0 && u < 1.0);
  327.  
  328.     /* relative position to pixels */
  329.     pixu = u * (double) pic->imagex;
  330.     pixv = v * (double) pic->imagey;
  331.  
  332.  
  333.     right_coord = ceil(pixu);
  334.     if (right_coord >= pic->imagex)
  335.     right_coord = 0;
  336.  
  337.     up_coord = ceil(pixv);
  338.     if (up_coord >= pic->imagey)
  339.     up_coord = 0;
  340.  
  341.     /* find colors in the corners */
  342.     color_in_pixmap(&r, &g, &b, pic, floor(pixu), up_coord);
  343.     leftup.r = r / 255.0;
  344.     leftup.g = g / 255.0;
  345.     leftup.b = b / 255.0;
  346.  
  347.     color_in_pixmap(&r, &g, &b, pic, floor(pixu), floor(pixv));
  348.     leftdown.r = r / 255.0;
  349.     leftdown.g = g / 255.0;
  350.     leftdown.b = b / 255.0;
  351.  
  352.     color_in_pixmap(&r, &g, &b, pic, right_coord, up_coord);
  353.     rightup.r = r / 255.0;
  354.     rightup.g = g / 255.0;
  355.     rightup.b = b / 255.0;
  356.  
  357.     color_in_pixmap(&r, &g, &b, pic, right_coord, floor(pixv));
  358.     rightdown.r = r / 255.0;
  359.     rightdown.g = g / 255.0;
  360.     rightdown.b = b / 255.0;
  361.  
  362.     /* don't walk off the picture */
  363.     pixu = pixu - ceil(pixu);
  364.     if (pixu < 0.0)
  365.     pixu += 1.0;
  366.  
  367.     pixv = pixv - ceil(pixv);
  368.     if (pixv < 0.0)
  369.     pixv += 1.0;
  370.  
  371.     /* find colors above and below of (u,v) */
  372.     up = color_add(scolorproduct(1.0 - pixu, leftup),
  373.            scolorproduct(pixu, rightup));
  374.     down = color_add(scolorproduct(1.0 - pixu, leftdown),
  375.              scolorproduct(pixu, rightdown));
  376.  
  377.     /* and linearly interpolate them */
  378.     final = color_add(scolorproduct(1.0 - pixv, down),
  379.               scolorproduct(pixv, up));
  380.  
  381.     return final;
  382. }
  383.  
  384. /* get a 24 bit color at (x,y) from a pixel data. */
  385. PRIVATE void
  386. color_in_pixmap(byte *r, byte *g, byte *b, struct pixel_data *pic, int x, int y)
  387. {
  388.     byte           *bp;
  389.     int             offset;
  390.  
  391.     offset = (x + y * pic->imagex) % (pic->imagex * pic->imagey);
  392.  
  393.     if (!pic->palsize) {
  394.     /* no palette, rgb raw data */
  395.     bp = pic->data + 3 * offset;
  396.     } else {
  397.     /* 256 color palette, */
  398.     int             palent;
  399.  
  400.     palent = *((byte *) (pic->data) + offset);
  401.     bp = pic->pal + 3 * palent;
  402.     }
  403.  
  404.     *r = *bp++;
  405.     *g = *bp++;
  406.     *b = *bp++;
  407.  
  408. }
  409.  
  410.  
  411. /* standard method. */
  412. PUBLIC void
  413. copy_image_map(struct image_map *dst, struct image_map *src)
  414. {
  415.     assert(dst != NULL && src != NULL);
  416.  
  417.     /*
  418.      * the raw pixel data itself is stored only once, so there is no need
  419.      * to copy the pixeldata
  420.      */
  421.     *dst = *src;
  422. }
  423.  
  424. /*
  425.  * yepp. another one (Vanessa: "Zie boven... " (chuckle) (never mind) (you
  426.  * won't understand))
  427.  */
  428. PUBLIC void
  429. print_image_map(struct image_map *p)
  430. {
  431.     printf("RES %d x %d\n", p->pic->imagex, p->pic->imagey);
  432.     printf("palsize %d", p->pic->palsize);
  433. }
  434.  
  435. /* eof */
  436.