rgl.*
interfacevignettes/deprecation.Rmd
deprecation.Rmd
Since 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
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
or
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
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 deprecated
There 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.
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.