// Cāmera e luz para exercicio de energia solar // Last edited on 2023-12-31 09:04:29 by stolfi #macro camsol(ctr,rad,vis,nor,sol,lux) // {ctr} = center of interest in scene. // {rad} = approx radius of scene. // {vis} = 0 for observer's view, 1 for sun's view. // {nor} = vector pointing from {ctr} to celestial nort; only its direction matters. // {sol} = vector pointing from {ctr} to sun; only its direction matters. // {lux} = a scaling factor for the intensity of standard light sources. // {cav} = vector pointing from {ctr} to camera; only its direction matters. // {dst} = distance from {ctr} to camera. // {upp} = vector pointing 'up' for camera roll; only direction matters. #local nor_dir = vnormalize(nor); #local sol_dir = vnormalize(sol); #if (vista = 0) // Flying observer's view: #local cam_dir = vnormalize(< -7, 3, 5 >); #local cam_dst = 6*(rad); #local upp = z; #elseif (vista = 1) // Sun's view: #local cam_dir = sol_dir; #local cam_dst = 100*(rad); #local upp = nor_dir; #elseif (vista = 2) // View from X-axis #local cam_dir = x; #local cam_dst = 100*(rad); #local upp = z; #elseif (vista = 3) // View from Y-axis #local cam_dir = -y; #local cam_dst = 100*(rad); #local upp = z; #end #if (vista = 0) #local nor_tip = 0.65*(rad)*nor_dir; #local font_size = 0.07*(rad); union{ object{ eixo(nor_tip,<1,1,1>,"norte") } text{ ttf "tt-fonts/arial.ttf" "N" 0.2, 0 texture{ pigment{ color rgb <1,1,1>} finish{ diffuse 0.6 ambient 0.4 } } scale font_size rotate 90*x rotate -90*z translate -0.45*font_size*z translate 1.1*nor_tip } translate ctr no_shadow } #end #local swh = sqrt(image_width/image_height); #local ape = 1.41*(rad)/cam_dst; // Camera aperture. camera { location (ctr) + cam_dst*cam_dir right -swh*ape*x up 1.0/swh*ape*y sky (upp) look_at (ctr) } #if (lux > 0) #local sol_elev = -degrees(atan2(sol_dir.z,sqrt(sol_dir.x*sol_dir.x + sol_dir.y*sol_dir.y))); #local sol_azim = degrees(atan2(sol_dir.y,sol_dir.x)); #local nrings = 2; #local angrad = 2; object{ lamp_array(nrings,angrad,lux) rotate 360*(sqrt(5)-1)/2*x scale 2000*rad rotate sol_elev*y rotate sol_azim*z translate ctr } #end #end #macro lamp_array(nrings,angrad,lux) // A round lamp array with {nrings} rings of lamps, // total angular radius {angrad} (degrees), and total strength {lux}. // The array is centered on the X axis at distance 1 // from the origin. // Compute normalization factor {st_norm} for ring strengths: #local k = 0; // Light ring index. #local st_norm = 0; #while (k < nrings) #local st = camlight_rel_ring_strength(k,nrings); #local st_norm = st_norm + st; #local k = k + 1; #end #local coin = seed(4615); union{ #local k = 0; // Light ring index. #while (k < nrings) // Number of lamps {np} in ring {k} and initial phase {phas}: #local np = (k = 0 ? 1 : 12*pow(2,k-1)); // Number of lamps in ring. #local phas = (k = 0 ? 0 : 0.6180/np); // Rel. position of first lamp // Total relative strength {st} of lamps in ring: #local st = camlight_rel_ring_strength(k,nrings); // Generate the lamps in the ring: #local p = 0; // Lamp index. #while (p < np) // Jittering terms in {k,p}: #local dk = (k = 0 ? 0 : 0.20*(2*rand(coin)-1)); #local dp = (k = 0 ? 0 : 0.20*(2*rand(coin)-1)); // Angular radius of ring: #local tau = camlight_rel_ring_radius(k+dk,nrings); // Relative radius of ring #local phi = (k = 0 ? 0 : angrad*tau); // Angular radius of ring. #local tht = 360*(phas + (p+dp)/np); light_source { <1,0,0> color rgb (st/st_norm/np)*lux*<1.0,1.0,1.0> rotate phi*z rotate tht*x } // #warning concat("light at phi = ", str(phi,6,1), " tht = ", str(tht,6,1), "\n") #local p = p + 1; #end #local k = k + 1; #end } #end #macro camlight_rel_ring_strength(k,nrings) // Relative total strength (unnormalized) of lights in ring {k} of {nrings} rings. #local st = (k = 0 ? 0.5*0.5 : 2*k)*((nrings-0.5)*(nrings-0.5) - k*k); st #end #macro camlight_rel_ring_radius(k,nrings) // Relative radius of light ring {k} in a lamp cluster with {nrings} rings. #local rr = (k = 0 ? 0 : pow(k/(nrings - 0.5),1.5)); rr #end