This is just for fun. It draws the buckets in 3d. This part is reasonable, but the computation of the critical angle is just stolen from the [code for the cone](https://topanswers.xyz/tex?q=1264). Then it places the balls avoiding collisions. This also sort of works. However, there are serious drawbacks. Apart from the bulky code there is no 3d ordering in place. Even worse, if the random numbers do not find a solution that does not intersect with previous balls, an error message will be issued. And of course it does not stack the balls if the lowest layer is full. All other parts are stolen from [samcarter's answer](https://topanswers.xyz/tex?q=1337#a1582).
```
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/bucket back/.style={code={%
\path[fill=gray] circle[radius=Rsmall];
\path[smooth,left color=gray!10,right color=gray!60!black]
plot[domain=\tdplotmainphi+180-\alphacrit:\tdplotmainphi+\alphacrit-360+s]
({Rsmall*cos(\x)},{Rsmall*sin(\x)},0) --
plot[domain=\tdplotmainphi+\alphacrit-360+s:\tdplotmainphi+180-\alphacrit]
({R*cos(\x)},{R*sin(\x)},h) -- cycle;
\path[smooth,left color=gray,right color=gray!10]
plot[domain=\tdplotmainphi+\alphacrit-360+s:\tdplotmainphi+\alphacrit-360]
({Rsmall*cos(\x)},{Rsmall*sin(\x)},0) --
plot[domain=\tdplotmainphi+\alphacrit-360:\tdplotmainphi+\alphacrit-360+s]
({R*cos(\x)},{R*sin(\x)},h) -- cycle;
}},
pics/bucket fore/.style={code={%
\path[smooth,left color=gray!10,right color=gray]
plot[domain=\tdplotmainphi+180-\alphacrit:\tdplotmainphi+\alphacrit-180+s]
({Rsmall*cos(\x)},{Rsmall*sin(\x)},0) --
plot[domain=\tdplotmainphi+\alphacrit-180+s:\tdplotmainphi+180-\alphacrit]
({R*cos(\x)},{R*sin(\x)},h) -- cycle;
\path[smooth,left color=gray!60!black,right color=gray!10]
plot[domain=\tdplotmainphi+\alphacrit-180+s:\tdplotmainphi+\alphacrit]
({Rsmall*cos(\x)},{Rsmall*sin(\x)},0) --
plot[domain=\tdplotmainphi+\alphacrit:\tdplotmainphi+\alphacrit-180+s]
({R*cos(\x)},{R*sin(\x)},h) -- cycle;
}},
bucket/.cd,place bucket/.code={\foreach \XX in {1,...,50}
{}}}
\begin{document}
\pgfmathsetseed{\number\pdfrandomseed}%
\foreach \ZZZ in {1,...,12}
{\begin{tikzpicture}[declare function={r=0.1;% radius of ball
R=0.4;% upper radius of bucket
Rsmall=0.35;% lower radius of
h=0.9;% height
N=8;% number of buckets
Nc=4;% number of colors/balls
d=1;% distance between the buckets
H=R*h/(R-Rsmall);% height of virtual cone
s=120;% shading
}]
\tdplotsetmaincoords{110}{00}
\begin{scope}[tdplot_main_coords,transform shape]
\pgfmathtruncatemacro{\Xmax}{N}
\pgfmathsetmacro{\alphacrit}{90+acos(R*cos(\tdplotmaintheta)/H)}%
\path foreach \X in {1,...,\Xmax} {(\X*d,0,0) pic{bucket back}};
\pgfmathtruncatemacro{\numcolors}{Nc}
\pgfmathparse{1/\numcolors}%
\definecolorseries{foo}{hsb}{step}{red!90!black}{\pgfmathresult,0,0}
\resetcolorseries[\numcolors]{foo}%
\foreach \Y in {1,...,\numcolors}
{\pgfmathrandominteger{\ibucket}{1}{\Xmax}%
\foreach \Z in {1,...,5000} % maximum 5000 tries
{\pgfmathsetmacro{\xrnd}{rnd*(Rsmall-r)}
\pgfmathsetmacro{\yrnd}{rnd*(Rsmall-r)}
\pgfmathtruncatemacro{\itest}{(sqrt(\xrnd*\xrnd+\yrnd*\yrnd)>Rsmall-r)}
\edef\jtest{1}
\ifnum\itest=0
\edef\jtest{0}
\ifnum\Y>1
\edef\irun{0}
\loop
\pgfmathtruncatemacro{\jtest}{\jtest+(\ibucket=={\LstPrevPos}[\irun][0])&&%
(sqrt(pow({\LstPrevPos}[\irun][1]-\xrnd,2)+%
pow({\LstPrevPos}[\irun][2]-\yrnd,2))<2*r)}
\edef\irun{\the\numexpr\irun+1}
\ifnum\irun<\numexpr\Y-1
\repeat
\fi
\fi
\ifnum\numexpr\itest+\jtest=0\relax
\ifnum\Y=1
\xdef\LstPrevPos{{\ibucket,\xrnd,\yrnd}}
\else
\xdef\LstPrevPos{\LstPrevPos,{\ibucket,\xrnd,\yrnd}}
\fi
\path (\ibucket*d+\xrnd,\yrnd,r) coordinate (b-\Y);
\shade[tdplot_screen_coords,ball color={foo!![\Y]}] (b-\Y) circle[radius=r];
\breakforeach
\fi
}
}
\path[opacity=0.5] foreach \X in {1,...,\Xmax} {(\X*d,0,0) pic{bucket fore}};
\end{scope}
\end{tikzpicture}}
\end{document}
```
![ani.gif](/image?hash=66ef25580d2fbc3057f9ccffac5dbd98b9014d117342328bd83f39fa5b52e14c)