10

I am trying to produce animations of asymptote pictures. Unfortunately, I am encountering some difficulties. Whenever I try to produce them directly in asymptote, my memory gets used up such that my browser crashes and I can no longer see the nice posts on the chat site. So this is not acceptable. ;-) After digesting this answer and this answer, I found a workaround. I write an asy code, which includes a file, which I write in the loop. (WHAT A MESS!) Then this snippet, when compiled with -shell-escape, produces an animation, which can be converted as described here with

convert -density 200 -delay 24 -loop 0 -alpha remove <file>.pdf <outfile>.gif

and this is the code:

\documentclass[border=3pt]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{asyduck.asf}
\begin{asypicture}{name=AsyDuck}
import graph3;
import solids;

size(6cm,6cm);
settings.render = 4;

include anglefile;
real viewangle = 4.5 - 3*beakangle*2*pi/360;

//currentprojection = perspective((0.6,0.3,1), up=Z,autoadjust=true);
currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
currentlight=(-3,-5,5);

// from https://tex.stackexchange.com/a/227192/121799
draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);

//draw(2X+2Y+2Z -- 2X-2Y+2Z -- -2X-2Y-2Z,white);

//limits((-1,-1,0),(1,1,1),Crop);

//limits((-2,-2,-2),(3,2,3));

// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// if I comment these two draw commands out, I get a completely different perspective
draw(O -- 2X,white, L=Label("$x$",position=EndPoint));
draw(O -- 2Y,white, L=Label("$y$", position=EndPoint));
//draw(O -- 2Z,white, L=Label("$z$", position=EndPoint));

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);


draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

draw(s5, surfacepen=m_eyeW);
draw(s6, surfacepen=m_eyeW);


real R=0.1, r=0.04;
draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
draw(surface(sphere(c4,r)),surfacepen=m_eyeB);
\end{asypicture}
\end{filecontents*}
\usepackage{asypictureB}
\standaloneenv{asypicture}
\usepackage{pgffor}


\begin{document}
\def\myangle{45}
\foreach \X [evaluate={\myangle=int(abs(20-\X))}] in {0,2,...,40}
{
\RequireAsyRecompile
\immediate\write18{echo "int beakangle = \myangle;" > anglefile.asy}
\input{asyduck.asf}
}
\end{document}

enter image description here

(I also don't know how the duck entered my asy code, it must be a very sneaky animal. ;-)

My question: Is there a simple way of achieving the same without these hacks?

EDIT: I got a very nice answer by Marcel Krüger, but my original question has been answered by Charles Staats, whom I'd like to thank at this point, in the comments. It turns out that he has already prepared his nice asypictureB package for this, I just failed to read the manual carefully. The upshot is that one can pass macros to the asypictures, one only needs to replace the \ by a @. With this one can include asymptote animations in a straightforward way into LaTeX documents:

\documentclass{standalone}
\standaloneconfig{border=-1.5cm -1.5cm -3cm 0.1cm} % see https://tex.stackexchange.com/q/422165/121799
\usepackage{filecontents}
\begin{filecontents*}{asyduck.asf}
\begin{asypicture}{name=AsyDuck}
import graph3;
import solids;

size(8cm,6cm);
settings.render = 4;

//include anglefile;
real beakangle = @myangle; // Big thanks to Charles Staats !!

real viewangle = 4.2 - 0*beakangle*2*pi/360;

//currentprojection = perspective((0.6,0.3,1), up=Z,autoadjust=true);
//currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1));
currentprojection=perspective(camera=scale3(4)*(2*cos(viewangle),2*sin(viewangle),1));

currentlight=(-3,-5,5);

// from https://tex.stackexchange.com/a/227192/121799
draw(scale(1.6,1.6,1.6)*unitsphere,lightgray+opacity(0));

// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// if I comment these two draw commands out, I get a completely different perspective
draw(O -- 2X,invisible, L=Label("$x$",position=EndPoint));
draw(O -- 2Y,invisible, L=Label("$y$", position=EndPoint));
draw(O -- 2Z,invisible, L=Label("$z$", position=EndPoint));

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple Water(pair uv) {
  real x = uv.x;
  real y = uv.y;
  real z = -0.2+0.1*cos(180*uv.x+18*beakangle) ;
  return (x, y, z);
}

//
//(0.5,0,1.5)
triple c1=S2((6pi/5,pi/4+0.3))+(-0.6,0,0.6);
triple c2=S2((4pi/5,pi/4+0.3))+(-0.6,0,0.6);
triple c3=S2((6pi/5,pi/4+0.5))+(-0.6,0,0.6);
triple c4=S2((4pi/5,pi/4+0.5))+(-0.6,0,0.6);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }
//shift(1.1,0,0.7)
surface s1 = shift(0,0,-0.2) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(-0.6,0,0.6) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s3 = shift(-0.8,0,0.7) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);
surface s4 = shift(-0.8,0,0.7) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(35, Z) * rotate(25, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-35, Z) * rotate(25, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s7 = surface(Water, (-3,-3), (5,3));


draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

draw(s5, surfacepen=m_eyeW);
draw(s6, surfacepen=m_eyeW);

draw(s7, surfacepen=blue+opacity(0.3));


real R=0.1, r=0.04;
draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
draw(surface(sphere(c4,r)),surfacepen=m_eyeB);
\end{asypicture}
\end{filecontents*}
\usepackage{asypictureB}
\standaloneenv{asypicture}
\usepackage{pgffor}
\begin{document}
\def\myangle{45}
\foreach \X [count=\n,evaluate={\myangle=int(abs(20-\X))}] in {0,2,...,40}
{
\RequireAsyRecompile
\input{asyduck.asf}
}
\end{document}

enter image description here

(If someone sees this and knows how to make the water more realistic and the duck more stable, it would be great if (s)he could share this knowledge with me.)

  • 4
    A pity we don't have a {duck} tag any more! – samcarter_is_at_topanswers.xyz Mar 18 '18 at 20:08
  • @samcarter Yes, especially since "Tag" means day in German, and we do have a Murmeltier Tag (Groundhog day). So sad that ducks are getting discriminated. ;-) –  Mar 18 '18 at 20:10
  • There is a rubber duck day: https://chat.stackexchange.com/transcript/41?m=42256080#42256080 (In case your ducks did not crash your chat :) – samcarter_is_at_topanswers.xyz Mar 18 '18 at 20:14
  • @samcarter Is this is the usual chat? (The animation is less than an MB, but probably there is no point in uploading it twice, the more so since I am not really done. I have trouble drawing the eyes in a nice way, i.e. I have not yet been able to convince asymptote to shade elliptical regions on an ellipsoid...) –  Mar 18 '18 at 20:18
  • Your eyes are probably more realistic anyway than the comic style version of the tikzducks! – samcarter_is_at_topanswers.xyz Mar 18 '18 at 20:54
  • @samcarter Nah, I really like the ducks of your package, they are cute, which this one is not. And there is not too much information on how to shade the eyes. When I put white flat ellipsoids it doesn't look too good, but perhaps that's my only option... –  Mar 18 '18 at 20:59
  • 1
    @marmot: Oh my, this is a scary duck ;-) Where is the sound? –  Mar 19 '18 at 00:11
  • Would this move easier if it has some wings? – Tarass Mar 19 '18 at 06:14
  • 1
    Note: As the author of the asypictureB package, I can confirm it was not designed to support animations. – Charles Staats Mar 19 '18 at 17:15
  • @CharlesStaats Thanks a lot! (I was just reading your nice tutorial and am wondering if there is an updated version, I'm particularly interested in cropping the picture. In this example, it would prevent the duck from jumping without shrinking it.) –  Mar 19 '18 at 17:23
  • 1
    No updated version -- I switched from mathematics to software engineering three years ago and my use of Asymptote (and TeX more generally) has tapered off. There are limited facilities for cropping 3d pictures in https://tex.stackexchange.com/a/159240/484 but I don't think they would apply for your use case. Something that might or might not help: invisible structures (create pen with opacity=0.0). – Charles Staats Mar 19 '18 at 17:32
  • @CharlesStaats Thanks again! Yes, I am aware of your Crop.asy. However, in the case at hand that would amount to applying it to each of the surfaces individually, right? Apart from being a bit cumbersome to type, this will also increase the compilation time. But thanks again, I really like your asypictureB. And sorry, one more thing, you allow the user to pass some keys to the asymptote codes, but not general lines, right? (If I was allowed to pass the line "int beakangle = \myangle;" to the asymptote code, I'd be done.) –  Mar 19 '18 at 17:38
  • 1
    @marmot: I'm glad you like it! Macros defined in TeX can be expanded (n.b. only expanded, not evaluated) inside an asypicture environment using @ instead of \\. See Section 6 of the asypictureB manual. – Charles Staats Mar 19 '18 at 17:52
  • @CharlesStaats Oh, I see! Thanks! So that's actually the answer I was looking for originally. But the answer below is (also) great. –  Mar 19 '18 at 18:01

1 Answers1

8

You can use the animate module for the animation. With default settings this needs a lot of memory, but you can add the global=false option to the animation constructor: With this option each frame is deleted from memory before the next one is generated, so the memory requirements are similar to your workaround. I also added another invisible sphare to stop the duck from jumping around: Run asy with the following source, this will directly generate the gif:

import animate;
import graph3;
import solids;

settings.render = 4;

currentlight=(-3,-5,5);


// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);

animation A=animation(global=false);
for(int i=20; i != -20; i -= 2) {
  int beakangle = abs(i);
  real viewangle = 4.5 - 3*beakangle*2*pi/360;

  currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
  surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);

  erase();

  size(10cm, 10cm);

  // from https://tex.stackexchange.com/a/227192/121799
  // draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(shift(1,1,1)*scale(2,2,2)*unitsphere,invisible);
  draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

  draw(s5, surfacepen=m_eyeW);
  draw(s6, surfacepen=m_eyeW);


  real R=0.1, r=0.04;
  draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
  draw(surface(sphere(c4,r)),surfacepen=m_eyeB);

  // Thanks to O.G.
  A.add(BBox(1cm, nullpen));
}
erase();
A.movie(delay=240);

enter image description here

For some reason this adds a lot of space and makes the duck smaller, so we have an animated duckling. Fixed with O.G. comment.

To integrate this into a LaTeX file, you can use the asymptote package. In my experiments it did not work with asypictureB because of the missing inline support. You have to replace A.movie with A.pdf to generate a PDF animation instead of a gif file. Attention: Your PDF Reader requires JavaScript support to show this file.

\documentclass[border=3pt]{standalone}
\usepackage[inline]{asymptote}
\usepackage{animate}
\standaloneenv{asypicture}
\begin{document}
\begin{asy}
import animate;
import graph3;
import solids;

settings.render = 4;

currentlight=(-3,-5,5);


// from https://tex.stackexchange.com/a/361583/121799
material m_eyeW=material(diffusepen=gray(0.001), emissivepen=gray(0.75), specularpen=gray(0.95),shininess=0.15);
material m_eyeB=material(diffusepen=gray(0.001), emissivepen=gray(0.01), specularpen=gray(0.9),shininess=0.15);

// SURFACES
// body
triple S1(pair uv) {
  real x = 1.1*cos(uv.x)*sin(uv.y);
  real y = 0.6*sin(uv.x)*sin(uv.y);
  real z =    0.6*       cos(uv.y)+0.4*sin(uv.y)/(1+uv.y);
  return (x, y, z);
}

// head (yes, I know that this is just an ellipsoid, but I plan to deform it)
triple S2(pair uv) {
  real x = 0.5*cos(uv.x)*sin(uv.y);
  real y = 0.5*sin(uv.x)*sin(uv.y);
  real z =    0.625*       cos(uv.y);
  return (x, y, z);
}

// beak (Alan Munn doesn't like it but he does not need to marry this duck ;-)
triple S3(pair uv) {
  real x = 0.6*cos(uv.x)*sin(uv.y);
  real y = 0.2*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple S4(pair uv) {
  real x = 0.03*cos(uv.x)*sin(uv.y);
  real y = 0.15*sin(uv.x)*sin(uv.y);
  real z =     0.2*      cos(uv.y);
  return (x, y, z);
}

triple c1=S2((6pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c2=S2((4pi/5,pi/4+0.25))+(0.5,0,1.5);
triple c3=S2((6pi/5,pi/4+0.45))+(0.5,0,1.5);
triple c4=S2((4pi/5,pi/4+0.45))+(0.5,0,1.5);

bool nearc1(triple pt) { return dot((pt-0.9*c1),c1) >0; }
bool nearc2(triple pt) { return (dot(pt,c2) - 0.1 >0); }

surface s1 = shift(1.1,0,0.7) * rotate(10, X) * surface(S1, (0, 0), (2pi, pi), 64, 64, Spline);
surface s2 = shift(0.5,0,1.5) * rotate(00, X) * surface(S2, (0, 0), (2pi, pi), 64, 64, Spline);
surface s4 = shift(0.3,0,1.6) * rotate(-20, Y) * surface(S3, (pi/2,pi/2), (3pi/2,pi), 64, 64, Spline);
surface s5 = shift(0.98*c1) * rotate(30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);
surface s6 = shift(0.98*c2) * rotate(-30, Z) * rotate(20, Y) * surface(S4, (0,0), (2pi,pi), 64, 64, Spline);

animation A=animation(global=false);
settings.inlinetex=false;
for(int i=20; i != -20; i -= 2) {
  int beakangle = abs(i);
  real viewangle = 4.5 - 3*beakangle*2*pi/360;

  currentprojection=perspective(camera=(2*cos(viewangle),2*sin(viewangle),1.5));
  surface s3 = shift(0.3,0,1.6) * rotate(-20+beakangle, Y) * surface(S3, (pi/2,0), (3pi/2,pi/2), 64, 64, Spline);

  erase();

  size(10cm, 10cm);

  // from https://tex.stackexchange.com/a/227192/121799
  // draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(scale(1.5,1.5,1.5)*shift(0.5,0,0.7)*unitsphere,invisible);
  draw(shift(1,1,1)*scale(2,2,2)*unitsphere,invisible);
  draw(s1, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s2, surfacepen=material(diffusepen=yellow,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s3, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));
  draw(s4, surfacepen=material(diffusepen=orange,emissivepen=gray(0.3),specularpen=gray(0.1)));

  draw(s5, surfacepen=m_eyeW);
  draw(s6, surfacepen=m_eyeW);


  real R=0.1, r=0.04;
  draw(surface(sphere(c3,r)),surfacepen=m_eyeB);
  draw(surface(sphere(c4,r)),surfacepen=m_eyeB);

  A.add(BBox(1cm,nullpen));
}
erase();
settings.inlinetex=true;
label(A.pdf("autoplay,loop",delay=240,keep=!settings.inlinetex));
\end{asy}
\end{document}

If this is saved as asyduck.tex you can build this with latexmk or

pdflatex asyduck
asy asyduck-*.asy
pdflatex asyduck
pdflatex asyduck
  • This looks really great! And yes, this is a very nice way to make animations. Yet I am also interested in incorporating this in a LaTeX document (after all, this is a LaTeX site). So I wait a tiny bit and see if someone comes up with a LaTeX solution. BTW, might it be that the smallness of the output comes from the fact that your code has two invisible spheres, the one from my original code and the one you added? (But clearly my invisible sphere was a bit stupid as I shifted it to be somewhere not too far from the "center" of the duck, but I still rotated the camera around the origin.) –  Mar 19 '18 at 01:42
  • I added a bit about embedding this into LaTeX. I think the size is caused by something else because I had the same problem before addig the second sphere. – Marcel Krüger Mar 19 '18 at 07:31
  • BBox(10cm) adds a very large 10cm border frame. So BBox(1cm) will be sufficient. Great animation. – O.G. Mar 19 '18 at 15:22
  • @O.G. Right, but with smaller BBoxes I had problems lines appearing at the border of the picture on some frames and the BBox was the only way I could find to fix this. – Marcel Krüger Mar 19 '18 at 15:33
  • BBox(1cm,nullpen) ? – O.G. Mar 19 '18 at 15:43
  • @O.G. Awesome, that worked. – Marcel Krüger Mar 19 '18 at 15:53
  • I'll be more than happy to accept this beautiful answer. (I didn't see this this conversation till now, nor the update.) Could you or @O.G. kindly teach me how to add a BBbox to my original code? –  Mar 19 '18 at 17:52
  • @marmot What do you mean by BBox, a border with specified margin and pen (colour, size) ? See the documentation http://asymptote.sourceforge.net/doc/Frames-and-pictures.html (search bbox, which is not in the index). It seems that there are some artefacts with tiny pen. – O.G. Mar 19 '18 at 20:51
  • @O.G. I am referring to your comment above BBox(1cm,nullpen). Is there a way I can add something similar to my above code (such that the duck doesn't jump)? –  Mar 19 '18 at 21:20
  • @marmot the duck jumps are due to automatic adjust camera. You can observe that adding autoadjust=false gives an error message camera too close. First try asy -V to choose the value of the camera variables. Secondly you can see my answer to this question : https://tex.stackexchange.com/questions/227136/asymptote-maintain-window-size-while-changing-pov-in-animation. Adding a well chosen invisible sphere will help. (I forget this question and my answer). – O.G. Mar 20 '18 at 08:27
  • @O.G. Thanks! I was well aware of your nice answer, I cite it just under current light in my code. And I will play with the camera position. –  Mar 20 '18 at 12:59