I am working on building a molecule viewer in Mathematica and am running in to problems with controlling rotation of the molecule (which is rendered as a Graphics3D
object). I apologize in advance for the lengthy code used to build the sample molecule; however the form of the graphics object is representative of real molecule objects generated by my molecule viewer package. I've moved this code to the end of the question so it hopefully does not distract from the real question.
Ultimately, I would like to be able to use the mouse or controllers to adjust the orientation of a 3D object. Then I would like to be able to rotate that object around the vertical axis. The animated gif below demonstrates the rotation:
I have started from the following point:
Manipulate[
Graphics3D[{
Specularity[GrayLevel[1], 100], gr
},
Boxed -> False,
Lighting -> "Neutral",
SphericalRegion -> True, Background -> Black,
ViewVertical -> {Cos[a], 0, Sin[a]}], {a, 0, 4 Pi}]
which demonstrates two problems:
- Clearly, the rotation is out of the viewing plane, and unless
I've missed it, no permutation of the
ViewVertical
values gives me the desired rotation axis. - When the graphic is altered using the mouse, changing the slider no longer changes the graphic.
Next, I tried using ViewVector
. I thought about being smart (no claims that I actually was) and noticed:
ParametricPlot3D[{Cos[a], Sin[a], 1}, {a, 0, 4 Pi}]
should give me the appropriate rotation:
Using
Manipulate[
Graphics3D[{
Specularity[GrayLevel[1], 100], gr
},
Boxed -> False,
Lighting -> "Neutral",
SphericalRegion -> True, Background -> Black,
ViewVector -> 1000 {Cos[a], Sin[a], 1}], {a, 0, 4 Pi}]
comes close to the rotation I'm looking for and it doesn't seem to be affected by problem (2) above. However when I do move the graphic with the mouse, the rotation axis changes in a way that makes no sense to me.
I suspect my code needs to capture the current ViewVector
and perform a rotation based on that information; however I'm having a hard enough time grasping the various View*
options in Graphics3D
that I can't begin to formulate that level of dynamic interactivity.
Update
Since posting this question and reviewing this reference which was provided in the comments I am able to rotate the camera which provides a decent means to view the molecule. As alluded to in one of the possible answers, rotating the molecule as opposed to rotating the viewpoint may be a better approach. (I put this code here only because I was stumped by the conditional that is needed for ViewVertical
, preventing the molecule from jumping.)
Manipulate[
Graphics3D[{Specularity[GrayLevel[1], 100], gr}, Boxed -> False,
Lighting -> "Neutral",
ViewPoint -> 2 {Sin[a] Sin[b], Cos[a] Sin[b], Cos[b]},
ViewCenter -> Automatic,
ViewVertical -> If[b > 0, {0, 0, 1}, {0, 0, -1}], ViewRange -> All,
ViewAngle -> All, SphericalRegion -> True,
Background -> Black], {{a, 0}, 0, 4 Pi}, {{b, .01}, -Pi, Pi}]
The molecule
{and a caveat for all the chemists out there - this is not a real molecule}
gr = GraphicsGroup[{EdgeForm[None],
GraphicsComplex[{{-7.53741, 11.3862, 4.91147}, {146.654, 5.10132,
2.65685}, {200.92, 7.38748, 138.895}, {199.898,
116.382, -68.4703}, {188.424, -110.427, -58.9037}}, {{{RGBColor[
0.4, 0.4, 0.4], Sphere[1, 34]}, {RGBColor[0.4, 0.4, 0.4],
Sphere[2, 34]}, {RGBColor[0.29, 0.44, 0.89],
Sphere[3, 32]}, {RGBColor[0.8, 0.2, 0.2],
Sphere[4, 31]}, {RGBColor[0.58, 0.86, 0.41], Sphere[5, 30]}}}],
GraphicsComplex[{{-7.53741, 11.3862, 4.91147}, {146.654, 5.10132,
2.65685}, {146.654, 5.10132, 2.65685}, {146.654, 5.10132,
2.65685}, {69.5583, 8.24374, 3.78416}, {173.787, 6.2444,
70.7759}, {173.276,
60.7416, -32.9067}, {167.539, -52.6626, -28.1234}}, {{RGBColor[
0.4, 0.4,
0.4], {GeometricTransformation[
Cylinder[{1, 5},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0.0418653,
5.9645, -13.7631}}],
GeometricTransformation[
Cylinder[{1, 5},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0.,
1.}}, {-0.0418653, -5.9645, 13.7631}}]},
RGBColor[0.4, 0.4,
0.4], {GeometricTransformation[
Cylinder[{2, 6},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}, RGBColor[0.4, 0.4,
0.4], {GeometricTransformation[
Cylinder[{3, 7},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}, RGBColor[0.4, 0.4,
0.4], {GeometricTransformation[
Cylinder[{4, 8},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}}}],
GraphicsComplex[{{146.654, 5.10132, 2.65685}, {200.92, 7.38748,
138.895}, {199.898,
116.382, -68.4703}, {188.424, -110.427, -58.9037}, {69.5583,
8.24374, 3.78416}, {173.787, 6.2444, 70.7759}, {173.276,
60.7416, -32.9067}, {167.539, -52.6626, -28.1234}}, {{RGBColor[
0.4, 0.4,
0.4], {GeometricTransformation[
Cylinder[{1, 5},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0.,
1.}}, {-0.0418653, -5.9645, 13.7631}}],
GeometricTransformation[
Cylinder[{1, 5},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0.0418653,
5.9645, -13.7631}}]},
RGBColor[0.29, 0.44,
0.89], {GeometricTransformation[
Cylinder[{2, 6},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}, RGBColor[0.8, 0.2,
0.2], {GeometricTransformation[
Cylinder[{3, 7},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}, RGBColor[0.58, 0.86,
0.41], {GeometricTransformation[
Cylinder[{4, 8},
10], {{{1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}}, {0., 0.,
0.}}]}}}], Null, Null}]