comment { dmj-pub.uxf 2.2 Transformations for Ultra Fractal 2 by Damien M. Jones November 11, 2002 For more information about this formula collection, please visit its home page: http://www.fractalus.com/ultrafractal/dmj-pub-uf.htm Most (all?) of the transformations in this file have little or no redeeming mathematical value, but are great for artistic control over fractal images. } dmj-Blob-Clipping { ; ; This transform allows you to define clipping regions ; using 2D "blobs". A single blob is circular, but blobs ; "reach out" towards each other. You can add positive ; blobs (which increase the clipping area) or negative ; blobs (which "cut away" from the clipping area). Use ; the eyedropper to choose your blobs, and then tweak ; the strengths as appropriate. A strength of zero will ; disable that particular blob. Up to eight blobs may ; be used. ; transform: float sum = @strength1 / |#pixel-@center1| + \ @strength2 / |#pixel-@center2| + \ @strength3 / |#pixel-@center3| + \ @strength4 / |#pixel-@center4| + \ @strength5 / |#pixel-@center5| + \ @strength6 / |#pixel-@center6| + \ @strength7 / |#pixel-@center7| + \ @strength8 / |#pixel-@center8| IF (@above == 0) IF (sum > @threshold) #solid = true ENDIF ELSEIF (@above == 1) IF (sum < @threshold) #solid = true ENDIF ENDIF ; IF (sum > @threshold && @above == 0) ; #solid = true ; ELSEIF (sum < @threshold && @above == 1) ; #solid = true ; ENDIF default: title = "Blob Clipping" helpfile = "dmj-pub\dmj-pub-uf-blobclip.htm" param threshold caption = "Threshold" default = 0.5 hint = "Sets the threshold, above or below which points will \ be clipped. Smaller values will increase the size \ pf the clipping region." endparam param above caption = "Clipping Region" default = 0 enum = "above threshold" "below threshold" hint = "Set whether points above or below the threshold value \ will be clipped." endparam param center1 caption = "Point 1 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength1 caption = "Point 1 Strength" default = 1.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center2 caption = "Point 2 Center" default = (-1,0) hint = "Sets the center point for this blob." endparam param strength2 caption = "Point 2 Strength" default = 0.5 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center3 caption = "Point 3 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength3 caption = "Point 3 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center4 caption = "Point 4 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength4 caption = "Point 4 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center5 caption = "Point 5 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength5 caption = "Point 5 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center6 caption = "Point 6 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength6 caption = "Point 6 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center7 caption = "Point 7 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength7 caption = "Point 7 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam param center8 caption = "Point 8 Center" default = (0,0) hint = "Sets the center point for this blob." endparam param strength8 caption = "Point 8 Strength" default = 0.0 hint = "Sets how 'strong' this blob is. Negative values will \ 'cut away' from the blobbed area." endparam } dmj-Clipping { ; ; Clipping Transformation ; This fulfills much the same function as Luke ; Plant's Scissors transform, but is geared ; towards being easier to use (i.e. just point ; and click). ; transform: complex p = (0,0) complex r = (0,0) ; complex s = (0,0) float re = 0.0 float te = 0.0 ; determine pixel location IF (@relative); relative coordinates complex p = real(#screenpixel)/#width + flip(imag(#screenpixel)/#height) ELSE; absolute coordinates complex p = #pixel ENDIF ; determine right edge IF (@rotation); rotation is enabled float re = cabs(@sciright-@scicenter) complex r = conj(@sciright-@scicenter) / re ELSEIF (@relative); relative coordinates float re = abs(real(@sciright)-real(@scicenter)) complex r = (1,0) ELSE; rotation is disabled complex r = conj(exp(flip(#angle))) float re = abs(real((@sciright-@scicenter)*r)) ENDIF ; determine top edge ; IF (@skewing); skewing is enabled ; float te = cabs(@scitop-@scicenter) ; complex s = conj(@scitop-@scicenter) / re ; ELSE; rotation is disabled float te = abs(imag((@scitop-@scicenter)*r)) ; complex s = (0,1) ; ENDIF ; see if point is inside clipping shape p = (p-@scicenter) * r bool in = (@sciinside == 1) IF (@scishape == 0); circle IF (|p| < sqr(re)) in = !in ENDIF ELSEIF (@scishape == 1); ellipse IF (sqr(real(p))/sqr(re)+sqr(imag(p))/sqr(te) < 1.0) in = !in ENDIF ELSEIF (@scishape == 2); square IF (abs(real(p)) < re && abs(imag(p)) < re) in = !in ENDIF ELSEIF (@scishape == 3); rectangular IF (abs(real(p)) < re && abs(imag(p)) < te) in = !in ENDIF ENDIF #solid = in default: title = "Clipping" helpfile = "dmj-pub\dmj-pub-uf-clipping.htm" param scicenter caption = "Clipping Center" default = (0,0) hint = "Sets the center of clipping." endparam param sciright caption = "Clipping Right Edge" default = (0,0) hint = "Sets the right edge of the clipping shape. If \ rotation is enabled, sets the center of the \ right edge." endparam param scitop caption = "Clipping Top Edge" default = (0,0) hint = "Sets the top edge of the clipping shape. Has no \ effect for Circle and Square clipping shapes." ; If \ ; skewing is enabled, sets the center of the \ ; top edge." endparam param scishape caption = "Clipping Shape" default = 2 enum = "circle" "ellipse" "square" "rectangle" hint = "Selects the clipping shape." endparam param rotation caption = "Allow Rotation" default = FALSE hint = "If enabled, you can use the Right Edge setting \ to also select a rotation for the clipping shape." endparam ; param skewing ; caption = "Allow Skewing" ; default = FALSE ; hint = "If enabled, you can use the Top Edge setting \ ; to also select a skewing for the clipping shape." ; endparam param sciinside caption = "Clipping Region" default = 1 enum = "inside" "outside" endparam param relative caption = "Screen-Relative" default = FALSE hint = "If set, all clipping coordinates are relative \ to the fractal window. This will leave the clipping \ shape intact while zooming, but make it harder \ to enter coordinates for clipping." endparam } dmj-EggScissors { ; ; Special Egg Scissors Transform ; This performs much the same function as the ; general clipping transform, but uses an egg ; shape. ; transform: complex c = @eggcenter; assume egg center is fixed IF (@centermove); relative egg center requested c = #center; egg center is image center ENDIF complex r = (0,1) ^ (@angle / 90.0); rotation vector complex z = (#pixel-c) * r; apply translation and rotation z = real(z) + flip(imag(z) * @aspect); apply aspect float d = (cabs(z-flip(@diameter)*2) + cabs(z)*@eggorder*0.5) / (@eggorder+1) IF (@egginside); want solid inside IF (d < @threshold); point is inside egg #solid = TRUE; color it solid ENDIF ELSE; want solid outside IF (d > @threshold); point is outside egg #solid = TRUE ENDIF ENDIF default: title = "Egg Scissors" helpfile = "dmj-pub\dmj-pub-uf-egg.htm" param eggorder caption = "Egginess" default = 3.0 hint = "Adjusts how non-circular the curve is." endparam param eggcenter caption = "Egg Center" default = (0,0) hint = "Sets the location of one focus of the egg shape." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the egg focus will be at the center of \ the window, regardless of the Egg Center \ setting." endparam param egginside caption = "Solid Inside" default = FALSE hint = "If set, the inside of the egg will be solid. Otherwise, \ the outside of the egg will be solid." endparam param aspect caption = "Aspect Ratio" default = 1.0 min = 0.0000000001 hint = "This is how square the egg curve is. You can \ distort the curve by using a value other than 1.0." endparam param threshold caption = "Threshold" default = 0.5 min = 0 hint = "This is the distance to the edge of the egg curve." endparam param diameter caption = "Diameter" default = 0.5 hint = "This is the distance between focal points of the egg curve." endparam param angle caption = "Rotation" default = 0.0 hint = "This is the angle, in degrees, that the egg \ curve should be rotated." endparam } dmj-fBm-Clipping { ; ; fBm-based clipping. ; This performs clipping based on fBm textures. ; transform: complex r = (0,1) ^ (@angle / 90.0) complex r2 = (0,1) ^ (@anglestep / 90.0) ; complex r3 = (0,1) ^ (@distangle / 90.0) complex p = #pixel * @scale * r + @offset float sum = 0.0 float freq = 1.0 int i = @octaves WHILE (i > 0) ; determine integer coordinate for corners of square ; surrounding p float bx0 = floor(real(p)) % 256 float by0 = floor(imag(p)) % 256 IF (bx0 < 0) bx0 = bx0 + 256 ENDIF IF (by0 < 0) by0 = by0 + 256 ENDIF float bx1 = (bx0 + 1) % 256 float by1 = (by0 + 1) % 256 float rx0 = real(p) - floor(real(p)) float ry0 = imag(p) - floor(imag(p)) float rx1 = rx0 - 1 float ry1 = ry0 - 1 ; create a "random" index for each corner ; (this is where Intel's version differs from Perlin's; ; I used Intel's version because it doesn't require a ; pre-computed random table, which is difficult to manage ; in UF.) float b00 = (bx0^@power % 65536 + by0)^@power % 65536 float b10 = (bx1^@power % 65536 + by0)^@power % 65536 float b01 = (bx0^@power % 65536 + by1)^@power % 65536 float b11 = (bx1^@power % 65536 + by1)^@power % 65536 ; produce a "random" vector for each corner float g_b00_0 = (b00)^@power*0.25 % 512 - 256 float g_b10_0 = (b10)^@power*0.25 % 512 - 256 float g_b01_0 = (b01)^@power*0.25 % 512 - 256 float g_b11_0 = (b11)^@power*0.25 % 512 - 256 float g_b00_1 = (b00+1)^@power*0.25 % 512 - 256 float g_b10_1 = (b10+1)^@power*0.25 % 512 - 256 float g_b01_1 = (b01+1)^@power*0.25 % 512 - 256 float g_b11_1 = (b11+1)^@power*0.25 % 512 - 256 ; normalize each vector float d = 0.0; d = 1 / sqrt(sqr(g_b00_0) + sqr(g_b00_1)) g_b00_0 = g_b00_0 * d g_b00_1 = g_b00_1 * d d = 1 / sqrt(sqr(g_b10_0) + sqr(g_b10_1)) g_b10_0 = g_b10_0 * d g_b10_1 = g_b10_1 * d d = 1 / sqrt(sqr(g_b01_0) + sqr(g_b01_1)) g_b01_0 = g_b01_0 * d g_b01_1 = g_b01_1 * d d = 1 / sqrt(sqr(g_b11_0) + sqr(g_b11_1)) g_b11_0 = g_b11_0 * d g_b11_1 = g_b11_1 * d ; produce colors for each corner float u1 = rx0 * g_b00_0 + ry0 * g_b00_1 float v1 = rx1 * g_b10_0 + ry0 * g_b10_1 float u2 = rx0 * g_b01_0 + ry1 * g_b01_1 float v2 = rx1 * g_b11_0 + ry1 * g_b11_1 ; interpolate between corners using ; bilinear filtering float sx = sqr(rx0) * (3 - rx0*2) float sy = sqr(ry0) * (3 - ry0*2) float a = u1 + sx*(v1-u1) float b = u2 + sx*(v2-u2) sum = sum + (a + sy*(b-a))*freq freq = freq * @step p = p * r2 / @step i = i - 1 ENDWHILE IF (@above == 0) IF (sum > @threshold) #solid = true ENDIF ELSEIF (@above == 1) IF (sum < @threshold) #solid = true ENDIF ENDIF ; IF (sum > @threshold && @above == 0) ; #solid = true ; ELSEIF (sum < @threshold && @above == 1) ; #solid = true ; ENDIF default: title = "fBm Clipping" helpfile = "dmj-pub\dmj-pub-uf-fbmclip.htm" param threshold caption = "Threshold" default = 0.0 hint = "Sets the threshold, above or below which points will \ be clipped." endparam param above caption = "Clipping Region" default = 0 enum = "above threshold" "below threshold" hint = "Set whether points above or below the threshold value \ will be clipped." endparam param offset caption = "Noise Offset" default = (0,0) hint = "This is the offset of the pattern. You can use this to shift \ the pattern around on the complex plane." endparam param scale caption = "Noise Scale" default = 1.0 hint = "This is the overall scale of the noise." endparam param angle caption = "Noise Rotation" default = 0.0 hint = "This is the angle, in degrees, of the noise." endparam param step caption = "Noise Scale Step" default = 0.5 hint = "This is the step in scale between noise iterations." endparam param anglestep caption = "Noise Rotation Step" default = 37.0 hint = "This is the angle, in degrees, to rotate between noise \ iterations." endparam param octaves caption = "Noise Octaves" default = 7 min = 1 hint = "This is the number of iterations of the noise formula." endparam param power caption = "Noise Exponent" default = 2.0 hint = "This is the exponent used to scramble numbers." endparam } dmj-fBm-Glass1 { ; ; fBm-based glass distortion. ; This provides one-dimensional distortion based ; on fBm textures. ; transform: complex c = @distcenter IF (@centermove) c = #center ENDIF complex r = (0,1) ^ (@angle / 90.0) complex r2 = (0,1) ^ (@anglestep / 90.0) complex r3 = (0,1) ^ (@distangle / 90.0) complex p = #pixel * @scale * r + @offset float sum = 0.0 float freq = 1.0 complex v = (0,0) int i = @octaves WHILE (i > 0) ; determine integer coordinate for corners of square ; surrounding p float bx0 = floor(real(p)) % 256 float by0 = floor(imag(p)) % 256 IF (bx0 < 0) bx0 = bx0 + 256 ENDIF IF (by0 < 0) by0 = by0 + 256 ENDIF float bx1 = (bx0 + 1) % 256 float by1 = (by0 + 1) % 256 float rx0 = real(p) - floor(real(p)) float ry0 = imag(p) - floor(imag(p)) float rx1 = rx0 - 1 float ry1 = ry0 - 1 ; create a "random" index for each corner ; (this is where Intel's version differs from Perlin's; ; I used Intel's version because it doesn't require a ; pre-computed random table, which is difficult to manage ; in UF.) float b00 = (bx0^@power % 65536 + by0)^@power % 65536 float b10 = (bx1^@power % 65536 + by0)^@power % 65536 float b01 = (bx0^@power % 65536 + by1)^@power % 65536 float b11 = (bx1^@power % 65536 + by1)^@power % 65536 ; produce a "random" vector for each corner float g_b00_0 = (b00)^@power*0.25 % 512 - 256 float g_b10_0 = (b10)^@power*0.25 % 512 - 256 float g_b01_0 = (b01)^@power*0.25 % 512 - 256 float g_b11_0 = (b11)^@power*0.25 % 512 - 256 float g_b00_1 = (b00+1)^@power*0.25 % 512 - 256 float g_b10_1 = (b10+1)^@power*0.25 % 512 - 256 float g_b01_1 = (b01+1)^@power*0.25 % 512 - 256 float g_b11_1 = (b11+1)^@power*0.25 % 512 - 256 ; normalize each vector float d = 0.0; d = 1 / sqrt(sqr(g_b00_0) + sqr(g_b00_1)) g_b00_0 = g_b00_0 * d g_b00_1 = g_b00_1 * d d = 1 / sqrt(sqr(g_b10_0) + sqr(g_b10_1)) g_b10_0 = g_b10_0 * d g_b10_1 = g_b10_1 * d d = 1 / sqrt(sqr(g_b01_0) + sqr(g_b01_1)) g_b01_0 = g_b01_0 * d g_b01_1 = g_b01_1 * d d = 1 / sqrt(sqr(g_b11_0) + sqr(g_b11_1)) g_b11_0 = g_b11_0 * d g_b11_1 = g_b11_1 * d ; produce colors for each corner float u1 = rx0 * g_b00_0 + ry0 * g_b00_1 float v1 = rx1 * g_b10_0 + ry0 * g_b10_1 float u2 = rx0 * g_b01_0 + ry1 * g_b01_1 float v2 = rx1 * g_b11_0 + ry1 * g_b11_1 ; interpolate between corners using ; bilinear filtering float sx = sqr(rx0) * (3 - rx0*2) float sy = sqr(ry0) * (3 - ry0*2) float a = u1 + sx*(v1-u1) float b = u2 + sx*(v2-u2) sum = sum + (a + sy*(b-a))*freq freq = freq * @step p = p * r2 / @step i = i - 1 ENDWHILE IF (@style == 0) ; radial distortion v = (#pixel-c)/cabs(#pixel-c) * r3 ; use vector based on angle to distortion center ELSEIF (@style == 1) ; linear distortion v = r3 ; just use rotation vector ENDIF #pixel = #pixel + v * sum*0.5*@distortion default: title = "fBm Glass 1" helpfile = "dmj-pub\dmj-pub-uf-fbmg1.htm" param distortion caption = "Distortion Strength" default = 1.0 hint = "This is the amount the noise distorts the image." endparam param style caption = "Distortion Style" default = 0 enum = "radial" "linear" hint = "This selects whether the distortion will be focused \ around a single point, or directed along a line." endparam param distangle caption = "Distortion Angle" default = 0.0 hint = "This is the angle to rotate the distortion." endparam param distcenter caption = "Distortion Center" default = (0,0) hint = "Sets the center of distortion. If Use Screen \ Center is set, this item is ignored." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, distortion will be around the center of \ the window, regardless of the Distortion Center \ setting." endparam param offset caption = "Noise Offset" default = (0,0) hint = "This is the offset of the pattern. You can use this to shift \ the pattern around on the complex plane." endparam param scale caption = "Noise Scale" default = 1.0 hint = "This is the overall scale of the noise." endparam param angle caption = "Noise Rotation" default = 0.0 hint = "This is the angle, in degrees, of the noise." endparam param step caption = "Noise Scale Step" default = 0.5 hint = "This is the step in scale between noise iterations." endparam param anglestep caption = "Noise Rotation Step" default = 37.0 hint = "This is the angle, in degrees, to rotate between noise \ iterations." endparam param octaves caption = "Noise Octaves" default = 7 min = 1 hint = "This is the number of iterations of the noise formula." endparam param power caption = "Noise Exponent" default = 2.0 hint = "This is the exponent used to scramble numbers." endparam } dmj-Forces { ; ; This uses the Mosaic algorithm to sprinkle the image ; with "force points" which attract or repel pixels in ; the image. For any given pixel, its final location is ; the sum of all the forces acting on it. You cannot place ; force points manually; they are placed by the same ; algorithm which places mosaic tile centers. ; transform: complex center2 = @moscenter IF (@centermove) center2 = #center ENDIF int i = 0 float d = 0 float random1 = @seed1 float random2 = @seed2 float random3 = @seed3 complex p = 0 complex point1 = 0 float r1 = 0 float range = 1.0 / 2147483648.0 WHILE (i < @mostiles); still another tile to check random1 = (random1 * 1103515245 + 12345) % 2147483648.0 random2 = (random2 * 1103515245 + 12345) % 2147483648.0 random3 = (random3 * 1103515245 + 12345) % 2147483648.0 p = center2 + ((random1 - 1073741824) + flip(random2 - 1073741824)) * range * @mosscale d = |p - #pixel| r1 = (random3 * range) * (@mosmax-@mosmin) + @mosmin point1 = point1 + r1/d*(p-#pixel) i = i + 1 ENDWHILE #pixel = #pixel + point1 default: title = "Forces" helpfile = "dmj-pub\dmj-pub-uf-forces.htm" param mostiles caption = "Number of Points" default = 500 hint = "Sets the number of force points. More points take \ longer to render." endparam param moscenter caption = "Force Area Center" default = (0,0) hint = "Sets the center of the force area. The cluster of \ force points will be centered at this point." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the force area center is assumed to be at the center of \ the window, regardless of the Force Area Center setting." endparam param mosscale caption = "Point Density" default = 5.0 hint = "Specifies the overall scale of the points. Smaller numbers \ will pack the points together more closely." endparam param mosmin caption = "Minimum Force" default = -0.1 hint = "This is the minimum force (strongest attraction) a point may have." endparam param mosmax caption = "Maximum Force" default = 0.1 hint = "This is the maximum force (strongest repulsion) a point may have." 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 param seed3 caption = "Random Seed 3" default = 654187327 hint = "This is the 'seed' for the random number generator for \ rotations." endparam } dmj-Inversion { ; ; This is a generalization of inversion, based on the ; ideas first presented by Kerry Mitchell in his ; Inversion fractal formula. This is a general-purpose ; transform and can be used with any fractal. ; ; Thanks to Kerry also for some optimizations on this ; formula. ; transform: complex c = @invcenter; assume inversion center is fixed IF (@centermove); relative inversion center requested c = #center; inversion center is image center ENDIF complex r = (0,1) ^ (@angle / 90.0); rotation vector complex z = (#pixel-c) * r; apply translation and rotation z = real(z) + flip(imag(z) * @aspect); apply aspect float d = 1.0 IF (@invtype == 4); one axis only inversion IF (@invpower == (-1,0)); standard power z = real(z) + @invscale*flip(1/imag(z)); invert just the one axis ELSE; general power z = real(z) + @invscale*flip(imag(z)^@invpower) ; do inversion ENDIF ELSE; any other inversion type ; IF (@invtype == 0); ellipse ;; same distance everywhere IF (@invtype == 1); hypercross ; d = imag(z) / real(z); slope of line passing through z ; d = 1.0 / sqrt(abs(d + 1.0/d)); distance from origin to hypercross ; ; through z d = sqrt(abs(real(z)*imag(z))/|z|) ; Kerry's simplification ELSEIF (@invtype == 2); flower d = atan2(z); angle to z d = abs(cos(d*@invorder)+@diameter) ; distance from origin to flower at ; angle z ELSEIF (@invtype == 3); lines d = sqrt(sqr(real(z)/imag(z))+1); distance from origin to horizontal ; line through z ENDIF ; z = z*d / sqr(cabs(z)); do inversion (stupid way) IF (@invpower == (-1,0)); standard power z = @invscale*z*d / |z|; do inversion (Kerry-optimized) ELSE; general power z = @invscale*z*d * cabs(z)^(@invpower-1); do inversion ENDIF ENDIF z = real(z) + flip(imag(z) / @aspect); undo aspect #pixel = z * conj(r) + c; undo rotation and translation default: title = "General Inversion" helpfile = "dmj-pub\dmj-pub-uf-inversion.htm" param invtype caption = "Inversion Curve" default = 0 enum = "ellipse" "hypercross" "flower" "lines" "one axis" hint = "Sets the shape of the curve through which inversion \ is done." endparam param invscale caption = "Inversion Scale" default = 1.0 hint = "Scale of the inversion. This performs a similar function \ to changing the magnitude of the fractal zoom." endparam param invorder caption = "Inversion Order" default = 3.0 hint = "Number of leaves for the flower curve." endparam param invcenter caption = "Inversion Center" default = (0,0) hint = "Sets the center of the inversion." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, inversion will be around the center of \ the window, regardless of the Inversion Center \ setting." endparam param aspect caption = "Aspect Ratio" default = 1.0 min = 0.0000000001 hint = "This is how square the inversion curve is. You can \ distort the curve by using a value other than 1.0." endparam param diameter caption = "Diameter" default = 1.5 hint = "This is the diameter of the inversion curve. Note this \ only matters for the 'flower' curve type." endparam param angle caption = "Rotation" default = 0.0 hint = "This is the angle, in degrees, that the inversion \ curve should be rotated." endparam param invpower caption = "Exponent" default = (-1,0) hint = "Gives the inversion exponent. (-1,0) gives the classic \ 1/z inversion type." endparam } dmj-Julia { ; ; This does a few Julia-set iterations to warp ; the fractal shape. Try using it with a ; Newton fractal. ; transform: int i = @iters complex z = #pixel/@magnification-@offset WHILE (i > 0 && |z| <= @bailout) z = z^@power + @seed i = i - 1 ENDWHILE IF (|z| > @bailout) #solid = true ELSE #pixel = z+@offset ENDIF default: title = "Julia" helpfile = "dmj-pub\dmj-pub-uf-mjpnx.htm" param iters caption = "Iterations" default = 4 hint = "Number of iterations to do before calculating the fractal. \ Use a small number." endparam param offset caption = "Offset" default = (0,0) hint = "Offsets the Julia distortion." endparam param magnification caption = "Magnification" default = 1.0 hint = "Sets the magnification on the Julia shape." endparam param seed caption = "Julia Seed" default = (0,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power caption = "Exponent" default = (2,0) hint = "Overall exponent for the equation. (2,0) gives \ the classic Julia type." endparam param bailout caption = "Bailout" default = 1.0e20 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Julia set anymore. Bailed-out points will be \ solid-colored." endparam } dmj-Kaleidoscope { ; ; Kaleidoscope Transformation ; This can be used to simulate many different ; kinds of symmetry. ; ; Changes: ; - When using "slice" mode, points not part of ; the slice will be colored using the solid ; color. You can use this to assemble several ; slices into the same image. ; transform: float r2 = 0.0 float d = 0.0 complex r = (0,1) ^ (@angle/90); complex rotation vector complex c = @symcenter; assume symmetry center is fixed IF (@centermove); relative symmetry center requested c = #center; symmetry center is image center ENDIF complex z2 = #pixel - c; get coordinate relative to symcenter ; convert z2 into angle and distance r2 = atan2(z2) IF (r2 < 0); negative angle (we want 0 < atan < pi*2) r2 = r2 + #pi * 2; rotate 360 degrees ENDIF d = cabs(z2); distance from symcenter IF (@symorder > 0); Zero symmetry disables the transform. ; apply symmetry IF (@symreflect == 0); reflective r2 = r2 - floor(r2*@symorder/#pi/2)*#pi*2/@symorder IF (r2 > #pi/@symorder); upper half of the range r2 = #pi*2/@symorder - r2; reflect angle ENDIF ELSEIF (@symreflect == 1); left symmetry r2 = r2 - floor(r2*@symorder/#pi/2)*#pi*2/@symorder ELSEIF (@symreflect == 2); right symmetry r2 = r2 - floor(r2*@symorder/#pi/2)*#pi*2/@symorder r2 = #pi*2/@symorder - r2; always reflect this ELSEIF (@symreflect == 3); slice-only symmetry IF (r2 > #pi*2/@symorder); outside of slice r2 = 0; reset angle #solid = true; this is outside now ENDIF ENDIF #pixel = (cos(r2)*d + flip(sin(r2)*d))/r + c; compute point ENDIF default: title = "Kaleidoscope" helpfile = "dmj-pub\dmj-pub-uf-kaleidoscope.htm" param symorder caption = "Symmetry Order" default = 8.0 hint = "Indicates the number of reflected components. \ Use 0 to temporarily disable symmetry." endparam param symreflect caption = "Symmetry Mode" default = 0 enum = "reflective" "left" "right" "slice only" hint = "Style of symmetry. Reflective will always be \ seamless; left and right may not be. If Slice \ is selected, only the section that will be \ mirrored will be shown." endparam param symcenter caption = "Symmetry Center" default = (0,0) hint = "Sets the center of symmetry. If Use Screen \ Center is set, this item is ignored." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, symmetry will be around the center of \ the window, regardless of the Symmetry Center \ setting." endparam param angle caption = "Rotation angle" default = 0.0 hint = "Sets how much to rotate the fractal (in degrees) \ before applying symmetry." endparam } dmj-LowRes { ; ; Low Resolution Transformation ; This deliberately lowers the resolution of ; the fractal, but it does so by limiting the ; precision of complex numbers, so it is still ; usable with other transformations. ; transform: complex r = (0,1) ^ (@angle/90); complex rotation vector #pixel = (round(real(#pixel*r)*@xres)/@xres + flip(round(imag(#pixel*r)*@yres)/@yres)) * conj(r) default: title = "Low Resolution" helpfile = "dmj-pub\dmj-pub-uf-lowres.htm" param xres caption = "Real Resolution" default = 25.0 hint = "Number of separate positions per horizontal unit distance." endparam param yres caption = "Imaginary Resolution" default = 25.0 hint = "Number of separate positions per vertical unit distance." endparam param angle caption = "Rotation angle" default = 0.0 hint = "Sets the angle at which the low-resolution grid is applied." endparam } dmj-Mandelbrot { ; ; This does a few M-set iterations to warp ; the fractal shape. Try using it with a ; Newton fractal. ; transform: int i = @iters complex z = @start WHILE (i > 0 && |z| <= @bailout) z = z^@power + #pixel-@offset i = i - 1 ENDWHILE IF (|z| > @bailout) #solid = true ELSE #pixel = z+@offset ENDIF default: title = "Mandelbrot" helpfile = "dmj-pub\dmj-pub-uf-mjpnx.htm" param iters caption = "Iterations" default = 4 hint = "Number of iterations to do before calculating the fractal. \ Use a small number." endparam param offset caption = "Offset" default = (0,0) hint = "Offsets the Mandelbrot distortion." endparam param start caption = "Start Value" default = (0,0) hint = "Starting value for each point. You can use this to \ 'perturb' the fractal." endparam param power caption = "Exponent" default = (2,0) hint = "Overall exponent for the equation. (2,0) gives \ the classic Mandelbrot type." endparam param bailout caption = "Bailout" default = 1.0e20 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Mandelbrot set anymore. Bailed-out points will be \ solid-colored." endparam } dmj-Mirror { ; ; This transform can be used to reflect a layer ; around any arbitrary axis. ; transform: complex center2 = @refcenter IF (@centermove) center2 = #center ENDIF complex r = (0,1) ^ (@angle / 90.0) #pixel = (#pixel-center2) * r #pixel = conj(#pixel) #pixel = #pixel * conj(r) + center2 default: title = "Mirror" helpfile = "dmj-pub\dmj-pub-uf-mirror.htm" param angle caption = "Reflection Angle" default = 0.0 hint = "This is the angle for the axis of reflection." endparam param refcenter caption = "Reflection Center" default = (0,0) hint = "Sets the center of reflection. Use the eyedropper \ to pick it." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, reflection is assumed to be at the center of \ the window, regardless of the Reflection Center setting." endparam } dmj-Mosaic { ; ; This transform can be used to break an image into ; many mosaic pieces, and either have those solid- ; colored or contain pieces of the fractal itself. ; ; In general you want to use as few tiles as you can ; get away with. Fewer tiles allows the algorithm to ; run much faster. Although speedups have been added ; to this version, about 500,000 tiles will make this ; formula run very slowly. (2,500 was the "slow" point ; for previous versions.) ; ; You may also want to re-enable guessing if you've ; turned it off, especially if you're using a small ; number of tiles. Mosaic normally produces large ; areas of solid color, which guessing can speed up. ; ; Because of the shortcuts used to speed up rendernig, ; this transform requires some memory; 1,000,000 tiles ; will require about 40M of RAM. ; ; The original code was much simpler; the algorithm ; was straightforward in that each pixel was checked ; against each tile center to find the closest one. ; global: ; ; The general idea is to generate, one time, the ; entire list of center points for each tile. But, ; as the list is generated, it is stored in sorted ; order (by X coordinate). This will allow fast ; finding of nearest center point. ; ; We store centerpoints as an array of float instead ; of an array of complex so we don't have to keep ; cutting our tree node numbers in half. ; float tilecenters[@mostiles*2]; tile center points float tileangles[@mostiles]; tile rotation angles int tiletree[@mostiles*2]; tile tree structure int tileorder[@mostiles*2]; tile ordering complex center2 = @moscenter IF (@centermove) center2 = #center ENDIF int i = 0 int j = 0 int k = 0 int l = 0 int rightbranch = 0 float random1 = @seed1 float random2 = @seed2 float random3 = @seed3 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) IF (@mosangle != 0.0); want an angle, too random3 = (random3 * 1103515245 + 12345) % 2147483648.0 tileangles[i] = random3 ENDIF ; ; 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 transform: ; ; 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 int k3 = 0 int l3 = 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 float r1 = 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(#pixel) < tilecenters[k2] || \ (real(#pixel) == tilecenters[k2] && \ imag(#pixel) < 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 - #pixel|; 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(#pixel)); 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 - #pixel|; distance to this tile IF (d < closest1); new closest value! closest1 = d; save distance l2 = i2; save index point1 = q; save center IF (@mosangle != 0.0); want a random angle, too r1 = tileangles[floor(l2 * 0.5)]; save angle ENDIF 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(#pixel)); 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 - #pixel|; distance to this tile IF (d < closest1); new closest value! closest1 = d; save distance l2 = j2; save index point1 = q; save center IF (@mosangle != 0.0); want a random angle, too r1 = tileangles[floor(l2 * 0.5)]; save angle ENDIF ENDIF j2 = tileorder[j2+1]; follow link to the right ENDIF ENDIF ENDWHILE ; ; We now have the location of the closest tile ; (point1) and the index of it (l2). If we're ; doing anything with the seams, we'll need the ; second-closest point, too. We scan left and ; right for it. This time, we don't need the ; angle, we just want to know where the tile is. ; IF (@usesolid > 0 && @tileseams > 0.0) 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(#pixel)); 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 - #pixel|; distance to this tile IF (d < closest2); new closest value! closest2 = d; save distance l3 = i3; save index 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(#pixel)); 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 - #pixel|; distance to this tile IF (d < closest2); new closest value! closest2 = d; save distance l3 = j3; save index point2 = q; save center ENDIF j3 = tileorder[j3+1]; follow link to the right ENDIF ENDIF ENDWHILE ENDIF ; ; With the coordinates of the closest and ; second-closest tile, we can transform our ; point (and apply the solid color). ; ; The algorithm for determining whether the ; point is in the "seam" between two tiles ; is not perfect. To be truly right, it would ; need to test against the seam for every ; neighboring tile; we don't have that data ; handy and it's not easy to get. So, we ; fudge it. ; IF (@usesolid == 1 && @tileseams > 0.0) d = real((#pixel-(point2+point1)*0.5) * conj(point2-point1)/cabs(point2-point1)) IF (abs(d) < @tileseams) #solid = true ENDIF ELSEIF (@usesolid == 2 && @tileseams > 0.0) d = real((#pixel-(point2+point1)*0.5) * conj(point2-point1)/cabs(point2-point1)) IF (abs(d) > @tileseams) #solid = true ENDIF ELSEIF (@usesolid == 3 && @tileseams > 0.0) closest1 = sqrt(closest1) closest2 = sqrt(closest2) IF (closest2-closest1 < @tileseams) #solid = true ENDIF ELSEIF (@usesolid == 4 && @tileseams > 0.0) closest1 = sqrt(closest1) closest2 = sqrt(closest2) IF (closest2-closest1 > @tileseams) #solid = true ENDIF ENDIF IF (@mosangle != 0.0) r1 = (r1 - 1073741824) * range ENDIF #pixel = point1*(1-@mosforce) + (#pixel-point1)*@tilescale * (0,1)^(r1*@mosangle/90.0) default: title = "Mosaic (Fast)" helpfile = "dmj3\dmj3-pub-uf-mosaic.htm" param mostiles caption = "Number of Tiles" default = 500 hint = "Sets the number of mosaic tiles. More tiles take \ longer to render." endparam param moscenter caption = "Tiled Area Center" default = (0,0) hint = "Sets the center of the tiled area. The cluster of \ tiles will be centered at this point." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the tiled area center is assumed to be at the center of \ the window, regardless of the Tiled Area Center setting." 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 param tilescale caption = "Tile Magnification" default = 0.0 hint = "Specifies the scale of the image within each tile. Use 0 \ for solid-color tiles, use 1 for no effect." endparam param tileseams caption = "Seam Width" default = 0.0 hint = "Sets the width of seams between tiles. If set to 0, then \ no seam will be calculated (faster)." endparam param usesolid caption = "Solid Color Use" default = 0 enum = "none" "seams, no gaps" "tiles, no gaps" "seams, with gaps" "tiles, with gaps" hint = "Sets what the solid color will be used for." endparam param mosforce caption = "Force Tiles to Origin" default = 0.0 hint = "Forces the center of each tile towards the origin. If zero, \ has no effect (tiles are centered normally). If one, tiles \ are fully moved towards the origin." endparam param mosangle caption = "Rotation Range" default = 0.0 hint = "Sets the range on rotations for each tile." 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 param seed3 caption = "Random Seed 3" default = 654187327 hint = "This is the 'seed' for the random number generator for \ rotations." endparam } dmj-NovaJulia { ; ; This does a few Nova Julia iterations to warp ; the fractal shape. Try using it with a ; Newton fractal. ; transform: complex zsquared = (0,0) complex zcubed = (0,0) complex zold = (0,0) int i = @iters complex z = #pixel-@offset WHILE (i > 0 && |z-zold| > @bailout) IF (@power == (3,0)); special optimized routine for power 3 zsquared = sqr(z) zcubed = zsquared * z zold = z z = z - (zcubed-1) / (3*zsquared) + @seed ELSE zold = z z = z - (z^@power-1) / (@power * z^(@power-1)) + @seed ENDIF i = i - 1 ENDWHILE IF (|z-zold| <= @bailout) #solid = true ELSE #pixel = z+@offset ENDIF default: title = "Nova (Julia)" helpfile = "dmj-pub\dmj-pub-uf-mjpnx.htm" param iters caption = "Iterations" default = 4 hint = "Number of iterations to do before calculating the fractal. \ Use a small number." endparam param offset caption = "Offset" default = (0,0) hint = "Offsets the Nova Julia distortion." endparam param seed caption = "Julia Seed" default = (0,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power caption = "Exponent" default = (3,0) hint = "Overall exponent for the equation. (3,0) gives \ the classic Nova type." endparam param bailout caption = "Bailout" default = 0.00001 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Nova Julia set anymore. Bailed-out points will be \ solid-colored." endparam } dmj-Offset { ; ; This transform offsets the fractal with rectangular ; displacement. By itself, it accomplishes nothing that ; cannot be done better by repositioning the fractal. ; However, combined with other transforms it can produce ; some interesting distortions, and it can also be a ; convenience when creating multi-layer fractals. ; transform: complex offset = @offvector * @offscale * ((0,1) ^ (@offangle / 90.0)) #pixel = #pixel + offset default: title = "Offset" helpfile = "dmj-pub\dmj-pub-uf-offset.htm" param offvector caption = "Offset Amount" default = (0,0) hint = "Specifies the amount of offset." endparam param offangle caption = "Offset Angle" default = 0.0 hint = "Angle of offset. You can use this to rotate the offset \ without having to calculate the rotated offset yourself." endparam param offscale caption = "Offset Scale" default = 1.0 hint = "Scale of offset. You can use this to scale the offset \ without having to calculate the scaled offset yourself." endparam } dmj-PhoenixJulia { ; ; This does a few Phoenix Julia iterations to warp ; the fractal shape. Try using it with a ; Newton fractal. ; transform: complex y = (0,0) complex newz = (0,0) int i = @iters complex z = #pixel-@offset WHILE (i > 0 && |z| <= @bailout) newz = z^@power1 + z^@power2 * @seed + @induct * y y = z z = newz i = i - 1 ENDWHILE IF (|z| > @bailout) #solid = true ELSE #pixel = z+@offset ENDIF default: title = "Phoenix (Julia)" helpfile = "dmj-pub\dmj-pub-uf-mjpnx.htm" param iters caption = "Iterations" default = 4 hint = "Number of iterations to do before calculating the fractal. \ Use a small number." endparam param offset caption = "Offset" default = (0,0) hint = "Offsets the Phoenix Julia distortion." endparam param seed caption = "Julia Seed" default = (0.56667,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power1 caption = "Primary Exponent" default = (2,0) hint = "Defines the primary exponent for the fractal. The classic \ Phoenix curve uses exponent 2." endparam param power2 caption = "Secondary Exponent" default = (0,0) hint = "Defines the secondary exponent for the fractal. The classic \ Phoenix curve uses exponent 0." endparam param induct caption = "Phoenix Distortion" default = (-0.5,0) hint = "Sets how 'strong' the previous iteration's effect should be \ on the fractal." endparam param bailout caption = "Bailout" default = 1.0e20 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Phoenix set anymore. Bailed-out points will be \ solid-colored." endparam } dmj-Polar { ; ; This transform takes the current pixel, assumes real(pixel) ; is the angle, and imag(pixel) is the distance, and converts ; these back to the rectangular coordinates the UF expects. ; This can be used to undo the effects of the Rectangular to ; Polar transform. It can also be used to warp the heck out of ; your fractal. :) ; transform: #pixel = real(#pixel)*cos(imag(#pixel)) + flip(real(#pixel)*sin(imag(#pixel))) + @polcenter default: title = "Polar to Rectangular" helpfile = "dmj-pub\dmj-pub-uf-p2r.htm" param polcenter caption = "Polar Center" default = (0,0) hint = "This is the center of the polar coordinate system." endparam } dmj-SelectJulia { ; ; This formula "selects" a portion of the image, ; based on the iteration count for the Julia set at ; each pixel. ; transform: complex z = #pixel float b = @bailout IF (@strict) b = sqr(1+sqrt(1+4*cabs(@seed)))*0.25 ENDIF int i = 0 WHILE (|z| < b && i < @maxiter) z = z^@power + @seed i = i + 1 ENDWHILE float r = real(@xfer(flip(flip(i)))) r = r - trunc(r / @divisor) * @divisor IF (r < @remainder || r >= @remainder+@width) #solid = TRUE ENDIF default: title = "Select (Julia)" helpfile = "dmj-pub\dmj-pub-uf-select.htm" param maxiter caption = "Maximum Iterations" default = 150 hint = "Maximum number of iterations that will be performed \ for the transform." endparam param seed caption = "Julia Seed" default = (0,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power caption = "Exponent" default = (2,0) hint = "Overall exponent for the equation. (2,0) gives \ the classic Julia type." endparam param bailout caption = "Bailout" default = 128 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Mandelbrot set anymore." endparam param strict caption = "Strict Bailout" default = FALSE hint = "If set, uses 'strict' bailout checking, which varies \ the bailout value with each point. This will override \ the Bailout parameter." endparam param divisor caption = "Iteration Divisor" default = 2.0 hint = "The iteration count will be divided by this value, and \ the remainder taken." endparam param remainder caption = "Iteration Remainder" default = 1.0 hint = "If the remainder after dividing the iteration count \ does not match this value, the pixel will be colored \ 'solid'." endparam param width caption = "Band Width" default = 1.0 hint = "The width of the non-solid band, in iterations." endparam func xfer caption = "Iteration Transfer" default = ident() hint = "This function will be applied to the iteration count \ before it is divided." endfunc } dmj-SelectMandel { ; ; This formula "selects" a portion of the image, ; based on the iteration count for the M-set at each ; pixel. ; transform: complex z = @start float b = @bailout IF (@strict) b = sqr(1+sqrt(1+4*cabs(#pixel)))*0.25 ENDIF int i = 0 WHILE (|z| < b && i < @maxiter) z = z^@power + #pixel i = i + 1 ENDWHILE float r = real(@xfer(flip(flip(i)))) r = r - trunc(r / @divisor) * @divisor IF (r < @remainder || r >= @remainder+@width) #solid = TRUE ENDIF default: title = "Select (Mandelbrot)" helpfile = "dmj-pub\dmj-pub-uf-select.htm" param maxiter caption = "Maximum Iterations" default = 150 hint = "Maximum number of iterations that will be performed \ for the transform." endparam param start caption = "Start Value" default = (0,0) hint = "Starting value for each point. You can use this to \ 'perturb' the fractal." endparam param power caption = "Exponent" default = (2,0) hint = "Overall exponent for the equation. (2,0) gives \ the classic Mandelbrot type." endparam param bailout caption = "Bailout" default = 128 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Mandelbrot set anymore." endparam param strict caption = "Strict Bailout" default = FALSE hint = "If set, uses 'strict' bailout checking, which varies \ the bailout value with each point. This will override \ the Bailout parameter." endparam param divisor caption = "Iteration Divisor" default = 2.0 hint = "The iteration count will be divided by this value, and \ the remainder taken." endparam param remainder caption = "Iteration Remainder" default = 1.0 hint = "If the remainder after dividing the iteration count \ does not match this value, the pixel will be colored \ 'solid'." endparam param width caption = "Band Width" default = 1.0 hint = "The width of the non-solid band, in iterations." endparam func xfer caption = "Iteration Transfer" default = ident() hint = "This function will be applied to the iteration count \ before it is divided." endfunc } dmj-SelectNovaJulia { ; ; This formula "selects" a portion of the image, ; based on the iteration count for the Nova set at ; each pixel. ; transform: complex zsquared = (0,0) complex zcubed = (0,0) complex zold = (0,0) complex z = #pixel int i = 0 WHILE (|z-zold| > @bailout && i < @maxiter) IF (@power == (3,0)); special optimized routine for power 3 zsquared = sqr(z) zcubed = zsquared * z zold = z z = z - (zcubed-1) / (3*zsquared) + @seed ELSE zold = z z = z - (z^@power-1) / (@power * z^(@power-1)) + @seed ENDIF i = i + 1 ENDWHILE float r = real(@xfer(flip(flip(i)))) r = r - trunc(r / @divisor) * @divisor IF (r < @remainder || r >= @remainder+@width) #solid = TRUE ENDIF default: title = "Select (Nova Julia)" helpfile = "dmj-pub\dmj-pub-uf-select.htm" param maxiter caption = "Maximum Iterations" default = 150 hint = "Maximum number of iterations that will be performed \ for the transform." endparam param seed caption = "Julia Seed" default = (0,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power caption = "Exponent" default = (3,0) hint = "Overall exponent for the equation. (3,0) gives \ the classic Nova type." endparam param bailout caption = "Bailout" default = 0.00001 hint = "Bailout value; smaller values will cause more \ iterations to be done for each point." endparam param divisor caption = "Iteration Divisor" default = 2.0 hint = "The iteration count will be divided by this value, and \ the remainder taken." endparam param remainder caption = "Iteration Remainder" default = 1.0 hint = "If the remainder after dividing the iteration count \ does not match this value, the pixel will be colored \ 'solid'." endparam param width caption = "Band Width" default = 1.0 hint = "The width of the non-solid band, in iterations." endparam func xfer caption = "Iteration Transfer" default = ident() hint = "This function will be applied to the iteration count \ before it is divided." endfunc } dmj-SelectPhoenixJulia { ; ; This formula "selects" a portion of the image, ; based on the iteration count for the Phoenix set ; at each pixel. ; transform: complex y = (0,0) complex newz = (0,0) complex z = #pixel int i = 0 WHILE (|z| < @bailout && i < @maxiter) newz = z^@power1 + z^@power2 * @seed + @induct * y y = z z = newz i = i + 1 ENDWHILE float r = real(@xfer(flip(flip(i)))) r = r - trunc(r / @divisor) * @divisor IF (r < @remainder || r >= @remainder+@width) #solid = TRUE ENDIF default: title = "Select (Phoenix Julia)" helpfile = "dmj-pub\dmj-pub-uf-select.htm" param maxiter caption = "Maximum Iterations" default = 150 hint = "Maximum number of iterations that will be performed \ for the transform." endparam param seed caption = "Julia Seed" default = (0.56667,0) hint = "This is the Julia seed, a constant parameter which \ defines the shape of the fractal." endparam param power1 caption = "Primary Exponent" default = (2,0) hint = "Defines the primary exponent for the fractal. The classic \ Phoenix curve uses exponent 2." endparam param power2 caption = "Secondary Exponent" default = (0,0) hint = "Defines the secondary exponent for the fractal. The classic \ Phoenix curve uses exponent 0." endparam param induct caption = "Phoenix Distortion" default = (-0.5,0) hint = "Sets how 'strong' the previous iteration's effect should be \ on the fractal." endparam param bailout caption = "Bailout" default = 1.0e20 hint = "Defines how soon an orbit bails out, i.e. doesn't belong \ to the Phoenix set anymore." endparam param divisor caption = "Iteration Divisor" default = 2.0 hint = "The iteration count will be divided by this value, and \ the remainder taken." endparam param remainder caption = "Iteration Remainder" default = 1.0 hint = "If the remainder after dividing the iteration count \ does not match this value, the pixel will be colored \ 'solid'." endparam param width caption = "Band Width" default = 1.0 hint = "The width of the non-solid band, in iterations." endparam func xfer caption = "Iteration Transfer" default = ident() hint = "This function will be applied to the iteration count \ before it is divided." endfunc } dmj-SpiralCut { ; ; This transformation cuts your image into several slices, ; and then inflates the size of each slice independently. ; I got the idea for this from an old Photoshop plug-in. ; transform: complex center2 = @cutcenter IF (@centermove) center2 = #center ENDIF complex r = (0,1) ^ (@angle / 90.0) complex p0 = (#pixel-center2)*r complex p = p0 float a = atan2(p0) float d = cabs(p0) IF (@mode == 0) d = round(d*@density)/@density ELSEIF (@mode == 1) a = round(a*@density)/@density ELSEIF (@mode == 2) d = round(d*@density)/@density a = round(a*@density)/@density ELSEIF (@mode == 3) p = round(real(p)*@density)/@density + flip(imag(p)) ELSEIF (@mode == 4) p = round(real(p)*@density)/@density + flip(round(imag(p)*@density)/@density) ENDIF IF (@mode < 3) p = d * (cos(a) + flip(sin(a))) ENDIF #pixel = (p + (p0-p)*@boost) * conj(r) + center2 default: title = "Spiral Cut" helpfile = "dmj-pub\dmj-pub-uf-spiralcut.htm" param mode caption = "Cut Mode" default = 0 enum = "rings" "rays" "radial grid" "lines" "grid" endparam ; param nodistort ; caption = "No Squashing" ; default = true ; endparam param density caption = "Cut Density" default = 5.0 endparam param angle caption = "Cut Angle" default = 0.0 endparam param boost caption = "Cut Exaggeration" default = 2.0 endparam param cutcenter caption = "Cut Center" default = (0,0) hint = "Sets the center of the cut pattern. Use the eyedropper \ to pick it." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the cut pattern is assumed to be at the center of \ the window, regardless of the Cut Center setting." endparam } dmj-Spots { ; ; This uses to mosaic tile placement algorithm to choose ; "spots" to paint the image with. However, once a spot is ; found to cover a pixel, the remaining spots are not ; calculated. The overall effect is one of pointillist ; fractals. ; transform: complex center2 = @moscenter IF (@centermove) center2 = #center ENDIF int i = 0 float d = 0 float random1 = @seed1 float random2 = @seed2 float random3 = @seed3 complex p = 0 complex point1 = 0 float r1 = 0 float range = 1.0 / 2147483648.0 WHILE (i < @mostiles); still another tile to check random1 = (random1 * 1103515245 + 12345) % 2147483648.0 random2 = (random2 * 1103515245 + 12345) % 2147483648.0 random3 = (random3 * 1103515245 + 12345) % 2147483648.0 p = center2 + ((random1 - 1073741824) + flip(random2 - 1073741824)) * range * @mosscale d = |p - #pixel| r1 = (random3 * range) * (@mosmax-@mosmin) + @mosmin IF (d < r1) point1 = p i = @mostiles ENDIF i = i + 1 ENDWHILE IF (i == @mostiles) IF (@usesolid) #solid = true ENDIF ELSE #pixel = point1 + (#pixel-point1)*@tilescale ENDIF default: title = "Spots" helpfile = "dmj-pub\dmj-pub-uf-spots.htm" param mostiles caption = "Number of Spots" default = 500 hint = "Sets the number of spots. More spots take \ longer to render." endparam param moscenter caption = "Spotted Area Center" default = (0,0) hint = "Sets the center of the spotted area. The cluster of \ spots will be centered at this point." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the spotted area center is assumed to be at the center of \ the window, regardless of the Spotted Area Center setting." endparam param mosscale caption = "Spot Density" default = 5.0 hint = "Specifies the overall scale of the spots. Smaller numbers \ will pack the spots together more closely." endparam param tilescale caption = "Spot Magnification" default = 0.0 hint = "Specifies the scale of the image within each spot. Use 0 \ for solid-color spots, use 1 for no effect." endparam param mosmin caption = "Minimum Spot Size" default = 0.01 hint = "This is the minimum size a spot may be." endparam param mosmax caption = "Maximum Spot Size" default = 0.1 hint = "This is the maximum size a spot may be." endparam param usesolid caption = "Use Solid Color" default = true hint = "If set, points outside all spots will use the solid color. \ Otherwise, those points are untransformed." 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 param seed3 caption = "Random Seed 3" default = 654187327 hint = "This is the 'seed' for the random number generator for \ rotations." endparam } dmj-Stretch { ; ; Stretch transform that can use screen center. ; If you have a fractal image that you want to stretch on ; one axis only, and don't want to work out the (hairy) math ; to make the Stretch transform that comes with UF work, you ; can just apply this one. The usual caveats for zooming into ; an image with a "Use Screen Center" transform do apply, ; of course. ; transform: complex r = (0,1) ^ (@strangle / 90.0) complex center2 = @strcenter IF (@centermove) center2 = #center ENDIF complex z2 = (#pixel - center2) * r #pixel = (real(z2)*real(@strscale) + flip(imag(z2)*imag(@strscale))) * conj(r) + center2 default: title = "Stretch" helpfile = "dmj-pub\dmj-pub-uf-stretch.htm" param strcenter caption = "Stretch Center" default = (0,0) hint = "Sets the center of stretching. Use the eyedropper \ to pick the center of stretching." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, stretching is assumed to be at the center of \ the window, regardless of the Stretch Center setting." endparam param strscale caption = "Stretch Scale" default = (1,1) hint = "Sets the amount of stretching on each axis. The default \ of (1,1) produces no stretching (normal scale)." endparam param strangle caption = "Stretch Angle" default = 0.0 hint = "Sets the angle of stretching. You can use this to rotate \ the axes where stretching occurs." endparam } dmj-Symmetry { ; ; Symmetry Transformation ; This is simpler (and faster) to use for basic ; symmetry than Kaleidoscope. However, because ; the symmetry center is ALWAYS the image center, ; various surprising things may happen if you try ; to zoom on an image using this transform. ; transform: complex r = (0,1) ^ (#angle * 2/#pi); complex rotation vector complex z2 = (0,0) complex c = #center; symmetry center is screen center IF (@mode == 0); horizontal symmetry IF (#x > #width/2); point is in right half z2 = (#pixel-c) / r; flip it #pixel = r * (-conj(z2)) + c ENDIF ELSEIF (@mode == 1); vertical symmetry IF (#y > #height/2); point is in bottom half z2 = (#pixel-c) / r; flip it #pixel = r * (conj(z2)) + c ENDIF ELSEIF (@mode == 2); diagonal symmetry IF (#x+#y > (#width+#height)/2); point is in lower right half z2 = (#pixel-c) / r; flip it #pixel = r * (-z2) + c ENDIF ELSEIF (@mode == 3); horizontal + vertical symmetry IF (#x > #width/2); point is in right half z2 = (#pixel-c) / r; flip it #pixel = r * (-conj(z2)) + c ENDIF IF (#y > #height/2); point is in bottom half z2 = (#pixel-c) / r; flip it #pixel = r * (conj(z2)) + c ENDIF ENDIF default: title = "Symmetry" helpfile = "dmj-pub\dmj-pub-uf-symmetry.htm" param mode caption = "Symmetry Mode" default = 0 enum = "horizontal" "vertical" "diagonal" "horz + vert" "none" hint = "Style of symmetry." endparam } dmj-Triangle-Glass1 { ; ; I think I must be insane. ; ; This formula iterates the M-set and uses triangle inequality ; average coloring as a turbulence value. It is similar to fBm ; Glass 1, just with a different texture used for the turbulence. ; ; Don't try this at home, kids. ; transform: complex z = 0 complex c = #pixel complex r3 = (0,1) ^ (@distangle / 90.0) complex v = 0 ; translate/scale c = c/@mandscale + @mandcenter float sum = 0.0 float sum2 = 0.0 float ac = cabs(c) float il = 1/log(@mandpower) float lp = log(log(@mandbailout)/2.0) float az2 = 0.0 float lowbound = 0.0 float f = 0.0 BOOL first = true float ipower = 1/@apower int i = 0 WHILE (i < @manditer && |z| < @mandbailout) z = z^@mandpower + c i = i + 1 sum2 = sum IF (!first) az2 = cabs(z - c) lowbound = abs(az2 - ac) IF (@aflavor == 0) sum = sum + ((cabs(z) - lowbound) / (az2+ac - lowbound))^@apower ELSEIF (@aflavor == 1) sum = sum + 1-(1-(cabs(z) - lowbound) / (az2+ac - lowbound))^ipower ENDIF ELSE first = false ENDIF ENDWHILE sum = sum / i sum2 = sum2 / (i-1) f = il*lp - il*log(log(cabs(z))) f = sum2 + (sum-sum2) * (f+1) ; f = f - floor(f) c = @distcenter IF (@centermove) c = #center ENDIF IF (@style == 0) ; radial distortion v = (#pixel-c)/cabs(#pixel-c) * r3 ; use vector based on angle to distortion center ELSEIF (@style == 1) ; linear distortion v = r3 ; just use rotation vector ENDIF #pixel = #pixel + v * f*0.5*@distortion default: title = "TIA Glass 1" helpfile = "dmj-pub\dmj-pub-uf-tiag1.htm" param distortion caption = "Distortion Strength" default = 1.0 hint = "This is the amount the noise distorts the image." endparam param style caption = "Distortion Style" default = 0 enum = "radial" "linear" hint = "This selects whether the distortion will be focused \ around a single point, or directed along a line." endparam param distangle caption = "Distortion Angle" default = 0.0 hint = "This is the angle to rotate the distortion." endparam param distcenter caption = "Distortion Center" default = (0,0) hint = "Sets the center of distortion. If Use Screen \ Center is set, this item is ignored." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, distortion will be around the center of \ the window, regardless of the Distortion Center \ setting." endparam param mandpower caption = "Mandelbrot Power" default = 2.0 hint = "Overall exponent for the equation. (2,0) gives \ the classic Mandelbrot type." endparam param mandbailout caption = "Mandelbrot Bailout" default = 1.0e10 hint = "Bailout value; larger values will cause more \ iterations to be done for each point." endparam param mandcenter caption = "Mandelbrot Center" default = (0,0) hint = "Center of Mandelbrot shape; this can be used to offset \ the distortion." endparam param mandscale caption = "Mandelbrot Scale" default = 1.0 hint = "Scale of Mandelbrot shape; this can be used to change \ the size of the Mandelbrot shape relative to the distorted \ fractal." endparam param manditer caption = "Mandelbrot Iterations" default = 100 hint = "Maximum number of Mandelbrot iterations to do." endparam param apower caption = "Average Exponent" default = 1.0 hint = "This skews the values averaged by raising them to \ this power. Use 1.0 for the classic coloring." endparam param aflavor caption = "Average Flavor" default = 0 enum = "normal" "reversed" hint = "Controls whether values are reversed before being \ raised to a power. Has no effect if Average Exponent \ is 1.0." endparam ; param power ; caption = "Exponent" ; default = 2.0 ; hint = "This should be set to match the exponent of the \ ; formula you are using. For Mandelbrot, this is 2." ; endparam ; param bailout ; caption = "Bailout" ; default = 1e20 ; min = 1 ; hint = "This should be set to match the bailout value in \ ; the Formula tab. Use a very high bailout!" ; endparam } dmj-Twirl { ; ; Ripple Transformation ; This transform will add ripples to a fractal. ; Add multiple transforms for interference effects. ; transform: complex center2 = @twirlcenter IF (@centermove) center2 = #center ENDIF float d = cabs(#pixel-center2) IF (d < @twirlfade) IF (@twirltype == 0); side to side #pixel = (#pixel-center2) * (0,1) ^ (cos(d*@twirlpitch*#pi) * @twirlscale * sqr(1-d/@twirlfade)) + center2 ELSEIF (@twirltype == 1); forward and back #pixel = (#pixel-center2) * (1 - cos(d*@twirlpitch*#pi) * @twirlscale * sqr(1-d/@twirlfade)) + center2 ELSEIF (@twirltype == 2); in and out float d2 = atan(imag(#pixel-center2)/real(#pixel-center2)) IF (real(d2) < 0); pointing to left d2 = d2 + #pi; rotate 180 degrees ENDIF IF (d2 < 0); negative angle (we want 0 < atan < pi*2) d2 = d2 + #pi * 2; rotate 360 degrees ENDIF #pixel = (#pixel-center2) * (1 - cos(d2*@twirlpitch) * @twirlscale * sqr(1-d/@twirlfade)) + center2 ELSEIF (@twirltype == 3); back and forth float d2 = atan(imag(#pixel-center2)/real(#pixel-center2)) IF (real(d2) < 0); pointing to left d2 = d2 + #pi; rotate 180 degrees ENDIF IF (d2 < 0); negative angle (we want 0 < atan < pi*2) d2 = d2 + #pi * 2; rotate 360 degrees ENDIF #pixel = (#pixel-center2) * (0,1) ^ (cos(d2*@twirlpitch) * @twirlscale * sqr(1-d/@twirlfade)) + center2 ENDIF ENDIF default: title = "Ripples" helpfile = "dmj-pub\dmj-pub-uf-ripples.htm" param twirlcenter caption = "Ripple Center" default = (0,0) hint = "Sets the center of the ripples." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, ripples will be around the center of \ the window, regardless of the Ripple Center \ setting." endparam param twirlscale caption = "Ripple Strength" default = 0.25 hint = "Sets the height of the ripples." endparam param twirlpitch caption = "Ripple Frequency" default = 10.0 min = 0.0 hint = "Frequency of ripples; higher values will give \ more densely packed ripples." endparam param twirlfade caption = "Ripple Fade" default = 1.0 min = 0.00000001 hint = "Distance at which ripples fade." endparam param twirltype caption = "Ripple Type" default = 1 enum = "Side to Side" "Forward and Back" "In and Out" "Back and Forth" hint = "Orientation of ripples with respect to the \ ripple center." endparam } dmj-Unpolar { ; ; This transform converts the normal rectangular coordinates ; used by UF to polar coordinates, such that real(pixel) is ; the angle and imag(pixel) is the distance. By itself, this ; can just warp your fractal quite dramatically, but you can ; also use this in conjuction with the Polar to Rectangular ; transform to make any other transform (sandwiched between ; the two) operate on polar coordinates instead of rectangular ; coordinates. ; transform: #pixel = cabs(#pixel-@polcenter) + flip(atan2(#pixel-@polcenter)) default: title = "Rectangular to Polar" helpfile = "dmj-pub\dmj-pub-uf-r2p.htm" param polcenter caption = "Polar Center" default = (0,0) hint = "This is the center of the polar coordinate system." endparam } dmj-Unspiral { ; ; This undoes a spiral, straightening the arms. ; You will have to play a bit to get this to ; exactly match. You can of course also use this ; to APPLY a spiral transformation. :-) ; transform: complex center2 = @spicenter IF (@centermove) center2 = #center ENDIF complex z2 = #pixel - center2 #pixel = (z2)*(0,1)^(log(cabs(z2))*@spipower) + center2 default: title = "Unspiral" helpfile = "dmj-pub\dmj-pub-uf-unspiral.htm" param spicenter caption = "Spiral Center" default = (0,0) hint = "Sets the center of the spiral. Use the eyedropper \ to pick the center of the spiral." endparam param centermove caption = "Use Screen Center" default = TRUE hint = "If set, the spiral is assumed to be at the center of \ the window, regardless of the Spiral Center setting." endparam param spipower caption = "Spiral Power" default = 1.0 hint = "Sets the 'tightness' of the spiral. Tweak this until \ the spiral arms are straight." endparam }