dmurdoch / rgl

rgl is a 3D visualization system based on OpenGL. It provides a medium to high level interface for use in R, currently modelled on classic R graphics, with extensions to allow for interaction.
https://dmurdoch.github.io/rgl/
GNU General Public License v2.0
84 stars 20 forks source link

snapshot3d fails on Windows 10 #391

Closed cfholbert closed 9 months ago

cfholbert commented 9 months ago

snapshot3d fails when trying to save a simple example on Windows 10. The example code is as follows:

vertices <- c( -1.0, -1.0, 0, 1.0, -1.0, 0, 1.0, 1.0, 0, -1.0, 1.0, 0 ) indices <- c( 1, 2, 3, 4 )

open3d()
wire3d( mesh3d(vertices = vertices, quads = indices) ) snapshot3d('mesh.png')

I get the following errors:

Warning messages: 1: In onRejected(...) : An error occurred: Error in onFulfilled(value): Unable to find any visible elements for selectors.

2: In normalizePath(path.expand(path), winslash, mustWork) : path[1]="An error occurred: Error in onFulfilled(value): Unable to find any visible elements for selectors. ": The filename, directory name, or volume label syntax is incorrect 3: In snapshot3d("mesh.png") : webshot2::webshot() failed; trying rgl.snapshot()

When I run chromote::find_chrome() I get the following path:

[1] "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"

rgl Version: 1.2.1 R Version: 4.3.1 Platform: Windows 10>

dmurdoch commented 9 months ago

First: your code works for me without an error. I'm not on Windows so that's not a big surprise, but it probably means I'm not going to be able to do much debugging here. In any case, it looks to me as though the problem is in webshot2 or chromote rather than rgl, because the first and second messages look like they're coming from one of those. The third one comes from rgl, after these commands in snapshot3d:

 res <- try(capture.output(webshot2::webshot(f1, file = filename, selector = "#webshot",
                    vwidth = width + 100, vheight = height, ...),
               type = "message"))

if (!inherits(res, "try-error") && file.exists(filename) && file.size(filename) > 0)
  return(invisible(filename))

warning("webshot2::webshot() failed; trying rgl.snapshot()")

Because I put the webshot2::webshot call in try(), it's hard to find the exact issue. If you want to track it down, you could call webshot2::webshot directly. The arguments being used are f1, the filename of an HTML tempfile used in htmlwidgets::savewidget(rglwidget(), f1) (with some optional arguments that probably don't matter), and filename, the file where you'd like to save the results. My guess would be that one of f1 or filename is a network file in a format that webshot2 or chromote doesn't know how to handle.

cfholbert commented 9 months ago

I tried using webshot2 directly and it worked. I wonder if the issue wit using snapshot3d is associated with how the temp html file is being saved.

widget <- rglwidget(width = 600, height = 600) filename = 'mesh.html' htmlwidgets::saveWidget( widget, filename, selfcontained = TRUE ) webshot2::webshot('mesh.html', 'mesh.png')

dmurdoch commented 9 months ago

Thanks for following up.

Maybe some more of the details affect things. I think this code is equivalent to what would happen from snapshot3d('mesh.png'):

rect <- par3d("windowRect")
width <- rect[3] - rect[1]
height <- rect[4] - rect[2]
f1 <- tempfile(fileext = ".html")
htmlwidgets::saveWidget(rglwidget(scene3d(), elementId = "webshot", width = width, 
        height = height, webgl = TRUE), f1)
filename <- "mesh.png"
unlink(filename)
webshot2::webshot(f1, file = filename, 
        selector = "#webshot", vwidth = width + 100, vheight = height)

Does that also work for you? If you get any warnings or errors, which lines triggered them?

cfholbert commented 9 months ago

Did not work. Error occurs on last line which is calling webshot:

file:///C:\Users\cholbert\AppData\Local\Temp\RtmpYtOniO\file43c44fbe5168.htmlC:\Users\cholbert\AppData\Local\Temp\RtmpYtOniO\file43c44fbe5168.html screenshot completed Warning messages: 1: In onRejected(...) : An error occurred: Error in onFulfilled(value): Unable to find any visible elements for selectors.

2: In normalizePath(path.expand(path), winslash, mustWork) : path[1]="An error occurred: Error in onFulfilled(value): Unable to find any visible elements for selectors. ": The filename, directory name, or volume label syntax is incorrect

dmurdoch commented 9 months ago

Okay, that's progress. The first error shows that the temp file f1 is being converted to a file: URL incorrectly: it shouldn't have backslashes in it still. It might be enough to run an extra line on the creation of that path, which is something rgl could do. Could you try this recipe?

rect <- par3d("windowRect")
width <- rect[3] - rect[1]
height <- rect[4] - rect[2]
f1 <- tempfile(fileext = ".html")
f1 <- normalizePath(f1, winslash = "/", mustwork = FALSE)
htmlwidgets::saveWidget(rglwidget(scene3d(), elementId = "webshot", width = width, 
        height = height, webgl = TRUE), f1)
filename <- "mesh.png"
unlink(filename)
webshot2::webshot(f1, file = filename, 
        selector = "#webshot", vwidth = width + 100, vheight = height)
cfholbert commented 9 months ago

Worked after changing "mustwork" to "mustWork"!

dmurdoch commented 9 months ago

Great, I can add that workaround, and leave an issue for webshot2.

cfholbert commented 9 months ago

Thank you so much for helping!!