// Persistence of Vision Ray Tracer Scene Description File // File: elliptic_torus.pov // Vers: 3.5 // Desc: Sample scene for elliptic torus macros, as spere_sweep, and as blob. // Date: 03/2006 // Auth: Bruno Cabasson // #version 3.5; #include "colors.inc" global_settings { assumed_gamma 1.0 } // ---------------------------------------- camera { location <0.0, 0.5, -4.0> direction 1.5*z right x*image_width/image_height look_at <0.0, 0.0, 0.0> } sky_sphere { pigment { gradient y color_map { [0.0 rgb <0.6,0.7,1.0>] [0.7 rgb <0.0,0.1,0.8>] } } } light_source { <0, 0, 0> // light's position (translated below) color rgb <1, 1, 1> // light's color translate <-30, 30, -30> } // ---------------------------------------- plane { y, -1 pigment { color rgb <0.7,0.5,0.3> } } // -------------------------------------------------------------------------------------- #macro SW_GenerateEllipticSplinePoints ( _center_point, _major, _minor, _radius, _normal, _major_dir, _start_angle, _end_angle, // These are the 'parametric angles' (used to sample the ellipse) _nb_points ) #local delta_angle = _end_angle - _start_angle; #local major_dir = vnormalize(_major_dir); #local i=0; #while (i<=_nb_points) // Find position of current point #local rel_time = i/_nb_points; #local cur_angle = _start_angle + rel_time*delta_angle; #local cur_angle_rad = radians(cur_angle); #local cur_x = _major*cos(cur_angle_rad); #local cur_y = _minor*sin(cur_angle_rad); #local cur_radius = vlength(); #local theta = degrees(atan2(cur_y, cur_x)); #declare p = _center_point + vaxis_rotate(cur_radius*major_dir, _normal, theta); #debug str(i, 0, 0) // Generate the spline control point #if (i < _nb_points) p, _radius, #else p, _radius #end #local i=i+1; #end #end // -------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------- #macro sw_elliptical_torus (_major, _minor, _radius, _tolerance) sphere_sweep { #local NB_POINTS = 20; // Enough to sample an ellipse. A lower value would not yield an accurate sphere_sweep #declare OFFSET = degrees(2*pi/NB_POINTS); cubic_spline NB_POINTS+3, SW_GenerateEllipticSplinePoints (0, _major, _minor, _radius, y, x, -OFFSET, 360+OFFSET, NB_POINTS+2) tolerance _tolerance } #end // -------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------- #macro elliptical_torus (_major, _minor, _radius) blob { // We use the parametric equation of an ellipse to sample the perimeter and deposit pheres // where needed. #local THRES = 0.65; #local DENSITY_PER_RADIUS = 10; // density per curved length unit #declare OVERSAMPLING_FACTOR = 10; // For instance... // First, determine the radius of the spheres #local k_ = 1.2185; // Determined by hand so that a true sphere with radius R is about to disappear when .... #local radius_ = k_*_radius; // Second, compute the number of samples for the perimeter. #local perimeter_ = 2*pi*sqrt((_major*_major + _minor*_minor)/2); #local nb_spheres_ = int(perimeter_/_radius)*DENSITY_PER_RADIUS + 1; #local nb_samples_ = nb_spheres_ * OVERSAMPLING_FACTOR; // Determine length of segment between spheres #local segment_ = radius_/DENSITY_PER_RADIUS; // Third: loop over the samples and intergrate perimeter. Drop a sphere where needed. #local l_ = 0; // length of protion of perimeter travelled so far. #local delta_ = 2*pi/nb_samples_; #local p0_ = <1, 0>; #local i=0; #while (i<=nb_samples_) // We loop approx OVERSAMPLING_FACTOR times before we reach the end of next segment // and drop a sphere. #local theta_ = i*delta_; // use parametric equation of an ellipse to find the point on the perimeter. #local x_ = _major*cos(theta_); #local y_ = _minor*sin(theta_); #local p1_ = ; // Compute length travelled so far #local sample_ = vlength (p1_ - p0_); #local l_ = l_ + sample_; // Check if segment_ has been travelled. If so, drop a sphere #if (l_ >= segment_) sphere {, radius_, 1} #local l_ = mod(l_, segment_); #end // Prepare next loop #local p0_ = p1_; #local i=i+1; #end threshold THRES sturm } #end // -------------------------------------------------------------------------------------- #declare R = 0.15; #declare MAJOR = 1.0; #declare MINOR = 0.6; // Reference spheres // sphere {MAJOR*x, R pigment {Blue}} // sphere {MINOR*y, R pigment {Blue}} // We superimpose the two versions and see the differences. // Comment out, and compare render speed ... // You will note that the sphere_sweep makes the reference spheres disappear. Not the blob version. object {sw_elliptical_torus(MAJOR, MINOR, R, 0.01) pigment {Green} rotate -90*x} // object {elliptical_torus(MAJOR, MINOR, R) pigment {Red} rotate -90*x}