The rgl
package is used to produce interactive 3-D
plots. It contains high-level graphics commands modelled loosely after
classic R graphics, but working in three dimensions. It also contains
low level structure inspired by (but incompatible with) the
grid
package.
This document gives an overview. See the help pages for details.
For installation instructions, see the README
file in
the top level directory of the source tarball rgl_1.3.14.tar.gz (or a
later version).
This document was written in R Markdown, using the knitr
package for production. It corresponds to rgl
version
1.3.14.
Most of the highlighted function names are HTML links. The internal links should work in any browser; the links to help topics should work if you view the vignette from within the R help system.
The document includes WebGL figures. To view these, you must have Javascript and WebGL enabled in your browser. Some older browsers may not support this – see https://get.webgl.org for tests and links to a discussion.
The
plot3d
function plots points within an RGL window. It is similar to the classic
plot
function, but works in 3 dimensions.
For example
with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length,
type="s", col=as.numeric(Species)))
plot3d() example.
can be used to plot three columns of the iris
data.
Allowed plot types include "p", "l", "h", "s"
, meaning
points, lines, segments from z=0, and spheres. There’s a lot of
flexibility in specifying the coordinates; the
xyz.coords
function from the grDevices
package is used for this.
You can use your mouse to manipulate the plot. The default is that if you click and hold with the left mouse button, you can rotate the plot by dragging it. The right mouse button is used to resize it, and the middle button changes the perspective in the point of view.
If you call plot3d
again, it will
overwrite the current plot. To open a new graphics window, use
open3d
.
The other high level function is
persp3d
to draw surfaces. It is similar to the classic
persp
function, but with greater flexibility. First, any of x
,
y
or z
can be specified using matrices, not
just z
. This allows parametric surfaces to be plotted. An
even simpler specification is possible: x
may be a
function, in which case persp3d
will work out the grid
itself. See
?persp3d.function
for details. For example, the MASS
package estimates Gamma
parameters using maximum likelihood in a
?MASS::fitdistr
example. Here we show the log likelihood surface.
# This example requires the MASS package
library(MASS)
# from the fitdistr example
set.seed(123)
x <- rgamma(100, shape = 5, rate = 0.1)
fit <- fitdistr(x, dgamma, list(shape = 1, rate = 0.1), lower = 0.001)
loglik <- function(shape, rate) sum(dgamma(x, shape=shape, rate=rate,
log=TRUE))
loglik <- Vectorize(loglik)
xlim <- fit$estimate[1]+4*fit$sd[1]*c(-1,1)
ylim <- fit$estimate[2]+4*fit$sd[2]*c(-1,1)
mfrow3d(1, 2, sharedMouse = TRUE)
persp3d(loglik,
xlim = xlim, ylim = ylim,
n = 30)
zlim <- fit$loglik + c(-qchisq(0.99, 2)/2, 0)
next3d()
persp3d(loglik,
xlim = xlim, ylim = ylim, zlim = zlim,
n = 30)
persp3d() example.
On the left, the whole surface over a range of the parameters; on the right, only the parts of the surface with log likelihood values near the maximum.
Note: this example used the knitr
hook functions (see
setupKnitr
) to insert the scene
into this vignette; the previous example used the rglwidget
function. We generally recommend the newer
rglwidget
approach.
Note that both plot3d
and persp3d
are
generic functions, with the following methods defined:
methods(plot3d)
## [1] plot3d.ashape3d* plot3d.default* plot3d.deldir*
## [4] plot3d.formula* plot3d.function* plot3d.lm*
## [7] plot3d.mesh3d* plot3d.rglbackground* plot3d.rglbboxdeco*
## [10] plot3d.rglobject* plot3d.rglscene* plot3d.rglsubscene*
## [13] plot3d.rglWebGL* plot3d.tri* plot3d.triSht*
## see '?methods' for accessing help and source code
methods(persp3d)
## [1] persp3d.ashape3d* persp3d.default* persp3d.deldir* persp3d.formula*
## [5] persp3d.function* persp3d.tri* persp3d.triSht*
## see '?methods' for accessing help and source code
Just as we have
points
and
lines
in classic graphics, there are a number of low level functions in
rgl
to add graphical elements to the currently active plot.
The “primitive” shapes are those that are native to OpenGL:
Function | Description |
---|---|
points3d : |
adds points |
lines3d : |
adds lines |
segments3d : |
adds line segments |
triangles3d : |
adds triangles |
quads3d : |
adds quadrilaterals |
Each of the above functions takes arguments x
,
y
and z
, again using
xyz.coords
for flexibility. They group successive entries as necessary. For
example, the triangles3d
function takes each successive triple of points as the vertices of a
triangle.
You can use these functions to annotate the current graph, or to construct a figure from scratch.
rgl
also has a number of objects which it constructs
from the primitives.
Function | Description |
---|---|
text3d ,
texts3d : |
adds text |
abclines3d : |
adds straight lines to plot (like abline ) |
arc3d : |
adds spherical arcs or spirals to plot |
planes3d : |
adds planes to plot |
clipplanes3d : |
add clipping planes to plot |
sprites3d ,
particles3d : |
add sprites (fixed shapes or images) to plot |
spheres3d : |
adds spheres |
surface3d ,
terrain3d : |
a surface (as used in
persp3d ) |
drape3d : |
drapes lines on a surface or object(s) |
shadow3d : |
projects mesh onto a surface |
arrow3d : |
add an arrow to a scene |
pch3d : |
draw base-style plotting symbols |
plotmath3d : |
used by text3d for math text |
The following low-level functions control the look of the graph:
Function | Description |
---|---|
axes3d ,
axis3d : |
add axes to plot |
box3d ,
bbox3d : |
add box around plot |
title3d : |
add title to plot |
mtext3d : |
add marginal text to plot |
decorate3d : |
add multiple “decorations” (scales, etc.) to plot |
aspect3d : |
set the aspect ratios for the plot |
bg3d ,
bgplot3d : |
set the background of the scene |
show2d : |
show a 2D plot or image in a 3D scene |
legend3d : |
set a legend for the scene |
grid3d : |
add a reference grid to a graph |
thigmophobe3d : |
choose label positions to avoid overlap |
setAxisCallbacks : |
set user-defined axis annotations |
For example, to plot three random triangles, one could use
triangles3d(cbind(x=rnorm(9), y=rnorm(9), z=rnorm(9)), col = "green")
decorate3d()
bg3d("lightgray")
triangles3d() example.
aspect3d(1,1,1)
Besides the *3d
functions mentioned above, there are
deprecated functions rgl.abclines
, rgl.bbox
,
rgl.bg
, rgl.clipplanes
,
rgl.lines
, rgl.linestrips
,
rgl.planes
, rgl.points
,
rgl.primitive
, rgl.quads
,
rgl.setAxisCallback
, rgl.spheres
,
rgl.sprites
, rgl.surface
,
rgl.texts
, rgl.triangles
. You should avoid
using all of these functions, which do not work properly with the
*3d
functions and will soon be removed from
rgl
. See the
?r3d
help topic for details.
The function
rgl.getAxisCallback
provides low-level support for
setAxisCallbacks
.
By default when you open a new plot with
open3d
:
You can change the camera angle simply by dragging the picture with the mouse.
To set the camera angle programmatically, use
view3d
.
This uses polar coordinates:
theta
sets the rotation around the vertical axis, in
degrees.phi
sets the “vertical” rotation around the horizontal
axis, from -90 to 90 degrees.The default angle is roughly theta = 0, phi = -70
.
Starting from this position:
theta
, the graph will spin
anticlockwise from your point of view.phi
to 0, you start to look down at the
scene from the top. If you increase phi
above 0, you
continue over and start to see the graph from the “back” (and upside
down).You can also use
observer3d
to change the camera location using x,y,z
coordinates. In
particular, increasing the z
coordinate lets you zoom out,
and decreasing it zooms you in.
One useful approach is to use the mouse to find a nice viewing angle.
You can then save it using par3d("userMatrix")
and restore
the same view later:
In most scenes, objects are “lit”, meaning that their appearance depends on their position and orientation relative to lights in the scene. The lights themselves don’t normally show up, but their effect on the objects does.
Use the
light3d
function to specify the position and characteristics of a light. Lights
may be infinitely distant, or may be embedded within the scene. Their
characteristics include ambient
, diffuse
, and
specular
components, all defaulting to white. The
ambient
component appears the same from any direction. The
diffuse
component depends on the angle between the surface
and the light, while the specular
component also takes the
viewer’s position into account.
The deprecated rgl.light
function should no longer be
used; use light3d
instead.
The mental model used in rgl
is that the objects being
shown in scenes are physical objects in space, with material properties
that affect how light reflects from them (or is emitted by them). These
are mainly controlled by the
material3d
function, or by arguments to other functions that are passed to it.
The material properties that are recognized in calls to
material3d
are described in detail in the
?material3d
help page, and listed in the
rgl.material.names
variable. All of them can be set except the ones in
rgl.material.readonly
.
Here we give an overview.
Property | Default | Meaning |
---|---|---|
color | white | vector of surface colors to apply to successive vertices for diffuse light |
alpha | 1 | transparency: 0 is invisible, 1 is opaque |
lit | TRUE | whether lighting calculations should be done |
ambient | black | color in ambient light |
specular | white | color in specular light |
emission | black | color emitted by the surface |
shininess | 50 | controls the specular lighting: high values look shiny |
smooth | TRUE | whether shading should be interpolated between vertices |
texture | NULL | optional path to a “texture” bitmap to be displayed on the surface |
front, back | fill | should polygons be filled, or outlined? |
size | 3 | size of points in pixels |
lwd | 1 | width of lines in pixels |
Other properties include “texmipmap”, “texmagfilter”, “texminfilter”, “texenvmap”, “fog”, “point_antialias”, “line_antialias”, “depth_mask”, “depth_test”, “polygon_offset”, “margin”, “floating”, “tag” and “blend”; see the help page for details.
There is also a deprecated rgl.material
function that
works at a lower level; users should avoid it.
As described in the previous section, one of the material properties
is texture
, the name of a bitmap file (in .png
format) containing an image to be displayed on the surface. This section
gives more details about textures.
In OpenGL
, each vertex in a polygon may be associated
with a particular location in the bitmap. The interior of the polygon
interpolates within the bitmap. There are two conventions in
rgl
functions for specifying these coordinates.
Functions which specify primitives
(triangles3d
, etc.) accept an
optional matrix argument texcoords
which gives
s
(horizontal) and t
(vertical) locations
within the bitmap in columns with one row per vertex. The coordinates
are (0,0)
for the lower left, and (1,1)
for
the upper right. If values outside this range are given, the image
repeats, i.e. (1.1, 1.2)
would specify the same point in
the image as (0.1, 0.2)
.
Other functions such as
surface3d
that take matrices for
each vertex coordinate accept texture coordinates as matrices as well,
in arguments texture_s
and texture_t
.
For example, the following code displays four copies of a 2D plot on
a quad, because the texture coordinates run from 0 to 2 in both
s
and t
:
filename <- tempfile(fileext = ".png")
png(filename = filename)
plot(rnorm(1000), rnorm(1000))
safe.dev.off()
## agg_png
## 2
open3d()
## null
## 11
xyz <- cbind(c(0,1,1,0), 0, c(0,0,1,1))
quads3d(xyz, texture = filename, texcoords = xyz[,c(1, 3)]*2,
col = "white", specular = "black")
Texture example.
Some other notes:
quads3d()
above was specified to be white.
By default, the colors in the bitmap will modify the color of the
surface. If col
is black (a common default), you won’t see
anything, so a warning may be issued.specular
to black prevents those."texmode"
allows texture colors
to be used differently. The default is "modulate"
, where
the texture values combine multiplicatively with the underlying
values."textype"
. The default is
"rgb"
, which takes the red-green-blue colors from the
bitmap and uses them to modify the corresponding colors in the
polygon."textype"
and
"texmode"
are described in
the
material3d help page."tex*"
material properties control how the
interpolation within the image is done.OpenGL
supports 1- and 3-dimensional textures;
these are not currently supported in rgl
.rgl
uses the same ideas as base graphics for drawing
text: there are font families named "sans"
,
"serif"
, and "mono"
for drawing text of those
types. In rgl
, the "symbol"
family is not
supported.
New font families can be defined using the low-level function
rglFonts
,
or more simply using the higher level function
rglExtrafonts
.
The latter function requires the extrafont
package to be
installed.
The
par3d
function, modelled after the classic graphics
par
function, sets or reads a variety of different rgl
internal
parameters, listed in the
rgl.par3d.names
variable. All of them can be set except the ones in
rgl.par3d.readonly
.
Some parameters are completely read-only; others are fixed at the time
the window is opened, and others may be changed at any time.
Name | Changeable? | Description |
---|---|---|
antialias | fixed | Amount of hardware antialiasing |
cex | Default size for text | |
family | Device-independent font family name; see ?text3d | |
font | Integer font number | |
useFreeType | Should FreeType fonts be used if available? | |
fontname | read-only | System-dependent font name set by
rglFonts
|
FOV | Field of view, in degrees. Zero means isometric perspective | |
ignoreExtent | Should rgl ignore the size of new objects when
computing the bounding box? |
|
skipRedraw | Should rgl suppress updates to the display? |
|
maxClipPlanes | read-only | How many clip planes can be defined? |
modelMatrix | read-only | The OpenGL ModelView matrix; partly set by
view3d
|
projMatrix | read-only | The OpenGL Projection matrix |
bbox | read-only | Current bounding-box of the scene |
viewport | Dimensions in pixels of the scene within the window | |
windowRect | Dimensions in pixels of the window on the whole screen | |
listeners | Which subscenes respond to mouse actions in the current one | |
mouseMode | What the mouse buttons do. See
“mouseMode”
|
|
observer | read-only | The position of the observer; set by
observer3d
|
scale | Rescaling for each coordinate; see
aspect3d
|
|
zoom | Magnification of the scene |
The deprecated rgl.viewpoint
function should not be
used.
The
r3dDefaults
list and the
getr3dDefaults
function control defaults in new windows opened by
open3d
.
The function looks for the variable in the user’s global environment,
and if not found there, finds the one in the rgl
namespace.
This allows the user to override the default settings for new
windows.
Once found, the r3dDefaults
list provides initial values
for par3d
parameters, as well as
defaults for material3d
and
bg3d
in components
"material"
and "bg"
respectively.
rgl
includes a number of functions to construct and
display various solid shapes. These generate objects of class
"shape3d"
, "mesh3d"
or
"shapelist3d"
. The details of the classes are described
below. We start with functions to generate them.
These functions generate specific shapes. Optional arguments allow attributes such as color or transformations to be specified.
Function | Description |
---|---|
tetrahedron3d ,
cube3d ,
octahedron3d ,
dodecahedron3d ,
icosahedron3d : |
Platonic solids |
cuboctahedron3d ,
oh3d : |
other solids |
cols <- rainbow(7)
layout3d(matrix(1:16, 4,4), heights=c(1,3,1,3))
text3d(0,0,0,"tetrahedron3d"); next3d()
shade3d(tetrahedron3d(col=cols[1])); next3d()
text3d(0,0,0,"cube3d"); next3d()
shade3d(cube3d(col=cols[2])); next3d()
text3d(0,0,0,"octahedron3d"); next3d()
shade3d(octahedron3d(col=cols[3])); next3d()
text3d(0,0,0,"dodecahedron3d"); next3d()
shade3d(dodecahedron3d(col=cols[4])); next3d()
text3d(0,0,0,"icosahedron3d"); next3d()
shade3d(icosahedron3d(col=cols[5])); next3d()
text3d(0,0,0,"cuboctahedron3d"); next3d()
shade3d(cuboctahedron3d(col=cols[6])); next3d()
text3d(0,0,0,"oh3d"); next3d()
shade3d(oh3d(col=cols[7]))
Solids example.
A very large collection of polyhedra is contained in the Rpolyhedra package.
These functions generate new shapes:
Function | Description |
---|---|
cylinder3d : |
generate a tube or cylinder |
polygon3d : |
generate a flat polygon by triangulation |
extrude3d : |
generate an “extrusion” of a polygon |
turn3d : |
generate a solid of rotation |
ellipse3d : |
generate an ellipsoid in various ways |
mesh3d : |
generate a shape from indexed vertices |
shapelist3d : |
generate a shape by combining other shapes |
as.mesh3d : |
a generic function; see below |
A related function is
triangulate
,
which takes a two dimensional polygon and divides it up into triangles
using the “ear-clipping” algorithm.
The generic function
as.mesh3d
is provided to allow data structures produced by other code to be
converted to mesh structures. Currently the following classes are
supported:
Class | Package | Description |
---|---|---|
deldir
|
deldir |
Delaunay triangulations of irregular point clouds |
triSht
|
interp |
Also Delaunay triangulations |
tri
|
tripack |
Generalized Delaunay triangulations |
ashape3d
|
alphashape3d |
Alpha-shapes |
rglId |
rgl |
rgl object identifiers |
The
checkDeldir
function checks that a compatible version of the deldir
package is installed.
The default
as.mesh3d.default
method is a simple way to construct a mesh from a matrix of vertices; it
can use
mergeVertices
(which can also be used on its own) to merge repeated vertices within
the matrix, allowing addNormals
to be used to give a smooth appearance.
The
as.tmesh3d
generic is a variation that guarantees the resulting object will have no
quad entries.
Functions
tmesh3d
,
qmesh3d
are now obsolete; use mesh3d
instead.
"shape3d"
is the basic abstract type. Objects of this
class can be displayed by
shade3d
(which shades faces),
wire3d
(which draws edges), or
dot3d
(which draws points at each vertex.)
"mesh3d"
is a descendant type. Objects of this type
contain the following fields:
Field | Meaning |
---|---|
vb | A 4 by n matrix of vertices in homogeneous coordinates. Each column is a point. |
ip | (optional) A vector of vertex indices for points. |
is | (optional) A 2 by s matrix of vertex indices. Each column is a line segment. |
it | (optional) A 3 by t matrix of vertex indices. Each column is a triangle. |
ib | (optional) A 4 by q matrix of vertex indices. Each column is a quadrilateral. |
material | (optional) A list of material properties. |
normals | (optional) A matrix of the same shape as vb, containing normal vectors at each vertex. |
texcoords | (optional) A 2 by n matrix of texture coordinates corresponding to each vertex. |
values | (optional) A vector of length n holding values at each vertex |
meshColor | (optional) A text value indicating how colors and texture coordinates should be interpreted. |
tags | (optional) A vector added by some functions
(e.g. clipMesh3d ) to relate
output parts to input parts. |
These functions compute and plot contours of functions on surfaces, or clip objects along a contour of a function.
Function | Description |
---|---|
contourLines3d : |
draw contour lines on surface |
filledContour3d : |
fill between contours on surface |
clipMesh3d : |
clip mesh object using curved boundary |
clipObj3d : |
clip general object using curved boundary |
These functions manipulate and modify mesh objects:
Function | Description |
---|---|
addNormals : |
add normal vectors to make a shape look smooth |
subdivision3d : |
add extra vertices to make it look even smoother |
merge : |
merge mesh objects |
facing3d : |
subset of mesh facing “up” |
getBoundary3d : |
get the boundary of a mesh object |
The individual steps in
subdivision3d
are also
available:
deform.mesh3d
,
divide.mesh3d
,
normalize.mesh3d
.
These are mainly intended for internal use.
rgl
has several functions to support displaying multiple
different “subscenes” in the same window. The high level functions
are
Function | Description |
---|---|
mfrow3d : |
Multiple figures (like par(“mfrow”) |
layout3d : |
Multiple figures (like
layout ) |
next3d : |
Move to the next figure (like
plot.new
or
frame ) |
subsceneList : |
List all the subscenes in the current layout |
clearSubsceneList : |
Clear the current list and revert to the previous one |
There are also lower level functions.
Function | Description |
---|---|
newSubscene3d : |
Create a new subscene, with fine control over what is inherited from the parent |
currentSubscene3d : |
Report on the active subscene |
subsceneInfo : |
Get information on current subscene |
useSubscene3d : |
Make a different subscene active |
addToSubscene3d ,
delFromSubscene3d : |
Add objects to a subscene, or delete them |
gc3d : |
Do “garbage collection”: delete objects that are not displayed in any subscene |
rgl
Scenes
The rgl
package can produce output that can be embedded
in other documents. The recommended way to do this has changed several
times over the years. We will start with the current recommendation,
then list older methods.
Currently the best way to embed an rgl
scene in a
document is to produce the document in HTML using R Markdown. Early in
the document, you should have code like this in one of the setup code
chunks:
The call to setupKnitr()
will install a number of hooks
and set options in knitr
so that rgl
code is
handled properly. The autoprint = TRUE
argument makes
rgl
act in the document almost the same way it would act in
the console, or the way base graphics are handled by knitr
:
If you print the value of high level rgl
functions, a plot
will be inserted into the output, but maybe only after low level
modifications to it are complete. For example, this code block prints
both triangles and spheres in a single plot at the end:
xyz <- matrix(rnorm(27), ncol = 3)
triangles3d(xyz, col = rainbow(9))
spheres3d(xyz, col = rainbow(9), radius = 0.1)
Autoprint example.
There are a few differences if you have a complicated situation:
rgl
function
calls being automatically printed. If the calls are in a loop or other
code block where automatic printing doesn’t happen, you’ll need some
trickery to get things to print. For example, this will print three
plots:
plots <- NULL
for (i in 1:3) {
plot3d(rnorm(10), rnorm(10), rnorm(10))
plots <- htmltools::tagList(plots, rglwidget())
close3d()
}
plots
rgl
functions return
results using lowlevel()
or highlevel()
to
mark which kind of plot they are. If you are using a function from
another package to produce the plot, you may need to insert an explicit
call to one of those to get it to print. Use lowlevel()
if
the function just modifies an existing plot, highlevel()
if
it starts a new one. For example,
foreignHigh() # Produces a high level plot, but doesn't return
# an appropriate value
highlevel()
foreignLow() # Modifies the previous plot
lowlevel()
This should display the output at the end of the code chunk, when modifications are assumed complete.
While some PDF previewers support interactive 3D graphics, most
don’t. To produce a screenshot of an rgl
scene in an R
Markdown document with PDF output, simply follow the directions given
above. The auto-printing will detect PDF output and use
snapshot3d
to produce a PNG file to insert. (See below if
you want to insert a different format of graphic.)
If you really need interactive output, see the
writeASY
function.
You may not want to use the setupKnitr(autoprint = TRUE)
method described above. It is very new, and may still have bugs; you may
have an older document and not want to edit it to work that way.
In this case, you can insert plots manually. Use setup code
and call rglwidget()
at top level whenever you want to
insert a plot.
There are a couple of other differences in default behaviour if you
are not using autoprint
:
By default, each code chunk continues the rgl
scene
from earlier chunks. You’ll need an explicit
open3d
call to get a clean
window.
Also by default, the rgl
window is not closed at the
end of the chunk. This probably doesn’t matter, but you may find you run
out of memory if your scenes are really big.
The original way to insert an rgl
scene in a document
was to use the deprecated writeWebGL
function to write HTML
code to insert in a document. Later, Sweave
and
knitr
hooks were added. These are no longer supported, and
you should update old documents to use the newer methods. If you are
reading documents that suggest using those methods, let the author know
they need updating!
By default, rgl
detects and handles mouse clicks within
your scene, and uses these to control its appearance. You can find out
the current handlers using the following code:
par3d("mouseMode")
## none left right middle wheel
## "none" "trackball" "zoom" "fov" "pull"
The labels c("left", "right", "middle")
refer to the
buttons on a three button mouse, or simulations of them on other mice.
"wheel"
refers to the mouse wheel, and "none"
refers to actions that take place when the mouse is moved without
pressing any button.
The button actions generally correspond to click and drag operations.
Possible values for
“mouseMode”
for the mouse pointer or wheel are as follows:
Mode | Description |
---|---|
"none" |
No action |
"trackball" |
The mouse acts as a virtual trackball. Clicking and dragging rotates the scene |
"xAxis" , "yAxis" ,
"zAxis"
|
Like "trackball" , but restricted to rotation about one
axis |
"polar" |
The mouse affects rotations by controlling polar coordinates directly |
"selecting" |
The mouse is being used by the
select3d function |
"zoom" |
The mouse zooms the display |
"fov" |
The mouse affects perspective by changing the field of view |
"pull" |
Rotating the mouse wheel towards the user “pulls the scene closer” |
"push" |
The same rotation “pushes the scene away” |
"user" |
A user action set by
setUserCallbacks ,
rgl.setMouseCallbacks ,
rgl.setWheelCallback .
Use
rgl.getMouseCallbacks
and
rgl.getWheelCallback
to retrieve. |
The following functions make use of the mouse for selection within a scene.
Function | Description |
---|---|
identify3d : |
like the classic graphics
identify
function |
select3d : |
returns a function that tests whether a coordinate was selected |
selectpoints3d : |
selects from specific objects |
hover3d : |
displays “hover” info about points |
selectionFunction3d
produces the selection function from information about the projection
and mouse selection region; it is used internally in the functions
above.
The deprecated rgl.select3d
function is an obsolete
version of select3d
, and
rgl.select
is a low-level support function.
rgl
has several functions that can be used to construct
animations. These are based on functions that update the scene according
to the current real-world time, and repeated calls to those. The
functions are:
Function | Description |
---|---|
play3d : |
Repeatedly call the update function |
spin3d : |
Update the display by rotating at a constant rate |
par3dinterp : |
Compute new values of some par3d
parameters by interpolation over time |
See the movie3d
function for a
way to output an animation to a file on disk.
Animations are not currently supported in the HTML written by
rglwidget
, though the
playwidget
function provides equivalent functionality.
There are three functions in rgl
that support control of
an rgl
scene using the TCL/TK framework.
Function | Description |
---|---|
tkspin3d : |
Set up buttons in a window to control a scene |
tkspinControl : |
Embed the control buttons in a separate TCL/TK frame |
tkpar3dsave : |
Create a dialog to interactively save mouse actions |
These functions were formerly contained (without the tk
prefixes on their names) in the tkrgl
package. That package
is now deprecated.
rgl
contains several functions to write scenes to disk
for use by other software, or to read them in.
In order from highest fidelity to lowest, the functions are:
Function | Description |
---|---|
scene3d : |
Save a scene to an R variable, which can be saved and reloaded |
rglwidget : |
Prints as HTML and Javascript to display a scene in a web browser. (See also User Interaction in WebGL.) |
writeASY : |
Write files for Asymptote |
writePLY : |
Write PLY files (commonly used in 3D printing) |
readOBJ ,
writeOBJ : |
Read or write OBJ files (commonly used in 3D graphics) |
readSTL ,
writeSTL : |
Read or write STL files (also common in 3D printing) |
as.rglscene : |
Generic function, no methods in rgl
|
The rgl2gltf
package can read or write GLTF and GLB files. It includes an
as.rglscene
method to convert GLTF objects to
rgl
scenes. The code in rgl
’s
Buffer
R6 class is based on the GLTF format. It is used by
rglwidget
to make output webpages
somewhat smaller than they were previously.
There are also functions to save snapshots or other recordings of a scene, without any 3D information being saved:
Function | Description |
---|---|
snapshot3d : |
Save a PNG file bitmap of the scene |
rgl.postscript : |
Save a Postscript, LaTeX, PDF, SVG or PGF vector rendering of the scene |
movie3d : |
Save a series of bitmaps to be assembled into a movie |
rgl.pixels : |
Obtain pixel-level information about the scene in an R variable |
rgl.Sweave : |
Driver function for inserting a snapshot into a Sweave document. |
hook_rgl ,
hook_webgl : |
knitr hook functions for inserting images into a
document. |
setupKnitr : |
Function to set up knitr hooks |
The
rgl.snapshot
function is a low level version of snapshot3d()
; it
requires that the rgl
display be onscreen and copies from
there. snapshot3d()
tries to use the webshot2
package so it will work even with no display. The functions
rgl.Sweave.off
,
Sweave.snapshot
are involved in Sweave processing and not normally called by users.
There are two ways in which rgl
scenes are normally
displayed within R. The older one is in a dedicated window. In
Unix-alikes this is an X11 window; it is a native window in Microsoft
Windows. On macOS, the XQuartz system (see https://www.xquartz.org)
needs to be installed to support this.
To suppress this display, set
options(rgl.useNULL = TRUE)
before opening a new
rgl
window. See the help page for the
rgl.useNULL
function for how to set this before starting R.
The newer way to display a scene is by using WebGL in a browser
window or in the Viewer pane in RStudio. To select this, set
options(rgl.printRglwidget = TRUE)
. Each operation that
would change the scene will return a value which triggers a new WebGL
display when printed.
You should use the following scheme for exporting a scene to a web page. There’s also an older scheme, which is no longer supported.
The recommended approach works with the htmlwidgets
framework (see http://www.htmlwidgets.org/). In an R Markdown document
in knitr
, use the
rglwidget
function. (You can also
use chunk option webgl=TRUE
; we recommend the explicit use
of rglwidget
.) This approach also allows display of
rgl
scenes in RStudio.
Besides rgl
scenes, various controls for them can be
displayed, and there are a few utility functions that can be useful:
Function | Description |
---|---|
propertyControl : |
set individual properties |
clipplaneControl : |
control a clipping plane |
subsetControl : |
control which objects are displayed |
ageControl : |
“age” vertices of an object |
vertexControl : |
control properties of vertices |
par3dinterpControl : |
WebGL control like
par3dinterp
|
playwidget : |
display and automate controls |
toggleWidget : |
display a button to toggle some items |
%>%: |
magrittr pipe |
figHeight ,
figWidth : |
Dimensions of figures in R Markdown document |
rglShared : |
share data using crosstalk package |
rglMouse : |
change mouse mode in RGL scene |
asRow : |
arrange multiple objects in an HTML display |
getWidgetId : |
get the elementId from a widget |
These functions work with the above scheme in Shiny apps:
Function | Description |
---|---|
sceneChange : |
used in Shiny for large scene changes |
shinyGetPar3d ,
shinySetPar3d : |
get or set par3d values from
Shiny |
shinyResetBrush : |
reset the mouse brush in Shiny |
The
selectionFunction3d
function is also likely to be involved in mouse interactions when using
Shiny.
Some functions are mainly for internal use:
elementId2Prefix
,
playwidgetOutput
,
renderPlaywidget
,
rglwidgetOutput
,
renderRglwidget
,
registerSceneChange
.
More details are given in the vignette User
Interaction in WebGL. The functions
lowlevel
,
highlevel
,
rglId
are also for internal use, marking function results for automatic
printing. Finally, the function
setUserShaders
allows you to use hand-written shaders in WebGL, and
getShaders
allows you to see what shader would be used.
rgl
maintains internal structures for all the scenes it
displays. The following functions allow users to find information about
them and manipulate them. In cases where there are both *3d
and rgl.*
versions of functions, most users should use the
*3d
version: the rgl.*
functions are more
primitive and are mainly intended for internal use.
Function | Description |
---|---|
open3d : |
open a new window |
close3d : |
close the current window |
cur3d : |
id of the active device |
set3d : |
set a particular device to be active |
pop3d : |
delete objects from the scene |
clear3d : |
delete all objects of certain classes |
ids3d : |
ids, types and tags of current objects |
tagged3d : |
find tags or objects with tags |
Some of these functions have alternate names for back
compatibility:rgl.cur
, rgl.ids
, rgl.pop
. Either
name will work, but the *3d
version is recommended for new
code. Some have deprecated versions: rgl.clear
,
rgl.set
. Those should not be called.
These functions are mainly intended for programming, and have no
corresponding *3d
counterparts:
Function | Description |
---|---|
rgl.bringtotop : |
bring the current window to the top |
rgl.dev.list : |
ids of all active devices |
rgl.attrib ,
rgl.attrib.info ,
rgl.attrib.count : |
attributes of objects in the scene |
rgl.projection : |
return information about the current projection |
rgl.user2window ,
rgl.window2user : |
convert between coordinates in the current projection |
The
as.triangles3d
generic function is intended to extract coordinates in a form suitable
for passing to triangles3d
.
Currently a method is provided for
rglId
objects.
In addition to these, there are some deprecated functions which
should not be called: rgl.init
, rgl.open
,
rgl.close
, rgl.quit
.
Most rgl
functions work internally with “homogeneous”
coordinates. In this system, 3-D points are represented with 4
coordinates, generally called (x, y, z, w). The corresponding Euclidean
point is (x/w, y/w, z/w), if w is nonzero; zero values of w correspond
to “points at infinity”. The advantage of this system is that affine
transformations including translations and perspective shifts become
linear transformations, with multiplication by a 4 by 4 matrix.
rgl
has the following functions to work with homogeneous
coordinates:
Function | Description |
---|---|
asEuclidean ,
asHomogeneous : |
convert between homogeneous and Euclidean coordinates when x, y and z are columns |
asEuclidean2 ,
asHomogeneous2 : |
convert when x, y and z are rows |
rotate3d ,
scale3d ,
translate3d : |
apply a transformation |
transform3d : |
apply a general transformation |
rotationMatrix ,
scaleMatrix ,
translationMatrix : |
compute the transformation matrix |
identityMatrix : |
return a 4 x 4 identity matrix |
projectDown : |
a 3D to 2D projection down a vector |
There is also a function
GramSchmidt
,
mainly for internal use: it does a Gram-Schmidt orthogonalization of a
3x3 matrix, with some specializations for its use in
cylinder3d
.
Sometimes it may be convenient to interactively rotate a scene to a
particular view, then display it in lattice
or base
graphics. The
rglToLattice
and
rglToBase
functions support this.
For example, we first display the volcano data in
rgl
:
persp3d(volcano, col = "green")
Volcano in rgl
This display is interactive, but we can reproduce the initial view
using the lattice
wireframe
or base graphics
persp
functions:
# Only evaluated if the lattice & orientlib packages are installed
lattice::wireframe(volcano, col = "green",
screen = rglToLattice())
angles <- rglToBase()
persp(volcano, col = "green", shade = TRUE,
theta = angles$theta, phi = angles$phi)
Note that the orientlib
package must be available for
these functions to work.
pkgdown
websites
The “Using RGL in pkgdown web sites”
vignette describes how to use rgl
in a pkgdown
web site. The utility function
in_pkgdown_example
can be used to detect that pkgdown
is being used.
testthat
The testthat
package is widely used for unit tests in
packages. Such tests are hard to write with rgl
, because
the output is visual and interactive rather than a simple value. The
expect_known_scene
,
compare_proxy.mesh3d
and
all.equal.mesh3d
functions help with this by removing system-dependent features of
rgl
output.
The WebGL displays created using
rglwidget
rely on a large body of
Javascript code included in this package. To help in development of this
code, the
makeDependency
function was written. It may be useful in other packages that include
Javascript.
This section is for miscellaneous functions and objects that don’t fall in any of the other categories in this document.
The
setGraphicsDelay
function is designed to work around what appears to be a bug on macOS:
if a standard plot window is opened too quickly after an
rgl
window, R can crash. This function inserts a one second
delay when it appears to be needed.
The
gltfTypes
vector contains constants used in OpenGL and glTF.
This vignette is always a work in progress. Some aspects of the
rgl
package are not described, or do not have examples.
There may even be functions that are missed completely, if the following
list is not empty:
## [1] "rgl.incrementID" "safe.dev.off" "textureSource"
The following functions and constants are described in this
document: