[R] Question about contour3d and writeWebGL: rgl and misc3d package

Duncan Murdoch murdoch.duncan at gmail.com
Sat Nov 17 22:22:48 CET 2012

On 12-11-17 3:11 PM, Duncan Murdoch wrote:
> On 12-11-17 1:51 PM, John Muschelli wrote:
>> 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).
> 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.

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)

   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")
     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

More information about the R-help mailing list