# Rotate 3D cube so nearest side is facing user

How do I figure out the new angle and rotation vectors for the most visible side of the cube?

Why: The user can rotate cube, but when finished I'd like the cube to snap to a side facing the user.

What: I'm currently using CoreAnimation in iOS to do the rotation with CATransform3D. I have the current angle and the rotation vectors so I can do this:

``````CATransform3DMakeRotation(angle, rotationVector[0], rotationVector[1], rotationVector[2]);
``````

Additional Info: I'm currently using Bill Dudney's Trackball code to generate movement and calculate angle and rotation vector.

-

To find the 'most visible side' of the cube, take dot products of the cube's X, Y, and Z axes with the 'look vector' - that is, the direction the camera is looking; the axis with the largest absolute dot product will be the axis most aligned with that vector, and the sign indicates which of the two faces along that axis ('positive' or 'negative') is facing the viewer. For instance, assuming you have your cube defined from (-1, -1, -1) to (+1, +1, +1), then dot products of -0.25, 0.3, and -0.92 would mean that the Z faces are most aligned with the view; whether that's the face z=-1 or the face z=1 depends on your particular conventions (e.g., whether positive Z goes into or out of the screen).

Note that this doesn't give you enough information to fully snap the cube into place, though - for that, you'd need not just the side of the cube facing the viewer but also the side of the cube facing in some orthogonal direction - for instance, which side of the cube is facing rightwards. You can find that using the same general idea, only dotting with (the worldspace transformation of) your screenspace X axis instead of Z (which is the look vector).

Once you have these two faces (or equivalently, the two axes - e.g., (0, 0, -1) and (1, 0, 0)), you can cross them to find your third 'aligned axis'; that's enough to give you an orientation matrix, and you can then Slerp from your current orientation to this target orientation. There are a couple of gotchas to be aware of with this approach - specifically, you have to be careful about how you handle ties to make sure that you never accidentally assign the same faces to your 'facing the viewer' and 'facing right' axes.

-
+1 for the mathematical solution. :) – chaosTechnician May 9 '12 at 19:49
Yeesh. Never is ever easy. I guess my attempt at simply rounding the rotation angle of the x,y axis to the nearest 90° seemed a bit too easy. – Steve Baughman May 9 '12 at 19:50
Another +1 for the mathematical idea.. I guess it was a hasty answer, but still good. The mathematical details are difficult to follow if you're not accustomed to basic Linear Algebra stuff. – teodron May 9 '12 at 21:08
@SteveBaughman - TBH, this is the 'easy way' in the long run - it may seem more complicated at the moment but it'll likely save you a fair bit of special-casing down the road. – Steven Stadnicki May 9 '12 at 21:09
@teodron Well, it's abstracted out a fair bit because I don't really know the relevant implementation details of CoreAnimation, but the core concepts involved in doing this are universal enough that they should be adaptable to any particular system. I agree that I'm probably assuming too much foreknowledge of the core 3d mathematics behind these notions, unfortunately - but that's a lot of background to try and fill in on the fly! – Steven Stadnicki May 9 '12 at 21:13

So, you have two problems you're trying to solve?

1. Determining the "most visible side of the cube."
2. Pointing that side at the camera.

Off the top of my head, if you were to determine the distances from the 8 vertices of the cube from the camera's location, the 4 least distances represent the quad that's mostly facing the camera. (There's probably a better way to do it but I'm not great a linear algebra.)

To point at the camera, align the surface normal of that cube face with a line from the center of the cube to the camera. (Or something similar constructing a LookAt matrix.)

-