What you're trying to do requires several ingredients.
First, you want to define your elf so that it can be combined with other objects in a Graphics3D
scene. This means you would just define the primitives making up the elf as follows:
elf = {Red, Cone[], White, Sphere[{0, 0, -1.5}, 1.03], Red,
Sphere[{0, 0, -3}, 1.09], Red, Sphere[{1, 0, -2.8}, 1/4],
Sphere[{1.4, 0, -2.85}, 1/4.5], Sphere[{1.7, 0, -2.95}, 1/4.9],
Sphere[{-1, 0, -2.8}, 1/4], Sphere[{-1.4, 0, -2.85}, 1/4.5],
Sphere[{-1.7, 0, -2.95}, 1/4.9], Yellow,
Sphere[{1.9, 0, -3.1}, 1/5.3], Sphere[{-1.9, 0, -3.1}, 1/5.3],
Black, Sphere[{-.5, -.80, -1.2}, 1/6],
Sphere[{.5, -.80, -1.2}, 1/6], Black,
Sphere[{-.3, -.84, -1.8}, 1/9], Sphere[{.3, -.84, -1.8}, 1/9],
Sphere[{.15, -.84, -1.9}, 1/9], Sphere[{-.15, -.84, -1.9}, 1/9],
Sphere[{0, -.84, -1.92}, 1/9], Green, Sphere[{0, 0, 0}, .457],
Green, Sphere[{0, 0, -.5}, .68], Green, Sphere[{0, 0, -1}, .901],
Sphere[{0, 0, 1}, 1/6], Green, Sphere[{0, 0, .5}, .235],
Sphere[{0, -1, -3}, 1/7], Green, Sphere[{0, -.87, -2.5}, 1/7],
Green, Sphere[{0, -.87, -3.5}, 1/7], White,
Sphere[{.9, 0, -1.5}, 1/4], Sphere[{-.9, 0, -1.5}, 1/4]};
Then you want a 2D image to be included in the Graphics3D
scene. This can be done with the following convenience function, which takes the image (or other object) as its first argument s
, and then places it with its upper left corner at 3D coordinate pos
. The orientation of the upper edge coming out of that corner is defined by the next argument xVec
. Also, the length of xVec
is equal to the length of the horizontal axis with which your image will be displayed, in units of the 3D scene. So by making xVec
longer, you scale up the whole image proportionally. The vertical edge of the image is tilted with respect to the vertical axis of the Graphics3D
scene by an angle tiltAngle
(it;s not needed here, so I set it to 0
):
pic3D[s_, pos_, xVec_, tiltAngle_] :=
Module[{width, height, r},
r = Rasterize[Style[HoldForm[s], Magnification -> 10], "Image"];
{width, height} = ImageDimensions[r];
Translate[(* //to make lefthand corner pos*)
Rotate[(* //around z axis*)
Rotate[(* //around y axis*)
Rotate[(* //tilt around x axis*)
Scale[(*//to make width equal|
xVec|*){EdgeForm[], Texture[ImageData@r],(* //
Texture fills polygon initially in the xz plane*)
Polygon[{{0, 0, 0}, {width, 0, 0}, {width, 0, height}, {0, 0,
height}},
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0,
1}}]}, Norm[xVec]/width, {0, 0, 0}],
tiltAngle, {1, 0, 0}],(* //x rotation*)
Arg[Chop@N[Norm[xVec[[1 ;; 2]] + I xVec[[3]]]]], {0, -1,
0}],(* //y rotation*)
Arg[Chop@N[xVec[[1]] + I xVec[[2]]]], {0, 0, 1}],(* //z rotation*)
pos]];
Now I'll combine the two objects defined above
pic = Import["http://i1.ytimg.com/vi/woHs5kFd3dI/maxresdefault.jpg"];
frames = Table[
Rasterize[
Graphics3D[{Rotate[elf, angle, {0, 0, 1}], Glow[White],
pic3D[pic, {-7, 5, -5}, {14, 0, 0}, 0]}, Boxed -> False ,
SphericalRegion -> True, ViewPoint -> {0, -10, -.5},
ViewAngle -> .05,
ImageSize -> {360, 200}],
"Image"],
{angle, 0, 2 Pi - Pi/10, Pi/10}];
Here I use Table
to generate the frames where the angle of rotation of the elf is varied. In order to make the background image appear with its own "natural" color, I added the Glow[White]
before inserting it with pic3D[pic,...]
at a position that looks OK.
Edit: To improve the rendering in the animation, I added some steps in the above Table
: First, reduce the ViewAngle
and add an ImageSize
option to Graphics3D
so that the displayed region better matches the aspect ratio of the scene. Second, wrap each Graphics3D
frame in Rasterize[..., "Image"]
because this dramatically speeds up the subsequent ListAnimate
. The animation then looks a little better that the GIF
I uploaded (but I'll just leave the old GIF
up for now).
Now make the animation. Unfortunately Mathematica is not very fast at rendering 3D graphics, so even the generation of the ListAnimate
display will take some time.
ListAnimate[frames]

To create the gif, I did this:
Export["elf.gif", frames, "DisplayDurations" -> .07,
AnimationRepetitions -> Infinity]
Clearly, the quality could be improved, but I just want to show some basic steps.
Dynamic
because that's overkill (in fact, the last command is incomplete becausefuns
is undefined). If you want a play button, you could useListAnimate[frames]
- whereframes
is the list of frames... $\endgroup$ListAnimate
works. $\endgroup$