mt
Class MT_CrackleTexture

Object
  extended by common:Generic
      extended by common:TrapShape
          extended by mt:MT_CrackleTexture

class 
TrapShape:MT_CrackleTexture

Based on the Mosaic (Fast) transformation in dmj3.uxf, with the kind permission of Damien M. Jones

Mark Townsend, June 2008


Ultra Fractal Source

Toggle UF Source Code Display

 class MT_CrackleTexture(common.ulb:TrapShape) {
 ;
 ; Based on the Mosaic (Fast) transformation in dmj3.uxf,
 ; with the kind permission of Damien M. Jones
 ; <p>
 ; Mark Townsend, June 2008
 ;
 public:
   func MT_CrackleTexture(Generic pparent)
     TrapShape.TrapShape(pparent)
 
     complex center2 = (0.0)
 
     int i = 0
     int j = 0
     int k = 0
     int l = 0
     int rightbranch = 0
     float random1 = @seed1
     float random2 = @seed2
     complex p = 0
     float range = 1.0 / 2147483648.0
 
     tiletree[0] = -1; initialize tree (one leaf node)
     tiletree[1] = -1
     tileorder[0] = -1; initialize order (one double-endpoint)
     tileorder[1] = -1
     WHILE (i < @mostiles); still another tile to generate
 
       ;
       ; generate random data
       ;
       random1 = (random1 * 1103515245 + 12345) % 2147483648.0
       random2 = (random2 * 1103515245 + 12345) % 2147483648.0
       p = center2 + ((random1 - 1073741824) + flip(random2 - 1073741824)) * range * @mosscale
       tilecenters[j] = real(p)
       tilecenters[j+1] = imag(p)
 
       ;
       ; find appropriate insertion point in the tree
       ;
       IF (i > 0); have at least one item in the tree
         k = 0; current node
         WHILE (k >= 0); not at a leaf node
           l = k; save current node
           IF (real(p) < tilecenters[k] ||   \
               (real(p) == tilecenters[k] && \
                imag(p) < tilecenters[k+1])) ; less than current node
             k = tiletree[k]; follow left branch
             rightbranch = 0
           ELSE; greater than current node
             k = tiletree[k+1]; follow right branch
             rightbranch = 1
           ENDIF
         ENDWHILE
 
         ;
         ; insert node into tree
         ;
         tiletree[j]   = -1; this node is a leaf node
         tiletree[j+1] = -1
         tiletree[l+rightbranch] = j; point this item to it
 
         ;
         ; insert node into sorted list
         ;
         IF (rightbranch == 0); followed the left branch
           IF (tileorder[l] >= 0); not the leftmost node so far
             tileorder[tileorder[l]+1] = j; follow it and point it to the new node
           ENDIF
           tileorder[j] = tileorder[l]; point new node to nodes it's between
           tileorder[j+1] = l
           tileorder[l] = j; point previous tree node's left to this node
         ELSE
           IF (tileorder[l+1] >= 0); not the rightmost node so far
             tileorder[tileorder[l+1]] = j; follow it and point it to the new node
           ENDIF
           tileorder[j] = l; point new node to nodes it's between
           tileorder[j+1] = tileorder[l+1]
           tileorder[l+1] = j; point previous tree node's right to this node
         ENDIF
       ENDIF
 
       i = i + 1
       j = j + 2
     ENDWHILE
 
   endfunc
 
   float func Iterate(complex pz)
     TrapShape.Iterate(pz)
     ;
     ; At this point, we already have a list of tile
     ; centers, with forward and backward order links,
     ; and a tree structure for finding the closest X
     ; value. For each pixel, find the tile center with
     ; the closest X value, then scan outwards until
     ; the tile centers under examination are too far
     ; (in the X direction) to beat what we already have.
     ;
     int i2 = 0
     int j2 = 0
     int k2 = 0
     int l2 = 0
 
     int i3 = 0
     int j3 = 0
 
     BOOL scanleft = TRUE
     BOOL scanright = TRUE
     float d = 0
     float closest1 = 1e20
     float closest2 = 1e20
     complex q = 0
     complex point1 = 0
     complex point2 = 0
     ;
     ; First, find the closest X value.
     ;
     k2 = 0; current node
     WHILE (k2 >= 0); not at a leaf node
       l2 = k2; save current node
       IF (real(pz) < tilecenters[k2] ||   \
           (real(pz) == tilecenters[k2] && \
            imag(pz) < tilecenters[k2+1])) ; less than current node
         k2 = tiletree[k2]; follow left branch
       ELSE; greater than current node
         k2 = tiletree[k2+1]; follow right branch
       ENDIF
     ENDWHILE
 
     q = tilecenters[l2]+flip(tilecenters[l2+1]) ; tile center (as a complex)
     closest1 = |q - pz|; save distance
     point1 = q; save center
     i2 = tileorder[l2]; left node to check
     j2 = tileorder[l2+1]; right node to check
 
     WHILE (scanleft || scanright); still scanning in at least one direction
       IF (i2 < 0); hit the leftmost node
         scanleft = FALSE; don't scan to the left
       ENDIF
       IF (scanleft); scanning to the left...
         q = tilecenters[i2]+flip(tilecenters[i2+1]) ; tile center (as a complex)
         d = sqr(real(q) - real(pz)); distance on X axis
         IF (d > closest1); X distance alone is greater than our closest
           scanleft = FALSE; so nothing else can possibly match
         ELSE; well maybe it's closer
           d = |q - pz|; distance to this tile
           IF (d < closest1); new closest value!
             closest1 = d; save distance
             l2 = i2; save index
             point1 = q; save center
           ENDIF
           i2 = tileorder[i2]; follow link to the left
         ENDIF
       ENDIF
 
       IF (j2 < 0); hit the rightmost node
         scanright = FALSE; don't scan to the right
       ENDIF
       IF (scanright); scanning to the right...
         q = tilecenters[j2]+flip(tilecenters[j2+1]) ; tile center (as a complex)
         d = sqr(real(q) - real(pz)); distance on X axis
         IF (d > closest1); X distance alone is greater than our closest
           scanright = FALSE; so nothing else can possibly match
         ELSE; well maybe it's closer
           d = |q - pz|; distance to this tile
           IF (d < closest1); new closest value!
             closest1 = d; save distance
             l2 = j2; save index
             point1 = q; save center
           ENDIF
           j2 = tileorder[j2+1]; follow link to the right
         ENDIF
       ENDIF
     ENDWHILE
     
     scanleft  = TRUE
     scanright = TRUE
     i3 = tileorder[l2]; left node to check
     j3 = tileorder[l2+1]; right node to check
 
     WHILE (scanleft || scanright); still scanning in at least one direction
       IF (i3 < 0); hit the leftmost node
         scanleft = FALSE; don't scan to the left
       ENDIF
       IF (scanleft); scanning to the left...
         q = tilecenters[i3]+flip(tilecenters[i3+1]) ; tile center (as a complex)
         d = sqr(real(q) - real(pz)); distance on X axis
         IF (d > closest2); X distance alone is greater than our closest
           scanleft = FALSE; so nothing else can possibly match
         ELSE; well maybe it's closer
           d = |q - pz|; distance to this tile
           IF (d < closest2); new closest value!
             closest2 = d; save distance
             point2 = q; save center
           ENDIF
           i3 = tileorder[i3]; follow link to the left
         ENDIF
       ENDIF
 
       IF (j3 < 0); hit the rightmost node
         scanright = FALSE; don't scan to the right
       ENDIF
       IF (scanright); scanning to the right...
         q = tilecenters[j3]+flip(tilecenters[j3+1]) ; tile center (as a complex)
         d = sqr(real(q) - real(pz)); distance on X axis
         IF (d > closest2); X distance alone is greater than our closest
           scanright = FALSE; so nothing else can possibly match
         ELSE; well maybe it's closer
           d = |q - pz|; distance to this tile
           IF (d < closest2); new closest value!
             closest2 = d; save distance
             point2 = q; save center
           ENDIF
           j3 = tileorder[j3+1]; follow link to the right
         ENDIF
       ENDIF
     ENDWHILE
 
     float dist = cabs(pz - point1)
     float dist2 = cabs(pz - point2)
     float v = sin(dist) +  cos(dist2^(1 / @nudge)) * 2 - 1.5
     if @invert
       return 1 - v
     else
       return v
     endif
 
   endfunc
 
 private:
   float tilecenters[@mostiles*2]; tile center points
   int tiletree[@mostiles*2]; tile tree structure
   int tileorder[@mostiles*2]; tile ordering
 
 default:
   title = "Crackle Texture"
   param mostiles
     caption = "Number of Tiles"
     default = 500
     hint = "Sets the number of mosaic tiles. More tiles take \
             longer to render."
   endparam
   float param nudge
     caption = "Nudge"
     default = 1
     min = 0
   endparam
   param mosscale
     caption = "Tile Density"
     default = 5.0
     hint = "Specifies the overall scale of the tiles. Smaller numbers \
             will pack the tiles together more closely."
   endparam
   bool param invert
     caption = "Invert Value"
     default = false
   endparam
   param seed1
     caption = "Random Seed 1"
     default = 51853571
     hint = "This is the 'seed' for the random number generator for \
             horizontal positions."
   endparam
   param seed2
     caption = "Random Seed 2"
     default = 8072177
     hint = "This is the 'seed' for the random number generator for \
             vertical positions."
   endparam
 }
 


Constructor Summary
MT_CrackleTexture()
           
MT_CrackleTexture(Generic pparent)
           
 
Method Summary
 float Iterate(complex pz)
          call this for each iteration being trapped
 
Methods inherited from class common:TrapShape
GetColorChannel, GetTextureValue, GetTransformedPoint, Init, IterateSilent, SetThreshold
 
Methods inherited from class common:Generic
GetParent
 
Methods inherited from class Object
 

Constructor Detail

MT_CrackleTexture

public MT_CrackleTexture(Generic pparent)

MT_CrackleTexture

public MT_CrackleTexture()
Method Detail

Iterate

public float Iterate(complex pz)
Description copied from class: TrapShape
call this for each iteration being trapped

Overrides:
Iterate in class TrapShape