# How to create a simple cross eyed 3d plot

I wanted to create a stereoscopic view of my threedimensional plots, so I can interpret them better.

The basic things, one would need, are two plot windows which are somehow connected to each other and modify the camera position of the second plot.

-
Great question. Related:demonstrations.wolfram.com/LookingAtPolyhedraIn3D – Michael E2 Aug 8 '13 at 0:34
Another solution, the StereoImagery package contains two main functions, MakeStereo and MakeAnaglyph: markfisher.net/~mefisher/mma/mathematica.html – VLC Aug 9 '13 at 15:33

I got my inspiration from Yu-Sung Chang in his answer to a question about Mathematica's viewmatrix.

The basic idea is now, to combine the two plots and simply rotate the viewpoint of the second plot around the vertical axis by a certain angle to get a satisfying result.

So at first, we create the plot with the four view-parameters as argument.

myplot[point_,angle_,vertical_,center_]:=Graphics3D[{
(*Objects*)
EdgeForm[],Specularity[White,20],FaceForm[Red],Sphere[{-0.2,-0.1,-0.3},.2],FaceForm[Blue],Cylinder[{{0.,0.3,-.5},{0.,0.3,0.}},.1],FaceForm[Green],Cone[{{0.2,0.,-0.5},{0.2,0.,-0.1}},.2]},

Boxed->True,
Lighting->"Neutral",
ImageSize->300,
RotationAction->"Clip",

(*View control*)
ViewPoint->point,
ViewAngle->angle,
ViewVertical->vertical,
ViewCenter->center]


The next step is the connection of this plot for both eyes:

DynamicModule[
{point={1.3,-2.4,2},angle=N[35 Degree],vertical={0,0,1},center=Automatic},
Grid[{{
Framed[
myplot[Dynamic[point],Dynamic[angle],Dynamic[vertical],Dynamic[center]],
FrameStyle->LightGray],

(*The second object*)
Framed[
myplot[Dynamic[RotationMatrix[-5\[Degree],vertical].point],Dynamic[angle],Dynamic[vertical],Dynamic[center]],
FrameStyle->LightGray]
}}]
]


The result can be easily viewed crosseyed and it is possible to rotate this view with the standard controls of the left plot. Using the right plot to change the camera position doesn't work as expected.

-
Okay, that's pretty darn cool. Why didn't I think of this? :^) +2 – Mr.Wizard Aug 7 '13 at 11:35
-1 I feel discriminated for not being able to cross my eyes without focusing on my finger. (kidding) – Rojo Aug 7 '13 at 17:31
@Rojo Kidding about the -1 or kidding about not being able to cross your eyes? (I'm genuinely curious.) – Mr.Wizard Aug 7 '13 at 21:03
@Mr.Wizard just about the -1 – Rojo Aug 9 '13 at 0:34
+1 I guess the next mission would be tracing the eyeballs and accordingly blurring the portions which are away from the current focus plane! – Silvia Aug 15 '13 at 7:45

Here's a function for application to an arbitrary Graphics3D object:

Plot3D[Sin[x + y^2], {x, -3, 3}, {y, -2, 2}] //
stereo3D[ImageSize -> 200, Axes -> False]


Syntax is either gr // stereo3D[options] or simply gr // stereo3D.

Code:

stereo3D[graphics_Graphics3D] := stereo3D[][graphics]
stereo3D[opts : OptionsPattern[Show]][graphics_Graphics3D] :=
DynamicModule[{
myplot,
point = {1.3, -2.4, 2},
angle = 35 °,
vertical = {0, 0, 1},
center = Automatic
},
myplot[pt_] :=
Framed[
Show[graphics, opts,
ViewPoint    -> pt,
ViewAngle    -> Dynamic[angle],
ViewVertical -> Dynamic[vertical],
ViewCenter   -> Dynamic[center]],
FrameStyle -> LightGray];
Grid[{{
myplot[point // Dynamic],
myplot[RotationMatrix[-5 °, vertical].point // Dynamic]
}}]
]

-
Very nice extension. This way, we can handle it much easier. – Stefan Aug 7 '13 at 12:13
@Stefan Thanks, I'm glad you approve. – Mr.Wizard Aug 7 '13 at 12:26
@Pato I wanted to be able to use either gr // stereo3D or gr // stereo3D[(*options*)]. To do this I convert an explicit appearance of the first form into the second; it is equivalent to gr // stereo3D[]. In all of these examples x // f is equivalent to f[x], but to me more logical for a post-processing function. – Mr.Wizard Aug 7 '13 at 13:43
May I remark that rotating the scene is not entirely equivalent to a translation of the viewpoints? – Sjoerd C. de Vries Aug 7 '13 at 21:23
@stefan I have no problem with focussing on the center of the object (note the phrase "not entirely" in my remark), and I agree that this may be done by rotating the scene, but it doesn't take into account that some parts of the scene are closer to one eye than the other and therefore have a different projection. Imagine a small stick of 1 cm height placed vertically 6.5 cm in front of your right eye (which is 6.5 cm to the right of your left eye). The stick subtends atan(1/6.5) rads of visual angle in the right eye, but subtends only atan(1/(sqr(2)6.5)) in the left eye, a whole lot less. – Sjoerd C. de Vries Aug 8 '13 at 14:07

I've been working on this problem on Wolfram Community http://community.wolfram.com/groups/-/m/t/788811. Posting my solution here for future searchers.

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


The right-hand image is interactive; the left-hand one does not react to the mouse. When the mouse button is released after rotating the right-hand image, the left-hand image is drawn. I added RotationAction -> "Clip" because the image jumps slightly after adjustment.

By appending //stereo to a Graphics3D expression (which includes any *Plot3D` function), the stereogram is generated instead of the flat image.

Eric

-