/////////////////////////////////////////////////////////////////////////////////////////// // // Twisted Torus macro // // Written by Richard Dault (rdault@yahoo.com) // // This file contains a macro that creates a twisted torus. I included support for // sphere_sweep, but I recommend using only blobs. They are much faster. The more parts // you specify, the smoother it gets. The blobbing takes care of the rest. // // Feel free to modify or use this code for your own personal use. Enjoy. // /////////////////////////////////////////////////////////////////////////////////////////// // Include almost everything for textures #include "colors.inc" #include "metals.inc" #include "stones.inc" #include "woods.inc" #include "glass.inc" // MegaPov is only needed for sphere sweeps. Can be removed if you only use blobs. #version unofficial MegaPov 0.5; camera { location <50,110,-90> look_at 0 } light_source { <-300,2000,-2000> color White } light_source { <20,500,0> color White*.5 } // Area lights for smoother shadows //light_source { <-300,2000,-2000> color White area_light y*3 x*3 5 5 } //light_source { <20,500,0> color White*.5 area_light x*3 z*3 5 5 } // The different objects type - see below #declare SPHERE = 1; #declare CYLINDERX = 2; #declare CYLINDERY = 3; #declare SWEEP = 4; /////////////////////////////////////////////////////////////////////////////////////////// // This is the macro // The arguments are as follows: // rad - the size of the spheres or cylinder radius // major - the major radius of the torus // rad1 - the radius of the spirals making the torus // count1 - the number of loops // rad2 - the radius of the spirals making the spirals making the torus :) // count2 - the number of loops for the above (usually bigger than count1) // loops - the number of times the spirals will go around the torus // this is like taking one big tube and passing it 'loops' times around to make the torus // Note: if loops > count1 and mod(loops,count1) = 0 then actual number of loops = loops/count1 // or if loops < count1 and mod(count1,loops) = 0 then actual number of loops = count1 // useblob - blob the object together (true/false) - this is ignored with type=SWEEP // objtype - the type of objects making the torus (SPHERE, CYLINDERX, CYLINDERY, SWEEP) // Note: blobs are so much faster than sweeps // parts - the number of parts making the 'tube' // this does not have to be very high for a sweep - if you make it too high, it will take forever to render // for blobs, the higher you make it, the smoother it gets /////////////////////////////////////////////////////////////////////////////////////////// #macro twistedtorus(rad, major, rad1, count1, rad2, count2, loops, useblob, objtype, parts) #local RAD = 0; #local twistdeg1 = 0; #local twistdeg2 = 0; #local slicedeg = 2*pi/parts; // changing the two values below can have interesting results but usually non-symmetrical #local ANGLE1 = 90; // the number of degrees to rotate the twist #local ANGLE2 = 180; // the number of degrees to rotate the twist of the twist #local initrad = rad; // OFFSET is to add a slight offset to each slice size so that we can do multiple loops #if ( loops = 1 ) #local OFFSET = 0; //SLICE/LOOP; #else #local OFFSET = slicedeg/(loops-1); #end #local i = 0; #if ( objtype = SWEEP ) sphere_sweep { b_spline_sphere_sweep parts*loops+3, #else #if ( useblob ) blob { threshold .7 #else union { #end #end #while ( i < parts*loops+3 ) // by uncommenting and altering the next line, you can change the radius in each twist //#local rad = initrad + (2-4*sin(twistdeg1)); #if ( objtype = CYLINDERX | objtype = CYLINDERY | objtype = SPHERE ) #switch ( objtype ) #case ( CYLINDERX ) cylinder { <15,0,0> <-15,0,0> rad #break #case ( CYLINDERY ) cylinder { <0,15,0> <0,-15,0> rad #break #else // SPHERE sphere { 0, rad #break #end #if ( useblob ) 1 #end // uncommenting the either one of these next two lines allows you to change the texture at // in each twist - you cal also try changing it to use twistdeg1 instead of twistdeg2 //texture { pigment { gradient y color_map {[0 color White][1 color DarkGreen]} } scale 3 } //pigment { color rgb } // you need to use rad2 and count2 for this one translate <0,rad2*cos(twistdeg2),rad2*sin(twistdeg2)> rotate z*(ANGLE1+degrees(twistdeg1)) translate rotate y*(ANGLE2-degrees(RAD)) translate } #else // SWEEP #local POINT = <0,rad2*cos(twistdeg2),rad2*sin(twistdeg2)>; #local POINT = vrotate(POINT,z*(ANGLE1+degrees(twistdeg1))); #local POINT = POINT + ; #local POINT = vrotate(POINT,y*(ANGLE2-degrees(RAD))); #local POINT = POINT + ; POINT rad #end #local i = i + 1; #local RAD = RAD + slicedeg + OFFSET; #local twistdeg1 = twistdeg1 + slicedeg*count1; #local twistdeg2 = twistdeg2 + slicedeg*count2; #end } #end /////////////////////////////////////////////////////////////////////////////////////////// // Here are many examples on how to use it. // Just uncomment which one you want to render and choose a plane at the bottom of the file. /////////////////////////////////////////////////////////////////////////////////////////// // Simple coil // try uncommenting the radius modifier in the macro too #declare A = function { pigment { marble turbulence 0.85 color_map {[0 color rgb 0][1 color rgb 1]} scale <1, .6, 1> rotate <10, 0, -20> } } #declare B = function { pigment { marble turbulence 0.7 scale <1.3, 2.5, 1.7> rotate <0, 0, 40> } } #declare C = function { pigment { granite turbulence 0.0 scale <1, 2, 2> rotate <0, 0, 40> } } object { twistedtorus(10,50,15,6,0,0,1,true,SPHERE,500) texture { T_Stone21 scale 50 } normal { function { A(x,y,z) | B(x,y,z) | C(x,y,z) } scale 50 } rotate y*20 translate y*20 } // glass torus with wire around it - warning: SLOW! to make it faster - convert to blobs // this is an example using a sphere sweep but would work as well as a blob - just increase the number of parts to something like 5000 /* union { // cheated here.. technically, we can use the macro, but it's much faster to use the old torus //object { twistedtorus(8,50,0,0,0,0,1,false,SWEEP,50) texture { T_Glass3 } interior { I_Glass } } torus { 50 8 texture { T_Glass3 } interior { I_Glass } } object { twistedtorus(2,50,11,10,0,0,1,false,SWEEP,50) texture { T_Gold_2D } } object { twistedtorus(2,50,11,10,0,0,1,false,SWEEP,50) texture { T_Silver_2D } rotate y*180/10} translate y*12 } */ // green yucky one - example with loop > 1 /* object { twistedtorus(8,50,10,5,5,60,2,true,SPHERE,1000) texture { pigment { crackle color_map { [0 color DarkGreen ][1 color Green] } } finish { phong .9 } } normal { function { pigment { crackle } } } translate y*14 } */ // gold mesh - lots of loops - looks like a spring //object { twistedtorus(1,50,15,5,0,0,12,true,SPHERE,1000) texture { T_Gold_2B } translate y*15.5 } // neon example - this shows the twisting of a twist // for best effect you should uncomment the pigment statment in the macro but only for the second twistedtorus // how I did my image was modify the macro and add a parameter - if =0 it would do color Black if =1 it would // do the color change /* union { object { twistedtorus(3,50,11,5,0,0,3,false,SPHERE,500) pigment { color Black } } object { twistedtorus(2,50,11,5,5,130,3,true,SPHERE,5000) texture { pigment { color NeonBlue } finish { ambient 1 } } } translate y*14 } */ // fancy mesh //object { twistedtorus(2,50,15,25,5,100,1,true,SPHERE,5000) texture { T_Gold_2D } translate y*16 } // cool sphere - almost like a light cover // you can get some neat shapes by shrinking the major radius and enlarging the twists //object { twistedtorus(2,0,40,10,5,80,1,true,SPHERE,5000) texture { pigment { color White } } } // corn on the cob // by not blobbing the spheres you get this corn or snake skin look /* object { twistedtorus(4,40,25,5,5,500,1,false,SPHERE,5000) texture { pigment { color rgb <244/255,227/255,49/255> } finish { phong .4 } } translate y*27 } */ // lasagna-like torus // this is an example using cylinder blobs that originated on the X axis /* object { twistedtorus(2,50,20,4,1,100,2,true,CYLINDERX,5000) texture { pigment { color Gold } finish { phong .8 } } translate y*20 } */ // frilly torus // similar to above but more frilly /* object { twistedtorus(2,50,10,6,5,100,1,true,CYLINDERX,5000) texture { pigment { color BlueViolet } finish { phong .8 } } translate y*20 } */ // frilly torus 2 // similar to above but using a cylinder that originated on the Y axis /* object { twistedtorus(2,50,10,6,5,10,1,true,CYLINDERY,5000) texture { pigment { color BlueViolet } finish { phong .8 } } translate y*20 } */ // spiral-like torus // now combine a CYLINDERX and a CYLINDERY /* object { twistedtorus(2,50,10,6,0,0,1,true,CYLINDERX,5000) texture { pigment { agate turbulence .2 pigment_map {[0 color DarkGreen][.5 color DarkGreen][.5 color Yellow][.6 color DarkGreen][1 color DarkGreen]} } finish { phong .7 } scale 30 } translate y*25 } object { twistedtorus(4,50,10,6,0,0,1,true,CYLINDERY,5000) texture { pigment { agate turbulence .2 pigment_map {[0 color Yellow][.4 color Yellow][.5 color DarkGreen][.6 color Yellow][1 color Yellow]} } finish { phong .7 } scale 30 } translate y*25 } */ // Keep in mind that since blobs are finite, they can be CSG'ed /* difference { object { twistedtorus(2,50,5,10,0,0,1,false,CYLINDERY,1000) } object { twistedtorus(3,50,15,10,0,0,1,false,SPHERE,1000) } pigment { color Red } } */ // Pick your floor // Here's a bunch of floors to put under your torus // Plain blue with some bumps /* plane { y 0 texture { pigment { color SteelBlue } finish { phong .8 reflection .8 } } normal { bumps .1 scale 15 } } */ // Plain Green //plane { y 0 texture { pigment { color DarkGreen } } } // Checkers //plane { y 0 texture { pigment { checker color Black color White scale 50 } finish { reflection .5 } } } // Simple granite //plane { y 0 texture { T_Grnt21 scale 50 finish { reflection .3 } } } // Wood plane { y 0 texture { T_Wood2 finish { reflection .4 /* reflection_blur .01 reflection_samples 100 */ } } scale 100 } // Pink marble //plane { y 0 texture { T_Stone5 finish { reflection .3 /* reflection_blur .01 reflection_samples 100 */ } } scale 75 }