Skip to content

Question about contour3d and writeWebGL: rgl and misc3d package

4 messages · John Muschelli, Duncan Murdoch

#
On 12-11-16 7:09 PM, John Muschelli wrote:
Sounds like a bug in the browser.  When I try it in Firefox 16.0.2 it 
doesn't display properly; the error log (found via Tools | Web developer 
| Error console has several errors in it, the first of which is:

Error: array initialiser too large

That's clearly a limitation of the browser.  You might be able to work 
around it by plotting one layer at a time; writeWebGL will write each 
rgl object in separate arrays of data.  If the layers are separate, the 
browser might be able to handle them.  I just tried this, and it works 
on my system, using this code:

contour3d(a, 1:64, 1:64, 1.5*(1:21), lev=c(3000),
  alpha = c(0.2), color = c("white"))

  contour3d(a, 1:64, 1:64, 1.5*(1:21), lev=c(8000),
  alpha = c(0.5), color = c("red"), add=TRUE)

  contour3d(a, 1:64, 1:64, 1.5*(1:21), lev=c(10000),
  alpha = c(1), color = c("green"), add=TRUE)

followed by the browseURL call you already had.

Duncan Murdoch
#
That works!  Thanks for the help, but I can't seem to figure out why this
happens with even one contour in the example below:
Disclaimer: using MNI template from FSL (
http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/Atlases).

Firefox still has array initialiser too large for this one contour, but
Safari and Chrome both will render it, but again it comes out half of a
brain and the vertices are connected across the brain and not a surface.

The code is the same as with the example from AnalyzeFMRI, but a different
dimension for the array and a different level (Also attached).

template <- f.read.nifti.volume("MNI152_T1_2mm_brain.nii")

template <- template[,,,1]


contour3d(template, x=1:dim(template)[1], y=1:dim(template)[2], z=1:dim(
template)[3], level = c(1000), alpha = c(0.2), color = c("white"))

browseURL(paste("file://", writeWebGL(dir=file.path(tempdir(), "webGL"),

          width=500), sep=""))
On Fri, Nov 16, 2012 at 8:37 PM, Duncan Murdoch <murdoch.duncan at gmail.com>wrote:

            
#
On 12-11-17 1:51 PM, John Muschelli wrote:
There's a thread from last year here:

https://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00093.html

that says that WebGL is limited to 65535 vertices in any object.  I 
assume that limit is still in effect, and your scenes probably have too 
many vertices.

The writeWebGL function doesn't do any checks for things like this. 
I'll think about having it split up objects as required, but in the 
meantime, you'll need to do it yourself.

Duncan Murdoch
#
On 12-11-17 3:11 PM, Duncan Murdoch wrote:
I just tried your example.  The image has 205311 vertices, so it will 
need splitting up.  It is made up of triangles, and they're fairly 
simple, so this should do it:

split_triangles <- function(ids = rgl.ids()$id, maxsize=65535) {

   if (maxsize %% 3 != 0)
     stop("maxsize must be a multiple of 3")

   save <- par3d(skipRedraw=TRUE)
   on.exit(par3d(save))

   allids <- rgl.ids()
   ids <- with(allids, id[ id %in% ids & type == "triangles" ])
   for (id in ids) {
     count <- rgl.attrib.count(id, "vertices")
     if (count <= maxsize) next
     verts <- rgl.attrib(id, "vertices")
     norms <- rgl.attrib(id, "normals")
     cols <- rgl.attrib(id, "colors")
     rgl.pop(id=id)
     while (nrow(verts) > 0) {
       n <- min(nrow(verts), maxsize)
       triangles3d(verts[1:n,], normals=norms[1:n,], 
color=rgb(cols[1:n,1], cols[1:n,2], cols[1:n,3]), alpha=cols[1:n,4])
       verts <- verts[-(1:n),,drop=FALSE]
       norms <- norms[-(1:n),]
       cols <- cols[-(1:n),]
     }
   }
}


This function isn't perfectly general, but I think it is good enough for 
contour3d output.  (It does slow down rendering noticeably:  having one 
object is easier to render than having 4.)  You might need to play with 
smaller values of maxsize.

Duncan Murdoch