I’m having trouble with finding a good way to convert between quaternion rotations and euler angles without gimbal lock issues.
I’m trying to expose GUI controls for an ofNode - the GUI shows euler angles for intuitive control, but the node calculates the rotations internally using quaternions.
This works perfectly with X and Z euler rotations of any degree, but my Y axis rotation is limited -90 to 90 degrees before it starts spazzing out:
I’m assuming this is a gimbal lock issue?
Any suggestions on how to avoid this, and get full rotation controls on all axes?
My euler/quaternion conversion functions are:
glm::vec3 euler = node.getOrientationEulerDeg(); // uses glm::eulerAngles( quaternion ) under the hood
glm::quat orientation( glm::vec3( ofDegToRad( euler.x ), ofDegToRad( euler.y ), ofDegToRad( euler.z ) ) );
Here’s the full code for above example:
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
class ofApp : public ofBaseApp
{
public:
void setup()
{
ofBackground( 0 );
gui.setup( "controls" );
gui.add( eulerAngles );
eulerAngles.addListener(this, &ofApp::setNodeOrientation);
}
void update()
{
glm::vec3 euler = node.getOrientationEulerDeg();
eulerAngles.setWithoutEventNotifications( euler );
}
void draw()
{
cam.begin();
node.transformGL();
ofNoFill();
ofDrawBox( 300 );
ofDrawAxis( 100 );
ofFill();
node.restoreTransformGL();
cam.end();
gui.draw();
}
void setNodeOrientation( glm::vec3& euler )
{
glm::quat orientation( glm::vec3( ofDegToRad( euler.x ), ofDegToRad( euler.y ), ofDegToRad( euler.z ) ) );
node.setOrientation(orientation);
}
ofxPanel gui;
ofParameter<glm::vec3> eulerAngles{ "euler", glm::vec3( 0 ), glm::vec3( -180 ), glm::vec3( 180 ) };
ofNode node;
ofEasyCam cam;
};