instead it seems the camera flips 180 degrees around the Z axis, almost like it has been spun around.
Maybe it’s its simpler to understand to just say your at or near the gimble point.
You get gimble lock when your forward and up vector are parrallel as a direction.
You hear alot about gimble lock which is annoying but you also have a gimble inflection point if you use a static up vector or a static forward one that is hard set like Vector3.Up (you will have that no matter what, unless you make your camera have a free up). To do that you use your cameraMatrix’s up vector itself as the up.
Once the vectors you feed to createlookat move past each other you get spin round.
Realize that for the cross product that is used to calculate the right vector internally, the order matters for it.
If you feed a cross product (a, b) you get a opposite direction of (b, a) so if one of your vectors never moves.
As one of the directions (forward) go pasts the other (up), you spin the right all the way around, its basically like feeding the up then forward to the CreateLookAt were a second ago it was taking cross(forward up). Of course you didn’t feed the function things in different order but as your vectors go past each other the right vector that is generated is reversed,
This is a snippet from a ad hock camera i made the other day the function demonstrates the idea of a free camera.
If you do this you don’t have a fixed up and you are like a pilot in space things are as they are, There is no gimble lock point anymore so neither is there gimble lock or a inflection point to spin around.
Vector3 position = Vector3.Zero;
void UpdateMovementCam(GameTime gameTime)
{
// key presses
Vector3 rotationalMoment = Vector3.Zero;
// rotational
if (Keyboard.GetState().IsKeyDown(Keys.W))
rotationalMoment.Y += rotspeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.S))
rotationalMoment.Y += -rotspeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.A))
rotationalMoment.X += rotspeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.D))
rotationalMoment.X += -rotspeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.C))
rotationalMoment.Z += rotspeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.Z))
rotationalMoment.Z += -rotspeed * elapsed;
// movement
if (Keyboard.GetState().IsKeyDown(Keys.E))
position += camera.Forward * movespeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.Q))
position += camera.Forward * -movespeed * elapsed;
// strafe
if (Keyboard.GetState().IsKeyDown(Keys.Up))
position += camera.Up * movespeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.Down))
position += camera.Up * -movespeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.Left))
position += camera.Right * -movespeed * elapsed;
if (Keyboard.GetState().IsKeyDown(Keys.Right))
position += camera.Right * +movespeed * elapsed;
// free camera
camera *=
Matrix.CreateFromAxisAngle(camera.Forward, rotationalMoment.Z) *
Matrix.CreateFromAxisAngle(camera.Up, rotationalMoment.X) *
Matrix.CreateFromAxisAngle(camera.Right, rotationalMoment.Y)
;
forward = camera.Forward;
camera.Translation = position;
camera = Matrix.CreateWorld(position, forward, camera.Up);
view = Matrix.CreateLookAt(camera.Translation, camera.Translation + camera.Forward, camera.Up);
}
Now if you want the best of both worlds as a free cam with no gimble lock and having a fixed up gives you a fixed point of gravity that can be very nice.
Then you have to comprimise and turn a free camera into a not quite so free camera,
You have to build a additional function to (gravitate / nudge) the up vector towards were you think up should be and softly up over time. Which really means figuring out what is the horizon and calculating a blending up vector from a right and forward.
That really depends on your needs most of the time a fixed up is just fine but not always.
What to choose as the gravity pull for your up vector for a free camera in different situations ? and how do you want to apply it is a whole other topic which is more of a art then a science.