/*******************************************************
 SPIDER'S WEB INCLUDE FILE FOR PERSISTENCE OF VISION 3.x
 *******************************************************

 Created by Chris Colefax, 25 September 1997

 OVERVIEW: Creates a spider's web composed of thin threads arranged
 in a spokes and concentric circles pattern.

 USAGE: To create the default spider's web, just include this file
 inside an object statement, eg:

    object {#include "SPWeb.inc"}

 This creates a web 10 units in radius, that lies in the XY plane.
 To modify the web, insert the desired option declarations before
 including the file (see below for a complete list of options), eg:

    object {#declare web_type = 3
            #declare web_radius = 3
            #declare thread_thickness = .1
            #include "SPWeb.inc"}

 To transform the web, add the desired modifications after including the
 file, eg:

    object {#include "SPWeb.inc"
            scale .5 rotate <-45, -45, 0>
            clipped_by {box {<-3, -3, -3>, <3, 3, 3>}}
            texture {pigment {rgbt <1, 1, 1, .5>}}
            translate <-10, 20, 30>}

 To create multiple webs, you can either include the file (as above)
 multiple times (this will produce a different web each time), or declare
 the object and reuse it in the standard way, eg:

    #declare SpiderWeb = object {#include "SPWeb.inc"}
       object {SpiderWeb translate <45, -10, 20>}
       object {SpiderWeb scale .5}

 Note that declaring the object in this way requires less parsing time,
 but produces identical webs.

 OPTIONS: The following is a list of options (see above for usage) and
 their default values.

 -- OPTION ------- DEFAULT -- DESCRIPTION ---------------------------
  web_type              2     Sets the style of the web circles
                                 (choose from 1, 2, or 3)
  web_radius           10     Sets the overall radius of the web
  web_spokes_count      8     Sets the number of spokes in the web
  web_circles_count     4     Sets the number of circles in the web
  web_circles_radius    8     Sets the overall radius of the web circles
  thread_thickness      0.05  Sets the thickness of the web thread
  thread_tightness      0.5   Sets the tightness of the web circles
  web_seed              0     Sets the random seed used to create the web
  web_spokes_turb       0.3   Sets the randomness of the web spokes
  web_circles_turb      0.5   Sets the randomness of the web circles

 Setting web_type to 1 gives web circles composed of straight threads
 (this is the quickest to parse and render).  Settings web_type to 2
 gives web circles composed of threads that curve towards the centre
 of the web, while setting web_type to 3 makes the threads hang
 downwards.  The amount of curvature for web types 2 and 3 can be
 controlled using the thread_tightness option (note that very small
 values, eg. < 0.1, will not work well for the thread_tightness option).

 *******************************************************/

// CHECK VARIABLES AND ASSIGN DEFAULTS
// ***********************************
   #declare _SW_tempver = version #version 3.0
   #ifndef (web_type) #declare web_type = 2 #end
   #ifndef (web_radius) #declare web_radius = 10 #end
   #ifndef (web_spokes_count) #declare web_spokes_count = 8 #end
   #ifndef (web_circles_count) #declare web_circles_count = 4 #end
   #ifndef (web_circles_radius) #declare web_circles_radius = web_radius * .8 #end
   #ifndef (thread_thickness) #declare thread_thickness = .05 #end
   #ifndef (thread_tightness) #declare thread_tightness = .5 #end
   #ifndef (web_seed) #declare web_seed = 0 #end
   #ifndef (web_spokes_turb) #declare web_spokes_turb = .3 #end
   #ifndef (web_circles_turb) #declare web_circles_turb = .5 #end

// CREATE WEB AS CSG UNION
// ***********************
   #declare _SW_rand = seed(web_seed)
   union {

// CREATE WEB SPOKES
// *****************
   #declare _SW_spokeint = 360 / web_spokes_count
   #declare _SW_rot = 0 #while (_SW_rot < 360)
      cylinder {<0, 0, 0>, y * web_radius, thread_thickness
         rotate z * (_SW_rot + ((rand(_SW_rand) - .5) * web_spokes_turb * _SW_spokeint))
         }
   #declare _SW_rot = _SW_rot + _SW_spokeint #end

// CREATE WEB CIRCLES
// ******************
   #declare _SW_rand2 = seed(web_seed)
   #declare _SW_circleint = web_circles_radius / web_circles_count
   #declare _SW_circlerad = _SW_circleint #while (_SW_circlerad <= web_circles_radius)
      #declare _SW_rand = seed(web_seed)
      #declare _SW_spoke0rot = (_SW_rot + ((rand(_SW_rand) - .5) * web_spokes_turb * _SW_spokeint))
      #declare _SW_point0 = y * (_SW_circlerad + ((rand(_SW_rand2) - .5) * web_circles_turb * _SW_circleint))
      #declare _SW_point0 = vrotate(_SW_point0, z * _SW_spoke0rot)

      #declare _SW_spoke1rot = _SW_spoke0rot #declare _SW_point1 = _SW_point0
      #declare _SW_rot = _SW_spokeint #while (_SW_rot < 360)
         #declare _SW_spoke2rot = (_SW_rot + ((rand(_SW_rand) - .5) * web_spokes_turb * _SW_spokeint))
         #declare _SW_point2 = y * (_SW_circlerad + ((rand(_SW_rand2) - .5) * web_circles_turb * _SW_circleint))
         #declare _SW_point2 = vrotate(_SW_point2, z * _SW_spoke2rot)

// USE CYLINDERS FOR WEB TYPE 1
// ****************************
         #if (web_type = 1)
            cylinder {_SW_point1, _SW_point2, thread_thickness}

// USE CLIPPED TORII FOR WEB TYPES 2 AND 3
// ***************************************
         #else
            #declare _SW_normal = vnormalize(vcross(_SW_point2 - _SW_point1, z))
            #if (web_type = 3) #if (_SW_normal.y < 0) #declare _SW_normal = -_SW_normal #end #end
            #declare _SW_midpoint = (_SW_point1 + _SW_point2) / 2
            #declare _SW_centre = _SW_midpoint + (_SW_normal * vlength(_SW_point2 - _SW_point1) * thread_tightness * 2)
            torus {vlength(_SW_centre - _SW_point1), thread_thickness
               rotate x * 90 translate _SW_centre
               clipped_by {sphere {_SW_midpoint, vlength(_SW_point1 - _SW_midpoint)}}
               }
         #end
         #declare _SW_spoke1rot = _SW_spoke2rot
         #declare _SW_point1 = _SW_point2
      #declare _SW_rot = _SW_rot + _SW_spokeint #end

// CLOSE WEB CIRCLES
// *****************
      #declare _SW_point2 = _SW_point0
      #if (web_type = 1) cylinder {_SW_point1, _SW_point2, thread_thickness}
      #else #declare _SW_normal = vnormalize(vcross(_SW_point2 - _SW_point1, z))
         #if (web_type = 3) #if (_SW_normal.y < 0) #declare _SW_normal = -_SW_normal #end #end
         #declare _SW_midpoint = (_SW_point1 + _SW_point2) / 2
         #declare _SW_centre = _SW_midpoint + (_SW_normal * vlength(_SW_point2 - _SW_point1) * thread_tightness * 2)
         torus {vlength(_SW_centre - _SW_point1), thread_thickness
            rotate x * 90 translate _SW_centre
            clipped_by {sphere {_SW_midpoint, vlength(_SW_point1 - _SW_midpoint)}}
            } #end
   #declare _SW_circlerad = _SW_circlerad + _SW_circleint #end

// DEFAULT TEXTURE FOR WEB
// ***********************
   texture {pigment {rgb <1, 1, 1>} finish {phong .2 phong_size 10}}}

// REDECLARE NEW WEB_SEED AND RESET VERSION
// ****************************************
   #declare web_seed = rand(_SW_rand) * 1e6
   #version _SW_tempver
