Clamp rotatation angle of a rigid body - c++

I recently attached a rigid body to the camera in my 3d game, so that it can collide with the environment. By now mouse movement directly rotates the rigid body.
#include <BULLET/btBulletDynamicsCommon.h>
void Rotate(float Pitch, float Yaw, float Roll, float Speed)
{
// get current rotation
btTransform transform = body->getWorldTransform();
btQuaternion rotation = transform.getRotation();
// create orientation vectors
btVector3 up(0, 1, 0);
btVector3 lookat = quatRotate(rotation, btVector3(0, 0, 1));
btVector3 forward = btVector3(lookat.getX(), 0, lookat.getZ()).normalize();
btVector3 side = btCross(up, forward);
// rotate camera with quaternions created from axis and angle
rotation = btQuaternion(up, Amount.getY()) * rotation;
rotation = btQuaternion(side, Amount.getX()) * rotation;
rotation = btQuaternion(forward, Amount.getZ()) * rotation;
// set new rotation
transform.setRotation(rotation);
body->setWorldTransform(transform);
}
I would like to clamp the pitch of the camera in the range of -80° to 80°. That helps the player to stay oriented. Otherwise he would be able to rotate the camera higher over his head and see the world behind himself upside down. In contrast a real person trying this would break his neck.
I let Bullet Physics store rotations for me in quaternions, thus pitch isn't stored directly. How can I clamp the pitch of a rigid body?

I came up with a solution. Instead of clamping the rotation of the camera's rigid body, I clamp how much rotation is applied before. Therefore, I keep track of the total vertical mouse movement. Actually, I store the overall mouse movement with applied sensitivity.
float Overallpitch = 0.0f;
If applying the passed yaw value would result in the overall pitch to exceed or deceed a given limit, I just apply as much of it as needed to touch the limit.
#include <BULLET/btBulletDynamicsCommon.h>
void Rotate(float Pitch, float Yaw, float Roll, float Sensitivity)
{
// apply mouse sensitivity
Yaw *= Sensitivity;
Pitch *= Sensitivity;
Roll *= Sensitivity;
// clamp camera pitch
const float clamp = 1.0f;
if (Overallpitch + Pitch > clamp) Pitch = clamp - Overallpitch;
else if(Overallpitch + Pitch < -clamp) Pitch = -clamp - Overallpitch;
Overallpitch += Pitch;
// apply rotation to camera quaternion
// ...
}
You can find the further camera code in another answer to my own question.

Related

How to set the pitch, yaw, roll of a quaternion relative to the world

So I have a quaternion that stores the orientation of an object and I have functions to change the pitch, yaw and roll of the quaternion like so:
void pitch(float amount)
{
orientation *= glm::angleAxis(glm::radians(amount), glm::vec3(1, 0, 0));
}
void yaw(float amount)
{
orientation *= glm::angleAxis(glm::radians(-amount), glm::vec3(0, 1, 0));
}
void roll(float amount)
{
orientation *= glm::angleAxis(glm::radians(amount), glm::vec3(0, 0, -1));
}
What I want to do is set the pitch, yaw and roll relative to the world instead of adding to the current orientation. What I mean by that is right now, say I have a roll of 90*. Each time I use my pitch function and pass 45* into it, the roll will turn into 135* then 180* and so on.
What I want the set pitch function to do is when I pass 45* into it, it will set the roll of the quaternion to 45* and still keep the pitch and yaw.
I made a better explanation in my comment below.
So to picture what I'm trying to do, imagine 4 walls around you with pictures hanging of an arrow pointing to the world up. What I want to do is no matter what the pitch, yaw and roll of the quaternion, if I'm looking at any of the hanging pictures (any yaw) but with a little roll (so the arrow will point anywhere but up). If I use the setRoll function and pass 0*, the object should see the arrow pointing up. If I pass 90* to the setRoll function, no matter how many times I call the function it should set the object's rotation to 90* so the arrow will point to the left.
Thanks to Thomas' answer, I now have this code, but sadly it still doesn't work correctly:
void Camera::setPitch(float amount)
{
glm::vec3 globalUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 globalRight = glm::vec3(1.0f, 0.0f, 0.0f);
// "The pitch is the angle between the front vector and the horizontal plane. This is pi/2 minus the angle between the front vector and the global up vector."
float currentPitch = 3.14f / 2.0f - glm::acos(glm::dot(direction, globalRight));
// "To find the angle over which you need to rotate, compute the current pitch, and subtract this from the target pitch."
amount = currentPitch - amount;
// "To set the pitch without affecting roll and yaw, you'll want to rotate around an axis that lies in the horizontal plane and is orthogonal to the front vector. For a vector to lie in a plane, it means that it's orthogonal to the plane's normal, so we're looking for a vector that is orthogonal to both the global up vector and the front vector. That's just the cross product of the two."
glm::quat rotation = glm::angleAxis(glm::radians(amount), glm::cross(globalUp, direction));
orientation *= rotation;
updateCameraVectors();
updateViewMatrix();
}
void Camera::setYaw(float amount)
{
glm::vec3 globalUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 globalRight = glm::vec3(1.0f, 0.0f, 0.0f);
// "The yaw is the angle between the projection of the front vector onto the global horizontal plane, and some global "zero yaw" vector that also lies in the global horizontal plane. To project the front vector onto the global horizontal plane, simply set its vertical coordinate to zero."
float currentYaw = 3.14f / 2.0f - glm::acos(glm::dot(direction, globalRight));
// "To find the angle over which to rotate, compute the current yaw and subtract this from the target yaw."
amount = currentYaw - amount;
// "To change the yaw, simply rotate around the global up vector."
glm::quat rotation = glm::angleAxis(glm::radians(amount), globalUp);
orientation *= rotation;
// "Note that yaw is ill-defined when looking straight up; in that case, you can maybe set the roll instead, because the two are essentially the same."
// TODO...
updateCameraVectors();
updateViewMatrix();
}
void Camera::setRoll(float amount)
{
glm::vec3 globalUp = glm::vec3(0.0f, 1.0f, 0.0f);
// "The roll is the angle between the local right vector and the global up vector, minus pi/2"
float currentRoll = glm::acos(glm::dot((right, globalUp)) - 3.14f / 2.0f;
// "To find the angle over which to rotate, compute the current roll and subtract this from the target roll."
amount = currentRoll - amount;
// "To change the roll, you'll want to rotate around the local front vector."
glm::quat rotation = glm::angleAxis(glm::radians(amount), direction);
orientation *= rotation;
updateCameraVectors();
updateViewMatrix();
}
So here's my understanding of what you're trying to do. You have a unit quaternion orientation. You can picture this as a "front" vector pointing out from your eyes, and an "up" vector pointing out of the top of your head. From these follows a "right" vector pointing out your right ear.
You didn't explain your coordinate system, so I'll keep this in pretty generic terms. And this post is more of a "how to think about the problem" rather than working code, but I hope that's at least as useful in the long term.
Pitch
The pitch is the angle between the front vector and the horizontal plane. This is pi/2 minus the angle between the front vector and the global up vector.
To set the pitch without affecting roll and yaw, you'll want to rotate around an axis that lies in the horizontal plane and is orthogonal to the front vector. For a vector to lie in a plane, it means that it's orthogonal to the plane's normal, so we're looking for a vector that is orthogonal to both the global up vector and the front vector. That's just the cross product of the two.
To find the angle over which you need to rotate, compute the current pitch, and subtract this from the target pitch.
Yaw
The yaw is the angle between the projection of the front vector onto the global horizontal plane, and some global "zero yaw" vector that also lies in the global horizontal plane. To project the front vector onto the global horizontal plane, simply set its vertical coordinate to zero.
To change the yaw, simply rotate around the global up vector.
To find the angle over which to rotate, compute the current yaw and subtract this from the target yaw.
Note that yaw is ill-defined when looking straight up; in that case, you can maybe set the roll instead, because the two are essentially the same.
Roll
The roll is the angle between the local right vector and the global up vector, minus pi/2.
To change the roll, you'll want to rotate around the local front vector.
To find the angle over which to rotate, compute the current rol and subtract this from the target roll.

OpenGL camera rotation using gluLookAt

I am trying to use gluLookAt to implement an FPS style camera in OpenGL fixed function pipeline. The mouse should rotate the camera in any given direction.
I store the position of the camera:
float xP;
float yP;
float zP;
I store the look at coordinates:
float xL;
float yL;
float zL;
The up vector is always set to (0,1,0)
I use this camera as follows: gluLookAt(xP,yP,zP, xL,yL,zL, 0,1,0);
I want my camera to be able to be able to move along the yaw and pitch, but not roll.
After every frame, I reset the coordinates of the mouse to the middle of the screen. From this I am able to get a change in both x and y.
How can I convert the change in x and y after each frame to appropriately change the lookat coordinates (xL, yL, zL) to rotate the camera?
Start with a set of vectors:
fwd = (0, 0, -1);
rht = (1, 0, 0);
up = (0, 1, 0);
Given that Your x and y, taken from the mouse positions You mentioned, are small enough You can take them directly as yaw and pitch rotations respectively. With yaw value rotate the rht and fwd vectors over the up vector, than rotate fwd vactor over the rht with pitch value. This way You'll have a new forward direction for Your camera (fwd vactor) from which You can derive a new look-at point (L = P + fwd in Your case).
You have to remember to restrict pitch rotation not to have fwd and up vectors parallel at some point. You can prevent that by recreating the up vector every time You do pitch rotation - simply do a cross product between rht and fwd vactors. A side-note here though - this way up will not always be (0,1,0).

Rotation About Incorrect Axes (First-Person Camera Implementation)

I am implementing a first-person camera to move about a scene using the arrow keys on my keyboard. It seems to work OK when I am only rotating about a single axis (X or Y), however if I am rotating about both axes it also gives me rotation about the third, Z, axis. I am fairly sure that the problem is that my camera does not rotate about global axis but instead its local ones, resulting in 'roll' when I just want yaw and pitch. In my code I deduce a forward vector from the X and Y rotation, stored in two variables. The most relevant code snippet is as follows:
glm::mat4 CameraManager::rotateWorld(float angle, glm::vec3 rot){
static float yRot = 0.0f;
static float xRot = 0.0f;
glm::vec3 degrees = rot * angle;
glm::vec3 radians = glm::vec3(degrees.x * (M_PI/180.0f),
degrees.y * (M_PI/180.0f),
degrees.z * (M_PI/180.0f));
yRot += radians.y;
xRot += radians.x;
forwardVector = glm::vec3(sinf(yRot) * cosf(xRot),
-sinf(xRot),
-cosf(yRot) * cosf(xRot));
return glm::rotate(glm::mat4(1.0f), angle, rot);
}
the rotateWorld function is complemented by the moveForwardfunction:
glm::mat4 CameraManager::moveForward(float dist){
glm::vec3 translation = forwardVector/glm::vec3(sqrt(forwardVector.x * forwardVector.x +
forwardVector.y * forwardVector.y +
forwardVector.z * forwardVector.z)) * dist;
return glm::translate(glm::mat4(1.0f), -translation);
}
where yRot is equivalent to yaw and xRot is equivalent to pitch.
The rotation and translation matrices are simply multiplied together in the main section of the program.
I then go on to multiply a distance d by this vector to update the position.
xRot and yRot are static doubles that get incremented/decremented when the user presses an arrow key.
When the program starts, this is the view. The plane and the monkey head are facing the 'right way' up. incrementing/decrementing the pitch and yaw individually work as expected. But when I, say, increase the pitch and then yaw, the scene flips sideways! (Picture below.) Any ideas how to fix this?
If I understand you correctly, the problem you're experiencing is that your "up" vector is not always pointing vertically upwards with respect to the intended Y axis of your viewing plane.
Determining a correct "up" vector usually requires a combination of cross product operations against the vector you have against the viewport's X and Y axes.
You may find some useful hints in the documentation for the gluLookAt function whose purpose is to calculate a view matrix with desired orientation (i.e. without roll) given an eye position and the coordinates of the intended centre of the field.

Issue with GLM Camera X,Y Rotation introducing Z Rotation

So I've been having trouble with a camera I've implemented in OpenGL and C++ using the GLM library. The type of camera I'm aiming for is a fly around camera which will allow easy exploration of a 3D world. I have managed to get the camera pretty much working, it's nice and smooth, looks around and the movement seems to be nice and correct.
The only problem I seem to have is that the rotation along the camera's X and Y axis (looking up and down) introduces some rotation about it's Z axis. This has the result of causing the world to slightly roll whilst travelling about.
As an example... if I have a square quad in front of the camera and move the camera in a circular motion, so as if looking around in a circle with your head, once the motion is complete the quad will have rolled slightly as if you've tilted your head.
My camera is currently a component which I can attach to an object/entity in my scene. Each entity has a "Frame" which is basically the model matrix for that entity. The Frame contains the following attributes:
glm::mat4 m_Matrix;
glm::vec3 m_Position;
glm::vec3 m_Up;
glm::vec3 m_Forward;
These are then used by the camera to create the appropriate viewMatrix like this:
const glm::mat4& CameraComponent::GetViewMatrix()
{
//Get the transform of the object
const Frame& transform = GetOwnerGO()->GetTransform();
//Update the viewMatrix
m_ViewMatrix = glm::lookAt(transform.GetPosition(), //position of camera
transform.GetPosition() + transform.GetForward(), //position to look at
transform.GetUp()); //up vector
//return reference to the view matrix
return m_ViewMatrix;
}
And now... here are my rotate X and Y methods within the Frame object, which I'm guessing is the place of the problem:
void Frame::RotateX( float delta )
{
glm::vec3 cross = glm::normalize(glm::cross(m_Up, m_Forward)); //calculate x axis
glm::mat4 Rotation = glm::rotate(glm::mat4(1.0f), delta, cross);
m_Forward = glm::normalize(glm::vec3(Rotation * glm::vec4(m_Forward, 0.0f))); //Rotate forward vector by new rotation
m_Up = glm::normalize(glm::vec3(Rotation * glm::vec4(m_Up, 0.0f))); //Rotate up vector by new rotation
}
void Frame::RotateY( float delta )
{
glm::mat4 Rotation = glm::rotate(glm::mat4(1.0f), delta, m_Up);
//Rotate forward vector by new rotation
m_Forward = glm::normalize(glm::vec3(Rotation * glm::vec4(m_Forward, 0.0f)));
}
So somewhere in there, there's a problem which I've been searching around trying to fix. I've been messing with it for a few days now, trying random things but I either get the same result, or the z axis rotation is fixed but other bugs appear such as incorrect X, Y rotation and camera movement.
I had a look at gimbal lock but from what I understood of it, this problem didn't seem quite like gimbal lock to me. But I may be wrong.
Store the current pitch/yaw angles and generate the camera matrix on-the-fly instead of trying to accumulate small changes on the intermediate vectors.
In your RotateY function, change it from this:
glm::mat4 Rotation = glm::rotate(glm::mat4(1.0f), delta, m_Up);
to this:
glm::mat4 Rotation = glm::rotate(glm::mat4(1.0f), delta, glm::vec3(0,1,0));

OpenGL camera - View matrix from quaternion behaves incorrectly and pitch is too restricted

I'm creating the view matrix for my camera using its current orientation (quaternion) and its current position.
void Camera::updateViewMatrix()
{
view = glm::gtx::quaternion::toMat4(orientation);
// Include rotation (Free Look Camera)
view[3][0] = -glm::dot(glm::vec3(view[0][0], view[0][1], view[0][2]), position);
view[3][1] = -glm::dot(glm::vec3(view[1][0], view[1][1], view[1][2]), position);
view[3][2] = -glm::dot(glm::vec3(view[2][0], view[2][1], view[2][2]), position);
// Ignore rotation (FPS Camera)
//view[3][0] = -position.x;
//view[3][1] = -position.y;
//view[3][2] = -position.z;
view[3][3] = 1.0f;
}
There is a problem with this in that I do not believe the quaternion to matrix calculation is giving the correct answer. Translating the camera works as expected but rotating it causes incorrect behavior.
I am rotating the camera using the difference between the current mouse position and the the centre of the screen (resetting the mouse position each frame)
int xPos;
int yPos;
glfwGetMousePos(&xPos, &yPos);
int centreX = 800 / 2;
int centreY = 600 / 2;
rotate(xPos - centreX, yPos - centreY);
// Reset mouse position for next frame
glfwSetMousePos(800 / 2, 600 / 2);
The rotation takes place in this method
void Camera::rotate(float yawDegrees, float pitchDegrees)
{
// Apply rotation speed to the rotation
yawDegrees *= lookSensitivity;
pitchDegrees *= lookSensitivity;
if (isLookInverted)
{
pitchDegrees = -pitchDegrees;
}
pitchAccum += pitchDegrees;
// Stop the camera from looking any higher than 90 degrees
if (pitchAccum > 90.0f)
{
//pitchDegrees = 90.0f - (pitchAccum - pitchDegrees);
pitchAccum = 90.0f;
}
// Stop the camera from looking any lower than 90 degrees
if (pitchAccum < -90.0f)
{
//pitchDegrees = -90.0f - (pitchAccum - pitchDegrees);
pitchAccum = -90.0f;
}
yawAccum += yawDegrees;
if (yawAccum > 360.0f)
{
yawAccum -= 360.0f;
}
if (yawAccum < -360.0f)
{
yawAccum += 360.0f;
}
float yaw = yawDegrees * DEG2RAD;
float pitch = pitchDegrees * DEG2RAD;
glm::quat rotation;
// Rotate the camera about the world Y axis (if mouse has moved in any x direction)
rotation = glm::gtx::quaternion::angleAxis(yaw, 0.0f, 1.0f, 0.0f);
// Concatenate quaterions
orientation = orientation * rotation;
// Rotate the camera about the world X axis (if mouse has moved in any y direction)
rotation = glm::gtx::quaternion::angleAxis(pitch, 1.0f, 0.0f, 0.0f);
// Concatenate quaternions
orientation = orientation * rotation;
}
Am I concatenating the quaternions correctly for the correct orientation?
There is also a problem with the pitch accumulation in that it restricts my view to ~±5 degrees rather than ±90. What could be the cause of that?
EDIT:
I have solved the problem for the pitch accumulation so that its range is [-90, 90]. It turns out that glm uses degrees and not vectors for axis angle and the order of multiplication for the quaternion concatenation was incorrect.
// Rotate the camera about the world Y axis
// N.B. 'angleAxis' method takes angle in degrees (not in radians)
rotation = glm::gtx::quaternion::angleAxis(yawDegrees, 0.0f, 1.0f, 0.0f);
// Concatenate quaterions ('*' operator concatenates)
// C#: Quaternion.Concatenate(ref rotation, ref orientation)
orientation = orientation * rotation;
// Rotate the camera about the world X axis
rotation = glm::gtx::quaternion::angleAxis(pitchDegrees, 1.0f, 0.0f, 0.0f);
// Concatenate quaterions ('*' operator concatenates)
// C#: Quaternion.Concatenate(ref orientation, ref rotation)
orientation = rotation * orientation;
The problem that remains is that the view matrix rotation appears to rotate the drawn object and not look around like a normal FPS camera.
I have uploaded a video to YouTube to demonstrate the problem. I move the mouse around to change the camera's orientation but the triangle appears to rotate instead.
YouTube video demonstrating camera orientation problem
EDIT 2:
void Camera::rotate(float yawDegrees, float pitchDegrees)
{
// Apply rotation speed to the rotation
yawDegrees *= lookSensitivity;
pitchDegrees *= lookSensitivity;
if (isLookInverted)
{
pitchDegrees = -pitchDegrees;
}
pitchAccum += pitchDegrees;
// Stop the camera from looking any higher than 90 degrees
if (pitchAccum > 90.0f)
{
pitchDegrees = 90.0f - (pitchAccum - pitchDegrees);
pitchAccum = 90.0f;
}
// Stop the camera from looking any lower than 90 degrees
else if (pitchAccum < -90.0f)
{
pitchDegrees = -90.0f - (pitchAccum - pitchDegrees);
pitchAccum = -90.0f;
}
// 'pitchAccum' range is [-90, 90]
//printf("pitchAccum %f \n", pitchAccum);
yawAccum += yawDegrees;
if (yawAccum > 360.0f)
{
yawAccum -= 360.0f;
}
else if (yawAccum < -360.0f)
{
yawAccum += 360.0f;
}
orientation =
glm::gtx::quaternion::angleAxis(pitchAccum, 1.0f, 0.0f, 0.0f) *
glm::gtx::quaternion::angleAxis(yawAccum, 0.0f, 1.0f, 0.0f);
}
EDIT3:
The following multiplication order allows the camera to rotate around its own axis but face the wrong direction:
glm::mat4 translation;
translation = glm::translate(translation, position);
view = glm::gtx::quaternion::toMat4(orientation) * translation;
EDIT4:
The following will work (applying the translation matrix based on the position after then rotation)
// Rotation
view = glm::gtx::quaternion::toMat4(orientation);
// Translation
glm::mat4 translation;
translation = glm::translate(translation, -position);
view *= translation;
I can't get the dot product with each orientation axis to work though
// Rotation
view = glm::gtx::quaternion::toMat4(orientation);
glm::vec3 p(
glm::dot(glm::vec3(view[0][0], view[0][1], view[0][2]), position),
glm::dot(glm::vec3(view[1][0], view[1][1], view[1][2]), position),
glm::dot(glm::vec3(view[2][0], view[2][1], view[2][2]), position)
);
// Translation
glm::mat4 translation;
translation = glm::translate(translation, -p);
view *= translation;
In order to give you a definite answer, I think that we would need the code that shows how you're actually supplying the view matrix and vertices to OpenGL. However, the symptom sounds pretty typical of incorrect matrix order.
Consider some variables:
V represents the inverse of the current orientation of the camera (the quaternion).
T represents the translation matrix holding the position of the camera. This should be an identity matrix with negation of the camera's position going down the fourth column (assuming that we're right-multiplying column vectors).
U represents the inverse of the change in orientation.
p represents a vertex in world space.
Note: all of the matrices are inverse matrices because the transformations will be applied to the vertex, not the camera, but the end result is the same.
By default the OpenGL camera is at the origin looking down the negative-z axis. When the view isn't changing (U==I), then the vertex's transformation from world coordinates to camera coordinates should be: p'=TVp. You first orient the camera (by rotating the world in the opposite direction) and then translate the camera into position (by shifting the world in the opposite direction).
Now there are a few places to put U. If we put U to the right of V, then we get the behavior of a first-person view. When you move the mouse up, whatever is currently in view rotates downward around the camera. When you move the mouse right, whatever is in view rotates to the left around the camera.
If we put U between T and V, then the camera turns relative to the world's axes instead of the camera's. This is strange behavior. If V happens to turn the camera off to the side, then moving the mouse up and down will make the world seem to 'roll' instead of 'pitch' or 'yaw'.
If we put U left of T, then the camera rotates around the world's axes around the world's origin. This can be even stranger because it makes the camera fly through world faster the farther the camera is from the origin. However, because the rotation is around the origin, if the camera happens to be looking at the origin, objects there will just appear to be turning around. This is sort of what you're seeing because of the dot-products that you're taking to rotate the camera's position.
You check to make sure that pitchAccum stays within [-90,90], but you've commented out the portion that would make use of that fact. This seems odd to me.
The way that you left-multiply pitch but right-multiply yaw makes it so that your quaternions aren't doing much for you. They're just holding your Euler angles. Unless orientation changes are coming in from other places, you could simply say that orientation = glm::gtx::quaternion::angleAxis(pitchAccum*DEG2RAD, 1.0f, 0.0f, 0.0f) * glm::gtx::quaternion::angleAxis(yawAccum*DEG2RAD, 0.0f, 1.0f, 0.0f); and overwrite the old orientation completely.
From what I understand in this tutorial, there might be a reason why pitch angle is restricted at 90 degrees.
Regardless of using quaternions or a look at matrix, at the end, we give an initial orientation to the Camera. In quaternions, this is the initial value of the orientation, in lookAt, it is the initial value of the up vector.
If the direction facing towards the camera is parallel to this initial vector, then the cross product of these will be zero, which means the camera might have any orientation if pitch is 90 or -90 degrees.
In the internal implementation of toMat4(orientation) this would result in one of your x_dir/y_dir/z_dir vectors to be a zero vector, which would mean that your can have any orientation. This is also discussed in this book, which says that if Y angle is 90 degrees, a degree of freedom is lost (Edward Angel and Dave Shreiner, Interactive Computer Graphics, A Top-Down Approach with WebGL, Seventh Edition, Addison-Wesley 2015.), which is discussed as Gimbal Lock.
I can see that you are aware of this problem, but in your code, the yaw angle is still set to 90 degrees if it overflows 90, leaving your Camera in an invalid state. You should consider something like this instead:
if (pitchAccum > 89.999f && pitchAccum <= 90.0f)
{
pitchAccum = 90.001f;
}
else if (pitchAccum < -89.999f && pitchAccum >= -90.0f)
{
pitchAccum = -90.001f;
}
if (pitchAccum >= 360.0f)
{
pitchAccum = 0.0f;
}
else if (pitchAccum <= -360.0f)
{
pitchAccum = 0.0f;
}
Or you can define another custom action of your choice when pitchAccum is 90 degrees.