geom_*_3d() function now has a documented annotate argument for embedding annotate_3d() annotations in the layer. geom_text_3d() with its default method = "billboard" now supports annotations; previously it ignored them with an "unknown parameter" warning.geom_text_3d() (billboard method) could draw labels at each other's depth-scaled sizes under perspective projection.on_top argument: annotate_3d("text", ..., on_top = TRUE) draws labels after everything else in the layer, instead of depth-sorting them, so geometry never hides or clips them.annotate_3d("polygon") draws filled polygons from their vertices, with group to draw several in one call. Like planes, they are lit from the side facing the viewer and never removed by back-face culling.annotate_3d("line") draws infinite lines through a point (x, y, z) in a direction (dx, dy, dz), clipped to the panel. Like planes, lines don't expand the plot's axis ranges.geom_segment_3d(arrow = )); they're drawn with an arrow only when given their own via annotate_3d(arrow = ).geom_segment_3d() and geom_path_3d() gain an arrow.fill argument. Closed arrowheads are now filled with the line colour by default, as in ggplot2; previously they were drawn hollow.annotate_3d("plane") draws planes clipped to the panel. Planes can be given as xintercept, yintercept, or zintercept (perpendicular to an axis); as intercept, slope_x, and slope_y (z = intercept + slope_x * x + slope_y * y, as from a linear model); or as general coefficients a * x + b * y + c * z = d. All forms are vectorized, so e.g. a linear system can be drawn in one call. Planes are depth-sorted (and, with pairwise sorting, split where they intersect) with the layer's geometry, lit from the side facing the viewer, never removed by back-face culling, and don't expand the plot's axis ranges.geom_point_3d() layer with pairwise sorting contained annotations. Pairwise sorting now also treats the reference lines of point layers as segments rather than degenerate polygons.annotate_3d("axes") draws x, y, and z axis lines through an origin (default 0), each spanning the panel's full range, with arrowheads and labels at their high ends. Axes are depth-sorted with the layer's geometry, and are built from the panel's limits at draw time, so they don't expand the plot's axis ranges.annotate_3d("segment") gains an arrow argument, taking a grid::arrow() specification. Closed arrowheads are filled with the segment colour, and when a segment is split where it passes through a polygon, its arrowheads stay at the original ends.coord_3d() now draws axis lines from the axis.line theme elements, plus a new axis.line.z. Each line runs along the cube edge carrying its axis's ticks and labels, so it appears only alongside rendered panels. Axis lines are blank in most complete themes, but plots using theme_classic() now show them. Lines run toward increasing data values, so arrows set with element_line(arrow = ) point up each axis. They are depth-scaled with the cube edges, under the "border" key of coord_3d(scale_depth = ).sort_method = "pairwise", and "auto" for small layers) now splits polygons that pass through one another, so intersecting planes and surfaces render with correct occlusion along their line of intersection. Outlines are drawn only along original polygon edges, not along the cuts.annotate_3d() segments) could be drawn on the wrong side of polygons.Changes to default behaviors, which slightly alter styling relative to prior version:
coord_3d() now draws axis ticks by default, whereas previously axis ticks were not implemented. They can be removed or styled with the standard axis.ticks and axis.ticks.length theme elements plus a new axis.ticks.z.coord_3d(scale_depth = c(text = FALSE)) to opt out.New options:
light() to it, e.g. ggplot(...) + coord_3d() + light(direction = c(1, 0, 0)). This is the recommended way to specify plot-level lighting, and works regardless of where it appears in the plot expression. The light argument of coord_3d() continues to work; supplying both is an error.light("none") is a new way to disable lighting, equivalent to the string "none" accepted by light arguments.scale_depth arguments are now more customizable: in 3D layer functions you can now pass continuous values to reduce or exaggerate the effect (rather than just a logical flag), and in coord_3d() you have more granular control over scaling for gridlines, ticks, and axis text.Bug fixes:
scale_z_continuous() and scale_z_discrete() stored z scales in a package-level cache, causing plots to sometimes contaminate each other's z-axis ranges. Now, the z scale is stored directly in the plot being built, preventing cross-contamination.geom_hull_3d()'s "alpha" method got some bug fixes related to face orientation and the radius parameter.orbit_3d() function builds HTML widgets that let you interactively rotate ggcube plots.xlab(expression(italic(alpha[1]))) now behaves as expected.element_rect(), guide_legend_3d(), and camera-anchored lighting.