// Last edited on 2010-05-16 00:17:44 by stolfilocal #macro camlight(viewCenter, viewAzim, viewElev, viewDist, viewRadius, viewSky, nrings, lux) // The lights are an array of lamps with {nrings} rings // and total intensity {lux} // Declares globally {camera_dir,camera_h_dir,camera_v_dir,camera_pos} // Camera #local dist = viewDist; #local azim = viewAzim; #local elev = viewElev; #local ctr = viewCenter; #local dir = vrotate(vrotate(<1,0,0>, -viewElev*y), viewAzim*z); #local disp = dir*viewDist; #local pos = viewCenter + disp; #local h_dir = vnormalize(vcross(viewSky, dir)); #local v_dir = vnormalize(vcross(dir, h_dir)); // Global declarations: #declare camera_dir = dir; #declare camera_disp = disp; #declare camera_pos = pos; #declare camera_h_dir = h_dir; #declare camera_v_dir = v_dir; // !!! Must fix the computation of camera {right,up} using tangent etc. #local slop = 0.77; #local c_h = sqrt(image_width/image_height); #local c_v = sqrt(image_height/image_width); #local h_min = - slop * c_h * viewRadius; #local h_max = + slop * c_h * viewRadius; #local v_min = - slop * c_v * viewRadius; #local v_max = + slop * c_v * viewRadius; #local c_a_h = (h_max - h_min)/viewDist; #local c_a_v = (v_max - v_min)/viewDist; camera { location pos right c_a_h * <00, -1, 00> up c_a_v * <00, 00, +1> sky viewSky look_at viewCenter } #if (lux > 0) // Lights: #local dir = dir; #local dist = viewDist; #local angrad = 15; // Angular light array radius (degrees). object{ camlight_lamp_array(nrings,angrad,lux) rotate 360*(sqrt(5)-1)/2*x scale dist rotate -(90 - 0.667*(90 - elev))*y rotate (azim + 15)*z translate ctr } #end #end #macro camlight_lamp_array(nrings,angrad,lux) // A round lamp array with {nrings} rings of lamps, // total angular radius {angrad}, 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 : 6*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 #debug "loaded pst_camlight.inc\n"