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}
(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}
(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.)



asypictureBpackage, I can confirm it was not designed to support animations. – Charles Staats Mar 19 '18 at 17:15opacity=0.0). – Charles Staats Mar 19 '18 at 17:32asypictureenvironment using@instead of\\. See Section 6 of the asypictureB manual. – Charles Staats Mar 19 '18 at 17:52