Question

Imagine a cube with each of 6 walls in a different color. The cube rotates in random directions around its center point. When a user clicks or taps a screen, the rotation stops instantly. The cube is frozen in a random position. After the user releases mouse button or moves finger up from the screen, the cube should 'straighten', what means it should rotate around some axis by the smallest possible angle, just enough to present the most visible cube wall in the 'screen plane' the way that all edges are parallel to the edges of the screen.

Is there a way to find this closest 'straight' rotation, assuming that we have an access to the 'frozen' position given either by a rotation matrix, or by a quaternion (whichever is more convenient)?

Was it helpful?

Solution

One way of looking at the top 3x3 portion of a matrix is that it's just a description of the basis vectors as, if you were to apply one to a point:

[A D G] [x]   [A*x + D*y + G*z]       [A]       [D]       [G]
[B E H] [y] = [B*x + E*y + H*z] = x * [B] + y * [E] + z * [H]
[C F I] [z]   [C*x + F*y + I*z]       [C]       [F]       [I]

i.e. if you apply that matrix then the input x axis will end up running along (A, B, C), the input y axis will end up running along (D, E, F) and the input z axis will end up running along (G, H, I).

What I think you're asking is equivalent to "which axis has the least change along output z, i.e. is closest to perpendicular to the screen"? So you can determine that by looking for the value from (C, F, I) that has the least magnitude.

You can then use the z sign of the cross product of (A, B, C) and (D, E, F) to decide whether you're looking along the axis positively or negatively by the same logic that allows you to use that test for reverse face removal — whichever face would be visible if the camera were hypothetically moved backward to infinity is the one genuinely in front.

That also suggests an alternative test which you may prefer: do the transform and the face closest to perpendicular is whichever is visible and largest. It's the same logic behind the Lambert lighting model, with the fact that the faces were of a uniform size in the first place factored in. The advantage of that test is that you could do it directly on the GPU using the occlusion query, assuming none of them is actually occluded.

OTHER TIPS

Simple solution.

1) Find the required wall, and construct vector from cube center to center of wall, let it be dir1

2) vector from cube center to camera, let it be dir2

3) Build quaternion "rotation_arc" between this vectors. http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

4) rotate cube by quaternion from "3)"

To find wall : Build 6 vectors from center of cube to centers of walls. Than build vector from center of cube to camera. Estimate 6 angles between first vectors and second vector and select wall with smallest angle.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top