// Last edited on 2012-09-26 00:15:11 by stolfilocal #macro vortex_layer_color(sp) // Theme color for layer {sp} (from 0 to 1). #local col0 = < 0.000, 0.880, 0.500 >; // 0.5830 #local col1 = < 0.200, 0.715, 1.000 >; // 0.5970 #local col = rgb col0*(1-sp) + col1*sp; col #end #macro vortex_layer_texture(sp) // Tetxure for tube of layer {sp} (from 0 to 1). #debug "ENTER vortex_layer_texture\n" #local col0 = vortex_layer_color(sp); #local wht = <1,1,1>; #local mix_dust = 0.65; #local col_dust = (1-mix_dust)*wht + mix_dust*col0; #local mix_glas = 0.12; #local col_glas = (1-mix_glas)*wht + mix_glas*col0; #local tx = texture{ pigment{ color col_glas filter 0.98 } finish{ diffuse 0.00 reflection 0 ambient 0.00 specular 0.00 roughness 0.005 } } texture{ pigment{ color col_dust transmit 0.50 } finish{ diffuse 0.80 reflection 0 ambient 0.20 specular 0.00 roughness 0.005 } } #local bogus = 0; tx #debug "EXIT vortex_layer_texture\n" #end #macro vortex_particle_texture(sp) // Tetxure for particles of layer {sp} (from 0 to 1). #local col0 = vortex_layer_color(sp); #local col1 = < 0.950, 0.800, 0.200 >; // 0.7775 #local mix = 0.50; #local col = (1-mix)*col1 + mix*col0; #local tx = texture{ pigment{ color col } finish{ diffuse 0.60 reflection 0 ambient 0.40 specular 0.00 roughness 0.005 } } #local bogus = 0; tx #end #macro vortex_particle_orbit_texture(sp) #local col = vortex_layer_color(sp); #local tx = texture{ pigment{ color 0.50*col } finish{ diffuse 0.90 reflection 0 ambient 0.10 specular 0.00 roughness 0.005 } } #local bogus = 0; tx #end #declare vortex_layer_in = interior{ ior 1.00 } #declare vortex_core_tx = texture{ pigment{ color rgb < 0.850, 0.950, 1.000 > filter 0.97 } finish{ diffuse 0.03 reflection 0 ambient 0.05 specular 0.25 roughness 0.005 } } #declare vortex_core_in = interior{ ior 1.1 } #declare vortex_axis_tx = texture{ pigment{ color rgb < 0.800, 0.100, 0.000 > } finish{ diffuse 0.80 reflection 0 ambient 0.20 specular 0.00 roughness 0.005 } } #macro vortex_all(R,ra,rc,dr,ang,max_nr,top_nro,bot_nro,np_min,nlayers,tt) // The vortex axis is a circle of radius {R} on the YZ cardinal plane, centered // at {C = <0,-R,0>}; so that the vortex axis goes through the origin. // The whole vortex covers an interval of angles from {-ang} to {+ang} // (degrees) as seen from the center {C}. // // {R} Radius of axis. // {rc} Radius of axis. // {rc} Radius of core. // {dr} Spacing between layers. // {ang} Half-exent of vortex in longitude. // {max_nr} Particle rings in innermost layer above and below midplane. // {top_nro} Particle rings to omit from top in each layer. // {bot_nro} Particle rings to omit from bot in each layer. // {np_min} Particles per ring in innermost layer. // {nlayers} Number of layers. // {tt} Phase of movie (0 to 1). #debug "ENTER vortex_all\n" #local pr_st = 2*ang/(2*max_nr); // Ang dist between successive particle rings. #local pr_rp = 0.08*dr; // Radius of particles. #local pr_skew = 0.5; // Relative offset between successive particle rings. #local pr_turns = 2; // Full turns in innermost layer as {tt} goes from 0 to 1. #local atop_st = 0.00*pr_st; // Ang dist between tops of successive layers. #local thk = 0.03*dr; // Thickness of layer tubes. union{ #local i = 1; #local pr_ini = -max_nr; // Index of first particle ring. #local pr_fin = +max_nr; // Index of last particle ring. #while (i <= nlayers) #debug concat("layer ", str(i,0,0), "\n") #local ri = i*dr; // Small radius of layer. #local wi = pr_turns*360/(i*i); // Angular speed of layer (degrees/cycle). #local sp = (i-1)/(nlayers - 1); // Spectral index for coloring. #local abot = -ang; // Bottom angle of tube (degrees). #local amid = pr_fin*pr_st; // Bottom angle of tube cutout (degrees). #local atop = +ang - (i-1)*atop_st; // Top angle of tube (degrees). object{ vortex_layer(sp,R,ri,abot,amid,atop,thk,tt) } #local pr_np = np_min*i; // Number of particles per orbit in this layer. #if (mod(pr_turns*pr_np, i*i) != 0) #debug "** animation will not close - aborted\n" #local j = 1/(i - i); #end object{ vortex_layer_particles(sp,R,ri,pr_ini,pr_fin,pr_st,pr_np,pr_rp,pr_skew,wi,tt) } #local pr_ini = pr_ini + bot_nro; #local pr_fin = pr_fin - top_nro; #local i = i + 1; #end #if (rc > 0) #local r_core = rc; #local abot_core = -ang - 1.00*pr_st; #local atop_core = +ang + 1.00*pr_st; object{ vortex_core(R,r_core,abot_core,atop_core) } #end #if (ra > 0) #local r_axis = ra; // Radius of axis line. #local d_axis = 6.0*ra; // Dash length of axis line. #local abot_axis= -ang - 2.00*pr_st; #local atop_axis= +ang + 2.00*pr_st; object{ vortex_axis(R,r_axis,d_axis,abot_axis,atop_axis) } #end } #end #macro vortex_layer(sp,R,r,abot,amid,atop,thk,tt) // Aayer of the vortex. // The layer is a section of a torus whose longitudinal axis circle has // radius {R}, lies on on the YZ cardinal plane, and is centered // at {C = <0,-R,0>}; so that it goes through the origin. // The layer covers an interval of angles from {abot} to {atop} // with a cutout starting at {amid} (degrees) as seen from the center {C}. // {sp} is the spectral index of the layer's color (0 to 1). #debug "ENTER vortex_layer\n" object{ vortex_torus_slice(R,r,abot,amid,atop,thk,false) interior{ vortex_layer_in } texture{ vortex_layer_texture(sp) } } #debug "EXIT vortex_layer\n" #end #macro vortex_layer_particles(sp,R,r,ini,fin,st,np,rp,skew,w,tt) // Particles in one layer of the vortex. // The parameters {R,r,tt} as as in {vortex_layer}. // {ini} index of first particle ring. // {fin} index of last particle ring. // {st} longitude spacing of rings (degrees). // {np} number of particles per ring. // {rp} radius of each particle. // {skew} is the relative offset between particles in successive rings. // {w} is the angular speed (degrees/cycle). // {sp} is the spectral index of the particle color (0 to 1). #local ro = r; // Radius of particle orbits. #local alat_st = 360/np; // Angular spacing between particles in each ring. #local askew_st = skew*alat_st; // Extra skew between successive orbits. #debug "ENTER vortex_layer_particles\n" union{ #local askew = 0; #local alon = (ini + 0.5)*st; #local k = ini; #while (k < fin) object{ vortex_particle_ring(sp,ro,rp,np) rotate (w*tt + askew)*z translate +R*y rotate alon*x translate -R*y } #local askew = askew + askew_st; #local alon = alon + st; #local k = k + 1; #end } #debug "EXIT vortex_layer_particles\n" #end #macro vortex_particle_ring(sp,ro,rp,np) // {ro} = radius of orbit // {rp} = radius of particle. // {np} = number of particles in ring. #local alat_st = 360/np; // Angular spacing between particles in each ring. #local rr = rp/4; // Minor radius of orbit line. union{ torus{ ro, rr rotate 90*x texture{ vortex_particle_orbit_texture(sp) } } #local j = 0; #while (j < np) sphere{ < 0, ro, 0>, rp rotate j*alat_st*z texture{ vortex_particle_texture(sp) } } #local j = j + 1; #end } #end #macro vortex_core(R,r,abot,atop) object{ vortex_torus_slice(R,r,abot,atop,atop,0.0,false) interior{ vortex_core_in } texture{ vortex_core_tx } } #end #macro vortex_axis(R,r,d,abot,atop) #debug "ENTER vortex_axis\n" #local dash_spc = 0.67; // Ratio of dash gap over dash length. #local dash_n = int(R*radians(atop - abot)/(d*(1+dash_spc)) + 0.5); // Num of dashes. #debug concat("dash_n", str(dash_n,1,0), "\n") #local dash_len = (atop - abot)/(dash_n + dash_spc*(dash_n - 1)); // True dash length. #debug concat("dash_len", str(dash_len,6,2), "\n") #local dash_step = (atop - abot + dash_spc*dash_len)/dash_n; // True dash step. #debug concat("dash_step", str(dash_step,6,2), "\n") #local dash = object{ vortex_torus_slice(R,r,0,dash_len,dash_len,0.0,true) } union{ #local ang = abot; #while (ang < atop) object{ dash translate R*y rotate ang*x translate -R*y } #local ang = ang + dash_step; #end texture{ vortex_axis_tx } } #debug "EXIT vortex_axis\n" #end #macro vortex_torus_slice(R,r,abot,amid,atop,thk,cap) // A segment of an {R,r} torus extending from longitudes {abot} to {atop}. // If {cap} is true, adds two spherical caps. // If {thk} is positive, makes it holow with thickness {thk}. // If {amid} is less than {atop}, slices off the front half from {amid} up. // The result is placed so that the circular axis passes through the origin. #local tube = object{ vortex_torus_slice_solid(R,r,abot,atop,cap) } #if (thk > 0) #if (cap) #local abot_hol = abot; #local atop_hol = atop; #else #local abot_hol = abot - 1.0; #local atop_hol = atop + 1.0; #end #local hole = object{ vortex_torus_slice_solid(R,r-thk,abot_hol,atop_hol,cap) } #local tube = difference{ object{ tube } object{ hole } } #end #if (amid < atop) // Cut out the front half of the top part: #local clipper = difference{ cylinder{ < -1.1*r, 0, 0 >, < +1.1*r, 0, 0>, R + 1.1*r } cylinder{ < -1.2*r, 0, 0 >, < +1.2*r, 0, 0>, R } plane{ +z,0 rotate amid*x } } #local tube = difference{ object{ tube } object{ clipper } } #end object{ tube translate -R*y } #end #macro vortex_torus_slice_solid(R,r,abot,atop,cap) // A segment of an {R,r} solid torus extending from longitudes {abot} to {atop}. // If {cap} is true, adds two spherical caps. // The result is placed so that the torus center is at the origin. #local tube = intersection{ torus{ R, r rotate 90*z } plane{ -z,0 rotate abot*x } plane{ +z,0 rotate atop*x } } #if (cap) #local tube = union{ sphere{ < 0, R, 0 >, 0.99999*r } object{ tube } sphere{ < 0, R, 0 >, 0.99999*r rotate atop*x } } #end object{ tube } #end