/* kIFSe.pov 2010 Samuel Benge With this scene file you can explore the world of Kaleidoscopic IFS fractals. These objects will produce fractal detail at any level, provided you adjust the settings to account for the finer details. It renders a single isosurface with fast cavity shading. There are a number of settings to change, but feel free to alter the core routines too. Scene settings (camera, lights, act.) are at the bottom of the file. Have fun! __________ Parameters ŻŻŻŻŻŻŻŻŻŻ Symmetry ŻŻŻŻŻŻŻŻ The reflection set to use. It is possible to expand the symmetry set array to include your own reflection planes. Available symmetry sets: 0 = tetrahedral 1 = cubic 2 = octahedral 3 = icosahedral COS ŻŻŻ Center of scaling. Change this for different polyhedra depending on the symmetry set. tetrahedral symmetry COS: <1,1,1> = tetrahedron COS: <0,1,0> = octahedron COS: <.5,1,.5> = truncated tetrahedron cubic symmetry COS: <1,1,1> = cube octahedral symmetry COS: <1,1,1> = cube COS: <0,1,0> = octahedron COS: <.5,.5,0> = truncated octahedron COS: <.5,1,.5> = truncated octahedron with cut edges icosahedral symmetry (Phi is predefined) COS: <1,Phi,0> = icosahedron COS: <1,1,1> = dodecahedron COS: Lerp(<1,Phi,0>, , 1/3) = soccer ball (truncated icosahedron) COS: Lerp(<1,Phi,0> ,<1,1,1>, .5) = truncated icosahedron with cut edges and dodecahedral tendencies Scale ŻŻŻŻŻ This is the amount of scaling per-iteration. You can turn, say, an octahedron into an octahedral Sierpinki's Gasket by changing this. Common values: 1.5 = polyhedra, 2 = Sierpinski's Gaskets (not just for infinite improbability drives anymore) Iters ŻŻŻŻŻ Number of iterations. Try to keep it above 20. Substance ŻŻŻŻŻŻŻŻŻ This value will be subtracted from the isosurface function to give the shape substance, and will also determine how fine to make the detail. Lower substance values will produce more detail, higher values will make a simpler object. If you want to render deep zooms, make this value *very* small, with a low accuracy value for the isosurface. Default: 0.001 Accuracy ŻŻŻŻŻŻŻŻ This is just a shortcut to the isosurface's accuracy. It's best to have it around Substance/10. Max_Gradient ŻŻŻŻŻŻŻŻŻŻŻŻ A shortcut to the isosurface's max_gradient. Usually a value between 0.5 - 1.0 will suffice, but you should check the message pane after a test render to find the correct value to use. Coloring_Mult ŻŻŻŻŻŻŻŻŻŻŻŻŻ This will affect the cavity shader used to color the object. It will need to be adjusted after changing other settings. It is very sensitive to the number of iterations. Make sure to settle on a good iteration value before making many changes to the other settings. Coloring_Mult will need to be tweaked to get the right coloring. The cavity shader is far from perfect, so if you make any useful changes, let me know! Pre_Transform() & Post_Transform() ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ These macros can be used to transform the object before and after the symmetry planes are applied. This is one good way to get the most out of Kaleidoscopic IFS fractals. Make_Container() ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ You can change the isosurface's containing object with this macro. A default Container_Center is provided, though how well it works has yet to be determined. It's best to center the object _after_ it is textured (example provided). Some objects may need a box container. Do_Stuff() ŻŻŻŻŻŻŻŻŻŻ This macro will be called directly inside the isosurface object's definition after Make_Container() has been called. With it you can texture the object, do transforms, or whatever. ____ Tips ŻŻŻŻ Keep the center of scaling in the "plus" range. (eg. COS = <1,1,1>) If you're unsure of what kind of containing object to use, start off with a large box: contained_by{ box{-2,2} } If the cavity shader produces lots of weird banding, try lowering the Accuracy value. To preview the shader, add this after the cavity shading in the Do_Stuff() macro: finish{ambient 1 diffuse 0} no_shadow Some transforms will not work well at all. Rotations and translations are best. Adding new reflection planes for non-uniform symmetries will require additional code. The center of the reflection planes needs to be accounted for. _______ Contact ŻŻŻŻŻŻŻ Decode the following, because I hate spam: gestneb@hotmail.com 3472516@hotmail.com */ // Helful items for editing parameters #macro Lerp(a,b,c) a*(1-c)+b*c #end // linear interpolation between two values #declare Phi = (1+sqrt(5))/2; // The Golden Ratio (used for icosahedral symmetries) //ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ// // editable parameters // //_________________________// #declare Symmetry = 3; #declare COS = <1,Phi,0>; #declare Scale = 2; #declare Iters = 40; #declare Substance = 0.001; #declare Accuracy = Substance/10; // might never need to be changed #declare Max_Gradient = 1.0; #declare Coloring_Mult = 6.1; #macro Pre_Transform() //rotate y*3 #end #macro Post_Transform() //translate y*.2 #end #macro Make_Container() #declare Container_Center = COS/2; // this seems to work OK for most configurations #declare Container_Radius = 1.5; // change radius as needed contained_by{ sphere{Container_Center, Container_Radius} } #end #macro Do_Stuff() pigment{ pigment_pattern{ // cavity shading function{Kaleidoscopic_IFS(Iters, true)} color_map{[0 rgb 1][1 rgb 0]} } poly_wave 4 // adjusting the falloff color_map{[0 rgb<0,.035,.1>][.55 rgb<1,.9,.6>]} } //finish{ambient 1 diffuse 0} no_shadow // uncomment this for fast preview translate -Container_Center // centering the object scale 2.5 rotate y*22 #end //ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ// // end editable parameters // //_________________________// // Expand this array to add new symmetry sets #declare Symmetry_Planes = array[4]{ // 0 = tetrahedral array[6]{ x+z, y+z, -x+y, x-z, x+y, y-z } // 1 = cubic array[3]{ x, y, z } // 2 = octahedral array[6]{ -x+y, y-z, x-y, x, y, z } // 3 = icosahedral array[9]{ vnormalize(<0,1,Phi>-), vnormalize(-<0,1,Phi>), vnormalize(<0,1,Phi>-<-1,Phi,0>), z, vnormalize(<1,Phi,0>-), vnormalize(-<0,1,Phi>), y, x, z } // Your reflection planes here } #declare CX = COS.x; #declare CY = COS.y; #declare CZ = COS.z; // Copied from transforms.inc for speed #macro VPerp_To_Vector(v0) #if (vlength(v0) = 0) #local vN = <0, 0, 0>; #else #local Dm = min(abs(v0.x), abs(v0.y), abs(v0.z)); #if (abs(v0.z) = Dm) #local vN = vnormalize(vcross(v0, z)); #else #if (abs(v0.y) = Dm) #local vN = vnormalize(vcross(v0, y)); #else #local vN = vnormalize(vcross(v0, x)); #end #end #end vN #end #macro Shear_Trans(A, B, C) transform { matrix< A.x, A.y, A.z, B.x, B.y, B.z, C.x, C.y, C.z, 0, 0, 0 > } #end #macro Point_At_Trans(YAxis) #local Y = vnormalize(YAxis); #local X = VPerp_To_Vector(Y); #local Z = vcross(X, Y); Shear_Trans(X, Y, Z) #end // reflect a pigment from a plane (plane = vnormalize(from_pt - to_pt)) #macro Reflect_Plane(V_Plane) transform{ Point_At_Trans(V_Plane) inverse } warp{repeat y*1e7 flip y} Point_At_Trans(V_Plane) #end // reflect all planes in a set #macro Reflect_All_Planes(Plane_Set) #local V=0; #while(V*1e8; #local rgb_sun = rgb<1.5,1.4,1.2>*1.3; light_source{l_pos, rgb_sun }//area_light x*1e8,z*1e8,4,4 jitter} light_source{<.3,.5,-1>*1e8,<.12,.12,.1> }//shadowless}// area_light x*1e8,z*1e8,2,2 jitter } camera{ right x*2 up y*2 location -z*10+y*7 look_at 0 angle 30 } sky_sphere{ pigment{ spherical scale 2 translate y Point_At_Trans(l_pos) cubic_wave warp{turbulence .1 lambda 3} pigment_map{ [0 rgb <0,.03,.15>] [1 rgb_sun] } } } global_settings{ max_trace_level 2 #if(0) // relatively low radiosity settings which work well for high-accuracy objects radiosity{ count 15 error_bound .1 pretrace_start .08 pretrace_end .04 nearest_count 1 recursion_limit 1 brightness 1 gray_threshold 0 adc_bailout 1/256 } #end } //ŻŻŻŻŻŻŻŻŻŻŻ// // end scene // //___________//