rgl.*
interfaceSince at least 2004, rgl
has had two interfaces for many
of the primitive functions: rgl.*
and *3d
. For example,
to draw points you could use rgl.points()
or points3d()
.
With the upcoming version 1.0.0 release of rgl
, most of
the duplication will be removed. The first step will be
to deprecate a large number of rgl.*
functions so they give
warnings when they are called, and a few months later
they will be removed from the package exports.
This document describes the differences and changes needed
by users of the rgl.*
interface.
The rgl.open()
function has a single argument, useNULL
.
If set to TRUE
, the NULL rgl
device will be used. The
par3d()
settings will be set to their defaults.
The open3d()
function has arguments
function(...,
params = getr3dDefaults(),
useNULL = rgl.useNULL(),
silent = FALSE )
and allows par3d()
values to be specified,
and uses the r3dDefaults
variable to set default values
for par3d()
, material3d()
, and bg3d()
. Initially
r3dDefaults
is defined as
list(userMatrix = rotationMatrix(290*pi/180, 1, 0, 0),
mouseMode = c("none", "trackball", "zoom", "fov", "pull"),
FOV = 30,
family = "sans",
bg = list(color="white",
fogtype = "none"),
material = list(color="black", fog = TRUE)
)
Users can create their own default lists; e.g. to get the
same result as rgl.open()
would give, use
open3d(params = list())
or
r3dDefaults <- list()
open3d()
The rgl.material()
function has a large number of parameters. The pre-deprecation arguments were:
function(
color = "white",
alpha = 1.0,
lit = TRUE,
ambient = "black",
specular = "white",
emission = "black",
shininess = 50.0,
smooth = TRUE,
texture = NULL,
textype = "rgb",
texmipmap = FALSE,
texminfilter = "linear",
texmagfilter = "linear",
texenvmap = FALSE,
front = "filled",
back = "filled",
size = 3.0,
lwd = 1.0,
fog = TRUE,
point_antialias = FALSE,
line_antialias = FALSE,
depth_mask = TRUE,
depth_test = "less",
polygon_offset = c(0.0, 0.0),
margin = "",
floating = FALSE,
tag = "",
blend = c("src_alpha", "one_minus_src_alpha"),
col,
...
)
Thus a call like rgl.material(color = "black")
will set
the color to black, and will also set all of the other
parameters to the default values listed above.
On the other hand, the arguments to material3d()
are
function (..., id = NULL)
Calling material3d(color = "black")
will set
the color to black and leave all other parameters unchanged.
The primitive shapes (points etc.) can be set using calls
like rgl.points(x, y, z, color = "black")
or
points3d(x, y, z, color = "black")
.
The first difference is
that rgl.*
primitives will call rgl.material()
to set
the material properties: in this example color
will be set
to black
, and all other parameters will be set to their
defaults. The *3d
versions of the primitives use
material3d()
to set material properties, so only those that
were specified will be changed, and the original values
will be restored afterwards.
The second difference is what happens if there is no
window already open. The rgl.*
functions will call
rgl.open()
(ignoring r3dDefaults
), whereas the *3d
functions will call open3d()
.
rgl.*
?Both of the systems worked, but they do not work together.
For example, calling rgl.points()
will have carry-on effects
on later points3d()
calls, whereas each points3d()
call
will just draw the points, it won’t affect future calls.
Users have found this confusing, and it makes their code hard
to debug, and the rgl
package hard to maintain. The *3d
interface is more flexible, and more similar to the base graphics
interface in R, so I’ve decided it will be the only one
available going forward.
rgl.*
functions are not deprecatedThere will still be some rgl.*
functions in the package.
These are functions that are mainly intended for
programming, such as rgl.attrib()
and rgl.user2window()
, and
a few legacy functions like rgl.Sweave()
supporting
older approaches of using rgl
.
In a few cases
both function versions are identical
(rgl.cur
, rgl.ids
, and rgl.pop
are identical
to cur3d
, ids3d
and pop3d
respectively),
and for those the rgl.*
versions will be kept,
but the documentation will concentrate on the *3d
functions.
rgl.*
. What do I need to do?If your package is using rgl.*
functions, the first
step is to just make the substitutions suggested by the
deprecation warning message. For example, if you use rgl.points(rnorm(10), rnorm(10), rnorm(10))
try using
points3d(rnorm(10), rnorm(10), rnorm(10))
instead.
In most cases this will give you what you want. In
some cases more changes will be needed.
rgl.open
and rgl.material
See above if you were using these.
The default color after rgl.open()
was white, whereas
with open3d()
the default color is black, with a white
background. Textures multiplicatively
modify the color of the object,
so after open3d()
, a texture on an object will still appear
black. Explicitly specifying color = "white"
when a texture
is used will fix this.
rgl.surface()
The arguments to rgl.surface()
and surface3d()
functions
are different. The argument lists are
rgl.surface( x, z, y,
coords = 1:3, ...,
normal_x = NULL, normal_y = NULL, normal_z = NULL,
texture_s = NULL, texture_t = NULL)
surface3d(x, y = NULL, z = NULL,
...,
normal_x = NULL, normal_y = NULL,
normal_z = NULL,
texture_s = NULL, texture_t=NULL)
Notice that the arguments are in a different order.
Another difference is that rgl.surface()
expects the surface
to be defined in the y
coordinate and viewed
in the orientation produced by rgl.open()
, not the one produced by
open3d()
. Up until very recently, surface3d()
didn’t allow both x
and z
to be vectors.
The excellent rayshader
package
used the convention
that the y
argument held the surface, so the y
direction
should point up. Using view3d(theta = 45, phi = 45)
(which it was already doing) gives a reasonable view.
Many functions in rgl
and other packages use ...
to set
material or par3d
properties in a call, and for some,
...
will
contain other optional arguments. Some packages used the
argument list of rgl.material()
to identify the
material property names. Going forward, packages should
use the
variables
rgl.material.names
rgl.material.readonly
These are character variables holding
all the material property names. (rgl.material.names
contains all names; rgl.material.readonly
is the
read-only subset of that list.) There are also variables
rgl.par3d.names
rgl.par3d.readonly
which give the same information for par3d
.
Since these variables are recently added, you will need to add
a dependence on rgl (>= 0.111.5)
if you use them.
If you have particular problems adapting other rgl.*
to the
*3d
interface, please post them as issues on https://github.com/dmurdoch/rgl/issues . I’ll
explain how to get what you want or fix things in rgl
so
you can do it.