Skip to main content
GameDev.net gamedev.net
🔒 Locked

Cross product question

Started by pjStyle Jan 20, 2010 at 5:56 AM 6 replies 1.5k views
Original Post
pjStyle
pjStyle
Hey there, Im creating a little prototype at the moment and have run into some trouble. In the prototype the player is able to move across the sides of a cube. Now i want to create a nice little rotation effect when of the borders is reached. How i have it set up now is as follows: * Every side of the cube is assigned a normal. * When the border of a side is reached the normals of the two adjacent sides are placed into a cross product. Now this works in some situations, but the cross product should only produce rotations across the X and Y axis. For example the front side has a normal of (0,0,1) and the side on the left has a normal of (-1,0,0). Now taking the cross product of these produces a rotation across the Y axis what i would expect. Now when the normals (-1,0,0) and (0,1,0), or in other words moving from the left side to the top side, are placed in the cross product this resulsts in a rotation across the Z axis. My question is, am i using the correct method of determining these rotations by using normals? Or is there another way? Thanks in advance!
remigius
remigius

You're close [smile]

The vector produced by a crossproduct on 3D vectors is essentially the axis of rotation between the two input vectors. If you calculate crossproduct C as A x B, then you end up with axis of rotation C, around which you could rotate vector A some amount of degrees to end up with B, and viceversa. To illustrate for your examples:



In the lefthand situation, the axis of rotation between (0,0,1) and (-1,0,0) is indeed the Y axis. You can rotate (0,0,1) about the Y axis by 90 degrees, so in the XZ plane, to end up with (-1,0,0). The same goes for the righthand situation. By rotating (-1,0,0) 90 degrees around the Z axis, you'll end up with (0,1,0). This is the basic significance and use of the crossproduct for 3D vectors.

To actually apply this to your situation, you can use the crossproduct to find this axis of rotation. Once you have that you can construct a rotation matrix using common utility functions to create this from the axis and some angle (for example D3DXMatrixRotationAxis). It might help to visualize that this axis of rotation you end up with is essentially the edge between two sides.

Since you're dealing with a cube, the 'rotation' when moving from one side to the other would be instantaneous (there is no average normal between the two perpendicular sides). So you'll probably want to fake it by rotating to the new side over say one second. To achieve this, you can supply some time variable as the angle, so the matrix makes the object gradually rotate from one orentation to the next.

I hope this helps somewhat or is even intelligible [wink]
pjStyle
pjStyle
Alright great, i'll see if i can get it working tonight!
haegarr
haegarr
Another caveat that may introduce misunderstanding is the difference between the local and the global space of co-ordinates. Let us assume that the avatar should always walk on the side in front of the camera, so that the rotation has to ensure that those side is always visible. Then you ever have to rotate using the global x or y axes, but never global z. However, the local axes may be any of x, y, and z. Since you should rotate incrementally, you will ever have to expand the overall rotation by another global rotation. Hence rotation around z should never occur in this scenario.
pjStyle
pjStyle
haegarr,

What you mentioned is spot on, that's exactly what is happening now. Hopefully everything will be working fine tonight.

Thanks for the replies!
pjStyle
pjStyle
Couldnt get it working just yet. Any more tips what i should try next?

I would like to be able to determine if i need to rotate across the X or Y axis depending on the side im on and the side im moving to. Anyone have an idea how i would do this?
Zakwayda
Zakwayda
Quote:
Couldnt get it working just yet. Any more tips what i should try next?

I would like to be able to determine if i need to rotate across the X or Y axis depending on the side im on and the side im moving to. Anyone have an idea how i would do this?
I didn't follow everything in the previous posts, but when say 'rotate across the X or Y axis', I assume you're referring to rotations about your character's local X and Y axes? I ask because in the scenario you describe, it seems that rotations could occur about any of the three cardinal world axes (including Z).

Personally I would approach this as more of an 'alignment' problem, and apply incremental rotations as necessary to keep the character aligned with the surface below him. In this scenario those will typically be 90 degree rotations about the X, Y, or Z world axes; if applied over a short amount of time (say, a second), this should give the 'rotation' effect you're looking for.

As mentioned, the angle for these rotations will be 90 degrees. The axis will be the cross product of the normal of the previous surface (which should be more or less the same as the character's current world-space 'up' vector), and the normal of the new surface.
Oogst
Oogst
Even though I actually saw your game running a while ago, I am still not 100% sure I understand what the problem is. I think this is what you mean:

The camera is looking at the cube from a fixed position and you want to rotate the cube in such a way that the side with the character on it is always facing the camera. So when you say that you want to rotate over X and Y but not over Z, you actually mean that in world space. I think that is the key observation here: if you just store the normals of the cube and do a cross product with them, then you are using object space normals, which is not good.

In object space, you might jump from one side of the cube to another to generate a z-rotation. But in world space you can never do that, because the starting side of the jump is always facing the camera, so the movement that would generate a z-axis-rotation is not possible, because that is from one side that is not facing the camera to another side that is not facing the camera.

So, as for a solution: if you have the current rotation matrix of your cube, then you can multiply the local normals of the sides that involve the jump by the rotation matrix. You then have world normals and a cross-product of those should never generate a z-rotation-axis. So, in pseudo-code:

Matrix3x3 cubeRotationMatrix;Vector3 jumpStartNormal, jumpEndNormal;Vector3 jumpStartNormalWorldSpace = cubeRotationMatrix * jumpStartNormal;Vector3 jumpEndNormalWorldSpace = cubeRotationMatrix * jumpEndNormal;Vector3 rotationAxis = jumpStartNormalWorldSpace.crossProduct(jumpEndNormalWorldSpace);


One final thing: the user will want to be able to quickly jump between sides and you definitely need a smooth rotation of the cube. Not just instantly switching which side you see, because that is disorienting. But what if the user jumps to another side while the interpolated rotation is still happening? If the user jumps back and forth between two sides, then you can simply invert the rotation matrix you are smoothly applying, but if he quickly jumps between three sides (at a corner), then you will end up with a pretty nasty kind-of-random orientation after that.

I think the easiest solution is this: calculate a quaternion for the desired rotation (with the correct side facing the camera). Then get the quaternion for the current rotation of the cube. Then do a quaternion lerp to smoothly go from the current rotation to the desired new rotation. Note that quaternion lerp is not just a linear interpolation of the numbers: the code is pretty difficult, but you can find it in any math library or rip it from a million places on the 1nt3rw3bz0rz.

(I hope I actually understood your problem correctly, because otherwise I have been wasting a lot of Typing Power here. :P )

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.