Alright so I've recently taken back to work on LDForge so that we can finally have something better than MLCad and text editors to make bricks with.

And by doing so I'm back to the ages old problem of breaking the gimbal lock. I've surfed around the web for years now looking for the solution and it generally is to use quaternions instead of euler angles. But I absolutely cannot wrap my head around: how exactly does 2D screen turning translate into a 4D quaternion?

I've been bashing my head against a wall regarding this for so long that I'm not even sure at this point that quaternions are the way to go. Maybe I'm supposed to use a rotation matrix instead? Or multiple quaternions? Or a mix of both? How am I supposed to model the camera?

(2017-01-30, 0:07)Santeri Piippo Wrote: [ -> ]Alright so I've recently taken back to work on LDForge so that we can finally have something better than MLCad and text editors to make bricks with.

And by doing so I'm back to the ages old problem of breaking the gimbal lock. I've surfed around the web for years now looking for the solution and it generally is to use quaternions instead of euler angles. But I absolutely cannot wrap my head around: how exactly does 2D screen turning translate into a 4D quaternion?

I've been bashing my head against a wall regarding this for so long that I'm not even sure at this point that quaternions are the way to go. Maybe I'm supposed to use a rotation matrix instead? Or multiple quaternions? Or a mix of both? How am I supposed to model the camera?

LDView uses quaternions for its camera, but not for model rotation. Model rotation is performed via a separate rotation matrix. In Lat/Long mode, LDView has gimbal lock, and this is expected. When Lat/Long mode is disabled, it doesn't have gimbal lock. All I do there is determine how fast the mouse is moving in both X and Y (scaled), and then apply rotations based on that and how long a frame takes to draw. I actually use GL to do the rotation, but that could easily be done other ways also. Here is the pertinent code:

Code:

` glPushMatrix();`

glLoadIdentity();

glRotatef(rotationSpeed, xRotate, yRotate, zRotate);

glMultMatrixf(rotationMatrix);

glGetFloatv(GL_MODELVIEW_MATRIX, rotationMatrix);

glPopMatrix();

glMultMatrixf(rotationMatrix);

The above code simply updates my rotationMatrix variable based on the current rotation settings, then applies that matrix to the GL transform prior to drawing the model. Note that zRotate in LDView is done via two keys on the keyboard, not the mouse. It effectively spins the camera around its own axis (although not really, since as I said, what I'm really doing is applying a transform to the model before I draw it.

To be honest, the way LDView does things could likely lead to problems in an editor, so I'm not really sure it's appropriate there. But I suspect that with a little work, the calculations I use above to figure out the model's rotation could be reverse applied to the camera, and end up with the same end result, but with known camera position. (The zRotate would obviously be trivial from the camera's perspective.)

Thank you so much for the reply. It took me the whole week to properly understand it, but in the end all it took was 15 minutes last night to get it to work and an hour today to get it working right.

Here is the commit where I implemented this. I made the rotation to be multiplied into the matrix immediately after the input is received. For some reason I had to switch

x and

y in the glRotate call.

Glad to hear you got it working.

(2017-02-08, 14:53)Philippe Hurbain Wrote: [ -> ]Quote:For some reason I had to switch x and y in the glRotate call.

LDraw Y axis going down?

Actually, it's because side-to-side motion of the mouse rotates

around the camera's Y axis, and vertical motion of the mouse rotates

around the camera's X axis. So this flip is expected. I had forgotten about this, so left it out of my original post. LDView swaps those before setting xRotate and yRotate. (In other words, xRotate in my pasted code gets set based on the Y mouse motion, and yRotate gets set based on the X mouse motion.)