discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Question about spring.gif on wikibooks

M
mikeonenine@web.de
Mon, Jan 22, 2024 5:30 AM

Jordan Brown wrote:

On 1/21/2024 6:25 PM, Caddiy via Discuss wrote:

One could probably write a small book on OpenSCAD animation
techniques.

Simple harmonic, circular, elliptical motion, full and part
rotation/different speeds - anything else? I couldn’t provide anything
on Turtle or sweep.

Well, I'm not quite sure how it would fit into those categories, but
take a look at
https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.webp
and its implementation:
https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.scad

It's largely driven by tables that control the position, size, and
rotation of various components at various times, with interpolation. 
(Once I got the basic infrastructure in place, the problem was actually
one of direction, not technology - I had to decide what I wanted to
happen, when.)

Or https://www.youtube.com/watch?v=6qNHy48iOOs
which is driven by a simpler table, but does first-person view.

https://imgur.com/a/5N20EP6
implementation: https://bpa.st/3VNA
in a sense just rotates one component, but it then calculates the
mechanical effects on the other components.

Take a look through the Advent calendars for animations by other people
with various interesting behaviors.  neri-engineering has some great
videos too.

Can you condense those techniques down into a page or two?  Maybe, but I
kind of doubt it.

Heck, you might be able to spend a page just on why you might want to
animate a model.

I think I’ll stick to what I know and leave the fancy stuff for others to put in the Users Manual. It will certainly be an improvement on the previous version.

Jordan Brown wrote: > On 1/21/2024 6:25 PM, Caddiy via Discuss wrote: > > > ``` > > One could probably write a small book on OpenSCAD animation > > techniques. > > ``` > > > > Simple harmonic, circular, elliptical motion, full and part > > rotation/different speeds - anything else? I couldn’t provide anything > > on Turtle or sweep. > > Well, I'm not quite sure how it would fit into those categories, but > take a look at > https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.webp > and its implementation: > https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.scad > > It's largely driven by tables that control the position, size, and > rotation of various components at various times, with interpolation.  > (Once I got the basic infrastructure in place, the problem was actually > one of direction, not technology - I had to decide what I wanted to > happen, when.) > > Or https://www.youtube.com/watch?v=6qNHy48iOOs > which is driven by a simpler table, but does first-person view. > > https://imgur.com/a/5N20EP6 > implementation: https://bpa.st/3VNA > in a sense just rotates one component, but it then calculates the > mechanical effects on the *other* components. > > Take a look through the Advent calendars for animations by other people > with various interesting behaviors.  neri-engineering has some great > videos too. > > Can you condense those techniques down into a page or two?  Maybe, but I > kind of doubt it. > > Heck, you might be able to spend a page just on *why* you might want to > animate a model. I think I’ll stick to what I know and leave the fancy stuff for others to put in the Users Manual. It will certainly be an improvement on the previous version.
J
jon
Mon, Jan 22, 2024 9:09 PM

Thanks for sharing this, Jordan.  I learned a lot!

Jon

On 1/21/2024 11:01 PM, Jordan Brown via Discuss wrote:

On 1/21/2024 6:25 PM, Caddiy via Discuss wrote:

 One could probably write a small book on OpenSCAD animation
 techniques.

Simple harmonic, circular, elliptical motion, full and part
rotation/different speeds - anything else? I couldn’t provide
anything on Turtle or sweep.

Well, I'm not quite sure how it would fit into those categories, but
take a look at
https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.webp
and its implementation:
https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.scad

It's largely driven by tables that control the position, size, and
rotation of various components at various times, with interpolation. 
(Once I got the basic infrastructure in place, the problem was
actually one of direction, not technology - I had to decide what I
wanted to happen, when.)

Or https://www.youtube.com/watch?v=6qNHy48iOOs
which is driven by a simpler table, but does first-person view.

https://imgur.com/a/5N20EP6
implementation: https://bpa.st/3VNA
in a sense just rotates one component, but it then calculates the
mechanical effects on the other components.

Take a look through the Advent calendars for animations by other
people with various interesting behaviors.  neri-engineering has some
great videos too.

Can you condense those techniques down into a page or two?  Maybe, but
I kind of doubt it.

Heck, you might be able to spend a page just on why you might want
to animate a model.


OpenSCAD mailing list
To unsubscribe send an email todiscuss-leave@lists.openscad.org

Thanks for sharing this, Jordan.  I learned a lot! Jon On 1/21/2024 11:01 PM, Jordan Brown via Discuss wrote: > On 1/21/2024 6:25 PM, Caddiy via Discuss wrote: >> >> One could probably write a small book on OpenSCAD animation >> techniques. >> >> Simple harmonic, circular, elliptical motion, full and part >> rotation/different speeds - anything else? I couldn’t provide >> anything on Turtle or sweep. >> > > Well, I'm not quite sure how it would fit into those categories, but > take a look at > https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.webp > and its implementation: > https://files.openscad.org/advent-calendar-2023/PorchPirate/Porch%20Pirate.scad > > It's largely driven by tables that control the position, size, and > rotation of various components at various times, with interpolation.  > (Once I got the basic infrastructure in place, the problem was > actually one of direction, not technology - I had to decide what I > wanted to happen, when.) > > Or https://www.youtube.com/watch?v=6qNHy48iOOs > which is driven by a simpler table, but does first-person view. > > https://imgur.com/a/5N20EP6 > implementation: https://bpa.st/3VNA > in a sense just rotates one component, but it then calculates the > mechanical effects on the *other* components. > > Take a look through the Advent calendars for animations by other > people with various interesting behaviors.  neri-engineering has some > great videos too. > > Can you condense those techniques down into a page or two?  Maybe, but > I kind of doubt it. > > Heck, you might be able to spend a page just on *why* you might want > to animate a model. > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email todiscuss-leave@lists.openscad.org
JB
Jordan Brown
Mon, Jan 22, 2024 11:21 PM

On 1/22/2024 1:09 PM, jon wrote:

Thanks for sharing this, Jordan.  I learned a lot!

You're welcome!  (And do look at other Advent calendar entries; there's
interesting animation in several.)

Linear and circular motion are fairly straightforward.  Multiply $t by
the distance to be moved, or multiply $t by 360 to walk around a circle.

For anything else, you need to somehow map the 0-1 range into the
behavior that you want.  That might be linear, or non-linear, or
discontinuous.  Interpolation is your friend.

The really hard part is that stuff like this is like Legos.  Each part
is small and, on its own, largely useless.  It's all in how you put them
all together - and there are an infinite number of ways to put them
together so it's hard to just give somebody a step-by-step procedure.

On 1/22/2024 1:09 PM, jon wrote: > > Thanks for sharing this, Jordan.  I learned a lot! > You're welcome!  (And do look at other Advent calendar entries; there's interesting animation in several.) Linear and circular motion are fairly straightforward.  Multiply $t by the distance to be moved, or multiply $t by 360 to walk around a circle. For anything else, you need to somehow map the 0-1 range into the behavior that you want.  That might be linear, or non-linear, or discontinuous.  Interpolation is your friend. The really hard part is that stuff like this is like Legos.  Each part is small and, on its own, largely useless.  It's all in how you put them all together - and there are an infinite number of ways to put them together so it's hard to just give somebody a step-by-step procedure.
M
mikeonenine@web.de
Tue, Jan 23, 2024 4:10 AM

Jordan Brown wrote:

Linear and circular motion are fairly straightforward.  Multiply $t by
the distance to be moved, or multiply $t by 360 to walk around a circle.

Except that the linear motion is unnatural i.e. not to be found in the real world.

children();
for (x = [ 
[10, -$t*20+10],
[-10, 20*$t-10],
[$t*20-10, 10],
[-20*$t+10, -10],
])
translate([x[0], x[1]])
square(5, center=true);

difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}

The above looks good with 4 squares, but remove one or give it a different colour and you see the Ilyushin. So how can a square be prevented from jumping back at the end of its travel and move off at 90° instead?

  • https://imgur.com/a/5N20EP6: “This post may contain erotic or adult imagery.” Disappointed, couldn’t find any.

  • Fascinating stuff in the Adventskalender!

  • Looking forward to other peoples’ additions to Animation: $t in the Users Manual!

Jordan Brown wrote: > Linear and circular motion are fairly straightforward.  Multiply $t by > the distance to be moved, or multiply $t by 360 to walk around a circle. Except that the linear motion is unnatural i.e. not to be found in the real world. ``` children(); for (x = [ [10, -$t*20+10], [-10, 20*$t-10], [$t*20-10, 10], [-20*$t+10, -10], ]) translate([x[0], x[1]]) square(5, center=true); difference() { offset(0.1) square(20, center=true); offset(-0.1) square(20, center=true); } ``` The above looks good with 4 squares, but remove one or give it a different colour and you see the Ilyushin. So how can a square be prevented from jumping back at the end of its travel and move off at 90° instead? * https://imgur.com/a/5N20EP6: “This post may contain erotic or adult imagery.” Disappointed, couldn’t find any. * Fascinating stuff in the Adventskalender! * Looking forward to other peoples’ additions to Animation: $t in the Users Manual!
JB
Jordan Brown
Tue, Jan 23, 2024 5:09 AM

On 1/22/2024 8:10 PM, Caddiy via Discuss wrote:

The above looks good with 4 squares, but remove one or give it a
different colour and you see the Ilyushin. So how can a square be
prevented from jumping back at the end of its travel and move off at
90° instead?

Well, yeah.  If you want the end of your animation to connect seamlessly
to the beginning, the final image has to be the same as the first.  (Or,
really, more subtle than that, since you'd want the last frame to be the
frame before the first one, not the same as the first.  I think
maybe OpenSCAD handles that for you by never setting $t=1, but I'm not
sure.)

For the three-square case, you've got to generate four times as long an
animation, because you have to include the missing square crossing all
four sides.

See a solution below, and some more commentary below that.

 https://imgur.com/a/5N20EP6: “This post may contain erotic or
 adult imagery.” Disappointed, couldn’t find any.

Don't know what to tell you.  I don't have it marked "Mature".

--- Here's a solution for the "missing square" animation ---

// Divide the animation into 4 segments.
// i is which of the four segments we're in.
// t2 is where we are (0..1) in that segment.
// I don't know whether $t is ever exactly equal to 1.
// Just in case, suppress that with the min().
i = min(floor($t4), 3);
t2 = $t
4 - i;

// Order is important.  The first is motion across the right side,
// the second across the bottom, et cetera.
positions = [
[10, -t220+10],
[-20
t2+10, -10],
[-10, 20t2-10],
[t2
20-10, 10],
];

// The segment (i) says which of the sides doesn't have a square.
for (j=[0:len(positions)-1]) {
if (i != j) {
translate(positions[j])
square(5, center=true);
}
}

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}

--- Here's a solution for coloring the squares differently ---

// Divide the animation into 4 segments.
// i is which of the four segments we're in.
// t2 is where we are (0..1) in that segment.
// I don't know whether $t is ever exactly equal to 1.
// Just in case, suppress that with the min().
i = min(floor($t4), 3);
t2 = $t
4 - i;

// Order is important.  The first is motion across the right side,
// the second across the bottom, et cetera.
positions = [
[10, -t220+10],
[-20
t2+10, -10],
[-10, 20t2-10],
[t2
20-10, 10],
];

colors = [ "red", "green", "blue", "black" ];

// The segment (i) says which of the sides doesn't have a square.
// Note that the colored square here plus the difference below add
// up to a preview problem, because there are different facets (including
// negative objects) at the same place.  Lifting the squares just a hair
// fixes it.
for (j=[0:len(positions)-1]) {
color(colors[(4+i-j)%4])
translate(positions[j])
translate([0,0,0.001])
square(5, center=true);
}

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}


Additional commentary:

These are just one way to solve these problems.  They extend the
original illusion; each square moves on only one side, and an external
mechanism dynamically hides one of the squares or gives them the right
color.

You could also track one square all the way around by having key
locations and interpolating.  Here's that style, with the additional
tidbit of having the square get bigger and smaller during its travels.


xTable = [
[ 0.00, -10 ],
[ 0.25,  10 ],
[ 0.50,  10 ],
[ 0.75, -10 ],
[ 1.00, -10 ],
];
yTable = [
[ 0.00,  10 ],
[ 0.25,  10 ],
[ 0.50, -10 ],
[ 0.75, -10 ],
[ 1.00,  10 ],
];

sizeTable = [
[ 0.00, 2 ],
[ 0.50, 7 ],
[ 1.00, 2 ],
];

x = lookup($t, xTable);
y = lookup($t, yTable);
size = lookup($t, sizeTable);

translate([x,y])
square(size, center=true);

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}

On 1/22/2024 8:10 PM, Caddiy via Discuss wrote: > > The above looks good with 4 squares, but remove one or give it a > different colour and you see the Ilyushin. So how can a square be > prevented from jumping back at the end of its travel and move off at > 90° instead? > Well, yeah.  If you want the end of your animation to connect seamlessly to the beginning, the final image has to be the same as the first.  (Or, really, more subtle than that, since you'd want the last frame to be the frame *before* the first one, not the same as the first.  I think *maybe* OpenSCAD handles that for you by never setting $t=1, but I'm not sure.) For the three-square case, you've got to generate four times as long an animation, because you have to include the missing square crossing all four sides. See a solution below, and some more commentary below that. > * > > https://imgur.com/a/5N20EP6: “This post may contain erotic or > adult imagery.” Disappointed, couldn’t find any. > Don't know what to tell you.  I don't have it marked "Mature". --- Here's a solution for the "missing square" animation --- // Divide the animation into 4 segments. // i is which of the four segments we're in. // t2 is where we are (0..1) in that segment. // I don't know whether $t is ever exactly equal to 1. // Just in case, suppress that with the min(). i = min(floor($t*4), 3); t2 = $t*4 - i; // Order is important. The first is motion across the right side, // the second across the bottom, et cetera. positions = [ [10, -t2*20+10], [-20*t2+10, -10], [-10, 20*t2-10], [t2*20-10, 10], ]; // The segment (i) says which of the sides *doesn't* have a square. for (j=[0:len(positions)-1]) { if (i != j) { translate(positions[j]) square(5, center=true); } } // Draw the track. difference() { offset(0.1) square(20, center=true); offset(-0.1) square(20, center=true); } --- Here's a solution for coloring the squares differently --- // Divide the animation into 4 segments. // i is which of the four segments we're in. // t2 is where we are (0..1) in that segment. // I don't know whether $t is ever exactly equal to 1. // Just in case, suppress that with the min(). i = min(floor($t*4), 3); t2 = $t*4 - i; // Order is important. The first is motion across the right side, // the second across the bottom, et cetera. positions = [ [10, -t2*20+10], [-20*t2+10, -10], [-10, 20*t2-10], [t2*20-10, 10], ]; colors = [ "red", "green", "blue", "black" ]; // The segment (i) says which of the sides *doesn't* have a square. // Note that the colored square here plus the difference below add // up to a preview problem, because there are different facets (including // negative objects) at the same place. Lifting the squares just a hair // fixes it. for (j=[0:len(positions)-1]) { color(colors[(4+i-j)%4]) translate(positions[j]) translate([0,0,0.001]) square(5, center=true); } // Draw the track. difference() { offset(0.1) square(20, center=true); offset(-0.1) square(20, center=true); } --- Additional commentary: These are just one way to solve these problems.  They extend the original illusion; each square moves on only one side, and an external mechanism dynamically hides one of the squares or gives them the right color. You could also track one square all the way around by having key locations and interpolating.  Here's that style, with the additional tidbit of having the square get bigger and smaller during its travels. --- xTable = [ [ 0.00, -10 ], [ 0.25, 10 ], [ 0.50, 10 ], [ 0.75, -10 ], [ 1.00, -10 ], ]; yTable = [ [ 0.00, 10 ], [ 0.25, 10 ], [ 0.50, -10 ], [ 0.75, -10 ], [ 1.00, 10 ], ]; sizeTable = [ [ 0.00, 2 ], [ 0.50, 7 ], [ 1.00, 2 ], ]; x = lookup($t, xTable); y = lookup($t, yTable); size = lookup($t, sizeTable); translate([x,y]) square(size, center=true); // Draw the track. difference() { offset(0.1) square(20, center=true); offset(-0.1) square(20, center=true); }
JB
Jordan Brown
Tue, Jan 23, 2024 5:51 AM

Here's a couple more.


Bounce a square back and forth.  The trick is in mapping $t from 0..1 to
0..1..0:

t2 = 1 - abs($t*2-1);

translate([t2*20,0]) square(5, center=true);

That one is simple enough that it might be worth including as an example.


Given a set of points, travel from one to the next at a constant speed.

// The square will travel from the first position to the second, ..., to the last,
// at a constant speed.  For the animation to loop, ensure that the last point is the
// same as the first.
positions = [
[-20,0],
[20,0],
[0,20],
[0,-20],
[-20, 0],
];

// Constuct a temporary array of the distances between each point and the point before it.
distances = [
0,
for (i=[1:len(positions)-1]) norm(positions[i]-positions[i-1])
];

// A function that, given an array, yields the running sum of the
// array.  That is, the first entry is a[0], the second is a[0]+a[1],
// et cetera.
function runningSum(a) = [ for (i = 0, sum=0; i < len(a); sum = sum + a[i], i = i + 1) sum + a[i] ];

// Get an array of, for each point, how far you've gone so far.
runningDistances = runningSum(distances);
// And the total distance.
totalDistance = runningDistances[len(runningDistances)-1];

// Construct lookup arrays, with the lookup key being the fraction of the distance that we've gone
// at that point.
positionsX = [ for (i = [0:len(positions)-1]) [ runningDistances[i]/totalDistance, positions[i].x ] ];
positionsY = [ for (i = [0:len(positions)-1]) [ runningDistances[i]/totalDistance, positions[i].y ] ];

//  Finally, given the current time, lookup the current position and place the square.
position = [ lookup($t, positionsX), lookup($t, positionsY) ];
translate(position) square(5, center=true);

Here's a couple more. --- Bounce a square back and forth.  The trick is in mapping $t from 0..1 to 0..1..0: t2 = 1 - abs($t*2-1); translate([t2*20,0]) square(5, center=true); That one is simple enough that it might be worth including as an example. --- Given a set of points, travel from one to the next at a constant speed. // The square will travel from the first position to the second, ..., to the last, // at a constant speed. For the animation to loop, ensure that the last point is the // same as the first. positions = [ [-20,0], [20,0], [0,20], [0,-20], [-20, 0], ]; // Constuct a temporary array of the distances between each point and the point before it. distances = [ 0, for (i=[1:len(positions)-1]) norm(positions[i]-positions[i-1]) ]; // A function that, given an array, yields the running sum of the // array. That is, the first entry is a[0], the second is a[0]+a[1], // et cetera. function runningSum(a) = [ for (i = 0, sum=0; i < len(a); sum = sum + a[i], i = i + 1) sum + a[i] ]; // Get an array of, for each point, how far you've gone so far. runningDistances = runningSum(distances); // And the total distance. totalDistance = runningDistances[len(runningDistances)-1]; // Construct lookup arrays, with the lookup key being the fraction of the distance that we've gone // at that point. positionsX = [ for (i = [0:len(positions)-1]) [ runningDistances[i]/totalDistance, positions[i].x ] ]; positionsY = [ for (i = [0:len(positions)-1]) [ runningDistances[i]/totalDistance, positions[i].y ] ]; // Finally, given the current time, lookup the current position and place the square. position = [ lookup($t, positionsX), lookup($t, positionsY) ]; translate(position) square(5, center=true);
M
mikeonenine@web.de
Tue, Jan 23, 2024 6:05 AM

Jordan Brown wrote:

On 1/22/2024 8:10 PM, Caddiy via Discuss wrote:

The above looks good with 4 squares, but remove one or give it a
different colour and you see the Ilyushin. So how can a square be
prevented from jumping back at the end of its travel and move off at
90° instead?

Well, yeah.  If you want the end of your animation to connect seamlessly
to the beginning, the final image has to be the same as the first.  (Or,
really, more subtle than that, since you'd want the last frame to be the
frame before the first one, not the same as the first.  I think
maybe OpenSCAD handles that for you by never setting $t=1, but I'm not
sure.)

For the three-square case, you've got to generate four times as long an
animation, because you have to include the missing square crossing all
four sides.

See a solution below, and some more commentary below that.

https://imgur.com/a/5N20EP6: “This post may contain erotic or
adult imagery.” Disappointed, couldn’t find any.

Don't know what to tell you.  I don't have it marked "Mature".

--- Here's a solution for the "missing square" animation ---

// Divide the animation into 4 segments.
// i is which of the four segments we're in.
// t2 is where we are (0..1) in that segment.
// I don't know whether $t is ever exactly equal to 1.
// Just in case, suppress that with the min().
i = min(floor($t4), 3);
t2 = $t
4 - i;

// Order is important.  The first is motion across the right side,
// the second across the bottom, et cetera.
positions = [
[10, -t220+10],
[-20
t2+10, -10],
[-10, 20t2-10],
[t2
20-10, 10],
];

// The segment (i) says which of the sides doesn't have a square.
for (j=[0:len(positions)-1]) {
if (i != j) {
translate(positions[j])
square(5, center=true);
}
}

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}

--- Here's a solution for coloring the squares differently ---

// Divide the animation into 4 segments.
// i is which of the four segments we're in.
// t2 is where we are (0..1) in that segment.
// I don't know whether $t is ever exactly equal to 1.
// Just in case, suppress that with the min().
i = min(floor($t4), 3);
t2 = $t
4 - i;

// Order is important.  The first is motion across the right side,
// the second across the bottom, et cetera.
positions = [
[10, -t220+10],
[-20
t2+10, -10],
[-10, 20t2-10],
[t2
20-10, 10],
];

colors = [ "red", "green", "blue", "black" ];

// The segment (i) says which of the sides doesn't have a square.
// Note that the colored square here plus the difference below add
// up to a preview problem, because there are different facets (including
// negative objects) at the same place.  Lifting the squares just a hair
// fixes it.
for (j=[0:len(positions)-1]) {
color(colors[(4+i-j)%4])
translate(positions[j])
translate([0,0,0.001])
square(5, center=true);
}

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}


Additional commentary:

These are just one way to solve these problems.  They extend the
original illusion; each square moves on only one side, and an external
mechanism dynamically hides one of the squares or gives them the right
color.

You could also track one square all the way around by having key
locations and interpolating.  Here's that style, with the additional
tidbit of having the square get bigger and smaller during its travels.


xTable = [
[ 0.00, -10 ],
[ 0.25,  10 ],
[ 0.50,  10 ],
[ 0.75, -10 ],
[ 1.00, -10 ],
];
yTable = [
[ 0.00,  10 ],
[ 0.25,  10 ],
[ 0.50, -10 ],
[ 0.75, -10 ],
[ 1.00,  10 ],
];

sizeTable = [
[ 0.00, 2 ],
[ 0.50, 7 ],
[ 1.00, 2 ],
];

x = lookup($t, xTable);
y = lookup($t, yTable);
size = lookup($t, sizeTable);

translate([x,y])
square(size, center=true);

// Draw the track.
difference()
{
offset(0.1)
square(20, center=true);
offset(-0.1)
square(20, center=true);
}

I think I’ve got the last one: interpolation means you can allocate position values to incremental values of $t. Could probably be used to show the flow of a fluid in a pipe. Needs further study.

Jordan Brown wrote: > On 1/22/2024 8:10 PM, Caddiy via Discuss wrote: > > > The above looks good with 4 squares, but remove one or give it a > > different colour and you see the Ilyushin. So how can a square be > > prevented from jumping back at the end of its travel and move off at > > 90° instead? > > Well, yeah.  If you want the end of your animation to connect seamlessly > to the beginning, the final image has to be the same as the first.  (Or, > really, more subtle than that, since you'd want the last frame to be the > frame *before* the first one, not the same as the first.  I think > *maybe* OpenSCAD handles that for you by never setting $t=1, but I'm not > sure.) > > For the three-square case, you've got to generate four times as long an > animation, because you have to include the missing square crossing all > four sides. > > See a solution below, and some more commentary below that. > > > * > > > > ``` > > https://imgur.com/a/5N20EP6: “This post may contain erotic or > > adult imagery.” Disappointed, couldn’t find any. > > ``` > > Don't know what to tell you.  I don't have it marked "Mature". > > \--- Here's a solution for the "missing square" animation --- > > // Divide the animation into 4 segments. > // i is which of the four segments we're in. > // t2 is where we are (0..1) in that segment. > // I don't know whether $t is ever exactly equal to 1. > // Just in case, suppress that with the min(). > i = min(floor($t*4), 3); > t2 = $t*4 - i; > > // Order is important. The first is motion across the right side, > // the second across the bottom, et cetera. > positions = \[ > \[10, -t2*20+10\], > \[-20*t2+10, -10\], > \[-10, 20*t2-10\], > \[t2*20-10, 10\], > \]; > > // The segment (i) says which of the sides *doesn't* have a square. > for (j=\[0:len(positions)-1\]) { > if (i != j) { > translate(positions\[j\]) > square(5, center=true); > } > } > > // Draw the track. > difference() > { > offset(0.1) > square(20, center=true); > offset(-0.1) > square(20, center=true); > } > > \--- Here's a solution for coloring the squares differently --- > > // Divide the animation into 4 segments. > // i is which of the four segments we're in. > // t2 is where we are (0..1) in that segment. > // I don't know whether $t is ever exactly equal to 1. > // Just in case, suppress that with the min(). > i = min(floor($t*4), 3); > t2 = $t*4 - i; > > // Order is important. The first is motion across the right side, > // the second across the bottom, et cetera. > positions = \[ > \[10, -t2*20+10\], > \[-20*t2+10, -10\], > \[-10, 20*t2-10\], > \[t2*20-10, 10\], > \]; > > colors = \[ "red", "green", "blue", "black" \]; > > // The segment (i) says which of the sides *doesn't* have a square. > // Note that the colored square here plus the difference below add > // up to a preview problem, because there are different facets (including > // negative objects) at the same place. Lifting the squares just a hair > // fixes it. > for (j=\[0:len(positions)-1\]) { > color(colors\[(4+i-j)%4\]) > translate(positions\[j\]) > translate(\[0,0,0.001\]) > square(5, center=true); > } > > // Draw the track. > difference() > { > offset(0.1) > square(20, center=true); > offset(-0.1) > square(20, center=true); > } > > --- > > Additional commentary: > > These are just one way to solve these problems.  They extend the > original illusion; each square moves on only one side, and an external > mechanism dynamically hides one of the squares or gives them the right > color. > > You could also track one square all the way around by having key > locations and interpolating.  Here's that style, with the additional > tidbit of having the square get bigger and smaller during its travels. > > --- > > xTable = \[ > \[ 0.00, -10 \], > \[ 0.25, 10 \], > \[ 0.50, 10 \], > \[ 0.75, -10 \], > \[ 1.00, -10 \], > \]; > yTable = \[ > \[ 0.00, 10 \], > \[ 0.25, 10 \], > \[ 0.50, -10 \], > \[ 0.75, -10 \], > \[ 1.00, 10 \], > \]; > > sizeTable = \[ > \[ 0.00, 2 \], > \[ 0.50, 7 \], > \[ 1.00, 2 \], > \]; > > x = lookup($t, xTable); > y = lookup($t, yTable); > size = lookup($t, sizeTable); > > translate(\[x,y\]) > square(size, center=true); > > // Draw the track. > difference() > { > offset(0.1) > square(20, center=true); > offset(-0.1) > square(20, center=true); > } I think I’ve got the last one: interpolation means you can allocate position values to incremental values of $t. Could probably be used to show the flow of a fluid in a pipe. Needs further study.
N
neri-engineering
Tue, Jan 23, 2024 8:01 AM

Don't know if this is already mentioned but one function in particular I find to be incredibly useful.

T=awk "BEGIN{print $COUNT / $TOT_STEPS}"
W=awk "BEGIN{print (1 - (cos($PI * $T))) / 2}"
The above written in UNIX shell script.

In OpenSCAD language the "W smoothing function" can be written like so:

w = (1 - cos(180 * $t)) / 2

This causes 'w' to go from zero to one, as does $t, except that w accelerates very gradually at the beginning and then it decelerates very gradually at the end. The speed of how fast 'w' is changing at the beginning and at the end is zero. The nice thing about trig functions is that you can do a derivative however many times you want, and they will still be smooth. They are very natural-looking to the eye.

Here is an online tool to help you figure out these sorts of functions: https://www.desmos.com/calculator

Sent with Proton Mail secure email.

On Monday, January 22nd, 2024 at 5:21 PM, Jordan Brown via Discuss discuss@lists.openscad.org wrote:

On 1/22/2024 1:09 PM, jon wrote:

Thanks for sharing this, Jordan. I learned a lot!

You're welcome! (And do look at other Advent calendar entries; there's interesting animation in several.)

Linear and circular motion are fairly straightforward. Multiply $t by the distance to be moved, or multiply $t by 360 to walk around a circle.

For anything else, you need to somehow map the 0-1 range into the behavior that you want. That might be linear, or non-linear, or discontinuous. Interpolation is your friend.

The really hard part is that stuff like this is like Legos. Each part is small and, on its own, largely useless. It's all in how you put them all together - and there are an infinite number of ways to put them together so it's hard to just give somebody a step-by-step procedure.

Don't know if this is already mentioned but one function in particular I find to be incredibly useful. T=`awk "BEGIN{print $COUNT / $TOT_STEPS}"` W=`awk "BEGIN{print (1 - (cos($PI * $T))) / 2}"` The above written in UNIX shell script. In OpenSCAD language the "W smoothing function" can be written like so: w = (1 - cos(180 * $t)) / 2 This causes 'w' to go from zero to one, as does $t, except that w accelerates very gradually at the beginning and then it decelerates very gradually at the end. The speed of how fast 'w' is changing at the beginning and at the end is zero. The nice thing about trig functions is that you can do a derivative however many times you want, and they will still be smooth. They are very natural-looking to the eye. Here is an online tool to help you figure out these sorts of functions: https://www.desmos.com/calculator Sent with [Proton Mail](https://proton.me/) secure email. On Monday, January 22nd, 2024 at 5:21 PM, Jordan Brown via Discuss <discuss@lists.openscad.org> wrote: > On 1/22/2024 1:09 PM, jon wrote: > >> Thanks for sharing this, Jordan. I learned a lot! > > You're welcome! (And do look at other Advent calendar entries; there's interesting animation in several.) > > Linear and circular motion are fairly straightforward. Multiply $t by the distance to be moved, or multiply $t by 360 to walk around a circle. > > For anything else, you need to somehow map the 0-1 range into the behavior that you want. That might be linear, or non-linear, or discontinuous. Interpolation is your friend. > > The really hard part is that stuff like this is like Legos. Each part is small and, on its own, largely useless. It's all in how you put them all together - and there are an infinite number of ways to put them together so it's hard to just give somebody a step-by-step procedure.
GS
Guenther Sohler
Tue, Jan 23, 2024 8:24 AM

I am just wondering, if openscad could not do the same, what awk is doing
for you ?

Especially the desmos homepage is a great  find for me today.
They do not only have a great graphical calculator, but also a 2D
geometry engine, a 3D graph plotter and even an SDF solver.
I like it and will definitely bookmark it!

On Tue, Jan 23, 2024 at 9:02 AM neri-engineering via Discuss <
discuss@lists.openscad.org> wrote:

Don't know if this is already mentioned but one function in particular I
find to be incredibly useful.

 T=`awk "BEGIN{print $COUNT / $TOT_STEPS}"`
 W=`awk "BEGIN{print (1 - (cos($PI * $T))) / 2}"`

The above written in UNIX shell script.

In OpenSCAD language the "W smoothing function" can be written like so:

w = (1 - cos(180 * $t)) / 2

This causes 'w' to go from zero to one, as does $t, except that w
accelerates very gradually at the beginning and then it decelerates very
gradually at the end.  The speed of how fast 'w' is changing at the
beginning and at the end is zero.  The nice thing about trig functions is
that you can do a derivative however many times you want, and they will
still be smooth.  They are very natural-looking to the eye.

Here is an online tool to help you figure out these sorts of functions:
https://www.desmos.com/calculator

Sent with Proton Mail https://proton.me/ secure email.

On Monday, January 22nd, 2024 at 5:21 PM, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

On 1/22/2024 1:09 PM, jon wrote:

Thanks for sharing this, Jordan. I learned a lot!

You're welcome! (And do look at other Advent calendar entries; there's
interesting animation in several.)

Linear and circular motion are fairly straightforward. Multiply $t by the
distance to be moved, or multiply $t by 360 to walk around a circle.

For anything else, you need to somehow map the 0-1 range into the behavior
that you want. That might be linear, or non-linear, or discontinuous.
Interpolation is your friend.

The really hard part is that stuff like this is like Legos. Each part is
small and, on its own, largely useless. It's all in how you put them all
together - and there are an infinite number of ways to put them together so
it's hard to just give somebody a step-by-step procedure.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I am just wondering, if openscad could not do the same, what awk is doing for you ? Especially the desmos homepage is a great find for me today. They do not only have a great graphical calculator, but also a 2D geometry engine, a 3D graph plotter and even an SDF solver. I like it and will definitely bookmark it! On Tue, Jan 23, 2024 at 9:02 AM neri-engineering via Discuss < discuss@lists.openscad.org> wrote: > Don't know if this is already mentioned but one function in particular I > find to be incredibly useful. > > T=`awk "BEGIN{print $COUNT / $TOT_STEPS}"` > W=`awk "BEGIN{print (1 - (cos($PI * $T))) / 2}"` > > The above written in UNIX shell script. > > In OpenSCAD language the "W smoothing function" can be written like so: > > w = (1 - cos(180 * $t)) / 2 > > This causes 'w' to go from zero to one, as does $t, except that w > accelerates very gradually at the beginning and then it decelerates very > gradually at the end. The speed of how fast 'w' is changing at the > beginning and at the end is zero. The nice thing about trig functions is > that you can do a derivative however many times you want, and they will > still be smooth. They are very natural-looking to the eye. > > Here is an online tool to help you figure out these sorts of functions: > https://www.desmos.com/calculator > > Sent with Proton Mail <https://proton.me/> secure email. > > On Monday, January 22nd, 2024 at 5:21 PM, Jordan Brown via Discuss < > discuss@lists.openscad.org> wrote: > > On 1/22/2024 1:09 PM, jon wrote: > > Thanks for sharing this, Jordan. I learned a lot! > > > You're welcome! (And do look at other Advent calendar entries; there's > interesting animation in several.) > > Linear and circular motion are fairly straightforward. Multiply $t by the > distance to be moved, or multiply $t by 360 to walk around a circle. > > For anything else, you need to somehow map the 0-1 range into the behavior > that you want. That might be linear, or non-linear, or discontinuous. > Interpolation is your friend. > > The really hard part is that stuff like this is like Legos. Each part is > small and, on its own, largely useless. It's all in how you put them all > together - and there are an infinite number of ways to put them together so > it's hard to just give somebody a step-by-step procedure. > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >