home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff397.lzh / DKBTrace / DKBSource.LZH / texture.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  29KB  |  1,033 lines

  1. /*****************************************************************************
  2. *
  3. *                                   texture.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements solid texturing functions such as wood, marble, and
  8. *  bozo.  The noise function used here is the one described by Ken Perlin in
  9. *  "Hypertexture", SIGGRAPH '89 Conference Proceedings page 253.
  10. *
  11. * This software is freely distributable. The source and/or object code may be
  12. * copied or uploaded to communications services so long as this notice remains
  13. * at the top of each file.  If any changes are made to the program, you must
  14. * clearly indicate in the documentation and in the programs startup message
  15. * who it was who made the changes. The documentation should also describe what
  16. * those changes were. This software may not be included in whole or in
  17. * part into any commercial package without the express written consent of the
  18. * author.  It may, however, be included in other public domain or freely
  19. * distributed software so long as the proper credit for the software is given.
  20. *
  21. * This software is provided as is without any guarantees or warranty. Although
  22. * the author has attempted to find and correct any bugs in the software, he
  23. * is not responsible for any damage caused by the use of the software.  The
  24. * author is under no obligation to provide service, corrections, or upgrades
  25. * to this package.
  26. *
  27. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  28. * about them.  Also, if you have any comments or questions, you may contact me
  29. * at the following address:
  30. *
  31. *     David Buck
  32. *     22C Sonnet Cres.
  33. *     Nepean Ontario
  34. *     Canada, K2H 8W7
  35. *
  36. *  I can also be reached on the following bulleton boards:
  37. *
  38. *     ATX              (613) 526-4141
  39. *     OMX              (613) 731-3419
  40. *     Mystic           (613) 731-0088 or (613) 731-6698
  41. *
  42. *  Fidonet:   1:163/109.9
  43. *  Internet:  David_Buck@Carleton.CA
  44. *
  45. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  46. *
  47. *     Lattice BBS                      (708) 916-1200
  48. *     The Information Exchange BBS     (708) 945-5575
  49. *     Stillwaters BBS                  (708) 403-2826
  50. *
  51. *
  52. *
  53. *
  54. *  The Noise and DNoise functions (and associated functions) were written by
  55. *  Robert Skinner (robert@sgi.com) and are used here with his permission.
  56. *  They are a lot better than the noise functions I had before!
  57. *
  58. *****************************************************************************/
  59.  
  60.  
  61. #include "frame.h"
  62. #include "vector.h"
  63. #include "dkbproto.h"
  64.  
  65. extern long Calls_To_Noise, Calls_To_DNoise;
  66.  
  67. #define MINX    -10000        /* Ridiculously large scaling values */
  68. #define MINY    MINX
  69. #define MINZ    MINX
  70.  
  71. #define MAXSIZE 267
  72. #define RNDMASK 0x7FFF
  73. #define RNDDIVISOR (float) RNDMASK
  74. #define NUMBER_OF_WAVES 10
  75. #define SINTABSIZE 1000
  76. #define EPSILON    (DBL) 0.00001
  77.  
  78. #define FLOOR(x) ((x) >= 0.0 ? floor(x) : (0.0 - floor(0.0 - (x)) - 1.0))
  79. #define FABS(x) ((x) < 0.0 ? (0.0 - x) : (x))
  80. #define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
  81. #define REALSCALE ( 2.0 / 65535.0 )
  82. #define Hash3d(a,b,c) hashTable[(int)(hashTable[(int)(hashTable[(int)((a) & 0xfffL)] ^ ((b) & 0xfffL))] ^ ((c) & 0xfffL))]
  83. #define INCRSUM(m,s,x,y,z)    ((s)*(RTable[m]*0.5        \
  84.                     + RTable[m+1]*(x)    \
  85.                     + RTable[m+2]*(y)    \
  86.                     + RTable[m+3]*(z)))
  87.  
  88. DBL sintab [SINTABSIZE];
  89. DBL frequency[NUMBER_OF_WAVES];
  90. VECTOR Wave_Sources[NUMBER_OF_WAVES];
  91. DBL    RTable[MAXSIZE];
  92. short *hashTable;
  93. unsigned short crctab[256] =
  94. {
  95.    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  96.    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  97.    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  98.    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  99.    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  100.    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  101.    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  102.    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  103.    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  104.    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  105.    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  106.    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  107.    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  108.    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  109.    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  110.    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  111.    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  112.    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  113.    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  114.    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  115.    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  116.    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  117.    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  118.    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  119.    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  120.    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  121.    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  122.    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  123.    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  124.    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  125.    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  126.    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  127. };
  128.  
  129.  
  130. void Compute_Colour (Colour, Colour_Map, value)
  131.    COLOUR *Colour;
  132.    COLOUR_MAP *Colour_Map;
  133.    DBL value;
  134.    {
  135.    register int i;
  136.    COLOUR_MAP_ENTRY *Entry;
  137.    register DBL fraction;
  138.  
  139.    for (i = 0, Entry = &(Colour_Map->Colour_Map_Entries[0]) ; i < Colour_Map -> Number_Of_Entries ; i++, Entry++)
  140.       if ((value >= Entry->start) && (value <= Entry->end))
  141.       {
  142.       fraction = (value - Entry->start) / (Entry->end - Entry->start);
  143.       Colour -> Red = Entry->Start_Colour.Red + fraction * (Entry->End_Colour.Red - Entry->Start_Colour.Red);
  144.       Colour -> Green = Entry->Start_Colour.Green + fraction * (Entry->End_Colour.Green - Entry->Start_Colour.Green);
  145.       Colour -> Blue = Entry->Start_Colour.Blue + fraction * (Entry->End_Colour.Blue - Entry->Start_Colour.Blue);
  146.       Colour -> Alpha = Entry->Start_Colour.Alpha + fraction * (Entry->End_Colour.Alpha - Entry->Start_Colour.Alpha);
  147.       return;
  148.       }
  149.  
  150.    Colour -> Red = 0.0;
  151.    Colour -> Green = 0.0;
  152.    Colour -> Blue = 0.0;
  153.    Colour -> Alpha = 0.0;
  154.    printf ("No colour for value: %f\n", value);
  155.    return;
  156.    }
  157.  
  158. void Initialize_Noise ()
  159.    {
  160.    register int i = 0;
  161.    VECTOR point;
  162.  
  163.    InitRTable();
  164.  
  165.    for (i = 0 ; i < SINTABSIZE ; i++)
  166.       sintab[i] = sin(i/(DBL)SINTABSIZE * (3.14159265359 * 2.0));
  167.  
  168.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++)
  169.       {
  170.       DNoise (&point, (DBL) i, 0.0, 0.0);
  171.       VNormalize (Wave_Sources[i], point);
  172.       frequency[i] = (rand() & RNDMASK) / RNDDIVISOR + 0.01;
  173.       }
  174.    }
  175.  
  176. void InitTextureTable()
  177.    {
  178.    int i, j, temp;
  179.  
  180.    srand(0);
  181.  
  182.    hashTable = (short int *) malloc(4096*sizeof(short int));
  183.    for (i = 0; i < 4096; i++)
  184.       hashTable[i] = i;
  185.    for (i = 4095; i >= 0; i--)
  186.       {
  187.       j = rand() % 4096;
  188.       temp = hashTable[i];
  189.       hashTable[i] = hashTable[j];
  190.       hashTable[j] = temp;
  191.       }
  192.    }
  193.  
  194.  
  195. /* modified by AAC to work properly with little bitty integers (16 bits) */
  196.  
  197. void InitRTable()
  198.    {
  199.    int i;
  200.    VECTOR rp;
  201.  
  202.    InitTextureTable();
  203.  
  204.    for (i = 0; i < MAXSIZE; i++)
  205.       {
  206.       rp.x = rp.y = rp.z = (DBL)i;
  207.       RTable[i] = (unsigned int) R(&rp) * REALSCALE - 1.0;
  208.       }
  209.    }
  210.  
  211.  
  212. int R(v)
  213.    VECTOR *v;
  214.    {
  215.    v->x *= .12345;
  216.    v->y *= .12345;
  217.    v->z *= .12345;
  218.  
  219.    return (Crc16((char *) v, sizeof(VECTOR)));
  220.    }
  221.  
  222. /*
  223.  * Note that passing a VECTOR array to Crc16 and interpreting it as
  224.  * an array of chars means that machines with different floating-point
  225.  * representation schemes will evaluate Noise(point) differently.
  226.  */
  227.  
  228. int Crc16(buf, count)
  229.    register char *buf;
  230.    register int  count;
  231.    {
  232.    register unsigned short crc = 0;
  233.  
  234.    while (count--)
  235.       crc = (crc >> 8) ^ crctab[ (unsigned char) (crc ^ *buf++) ];
  236.  
  237.    return ((int) crc);
  238.    }
  239.  
  240.  
  241. /*
  242.     Robert's Skinner's Perlin-style "Noise" function - modified by AAC
  243.     to ensure uniformly distributed clamped values between 0 and 1.0...
  244. */
  245.  
  246. DBL Noise(x, y, z)
  247.    DBL x, y, z;
  248.    {
  249.    register long ix, iy, iz, jx, jy, jz;
  250.    DBL sx, sy, sz, tx, ty, tz;
  251.    DBL sum;
  252.    short m;
  253.  
  254.  
  255.    Calls_To_Noise++;
  256.    /* ensures the values are positive. */
  257.    x -= MINX;
  258.    y -= MINY;
  259.    z -= MINZ;
  260.  
  261.    /* its equivalent integer lattice point. */
  262.    ix = (long)x; iy = (long)y; iz = (long)z;
  263.    jx = ix + 1; jy = iy + 1; jz = iz + 1;
  264.  
  265.    sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  266.  
  267.    /* the complement values of sx,sy,sz */
  268.    tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  269.  
  270.    /*
  271.     *  interpolate!
  272.     */
  273.    m = Hash3d( ix, iy, iz ) & 0xFF;
  274.    sum = INCRSUM(m,(tx*ty*tz),(x-ix),(y-iy),(z-iz));
  275.  
  276.    m = Hash3d( jx, iy, iz ) & 0xFF;
  277.    sum += INCRSUM(m,(sx*ty*tz),(x-jx),(y-iy),(z-iz));
  278.  
  279.    m = Hash3d( ix, jy, iz ) & 0xFF;
  280.    sum += INCRSUM(m,(tx*sy*tz),(x-ix),(y-jy),(z-iz));
  281.  
  282.    m = Hash3d( jx, jy, iz ) & 0xFF;
  283.    sum += INCRSUM(m,(sx*sy*tz),(x-jx),(y-jy),(z-iz));
  284.  
  285.    m = Hash3d( ix, iy, jz ) & 0xFF;
  286.    sum += INCRSUM(m,(tx*ty*sz),(x-ix),(y-iy),(z-jz));
  287.  
  288.    m = Hash3d( jx, iy, jz ) & 0xFF;
  289.    sum += INCRSUM(m,(sx*ty*sz),(x-jx),(y-iy),(z-jz));
  290.  
  291.    m = Hash3d( ix, jy, jz ) & 0xFF;
  292.    sum += INCRSUM(m,(tx*sy*sz),(x-ix),(y-jy),(z-jz));
  293.  
  294.    m = Hash3d( jx, jy, jz ) & 0xFF;
  295.    sum += INCRSUM(m,(sx*sy*sz),(x-jx),(y-jy),(z-jz));
  296.  
  297.    sum = sum + 0.5;          /* range at this point -0.5 - 0.5... */
  298.     
  299.    if (sum < 0.0)
  300.       sum = 0.0;
  301.    if (sum > 1.0)
  302.       sum = 1.0;
  303.  
  304.    return (sum);
  305.    }
  306.  
  307.  
  308. /*
  309.        Vector-valued version of "Noise"
  310. */
  311.  
  312. void DNoise(result, x, y, z)
  313.    VECTOR *result;
  314.    DBL x, y, z;
  315.    {
  316.    register long ix, iy, iz, jx, jy, jz;
  317.    DBL px, py, pz, s;
  318.    DBL sx, sy, sz, tx, ty, tz;
  319.    short m;
  320.  
  321.    Calls_To_DNoise++;
  322.    /* ensures the values are positive. */
  323.    x -= MINX;
  324.    y -= MINY;
  325.    z -= MINZ;
  326.  
  327.    /* its equivalent integer lattice point. */
  328.    ix = (long)x; iy = (long)y; iz = (long)z;
  329.    jx = ix+1; jy = iy + 1; jz = iz + 1;
  330.  
  331.    sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  332.  
  333.    /* the complement values of sx,sy,sz */
  334.    tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  335.  
  336.    /*
  337.     *  interpolate!
  338.     */
  339.    m = Hash3d( ix, iy, iz ) & 0xFF;
  340.    px = x-ix;  py = y-iy;  pz = z-iz;
  341.    s = tx*ty*tz;
  342.    result->x = INCRSUM(m,s,px,py,pz);
  343.    result->y = INCRSUM(m+4,s,px,py,pz);
  344.    result->z = INCRSUM(m+8,s,px,py,pz);
  345.  
  346.    m = Hash3d( jx, iy, iz ) & 0xFF;
  347.    px = x-jx;
  348.    s = sx*ty*tz;
  349.    result->x += INCRSUM(m,s,px,py,pz);
  350.    result->y += INCRSUM(m+4,s,px,py,pz);
  351.    result->z += INCRSUM(m+8,s,px,py,pz);
  352.  
  353.    m = Hash3d( jx, jy, iz ) & 0xFF;
  354.    py = y-jy;
  355.    s = sx*sy*tz;
  356.    result->x += INCRSUM(m,s,px,py,pz);
  357.    result->y += INCRSUM(m+4,s,px,py,pz);
  358.    result->z += INCRSUM(m+8,s,px,py,pz);
  359.  
  360.    m = Hash3d( ix, jy, iz ) & 0xFF;
  361.    px = x-ix;
  362.    s = tx*sy*tz;
  363.    result->x += INCRSUM(m,s,px,py,pz);
  364.    result->y += INCRSUM(m+4,s,px,py,pz);
  365.    result->z += INCRSUM(m+8,s,px,py,pz);
  366.  
  367.    m = Hash3d( ix, jy, jz ) & 0xFF;
  368.    pz = z-jz;
  369.    s = tx*sy*sz;
  370.    result->x += INCRSUM(m,s,px,py,pz);
  371.    result->y += INCRSUM(m+4,s,px,py,pz);
  372.    result->z += INCRSUM(m+8,s,px,py,pz);
  373.  
  374.    m = Hash3d( jx, jy, jz ) & 0xFF;
  375.    px = x-jx;
  376.    s = sx*sy*sz;
  377.    result->x += INCRSUM(m,s,px,py,pz);
  378.    result->y += INCRSUM(m+4,s,px,py,pz);
  379.    result->z += INCRSUM(m+8,s,px,py,pz);
  380.  
  381.    m = Hash3d( jx, iy, jz ) & 0xFF;
  382.    py = y-iy;
  383.    s = sx*ty*sz;
  384.    result->x += INCRSUM(m,s,px,py,pz);
  385.    result->y += INCRSUM(m+4,s,px,py,pz);
  386.    result->z += INCRSUM(m+8,s,px,py,pz);
  387.  
  388.    m = Hash3d( ix, iy, jz ) & 0xFF;
  389.    px = x-ix;
  390.    s = tx*ty*sz;
  391.    result->x += INCRSUM(m,s,px,py,pz);
  392.    result->y += INCRSUM(m+4,s,px,py,pz);
  393.    result->z += INCRSUM(m+8,s,px,py,pz);
  394.    }
  395.  
  396. DBL Turbulence (x, y, z)
  397.    DBL x, y, z;
  398.    {
  399.    register DBL pixelSize = 0.1;
  400.    register DBL t = 0.0;
  401.    register DBL scale, value;
  402.  
  403.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  404.       value = Noise (x/scale, y/scale, z/scale);
  405.       t += FABS (value) * scale;
  406.       }
  407.    return (t);
  408.    }
  409.  
  410. void DTurbulence (result, x, y, z)
  411.    VECTOR *result;
  412.    DBL x, y, z;
  413.    {
  414.    register DBL pixelSize = 0.01;
  415.    register DBL scale;
  416.    VECTOR value;
  417.  
  418.    result -> x = 0.0;
  419.    result -> y = 0.0;
  420.    result -> z = 0.0;
  421.  
  422.    value.x = value.y = value.z = 0.0;
  423.  
  424.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  425.       DNoise(&value, x/scale, y/scale, z/scale);
  426.       result -> x += value.x * scale;
  427.       result -> y += value.y * scale;
  428.       result -> z += value.z * scale;
  429.       }
  430.    }
  431.  
  432. DBL cycloidal (value)
  433.    DBL value;
  434.    {
  435.  
  436.    if (value >= 0.0)
  437.       return (sintab [(int)((value - floor (value)) * SINTABSIZE)]);
  438.    else
  439.       return (0.0 - sintab [(int)((0.0 - (value + floor (0.0 - value)))
  440.                                     * SINTABSIZE)]);
  441.    }
  442.  
  443.  
  444. DBL Triangle_Wave (value)
  445.    DBL value;
  446.    {
  447.    register DBL offset;
  448.  
  449.    if (value >= 0.0) offset = value - floor(value);
  450.    else offset = value - (-1.0 - floor(FABS(value)));
  451.  
  452.    if (offset >= 0.5) return (2.0 * (1.0 - offset));
  453.    else return (2.0 * offset);
  454.    }
  455.  
  456.  
  457. int Bozo (x, y, z, Object, Colour)
  458. DBL x, y, z;
  459. OBJECT *Object;
  460. COLOUR *Colour;
  461.    {
  462.    register DBL noise, turb;
  463.    COLOUR New_Colour;
  464.    VECTOR BozoTurbulence;
  465.  
  466.  
  467.    if ((turb = Object->Object_Texture->Turbulence) != 0.0)
  468.       {
  469.       DTurbulence (&BozoTurbulence, x, y, z);
  470.       x += BozoTurbulence.x * turb;
  471.       y += BozoTurbulence.y * turb;
  472.       z += BozoTurbulence.z * turb;
  473.       }
  474.  
  475.    noise = Noise (x, y, z);
  476.  
  477.    if (Object -> Object_Texture->Colour_Map != NULL) {
  478.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  479.       Colour -> Red += New_Colour.Red;
  480.       Colour -> Green += New_Colour.Green;
  481.       Colour -> Blue += New_Colour.Blue;
  482.       Colour -> Alpha += New_Colour.Alpha;
  483.       return (0);
  484.       }
  485.  
  486.    if (noise < 0.4) {
  487.       Colour -> Red += 1.0;
  488.       Colour -> Green += 1.0;
  489.       Colour -> Blue += 1.0;
  490.       return (0);
  491.       }
  492.  
  493.    if (noise < 0.6) {
  494.       Colour -> Green += 1.0;
  495.       return (0);
  496.       }
  497.  
  498.    if (noise < 0.8) {
  499.       Colour -> Blue += 1.0;
  500.       return (0);
  501.       }
  502.  
  503.    Colour -> Red += 1.0;
  504.    return (0);
  505.    }
  506.  
  507. int marble (x, y, z, Object, colour)
  508.    DBL x, y, z;
  509.    OBJECT *Object;
  510.    COLOUR *colour;
  511.    {
  512.    register DBL noise, hue;
  513.    COLOUR New_Colour;
  514.  
  515.    noise = Triangle_Wave(x + Turbulence(x, y, z) * Object -> Object_Texture->Turbulence);
  516.  
  517.    if (Object -> Object_Texture->Colour_Map != NULL)
  518.       {
  519.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  520.       colour -> Red += New_Colour.Red;
  521.       colour -> Green += New_Colour.Green;
  522.       colour -> Blue += New_Colour.Blue;
  523.       colour -> Alpha += New_Colour.Alpha;
  524.       return (0);
  525.       }
  526.  
  527.    if (noise < 0.0)
  528.       {
  529.       colour -> Red += 0.9;
  530.       colour -> Green += 0.8;
  531.       colour -> Blue += 0.8;
  532.       }
  533.    else if (noise < 0.9)
  534.       {
  535.       colour -> Red += 0.9;
  536.       hue = 0.8 - noise * 0.8;
  537.       colour -> Green += hue;
  538.       colour -> Blue += hue;
  539.       }
  540.    return (0);
  541.    }
  542.  
  543.  
  544. void ripples (x, y, z, Object, Vector)
  545.    DBL x, y, z;
  546.    OBJECT *Object;
  547.    VECTOR *Vector;
  548.    {
  549.    register int i;
  550.    VECTOR point;
  551.    register DBL length, scalar, index;
  552.  
  553.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  554.       point.x = x;
  555.       point.y = y;
  556.       point.z = z;
  557.       VSub (point, point, Wave_Sources[i]);
  558.       VDot (length, point, point);
  559.       if (length == 0.0)
  560.          length = 1.0;
  561.  
  562.       length = sqrt(length);
  563.       index = length*Object->Object_Texture->Frequency
  564.                     + Object -> Object_Texture->Phase;
  565.       scalar = cycloidal (index) * Object -> Object_Texture->Bump_Amount;
  566.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  567.       VAdd (*Vector, *Vector, point);
  568.       }
  569.    VNormalize (*Vector, *Vector);
  570.    }
  571.  
  572. void waves (x, y, z, Object, Vector)
  573.    DBL x, y, z;
  574.    OBJECT *Object;
  575.    VECTOR *Vector;
  576.    {
  577.    register int i;
  578.    VECTOR point;
  579.    register DBL length, scalar, index, sinValue ;
  580.  
  581.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  582.       point.x = x;
  583.       point.y = y;
  584.       point.z = z;
  585.       VSub (point, point, Wave_Sources[i]);
  586.       VDot (length, point, point);
  587.       if (length == 0.0)
  588.          length = 1.0;
  589.  
  590.       length = sqrt(length);
  591.       index = (length * Object -> Object_Texture->Frequency * frequency[i])
  592.                    + Object -> Object_Texture->Phase;
  593.       sinValue = cycloidal (index);
  594.  
  595.       scalar =  sinValue * Object -> Object_Texture->Bump_Amount /
  596.                   frequency[i];
  597.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  598.       VAdd (*Vector, *Vector, point);
  599.       }
  600.    VNormalize (*Vector, *Vector);
  601.    }
  602.  
  603. int wood (x, y, z, Object, colour)
  604.    DBL x, y, z;
  605.    OBJECT *Object;
  606.    COLOUR *colour;
  607.    {
  608.    register DBL noise, length;
  609.    VECTOR WoodTurbulence;
  610.    VECTOR point;
  611.    COLOUR New_Colour;
  612.  
  613.    DTurbulence (&WoodTurbulence, x, y, z);
  614.  
  615.    point.x = cycloidal((x + WoodTurbulence.x)
  616.                * Object -> Object_Texture->Turbulence);
  617.    point.y = cycloidal((y + WoodTurbulence.y)
  618.                * Object -> Object_Texture->Turbulence);
  619.    point.z = 0.0;
  620.  
  621.    point.x += x;
  622.    point.y += y;
  623.    point.z += z;
  624.  
  625.    VLength (length, point);
  626.  
  627.    noise = Triangle_Wave(length);
  628.  
  629.    if (Object -> Object_Texture->Colour_Map != NULL) {
  630.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  631.       colour -> Red += New_Colour.Red;
  632.       colour -> Green += New_Colour.Green;
  633.       colour -> Blue += New_Colour.Blue;
  634.       colour -> Alpha += New_Colour.Alpha;
  635.       return (0);
  636.       }
  637.  
  638.    if (noise > 0.6) {
  639.       colour -> Red += 0.4;
  640.       colour -> Green += 0.133;
  641.       colour -> Blue += 0.066;
  642.       }
  643.   else {
  644.       colour -> Red += 0.666;
  645.       colour -> Green += 0.312;
  646.       colour -> Blue += 0.2;
  647.       }
  648.       return (0);
  649.    }
  650.  
  651.  
  652. void checker (x, y, z, Object, colour)
  653.    DBL x, y, z;
  654.    OBJECT *Object;
  655.    COLOUR *colour;
  656.    {
  657.    int brkindx;
  658.  
  659.    brkindx = (int) FLOOR(x) + (int) FLOOR(z);
  660.  
  661.    if (brkindx & 1)
  662.       *colour = Object -> Object_Texture->Colour1;
  663.    else
  664.       *colour = Object -> Object_Texture->Colour2;
  665.    return;
  666.    }
  667.  
  668. /*
  669.    Ideas garnered from SIGGRAPH '85 Volume 19 Number 3, "An Image Synthesizer"
  670.    By Ken Perlin.
  671. */
  672.  
  673.  
  674. /*    
  675.     With a little reflectivity and brilliance, can look like organ pipe
  676.     metal.   With tiny scaling values can look like masonry or concrete.
  677.     Works with color maps, supposedly. (?)
  678. */
  679.  
  680. void spotted (x, y, z, Object, Colour)
  681.    DBL x, y, z;
  682.    OBJECT *Object;
  683.    COLOUR *Colour;
  684.    {
  685.    register DBL noise;
  686.    COLOUR New_Colour;
  687.  
  688.    noise = Noise (x, y, z);
  689.  
  690.    if (Object -> Object_Texture->Colour_Map != NULL)
  691.       {
  692.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  693.       Colour -> Red += New_Colour.Red;
  694.       Colour -> Green += New_Colour.Green;
  695.       Colour -> Blue += New_Colour.Blue;
  696.       Colour -> Alpha += New_Colour.Alpha;
  697.       return;
  698.       }
  699.  
  700.    Colour -> Red += noise;             /* "white (1.0) * noise" */
  701.    Colour -> Green += noise;
  702.    Colour -> Blue += noise;
  703.  
  704.    return;
  705.    }
  706.  
  707. void bumps (x, y, z, Object, normal)
  708.    DBL x, y, z;
  709.    OBJECT *Object;
  710.    VECTOR *normal;
  711.    {
  712.    VECTOR bump_turb;
  713.  
  714.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  715.       return;                            /* why are we here?? */
  716.  
  717.    DNoise (&bump_turb, x, y, z);         /* Get Normal Displacement Val. */
  718.    VScale(bump_turb, bump_turb, Object->Object_Texture->Bump_Amount);
  719.    VAdd (*normal, *normal, bump_turb);   /* displace "normal" */
  720.    VNormalize (*normal, *normal);        /* normalize normal! */
  721.    return;
  722.    }
  723.  
  724. /*
  725.    dents is similar to bumps, but uses noise() to control the amount of
  726.    dnoise() perturbation of the object normal...
  727. */
  728.  
  729. void dents (x, y, z, Object, normal)
  730.    DBL x, y, z;
  731.    OBJECT *Object;
  732.    VECTOR *normal;
  733.    {
  734.    VECTOR stucco_turb;
  735.    DBL noise;
  736.  
  737.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  738.       return;                           /* why are we here?? */
  739.  
  740.    noise = Noise (x, y, z);
  741.  
  742.    noise =  noise * noise * noise * Object->Object_Texture->Bump_Amount;
  743.  
  744.    DNoise (&stucco_turb, x, y, z);       /* Get Normal Displacement Val. */
  745.     
  746.    VScale (stucco_turb, stucco_turb, noise);
  747.    VAdd (*normal, *normal, stucco_turb); /* displace "normal" */
  748.    VNormalize (*normal, *normal);        /* normalize normal! */
  749.    return;
  750.    }
  751.  
  752.  
  753. void agate (x, y, z, Object, colour)
  754.    DBL x, y, z;
  755.    OBJECT *Object;
  756.    COLOUR *colour;
  757.    {
  758.    register DBL noise, hue;
  759.    COLOUR New_Colour;
  760.  
  761.    noise = cycloidal(1.3 * Turbulence(x, y, z) + 1.1 * z) + 1;
  762.    noise *= 0.5;
  763.    noise = pow(noise, 0.77);
  764.  
  765.    if (Object -> Object_Texture->Colour_Map != NULL)
  766.       {
  767.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  768.       colour -> Red += New_Colour.Red;
  769.       colour -> Green += New_Colour.Green;
  770.       colour -> Blue += New_Colour.Blue;
  771.       colour -> Alpha += New_Colour.Alpha;
  772.       return;
  773.       }
  774.  
  775.    hue = 1.0 - noise;
  776.  
  777.    if (noise < 0.5)
  778.       {
  779.       colour -> Red += (1.0 - (noise / 10));
  780.       colour -> Green += (1.0 - (noise / 5));
  781.       colour -> Blue += hue;
  782.       }
  783.    else if (noise < 0.6)
  784.       {
  785.       colour -> Red += 0.9;
  786.       colour -> Green += 0.7;
  787.       colour -> Blue += hue;
  788.       }
  789.    else
  790.       {
  791.       colour -> Red += (0.6 + hue);
  792.       colour -> Green += (0.3 + hue);
  793.       colour -> Blue += hue;
  794.       }
  795.    return;
  796.    }
  797.  
  798.  
  799. /*
  800.    Ideas garnered from the April 89 Byte Graphics Supplement on RenderMan,
  801.    refined from "The RenderMan Companion, by Steve Upstill of Pixar, (C) 1990
  802.    Addison-Wesley.
  803. */
  804.  
  805.  
  806. /*
  807.    wrinkles - This is my implementation of the dented() routine, using
  808.    a surface iterative fractal derived from DTurbulence.  This is a 3-D vers.
  809.    (thanks to DNoise()...) of the usual version using the singular Noise()...
  810.    Seems to look a lot like wrinkles, however... (hmmm)
  811. */
  812.  
  813. void wrinkles (x, y, z, Object, normal)
  814.    DBL x, y, z;
  815.    OBJECT *Object;
  816.    VECTOR *normal;
  817.    {
  818.    register int i;
  819.    register DBL scale = 1.0;
  820.    VECTOR result, value;
  821.  
  822.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  823.       return;                                /* why are we here?? */
  824.  
  825.    result.x = 0.0;
  826.    result.y = 0.0;
  827.    result.z = 0.0;
  828.  
  829.    for (i = 0; i < 10 ; scale *= 2.0, i++)
  830.       {
  831.       DNoise(&value, x * scale, y * scale, z * scale);   /* * scale,*/
  832.       result.x += FABS (value.x / scale);
  833.       result.y += FABS (value.y / scale);
  834.       result.z += FABS (value.z / scale);
  835.       }
  836.  
  837.    VScale(result, result, Object->Object_Texture->Bump_Amount);
  838.    VAdd (*normal, *normal, result);             /* displace "normal" */
  839.    VNormalize (*normal, *normal);               /* normalize normal! */
  840.    return;
  841.    }
  842.  
  843.  
  844. /*
  845.    Granite - kind of a union of the "spotted" and the "dented" textures,
  846.    using a 1/f fractal noise function for color values.  Typically used
  847.    w/ small scaling values.  Should work with colour maps for pink granite...
  848. */
  849.  
  850.  
  851. void granite (x, y, z, Object, Colour)
  852.    DBL x, y, z;
  853.    OBJECT *Object;
  854.    COLOUR *Colour;
  855.    {
  856.    register int i;
  857.    register DBL temp, noise = 0.0, freq = 1.0;
  858.    COLOUR New_Colour;
  859.  
  860.    for (i = 0; i < 6 ; freq *= 2.0, i++)
  861.       {
  862.       temp = 0.5 - Noise (x * 4 * freq, y * 4 * freq, z * 4 * freq);
  863.       temp = FABS(temp);
  864.       noise += temp / freq;
  865.       }
  866.  
  867.    if (Object -> Object_Texture->Colour_Map != NULL)
  868.       {
  869.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  870.       Colour -> Red += New_Colour.Red;
  871.       Colour -> Green += New_Colour.Green;
  872.       Colour -> Blue += New_Colour.Blue;
  873.       Colour -> Alpha += New_Colour.Alpha;
  874.       return;
  875.       }
  876.  
  877.    Colour -> Red += noise;                  /* "white (1.0) * noise" */
  878.    Colour -> Green += noise;
  879.    Colour -> Blue += noise;
  880.  
  881.    return;
  882.    }
  883.  
  884. /*
  885.    Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley)
  886. */
  887.  
  888.  
  889. /*
  890.    Color Gradient Texture - gradient based on the fractional values of x, y or
  891.    z, based on whether or not the given directional vector is a 1.0 or a 0.0.
  892.    Note - ONLY works with colour maps, preferably one that is circular - i.e.
  893.    the last defined colour (value 1.001) is the same as the first colour (with
  894.    a value of 0.0) in the map.  The basic concept of this is from DBW Render,
  895.    but Dave Wecker's only supports simple Y axis gradients.
  896. */
  897.  
  898. void gradient (x, y, z, Object, Colour)
  899.    DBL x, y, z;
  900.    OBJECT *Object;
  901.    COLOUR *Colour;
  902.    {
  903.    COLOUR New_Colour;
  904.    DBL value = 0.0, turb;
  905.    VECTOR GradTurbulence;
  906.  
  907.    if ((turb = Object->Object_Texture->Turbulence) != 0.0)
  908.       {
  909.       DTurbulence (&GradTurbulence, x, y, z);
  910.       x += GradTurbulence.x * turb;
  911.       y += GradTurbulence.y * turb;
  912.       z += GradTurbulence.z * turb;
  913.       }
  914.  
  915.    if (Object -> Object_Texture->Colour_Map == NULL)
  916.       return;
  917.    if (Object -> Object_Texture->Texture_Gradient.x != 0.0)
  918.       {
  919.       x = FABS(x);
  920.       value += x - FLOOR(x);    /* obtain fractional X component */
  921.       }
  922.    if (Object -> Object_Texture->Texture_Gradient.y != 0.0)
  923.       {
  924.       y = FABS(y);
  925.       value += y - FLOOR(y);    /* obtain fractional Y component */
  926.    }
  927.    if (Object -> Object_Texture->Texture_Gradient.z != 0.0)
  928.       {
  929.       z = FABS(z);
  930.       value += z - FLOOR(z);    /* obtain fractional Z component */
  931.       }
  932.    value = ((value > 1.0) ? fmod(value, 1.0) : value); /* clamp to 1.0 */
  933.    Compute_Colour(&New_Colour, Object->Object_Texture->Colour_Map, value);
  934.    Colour -> Red += New_Colour.Red;
  935.    Colour -> Green += New_Colour.Green;
  936.    Colour -> Blue += New_Colour.Blue;
  937.    Colour -> Alpha += New_Colour.Alpha;
  938.    return;
  939.    }
  940.  
  941. /*
  942.    2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  943.        
  944.    Simplistic method of object image projection devised by DKB and AAC.
  945.  
  946.    1. Transform texture in 3-D space if requested.
  947.    2. Determine local object 2-d coords from 3-d coords by <X Y Z> triple.
  948.    3. Return pixel color value at that position on the 2-d plane of "Image".
  949.    3. Map colour value in Image [0..255] to a more normal colour range [0..1].
  950. */
  951.  
  952. void texture_map (x, y, z, Object, colour)
  953.    DBL x, y, z;
  954.    OBJECT *Object;
  955.    COLOUR *colour;
  956.    {
  957.    /* determine local object 2-d coords from 3-d coords */
  958.    /* "unwrap" object 2-d coord onto flat 2-d plane */
  959.    /* return pixel color value at that posn on 2-d plane */
  960.  
  961.    int xcoor, ycoor, index;
  962.    TEXTURE *local_texture;
  963.    DBL width, height, turb;
  964.    VECTOR TextureTurbulence;
  965.  
  966.    local_texture = Object->Object_Texture;
  967.  
  968.    if ((turb = local_texture->Turbulence) != 0.0)
  969.       {
  970.       DTurbulence (&TextureTurbulence, x, y, z);
  971.       x += TextureTurbulence.x * turb;
  972.       y += TextureTurbulence.y * turb;
  973.       z += TextureTurbulence.z * turb;
  974.       }
  975.  
  976.    width = local_texture->Image->width;
  977.    height = local_texture->Image->height;
  978.  
  979.    if (local_texture -> Texture_Gradient.x != 0.0) {
  980.       if ((local_texture->Once_Flag) &&
  981.            ((x < 0.0) || (x > 1.0))) {
  982.          *colour = Object -> Object_Colour;
  983.          return;
  984.          }
  985.  
  986.       if (local_texture -> Texture_Gradient.x > 0)
  987.          xcoor = (int) fmod (x * width, width);
  988.       else ycoor = (int) fmod (x * height, height);
  989.       }
  990.  
  991.    if (local_texture -> Texture_Gradient.y != 0.0) {
  992.       if ((local_texture->Once_Flag) &&
  993.            ((y < 0.0) || (y > 1.0))) {
  994.          *colour = Object -> Object_Colour;
  995.          return;
  996.          }
  997.  
  998.       if (local_texture -> Texture_Gradient.y > 0)
  999.          xcoor = (int) fmod (y * width, width);
  1000.       else ycoor = (int) fmod (y * height, height);
  1001.       }
  1002.  
  1003.    if (local_texture -> Texture_Gradient.z != 0.0) {
  1004.       if ((local_texture->Once_Flag) &&
  1005.            ((z < 0.0) || (z > 1.0))) {
  1006.          *colour = Object -> Object_Colour;
  1007.          return;
  1008.          }
  1009.  
  1010.       if (local_texture -> Texture_Gradient.z > 0)
  1011.          xcoor = (int) fmod (z * width, width);
  1012.       else ycoor = (int) fmod (z * height, height);
  1013.       }
  1014.  
  1015.    if (xcoor < 0)
  1016.       xcoor += local_texture->Image->iwidth;
  1017.    if (ycoor < 0)
  1018.       ycoor += local_texture->Image->iheight;
  1019.  
  1020.    if ((xcoor >= local_texture->Image->iwidth) ||
  1021.        (ycoor >= local_texture->Image->iheight) ||
  1022.        (xcoor < 0) || (ycoor < 0))
  1023.      printf ("Out of range\n");
  1024.  
  1025.    index = (unsigned)ycoor* (unsigned)local_texture->Image->iwidth +
  1026.            (unsigned)xcoor;
  1027.  
  1028.    Make_Colour (colour, (DBL) local_texture->Image->red[index]/255.0,
  1029.                         (DBL) local_texture->Image->green[index]/255.0,
  1030.                         (DBL) local_texture->Image->blue[index]/255.0);
  1031.    }
  1032.  
  1033.