MATHWORKS官方举办的迷你黑客大赛第三期(MATLAB Flipbook Mini Hack)的最新进展!!
很荣幸前三周都成为了阶段性获奖者~:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/13382
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/13917
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14937
下面正式开始!
本次比赛要求提交名为drawframe(f)
的函数代码,生成长达2s,48帧的动态图,动图生成是依靠如下代码来做到的:
function contestAnimator()
animFilename = 'animation.gif'; % Output file name
firstFrame = true;
framesPerSecond = 24;
delayTime = 1/framesPerSecond;
% Create the gif
for frame = 1:48
drawframe(frame)
fig = gcf();
fig.Units = 'pixels';
fig.Position(3:4) = [300,300];
im = getframe(fig);
[A,map] = rgb2ind(im.cdata,256);
if firstFrame
firstFrame = false;
imwrite(A,map,animFilename, LoopCount=Inf, DelayTime=delayTime);
else
imwrite(A,map,animFilename, WriteMode="append", DelayTime=delayTime);
end
end
end
闲话少叙,一起看作品!!
作品概览
我之前写的玫瑰改成的动图版:
Zhaoxu Liu / slandarer / rose bouquet
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14747
function drawframe(g)
if g==1
s=@sin;c=@cos;f=@surface;e=@size;
[xr,tr]=meshgrid((0:24)./24,(0:0.5:575)./575.*20.*pi+4*pi);
p=(pi/2)*exp(-tr./(8*pi));
cr=s(15*tr)/150;
u=1-(1-mod(3.6*tr,2*pi)./pi).^4./2+cr;
yr=2*(xr.^2-xr).^2.*s(p);
rr=u.*(xr.*s(p)+yr.*c(p));
hr=u.*(xr.*c(p)-yr.*s(p));
rb=0:.01:1;
tb=linspace(0,2,151);
w=rb'*((abs((1-mod(tb*5,2))))/2+.3);
xb=w.*c(tb*pi);
yb=w.*s(tb*pi);
zb=@(a)(-c(w*a*pi)+1).^.2;
Zb=zb(1.2);
cL=[.33 .33 .69;.68 .42 .63;.78 .42 .57;.96 .73 .44];
cMr=sH(hr,cL);
cMb=sH(Zb,cL.*.4+.6);
yz=72*pi/180;
rx1=pi/8;
rx2=pi/9;
Rz2=[c(yz),-s(yz),0;s(yz),c(yz),0;0,0,1];
Rz=@(n)[c(yz/n),-s(yz/n),0;s(yz/n),c(yz/n),0;0,0,1];
Rx=@(n)[1,0,0;0,c(n),-s(n);0,s(n),c(n)];
Rz1=Rz(2);Rz3=Rz(3);
Rx1=Rx(rx1);Rx2=Rx(rx2);
hold on
cp={'EdgeAlpha',0.05,'EdgeColor','none','FaceColor','interp','CData',cMr};
f(rr.*c(tr),rr.*s(tr),hr+0.35,cp{:})
[U,V,W]=rT(rr.*c(tr),rr.*s(tr),hr+0.35,Rx1);
V=V-.4;
f(U,V,W-.1,cp{:})
dS(U,V,W-.1)
for k=1:4
[U,V,W]=rT(U,V,W,Rz2);
f(U,V,W-.1,cp{:})
dS(U,V,W-.1)
end
[u1,v1,w1]=rT(xb./2.5,yb./2.5,Zb./2.5+.32,Rx2);
v1=v1-1.35;
[u2,v2,w2]=rT(u1,v1,w1,Rz1);
[u3,v3,w3]=rT(u1,v1,w1,Rz3);
[u4,v4,w4]=rT(u3,v3,w3,Rz3);
U={u1,u2,u3,u4};
V={v1,v2,v3,v4};
W={w1,w2,w3,w4};
for k=1:5
for b=1:4
[ut,vt,wt]=rT(U{b},V{b},W{b},Rz2);
U{b}=ut;V{b}=vt;W{b}=wt;
f(U{b},V{b},W{b},cp{3:7},cMb)
dS(U{b},V{b},W{b})
end
end
a=gca;axis off
a.Position=[0,0,1,1]+[-1,-1,2,2]./6;
axis equal
end
view(g*2.1,35);
function c=sH(H,cList)
X=(H-min(min(H)))./(max(max(H))-min(min(H)));
x=(0:e(cList,1)-1)./(e(cList,1)-1);
u=cList(:,1);v=cList(:,2);w=cList(:,3);
q=@interp1;
c(:,:,1)=q(x,u,X);
c(:,:,2)=q(x,v,X);
c(:,:,3)=q(x,w,X);
end
function [U,V,W]=rT(X,Y,Z,R)
U=X.*0;V=Y.*0;W=Z.*0;
for i=1:e(X,1)*e(X,2)
v=[X(i);Y(i);Z(i)];
n=R*v;U(i)=n(1);V(i)=n(2);W(i)=n(3);
end
end
function dS(X,Y,Z)
[m,n]=find(Z==min(min(Z)));
m=m(1);n=n(1);
x1=X(m,n);y1=Y(m,n);z1=Z(m,n)+.03;
x=[x1,0,(x1.*c(pi/3)-y1.*s(pi/3))./3].';
y=[y1,0,(y1.*c(pi/3)+x1.*s(pi/3))./3].';
z=[z1,-.7,-1.5].';
p=[x,y,z];
N=50;
t=(1:N)/N;
q=e(p,1)-1;
F=@factorial;
c1=F(q)./F(0:q)./F(q:-1:0);
c2=((t).^((0:q)')).*((1-t).^((q:-1:0)'));
p=(p'*(c1'.*c2))';
plot3(p(:,1),p(:,2),p(:,3),'Color',[88,130,126]./255)
end
end
由我代码remix的一个作品~
ME / Moving points on circles - color changes with y coordinate
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14732
function drawframe(f)
alpha0=pi/6;
K=18;
R=sqrt(3)/2;
[XMesh,YMesh]=meshgrid(1:K);
tList=linspace(0,2*pi,100);
tCos=[cos(tList).*R,nan]';
tSin=[sin(tList).*R,nan]';
tX=tCos+XMesh(:)';tX=tX(:);
tY=tSin+YMesh(:)';tY=tY(:);
figure('Units','normalized','Position',[.3,.2,.5,.65]);
plot(tX,tY,'Color',[0.2,0.2,0.2,.8],'LineWidth',1)
% -----------------------------
ax=gca;hold on;
ax.XLim=[0,K+1];
ax.YLim=[0,K+1];
ax.XColor='none';
ax.YColor='none';
ax.PlotBoxAspectRatio=[1,1,1];
ax.Position=[0,0,1,1];
% -----------------------------
dTheta=2*pi/48;
alpha=flipud(XMesh+YMesh);
thetaMesh=alpha(:).*alpha0;
% -----------------------------
for i=1:f
thetaMesh=thetaMesh+dTheta;
pntHdl.XData=cos(thetaMesh).*R+XMesh(:);
pntHdl.YData=sin(thetaMesh).*R+YMesh(:);
end
%-----------------------------
pntHdl=scatter(cos(thetaMesh).*R+XMesh(:),...
sin(thetaMesh).*R+YMesh(:),...
15,sin(thetaMesh).*R,'filled');
set(gca,'Color','k');
set(gcf,'Color','k');
end
Danuanping / Tablecloth
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14547
function drawframe(f)
[i,j]=meshgrid(0:1023);
s=3./(j+99);DIM=1024;
y=(j+sin((i.*i+(j-700).^2.*5)./100./DIM+2*pi/48*f).*35).*s;
P(:,:,1)=(mod(round((i+DIM).*s+y),2)+mod(round((DIM.*2-i).*s+y),2)).*110;
P(:,:,2)=(mod(round(5.*((i+DIM).*s+y)),2)+mod(round(5.*((DIM.*2-i).*s+y)),2)).*127;
P(:,:,3)=(mod(round(29.*((i+DIM).*s+y)),2)+mod(round(29.*((DIM.*2-i).*s+y)),2)).*100;
imshow(uint8(P))
end
Adam Danz / Street puddle on a rainy day in the MATropolis
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14762
function drawframe(f)
% Persistent variable definitions
% CD: CData of full city reflection image
% R: surface object for the city image in the puddle reflection
persistent CD R
if f==1
%% Create city reflection (variable CD)
rng default
axes(colorm=gray,Color='k',Projection='perspective')
hold on
h=randg(2,5,5); % building heights
b=bar3(h); % buildings
set(b,{'CData'},get(b,'ZData'),{'FaceColor'},{'interp'}) % lighter at top
b(3).delete % remove a row of buildings
% Set up axes and field of view
axis equal
clim([0,3])
campos([3,3,0])
camtarget([4 3 6])
camva(90)
camup([-1 0 0])
% loop through the buildings to add windows
for i=1:5
for j=[1 2 4 5]
s=(j<3)*.82-.41; % which side of the building will be windows be on
c=.1:.2:h(i,j)-.2;
d=[c;c];
z=d(:)'+[0;0;.1;.1];
y=i+[-.2,.2]+[-1;1;1;-1]/12;
y=repmat(y,size(c));
ison=logical(rand(1,numel(d))>0.4);
patch(z(:,ison)*0+j+s,y(:,ison),z(:,ison),[.48 .46 .17]); % Lights on
patch(z(:,~ison)*0+j+s,y(:,~ison),z(:,~ison),[.2 .2 .3]); % Lights off
end
end
% Create coherent noise for clouds
m=400;
X=linspace(-1,1,m);
d=hypot(X,X').^-1.7;
fr=fftshift(fft2(rand(m)));
sd=ifft2(ifftshift(fr.*d));
% Scale the noise to within the clim
cl=rescale(abs(sd),0,2);
% Plot cloudy sky; x and y extents will be large due to perspective
w=linspace(-20,30,m);
surf(w,w,max(h(:))+ones(m)-.9,FaceColor='texturemap',EdgeColor='none',CData=cl);
% capture image
fr=getframe;
CD=flipud(fr.cdata); % Take a peek: clf; imagesc(CD); set(gca,'YDir','normal')
%% Iterate the buffer to the 48th frame so we start with the end-state
% This will simulate the entire 48-frame animation and use the updated
% image as a starting point so the animation cycles (because Ned keeps
% praising animations that cycle :D)
rng(860411,'twister')
G=rng;
updatebuf(CD,1);
for i=2:48
updatebuf(CD,0);
end
%% Create street terrain
rng(790316,'twister') % This seed makes a nice puddle
n=1000; % determines size of the final image
X=linspace(-1,1,n); %create linear r matrix
[~,r]=cart2pol(X,X');
rd=rand(n);
filt=r.^-2.5; % roughness of puddle edges -- 2.5 is great,2.0-edges are too rough
fr=fftshift(fft2(rd));
td=ifft2(ifftshift(fr.*filt));
st=-rescale(abs(td),-0.2,0); % This scales from 0 to .2
wlev=0.13; % Water level; 0.12 and 0.13 look good
%% Plot street terrain
clf % clear figure
g=rescale(imgaussfilt(rand(n),2),0,1); % street texture
surf(1:n,1:n,st,FaceColor='texturemap',CData=g,EdgeColor='none'); % street
hold on
view(2)
colormap gray
set(gca,'Position',[0 0 1 1])
%% Initialize puddle reflection (variable R)
% add the city image and water level depth
u=size(CD);
R=surf(linspace(0,n,u(1)),linspace(0,n,u(2)),zeros(u([2,1]))+wlev,...
FaceColor='Texturemap',EdgeColor='none',CData=CD);
clim([0,1])
%% Return random number generator state to replicate ripples
% This must be at the end of setup
rng(G)
end
% Update ripples and rain drops on each iteration
[xo,yo]=updatebuf(CD,0);
R.CData=updateCD(CD,xo,yo);
end
function [xo,yo]=updatebuf(CD,TF)
% Update buffers
persistent b1 b2
[r,c]=size(CD,1:2); % reflection image size
if TF || isempty(b1)
% Create buffers that map ripples on to the image on first call
b1=zeros(r,c);
b2=b1;
end
% Animation: add rain drops
% Set up some variables that won't change between iterations
d=1/36; % dampening parameter determins how quickly the ripples fade,lower values last longer
M=zeros(3); % mask
M(2:2:end)=1;
xM=[-1 0 1];
yM=[-1;0;1];
[x,y]=meshgrid(1:c,1:r);
% On each frame there is a probability of there being a new rain drop
if rand<.2 % increase threshold to increase frequency of new drops
xp=randi(c);
yp=randi(r);
startX=max(1,xp-10);
startY=max(1,yp-10);
b2(startY:yp,startX:xp)=-randi(100);
end
% Propagate the ripples
for k=1:3
b2=filter2(M,b1)/2 - b2;
b2=b2 - b2*d;
xo=min(c,max(1,x+filter2(xM,b2))); % x-offset bounded by [1,c]
yo=min(r,max(1,y+filter2(yM,b2))); % y-offset bounded by [1,r]
% Swap buffers
tmp=b2;
b2=b1;
b1=tmp;
end
end
function I=updateCD(CD,xo,yo)
% Create the a new image by applying the buffer offsets to the old image CData
f=@(i)interp2(double(CD(:,:,i)),xo,yo);
I(:,:,1)=f(1);
I(:,:,2)=f(2);
I(:,:,3)=f(3);
I=uint8(I);
end
Tim / Light ripples
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14952
function drawframe(f)
persistent S wgt dd2
if f == 1
rng default
tic
% Underwater scene.
% 1) Procedural ripples from 2 years ago
N=400;
H=randn(N);
y=1:N;
r=@round;
k=zeros(N);
k(r(rand(3)*N^2))=1;
k=conv2(k,ones(29),'same')<1;
for n=1:400
d=gradient(H);
g=1.4*(d+1)/6;
m=mod(r(y+randn(N).*k*4),N)+1;
o=mod(r(y'+(5-9*d).*k),N)+1;
H=conv2(H-g+accumarray([o(:),m(:)],g(:),[N,N]),ones(3)/9,'same');
end
% 2) Light caustics
[x,y]=meshgrid(linspace(0,1,N));
xyzg=[x(:),y(:),x(:)*0];
xyzi=rand(N*5,3);
zscl=0.1;
xyzi=[xyzi-[0,0,1];xyzi;xyzi+[0,0,1]].*[1,1,zscl];
kdOBJ = KDTreeSearcher(xyzi);
zvl=0:.021:1;
clear distS
for n = 1:48
[idx, dist] = knnsearch(kdOBJ,xyzg+[0,0,zvl(n)*zscl],'k',1);
distS(:,:,n)=reshape(erf(dist.^2*150), size(x));
end
toc
rng default
% 3) Weight map between color schemes
dst = sqrt((x-.1).^2 + (y-.1).^2);
wgt = erf((1-dst*3)*3)/2+.5;
wga = erf((1-dst*1.5)*5)/2+.5;
% distS = (distS+0.8).^((wgt+0.2)/1.2)-.8;
distS = distS.*(wgt+.2)/1.2;
% 4) Color schemes
cst = distS(:,:,1);
cR = rescale(min(6*cst, 1), 0.7, 1);
cst3 = cat(3,cR.^8,cR.^2.5,cR.^0.9);
cst3B = cat(3,cR,cR.^1.1,cR.^1.8);
cnw = cst3B.*wgt + cst3.*(1-wgt);
% x(wga<1e-2)=nan;
% y(wga<1e-2)=nan;
% imagesc(wga)
%
%%
clf
cv=.63;
CC=[cv.^8,cv.^2.5,cv.^.9];
set(gcf,'color',CC);
% "Light" causes loop to time out, so this leverages surfnorm to calculate
% lambertian scattering from a local source
cpxyz = [.4,.4,.7]*1;
xyzl = ([x(:),y(:),0*x(:)]-cpxyz)';
xyzl = xyzl./vecnorm(xyzl);
[nx,ny,nz]=surfnorm(x,y,H/2000+randn(size(H))/6000);
dd2 = abs(reshape(sum(xyzl.*[nx(:),ny(:),nz(:)]'),[400,400]));
dd2=dd2.^.9;
S=surf(x,y,H/2000+randn(size(H))/6000,cnw.*dd2, 'SpecularStrength', 0, 'AmbientStrength', 0, 'DiffuseStrength', 1,'FaceAlpha','flat','AlphaData',wga);
shading flat
camproj p
campos([0.0, 0.0, 0.15]);
camtarget([0.5, 0.5, 0]*0.4);
camva(30);
% light('position', [.5, .5, .5], 'style', 'local');
% light('position', [.5, .5, .5], 'style', 'local','color',[1,1,1]*.3);
axis equal off
axis([-2,2,-2,2,-2,2]);
S.UserData=distS;
% lighting g
%%
end
ags = linspace(0,2*pi,49);
% for n = 1;
cst = S.UserData(:,:,f);
cR = rescale(min(6*cst, 1), 0.7, 1);
cst3 = cat(3,cR.^8,cR.^2.5,cR.^0.9);
cst3B = cat(3,cR,cR.^1.1,cR.^1.8);
cnw = cst3B.*wgt + cst3.*(1-wgt);
camup([0, sin(ags(f)+pi/2)*0.05, cos(ags(f)+pi/2)*0.05+1]);
campos([0.0, 0.0, 0.15+sin(ags(f))/45]);
S.CData = cnw.*dd2;
% drawnow;
toc
end
Jr / dandelions
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/15037
function drawframe(f)
n=80;
h=pi*(3-5^.5);
z=linspace(1-1/n,1/(n-1),n);
t=h.*linspace(0,n,n);
r=(1-z.^2);
p=r*f/60.*cos(t*f);
q=r*f/60.*sin(t*f);
u=r*f/90.*cos(t);
v=r*f/90.*sin(t);
image(zeros(99,100,3))
hold on
plot(flip(30*(z.^2))+34,80*(-z)+110,'-','LineWidth',4,'Color',[.41 .59 .29])
plot(30*(z.^2)+45,80*(-z)+100,'-','LineWidth',4,'Color',[.41 .59 .29])
for k=1:n
plot3(17*([0 u(k)]+2),17*([0 v(k)]+1.8),170*([0 z(k)]),'*--w','markersize',.1)
plot3(17*([0 p(k)]+4.4),17*([0 q(k)]+1.2),170*([0 z(k)]),'*--w', 'markersize',.1)
end
ht=text(55,80,'🌿','color','g','FontSize',60+f/4,'Color',[.41 .59 .29]);
kt=text(27,80,'🌿','color','g','FontSize',55+f/4,'Color',[.41 .59 .29]);
kt.Rotation = 90
axis equal off %I kind of liked the stem coming out of the figure
end
Shanshan / Sticky note--upgraded version 2
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries/14982
function drawframe(f)
ax=axes('position',[0 0 1 1]);
dx=sin(f*0.15);
map=(turbo);
c=map(f*5,:);
x=[-1+dx 1 1-dx -1]*0.8^((f-1)/5);
y=[-1 -1+dx 1 1-dx]*0.8^((f-1)/5);
patch(x,y,c,'edgecolor','none')
hold on
xlim([-1 1])
ylim([-1 1])
axis equal off
end
完
比赛还有3天就结束啦,感兴趣的快去参加:
https://ww2.mathworks.cn/matlabcentral/communitycontests/contests/6/entries