Search code examples
r3drgl

Create two subscenes in a single rgl window without using mfrow3d in R


I want to create two subscenes in a single rgl window in R, one on the left and the other on the right. I do not want to use mfrow3d function since in my real code, subscenes will not be aligned in a single row or column. Here is my code:

library(rgl)

# Open 3D device
open3d()

# Set up first subscene on the left
par3d(windowRect = c(0, 0, 0.5, 1))
plot3d(rnorm(100), rnorm(100), rnorm(100), col = "red", type = "s")

# Set up second subscene on the right
par3d(windowRect = c(0.5, 0, 1, 1))
plot3d(rnorm(100), rnorm(100), rnorm(100), col = "blue", type = "s")

I should be seeing red spheres on the left subscene and blue spheres on the right subscene. But the above code only returned blue spheres. I can see the red spheres appearing but quickly replaced by the subscene for the blue spheres. I read the user manual for windowRect and noted that it is "A vector of four values indicating the left, top, right and bottom of the displayed window". I think my issue lies in the misspecified windowRectargument, but I am not sure how I should update it.

Another question is if it is possible to plot the subscene for the blue spheres in the top right corner (1/4 of the width and height of the red spheres subscene) of the subscene for the red spheres?


Solution

  • The windowRect setting is for the whole window. You only have one subscene. I don't think you've shown us your real code, because setting the windowRect to that size makes it too small to display anything.

    To set up a subscene at an arbitrary location, use newSubscene3d() with the newviewport setting describing the location in pixels relative to the container.

    For example, this plots them side-by-side:

    library(rgl)
    
    # Open 3D device
    open3d(windowRect = c(50, 50, 550, 550))
    
    toplevel <- subsceneInfo()$id
    
    # Set up first subscene on the left
                               # left bottom width height
    newSubscene3d(newviewport = c(0,  0,     250,  500))
    plot3d(rnorm(100), rnorm(100), rnorm(100), col = "red", type = "s")
    
    # Go back to the top level
    useSubscene3d(toplevel)
    
    # Set up second subscene on the right
    newSubscene3d(newviewport = c(250, 0, 250, 500))
    plot3d(rnorm(100), rnorm(100), rnorm(100), col = "blue", type = "s")
    

    If you want the second one as part of the first one, skip the useSubscene3d(toplevel) call, and just set up the new one, which will be embedded within the previous one.