# Re: Rotation always relative to the world

*From*: "punkrock" <punkrock@xxxxxxxxxxxxxxxxxxxxxxxxx>*Date*: Thu, 17 Nov 2005 00:22:07 -0800

As far as I know you can pretty much copy and paste the code into your

application (someone at MSFT please correct me if I've missed something

important in one of the licenses). The ModelViewerCamera is fairly dependent

on the DXUT framework, so you may want to stick with just the ArcBall. I'll

run over the methods you'll want to call, or perhaps modify.

If I'm being too detailed on anything, or repeating stuff you already know,

bear with me. I'd rather answer your question all at once than waiting for

you to get stumped and dragging the answer out over weeks.

I'll start with a little bit of theory. Quaternions are the preferred way to

work with complex rotations in 3D most 3D graphics applications. A quaternion

consists of 4 numbers (floats) and represents a rotation about an arbitrary

axis. You can multiply quaternions together to create a new quaternion that

expresses the result of a rotation about the first, and then about the

second, and you can convert them to matrices. The mathematics is fairly

involved (complex numbers, etc) but that's OK since the

Microsoft.DirectX.Quaternion struct has methods and operators to hide all of

that.

ArcBall translates 2D mouse input into 3D quaternion math. It basically

models the mouse rolling a virtual ball around. So start with an ArcBall:

By default the ArcBall initializes itself to work with the currently active

Form. If you're using a different Form or an embedded Control to host your 3D

content then you'll have to either modify its constructor to use the target

Control's dimensions instead (the SetWindow call is the important bit), or

you could call SetWindow on it yourself.

SetWindow gives the ArcBall the dinensions of the rectangle that the mouse

will be acting in, allowing it to scale the movement of the scene to match

the mouse's progress across the screen.

ScreenToVector constructs a vector that goes from the ArcBall's center (the

origin) to the point on the virtual sphere's surface that you clicked. If you

click outside of the sphere, the method will snap the vector to the nearest

point on the sphere (this allows you to drag outside the virtual sphere and

turn the scene like a knob, rather than just rolling it-this is an extra

degree of control that you get for free).

QuaternionFromBallPoints is the real worker method here. It takes two points

on the sphere (which is the same thing as the vectors that ScreenToVector

returns) and generates a quaternion that will rotate the sphere in such a way

that the first point will move to the location of the second point. The

rotation will always go the short way around the sphere.

The first line is just a dot product that gets the cos of the angle between

the vectors. The second line gets a vector that's perpendicular to both, this

vector points in the direction about which the sphere must be rotated. The

third line packs this all into a Quaternion. While it looks like the first

three paramaters are the xyz of the axis of rotation and the last one is the

angle, it doesn't exactly work like that in all cases. In this case it just

happens to (and if you need help understanding this I suggest you get a good

math book, or talk to a friend that's good with numbers, it's really too big

of a subject to even begin to cover here). If you want to change things to

use an axis vector and an angle, and you don't want to worry about it being

set up right, then I suggest you construct your Quaternion with the

RotateAxis function instead.

The remaining methods are designed to convert mouse drags into rotations,

and they rely on the above methods. I would suggest using them as they are

meant to be used and not faking them out with your own angleX, angleZ

values-if you do that then you'll lose the ability to turn the scene like a

knob, plus you'll negate all of the code that exists to keep the rotation in

sync with the mouse.

OnBegin gets the point where the mouse button was pressed and converts it

into a vector (call this the starting vector) using ScreenToVector. It also

saves a copy of the current rotation state.

After an OnBegin, whenever OnMove is called, the ArcBall gets the vector to

the new point. It uses QuaternionFromBallPoints to convert the starting

vector and the current vector into a rotation (which, unsurprisingly, rotates

the starting vector into the position of the current vector) and appends this

rotation to the starting rotation state to get the new current rotation state.

OnEnd clears the dragging flag and makes the ArcBall stop updating the

current rotation.

At any point you can get a matrix for all of this by reading the

RotationMatrix property.

The HandleMessages method is in there to support the DXUT framework. Once

you get set up calling OnBegin, OnMove, and OnEnd you're pretty much done and

you can ignore it, unless you want to check out how DXUT calls the ArcBall

methods.

The ModelViewerCamera does some fancy math on top of the ArcBall to add

translation and motion velocity, and to remove jitters from the final matrix

that would come from floating-point error. Unless you need velocity-based

motion for your camera, ignore it completely.

I hope I've given you enough to implement your solution.

.

**Follow-Ups**:**Re: Rotation always relative to the world***From:*6tc1

**References**:**Rotation always relative to the world***From:*6tc1

**Re: Rotation always relative to the world***From:*6tc1

- Prev by Date:
**Re: Rotation always relative to the world** - Next by Date:
**Re: Screensaver project - Compress File** - Previous by thread:
**Re: Rotation always relative to the world** - Next by thread:
**Re: Rotation always relative to the world** - Index(es):