Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

OpenSCAD User Manual/Example/HelloThere

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Hello There Animation example using objects to manage the data. Code // this script requires 2025.07.11. _v = version(); assert( _v.x== 2025 && _v.y>=7 && _v.z >= 11 ); /* This script was presented by Jordan Brown in the OpenSCAD forum to illustrate how an object could be used to control an animation. The animation runs well with Use FPS=10 and steps=100. */ // Best view is looking straight down at the origin. $vpr = [0,0,0]; $vpt = [0,0,0]; // This vector is a description of everything that happens // during the animation. You want a wide window to read it. // The only thing that's defined is "t", the timestamp for that // particular entry. The rest are up to your program. // For this animation: // pos1, pos2: the {red, green} stick man's position // arm1, arm2: the {red, green} stick man's arm angle // says1, says2: what the {red, green} stick man is saying timeline = [ object(t=0, pos1=[-50,0,0], arm1=-30, says1="", pos2=[50,0], arm2=-30, says2=""), object(t=2.5, arm1=-30 ), object(t=3, arm1=50, says1="Hey, George!" ), object(t=3.5, arm1=-30 ), object(t=5, says1="" ), object(t=5.5, arm2=-30 ), object(t=6, arm2=50, says2="Hey, Fred!" ), object(t=6.5, arm2=-30 ), object(t=7, says2="" ), object(t=12, pos1=[-5,0,0], pos2=[5,0] ), object(t=13, says1="Can I go past?" ), object(t=14, says1="" ), object(t=15, says2="Sorry, no." ), object(t=16, says2="" ), object(t=17, says1="I hate living on a number line!" ), object(t=19, says1="" ), object(t=19.5, says2="Me too!" ), object(t=20.5, says2="" ), object(t=22, pos1=[-5,0,0], arm2=-30, says1="", pos2=[5,0], arm2=-30, says2="" ), ]; // Now, create the current frame of the animation. // Get the current values of all of the timeline columns. a = animate(timeline); /* Using those values, create the model at this moment. There are two stick men. */ translate(a.pos1) { color("red") stickman(a.says1, a.arm1); } translate(a.pos2) { color("green") stickman(a.says2, a.arm2); } // Create a stick man, holding his arms at the specified angle and saying what's specified. module stickman(says, arm) { square([1,8], center=true); translate([0,5]) circle(2); translate([0,2]) rotate(arm) translate([0,-0.5]) square([4,1]); translate([0,2]) rotate(180-arm) translate([0,-0.5]) square([4,1]); translate([0,-4]) rotate(200) translate([-0.5,0]) square([1,5]); translate([0,-4]) rotate(160) translate([-0.5,0]) square([1,5]); translate([0, 8]) text(says, halign="center", valign="baseline", size=3); } // The rest is generic support for using a timeline like that. // Extract one column from an animation timeline, extracting only // those entries where that column is present. function animate_extract(list, key) = [ for (e = list) if( !is_undef(e[key]) ) [ e.t, e[key] ] ]; // Get the duration of the timeline, the timestamp of the // last entry in the timeline. function animate_duration(list) = list[len(list)-1].t; // Given $t, a timeline and a key, interpolate the current value // of the key. function animate_interpolate(list, key) = xlookup( $t * animate_duration(list), animate_extract(list, key) ); // Get a list of all keys used in the timeline. function animate_keys(list) = let( o = object( [ for (e = list) for (k = e) [ k, true ] ] ) ) [ for (k = o) k ]; // Given $t and a timeline, return an aggregated object with the // current values of all of the columns of the timeline. function animate(timeline) = let(keys = animate_keys(timeline)) object( [ for (k = keys) [ k, animate_interpolate(timeline, k) ] ] ); // lookup() on steroids. Given a value and a lookup-like list, // do the lookup and interpolation that lookup() does... but have // it also work for strings, booleans, and identical-length lists // of numbers. function xlookup(val, list) = is_num(list[0][1]) ? lookup(val, list) : is_string(list[0][1]) ? lookup_string(val, list) : is_bool(list[0][1]) ? lookup_bool( val, list) : is_list(list[0][1]) ? lookup_list( val, list) : assert(false, "don't know how to lookup that type") ; // Given a value and a lookup list, return the index of the entry // before (or matching) the value. function lookup_prev(val, list) = let (tmp = [ for (i = [0:1:len(list)-1]) [ list[i][0], i ] ] ) floor(lookup(val, tmp)) ; //Given a value and a lookup list, return the index of the entry // after (or matching) the value. function lookup_next(val, list) = let (tmp = [ for (i = [0:1:len(list)-1]) [ list[i][0], i ] ] ) ceil(lookup(val, tmp)) ; // Given a value and a lookup list containing strings, return the // string before (or matching) the value. function lookup_string(val, list) = list[lookup_prev(val, list)][1] ; // Given a value and a lookup list containing booleans, return the // boolean before (or matching) the value. function lookup_bool(val, list) = list[lookup_prev(val, list)][1] ; // Given a value and a lookup list containing same-length lists of // numbers, interpolate values for the list. Note that because // lookup_prev() and lookup_next() return the same entry on an exact // match, and that leads to 0*0/0, that case has to be handled // specially. function lookup_list(val, list) = let( p = lookup_prev(val, list), n = lookup_next(val, list) ) p == n ? list[p][1] : list[p][1] + (list[n][1]-list[p][1]) * (val - list[p][0]) / (list[n][0] - list[p][0]) ;