More efficient use of lookup for animations?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

More efficient use of lookup for animations?

Cerin
Hi,

I'm new to OpenSCAD's animation feature, and I'm playing around with
some simple animation scripts. Generally, it's very useful, however,
I'm running into a fairly annoying problem.

I started with this guide
(https://www.instructables.com/id/Animating-with-OpenSCAD/) which
recommended wrapping your use of lookup() in a function like:

    loc = [
        [0,0,0], // initial position
        [0,0,0], // top body shifts over slightly
        [0,0,10], // lifts leg up
        [0,5,10], // moves leg forward
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
    ];

    function xyz(t,i) = lookup(t, [
        [0/len(loc),loc[0][i]],
        [1/len(loc),loc[1][i]],
        [2/len(loc),loc[2][i]],
        [3/len(loc),loc[3][i]],
        [4/len(loc),loc[4][i]],
        [5/len(loc),loc[5][i]],
        [6/len(loc),loc[6][i]],
        [7/len(loc),loc[7][i]],
        [8/len(loc),loc[8][i]],
        [9/len(loc),loc[9][i]],
        [10/len(loc),loc[10][i]],
    ]);

Then you can animate something by simply plugging in a call to
`xyz($t, <0|1|2>)` inside a translate or rotate statement.

Yet, as you can see, this violates the DRY rule, and makes for some
very tedious and unnecessary code. For every new step added to my
`loc` array, I need to add an entry to the array inside my `xyz()`
function as well.

Is there any way to rewrite my `xyz()` function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: More efficient use of lookup for animations?

nophead
You don't need to use lookup at all. Just work out the two indices of loc that t will select a point  between and then use linear interpolation between those two points. That is what lookup does.

Or you could use list comprehension for loop to make the list to pass to lookup. 

I don't think you need to pass i because lookup should be able to interpolate vectors.

On Fri, 6 Mar 2020 at 22:47, Chris Spencer <[hidden email]> wrote:
Hi,

I'm new to OpenSCAD's animation feature, and I'm playing around with
some simple animation scripts. Generally, it's very useful, however,
I'm running into a fairly annoying problem.

I started with this guide
(https://www.instructables.com/id/Animating-with-OpenSCAD/) which
recommended wrapping your use of lookup() in a function like:

    loc = [
        [0,0,0], // initial position
        [0,0,0], // top body shifts over slightly
        [0,0,10], // lifts leg up
        [0,5,10], // moves leg forward
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
        [0,5,0], // puts leg down
    ];

    function xyz(t,i) = lookup(t, [
        [0/len(loc),loc[0][i]],
        [1/len(loc),loc[1][i]],
        [2/len(loc),loc[2][i]],
        [3/len(loc),loc[3][i]],
        [4/len(loc),loc[4][i]],
        [5/len(loc),loc[5][i]],
        [6/len(loc),loc[6][i]],
        [7/len(loc),loc[7][i]],
        [8/len(loc),loc[8][i]],
        [9/len(loc),loc[9][i]],
        [10/len(loc),loc[10][i]],
    ]);

Then you can animate something by simply plugging in a call to
`xyz($t, <0|1|2>)` inside a translate or rotate statement.

Yet, as you can see, this violates the DRY rule, and makes for some
very tedious and unnecessary code. For every new step added to my
`loc` array, I need to add an entry to the array inside my `xyz()`
function as well.

Is there any way to rewrite my `xyz()` function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: More efficient use of lookup for animations?

Ronaldo
I don't think you need to pass i because lookup should be able to interpolate vectors.

It would be nice but lookup only accepts numbers in the table.

Is there any way to rewrite my `xyz()` function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?  

You may try this:

function xyz(loc,t) =
  t<0 || t>1 ? echo("xyz: t out of range") undef
  :
  let( s = t*(len(loc)-1),
       k = floor(s) )
  (1-s+k)*loc[k] + (s-k)*loc[k+1];
 
that returns the interpolated position from table loc.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: More efficient use of lookup for animations?

Ronaldo
My previous code of xyz() has a bug: it returns undef when t=1. Here is a correction:

function xyz(loc,t) =
  t<0 || t>1 ? echo("xyz: t out of range") undef
  :
  let( s = t*(len(loc)-1),
       k = floor(s) )
  k<len(loc)-1? (1-s+k)*loc[k] + (s-k)*loc[k+1]: loc[k];

Em seg., 9 de mar. de 2020 às 16:22, Ronaldo Persiano <[hidden email]> escreveu:
I don't think you need to pass i because lookup should be able to interpolate vectors.

It would be nice but lookup only accepts numbers in the table.

Is there any way to rewrite my `xyz()` function to generate the array
on demand so I don't have to maintain what are effectively duplicate
arrays? Is a more efficient way to do this that I'm not seeing?  

You may try this:

function xyz(loc,t) =
  t<0 || t>1 ? echo("xyz: t out of range") undef
  :
  let( s = t*(len(loc)-1),
       k = floor(s) )
  (1-s+k)*loc[k] + (s-k)*loc[k+1];
 
that returns the interpolated position from table loc.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org