[R] rgl package and animation

Duncan Murdoch murdoch.duncan at gmail.com
Sun Nov 4 14:45:28 CET 2012


On 12-11-03 11:40 AM, Robert Baer wrote:
> On 11/3/2012 6:47 AM, Duncan Murdoch wrote:
>> On 12-11-02 7:47 PM, Robert Baer wrote:
>>> I am trying to figure out how to use rgl package for animation.  It
>>> appears that this is done using the play3d() function.  Below I have
>>> some sample code that plots a 3D path and puts a sphere at the point
>>> farthest from the origin (which in this case also appears to be at the
>>> end of the path).  What I would like to do is animate the movement of
>>> another sphere along the length of the path while simultaneously
>>> rotating the viewport.
>>>
>>> Duncan Murdock's (wonderful) Braided Knot YouTube video:
>>>     (http://www.youtube.com/watch?v=prdZWQD7L5c)
>>> makes it clear that such things can be done, but I am having trouble
>>> understanding how to construct the f(time) function that gets passed to
>>> play3d().  The demo(flag) example is a little helpful, but I still can't
>>> quite translate it to my problem.
>>>
>>> Can anyone point to some some simple f(time) function examples that I
>>> could use for reference or give me a little hint as to how to construct
>>> f(time) for movement along the path while simultaneously rotating the
>>> viewport?
>>>
>>> Thanks,
>>>
>>> Rob
>>>
>>>
>>>
>>> library(rgl)
>>> # Generate a 3D path
>>> dat <-
>>> structure(list(X = c(0, 0.0618130000000008, 0.00223599999999635,
>>> -0.0308069999999958, -0.172805999999994, -0.372467, -0.587706999999995,
>>> -0.881484999999998, -1.103668, -1.366157, -1.625862, -1.94806699999999,
>>> -2.265388, -2.68982699999999, -3.095001, -3.49749, -3.946068,
>>> -4.395653, -4.772034, -5.111259, -5.410515, -5.649475, -5.73439,
>>> -5.662201, -5.56714599999999, -5.39033499999999, -5.081581, -4.796631,
>>> -4.496559, -4.457024, -4.459564, -4.641746, -4.84910599999999,
>>> -5.08994300000001, -5.43129, -5.76372499999999, -6.199448, -6.517578,
>>> -6.86423499999999, -6.90743999999999), Y = c(0, -0.100724,
>>> -0.169471999999999,
>>> 0.0365059999999886, -0.0929950000000019, -0.222977, -0.355759000000006,
>>> -0.365822000000009, -0.329948999999999, -0.209557000000004,
>>> -0.0804140000000046,
>>> 0.0201339999999988, 0.295372, 0.138831999999994, 0.281104999999997,
>>> 0.223761999999994, 0.141905999999992, 0.0602949999999964,
>>> -0.0933080000000075,
>>> -0.207596000000009, -0.328629000000006, -0.438568000000004,
>>> -0.469109000000003,
>>> -0.623505000000009, -0.525467000000006, -0.568444, -0.638885999999999,
>>> -0.727356, -1.073769, -1.03213500000001, -1.203461, -1.438637,
>>> -1.65023100000001, -1.861351, -2.169083, -2.43147300000001,
>>> -2.69914300000001,
>>> -2.961258, -3.23938000000001, -3.466103), Z = c(0, 0.13552900000002,
>>> 0.401062000000024, 1.21637000000004, 1.55395500000003, 1.73080500000003,
>>> 1.81167600000003, 2.18512000000004, 2.52603200000004, 3.03479000000004,
>>> 3.42654400000004, 3.82251000000002, 4.74490400000002, 4.644837,
>>> 5.41848800000002, 5.85867300000001, 6.37835699999999, 6.83395400000001,
>>> 7.216339, 7.59411600000004, 7.95590200000004, 8.352936,
>>> 8.70931999999999,
>>> 9.01669300000003, 9.48553500000003, 9.90005500000001, 10.397003,
>>> 10.932068, 11.025726, 12.334595, 13.177887, 13.741852, 14.61142,
>>> 15.351013, 16.161255, 16.932831, 17.897186, 18.826691, 19.776001,
>>> 20.735596), time = c(0, 0.0100000000000016, 0.0199999999999996,
>>> 0.0300000000000011, 0.0399999999999991, 0.0500000000000007,
>>> 0.0600000000000023,
>>> 0.0700000000000003, 0.0800000000000018, 0.0899999999999999,
>>> 0.100000000000001,
>>> 0.109999999999999, 0.120000000000001, 0.129999999999999,
>>> 0.140000000000001,
>>> 0.150000000000002, 0.16, 0.170000000000002, 0.18, 0.190000000000001,
>>> 0.199999999999999, 0.210000000000001, 0.220000000000002, 0.23,
>>> 0.240000000000002, 0.25, 0.260000000000002, 0.27, 0.280000000000001,
>>> 0.289999999999999, 0.300000000000001, 0.310000000000002, 0.32,
>>> 0.330000000000002, 0.34, 0.350000000000001, 0.359999999999999,
>>> 0.370000000000001, 0.379999999999999, 0.390000000000001)), .Names =
>>> c("X",
>>> "Y", "Z", "time"), row.names = c("1844", "1845", "1846", "1847",
>>> "1848", "1849", "1850", "1851", "1852", "1853", "1854", "1855",
>>> "1856", "1857", "1858", "1859", "1860", "1861", "1862", "1863",
>>> "1864", "1865", "1866", "1867", "1868", "1869", "1870", "1871",
>>> "1872", "1873", "1874", "1875", "1876", "1877", "1878", "1879",
>>> "1880", "1881", "1882", "1883"), class = "data.frame")
>>>
>>>
>>> # Plot 3d path
>>> with(dat, plot3d(X,Y,Z, type = 'l', col = 'blue', lty = 1))
>>>
>>> # get absolute distance from origin
>>> dat$r = sqrt(dat$X ^ 2 + dat$Y ^ 2 + dat$Z ^ 2)
>           mr = max(dat$r)  # yes sorry, didn't get copied to original
> email code
>>> mxpnt = dat[dat$r == mr,] # Coordinates of furthest point
>>>
>>> # Plot a blue sphere at max distance
>>> plot3d(mxpnt$X, mxpnt$Y, mxpnt$Z, type = 's', radius = 1, col = 'blue',
>>> add = TRUE)
>>>
>>
>> Your code didn't include the mr variable, but I assume it's just
>> max(dat$r).  With that assumption, I'd do the animation function as
>> follows:
>>
>> First, draw the new sphere at the first point and save the object id:
>>
>> sphereid <- sphere3d(dat[1,c("X", "Y", "Z")], col="red", radius=1)
>>
>> # Also save the spinner that you like:
>>
>> spin <- spin3d( ) #maybe with different parms
>>
>> # Now, the animation function:
>>
>> f <- function(time) {
>>    par3d(skipRedraw = TRUE) # stops intermediate redraws
>>    on.exit(par3d(skipRedraw=FALSE)) # redraw at the end
>>
>>    rgl.pop(id=sphereid) # delete the old sphere
>>    pt <- time %% 40 + 1 # compute which one to draw
>>    pnt <- dat[pt, c("X", "Y", "Z")] # maybe interpolate instead?
>>    sphereid <<- spheres3d(pnt, radius=1, col="red")
>>    spin(time)
>> }
>>
>> Duncan Murdoch
>
> Thanks so much Duncan!
>
> I probably never would have gotten there without your help. (Especially
> since I had to look at the help for the <<- operator, which is
> conceptually a level beyond where I usually work).   It would be great
> to have an additional creative example or two for  f(time) functions in
> the play3d() help.  Your useful code comments really help me see what
> needs to happen in an f(time) function.
>
> I really appreciate that you took the time to get me going!

I've made a small addition to the spin3d function and added an example 
to the ?spin3d page.  This isn't on CRAN yet, but you can get the latest 
from R-forge.  Make sure you get 0.92.898 or newer.

The new example shows a rotating view of spinning cubes, using the 
sprites3d function within the animation function.

Duncan Murdoch




More information about the R-help mailing list