play3d calls a function repeatedly, passing it the elapsed time in seconds, and using the result of the function to reset the viewpoint. movie3d does the same, but records each frame to a file to make a movie.

play3d(f, duration = Inf, dev = cur3d(), ..., startTime = 0)
movie3d(f, duration, dev = cur3d(), ..., fps = 10, 
                    movie = "movie", frames = movie, dir = tempdir(), 
                    convert = NULL, clean = TRUE, verbose = TRUE,
                    top = !rgl.useNULL(), type = "gif", startTime = 0,
                    webshot = TRUE)

Arguments

f

A function returning a list that may be passed to par3d

duration

The duration of the animation

dev

Which RGL device to select

...

Additional parameters to pass to f.

startTime

Initial time at which to start the animation

fps

Number of frames per second

movie

The base of the output filename, not including .gif

frames

The base of the name for each frame

dir

A directory in which to create temporary files for each frame of the movie

convert

How to convert to a GIF movie; see Details

clean

If convert is NULL or TRUE, whether to delete the individual frames

verbose

Whether to report the convert command and the output filename

top

Whether to call rgl.bringtotop before each frame

type

What type of movie to create. See Details.

webshot

Whether to use the webshot2 package for snapshots of frames. See snapshot3d.

Details

The function f will be called in a loop with the first argument being the startTime plus the time in seconds since the start (where the start is measured after all arguments have been evaluated).

play3d is likely to place a high load on the CPU; if this is a problem, calls to Sys.sleep should be made within the function to release time to other processes.

play3d will run for the specified duration (in seconds), but can be interrupted by pressing ESC while the RGL window has the focus.

movie3d saves each frame to disk in a filename of the form framesXXX.png, where XXX is the frame number, starting from 0. If convert is NULL (the default) and the magick package is installed, it will be used to convert the frames to a GIF movie (or other format if supported). If magick is not installed or convert is TRUE, movie3d will attempt to use the external ImageMagick program to convert the frames to a movie. The newer magick executable is tried first, then convert if that fails. The type argument will be passed to ImageMagick to use as a file extension to choose the file type.

Finally, convert can be a template for a command to execute in the standard shell (wildcards are allowed). The template is converted to a command using
sprintf(convert, fps, frames, movie, type, duration, dir)
For example, convert = TRUE uses the template "magick -delay 1x%d %s*.png %s.%s". All work is done in the directory dir, so paths should not be needed in the command. (Note that sprintf does not require all arguments to be used, and supports formats that use them in an arbitrary order.)

The top = TRUE default is designed to work around an OpenGL limitation: in some implementations, rgl.snapshot will fail if the window is not topmost.

As of rgl version 0.94, the dev argument is not needed: the function f can specify its device, as spin3d does, for example. However, if dev is specified, it will be selected as the current device as each update is played.

As of rgl version 0.95.1476, f can include multiple values in a "subscene" component, and par3d() will be called for each of them.

Value

play3d is called for the side effect of its repeated calls to f. It returns NULL invisibly.

movie3d is also normally called for the side effect of producing the output movie. It invisibly returns

Author

Duncan Murdoch, based on code by Michael Friendly

See also

spin3d and par3dinterp return functions suitable to use as f. See demo(flag) for an example that modifies the scene in f.

Examples

open3d()
plot3d( cube3d(col = "green") )


M <- par3d("userMatrix")
if (!rgl.useNULL() && interactive())
  play3d( par3dinterp(times = (0:2)*0.5, userMatrix = list(M,
                                     rotate3d(M, pi/2, 1, 0, 0),
                                     rotate3d(M, pi/2, 0, 1, 0) ) ), 
        duration = 2 )
if (FALSE) {
movie3d( spin3d(), duration = 5 )
}