I will need to make a video from the manual rotation of a 3D graphics. In order to do this, I will need to record the set of all view points that I made during rotation. There is method that we can use to get a single viewpoint, like discussed here, but can we find a way to use AppendTo or Sow and Reap to automatically store all the view points in a list?
1 Answer
Here's a start:
(* Recording *)
vp = OptionValue[Graphics3D, ViewPoint];
vv = OptionValue[Graphics3D, ViewVertical];
vprec = list[];
vvrec = list[];
g = Graphics3D[Cuboid[],
ViewPoint -> Dynamic[vp, (vp = #; vprec = list[vprec, #]) &],
ViewVertical -> Dynamic[vv, (vv = #; vvrec = list[vvrec, #]) &]
]
I used a linked list for O(1) appending.
Now rotate the graphic slowly using the mouse. The view points will be recorded.
(* Playback *)
vpplay = List @@ Flatten[vprec, Infinity, list];
vvplay = List @@ Flatten[vvrec, Infinity, list];
ListAnimate@
MapThread[
Show[g, ViewPoint -> #1, ViewVertical -> #2] &, {vpplay, vvplay}]
For a better result you also need to record the precise time of each step (AbsoluteTime[]
), compute the correct frame durations and reproduce them using a custom ListAnimate
. (When you export to GIF you can specify frame durations---check the docs on GIF exporting).
-
$\begingroup$ Amazing! I will need to go deep into Dynamic... Thanks! $\endgroup$– saturaslApr 7, 2013 at 3:59
-
$\begingroup$ Adopting Szabolcs's code, we can also write something like: vprec = {}; vvrec{}; then change the Dynamic[vp, (vp = #; vprec = list[vprec, #]) &] to Dynamic[vp, (vp = #; AppendTo[vprec, #]&]. This makes the code easier to read, but may decrease performance in complex situation. $\endgroup$– saturaslApr 7, 2013 at 4:38
-
$\begingroup$ @saturasl To be precise, the time taken by
AppendTo[list, ...]
is proportional to the length oflist
. It'll slow down as the list gets big, but I haven't tried if it makes a difference in this application. It might not. $\endgroup$– SzabolcsApr 9, 2013 at 21:34