home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / graphics / povsrc20 / texture.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  21KB  |  812 lines

  1. /****************************************************************************
  2. *                texture.c
  3. *
  4. *  This module implements texturing functions such as noise, turbulence and
  5. *  texture transformation functions. The actual texture routines are in the
  6. *  files pigment.c & normal.c.
  7. *  The noise function used here is the one described by Ken Perlin in
  8. *  "Hypertexture", SIGGRAPH '89 Conference Proceedings page 253.
  9. *
  10. *  from Persistence of Vision Raytracer
  11. *  Copyright 1993 Persistence of Vision Team
  12. *---------------------------------------------------------------------------
  13. *  NOTICE: This source code file is provided so that users may experiment
  14. *  with enhancements to POV-Ray and to port the software to platforms other 
  15. *  than those supported by the POV-Ray Team.  There are strict rules under
  16. *  which you are permitted to use this file.  The rules are in the file
  17. *  named POVLEGAL.DOC which should be distributed with this file. If 
  18. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  19. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  20. *  Forum.  The latest version of POV-Ray may be found there as well.
  21. *
  22. * This program is based on the popular DKB raytracer version 2.12.
  23. * DKBTrace was originally written by David K. Buck.
  24. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  25. *
  26. *****************************************************************************/
  27.  
  28. /*
  29.    Some texture ideas garnered from SIGGRAPH '85 Volume 19 Number 3, 
  30.    "An Image Synthesizer" By Ken Perlin.
  31.    Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley)
  32. */
  33.  
  34. #include "frame.h"
  35. #include "vector.h"
  36. #include "povproto.h"
  37. #include "texture.h"
  38.  
  39. DBL *sintab;
  40. DBL frequency[NUMBER_OF_WAVES];
  41. VECTOR Wave_Sources[NUMBER_OF_WAVES];
  42. DBL *RTable;
  43. short *hashTable;
  44.  
  45. unsigned short crctab[256] =
  46.   {
  47.   0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  48.   0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  49.   0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  50.   0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  51.   0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  52.   0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  53.   0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  54.   0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  55.   0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  56.   0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  57.   0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  58.   0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  59.   0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  60.   0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  61.   0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  62.   0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  63.   0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  64.   0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  65.   0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  66.   0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  67.   0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  68.   0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  69.   0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  70.   0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  71.   0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  72.   0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  73.   0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  74.   0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  75.   0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  76.   0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  77.   0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  78.   0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  79.   };
  80.  
  81. void Compute_Colour (Colour, Pigment, value)
  82. COLOUR *Colour;
  83. PIGMENT *Pigment;
  84. DBL value;
  85.   {
  86.   COLOUR_MAP *Colour_Map = Pigment->Colour_Map;
  87.   int max_colors = Colour_Map->Number_Of_Entries-1;
  88.   COLOUR_MAP_ENTRY *Cur, *Prev;
  89.   register DBL fraction;
  90.  
  91.   value = fmod(value * Pigment->Frequency + Pigment->Phase,1.00001);
  92.   if (value < 0.0)         /* allow negative Frequency */
  93.     value -=floor(value);
  94.  
  95.   /* if greater than last, use last. */
  96.   if (value >= Colour_Map->Colour_Map_Entries[max_colors].value)
  97.     {
  98.     *Colour = Colour_Map->Colour_Map_Entries[max_colors].Colour;
  99.     return;
  100.     }
  101.  
  102.   Prev = Cur = &(Colour_Map->Colour_Map_Entries[0]);
  103.   while (value >= Cur->value)
  104.     Prev = Cur++;
  105.  
  106.   /* if stopped on first entry, use first. */
  107.   if (Prev == Cur)
  108.     {
  109.     *Colour = Cur->Colour;
  110.     return;
  111.     }
  112.  
  113.   fraction = (value - Prev->value) / (Cur->value - Prev->value);
  114.   Colour->Red   = Prev->Colour.Red   + fraction * (Cur->Colour.Red   - Prev->Colour.Red);
  115.   Colour->Green = Prev->Colour.Green + fraction * (Cur->Colour.Green - Prev->Colour.Green);
  116.   Colour->Blue  = Prev->Colour.Blue  + fraction * (Cur->Colour.Blue  - Prev->Colour.Blue);
  117.   Colour->Filter = Prev->Colour.Filter + fraction * (Cur->Colour.Filter - Prev->Colour.Filter);
  118.  
  119.   return;
  120.   }
  121.  
  122. void Initialize_Noise ()
  123.   {
  124.   register int i = 0;
  125.   VECTOR point;
  126.  
  127.   InitRTable();
  128.  
  129.   if ((sintab = (DBL *)malloc(SINTABSIZE * sizeof(DBL))) == NULL) 
  130.     MAError ("sine table");
  131.  
  132.   for (i = 0 ; i < SINTABSIZE ; i++)
  133.     sintab[i] = sin(i/(DBL)SINTABSIZE * (3.14159265359 * 2.0));
  134.  
  135.   for (i = 0 ; i < NUMBER_OF_WAVES ; i++)
  136.     {
  137.     DNoise (&point, (DBL) i, 0.0, 0.0);
  138.     VNormalize (Wave_Sources[i], point);
  139.     frequency[i] = (rand() & RNDMASK) / RNDDIVISOR + 0.01;
  140.     }
  141.   }
  142.  
  143. void InitTextureTable()
  144.   {
  145.   int i, j, temp;
  146.  
  147.   srand(0);
  148.  
  149.   if ((hashTable = (short int *) malloc(4096*sizeof(short int))) == NULL) 
  150.     MAError ("hash table");
  151.  
  152.   for (i = 0; i < 4096; i++)
  153.     hashTable[i] = i;
  154.   for (i = 4095; i >= 0; i--) 
  155.     {
  156.     j = rand() % 4096;
  157.     temp = hashTable[i];
  158.     hashTable[i] = hashTable[j];
  159.     hashTable[j] = temp;
  160.     }
  161.   }
  162.  
  163. /* modified by AAC to work properly with little bitty integers (16 bits) */
  164.  
  165. void InitRTable()
  166.   {
  167.   int i;
  168.   VECTOR rp;
  169.  
  170.   InitTextureTable();
  171.  
  172.   if ((RTable = (DBL *)malloc(MAXSIZE * sizeof(DBL))) == NULL) 
  173.     MAError ("RTable");
  174.  
  175.   for (i = 0; i < MAXSIZE; i++)
  176.     {
  177.     rp.x = rp.y = rp.z = (DBL)i;
  178.     RTable[i] = (unsigned int) R(&rp) * REALSCALE - 1.0;
  179.     }
  180.   }
  181.  
  182. int R(v)
  183. VECTOR *v;
  184.   {
  185.   v->x *= .12345;
  186.   v->y *= .12345;
  187.   v->z *= .12345;
  188.  
  189.   return (Crc16((char *) v, sizeof(VECTOR)));
  190.   }
  191.  
  192. /*
  193.  * Note that passing a VECTOR array to Crc16 and interpreting it as
  194.  * an array of chars means that machines with different floating-point
  195.  * representation schemes will evaluate Noise(point) differently.
  196.  */
  197.  
  198. int Crc16(buf, count)
  199. register char *buf;
  200. register int  count;
  201.   {
  202.   register unsigned short crc = 0;
  203.  
  204.   while (count--)
  205.     crc = (crc >> 8) ^ crctab[ (unsigned char) (crc ^ *buf++) ];
  206.  
  207.   return ((int) crc);
  208.   }
  209.  
  210.  
  211. /*
  212.         Robert's Skinner's Perlin-style "Noise" function - modified by AAC
  213.         to ensure uniformly distributed clamped values between 0 and 1.0...
  214. */
  215.  
  216.  
  217. DBL Noise(x, y, z)
  218. DBL x, y, z;
  219.   {
  220.   DBL *mp;
  221.   long ix, iy, iz, jx, jy, jz;
  222.   int ixiy_hash, ixjy_hash, jxiy_hash, jxjy_hash;
  223.  
  224.   DBL sx, sy, sz, tx, ty, tz;
  225.   DBL sum;
  226.  
  227.   DBL x_ix, x_jx, y_iy, y_jy, z_iz, z_jz, txty, sxty, txsy, sxsy;
  228.  
  229.   Calls_To_Noise++;
  230.  
  231.   /*setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);*/
  232.   x -= MINX;
  233.   y -= MINY;
  234.   z -= MINZ;
  235.  
  236.   /* its equivalent integer lattice point. */
  237.   ix = (long)x; iy = (long)y; iz = (long)z;
  238.   jx = ix + 1; jy = iy + 1; jz = iz + 1;
  239.  
  240.   sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  241.  
  242.   /* the complement values of sx,sy,sz */
  243.   tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  244.  
  245.   /*
  246.     *  interpolate!
  247.     */
  248.   x_ix = x - ix;
  249.   x_jx = x - jx;
  250.   y_iy = y - iy;
  251.   y_jy = y - jy;
  252.   z_iz = z - iz;
  253.   z_jz = z - jz;
  254.   txty = tx * ty;
  255.   sxty = sx * ty;
  256.   txsy = tx * sy;
  257.   sxsy = sx * sy;
  258.   ixiy_hash = Hash2d ( ix, iy );
  259.   jxiy_hash = Hash2d ( jx, iy );
  260.   ixjy_hash = Hash2d ( ix, jy );
  261.   jxjy_hash = Hash2d ( jx, jy );
  262.  
  263.   mp = &RTable[(int) Hash1d(ixiy_hash, iz ) & 0xFF];
  264.   sum = INCRSUMP(mp,(txty*tz), x_ix, y_iy, z_iz);
  265.  
  266.   mp = &RTable[(int) Hash1d( jxiy_hash, iz ) & 0xFF];
  267.   sum += INCRSUMP(mp,(sxty*tz), x_jx, y_iy, z_iz);
  268.  
  269.   mp = &RTable[(int) Hash1d( ixjy_hash, iz ) & 0xFF];
  270.   sum += INCRSUMP(mp,(txsy*tz), x_ix, y_jy, z_iz);
  271.  
  272.   mp = &RTable[(int) Hash1d( jxjy_hash, iz ) & 0xFF];
  273.   sum += INCRSUMP(mp,(sxsy*tz), x_jx, y_jy, z_iz);
  274.  
  275.   mp = &RTable[(int) Hash1d( ixiy_hash, jz ) & 0xFF];
  276.   sum += INCRSUMP(mp,(txty*sz), x_ix, y_iy, z_jz);
  277.  
  278.   mp = &RTable[(int) Hash1d( jxiy_hash, jz ) & 0xFF];
  279.   sum += INCRSUMP(mp,(sxty*sz), x_jx, y_iy, z_jz);
  280.  
  281.   mp = &RTable[(int) Hash1d( ixjy_hash, jz ) & 0xFF];
  282.   sum += INCRSUMP(mp,(txsy*sz), x_ix, y_jy, z_jz);
  283.  
  284.   mp = &RTable[(int) Hash1d( jxjy_hash, jz ) & 0xFF];
  285.   sum += INCRSUMP(mp,(sxsy*sz), x_jx, y_jy, z_jz);
  286.  
  287.   sum = sum + 0.5;          /* range at this point -0.5 - 0.5... */
  288.  
  289.   if (sum < 0.0)
  290.     sum = 0.0;
  291.   if (sum > 1.0)
  292.     sum = 1.0;
  293.  
  294.   return (sum);
  295.   }
  296.  
  297.  
  298. /*
  299.        Vector-valued version of "Noise"
  300. */
  301.  
  302. void DNoise(result, x, y, z)
  303. VECTOR *result;
  304. DBL x, y, z;
  305.   {
  306.   DBL *mp;
  307.   long ix, iy, iz, jx, jy, jz;
  308.   int ixiy_hash, ixjy_hash, jxiy_hash, jxjy_hash;
  309.   DBL px, py, pz, s;
  310.   DBL sx, sy, sz, tx, ty, tz;
  311.   DBL txty, sxty, txsy, sxsy;
  312.  
  313.   Calls_To_DNoise++;
  314.  
  315.   /*setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);*/
  316.   x -= MINX;
  317.   y -= MINY;
  318.   z -= MINZ;
  319.  
  320.   /* its equivalent integer lattice point. */
  321.   ix = (long)x; iy = (long)y; iz = (long)z;
  322.   jx = ix + 1; jy = iy + 1; jz = iz + 1;
  323.  
  324.   sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  325.  
  326.   /* the complement values of sx,sy,sz */
  327.   tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  328.  
  329.   /*
  330.     *  interpolate!
  331.     */
  332.   txty = tx * ty;
  333.   sxty = sx * ty;
  334.   txsy = tx * sy;
  335.   sxsy = sx * sy;
  336.   ixiy_hash = Hash2d ( ix, iy );
  337.   jxiy_hash = Hash2d ( jx, iy );
  338.   ixjy_hash = Hash2d ( ix, jy );
  339.   jxjy_hash = Hash2d ( jx, jy );
  340.  
  341.   mp = &RTable[(int) Hash1d( ixiy_hash, iz ) & 0xFF];
  342.   px = x-ix;  py = y-iy;  pz = z-iz;
  343.   s = txty*tz;
  344.   result->x = INCRSUMP(mp,s,px,py,pz);
  345.   mp += 4;
  346.   result->y = INCRSUMP(mp,s,px,py,pz);
  347.   mp += 4;
  348.   result->z = INCRSUMP(mp,s,px,py,pz);
  349.  
  350.   mp = &RTable[(int) Hash1d( jxiy_hash, iz ) & 0xFF];
  351.   px = x-jx;
  352.   s = sxty*tz;
  353.   result->x += INCRSUMP(mp,s,px,py,pz);
  354.   mp += 4;
  355.   result->y += INCRSUMP(mp,s,px,py,pz);
  356.   mp += 4;
  357.   result->z += INCRSUMP(mp,s,px,py,pz);
  358.  
  359.   mp = &RTable[(int) Hash1d( jxjy_hash, iz ) & 0xFF];
  360.   py = y-jy;
  361.   s = sxsy*tz;
  362.   result->x += INCRSUMP(mp,s,px,py,pz);
  363.   mp += 4;
  364.   result->y += INCRSUMP(mp,s,px,py,pz);
  365.   mp += 4;
  366.   result->z += INCRSUMP(mp,s,px,py,pz);
  367.  
  368.   mp = &RTable[(int) Hash1d( ixjy_hash, iz ) & 0xFF];
  369.   px = x-ix;
  370.   s = txsy*tz;
  371.   result->x += INCRSUMP(mp,s,px,py,pz);
  372.   mp += 4;
  373.   result->y += INCRSUMP(mp,s,px,py,pz);
  374.   mp += 4;
  375.   result->z += INCRSUMP(mp,s,px,py,pz);
  376.  
  377.   mp = &RTable[(int) Hash1d( ixjy_hash, jz ) & 0xFF];
  378.   pz = z-jz;
  379.   s = txsy*sz;
  380.   result->x += INCRSUMP(mp,s,px,py,pz);
  381.   mp += 4;
  382.   result->y += INCRSUMP(mp,s,px,py,pz);
  383.   mp += 4;
  384.   result->z += INCRSUMP(mp,s,px,py,pz);
  385.  
  386.   mp = &RTable[(int) Hash1d( jxjy_hash, jz ) & 0xFF];
  387.   px = x-jx;
  388.   s = sxsy*sz;
  389.   result->x += INCRSUMP(mp,s,px,py,pz);
  390.   mp += 4;
  391.   result->y += INCRSUMP(mp,s,px,py,pz);
  392.   mp += 4;
  393.   result->z += INCRSUMP(mp,s,px,py,pz);
  394.  
  395.   mp = &RTable[(int) Hash1d( jxiy_hash, jz ) & 0xFF];
  396.   py = y-iy;
  397.   s = sxty*sz;
  398.   result->x += INCRSUMP(mp,s,px,py,pz);
  399.   mp += 4;
  400.   result->y += INCRSUMP(mp,s,px,py,pz);
  401.   mp += 4;
  402.   result->z += INCRSUMP(mp,s,px,py,pz);
  403.  
  404.   mp = &RTable[(int) Hash1d( ixiy_hash, jz ) & 0xFF];
  405.   px = x-ix;
  406.   s = txty*sz;
  407.   result->x += INCRSUMP(mp,s,px,py,pz);
  408.   mp += 4;
  409.   result->y += INCRSUMP(mp,s,px,py,pz);
  410.   mp += 4;
  411.   result->z += INCRSUMP(mp,s,px,py,pz);
  412.   }
  413.  
  414. DBL Turbulence (x, y, z, omega, lambda, octaves)
  415. DBL x, y, z,omega, lambda;
  416. int octaves;
  417.   {
  418.   int i;
  419.   DBL l, o, value, tempx, tempy, tempz;
  420.  
  421.   value = Noise(x, y, z);
  422.   l = lambda;
  423.   o = omega;
  424.   for (i = 2; i <= octaves; i++)
  425.     {
  426.     tempx = l * x;
  427.     tempy = l * y;
  428.     tempz = l * z;
  429.     value += o * Noise(tempx, tempy, tempz);
  430.     if (i < octaves)
  431.       {
  432.       l *= lambda;
  433.       o *= omega;
  434.       }
  435.     }
  436.   return (value);
  437.   }
  438.  
  439. void DTurbulence (result, x, y, z, omega, lambda, octaves)
  440. VECTOR  *result;
  441. DBL x, y, z, omega, lambda;
  442. int octaves;
  443.   {
  444.   int i;
  445.   DBL l, o;
  446.   VECTOR value, temp;
  447.  
  448.   result -> x = 0.0;
  449.   result -> y = 0.0;
  450.   result -> z = 0.0;
  451.  
  452.   value.x = value.y = value.z = 0.0;
  453.  
  454.   DNoise(result, x,y,z);
  455.  
  456.   l = lambda;
  457.   o = omega;
  458.   for (i = 2; i <= octaves; i++)
  459.     {
  460.     temp.x = l * x;
  461.     temp.y = l * y;
  462.     temp.z = l * z;
  463.  
  464.     DNoise(&value, temp.x, temp.y, temp.z);
  465.     result->x += o * value.x;
  466.     result->y += o * value.y;
  467.     result->z += o * value.z;
  468.     if (i < octaves)
  469.       {
  470.       l *= lambda;
  471.       o *= omega;
  472.       }
  473.     }
  474.   }
  475.  
  476. DBL cycloidal (value)
  477. DBL value;
  478.   {
  479.   register int indx;
  480.  
  481.   if (value >= 0.0)
  482.     {
  483.     indx = (int)((value - floor (value)) * SINTABSIZE);
  484.     return (sintab [indx]);
  485.     }
  486.   else
  487.     {
  488.     indx = (int)((0.0 - (value + floor (0.0 - value))) * SINTABSIZE);
  489.     return (0.0 - sintab [indx]);
  490.     }
  491.   }
  492.  
  493. DBL Triangle_Wave (value)
  494. DBL value;
  495.   {
  496.   register DBL offset,temp1;
  497.  
  498.   if (value >= 0.0) offset = value - floor(value);
  499.   else 
  500.     {
  501.     temp1 = -1.0 - floor(fabs(value));
  502.     offset = value - temp1;
  503.     }
  504.   if (offset >= 0.5) return (2.0 * (1.0 - offset));
  505.   else return (2.0 * offset);
  506.   }
  507.  
  508.   void Translate_Textures (Textures, Vector)
  509.     TEXTURE *Textures;
  510. VECTOR *Vector;
  511.   {
  512.   TRANSFORM Trans;
  513.  
  514.   Compute_Translation_Transform (&Trans, Vector);
  515.   Transform_Textures (Textures, &Trans);
  516.   }
  517.  
  518. void Rotate_Textures (Textures, Vector)
  519. TEXTURE *Textures;
  520. VECTOR *Vector;
  521.   {
  522.   TRANSFORM Trans;
  523.  
  524.   Compute_Rotation_Transform (&Trans, Vector);
  525.   Transform_Textures (Textures, &Trans);
  526.   }
  527.  
  528. void Scale_Textures (Textures, Vector)
  529. TEXTURE *Textures;
  530. VECTOR *Vector;
  531.   {
  532.   TRANSFORM Trans;
  533.  
  534.   Compute_Scaling_Transform (&Trans, Vector);
  535.   Transform_Textures (Textures, &Trans);
  536.   }
  537.  
  538. void Transform_Textures (Textures, Trans)
  539. TEXTURE *Textures;
  540. TRANSFORM *Trans;
  541.   {
  542.   TEXTURE *Layer, *Material;
  543.  
  544.   for (Layer = Textures;
  545.   Layer != NULL;
  546.   Layer = Layer->Next_Layer)
  547.     switch (Layer->Type)
  548.     {
  549.     case PNF_TEXTURE:
  550.       Transform_Pigment (Layer->Pigment, Trans);
  551.       Transform_Tnormal (Layer->Tnormal, Trans);
  552.       break;
  553.  
  554.     case TILE_TEXTURE:
  555.       if (((TILES *)Layer)->Trans == NULL)
  556.         ((TILES *)Layer)->Trans = Create_Transform ();
  557.       Compose_Transforms (((TILES *)Layer)->Trans, Trans);
  558.       Transform_Textures (((TILES *)Layer)->Tile1, Trans);
  559.       Transform_Textures (((TILES *)Layer)->Tile2, Trans);
  560.       break;
  561.  
  562.     case MAT_TEXTURE:
  563.       if (((MATERIAL *)Layer)->Trans == NULL)
  564.         ((MATERIAL *)Layer)->Trans = Create_Transform ();
  565.       Compose_Transforms (((MATERIAL *)Layer)->Trans, Trans);
  566.       for (Material = ((MATERIAL *)Layer)->Materials;
  567.       Material != NULL;
  568.       Material = Material->Next_Material)
  569.         Transform_Textures (Material, Trans);
  570.       break;
  571.     }
  572.   }
  573.  
  574. FINISH *Create_Finish ()
  575.   {
  576.   FINISH *New;
  577.  
  578.   if ((New = (FINISH *) malloc (sizeof (FINISH))) == NULL)
  579.     MAError ("finish");
  580.  
  581.   New->Reflection = 0.0;
  582.   New->Ambient    = 0.1;
  583.   New->Diffuse    = 0.6;
  584.   New->Brilliance = 1.0;
  585.   New->Index_Of_Refraction = 1.0;
  586.   New->Refraction = 0.0;
  587.   New->Specular   = 0.0;
  588.   New->Roughness  = 1.0/0.05; /* CEY 12/92 */
  589.   New->Phong      = 0.0;
  590.   New->Phong_Size = 40.0;
  591.   New->Crand = 0.0;
  592.   New->Metallic_Flag = FALSE;
  593.  
  594.   return (New);
  595.   }
  596.  
  597. FINISH *Copy_Finish (Old)
  598. FINISH *Old;
  599.   {
  600.   FINISH *New;
  601.  
  602.   if (Old != NULL)
  603.     {
  604.     New  = Create_Finish ();
  605.     *New = *Old;
  606.     }
  607.   else
  608.     New = NULL;
  609.   return (New);
  610.   }
  611.  
  612. TEXTURE *Create_PNF_Texture ()
  613.   {
  614.   TEXTURE *New;
  615.  
  616.   if ((New = (TEXTURE *) malloc (sizeof (TEXTURE))) == NULL)
  617.     MAError ("texture");
  618.  
  619.   New->Type    = PNF_TEXTURE;
  620.   New->Flags   = NO_FLAGS;
  621.   New->Pigment = NULL;
  622.   New->Tnormal = NULL;
  623.   New->Finish  = NULL;
  624.   New->Next_Layer = NULL;
  625.   New->Next_Material = NULL;
  626.  
  627.   return (New);
  628.   }
  629.  
  630. TILES *Create_Tiles_Texture ()
  631.   {
  632.   TILES *New;
  633.  
  634.   if ((New = (TILES *) malloc (sizeof (TILES))) == NULL)
  635.     MAError ("checker texture");
  636.  
  637.   New->Type  = TILE_TEXTURE;
  638.   New->Flags = NO_FLAGS;
  639.   New->Tile1 = NULL;
  640.   New->Tile2 = NULL;
  641.   New->Trans  = NULL;
  642.   New->Next_Layer = NULL;
  643.   New->Next_Material = NULL;
  644.  
  645.   return (New);
  646.   }
  647.  
  648. MATERIAL *Create_Material_Texture ()
  649.   {
  650.   MATERIAL *New;
  651.  
  652.   if ((New = (MATERIAL *) malloc (sizeof (MATERIAL))) == NULL)
  653.     MAError ("material texture");
  654.  
  655.   New->Type      = MAT_TEXTURE;
  656.   New->Flags     = NO_FLAGS;
  657.   New->Materials = NULL;
  658.   New->Num_Of_Mats = 0;
  659.   New->Trans  = NULL;
  660.   New->Next_Layer = NULL;
  661.   New->Next_Material = NULL;
  662.  
  663.   return (New);
  664.   }
  665.  
  666. TEXTURE *Copy_Textures (Textures)
  667. TEXTURE *Textures;
  668.   {
  669.   TEXTURE *New, *First, *Previous, *Layer;
  670.  
  671.   Previous = First = NULL;
  672.  
  673.   for (Layer = Textures;
  674.   Layer != NULL;
  675.   Layer = Layer->Next_Layer)
  676.     {
  677.     switch (Layer->Type)
  678.     {
  679.     case PNF_TEXTURE:
  680.       New = Create_PNF_Texture ();
  681.       New->Pigment = Copy_Pigment (Layer->Pigment);
  682.       New->Tnormal = Copy_Tnormal (Layer->Tnormal);
  683.       New->Finish  = Copy_Finish  (Layer->Finish);
  684.       break;
  685.  
  686.     case TILE_TEXTURE:
  687.       New = (TEXTURE *) Create_Tiles_Texture ();
  688.       ((TILES *)New)->Tile1 = Copy_Textures (((TILES *)Layer)->Tile1);
  689.       ((TILES *)New)->Tile2 = Copy_Textures (((TILES *)Layer)->Tile2);
  690.       ((TILES *)New)->Trans = Copy_Transform (((TILES *)Layer)->Trans);
  691.       break;
  692.  
  693.     case MAT_TEXTURE:
  694.       New = (TEXTURE *) Create_Material_Texture ();
  695.       ((MATERIAL *)New)->Materials = Copy_Materials (((MATERIAL *)Layer)->Materials);
  696.       ((MATERIAL *)New)->Trans = Copy_Transform (((MATERIAL *)Layer)->Trans);
  697.       ((MATERIAL *)New)->Num_Of_Mats = (((MATERIAL *)Layer)->Num_Of_Mats);
  698.       break;
  699.     }
  700.  
  701.     if (First == NULL)
  702.       First = New;
  703.     if (Previous != NULL)
  704.       Previous->Next_Layer = New;
  705.     Previous = New;
  706.     }
  707.   return (First);
  708.   }
  709.  
  710. TEXTURE *Copy_Materials (Old)
  711. TEXTURE *Old;
  712.   {
  713.   TEXTURE *New, *First, *Previous, *Material;
  714.  
  715.   Previous = First = NULL;
  716.  
  717.   for (Material = Old;
  718.   Material != NULL;
  719.   Material = Material->Next_Material)
  720.     {
  721.     New = Copy_Textures (Material);
  722.  
  723.     if (First == NULL)
  724.       First = New;
  725.  
  726.     if (Previous != NULL)
  727.       Previous->Next_Material = New;
  728.  
  729.     Previous = New;
  730.     }
  731.   return (First);
  732.   }
  733.  
  734. void Destroy_Textures (Textures)
  735. TEXTURE *Textures;
  736.   {
  737.   TEXTURE *Layer=Textures;
  738.   TEXTURE *Mats;
  739.   TEXTURE *Temp;
  740.  
  741.   while (Layer != NULL)
  742.     {
  743.     Mats = Layer->Next_Material;
  744.     while (Mats != NULL)
  745.       {
  746.       Temp = Mats->Next_Material;
  747.       Destroy_Textures (Mats);
  748.       Mats = Temp;
  749.       }
  750.     switch (Layer->Type)
  751.     {
  752.     case PNF_TEXTURE:
  753.       Destroy_Pigment (Layer->Pigment);
  754.       Destroy_Tnormal (Layer->Tnormal);
  755.       Destroy_Finish (Layer->Finish);
  756.       break;
  757.  
  758.     case TILE_TEXTURE:
  759.       Destroy_Transform (((TILES *)Layer)->Trans);
  760.       Destroy_Textures (((TILES *)Layer)->Tile1);
  761.       Destroy_Textures (((TILES *)Layer)->Tile2);
  762.       break;
  763.  
  764.     case MAT_TEXTURE:
  765.       Destroy_Transform (((MATERIAL *)Layer)->Trans);
  766.       Destroy_Textures (((MATERIAL *)Layer)->Materials);
  767.       Destroy_Image (((MATERIAL *)Layer)->Image);
  768.       break;
  769.     }
  770.     Temp = Layer->Next_Layer;
  771.     free (Layer);
  772.     Layer = Temp;
  773.     }
  774.   }  
  775.  
  776. void Post_Textures (Textures)
  777. TEXTURE *Textures;
  778.   {
  779.   TEXTURE *Layer, *Material;
  780.  
  781.   if (Textures == NULL)
  782.     return;
  783.  
  784.   for (Layer = Textures;
  785.   Layer != NULL;
  786.   Layer = Layer->Next_Layer)
  787.     {
  788.     if (!((Layer->Flags) & POST_DONE))
  789.       switch (Layer->Type)
  790.       {
  791.       case PNF_TEXTURE:
  792.         Post_Pigment (Layer->Pigment);
  793.         Post_Tnormal (Layer->Tnormal);
  794.         break;
  795.  
  796.       case TILE_TEXTURE:
  797.         Post_Textures (((TILES *)Layer)->Tile1);
  798.         Post_Textures (((TILES *)Layer)->Tile2);
  799.         break;
  800.  
  801.       case MAT_TEXTURE:
  802.         for (Material = ((MATERIAL *)Layer)->Materials;
  803.         Material != NULL;
  804.         Material = Material->Next_Material)
  805.           Post_Textures(Material);
  806.         break;
  807.       }
  808.     }
  809.   return;
  810.   }
  811.  
  812.