home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / graphics / povsrc20 / pigment.c < prev    next >
C/C++ Source or Header  |  1993-09-20  |  20KB  |  803 lines

  1. /****************************************************************************
  2. *                pigment.c
  3. *
  4. *  This module implements solid texturing functions that modify the color
  5. *  transparency of an object's surface.
  6. *
  7. *  from Persistence of Vision Raytracer
  8. *  Copyright 1993 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other 
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If 
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. /*
  26.    Some texture ideas garnered from SIGGRAPH '85 Volume 19 Number 3, 
  27.    "An Image Synthesizer" By Ken Perlin.
  28.    Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley).
  29. */
  30.  
  31. #include "frame.h"
  32. #include "vector.h"
  33. #include "povproto.h"
  34. #include "texture.h"
  35.  
  36. COLOUR_MAP_ENTRY Black_White_Entries[2]=
  37.    {{0.0, {0.0,0.0,0.0,0.0}},
  38.     {1.0, {1.0,1.0,1.0,0.0}}};
  39.  
  40. COLOUR_MAP Gray_Default_Map =
  41.   { 2, FALSE, -1, Black_White_Entries};
  42.  
  43. COLOUR_MAP_ENTRY Bozo_Entries[6]=
  44.    {{0.4, {1.0,1.0,1.0,0.0}},
  45.     {0.4, {0.0,1.0,0.0,0.0}},
  46.     {0.6, {0.0,1.0,0.0,0.0}},
  47.     {0.6, {0.0,0.0,1.0,0.0}},
  48.     {0.8, {0.0,0.0,1.0,0.0}},
  49.     {0.8, {1.0,0.0,0.0,0.0}}};
  50.  
  51. COLOUR_MAP Bozo_Default_Map =
  52.   { 6, FALSE, -1, Bozo_Entries};
  53.  
  54. COLOUR_MAP_ENTRY Wood_Entries[2]=
  55.    {{0.6, {0.666,0.312, 0.2,  0.0}},
  56.     {0.6, {0.4,  0.1333,0.066,0.0}}};
  57.  
  58. COLOUR_MAP Wood_Default_Map =
  59.   { 2, FALSE, -1, Wood_Entries};
  60.  
  61. COLOUR_MAP_ENTRY Mandel_Entries[5]=
  62.    {{0.001, {0.0,0.0,0.0,0.0}},
  63.     {0.001, {0.0,1.0,1.0,0.0}},
  64.     {0.012, {1.0,1.0,0.0,0.0}},
  65.     {0.015, {1.0,0.0,1.0,0.0}},
  66.     {0.1,   {0.0,1.0,1.0,0.0}}};
  67.  
  68. COLOUR_MAP Mandel_Default_Map =
  69.   { 5, FALSE, -1, Mandel_Entries};
  70.  
  71. COLOUR_MAP_ENTRY Agate_Entries[6]=
  72.    {{0.0, {1.0, 1.0, 1.0, 0.0}},
  73.     {0.5, {0.95,0.75,0.5, 0.0}},
  74.     {0.5, {0.9, 0.7, 0.5, 0.0}},
  75.     {0.6, {0.9, 0.7, 0.4, 0.0}},
  76.     {0.6, {1.0, 0.7, 0.4, 0.0}},
  77.     {1.0, {0.6, 0.3, 0.0, 0.0}}};
  78.  
  79. COLOUR_MAP Agate_Default_Map =
  80.   { 6, FALSE, -1, Agate_Entries};
  81.  
  82. COLOUR_MAP_ENTRY Radial_Entries[4]=
  83.    {{0.0,   {0.0,1.0,1.0,0.0}},
  84.     {0.333, {1.0,1.0,0.0,0.0}},
  85.     {0.666, {1.0,0.0,1.0,0.0}},
  86.     {1.0,   {0.0,1.0,1.0,0.0}}};
  87.  
  88. COLOUR_MAP Radial_Default_Map =
  89.   { 4, FALSE, -1, Radial_Entries};
  90.  
  91. COLOUR_MAP_ENTRY Marble_Entries[3]=
  92.    {{0.0,   {0.9,0.8, 0.8, 0.0}},
  93.     {0.9,   {0.9,0.08,0.08,0.0}},
  94.     {0.9,   {0.0,0.0,0.0,0.0}}};
  95.  
  96. COLOUR_MAP Marble_Default_Map =
  97.   { 3, FALSE, -1, Marble_Entries};
  98.  
  99. void agate (x, y, z, Pigment, colour)
  100. DBL x, y, z;
  101. PIGMENT *Pigment;
  102. COLOUR *colour;
  103.   {
  104.   register DBL noise, turb;
  105.   COLOUR New_Colour;
  106.  
  107.   turb = Turbulence(x, y, z,Pigment->omega,
  108.                     Pigment->lambda,Pigment->Octaves) 
  109.            * Pigment->Agate_Turb_Scale;
  110.   noise = 0.5 * (cycloidal(1.3 * turb + 1.1 * z) + 1.0);
  111.   if (noise <= 0.0)
  112.      noise = 0.0;
  113.   else 
  114.     {
  115.      noise = (noise > 1.0 ? 1.0 : noise);
  116.      noise = pow(noise, 0.77);
  117.     }
  118.  
  119.   Compute_Colour (&New_Colour, Pigment, noise);
  120.   colour -> Red += New_Colour.Red;
  121.   colour -> Green += New_Colour.Green;
  122.   colour -> Blue += New_Colour.Blue;
  123.   colour -> Filter += New_Colour.Filter;
  124.   }
  125.  
  126. void bozo (x, y, z, Pigment, colour)
  127. DBL x, y, z;
  128. PIGMENT *Pigment;
  129. COLOUR *colour;
  130.   {
  131.   register DBL noise;
  132.   COLOUR New_Colour;
  133.  
  134.   noise = Noise (x, y, z);
  135.  
  136.   Compute_Colour (&New_Colour, Pigment, noise);
  137.   colour -> Red += New_Colour.Red;
  138.   colour -> Green += New_Colour.Green;
  139.   colour -> Blue += New_Colour.Blue;
  140.   colour -> Filter += New_Colour.Filter;
  141.   }
  142.  
  143. void brick (x, y, z, Pigment, colour)
  144. DBL x, y, z;
  145. PIGMENT *Pigment;
  146. COLOUR *colour;
  147.   {
  148.  
  149.   /* Disabled.  Needs work.
  150.  
  151.    DBL xr, yr, zr;
  152.  
  153.      xr = fabs(fmod(x, 1.0));
  154.      yr = fabs(fmod(y, 1.0));
  155.      zr = fabs(fmod(z, 1.0));
  156.  
  157.    *colour = *Pigment -> Colour2;
  158.  
  159.     if (xr > 0 && xr < Pigment-> Mortar) {
  160.        *colour = *Pigment -> Colour1;
  161.        return;
  162.        }
  163.     if (yr > 0 && yr < Pigment-> Mortar) {
  164.        *colour = *Pigment -> Colour1;
  165.        return;
  166.        }
  167.     if (zr > 0 && zr < Pigment-> Mortar)
  168.        *colour = *Pigment -> Colour1;
  169.  
  170. */
  171.   return;
  172.  
  173.   }
  174.  
  175. void checker (x, y, z, Pigment, colour)
  176. DBL x, y, z;
  177. PIGMENT *Pigment;
  178. COLOUR *colour;
  179.   {
  180.   DBL value;
  181.   COLOUR_MAP_ENTRY *Cur;
  182.   int Num_Entries = Pigment->Colour_Map->Number_Of_Entries;
  183.   int Fudge = (int)((DBL)Num_Entries/Pigment->Frequency);
  184.  
  185.   x += Small_Tolerance;
  186.   y += Small_Tolerance;
  187.   z += Small_Tolerance;
  188.  
  189.   x -= FLOOR(x/Fudge) * Fudge-Small_Tolerance;
  190.   y -= FLOOR(y/Fudge) * Fudge-Small_Tolerance;
  191.   z -= FLOOR(z/Fudge) * Fudge-Small_Tolerance;
  192.  
  193.   value = (FLOOR(x)+FLOOR(y)+FLOOR(z))* Pigment->Frequency;
  194.  
  195.   value = fmod(FLOOR(value + (int)(Pigment->Phase)),
  196.     (DBL) Num_Entries);
  197.  
  198.   Cur = &(Pigment->Colour_Map->Colour_Map_Entries[0]);
  199.  
  200.   while (value > Cur->value)
  201.     Cur++;
  202.  
  203.   colour->Red   += Cur->Colour.Red;
  204.   colour->Green += Cur->Colour.Green;
  205.   colour->Blue  += Cur->Colour.Blue;
  206.   colour->Filter += Cur->Colour.Filter;
  207.  
  208.   }
  209.  
  210.  
  211. /*
  212.    Color Gradient Pigment - gradient based on the fractional values of x, y or
  213.    z, based on whether or not the given directional vector is a 1.0 or a 0.0.
  214.    Note - ONLY works with colour maps, preferably one that is circular - i.e.
  215.    the last defined colour (value 1.001) is the same as the first colour (with
  216.    a value of 0.0) in the map.  The basic concept of this is from DBW Render,
  217.    but Dave Wecker's only supports simple Y axis gradients.
  218. */
  219.  
  220. void gradient (x, y, z, Pigment, colour)
  221. DBL x, y, z;
  222. PIGMENT *Pigment;
  223. COLOUR *colour;
  224.   {
  225.   COLOUR New_Colour;
  226.   DBL value = 0.0;
  227.  
  228.   if (Pigment -> Colour_Gradient.x != 0.0)
  229.     {
  230.     x = FABS(x);
  231.     value += x - FLOOR(x);        /* obtain fractional X component */
  232.     }
  233.   if (Pigment -> Colour_Gradient.y != 0.0)
  234.     {
  235.     y = FABS(y);
  236.     value += y - FLOOR(y);        /* obtain fractional Y component */
  237.     }
  238.   if (Pigment -> Colour_Gradient.z != 0.0)
  239.     {
  240.     z = FABS(z);
  241.     value += z - FLOOR(z);        /* obtain fractional Z component */
  242.     }
  243.   value = ((value > 1.0) ? fmod(value, 1.0) : value); /* clamp to 1.0 */
  244.  
  245.   Compute_Colour (&New_Colour, Pigment, value);
  246.   colour -> Red += New_Colour.Red;
  247.   colour -> Green += New_Colour.Green;
  248.   colour -> Blue += New_Colour.Blue;
  249.   colour -> Filter += New_Colour.Filter;
  250.   }
  251.  
  252.  
  253. /*
  254.    Granite - kind of a union of the "spotted" and the "dented" textures,
  255.    using a 1/f fractal noise function for color values.  Typically used
  256.    w/ small scaling values.  Should work with colour maps for pink granite...
  257. */
  258.  
  259.  
  260. void granite (x, y, z, Pigment, colour)
  261. DBL x, y, z;
  262. PIGMENT *Pigment;
  263. COLOUR *colour;
  264.   {
  265.   register int i;
  266.   register DBL temp, noise = 0.0, freq = 1.0;
  267.   COLOUR New_Colour;
  268.  
  269.   for (i = 0; i < 6 ; freq *= 2.0, i++)
  270.     {
  271.     temp = 0.5 - Noise (x * 4 * freq, y * 4 * freq, z * 4 * freq);
  272.     temp = FABS(temp);
  273.     noise += temp / freq;
  274.     }
  275.  
  276.   Compute_Colour (&New_Colour, Pigment, noise);
  277.   colour -> Red += New_Colour.Red;
  278.   colour -> Green += New_Colour.Green;
  279.   colour -> Blue += New_Colour.Blue;
  280.   colour -> Filter += New_Colour.Filter;
  281.   }
  282.  
  283. void mandel (x, y, z, Pigment, colour)
  284. DBL x, y, z;
  285. PIGMENT *Pigment;
  286. COLOUR *colour;
  287.   {  
  288.   DBL a,b,cf,a2,b2;
  289.   int it_max,col;
  290.   COLOUR thepoint;
  291.  
  292.   a = x; a2 = a*a;
  293.   b = y; b2 = b*b;
  294.   it_max = Pigment->Iterations;
  295.   for (col=0;col<it_max;col++) 
  296.     {
  297.      b  = 2*a*b + y;
  298.      a  = a2 - b2 + x;
  299.      a2 = a*a;
  300.      b2 = b*b;
  301.      if (a2 + b2 > 4.0)
  302.        break;
  303.     }
  304.   cf = (DBL)col / it_max;
  305.  
  306.   Compute_Colour (&thepoint, Pigment, cf);
  307.   colour->Red   +=thepoint.Red;
  308.   colour->Green +=thepoint.Green;
  309.   colour->Blue  +=thepoint.Blue;
  310.   colour->Filter +=thepoint.Filter;
  311.   }
  312.  
  313.  
  314. void marble (x, y, z, Pigment, colour)
  315. DBL x, y, z;
  316. PIGMENT *Pigment;
  317. COLOUR *colour;
  318.   {
  319.   register DBL noise, turb;
  320.   COLOUR New_Colour;
  321.  
  322.   if ((Pigment->Flags) & HAS_TURB)
  323.     turb =  Turbulence(x, y, z,Pigment->omega,Pigment->lambda,Pigment->Octaves) *
  324.     Pigment->Turbulence.x;
  325.   else
  326.     turb = 0.0;
  327.  
  328.   noise = Triangle_Wave(x + turb);
  329.  
  330.   Compute_Colour (&New_Colour, Pigment, noise);
  331.   colour -> Red += New_Colour.Red;
  332.   colour -> Green += New_Colour.Green;
  333.   colour -> Blue += New_Colour.Blue;
  334.   colour -> Filter += New_Colour.Filter;
  335.   }
  336.  
  337. void radial (x, y, z, Pigment, colour)
  338. DBL x, y, z;
  339. PIGMENT *Pigment;
  340. COLOUR *colour;
  341.   {
  342.   register DBL value;
  343.   COLOUR New_Colour;
  344.  
  345.   if ( (fabs(x)<0.001) && (fabs(z)<0.001))
  346.     value = 0.25;
  347.   else
  348.     value = 0.25+(atan2(x,z)+M_PI)/(2*M_PI);
  349.  
  350.   Compute_Colour (&New_Colour, Pigment, value);
  351.   colour -> Red += New_Colour.Red;
  352.   colour -> Green += New_Colour.Green;
  353.   colour -> Blue += New_Colour.Blue;
  354.   colour -> Filter += New_Colour.Filter;
  355.   }
  356.  
  357.  
  358. /*        
  359.    With a little reflectivity and brilliance, can look like organ pipe
  360.    metal.   With tiny scaling values can look like masonry or concrete.
  361.    Works with color maps.
  362. */
  363.  
  364. void spotted (x, y, z, Pigment, colour)
  365. DBL x, y, z;
  366. PIGMENT *Pigment;
  367. COLOUR *colour;
  368.   {
  369.   register DBL noise;
  370.   COLOUR New_Colour;
  371.  
  372.   noise = Noise (x, y, z);
  373.  
  374.   Compute_Colour (&New_Colour, Pigment, noise);
  375.   colour -> Red += New_Colour.Red;
  376.   colour -> Green += New_Colour.Green;
  377.   colour -> Blue += New_Colour.Blue;
  378.   colour -> Filter += New_Colour.Filter;
  379.   }
  380.  
  381.  
  382. void wood (x, y, z, Pigment, colour)
  383. DBL x, y, z;
  384. PIGMENT *Pigment;
  385. COLOUR *colour;
  386.   {
  387.   register DBL noise, length;
  388.   VECTOR WoodTurbulence;
  389.   VECTOR point;
  390.   COLOUR New_Colour;
  391.  
  392.   DTurbulence (&WoodTurbulence, x, y, z,Pigment->omega,Pigment->lambda,Pigment->Octaves);
  393.  
  394.   point.x = cycloidal((x + WoodTurbulence.x)
  395.     * Pigment -> Turbulence.x);
  396.   point.y = cycloidal((y + WoodTurbulence.y)
  397.     * Pigment -> Turbulence.y);
  398.   point.z = 0.0;
  399.  
  400.   point.x += x;
  401.   point.y += y;
  402.  
  403.   /*  point.z += z;       Deleted per David Buck --  BP 7/91 */
  404.  
  405.   VLength (length, point);
  406.  
  407.   noise = Triangle_Wave(length);
  408.  
  409.   Compute_Colour (&New_Colour, Pigment, noise);
  410.   colour -> Red += New_Colour.Red;
  411.   colour -> Green += New_Colour.Green;
  412.   colour -> Blue += New_Colour.Blue;
  413.   colour -> Filter += New_Colour.Filter;
  414.   }
  415.  
  416. /* Two new pigments by Scott Taylor LEOPARD & ONION */
  417.  
  418. void leopard (x, y, z, Pigment, colour)      /* SWT 7/18/91 */
  419. DBL x, y, z;
  420. PIGMENT *Pigment;
  421. COLOUR *colour;
  422.   {
  423.   /* The variable noise is not used as noise in this function */
  424.   register DBL noise,temp1,temp2,temp3;
  425.   COLOUR New_Colour;
  426.  
  427.   /* This form didn't work with Zortech 386 compiler */
  428.   /* noise = Sqr((sin(x)+sin(y)+sin(z))/3); */
  429.   /* So we break it down. */
  430.   temp1 = sin(x);
  431.   temp2 = sin(y);
  432.   temp3 = sin(z);
  433.   noise = Sqr((temp1+temp2+temp3)/3);
  434.  
  435.   Compute_Colour (&New_Colour, Pigment, noise);
  436.   colour -> Red += New_Colour.Red;
  437.   colour -> Green += New_Colour.Green;
  438.   colour -> Blue += New_Colour.Blue;
  439.   colour -> Filter += New_Colour.Filter;
  440.   }
  441.  
  442. void onion (x, y, z, Pigment, colour)      /* SWT 7/18/91 */
  443. DBL x, y, z;
  444. PIGMENT *Pigment;
  445. COLOUR *colour;
  446.   {
  447.   /* The variable noise is not used as noise in this function */
  448.   register DBL noise;
  449.   COLOUR New_Colour;
  450.  
  451.   /* This ramp goes 0-1,1-0,0-1,1-0...
  452.    noise = (fmod(SQRT(Sqr(x)+Sqr(y)+Sqr(z)),2.0)-1.0);
  453.    if (noise<0.0) {noise = 0.0-noise;}
  454.    */
  455.  
  456.   /* This ramp goes 0-1,0-1,0-1,0-1... */
  457.   noise = (fmod(SQRT(Sqr(x)+Sqr(y)+Sqr(z)),1.0));
  458.  
  459.   Compute_Colour (&New_Colour, Pigment, noise);
  460.   colour -> Red += New_Colour.Red;
  461.   colour -> Green += New_Colour.Green;
  462.   colour -> Blue += New_Colour.Blue;
  463.   colour -> Filter += New_Colour.Filter;
  464.   }
  465.  
  466. /* TriHex pattern -- Ernest MacDougal Campbell III (EMC3) 11/23/92
  467.  *
  468.  * Creates a hexagon pattern in the XZ plane.
  469.  *
  470.  * This algorithm is hard to explain.  First it scales the point to make
  471.  * a few of the later calculations easier, then maps some points to be
  472.  * closer to the Origin.  A small area in the first quadrant is subdivided
  473.  * into a 6 x 6 grid.  The position of the point mapped into that grid
  474.  * determines its color.  For some points, just the grid location is enough,
  475.  * but for others, we have to calculate which half of the block it's in 
  476.  * (this is where the atan2() function comes in handy).
  477.  */
  478.  
  479. #define xfactor 0.5;         /* each triangle is split in half for the grid */
  480. #define zfactor 0.866025404; /* sqrt(3)/2 -- Height of an equilateral triangle */
  481.  
  482. void hexagon (x, y, z, Pigment, colour)
  483. DBL x, y, z;
  484. PIGMENT *Pigment;
  485. COLOUR *colour;
  486.   {
  487.   int xm, zm;
  488.   DBL xs, zs, xl, zl, value;
  489.   int brkindx;
  490.   COLOUR_MAP_ENTRY *Cur;
  491.  
  492.   /* Keep all numbers positive.  Also, if z is negative, map it in such a
  493.  * way as to avoid mirroring across the x-axis.  The value 5.196152424
  494.  * is (sqrt(3)/2) * 6 (because the grid is 6 blocks high)
  495.  */
  496.  
  497.   x = fabs(x);
  498.   z = z<0?5.196152424 - fabs(z):z;  /* avoid mirroring across x-axis */
  499.  
  500.   xs = x/xfactor;               /* scale point to make calcs easier */
  501.   zs = z/zfactor;
  502.  
  503.   xs -= floor(xs/6) * 6;        /* map points into the 6 x 6 grid where  */
  504.   zs -= floor(zs/6) * 6;        /* the basic formula works               */
  505.  
  506.   xm = (int) FLOOR(xs) % 6;     /* Get a block in the 6 x 6 grid */
  507.   zm = (int) FLOOR(zs) % 6;
  508.  
  509.   switch (xm)
  510.     {                 /* These are easy cases:           */
  511.   case 0:                     /* color depends only on xm and zm */
  512.   case 5:
  513.     switch (zm)
  514.       {
  515.     case 0:
  516.     case 5:
  517.       value = 0;
  518.       break;
  519.     case 1:
  520.     case 2:
  521.       value = 1;
  522.       break;
  523.     case 3:
  524.     case 4:
  525.       value = 2;
  526.       break;
  527.     }
  528.     break;
  529.   case 2:
  530.   case 3:
  531.     switch (zm)
  532.       {
  533.     case 0:
  534.     case 1:
  535.       value = 2;
  536.       break;
  537.     case 2:
  538.     case 3:
  539.       value = 0;
  540.       break;
  541.     case 4:
  542.     case 5:
  543.       value = 1;
  544.       break;
  545.     }
  546.     break;
  547.  
  548.     /* These cases are harder.  These blocks are divided diagonally
  549.       * by the angled edges of the hexagons.  Some slope positive, and
  550.       * others negative.  We flip the x value of the negatively sloped
  551.       * pieces.  Then we check to see if the point in question falls
  552.       * in the upper or lower half of the block.  That info, plus the
  553.       * z status of the block determines the color.
  554.       */
  555.  
  556.   case 1:
  557.   case 4:
  558.     xl = xs-xm; /* map the point into the block at the origin */
  559.     zl = zs-zm;
  560.  
  561.     if (((xm+zm) % 2) == 1)   /* These blocks have negative slopes */
  562.       xl = 1 - xl;            /* so we flip it horizontally        */
  563.  
  564.     if (xl == 0) 
  565.       xl = .0001;             /* avoid a divide-by-zero error */
  566.  
  567.     /* is the angle less-than or greater-than 45 degrees? */
  568.  
  569.     brkindx = (zl/xl) < 1;
  570.  
  571.     /* was...
  572.          * brkindx = (atan2(zl,xl) < (45 * M_PI/180));  
  573.          * ...but because of the mapping, it's easier and cheaper, 
  574.          * CPU-wise, to just use a good ol' slope.
  575.          */
  576.  
  577.     switch (brkindx) 
  578.       {
  579.     case TRUE:
  580.       switch (zm) 
  581.         {
  582.       case 0:
  583.       case 3:
  584.         value = 0;
  585.         break;
  586.       case 2:
  587.       case 5:
  588.         value = 1;
  589.         break;
  590.       case 1:
  591.       case 4:
  592.         value = 2;
  593.         break;
  594.       }
  595.       break;
  596.     case FALSE:
  597.       switch (zm) 
  598.         {
  599.       case 0:
  600.       case 3:
  601.         value = 2;
  602.         break;
  603.       case 2:
  604.       case 5:
  605.         value = 0;
  606.         break;
  607.       case 1:
  608.       case 4:
  609.         value = 1;
  610.         break;
  611.       }
  612.       }
  613.     }
  614.   value = fmod (value+(int)Pigment->Phase,3);
  615.  
  616.   Cur = &(Pigment->Colour_Map->Colour_Map_Entries[0]);
  617.   while (value > Cur->value)
  618.     Cur++;
  619.  
  620.   colour->Red   += Cur->Colour.Red;
  621.   colour->Green += Cur->Colour.Green;
  622.   colour->Blue  += Cur->Colour.Blue;
  623.   colour->Filter += Cur->Colour.Filter;
  624.  
  625.   return;
  626.   }
  627.  
  628. /* End trihex() */
  629.  
  630. PIGMENT *Create_Pigment ()
  631.   {
  632.   PIGMENT *New;
  633.  
  634.   if ((New = (PIGMENT *) malloc (sizeof (PIGMENT))) == NULL)
  635.     MAError ("pigment");
  636.  
  637.   INIT_TPATTERN_FIELDS(New,NO_PIGMENT)
  638.     New->Colour1 = NULL;
  639.   Make_Colour(&(New->Quick_Colour), 0.5,0.5,0.5) ;
  640.   New->Colour_Map = NULL;
  641.   Make_Vector (&(New->Colour_Gradient), 0.0, 0.0, 0.0);
  642.   New->Image = NULL;
  643.   New->Mortar = 0.2;
  644.   New->Agate_Turb_Scale = 1.0;
  645.   New->Iterations = 0;
  646.   return (New);
  647.   }
  648.  
  649. PIGMENT *Copy_Pigment (Old)
  650. PIGMENT *Old;
  651.   {
  652.   PIGMENT *New;
  653.  
  654.   if (Old != NULL)
  655.     {
  656.     New = Create_Pigment ();
  657.     *New = *Old;
  658.  
  659.     New->Trans = Copy_Transform (Old->Trans);
  660.     New->Colour1 = Copy_Colour (Old->Colour1);
  661.     New->Image = Copy_Image (Old->Image);
  662.     New->Colour_Map = Copy_Colour_Map (Old->Colour_Map);
  663.     }
  664.   else
  665.     New = NULL;
  666.  
  667.   return (New);   
  668.   }
  669.  
  670. void Translate_Pigment(Pigment,Vector)
  671. PIGMENT *Pigment;
  672. VECTOR *Vector;
  673.   {
  674.   TRANSFORM Trans;
  675.  
  676.   if (Pigment == NULL)
  677.     return;
  678.  
  679.   Compute_Translation_Transform (&Trans, Vector);
  680.   Transform_Pigment (Pigment, &Trans);
  681.   }
  682.  
  683. void Rotate_Pigment(Pigment,Vector)
  684. PIGMENT *Pigment;
  685. VECTOR *Vector;
  686.   {
  687.   TRANSFORM Trans;
  688.  
  689.   if (Pigment == NULL)
  690.     return;
  691.  
  692.   Compute_Rotation_Transform (&Trans, Vector);
  693.   Transform_Pigment (Pigment, &Trans);
  694.   }
  695.  
  696. void Scale_Pigment(Pigment,Vector)
  697. PIGMENT *Pigment;
  698. VECTOR *Vector;
  699.   {
  700.   TRANSFORM Trans;
  701.  
  702.   if (Pigment == NULL)
  703.     return;
  704.  
  705.   Compute_Scaling_Transform (&Trans, Vector);
  706.   Transform_Pigment (Pigment, &Trans);
  707.   }
  708.  
  709. void Transform_Pigment(Pigment,Trans)
  710. PIGMENT *Pigment;
  711. TRANSFORM *Trans;
  712.   {
  713.   if (Pigment == NULL)
  714.     return;
  715.  
  716.   if (!Pigment->Trans)
  717.     Pigment->Trans = Create_Transform ();
  718.  
  719.   Compose_Transforms (Pigment->Trans, Trans);
  720.   }
  721.  
  722. void Destroy_Pigment (Pigment)
  723. PIGMENT *Pigment;
  724.   {
  725.   if (Pigment == NULL)
  726.     return;
  727.  
  728.   Destroy_Colour (Pigment->Colour1);
  729.   Destroy_Colour_Map (Pigment->Colour_Map);
  730.   Destroy_Image (Pigment->Image);
  731.   Destroy_Transform (Pigment->Trans);
  732.   free (Pigment);
  733.   }
  734.  
  735. void Post_Pigment (Pigment)
  736. PIGMENT *Pigment;
  737.   {
  738.   if (Pigment == NULL)
  739.     Error("Missing pigment");
  740.  
  741.   if (Pigment->Flags & POST_DONE)
  742.     return;
  743.  
  744.   if (Pigment->Type == NO_PIGMENT)
  745.     {
  746.     Pigment->Type = COLOUR_PIGMENT;
  747.     Pigment->Colour1 = Create_Colour ();
  748.     Warn("No pigment type given",1.5);
  749.     }
  750.  
  751.   Pigment->Flags |= POST_DONE;
  752.  
  753.   switch (Pigment->Type)
  754.   {
  755.   case COLOUR_PIGMENT:
  756.     Destroy_Transform (Pigment->Trans);
  757.     Pigment->Trans = NULL;
  758.     Make_Vector(&(Pigment->Turbulence),0.0,0.0,0.0);
  759.     break;
  760.  
  761.   case BOZO_PIGMENT:
  762.     if (Pigment->Colour_Map == NULL)
  763.       Pigment->Colour_Map = &Bozo_Default_Map;
  764.     break;
  765.  
  766.   case WOOD_PIGMENT:
  767.     if (Pigment->Colour_Map == NULL)
  768.       Pigment->Colour_Map = &Wood_Default_Map;
  769.     break;
  770.  
  771.   case MANDEL_PIGMENT:
  772.     if (Pigment->Colour_Map == NULL)
  773.       Pigment->Colour_Map = &Mandel_Default_Map;
  774.     break;
  775.  
  776.   case RADIAL_PIGMENT:
  777.     if (Pigment->Colour_Map == NULL)
  778.       Pigment->Colour_Map = &Radial_Default_Map;
  779.     break;
  780.  
  781.   case AGATE_PIGMENT:
  782.     if (Pigment->Colour_Map == NULL)
  783.       Pigment->Colour_Map = &Agate_Default_Map;
  784.     break;
  785.  
  786.   case MARBLE_PIGMENT:
  787.     if (Pigment->Colour_Map == NULL)
  788.       Pigment->Colour_Map = &Marble_Default_Map;
  789.     break;
  790.  
  791.   case SPOTTED_PIGMENT:
  792.   case GRADIENT_PIGMENT:
  793.   case GRANITE_PIGMENT:
  794.   case ONION_PIGMENT:
  795.   case LEOPARD_PIGMENT:
  796.     if (Pigment->Colour_Map == NULL)
  797.       Pigment->Colour_Map = &Gray_Default_Map;
  798.     break;
  799.   }
  800.  
  801.   return;   
  802.   }
  803.