Jump to content
  • Advertisement
Sign in to follow this  
McFury

Camera woes, need help

This topic is 3206 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I have a camera for my scene that revolves around objects in game. I am trying to implement a feature that is the same as the middle-mouse click in google earth. As in, once clicked, the up-down mouse movement rotates the camera up-down the object about the clicked focus point. Also the left-right mouse movement rotates the object about an axis from the clicked point to the centre of the object. I am using quaternions to represent the rotation (using angle / axis to constructed them). I can get both parts working, but there are some issues. 1) With the up-down movement, I currently do not clamp it to any angle. I noticed that google earth has a way to 'lock' the angle to a specific value. As in where you clicked, you cannot rotate further upwards, but you can rotate downwards. You can rotate back up, but not beyond a specific angle value. I am not sure what is happening there or how it is achieved. How would they determine that tilt angle to clamp to? Or be able to reset to that tilt? 2) If I use either in isolation (left-right or up-down) they work fine, however, if I apply both at the same time (each one applies a rotation and a translation seperately one after the other), I can notice that the object starts drifting off-centre of the screen. So if I move the mouse in rapid diagonal movements then it slowly goes to hell. I am not sure how to address this problem, as I dont see how either a stationary rotation on an axis (left-right movement) or rotation on a focus click point (up-down movement) could cause it to drift. To do the up-down movement I am using the current -right vector of the camera as the axis of rotation and the delta mouse movement as the angle. To do the left-right movement I am using a unit vector from the centre of the object pointing to the clicked point as the axis of rotation and the delta mouse movement as the angle. I would be greatful for any help, thank you.

Share this post


Link to post
Share on other sites
Advertisement
How are you generating your rotations and when? It sounds like you are generating them with each movement of the mouse and then accumulating them over the life of the app?

Share this post


Link to post
Share on other sites
Correct, I am generating a rotation from an angle axis each time there is mouse movement. i.e. (not exact code, just off top of my head)



// where angleUpDown is derived from mouse movement

Matrix rot;
Quaternion q(angleUpDown, focusPointAxis);
q.Normalize();
q.ToMatrix(rot);

currentTranform.m_rotate = rot * currentTranform.m_rotate;

etc

Share this post


Link to post
Share on other sites
Ive had better luck with controlling camera angles by simply tracking and summing the angles (clamping to 0 - 360, or whatever) and then generating a new orientation from the angles each frame in an update call.
So you yaw about the object, mYaw += mouseMoveAngleAmount, etc, then in update, generate your yaw, pitch, roll quaternions and concatenate and use the new result for your view.
For your google middle mouse down movement, which after looking at it seems like a -90 rotate down (and back restriction), you can save the current pitch angle (which youre tracking) when middle mouse goes down, and then in your mAngle += move calls (where mAngle is one of yaw, roll, pitch), makes sure that the movement doesnt go below mAngle - 90 or greater then mAngle as long as middle mouse is down.
Reconstructing the orientation once each frame from clean float angles should eliminate your drifting problem, instead of modifying it slightly each mouse movement.

Share this post


Link to post
Share on other sites
Thanks for your feedback, it's slightly difficult for me to visualize as I was also using the rotation increment to alter the camera position:


Matrix rot;
Quaternion q(angleUpDown, focusPointAxis);
q.Normalize();
q.ToMatrix(rot);

currentTranform.m_rotate = rot * currentTranform.m_rotate;
currentPosition = rot * currentPosition;

So now I am unsure about generating the new camera postion from it:



// where 'inputValues' gets cleared at the end of each update so doesnt stack.
if (inputValues[LEFT_RIGHT_MOUSE] != 0.0f)
m_yaw += inputValues[LEFT_RIGHT_MOUSE];


if (m_inputValues[UP_DOWN_MOUSE] != 0.0f)
m_pitch += inputValues[UP_DOWN_MOUSE];


Matrix rot;

Quaternion yawQ(m_yaw, pickPointToCentreAxis);
yawQ.Normalize();
yawQ.ToMatrix(rot);


//currentPosition = rot * currentPosition; ??


Quaternion pitchQ(m_pitch, cameraNegRightVecAxis);
pitchQ.Normalize();
pitchQ.ToMatrix(rot);


//Vector3 clickPos = currentPosition - m_pickPointStart;
//clickPos = rot * clickPos;
//currentPosition = m_pickPointStart + clickPos; ??


(yawQ * pitchQ).ToMatrix(currentTranform.m_rotate);



Sorry im just a tad confused, any more help would be great, thanks.

Share this post


Link to post
Share on other sites
Im not sure what your complete feature set is going to be so I can only provide info on what Ive done that is similar, even then it may be done entirely different.
My camera implementation is basically a generic node that moves differently, so it has a parent potentially that affects its position or its just in the world, so it can be attached to things that move.
My nodes have a quaternion r, and a translation vector t. These are considered the local node (camera) orentiation. World version of these are derived on update, and when rendering, the world versions are used to create a 4x4 matrix, which is usually just used for rendering.
But the camera moves different, it has extra members like Yaw(degAng), Pitch(degAng), etc which just take an angle from input when a key is pressed.
The derived camera which is like an orbiting third person camera has 3 extra members float mYaw, mPitch, mOffsetRadius. When Yaw() is called (rotate left and right around) i just do something like


Yaw(degrees)
{
mYaw += degrees;
if(mYaw > 360.0) // continue in positve direction at > 360 overflow
mYaw = mYaw - 360.0;
else if(mYaw, < -360.0) // continue negative rotation < -360 overflow
mYaw = mYaw + 360.0;
}



where if this was a pitch call you might limit it to 0 - 180 range so you dont end up upside down. Then I override my _UpdateTransform() call


_UpdateTransform()
{
pt3 pos = SphericalToCartesian(mOffsetRadius, mYaw, mPitch)

mLocal.t = pos; // this will translate the camera off its target for now

// I then generate an orientation that will "reaim" the camera at its target
// which in this setup, has the affect of aiming at its parents orgin

quaternion ryaw;
// <- some +/- 180 are done here to create "yawToAim" from mYaw ->
ryaw.FromAxisAngle(UNITY, TORAD(yawToAim);

quaternion rpitch;
// <- some checks and +/- 90s/180s are done here to create "pitchToAim" from mPitch
ryaw.FromAxisAngle(UNITX, TORAD(pitchToAim);

mLocal.r = ryaw * rpitch;

// call here to base class _UpdateTransform() which would derive and store
// mWorld from mLocal and parent (if any), and the matrix would be generated
// and cached when asked for
}



now this code just illustrates the idea, your implementation is different from mine so i left it as slim as possible just to show the idea. When youre trying to restrict movement, its very easy to do when you have the angles, rather then having a full orientation, which could have been assembled from any number of angles and methods.
The general idea is
1) collect the input
2) limit/restrict it in some way if need be
3) on update, generate the new orientation
4) use it
5) repeat, throwing out the resulting orientation from 3), and regenerating next time using the old values clamped and wrapped in combination with new input values

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!