home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine 1996 / ARCHIVE_96.iso / discs / shareware / share_43 / source / c / TEXTURE < prev    next >
Text File  |  1991-08-22  |  30KB  |  1,034 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.    if ((hashTable = (short int *) malloc(4096*sizeof(short int))) == NULL) {
  183.       printf("Cannot allocate memory for hash table\n");
  184.       exit(1);
  185.       }
  186.    for (i = 0; i < 4096; i++)
  187.       hashTable[i] = i;
  188.    for (i = 4095; i >= 0; i--) {
  189.       j = rand() % 4096;
  190.       temp = hashTable[i];
  191.       hashTable[i] = hashTable[j];
  192.       hashTable[j] = temp;
  193.       }
  194.    }
  195.  
  196.  
  197. /* modified by AAC to work properly with little bitty integers (16 bits) */
  198.  
  199. void InitRTable()
  200.    {
  201.    int i;
  202.    VECTOR rp;
  203.  
  204.    InitTextureTable();
  205.  
  206.    for (i = 0; i < MAXSIZE; i++)
  207.       {
  208.       rp.x = rp.y = rp.z = (DBL)i;
  209.       RTable[i] = (unsigned int) R(&rp) * REALSCALE - 1.0;
  210.       }
  211.    }
  212.  
  213.  
  214. int R(v)
  215.    VECTOR *v;
  216.    {
  217.    v->x *= .12345;
  218.    v->y *= .12345;
  219.    v->z *= .12345;
  220.  
  221.    return (Crc16((char *) v, sizeof(VECTOR)));
  222.    }
  223.  
  224. /*
  225.  * Note that passing a VECTOR array to Crc16 and interpreting it as
  226.  * an array of chars means that machines with different floating-point
  227.  * representation schemes will evaluate Noise(point) differently.
  228.  */
  229.  
  230. int Crc16(buf, count)
  231.    register char *buf;
  232.    register int  count;
  233.    {
  234.    register unsigned short crc = 0;
  235.  
  236.    while (count--)
  237.       crc = (crc >> 8) ^ crctab[ (unsigned char) (crc ^ *buf++) ];
  238.  
  239.    return ((int) crc);
  240.    }
  241.  
  242.  
  243. /*
  244.     Robert's Skinner's Perlin-style "Noise" function - modified by AAC
  245.     to ensure uniformly distributed clamped values between 0 and 1.0...
  246. */
  247.  
  248. void setup_lattice(x, y, z, ix, iy, iz, jx, jy, jz, sx, sy, sz, tx, ty, tz)
  249.    DBL *x, *y, *z, *sx, *sy, *sz, *tx, *ty, *tz;
  250.    long *ix, *iy, *iz, *jx, *jy, *jz;
  251.    {
  252.    /* ensures the values are positive. */
  253.    *x -= MINX;
  254.    *y -= MINY;
  255.    *z -= MINZ;
  256.  
  257.    /* its equivalent integer lattice point. */
  258.    *ix = (long)*x; *iy = (long)*y; *iz = (long)*z;
  259.    *jx = *ix + 1; *jy = *iy + 1; *jz = *iz + 1;
  260.  
  261.    *sx = SCURVE(*x - *ix); *sy = SCURVE(*y - *iy); *sz = SCURVE(*z - *iz);
  262.  
  263.    /* the complement values of sx,sy,sz */
  264.    *tx = 1.0 - *sx; *ty = 1.0 - *sy; *tz = 1.0 - *sz;
  265.    return;
  266.    }
  267.  
  268.  
  269. DBL Noise(x, y, z)
  270.    DBL x, y, z;
  271.    {
  272.    long ix, iy, iz, jx, jy, jz;
  273.    DBL sx, sy, sz, tx, ty, tz;
  274.    DBL sum;
  275.    short m;
  276.  
  277.  
  278.    Calls_To_Noise++;
  279.    
  280.    setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);
  281.  
  282.    /*
  283.     *  interpolate!
  284.     */
  285.    m = Hash3d( ix, iy, iz ) & 0xFF;
  286.    sum = INCRSUM(m,(tx*ty*tz),(x-ix),(y-iy),(z-iz));
  287.  
  288.    m = Hash3d( jx, iy, iz ) & 0xFF;
  289.    sum += INCRSUM(m,(sx*ty*tz),(x-jx),(y-iy),(z-iz));
  290.  
  291.    m = Hash3d( ix, jy, iz ) & 0xFF;
  292.    sum += INCRSUM(m,(tx*sy*tz),(x-ix),(y-jy),(z-iz));
  293.  
  294.    m = Hash3d( jx, jy, iz ) & 0xFF;
  295.    sum += INCRSUM(m,(sx*sy*tz),(x-jx),(y-jy),(z-iz));
  296.  
  297.    m = Hash3d( ix, iy, jz ) & 0xFF;
  298.    sum += INCRSUM(m,(tx*ty*sz),(x-ix),(y-iy),(z-jz));
  299.  
  300.    m = Hash3d( jx, iy, jz ) & 0xFF;
  301.    sum += INCRSUM(m,(sx*ty*sz),(x-jx),(y-iy),(z-jz));
  302.  
  303.    m = Hash3d( ix, jy, jz ) & 0xFF;
  304.    sum += INCRSUM(m,(tx*sy*sz),(x-ix),(y-jy),(z-jz));
  305.  
  306.    m = Hash3d( jx, jy, jz ) & 0xFF;
  307.    sum += INCRSUM(m,(sx*sy*sz),(x-jx),(y-jy),(z-jz));
  308.  
  309.    sum = sum + 0.5;          /* range at this point -0.5 - 0.5... */
  310.     
  311.    if (sum < 0.0)
  312.       sum = 0.0;
  313.    if (sum > 1.0)
  314.       sum = 1.0;
  315.  
  316.    return (sum);
  317.    }
  318.  
  319.  
  320. /*
  321.        Vector-valued version of "Noise"
  322. */
  323.  
  324. void DNoise(result, x, y, z)
  325.    VECTOR *result;
  326.    DBL x, y, z;
  327.    {
  328.    long ix, iy, iz, jx, jy, jz;
  329.    DBL px, py, pz, s;
  330.    DBL sx, sy, sz, tx, ty, tz;
  331.    short m;
  332.  
  333.    Calls_To_DNoise++;
  334.  
  335.    setup_lattice(&x, &y, &z, &ix, &iy, &iz, &jx, &jy, &jz, &sx, &sy, &sz, &tx, &ty, &tz);
  336.  
  337.    /*
  338.     *  interpolate!
  339.     */
  340.    m = Hash3d( ix, iy, iz ) & 0xFF;
  341.    px = x-ix;  py = y-iy;  pz = z-iz;
  342.    s = tx*ty*tz;
  343.    result->x = INCRSUM(m,s,px,py,pz);
  344.    result->y = INCRSUM(m+4,s,px,py,pz);
  345.    result->z = INCRSUM(m+8,s,px,py,pz);
  346.  
  347.    m = Hash3d( jx, iy, iz ) & 0xFF;
  348.    px = x-jx;
  349.    s = sx*ty*tz;
  350.    result->x += INCRSUM(m,s,px,py,pz);
  351.    result->y += INCRSUM(m+4,s,px,py,pz);
  352.    result->z += INCRSUM(m+8,s,px,py,pz);
  353.  
  354.    m = Hash3d( jx, jy, iz ) & 0xFF;
  355.    py = y-jy;
  356.    s = sx*sy*tz;
  357.    result->x += INCRSUM(m,s,px,py,pz);
  358.    result->y += INCRSUM(m+4,s,px,py,pz);
  359.    result->z += INCRSUM(m+8,s,px,py,pz);
  360.  
  361.    m = Hash3d( ix, jy, iz ) & 0xFF;
  362.    px = x-ix;
  363.    s = tx*sy*tz;
  364.    result->x += INCRSUM(m,s,px,py,pz);
  365.    result->y += INCRSUM(m+4,s,px,py,pz);
  366.    result->z += INCRSUM(m+8,s,px,py,pz);
  367.  
  368.    m = Hash3d( ix, jy, jz ) & 0xFF;
  369.    pz = z-jz;
  370.    s = tx*sy*sz;
  371.    result->x += INCRSUM(m,s,px,py,pz);
  372.    result->y += INCRSUM(m+4,s,px,py,pz);
  373.    result->z += INCRSUM(m+8,s,px,py,pz);
  374.  
  375.    m = Hash3d( jx, jy, jz ) & 0xFF;
  376.    px = x-jx;
  377.    s = sx*sy*sz;
  378.    result->x += INCRSUM(m,s,px,py,pz);
  379.    result->y += INCRSUM(m+4,s,px,py,pz);
  380.    result->z += INCRSUM(m+8,s,px,py,pz);
  381.  
  382.    m = Hash3d( jx, iy, jz ) & 0xFF;
  383.    py = y-iy;
  384.    s = sx*ty*sz;
  385.    result->x += INCRSUM(m,s,px,py,pz);
  386.    result->y += INCRSUM(m+4,s,px,py,pz);
  387.    result->z += INCRSUM(m+8,s,px,py,pz);
  388.  
  389.    m = Hash3d( ix, iy, jz ) & 0xFF;
  390.    px = x-ix;
  391.    s = tx*ty*sz;
  392.    result->x += INCRSUM(m,s,px,py,pz);
  393.    result->y += INCRSUM(m+4,s,px,py,pz);
  394.    result->z += INCRSUM(m+8,s,px,py,pz);
  395.    }
  396.  
  397. DBL Turbulence (x, y, z)
  398.    DBL x, y, z;
  399.    {
  400.    register DBL pixelSize = 0.1;
  401.    register DBL t = 0.0;
  402.    register DBL scale, value;
  403.  
  404.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  405.       value = Noise (x/scale, y/scale, z/scale);
  406.       t += FABS (value) * scale;
  407.       }
  408.    return (t);
  409.    }
  410.  
  411. void DTurbulence (result, x, y, z)
  412.    VECTOR *result;
  413.    DBL x, y, z;
  414.    {
  415.    register DBL pixelSize = 0.01;
  416.    register DBL scale;
  417.    VECTOR value;
  418.  
  419.    result -> x = 0.0;
  420.    result -> y = 0.0;
  421.    result -> z = 0.0;
  422.  
  423.    value.x = value.y = value.z = 0.0;
  424.  
  425.    for (scale = 1.0 ; scale > pixelSize ; scale *= 0.5) {
  426.       DNoise(&value, x/scale, y/scale, z/scale);
  427.       result -> x += value.x * scale;
  428.       result -> y += value.y * scale;
  429.       result -> z += value.z * scale;
  430.       }
  431.    }
  432.  
  433. DBL cycloidal (value)
  434.    DBL value;
  435.    {
  436.  
  437.    if (value >= 0.0)
  438.       return (sintab [(int)((value - floor (value)) * SINTABSIZE)]);
  439.    else
  440.       return (0.0 - sintab [(int)((0.0 - (value + floor (0.0 - value)))
  441.                                     * SINTABSIZE)]);
  442.    }
  443.  
  444.  
  445. DBL Triangle_Wave (value)
  446.    DBL value;
  447.    {
  448.    register DBL offset;
  449.  
  450.    if (value >= 0.0) offset = value - floor(value);
  451.    else offset = value - (-1.0 - floor(FABS(value)));
  452.  
  453.    if (offset >= 0.5) return (2.0 * (1.0 - offset));
  454.    else return (2.0 * offset);
  455.    }
  456.  
  457.  
  458. int Bozo (x, y, z, Object, Colour)
  459. DBL x, y, z;
  460. OBJECT *Object;
  461. COLOUR *Colour;
  462.    {
  463.    register DBL noise, turb;
  464.    COLOUR New_Colour;
  465.    VECTOR BozoTurbulence;
  466.  
  467.  
  468.    if ((turb = Object->Object_Texture->Turbulence) != 0.0)
  469.       {
  470.       DTurbulence (&BozoTurbulence, x, y, z);
  471.       x += BozoTurbulence.x * turb;
  472.       y += BozoTurbulence.y * turb;
  473.       z += BozoTurbulence.z * turb;
  474.       }
  475.  
  476.    noise = Noise (x, y, z);
  477.  
  478.    if (Object -> Object_Texture->Colour_Map != NULL) {
  479.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  480.       Colour -> Red += New_Colour.Red;
  481.       Colour -> Green += New_Colour.Green;
  482.       Colour -> Blue += New_Colour.Blue;
  483.       Colour -> Alpha += New_Colour.Alpha;
  484.       return (0);
  485.       }
  486.  
  487.    if (noise < 0.4) {
  488.       Colour -> Red += 1.0;
  489.       Colour -> Green += 1.0;
  490.       Colour -> Blue += 1.0;
  491.       return (0);
  492.       }
  493.  
  494.    if (noise < 0.6) {
  495.       Colour -> Green += 1.0;
  496.       return (0);
  497.       }
  498.  
  499.    if (noise < 0.8) {
  500.       Colour -> Blue += 1.0;
  501.       return (0);
  502.       }
  503.  
  504.    Colour -> Red += 1.0;
  505.    return (0);
  506.    }
  507.  
  508. int marble (x, y, z, Object, colour)
  509.    DBL x, y, z;
  510.    OBJECT *Object;
  511.    COLOUR *colour;
  512.    {
  513.    register DBL noise, hue;
  514.    COLOUR New_Colour;
  515.  
  516.    noise = Triangle_Wave(x + Turbulence(x, y, z) * Object -> Object_Texture->Turbulence);
  517.  
  518.    if (Object -> Object_Texture->Colour_Map != NULL)
  519.       {
  520.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  521.       colour -> Red += New_Colour.Red;
  522.       colour -> Green += New_Colour.Green;
  523.       colour -> Blue += New_Colour.Blue;
  524.       colour -> Alpha += New_Colour.Alpha;
  525.       return (0);
  526.       }
  527.  
  528.    if (noise < 0.0)
  529.       {
  530.       colour -> Red += 0.9;
  531.       colour -> Green += 0.8;
  532.       colour -> Blue += 0.8;
  533.       }
  534.    else if (noise < 0.9)
  535.       {
  536.       colour -> Red += 0.9;
  537.       hue = 0.8 - noise * 0.8;
  538.       colour -> Green += hue;
  539.       colour -> Blue += hue;
  540.       }
  541.    return (0);
  542.    }
  543.  
  544.  
  545. void ripples (x, y, z, Object, Vector)
  546.    DBL x, y, z;
  547.    OBJECT *Object;
  548.    VECTOR *Vector;
  549.    {
  550.    register int i;
  551.    VECTOR point;
  552.    register DBL length, scalar, index;
  553.  
  554.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  555.       point.x = x;
  556.       point.y = y;
  557.       point.z = z;
  558.       VSub (point, point, Wave_Sources[i]);
  559.       VDot (length, point, point);
  560.       if (length == 0.0)
  561.          length = 1.0;
  562.  
  563.       length = sqrt(length);
  564.       index = length*Object->Object_Texture->Frequency
  565.                     + Object -> Object_Texture->Phase;
  566.       scalar = cycloidal (index) * Object -> Object_Texture->Bump_Amount;
  567.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  568.       VAdd (*Vector, *Vector, point);
  569.       }
  570.    VNormalize (*Vector, *Vector);
  571.    }
  572.  
  573. void waves (x, y, z, Object, Vector)
  574.    DBL x, y, z;
  575.    OBJECT *Object;
  576.    VECTOR *Vector;
  577.    {
  578.    register int i;
  579.    VECTOR point;
  580.    register DBL length, scalar, index, sinValue ;
  581.  
  582.    for (i = 0 ; i < NUMBER_OF_WAVES ; i++) {
  583.       point.x = x;
  584.       point.y = y;
  585.       point.z = z;
  586.       VSub (point, point, Wave_Sources[i]);
  587.       VDot (length, point, point);
  588.       if (length == 0.0)
  589.          length = 1.0;
  590.  
  591.       length = sqrt(length);
  592.       index = (length * Object -> Object_Texture->Frequency * frequency[i])
  593.                    + Object -> Object_Texture->Phase;
  594.       sinValue = cycloidal (index);
  595.  
  596.       scalar =  sinValue * Object -> Object_Texture->Bump_Amount /
  597.                   frequency[i];
  598.       VScale (point, point, scalar/length/(DBL)NUMBER_OF_WAVES);
  599.       VAdd (*Vector, *Vector, point);
  600.       }
  601.    VNormalize (*Vector, *Vector);
  602.    }
  603.  
  604. int wood (x, y, z, Object, colour)
  605.    DBL x, y, z;
  606.    OBJECT *Object;
  607.    COLOUR *colour;
  608.    {
  609.    register DBL noise, length;
  610.    VECTOR WoodTurbulence;
  611.    VECTOR point;
  612.    COLOUR New_Colour;
  613.  
  614.    DTurbulence (&WoodTurbulence, x, y, z);
  615.  
  616.    point.x = cycloidal((x + WoodTurbulence.x)
  617.                * Object -> Object_Texture->Turbulence);
  618.    point.y = cycloidal((y + WoodTurbulence.y)
  619.                * Object -> Object_Texture->Turbulence);
  620.    point.z = 0.0;
  621.  
  622.    point.x += x;
  623.    point.y += y;
  624.    point.z += z;
  625.  
  626.    VLength (length, point);
  627.  
  628.    noise = Triangle_Wave(length);
  629.  
  630.    if (Object -> Object_Texture->Colour_Map != NULL) {
  631.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  632.       colour -> Red += New_Colour.Red;
  633.       colour -> Green += New_Colour.Green;
  634.       colour -> Blue += New_Colour.Blue;
  635.       colour -> Alpha += New_Colour.Alpha;
  636.       return (0);
  637.       }
  638.  
  639.    if (noise > 0.6) {
  640.       colour -> Red += 0.4;
  641.       colour -> Green += 0.133;
  642.       colour -> Blue += 0.066;
  643.       }
  644.   else {
  645.       colour -> Red += 0.666;
  646.       colour -> Green += 0.312;
  647.       colour -> Blue += 0.2;
  648.       }
  649.       return (0);
  650.    }
  651.  
  652.  
  653. void checker (x, y, z, Object, colour)
  654.    DBL x, y, z;
  655.    OBJECT *Object;
  656.    COLOUR *colour;
  657.    {
  658.    int brkindx;
  659.  
  660.    brkindx = (int) FLOOR(x) + (int) FLOOR(z);
  661.  
  662.    if (brkindx & 1)
  663.       *colour = Object -> Object_Texture->Colour1;
  664.    else
  665.       *colour = Object -> Object_Texture->Colour2;
  666.    return;
  667.    }
  668.  
  669. /*
  670.    Ideas garnered from SIGGRAPH '85 Volume 19 Number 3, "An Image Synthesizer"
  671.    By Ken Perlin.
  672. */
  673.  
  674.  
  675. /*    
  676.     With a little reflectivity and brilliance, can look like organ pipe
  677.     metal.   With tiny scaling values can look like masonry or concrete.
  678.     Works with color maps, supposedly. (?)
  679. */
  680.  
  681. void spotted (x, y, z, Object, Colour)
  682.    DBL x, y, z;
  683.    OBJECT *Object;
  684.    COLOUR *Colour;
  685.    {
  686.    register DBL noise;
  687.    COLOUR New_Colour;
  688.  
  689.    noise = Noise (x, y, z);
  690.  
  691.    if (Object -> Object_Texture->Colour_Map != NULL)
  692.       {
  693.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  694.       Colour -> Red += New_Colour.Red;
  695.       Colour -> Green += New_Colour.Green;
  696.       Colour -> Blue += New_Colour.Blue;
  697.       Colour -> Alpha += New_Colour.Alpha;
  698.       return;
  699.       }
  700.  
  701.    Colour -> Red += noise;             /* "white (1.0) * noise" */
  702.    Colour -> Green += noise;
  703.    Colour -> Blue += noise;
  704.  
  705.    return;
  706.    }
  707.  
  708. void bumps (x, y, z, Object, normal)
  709.    DBL x, y, z;
  710.    OBJECT *Object;
  711.    VECTOR *normal;
  712.    {
  713.    VECTOR bump_turb;
  714.  
  715.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  716.       return;                            /* why are we here?? */
  717.  
  718.    DNoise (&bump_turb, x, y, z);         /* Get Normal Displacement Val. */
  719.    VScale(bump_turb, bump_turb, Object->Object_Texture->Bump_Amount);
  720.    VAdd (*normal, *normal, bump_turb);   /* displace "normal" */
  721.    VNormalize (*normal, *normal);        /* normalize normal! */
  722.    return;
  723.    }
  724.  
  725. /*
  726.    dents is similar to bumps, but uses noise() to control the amount of
  727.    dnoise() perturbation of the object normal...
  728. */
  729.  
  730. void dents (x, y, z, Object, normal)
  731.    DBL x, y, z;
  732.    OBJECT *Object;
  733.    VECTOR *normal;
  734.    {
  735.    VECTOR stucco_turb;
  736.    DBL noise;
  737.  
  738.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  739.       return;                           /* why are we here?? */
  740.  
  741.    noise = Noise (x, y, z);
  742.  
  743.    noise =  noise * noise * noise * Object->Object_Texture->Bump_Amount;
  744.  
  745.    DNoise (&stucco_turb, x, y, z);       /* Get Normal Displacement Val. */
  746.     
  747.    VScale (stucco_turb, stucco_turb, noise);
  748.    VAdd (*normal, *normal, stucco_turb); /* displace "normal" */
  749.    VNormalize (*normal, *normal);        /* normalize normal! */
  750.    return;
  751.    }
  752.  
  753.  
  754. void agate (x, y, z, Object, colour)
  755.    DBL x, y, z;
  756.    OBJECT *Object;
  757.    COLOUR *colour;
  758.    {
  759.    register DBL noise, hue;
  760.    COLOUR New_Colour;
  761.  
  762.    noise = cycloidal(1.3 * Turbulence(x, y, z) + 1.1 * z) + 1;
  763.    noise *= 0.5;
  764.    noise = pow(noise, 0.77);
  765.  
  766.    if (Object -> Object_Texture->Colour_Map != NULL)
  767.       {
  768.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  769.       colour -> Red += New_Colour.Red;
  770.       colour -> Green += New_Colour.Green;
  771.       colour -> Blue += New_Colour.Blue;
  772.       colour -> Alpha += New_Colour.Alpha;
  773.       return;
  774.       }
  775.  
  776.    hue = 1.0 - noise;
  777.  
  778.    if (noise < 0.5)
  779.       {
  780.       colour -> Red += (1.0 - (noise / 10));
  781.       colour -> Green += (1.0 - (noise / 5));
  782.       colour -> Blue += hue;
  783.       }
  784.    else if (noise < 0.6)
  785.       {
  786.       colour -> Red += 0.9;
  787.       colour -> Green += 0.7;
  788.       colour -> Blue += hue;
  789.       }
  790.    else
  791.       {
  792.       colour -> Red += (0.6 + hue);
  793.       colour -> Green += (0.3 + hue);
  794.       colour -> Blue += hue;
  795.       }
  796.    return;
  797.    }
  798.  
  799.  
  800. /*
  801.    Ideas garnered from the April 89 Byte Graphics Supplement on RenderMan,
  802.    refined from "The RenderMan Companion, by Steve Upstill of Pixar, (C) 1990
  803.    Addison-Wesley.
  804. */
  805.  
  806.  
  807. /*
  808.    wrinkles - This is my implementation of the dented() routine, using
  809.    a surface iterative fractal derived from DTurbulence.  This is a 3-D vers.
  810.    (thanks to DNoise()...) of the usual version using the singular Noise()...
  811.    Seems to look a lot like wrinkles, however... (hmmm)
  812. */
  813.  
  814. void wrinkles (x, y, z, Object, normal)
  815.    DBL x, y, z;
  816.    OBJECT *Object;
  817.    VECTOR *normal;
  818.    {
  819.    register int i;
  820.    register DBL scale = 1.0;
  821.    VECTOR result, value;
  822.  
  823.    if (Object -> Object_Texture->Bump_Amount == 0.0)
  824.       return;                                /* why are we here?? */
  825.  
  826.    result.x = 0.0;
  827.    result.y = 0.0;
  828.    result.z = 0.0;
  829.  
  830.    for (i = 0; i < 10 ; scale *= 2.0, i++)
  831.       {
  832.       DNoise(&value, x * scale, y * scale, z * scale);   /* * scale,*/
  833.       result.x += FABS (value.x / scale);
  834.       result.y += FABS (value.y / scale);
  835.       result.z += FABS (value.z / scale);
  836.       }
  837.  
  838.    VScale(result, result, Object->Object_Texture->Bump_Amount);
  839.    VAdd (*normal, *normal, result);             /* displace "normal" */
  840.    VNormalize (*normal, *normal);               /* normalize normal! */
  841.    return;
  842.    }
  843.  
  844.  
  845. /*
  846.    Granite - kind of a union of the "spotted" and the "dented" textures,
  847.    using a 1/f fractal noise function for color values.  Typically used
  848.    w/ small scaling values.  Should work with colour maps for pink granite...
  849. */
  850.  
  851.  
  852. void granite (x, y, z, Object, Colour)
  853.    DBL x, y, z;
  854.    OBJECT *Object;
  855.    COLOUR *Colour;
  856.    {
  857.    register int i;
  858.    register DBL temp, noise = 0.0, freq = 1.0;
  859.    COLOUR New_Colour;
  860.  
  861.    for (i = 0; i < 6 ; freq *= 2.0, i++)
  862.       {
  863.       temp = 0.5 - Noise (x * 4 * freq, y * 4 * freq, z * 4 * freq);
  864.       temp = FABS(temp);
  865.       noise += temp / freq;
  866.       }
  867.  
  868.    if (Object -> Object_Texture->Colour_Map != NULL)
  869.       {
  870.       Compute_Colour (&New_Colour, Object->Object_Texture->Colour_Map, noise);
  871.       Colour -> Red += New_Colour.Red;
  872.       Colour -> Green += New_Colour.Green;
  873.       Colour -> Blue += New_Colour.Blue;
  874.       Colour -> Alpha += New_Colour.Alpha;
  875.       return;
  876.       }
  877.  
  878.    Colour -> Red += noise;                  /* "white (1.0) * noise" */
  879.    Colour -> Green += noise;
  880.    Colour -> Blue += noise;
  881.  
  882.    return;
  883.    }
  884.  
  885. /*
  886.    Further Ideas Garnered from "The RenderMan Companion" (Addison Wesley)
  887. */
  888.  
  889.  
  890. /*
  891.    Color Gradient Texture - gradient based on the fractional values of x, y or
  892.    z, based on whether or not the given directional vector is a 1.0 or a 0.0.
  893.    Note - ONLY works with colour maps, preferably one that is circular - i.e.
  894.    the last defined colour (value 1.001) is the same as the first colour (with
  895.    a value of 0.0) in the map.  The basic concept of this is from DBW Render,
  896.    but Dave Wecker's only supports simple Y axis gradients.
  897. */
  898.  
  899. void gradient (x, y, z, Object, Colour)
  900.    DBL x, y, z;
  901.    OBJECT *Object;
  902.    COLOUR *Colour;
  903.    {
  904.    COLOUR New_Colour;
  905.    DBL value = 0.0, turb;
  906.    VECTOR GradTurbulence;
  907.  
  908.    if ((turb = Object->Object_Texture->Turbulence) != 0.0)
  909.       {
  910.       DTurbulence (&GradTurbulence, x, y, z);
  911.       x += GradTurbulence.x * turb;
  912.       y += GradTurbulence.y * turb;
  913.       z += GradTurbulence.z * turb;
  914.       }
  915.  
  916.    if (Object -> Object_Texture->Colour_Map == NULL)
  917.       return;
  918.    if (Object -> Object_Texture->Texture_Gradient.x != 0.0)
  919.       {
  920.       x = FABS(x);
  921.       value += x - FLOOR(x);    /* obtain fractional X component */
  922.       }
  923.    if (Object -> Object_Texture->Texture_Gradient.y != 0.0)
  924.       {
  925.       y = FABS(y);
  926.       value += y - FLOOR(y);    /* obtain fractional Y component */
  927.    }
  928.    if (Object -> Object_Texture->Texture_Gradient.z != 0.0)
  929.       {
  930.       z = FABS(z);
  931.       value += z - FLOOR(z);    /* obtain fractional Z component */
  932.       }
  933.    value = ((value > 1.0) ? fmod(value, 1.0) : value); /* clamp to 1.0 */
  934.    Compute_Colour(&New_Colour, Object->Object_Texture->Colour_Map, value);
  935.    Colour -> Red += New_Colour.Red;
  936.    Colour -> Green += New_Colour.Green;
  937.    Colour -> Blue += New_Colour.Blue;
  938.    Colour -> Alpha += New_Colour.Alpha;
  939.    return;
  940.    }
  941.  
  942. /*
  943.    2-D to 3-D Procedural Texture Mapping of a Bitmapped Image onto an Object:
  944.        
  945.    Simplistic method of object image projection devised by DKB and AAC.
  946.  
  947.    1. Transform texture in 3-D space if requested.
  948.    2. Determine local object 2-d coords from 3-d coords by <X Y Z> triple.
  949.    3. Return pixel color value at that position on the 2-d plane of "Image".
  950.    3. Map colour value in Image [0..255] to a more normal colour range [0..1].
  951. */
  952.  
  953. void texture_map (x, y, z, Object, colour)
  954.    DBL x, y, z;
  955.    OBJECT *Object;
  956.    COLOUR *colour;
  957.    {
  958.    /* determine local object 2-d coords from 3-d coords */
  959.    /* "unwrap" object 2-d coord onto flat 2-d plane */
  960.    /* return pixel color value at that posn on 2-d plane */
  961.  
  962.    int xcoor = 0, ycoor = 0, index;
  963.    TEXTURE *local_texture;
  964.    DBL width, height, turb;
  965.    VECTOR TextureTurbulence;
  966.  
  967.    local_texture = Object->Object_Texture;
  968.  
  969.    if ((turb = local_texture->Turbulence) != 0.0)
  970.       {
  971.       DTurbulence (&TextureTurbulence, x, y, z);
  972.       x += TextureTurbulence.x * turb;
  973.       y += TextureTurbulence.y * turb;
  974.       z += TextureTurbulence.z * turb;
  975.       }
  976.  
  977.    width = local_texture->Image->width;
  978.    height = local_texture->Image->height;
  979.  
  980.    if (local_texture -> Texture_Gradient.x != 0.0) {
  981.       if ((local_texture->Once_Flag) &&
  982.            ((x < 0.0) || (x > 1.0))) {
  983.          *colour = Object -> Object_Colour;
  984.          return;
  985.          }
  986.  
  987.       if (local_texture -> Texture_Gradient.x > 0)
  988.          xcoor = (int) fmod (x * width, width);
  989.       else ycoor = (int) fmod (x * height, height);
  990.       }
  991.  
  992.    if (local_texture -> Texture_Gradient.y != 0.0) {
  993.       if ((local_texture->Once_Flag) &&
  994.            ((y < 0.0) || (y > 1.0))) {
  995.          *colour = Object -> Object_Colour;
  996.          return;
  997.          }
  998.  
  999.       if (local_texture -> Texture_Gradient.y > 0)
  1000.          xcoor = (int) fmod (y * width, width);
  1001.       else ycoor = (int) fmod (y * height, height);
  1002.       }
  1003.  
  1004.    if (local_texture -> Texture_Gradient.z != 0.0) {
  1005.       if ((local_texture->Once_Flag) &&
  1006.            ((z < 0.0) || (z > 1.0))) {
  1007.          *colour = Object -> Object_Colour;
  1008.          return;
  1009.          }
  1010.  
  1011.       if (local_texture -> Texture_Gradient.z > 0)
  1012.          xcoor = (int) fmod (z * width, width);
  1013.       else ycoor = (int) fmod (z * height, height);
  1014.       }
  1015.  
  1016.    if (xcoor < 0)
  1017.       xcoor += local_texture->Image->iwidth;
  1018.    if (ycoor < 0)
  1019.       ycoor += local_texture->Image->iheight;
  1020.  
  1021.    if ((xcoor >= local_texture->Image->iwidth) ||
  1022.        (ycoor >= local_texture->Image->iheight) ||
  1023.        (xcoor < 0) || (ycoor < 0))
  1024.      printf ("Out of range\n");
  1025.  
  1026.    index = (unsigned)ycoor* (unsigned)local_texture->Image->iwidth +
  1027.            (unsigned)xcoor;
  1028.  
  1029.    Make_Colour (colour, (DBL) local_texture->Image->red[index]/255.0,
  1030.                         (DBL) local_texture->Image->green[index]/255.0,
  1031.                         (DBL) local_texture->Image->blue[index]/255.0);
  1032.    }
  1033.  
  1034.