# Missing z-axis rotation for transforming between two vectors

I'm trying to rotate a cube so that it's facing up, but am getting hung up on the final implementation details. It now reliably will rotate the x,y axis to the correct side, but the z-axis is never rotating (See photos of before and after rotation). When I'm using the code below I always get '0' for my rotationVector.z. What am I missing here?

// Define lookAt vector
lookAtVector = GLKVector3Make(0,0,1);

// Define axes vectors
axes[0] = GLKVector3Make(0,0,1);
axes[1] = GLKVector3Make(-1,0,0);
axes[2] = GLKVector3Make(0,1,0);
axes[3] = GLKVector3Make(1,0,0);
axes[4] = GLKVector3Make(0,-1,0);
axes[5] = GLKVector3Make(0,0,-1);

CGFloat highest_dot = -1.0;
GLKVector3 closest_axis;

for(int i = 0; i < 6; i++) {
// multiply cube's axes by existing matrix
GLKVector3 axis = GLKMatrix4MultiplyVector3(matrix, axes[i]);
CGFloat dot = GLKVector3DotProduct(axis, lookAtVector);
if(dot > highest_dot) {
closest_axis = axis;
highest_dot = dot;
}
}

GLKVector3 rotationVector = GLKVector3CrossProduct(closest_axis, lookAtVector);

// Get angle between vectors
CGFloat angle = atan2(GLKVector3Length(rotationVector), GLKVector3DotProduct(closest_axis, lookAtVector));

// normalize the rotation vector
rotationVector = GLKVector3Normalize(rotationVector);

// Create transform
CATransform3D rotationTransform = CATransform3DMakeRotation(angle,  rotationVector.x, rotationVector.y, rotationVector.z);

// add rotation transform to existing transformation
baseTransform = CATransform3DConcat(baseTransform, rotationTransform);
return baseTransform;


Before 3d Rotation

After 3d Rotation

Implementation based on this post

• I'm not familiar with ios really, but it sounds like what you're doing is trying to take a cube and make one particular side be facing the same plane that is defined by the camera's position and look vector, or possibly make the cubes face directly towards the camera (which might not be what you want)? Is this correct and if so, which of those operations are you trying to do? – Jeff Tucker Jun 4 '12 at 2:26
• Is your lookat vector supposed to change, ever? – indeed005 Jun 4 '12 at 5:24

lookAtVector = GLKVector3Make(0,0,1);
(...)
GLKVector3 rotationVector = GLKVector3CrossProduct(closest_axis, lookAtVector);


In 3D and higher dimensions, a cross-product returns a vector which is perpendicular to the two input vectors.

lookAtVector is defined as (0,0,1).

Hence, if you use it in a cross-product, no matter what the value of closest_axis might be, the result will have 0 as its z component, because if it did not, it would not be perpendicular to lookAtVector.

You don't say what you're actually trying to do, so I can't go on and explain how to actually do whatever your intent was. But I hope that the explanation of the maths is enough to help you solve your own issue, here!

• Thanks. Answer is spot on. I ended up getting another face that was orthogonal and using that vector to get the Z rotation. Then I could combine the two rotation matrices and get the rotation matrix I needed to rotate the cube to face the camera. Maybe not most efficient way to do it, but works great. – Steven Baughman Jun 7 '12 at 19:38

I don't think this is your entire problem, but you do at least need to be doing this:

CGFloat highest_abs_dot = 0.0;
GLKVector3 closest_axis;

for(int i = 0; i < 6; i++) {
// multiply cube's axes by existing matrix
GLKVector3 axis = GLKMatrix4MultiplyVector3(matrix, axes[i]);
CGFloat abs_dot = fabsf(GLKVector3DotProduct(axis, lookAtVector));
if(abs_dot > highest_abs_dot) {
closest_axis = axis;
highest_abs_dot = abs_dot;
}
}


Remember that there are 4 possible orientations of the cube for any given face 'up'.

I made a game of rotating cubes before (search 'Obecolo').

To avoid floating point approximation errors accumulating in each cubes model matrix, I set up a multiply-linked list of the 24 possible orientations. I.e., each entry would have links to the 'adjacent' orientations obtained by rotating +-90 degrees on each axis.

I built the list on startup, one antry at a time, by multiplying basic 'building block' matrices (i.e., 90, 180 or 270 rotation on X, Y or Z).

To write the code above, it helped a lot to have a cube on my desk with the faces labeled 'TOP', 'BOTTOM', 'LEFT', 'RIGHT', 'FRONT' and 'BACK'. Also, texturing the cube faces with colors that provide a visual cue: RED for +X (cyan for -X), GREEN for +Y (magenta for -Y) and BLUE for +Z (yellow for -Z).