[R] rgl package and animation

Duncan Murdoch murdoch.duncan at gmail.com
Sat Nov 3 12:47:57 CET 2012


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




More information about the R-help mailing list