home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Peter's Final Project / src / texture.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  8.4 KB  |  322 lines  |  [TEXT/KAHL]

  1. /*
  2.  *  Peter's Final Project -- A texture mapping demonstration
  3.  *  © 1995, Peter Mattis
  4.  *
  5.  *  E-mail:
  6.  *  petm@soda.csua.berkeley.edu
  7.  *
  8.  *  Snail-mail:
  9.  *   Peter Mattis
  10.  *   557 Fort Laramie Dr.
  11.  *   Sunnyvale, CA 94087
  12.  *
  13.  *  Avaible from:
  14.  *  http://www.csua.berkeley.edu/~petm/final.html
  15.  *
  16.  *  This program is free software; you can redistribute it and/or modify
  17.  *  it under the terms of the GNU General Public License as published by
  18.  *  the Free Software Foundation; either version 2 of the License, or
  19.  *  (at your option) any later version.
  20.  *
  21.  *  This program is distributed in the hope that it will be useful,
  22.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  *  GNU General Public License for more details.
  25.  *
  26.  *  You should have received a copy of the GNU General Public License
  27.  *  along with this program; if not, write to the Free Software
  28.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  *
  30.  *
  31.  *  Parts of this module are code excerpted from the Independent JPEG
  32.  *  Group's software. Specifically the function "texture_read" is a nearly
  33.  *  verbatim copy of the function "read_JPEG_file" located in the file
  34.  *  "example.c" in the March 15, 1995 release of the libjpeg library.
  35.  */
  36.  
  37. #include <assert.h>
  38. #include <math.h>
  39. #include <stdio.h>
  40. #include <jpeglib.h>
  41.  
  42. #include "sys.stuff.h"
  43. #include "texture.h"
  44. #include "utils.h"
  45.  
  46. /*
  47.  * Declare the functions private to this module.
  48.  */
  49.  
  50. static void texture_put_scanline (TEXTURE, JSAMPROW, long);
  51.  
  52. /*
  53.  * Make a camera object and initialize its values to something decent.
  54.  */
  55.  
  56. TEXTURE
  57. make_texture ()
  58. {
  59.     TEXTURE texture;
  60.  
  61.     texture = (TEXTURE) ALLOC (sizeof (_TEXTURE));
  62.     assert (texture != NULL);
  63.  
  64.     set_texture_address (texture, NULL);
  65.     set_texture_size (texture, 0);
  66.     set_texture_size_log2 (texture, 0);
  67.  
  68.     return texture;
  69. }
  70.  
  71. /*
  72.  * Free a texture.
  73.  */
  74.  
  75. void
  76. free_texture (t)
  77.     TEXTURE t;
  78. {
  79.     if (t)
  80.         FREE (texture_address (t));
  81.     FREE (t);
  82. }
  83.  
  84. /*
  85.  * Initialize the texture to a checker board pattern.
  86.  * (Used mainly for debugging since it show texture
  87.  *  mapping problems very nicely.)
  88.  */
  89.  
  90. void
  91. texture_checker (t, size)
  92.     TEXTURE t;
  93.     short size;
  94. {
  95.     short i, j;
  96.     long pixel_size;
  97.     long c1, c2;
  98.  
  99.     assert (t != NULL);
  100.  
  101.     pixel_size = get_frame_buffer_pixel ();
  102.  
  103.     switch (get_frame_buffer_depth ())
  104.     {
  105.     case 8:
  106.         c1 = 100;
  107.         c2 = 200;
  108.         break;
  109.     case 24:
  110.         c1 = 0x00FF0000;
  111.         c2 = 0x000000FF;
  112.         break;
  113.     }
  114.  
  115.     set_texture_size (t, size);
  116.     set_texture_size_log2 (t, (short) ((float) (log (texture_size (t))) /log (2)));
  117.     set_texture_bytes_per_texel (t, pixel_size);
  118.     set_texture_address (t, ALLOC (pixel_size * texture_size (t) * texture_size (t)));
  119.     assert (texture_address (t) != NULL);
  120.  
  121.     for (i = 0; i < texture_size (t); i++)
  122.         for (j = 0; j < texture_size (t); j++)
  123.             switch (pixel_size)
  124.             {
  125.             case 1:
  126.                 set_texel8 (t, i, j, ((i + j) % 2) ? c1 : c2);
  127.                 break;
  128.             case 2:
  129.                 set_texel16 (t, i, j, ((i + j) % 2) ? c1 : c2);
  130.                 break;
  131.             case 4:
  132.                 set_texel32 (t, i, j, ((i + j) % 2) ? c1 : c2);
  133.                 break;
  134.             }
  135. }
  136.  
  137. /*
  138.  * Initialize a texture from a jpeg file.
  139.  *
  140.  * The following routine was taken (almost) entirely from the
  141.  *  "example.c" file distributed with the "libjpeg" library. That is
  142.  *  to say, the following code is excerpted from the Independent
  143.  *  JPEG Group's software.
  144.  *
  145.  * Thank you Independent JPEG Group for writing an amazingly easy
  146.  *  to use and portable library for reading and writing JPEG files.
  147.  */
  148.  
  149. void
  150. texture_read (t, file_name)
  151.     TEXTURE t;
  152.     char *file_name;
  153. {
  154.     /* This struct contains the JPEG decompression parameters and pointers to
  155.      * working space (which is allocated as needed by the JPEG library).
  156.      */
  157.     struct jpeg_decompress_struct cinfo;
  158.     /* We use our private extension JPEG error handler. */
  159.     struct jpeg_error_mgr jerr;
  160.     /* More stuff */
  161.     FILE *infile; /* source file */
  162.     JSAMPARRAY buffer; /* Output row buffer */
  163.     int row_stride; /* physical row width in output buffer */
  164.     long pixel_size;
  165.  
  166.     /* In this example we want to open the input file before doing anything else,
  167.      * so that the setjmp() error recovery below can assume the file is open.
  168.      * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  169.      * requires it in order to read binary files.
  170.      */
  171.  
  172.     if ((infile = fopen (file_name, "rb")) == NULL)
  173.     {
  174.         fprintf (stderr, "can't open %s\n", file_name);
  175.         exit (0);
  176.     }
  177.  
  178.     /* Step 1: allocate and initialize JPEG decompression object */
  179.  
  180.     /* We set up the normal JPEG error routines. */
  181.     cinfo.err = jpeg_std_error (&jerr);
  182.  
  183.     /* Now we can initialize the JPEG decompression object. */
  184.     jpeg_create_decompress (&cinfo);
  185.  
  186.     /* Step 2: specify data source (eg, a file) */
  187.  
  188.     jpeg_stdio_src (&cinfo, infile);
  189.  
  190.     /* Step 3: read file parameters with jpeg_read_header() */
  191.  
  192.     (void) jpeg_read_header (&cinfo, TRUE);
  193.     /* We can ignore the return value from jpeg_read_header since
  194.      *   (a) suspension is not possible with the stdio data source, and
  195.      *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
  196.      * See libjpeg.doc for more info.
  197.      */
  198.  
  199.     /* Step 4: set parameters for decompression */
  200.  
  201.     /* In this example, we don't need to change any of the defaults set by
  202.      * jpeg_read_header(), so we do nothing here.
  203.      */
  204.  
  205.     /* Step 5: Start decompressor */
  206.  
  207.     jpeg_start_decompress (&cinfo);
  208.  
  209.     /* We may need to do some setup of our own at this point before reading
  210.      * the data.  After jpeg_start_decompress() we have the correct scaled
  211.      * output image dimensions available, as well as the output colormap
  212.      * if we asked for color quantization.
  213.      * In this example, we need to make an output work buffer of the right size.
  214.      */
  215.     /* JSAMPLEs per row in output buffer */
  216.     row_stride = cinfo.output_width * cinfo.output_components;
  217.     /* Make a one-row-high sample array that will go away when done with image */
  218.     buffer = (*cinfo.mem->alloc_sarray)
  219.         ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
  220.  
  221.     assert (cinfo.output_width == cinfo.output_height);
  222.  
  223.     pixel_size = get_frame_buffer_pixel ();
  224.     set_texture_size (t, cinfo.output_width);
  225.     set_texture_size_log2 (t, (short) ((float) (log (texture_size (t))) /log (2)));
  226.     set_texture_bytes_per_texel (t, pixel_size);
  227.     set_texture_address (t, ALLOC (pixel_size * texture_size (t) * texture_size (t)));
  228.     assert (texture_address (t) != NULL);
  229.  
  230.     /* Step 6: while (scan lines remain to be read) */
  231.     /*           jpeg_read_scanlines(...); */
  232.  
  233.     /* Here we use the library's state variable cinfo.output_scanline as the
  234.      * loop counter, so that we don't have to keep track ourselves.
  235.      */
  236.     while (cinfo.output_scanline < cinfo.output_height)
  237.     {
  238.         (void) jpeg_read_scanlines (&cinfo, buffer, 1);
  239.         texture_put_scanline (t, buffer[0], cinfo.output_scanline);
  240.     }
  241.  
  242.     /* Step 7: Finish decompression */
  243.  
  244.     (void) jpeg_finish_decompress (&cinfo);
  245.     /* We can ignore the return value since suspension is not possible
  246.      * with the stdio data source.
  247.      */
  248.  
  249.     /* Step 8: Release JPEG decompression object */
  250.  
  251.     /* This is an important step since it will release a good deal of memory. */
  252.     jpeg_destroy_decompress (&cinfo);
  253.  
  254.     /* After finish_decompress, we can close the input file.
  255.      * Here we postpone it until after no more JPEG errors are possible,
  256.      * so as to simplify the setjmp error logic above.  (Actually, I don't
  257.      * think that jpeg_destroy can do an error exit, but why assume anything...)
  258.      */
  259.     fclose (infile);
  260.  
  261.     /* At this point you may want to check to see whether any corrupt-data
  262.      * warnings occurred (test whether jerr.num_warnings is nonzero).
  263.      */
  264.  
  265.     /* And we're done! */
  266. }
  267.  
  268. /*
  269.  * Take a scanline of texture read by the library
  270.  *  and place it in the texture. Appropriate conversion
  271.  *  to a new depth takes place at this point.
  272.  * Note: Textures are assumed to be 24-bit jpegs. Grayscale
  273.  *       jpegs which have only 8-bits per pixel will probably
  274.  *       crash and burn.
  275.  */
  276.  
  277. static void
  278. texture_put_scanline (t, buf, row)
  279.     TEXTURE t;
  280.     JSAMPROW buf;
  281.     long row;
  282. {
  283.     long i;
  284.     long pix;
  285.  
  286.     row--;
  287.     switch (texture_bytes_per_texel (t))
  288.     {
  289.     case 1:
  290.         /*
  291.          * We're in 8bit mode, so take the average
  292.          *  of the red, green, and blue bytes as the
  293.          *  grayscale byte.
  294.          */
  295.         
  296.         for (i = 0; i < texture_size (t); i++)
  297.         {
  298.             pix = *buf++;
  299.             pix += *buf++;
  300.             pix += *buf++;
  301.             pix /= 3;
  302.             set_texel8 (t, i, row, (PIXEL8) pix);
  303.         }
  304.         break;
  305.     case 4:
  306.         /*
  307.          * We're in 24bit mode, so just plop the pixels
  308.          *  right in the texture. (A little bit shifting
  309.          *  is needed).
  310.          */
  311.         
  312.         for (i = 0; i < texture_size (t); i++)
  313.         {
  314.             pix = *buf++ << 16;
  315.             pix += *buf++ << 8;
  316.             pix += *buf++;
  317.             set_texel32 (t, i, row, pix);
  318.         }
  319.         break;
  320.     }
  321. }
  322.