Message Boards Message Boards

Universal stereo plotter

Hi,

This is an idea that has challenged me since I started using MMA a little over two years ago. The idea was to append //stereo to a 3D plot and instantly get a stereogram that can be manipulated just like a normal 3D plot, turning it around and viewing it from different angles. This is my first use of Dynamic, so it might be a little clunky. Help in speeding it up would be appreciated.

stereo[expr_] :=  DynamicModule[
  {vp = {1.3, -2.4, 2.0}, vv = {0., 0., 2.0}, plot}, 
  plot = expr; 
  GraphicsRow[
    {Show[plot, ViewPoint -> Dynamic[vp + {0.4, 0, 0}], ViewVertical -> Dynamic[vv]], 
     Show[plot, ViewPoint -> Dynamic[vp], ViewVertical -> Dynamic[vv]]}, 
    ImageSize -> Large
   ]
]

For instance,

Plot3D[Sin[x] Cos[y] Cos[x y], {x, 0, 2 Pi}, {y, 0, 2 Pi}, 
  PlotRange -> All, ColorFunction -> "BlueGreenYellow"] // stereo

enter image description here

Viewing the stereogram takes a little practice. I learned it from a radiologist who used it to make 3D X-rays. He would position the patient, take an x-ray, move the x-ray source over a couple of inches, and take another x-ray. Then he put both x-rays side-by-side on the light panel, stepped back, and crossed his eyes until the two images superimposed. Voila! a 3D view of the interior of patient's body.

When learning, it's helpful to hold a finger between your eyes and the image. Focus on the finger and move it back and forth until the images coalesce in the background. Now keep the images together and re-focus your eyes on them. That can be tricky as it's quite unnatural.

Once the trick is learned, stereo images are as easy to see as flat ones.

The right-hand image can be moved around using the mouse and the left will follow.

The function needs improvement, though. Sometimes the images get out of sync. Just do a shift-enter to restart.

Eric

EDIT: I've changed the offset in the viewpoint from {0,0.4,0} to {0.4,0,0}. Strange how even the wrong offset results in a stereogram!

POSTED BY: Eric Johnstone
4 Replies

Nicely done, Eric. I wonder if finding $0.4$ in ViewPoint -> Dynamic[vp + {0.4, 0, 0}] was trial and error sort process. Such things were tried already. Take a look at Herbert W. Franke's demos, fro example Stereo View without Glasses and at @Kay Herbert's 3D Anaglyph Graphics. WL code is available for free download at those links.

enter image description here

enter image description here

POSTED BY: Sam Carrettie

Hi Sam,

Yes, I made a little Manipulate tester to find the offset. My approach is to have a function that can be used in normal MMA explorations. I'm working on using the event handler to detect a mouseup event, at which point the left-hand image will be drawn. That should allow fast image rotations, although it isn't what I'd really like: to see the stereoscopic movement similar to the flat movement.

Eric

POSTED BY: Eric Johnstone

Hi Sam,

Yes, I made a little Manipulate tester to find the offset. However, I was using the wrong axis. On further testing, a value of 0.2 works better.

My approach is to have a function that can be used in normal MMA explorations. I'm working on using the event handler to detect a mouseup event, at which point the left-hand image will be drawn. That should allow fast image rotations, although it isn't what I'd really like: to see the stereoscopic movement similar to the flat movement.

Eric

POSTED BY: Eric Johnstone

Dynamic has a second argument that gives the behaviour I'm looking for. Since the left-hand plot is too slow to move with the right-hand one, it can be disabled until the right-hand plot is in the desired position. When the mouse button is released, the Dynamic variable is broadcast and the left-hand plot is updated.

The second argument can also disable interaction, so that the left-hand plot cannot be moved by the mouse. It shouldn't be moved anyway, because that generates and error.

So here is the finished code:

    stereo[expr_] := 
     DynamicModule[{vp = {1.3, -2.4, 2.0}, vv = {0., 0., 2.0}, plot}, 
      plot = expr; 
      GraphicsRow[{Show[plot, ViewPoint -> Dynamic[vp + {.2, 0, 0}, None],
          ViewVertical -> Dynamic[vv, None]], 
        Show[plot, ViewPoint -> Dynamic[vp, Temporary], 
          ViewVertical -> Dynamic[vv, Temporary]]}, 
        ImageSize -> Large]]

You might want to play around with the 0.2 offset.

Note that this can turn any 3D graphic into a stereoscopic image. Just append //stereo to the 3D graphic expression.

Edit:

That annoying jump when you release the mouse button can be fixed by adding the Option RotationAction -> "Clip". It only applies to functions that recognize this option, but that includes most of the Plot3D functions:

stereo[expr_] := 
 DynamicModule[{vp = {1.3, -2.4, 2.0}, vv = {0., 0., 2.0}, plot}, 
  plot = expr; 
  GraphicsRow[{Show[plot, ViewPoint -> Dynamic[vp + {.3, 0, 0}, None],
      ViewVertical -> Dynamic[vv, None], RotationAction -> "Clip"], 
    Show[plot, ViewPoint -> Dynamic[vp, Temporary], 
     ViewVertical -> Dynamic[vv, Temporary], 
     RotationAction -> "Clip"]}, ImageSize -> 600]]

The ImageSize can be set to your liking, too.

Eric

POSTED BY: Eric Johnstone
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract