user101089 - 1 year ago 112
R Question

# rgl: drawing a cube with colored faces, vertex points and lines

To demonstrate the effect of linear transformations in 3D,

`x -> A x`
, I want to draw a cube and show its transformation under
`A`
. For this, I need to color each face separately, and also show the vertex points and the lines that outline each face.

I can't figure out how to use distinct colors for the faces, and how to make this more general so I don't have to repeat all the steps for the result under the transformation.

what I tried:

``````library(rgl)
c3d <- cube3d(color=rainbow(6), alpha=0.5)
open3d()
points3d(t(c3d\$vb), size=5)
for (i in 1:6)
lines3d(t(c3d\$vb)[c3d\$ib[,i],])
``````

This gives the image below. But I don't understand how the faces are colored. And, I seem to have to use
`points3d`
and
`lines3d`
on the components of the
`c3d`
shape, and don't have a single object I can transform.

A particular transformation is given by the matrix
`A`
below, and here is how I add that to the scene,

``````A <- matrix(c( 1, 0, 1, 0, 2, 0,  1, 0, 2), 3, 3)
c3d_trans <- transform3d(c3d, A)
points3d(t(c3d_trans\$vb), size=5)
``````

This gives:

Is there some way to simplify this and make it more generally useful?

In `rgl`, when drawing primitive shapes, you apply colours to vertices, not faces. The faces are coloured by interpolating the colors at the vertices.

However, `cube3d()` is not a primitive shape, it's a "mesh". It is drawn as 6 separate quadrilaterals. Each vertex is used 3 times.

It's not really documented, but the order the colours are used is that the first 4 are used for one face, then the next 4 for the next face, etc. If you want your colours to be `rainbow(6)`, you need to replicate each colour 4 times:

``````library(rgl)
c3d <- cube3d(color=rep(rainbow(6), each = 4), alpha = 0.5)
open3d()
points3d(t(c3d\$vb), size = 5)
for (i in 1:6)
lines3d(t(c3d\$vb)[c3d\$ib[,i],])
``````

I'd recommend a higher `alpha` value; I find the transparency a little confusing at `alpha = 0.5`.

By the way, for the same purpose, I generally use a shape that looks more spherical as the baseline; I think it gives better intuition about the transformation. Here's code I have used:

``````sphere <- subdivision3d(cube3d(color=rep(rainbow(6),rep(4*4^4,6)), alpha=0.9),
depth=4)
sphere\$vb[4,] <- apply(sphere\$vb[1:3,], 2, function(x) sqrt(sum(x^2)))
open3d()
``````

and this gives this shape:

which transforms to this:

``````A <- matrix(c( 1, 0, 1, 0, 2, 0,  1, 0, 2), 3, 3)
trans <- transform3d(sphere, A)
open3d()