Rotating a Dial with a mouse

Started by
8 comments, last by Ezbez 16 years, 10 months ago
Dear All, This seems like an easy question, but I cannot seem to solve it properly. I would like to be able to have the user rotate a turn a dial either direction with a mouse. So I have the vector the dial is currently pointing in, and I have the vector from the center of the dial to the mouse pointer. So my first thought was to use the dot product property to find the angle between the two, then rotate the dial by that amount. Unfortuantly in real code this doesnt seem to work, as acos only goes from [0,pi]. When I rotate the dial 180 degrees, the dial starts rotating back the opposite direction, instead of continuing though the 360. I'm not sure how to remedy this. It seems like it should be an easy task, but I just cant think of the solution and I've wasted alot of time playing with this. Can anyone give me a hand? Thanks, J.
Advertisement
Can't you just set the dial's rotation to the rotation from the center to the mouse?
Maybe my brain is a little fogged, but wouldnt that involve the same set of vector calculations?
AFAIK, in any nice vector program it would be as easy as:

dialRotationVector = toMouseRotationVector;

I mean that you should, quite literally, replace the dial's rotation with the rotation to the mouse, not transform the dial's rotation to the rotation of the mouse.
Well the dial isnt acctually drawn with a vector, its drawn as a quad, and I need a rotation angle to build transform.
I've had this problem, as I recall.

If I recall correctly, you should be able to check your mouse vector components to determine which quadrant you are in, and if it is in the problem region subtract the angle that you calculated from 2*PI.

For instance, if you take your angles relative to a vector pointing directly up from the point of origin, increasing clockwise, and with right being along the positive x-axis, then I think that you should test your vector's x-coordinate and perform the above modification when it is negative.

To do this for two arbitrary vectors, subtract the first angle from the second to transform yourself to a system in which you have one vector relative to your reference vector (the vector which is at 0 radians, that is - the vertical vector mentioned above, for instance), and then simply check your vector components.

(I may be off in terms of which coordinate to test, or whether to test for negative or positive sign, but the principle should be sound, I believe. The specifics may well depend on your set-up.)

MWAHAHAHAHAHAHA!!!

My Twitter Account: @EbornIan

When checking the quandrants you didnt have any issues with the floating point making it skip just a bit when you crossed over?
Not that I recall, but it has been a while since I did it, I think, and in the last case in which I implemented this I was using a scripting language, so some correction may have occurred under the hood (although this seems unlikely to me).

Of course, I may have simply not noticed.

If you haven't already, give it a try - it shouldn't be too hard to implement, I don't think - and see whether a noticeable skip occurs. If you have tried it, how big a skip was it?

MWAHAHAHAHAHAHA!!!

My Twitter Account: @EbornIan

small but noticable.
Assuming that this is entirely 2D (eg: a GUI, not a valve in a game), here's the way that I'd do it in pseudo code:

mousePos = position of the mousedialCenter = position of the center of the dialdialRot = the number of radians the dial is rotatedslope = (mousePos.y - dialCenter.y) / (mousePos.x - dialCenter.x)angleToMouse = atan( slope )dialRot = angleToMouse//Now, when we draw the dial:dialTransform = transform matrix of dialdialTransform.rotate(dialRot, 0,0,-1)


Even better, use atan2( mousePos.y - dialCenter.y, mousePos.x - dialCenter.x) in C++ since atan2 will a) check for dividing by zero and b) take whichever quadrant you are in into account (which the above code is currently not doing).

This topic is closed to new replies.

Advertisement