#version 3.7; #include "colors.inc" #include "functions.inc" #include "textures.inc" #include "transforms.inc" global_settings { assumed_gamma 1.0 } // sky --------------------------------------------------------------- plane {<0,1,0>, 1 hollow texture {pigment {bozo turbulence 0.92 color_map { [0.00 rgb <0.25, 0.35, 1.0>*0.7] [0.50 rgb <0.25, 0.35, 1.0>*0.7] [0.70 rgb <1,1,1>] [0.85 rgb <0.25,0.25,0.25>] [1.0 rgb <0.5,0.5,0.5>]} scale <1, 1, 1.5>*2.5 translate <0,0,0> } finish {ambient 1 diffuse 0} } scale 10000} // fog on the ground ------------------------- end of sky with clouds fog { fog_type 2 distance 100 color White*0.5 fog_offset 0.1 fog_alt 2.0 turbulence 1.8 } //------------------------------------------------- end of ground fog light_source {<10, 50, -100> color rgb <1, 1, 1>} #declare Zoom = 2; camera { orthographic location <200, 100, -120> right x*image_width/Zoom up y*image_height/Zoom look_at <200, 50, 0> } #declare Rad = 2; #declare Hvel = 5; #declare BallMass = 100; #declare BallHeight = 100; #declare h0 = 10; #declare Elasticity = 0.9; #declare G = 32; #declare V = sqrt(2*G*BallHeight); //#declare Dist = V0*T + G*pow(T,2)/2; //#declare h = h0 - 0.5*G*pow(T,2); // 1/2mv^2 = mgh = vf #declare Vf = sqrt(2*G*BallHeight); #declare Vnew = Elasticity* Vf; // 1/2mv^2 = mgh = Hnew #declare h = pow(Vnew,2)/(2*G); #declare MaxHeight = 100; #declare MaxEnergy = G*MaxHeight; #declare MaxVel = sqrt(2*G*MaxHeight); #declare SubT = 0; #declare Step = 0.1; #declare Power = 2; #declare Direction = -1; #declare LastH = MaxHeight; #declare CurrentH = MaxHeight; #declare Color = pigment {Green}; #for (T, 0, 25, Step) #if (CurrentH < 0) #debug concat ("CurrentH = ", str(CurrentH, 3, 1), "\n") #declare Direction = 1; #declare CurrentH = CurrentH * Direction; #declare MaxHeight = MaxHeight*Elasticity; #declare Time = sqrt(2*MaxHeight/G); #declare Color = rgb <1, 0, 0>; #declare Power = 2; #declare SubT = 0; #debug concat ("Direction = ", str(Direction, 3, 1), "\n") #debug "\n\n*Rising \n" #end // end check for impact #if (CurrentH > MaxHeight) #debug concat ("CurrentH = ", str(CurrentH, 3, 1), "\n") #debug concat ("MaxHeight = ", str(MaxHeight, 3, 1), "\n") #declare Direction = -1; #declare CurrentH = MaxHeight-(CurrentH-MaxHeight); #debug concat ("new CurrentH = ", str(CurrentH, 3, 1), "\n") #declare Color = rgb <0, 1, 0>; #declare Power = 2; #declare SubT = 0; #debug concat ("Direction = ", str(Direction, 3, 1), "\n") #debug "\n\n*Falling \n" #end #if (Direction = -1) #declare CurrentH = LastH - ( (G/2) * pow(SubT, Power)); #debug "Falling \n" #else #declare CurrentH = MaxHeight - (G/2) * pow(Time-SubT, Power); #debug "Rising \n" #debug concat( "CurrentH = ", str(CurrentH, 3, 1), "\n") #debug concat( "MaxHeight = ", str(MaxHeight, 3, 1), "\n") #end sphere {0, Rad pigment {Color} translate } #declare LastH = CurrentH; #declare SubT = SubT + Step; #end // end for T /* bounceFactory * * Consult this article: https://medium.com/@willsilversmith/the-bounce-factory-3498de1e5262#.pn5rcjp15 * The variables below are annotate with comments that reference the article. * * Simulate a physical bouncing motion based on physics equations of motion. * * We assume mass and gravity = 1 as they are immaterial when we normalize both * the y and t axis to 1. The length of the animation in msec will determine "gravity" * and the elasticity will determine the number of bounces. * * Required: * [0] bounces: (positive int) how many bounces do you want * * Optional: * [1] threshold (epsilon): [0..1], (default 0.1%) percent of energy remaining * at which to terminate the animation * * Return: f(t), t in 0..1 function bounceFactory (bounces, threshold) { threshold = threshold || 0.001; function energy_to_height (energy) { return energy; // h = E/mg, Eqn. 4 } function height_to_energy (height) { return height; // E = mgh, Eqn. 4 } function bounce_time (height) { // 2 x the half bounce time measured from the peak return 2 * Math.sqrt(2 * height); // Modified Eqn. 7 } function speed (energy) { // E = 1/2 m v^2, s = |sqrt(2E/m)| return Math.sqrt(2 * energy); // Eqn. 8 } var height = 1; var potential = height_to_energy(height); var elasticity = Math.pow(threshold, 1 / bounces); // Eqn. 10 // The critical points are the points where the object contacts the "ground" // Since the object is initially suspended at 1 height, this either creates an // exception for the following code, or you can use the following trick of placing // a critical point behind 0 and representing the inital position as halfway though // that arc. var critical_points = [{ time: - bounce_time(height) / 2, energy: potential, }, { time: bounce_time(height) / 2, energy: potential * elasticity, }]; potential *= elasticity; height = energy_to_height(potential); var time = critical_points[1].time; for (var i = 1; i < bounces; i++) { time += bounce_time(height); potential *= elasticity; // Eqn. 2, remove energy after each bounce critical_points.push({ time: time, energy: potential, }); height = energy_to_height(potential); } var duration = time; // renaming to emphasize it's the total time now return function (t) { t = clamp(t, 0, 1); var tadj = t * duration; if (tadj === 0) { return 0; } else if (tadj >= duration) { return 1; } // Find the bounce point we are bouncing from, for very long animations (hours, days), // an binary search algorithm might be appropriate. var index; for (index = 0; index < critical_points.length; index++) { if (critical_points[index].time > tadj) { break; } } var bouncept = critical_points[index - 1]; // Bouncing from a bounce point effectively resets time as it is a discontinuity tadj -= bouncept.time; var v0 = speed(bouncept.energy); // Project position of object from bounce point to the current time var pos = v0 * tadj + -0.5 * tadj * tadj; // Eqn. 1 return 1 - pos; }; } function clamp (val, lower, upper) { return Math.max(Math.min(val, upper), lower); } #declare Tbounce = 2*sqrt(2*h/G); // Initial bounce time */