[Tex/LaTex] How to draw a 3D Christmas gift box, with TikZ

3dfuntikz-pgf

In the spirit of How can we draw a Christmas tree with decorations, using TikZ?

Can you draw a 3D Christmas gift box with as many details as possible(bow tie, elevated lid/bow, patterned wrapping paper)?

Bonus points (500 rep bounty) for animating the box as it opens.

MWE (Addition by HK)

\documentclass[varwidth,tikz]{standalone}
\begin{document}

\begin{tikzpicture}
\draw[fill=red] (0,0) rectangle (1,1);
\draw[fill=red] (1,0) -- ++(50:0.75cm) -- ++(90:1cm) -- (1,1) -- cycle;
\draw[fill=magenta] (0,1) -- ++(50:0.75cm) -- ++(0:1cm) -- (1,1) --  cycle;
\draw (0,0.8) -- (1,0.8) -- +(50:0.75cm);
\end{tikzpicture}
\end{document}

enter image description here

Best Answer

Just to get things going...

\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}


\tikzset{gift box/.cd,
  x/.store in=\gbx,
  y/.store in=\gby,
  z/.store in=\gbz,
  x=0,y=0,z=0
}
\tikzdeclarecoordinatesystem{gift box}{%
  \tikzset{x=(-20:1cm),y=(200:1cm),z=(90:1cm)}%
  \tikzset{gift box/.cd, #1}%
  \pgfpointxyz{\gbx*(.9+\gbz/20)}{\gby*(.9+\gbz/20)}{\gbz*(1+\gbx/10+\gby/10)}%
}

\tikzset{wrapping paper/.style={
    bottom color=red!75!black, top color=red!50!black,
  },
  ribbon/.style={
    bottom color=yellow!75!orange, top color=yellow!50!orange,
  },
  sheen/.style={
    left color=black, right color=white, opacity=0.25
  },
  highlight/.style={
    draw=white,
    opacity=1/100,
    line width=#1,
    line cap=round
  },
  lowlight/.style={
    draw=black,
    opacity=1/80,
    line width=#1,
    line cap=round,
    line join=round
  }
}



\begin{document}

\begin{tikzpicture}

\foreach \l in {1,...,20}
  \path [lowlight=\l/3] 
       (gift box cs:x=-1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1)
    -- cycle;



\path [wrapping paper]
     (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=1)
  -- (gift box cs:x= 1, y= 1, z=1)
  -- (gift box cs:x= 1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- (gift box cs:x= 1, y= 1, z=-1)
  -- cycle;


\foreach \n/\o in {.25/1, .33/.5}
  \path [ribbon, opacity=\o] 
       (gift box cs:x=1, y=-\n, z=-1)
    -- (gift box cs:x=1, y=-\n, z=1)
    -- (gift box cs:x=1, y= \n, z=1)
    -- (gift box cs:x=1, y= \n, z=-1)
    -- cycle
       (gift box cs:x=-\n, y=1, z=-1)
    -- (gift box cs:x=-\n, y=1, z=1)
    -- (gift box cs:x= \n, y=1, z=1)
    -- (gift box cs:x= \n, y=1, z=-1)
    -- cycle;

\path [sheen]
     (gift box cs:x=1,y=-1,z=-1)
  -- (gift box cs:x=1,y=-1,z=1)
  -- (gift box cs:x=1, y=1,z=1)
  -- (gift box cs:x=1, y=1,z=-1)
  -- cycle;

\path  [sheen]
     (gift box cs:x=-1,y=1,z=-1)
  -- (gift box cs:x=-1,y=1,z=1)
  -- (gift box cs:x=1, y=1,z=1)
  -- (gift box cs:x=1, y=1,z=-1)
  -- cycle;

\begin{scope}

\path [clip]
     (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z= 1)
  -- (gift box cs:x= 1, y= 1, z= 1)
  -- (gift box cs:x= 1, y=-1, z= 1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- (gift box cs:x= 1, y= 1, z=-1)
  -- cycle;

\foreach \l in {1,...,10}{
  \path [lowlight=\l/3] 
       (gift box cs:x=-1, y= 1, z=1) 
    -- (gift box cs:x=-1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=1)
       (gift box cs:x=1, y=1,z=-1) 
    -- (gift box cs:x=1, y=1,z= 1);

  \path [lowlight=\l/2]
       (gift box cs:x=-1.05, y= 1.05, z=1) 
    -- (gift box cs:x=-1.05, y= 1.05, z=.5)
    -- (gift box cs:x= 1.05, y= 1.05, z=.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=1);
}
\end{scope}


\path [wrapping paper]
     (gift box cs:x=-1.05, y=-1.05, z=1)
  -- (gift box cs:x=-1.05, y= 1.05, z=1)
  -- (gift box cs:x=-1.05, y= 1.05, z=.5)
  -- (gift box cs:x= 1.05, y= 1.05, z=.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=1)
  -- cycle;



\foreach \n/\o in {.33/.5, .25/1}{
  \path [ribbon, opacity=\o]
       (gift box cs:x= 1.05, y=-\n, z=0.5)
    -- (gift box cs:x= 1.05, y=-\n, z=1)
    -- (gift box cs:x=-1.05, y=-\n, z=1)
    -- (gift box cs:x=-1.05, y= \n, z=1)
    -- (gift box cs:x= 1.05, y= \n, z=1)
    -- (gift box cs:x= 1.05, y= \n, z=.5)
    -- cycle;

  \path [ribbon, opacity=\o]
       (gift box cs:y= 1.05, x=-\n, z=0.5)
    -- (gift box cs:y= 1.05, x=-\n, z=1)
    -- (gift box cs:y=-1.05, x=-\n, z=1)
    -- (gift box cs:y=-1.05, x= \n,  z=1)
    -- (gift box cs:y= 1.05, x= \n, z=1)
    -- (gift box cs:y= 1.05, x= \n, z=.5)
    -- cycle;
}


\path [sheen]
     (gift box cs:x=-1.05, y=1.05, z=1)
  -- (gift box cs:x=-1.05, y=1.05, z=0.5)
  -- (gift box cs:x= 1.05, y=1.05, z=0.5)
  -- (gift box cs:x= 1.05, y=1.05, z=1)
  -- cycle;

\path [sheen]
     (gift box cs:x=1.05, y=-1.05, z=1)
  -- (gift box cs:x=1.05, y=-1.05, z=0.5)
  -- (gift box cs:x=1.05, y= 1.05, z=0.5)
  -- (gift box cs:x=1.05, y= 1.05, z=1)
  -- cycle;

\path [sheen]
     (gift box cs:x=-1.05, y=-1.05, z=1)
  -- (gift box cs:x=-1.05, y= 1.05, z=1)
  -- (gift box cs:x= 1.05, y= 1.05, z=1)
  -- (gift box cs:x= 1.05, y=-1.05, z=1)
  -- cycle;

\begin{scope}
\path [clip]
     (gift box cs:x=-1.05, y=-1.05, z=1)
  -- (gift box cs:x=-1.05, y= 1.05, z=1)
  -- (gift box cs:x=-1.05, y= 1.05, z=.5)
  -- (gift box cs:x= 1.05, y= 1.05, z=.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=1)
  -- cycle;

\foreach \l in {1,...,10}{
  \path [highlight=\l/3] 
       (gift box cs:x= 1.05, y= 1.05, z=1) 
    -- (gift box cs:x= 1.05, y=-1.05, z=1) 
    -- (gift box cs:x=-1.05, y=-1.05, z=1) 
    -- (gift box cs:x=-1.05, y= 1.05, z=1)
    -- cycle 
       (gift box cs:x=1.05, y=1.05, z=1) 
    -- (gift box cs:x=1.05, y=1.05, z=0.5);

  \path [lowlight=\l/3]
       (gift box cs:x=-1.05, y= 1.05, z=1) 
    -- (gift box cs:x=-1.05, y= 1.05, z=.5)
    -- (gift box cs:x= 1.05, y= 1.05, z=.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=1);
}
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

And, with surprisingly little extra work:

enter image description here

Unfortunately, this gift box is empty. Sad faces all round.

(Unless it contains something small that cannot yet be seen).

The (rather pleasing) "texture" that the wrapping seems to have is a result of reducing the size and optimizing the color space of the gif for uploading.

The code (which takes some time to compile) is shown below. The resulting pdf is then processed with gimp to produce the image above:

\documentclass[tikz,border=0.125cm]{standalone}

\tikzset{gift box/.cd,
  x/.store in=\gbx,
  y/.store in=\gby,
  z/.store in=\gbz,
  rotate around z axis/.store in=\gbzaxisrotate,
  x=0,y=0,z=0,  
  rotate around z axis=0
}
\tikzdeclarecoordinatesystem{gift box}{%
  \tikzset{x=(-20:1cm),y=(200:1cm),z=(90:1cm)}%
  \tikzset{gift box/.cd, #1}%
  \pgfmathsin{\gbzaxisrotate}\let\gbsin=\pgfmathresult%
  \pgfmathcos{\gbzaxisrotate}\let\gbcos=\pgfmathresult%
  \pgfmathparse{cos(\gbzaxisrotate)*(\gbx)-sin(\gbzaxisrotate)*(\gby)}\let\gbxa=\pgfmathresult%
  \pgfmathparse{sin(\gbzaxisrotate)*(\gbx)+cos(\gbzaxisrotate)*(\gby)}\let\gbya=\pgfmathresult%
  \pgfpointxyz{\gbxa*(.9+(\gbz)/20)}{\gbya*(.9+(\gbz)/20)}{(\gbz)*(1+\gbxa/10+\gbya/10)}%
}

\tikzset{wrapping paper/.style={
    bottom color=red!75!black, top color=red!50!black,
  },
  ribbon/.style={
    bottom color=yellow!75!orange, top color=yellow!50!orange,
  },
  sheen/.style={
    left color=black, right color=white, opacity=0.25
  },
  sheen inside/.style={
    left color=black, right color=black!50, opacity=0.25
  },
  highlight/.style={
    draw=white,
    opacity=1/100,
    line width=#1,
    line cap=round
  },
  lowlight/.style={
    draw=black,
    opacity=1/80,
    line width=#1,
    line cap=round,
    line join=round
  }
}



\begin{document}


\foreach \i [evaluate={\zangle=-45+mod(\i,18)*5; \lidz=1.25+min(\i,18)*.1;}] in {0,...,35}{
\begin{tikzpicture}[gift box/rotate around z axis=\zangle]

\useasboundingbox [gift box/rotate around z axis=0] 
     (gift box cs:x= 1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=3)
  -- (gift box cs:x=-1, y=-1, z=3)
  -- (gift box cs:x= 1, y=-1, z=3)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- cycle;

\foreach \l in {1,...,20}
  \path [lowlight=\l/3] 
       (gift box cs:x=-1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1)
    -- cycle;

\path [wrapping paper]
     (gift box cs:x= 1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=1)
  -- (gift box cs:x=-1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- cycle;


\path [sheen inside]
     (gift box cs:x= 1, y=-1, z=-1)
  -- (gift box cs:x= 1, y=-1, z=1)
  -- (gift box cs:x=-1, y=-1, z=1)
  -- (gift box cs:x=-1, y=-1, z=-1)
  -- cycle;

\path  [sheen inside]
     (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=1)
  -- (gift box cs:x=-1, y=-1, z=1)
  -- (gift box cs:x=-1, y=-1, z=-1)
  -- cycle;

\begin{scope}

\path [clip]
     (gift box cs:x= 1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=1)
  -- (gift box cs:x=-1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- cycle;

\foreach \l in {1,...,20}
  \path [lowlight=\l/3] 
       (gift box cs:x=-1, y= 1, z=1) 
    -- (gift box cs:x=-1, y=-1, z=1) 
    -- (gift box cs:x= 1, y=-1, z=1);
\end{scope}

\path [wrapping paper]
     (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z=1)
  -- (gift box cs:x= 1, y= 1, z=1)
  -- (gift box cs:x= 1, y=-1, z=1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- (gift box cs:x= 1, y= 1, z=-1)
  -- cycle;


\foreach \n/\o in {.25/1, .33/.5}
  \path [ribbon, opacity=\o] 
       (gift box cs:x=1, y=-\n, z=-1)
    -- (gift box cs:x=1, y=-\n, z=1)
    -- (gift box cs:x=1, y= \n, z=1)
    -- (gift box cs:x=1, y= \n, z=-1)
    -- cycle
       (gift box cs:x=-\n, y=1, z=-1)
    -- (gift box cs:x=-\n, y=1, z=1)
    -- (gift box cs:x= \n, y=1, z=1)
    -- (gift box cs:x= \n, y=1, z=-1)
    -- cycle;

\path [sheen]
     (gift box cs:x=1, y=-1, z=-1)
  -- (gift box cs:x=1, y=-1, z=1)
  -- (gift box cs:x=1, y= 1, z=1)
  -- (gift box cs:x=1, y= 1, z=-1)
  -- cycle;

\path  [sheen]
     (gift box cs:x=-1,y=1,z=-1)
  -- (gift box cs:x=-1,y=1,z=1)
  -- (gift box cs:x=1, y=1,z=1)
  -- (gift box cs:x=1, y=1,z=-1)
  -- cycle;

\begin{scope}

\path [clip]
     (gift box cs:x=-1, y= 1, z=-1)
  -- (gift box cs:x=-1, y= 1, z= 1)
  -- (gift box cs:x= 1, y= 1, z= 1)
  -- (gift box cs:x= 1, y=-1, z= 1)
  -- (gift box cs:x= 1, y=-1, z=-1)
  -- (gift box cs:x= 1, y= 1, z=-1)
  -- cycle;

\foreach \l in {1,...,10}{
  \path [lowlight=\l/3] 
       (gift box cs:x=-1, y= 1, z=1) 
    -- (gift box cs:x=-1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y= 1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=-1) 
    -- (gift box cs:x= 1, y=-1, z=1)
       (gift box cs:x=1, y=1,z=-1) 
    -- (gift box cs:x=1, y=1,z= 1);

   \path [highlight=\l/3]
        (gift box cs:x=-1, y= 1, z=1) 
     -- (gift box cs:x= 1, y= 1, z=1)
     -- (gift box cs:x= 1, y=-1, z=1);

    \path [lowlight=\l/2]
        (gift box cs:x=-1.05, y= 1.05, z=\lidz-.5) 
     -- (gift box cs:x= 1.05, y= 1.05, z=\lidz-.5)
     -- (gift box cs:x= 1.05, y=-1.05, z=\lidz-.5);
}
\end{scope}

\path [wrapping paper]
     (gift box cs:x=-1.05, y=-1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y= 1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y= 1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y= 1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=\lidz)
  -- cycle;



\foreach \n/\o in {.33/.5, .25/1}{
  \path [ribbon, opacity=\o]
       (gift box cs:x= 1.05, y=-\n, z=\lidz-.5)
    -- (gift box cs:x= 1.05, y=-\n, z=\lidz)
    -- (gift box cs:x=-1.05, y=-\n, z=\lidz)
    -- (gift box cs:x=-1.05, y= \n, z=\lidz)
    -- (gift box cs:x= 1.05, y= \n, z=\lidz)
    -- (gift box cs:x= 1.05, y= \n, z=\lidz-.5)
    -- cycle;

  \path [ribbon, opacity=\o]
       (gift box cs:y= 1.05, x=-\n, z=\lidz-.5)
    -- (gift box cs:y= 1.05, x=-\n, z=\lidz)
    -- (gift box cs:y=-1.05, x=-\n, z=\lidz)
    -- (gift box cs:y=-1.05, x= \n,  z=\lidz)
    -- (gift box cs:y= 1.05, x= \n, z=\lidz)
    -- (gift box cs:y= 1.05, x= \n, z=\lidz-.5)
    -- cycle;
}


\path [sheen]
     (gift box cs:x=-1.05, y=1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y=1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=1.05, z=\lidz)
  -- cycle;

\path [sheen]
     (gift box cs:x=1.05, y=-1.05, z=\lidz)
  -- (gift box cs:x=1.05, y=-1.05, z=\lidz-.5)
  -- (gift box cs:x=1.05, y= 1.05, z=\lidz-.5)
  -- (gift box cs:x=1.05, y= 1.05, z=\lidz)
  -- cycle;

\path [sheen]
     (gift box cs:x=-1.05, y=-1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y= 1.05, z=\lidz)
  -- (gift box cs:x= 1.05, y= 1.05, z=\lidz)
  -- (gift box cs:x= 1.05, y=-1.05, z=\lidz)
  -- cycle;

\begin{scope}
\path [clip]
     (gift box cs:x=-1.05, y=-1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y= 1.05, z=\lidz)
  -- (gift box cs:x=-1.05, y= 1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y= 1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=\lidz-.5)
  -- (gift box cs:x= 1.05, y=-1.05, z=\lidz)
  -- cycle;

\foreach \l in {1,...,10}{
  \path [highlight=\l/3] 
       (gift box cs:x= 1.05, y= 1.05, z=\lidz) 
    -- (gift box cs:x= 1.05, y=-1.05, z=\lidz) 
    -- (gift box cs:x=-1.05, y=-1.05, z=\lidz) 
    -- (gift box cs:x=-1.05, y= 1.05, z=\lidz)
    -- cycle 
       (gift box cs:x=1.05, y=1.05, z=\lidz) 
    -- (gift box cs:x=1.05, y=1.05, z=\lidz-.5);

  \path [lowlight=\l/3]
       (gift box cs:x=-1.05, y= 1.05, z=\lidz) 
    -- (gift box cs:x=-1.05, y= 1.05, z=\lidz-.5)
    -- (gift box cs:x= 1.05, y= 1.05, z=\lidz-.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=\lidz-.5)
    -- (gift box cs:x= 1.05, y=-1.05, z=\lidz);
}
\end{scope}
\ifnum\i>17
\path [fill=white,opacity=(\i-17)/7]
     (gift box cs:x=-1.1, y=-1.1, z=\lidz)
  -- (gift box cs:x=-1.1, y= 1.1, z=\lidz)
  -- (gift box cs:x=-1.1, y= 1.1, z=\lidz-.5)
  -- (gift box cs:x= 1.1, y= 1.1, z=\lidz-.5)
  -- (gift box cs:x= 1.1, y=-1.1, z=\lidz-.5)
  -- (gift box cs:x= 1.1, y=-1.1, z=\lidz)
  -- cycle;
\fi
\end{tikzpicture}
}
\end{document}