3D animations with R

Every now and then I need to make a rotating animation of a 3D plot. The R package rgl turns out to have everything you need, but the grip is a little difficult. Below is an example that will walk you through the steps to make this animation.

First things first, you must make sure that rgl is installed. On Unbuntu, you may also have to install additional libraries. And by the end, you will need to use imagemagick, so at the shell command line you can issue

sudo apt-get install libglu1-mesa-dev
sudo apt-get install imagemagick

You can now start R. Since the package is on the CRAN, you can install it as usual.

install.packages("rgl")

For the purposes of this example, we create a random 3D cloud that consist of two Gaussian spheres next to each other.

# Distribute 1000 points at random among two spheres.
x <- matrix(rnorm(3000, mean=rep(c(0,2), each=1500)),
ncol=3, byrow=TRUE)
cols <- rep(c("dodgerblue4", "dodgerblue2"), each=500)

Now we plot the cloud in 3D and save the frames to different .png files. After the call to plot3d you can resize the window. This will be the size of the picture will be the one that appears on your screen. You can also rotate the cloud with the mouse, this is useless but still very cool.

library(rgl)
plot3d(x, col=cols, box=NA)
# This is ugly. NA makes the drawing of the box fail.
# We do not want the box to mess up the animation.
# A that point you can play with the window, rotate
# the cloud with the mouse etc.
dir.create("animation")
for (i in 1:90) {
view3d(userMatrix=rotationMatrix(2*pi * i/90, 1, -1, -1))
rgl.snapshot(filename=paste("animation/frame-",
sprintf("%03d", i), ".png", sep=""))
}

The trick to create the frames is to use rotationMatrix. The last 3 parameters are the coordinates of a 3D vector, and the first parameter is an angle (in radians) describing a rotation around this axis. This parametrization is much simpler than the alternatives. The example above creates 90 frames. Adjust this number to more or less, depending on your needs.

The frames are there, in the animation directory. You can quit R and get ready to assemble the frames in a .gif file. At the shell command line, you then need to use convert from imagemagick to create the animated gif.

cd animation
convert -delay 5 -loop 0 frame*.png animated.gif

The option -delay 5 indicates the time between the frames and -loop 0 indicates to create a looping animation.

A technical note

When I used the default graphics driver of my Ubuntu system, rgl.snapshot created an empty black picture. I had to save the 3D view as a postscript file and later convert it to png. If this happens, you need to replace the line that contains rgl.snapshot in the for loop above by rgl.postscript and replace .png by .eps. You can then convert the files to png with convert as follows:

convert -flatten frame*eps frame*.png

« | »





comments powered by Disqus