Rotation on 3 axis


photo

Recommended Posts

Hi,

I am trying to make my playerSpectator rotate around the 3axis, but for now I haven't understand the right way to do it with the unigine sdk.

Here is my present work:

 

    Unigine::Math::vec3 currentEulerAngles{ 0, static_cast<float>(mTowerPitch), static_cast<float>(mTowerHeading)};
    Unigine::Math::Vec3  initRotationToLookNorth = Unigine::Math::vec3(-90.0f, 0.0f, 0.0f);
    Unigine::Math::vec3 newEulerAngles = Unigine::Math::vec3::ZERO;
    Unigine::Math::vec3 offsetRot = Unigine::Math::vec3{-verticalOffset, 0, -horizontalOffset};

    //Rotation
    Unigine::Math::vec3 rotation = currentEulerAngles +initRotationToLookNorth + offsetRot;
    Unigine::Math::mat4 composedMatrix = Unigine::Math::composeRotationZXY(rotation);
    mpPlayerSpectator->setRotation(composedMatrix.getRotate());

As you can see, for now I am able to rotate on the Z and Y axis but then the X is locked, I tried to bypass the gimbal lock by using the quaternion but same result:

	mpPlayerSpectator->setRotation(Unigine::Math::quat(rotation.x, rotation.y, rotation.z));

Should I use the composedRotation or the quaternion or the matrix ? What is the right way to do it ?

Thanks,

Link to post

Dear @Antoine,

I had similar situation with different rotations and positions of raw transform, Device Transform and offset transforms. 

Raw transforms came for me from tracking hardware.

Device transforms were offsets added to the device hardware respect to reference origin.

and offset transforms were inputs from user so I needed to keep everything as XYZ positions and X Y Z euler angles on GUI for user to chose from -360 degrees to 360 degrees. For me things are 100% correct with following.

//Raw Transform
			quat quatRotation = quat::IDENTITY;
			quat quatOffsetX = quat::IDENTITY;
			quat quatOffsetY = quat::IDENTITY;
			quat quatOffsetZ = quat::IDENTITY;

			vec3 vec3Position = objTrackingPoseToUse->m_vec3Position * vec3(m_ivec3PositionMultiplier);
			vec3 vec3RotationEulerAngles = objTrackingPoseToUse->m_vec3RotationEulerAngles * vec3(m_ivec3RotationMultiplier);
			quatRotation = quat(vec3RotationEulerAngles.x, vec3RotationEulerAngles.y, vec3RotationEulerAngles.z);
			quatOffsetX = quat(vec3(1.0f, 0.0f, 0.0f), vec3RotationEulerAngles.x);
			quatOffsetY = quat(vec3(0.0f, 1.0f, 0.0f), vec3RotationEulerAngles.y);
			quatOffsetZ = quat(vec3(0.0f, 0.0f, 1.0f), vec3RotationEulerAngles.z);
			quatRotation = quatOffsetX * quatOffsetY * quatOffsetZ;
			mat4 matTransform = mat4(quatRotation, vec3Position);
						
			//Device Transform
			vec3Position = alt_translation.get();
			vec3RotationEulerAngles = alt_rotation.get();
			quatRotation = quat(vec3RotationEulerAngles.x, vec3RotationEulerAngles.y, vec3RotationEulerAngles.z);
			quatOffsetX = quat(vec3(1.0f, 0.0f, 0.0f), vec3RotationEulerAngles.x);
			quatOffsetY = quat(vec3(0.0f, 1.0f, 0.0f), vec3RotationEulerAngles.y);
			quatOffsetZ = quat(vec3(0.0f, 0.0f, 1.0f), vec3RotationEulerAngles.z);
			quatRotation = quatOffsetX * quatOffsetY * quatOffsetZ;
			mat4 matDeviceTransform = mat4(quatRotation, vec3Position);

			//Offset Transform
			vec3Position = translation_offsets.get();
			vec3RotationEulerAngles = rotation_offsets.get();
			quatRotation = quat(vec3RotationEulerAngles.x, vec3RotationEulerAngles.y, vec3RotationEulerAngles.z);
			quatOffsetX = quat(vec3(1.0f, 0.0f, 0.0f), vec3RotationEulerAngles.x);
			quatOffsetY = quat(vec3(0.0f, 1.0f, 0.0f), vec3RotationEulerAngles.y);
			quatOffsetZ = quat(vec3(0.0f, 0.0f, 1.0f), vec3RotationEulerAngles.z);
			quatRotation = quatOffsetX * quatOffsetY * quatOffsetZ;
			mat4 matOffsetTransform = mat4(quatRotation, vec3Position);

			getNode()->setTransform(matTransform * matDeviceTransform * matOffsetTransform);

 

Instead of adding rotations 

Unigine::Math::vec3 rotation = currentEulerAngles +initRotationToLookNorth + offsetRot;

Do as above.

Prepare separate matrix for each rotation and then multiply those matrices. 

Regards,

Rohit

Edited by rohit.gonsalves
Link to post
  • 3 weeks later...

Thanks for the help!

As I understand it:

//This code :
quatRotation = quat(vec3RotationEulerAngles.x, vec3RotationEulerAngles.y, vec3RotationEulerAngles.z);
quatOffsetX = quat(vec3(1.0f, 0.0f, 0.0f), vec3RotationEulerAngles.x);
quatOffsetY = quat(vec3(0.0f, 1.0f, 0.0f), vec3RotationEulerAngles.y);
quatOffsetZ = quat(vec3(0.0f, 0.0f, 1.0f), vec3RotationEulerAngles.z);
quatRotation = quatOffsetX * quatOffsetY * quatOffsetZ;
mat4 matTransform = mat4(quatRotation, vec3Position);

//Is doing the same as this :
Unigine::Math::mat4 composedMat = Unigine::Math::composeRotationXYZ(vec3RotationEulerAngles);

And as long as we use the Eulers angles we are vulnerable to the Gimbal lock problem, doesn't matter if we change those euler angles in quaternion or Matrix.

In my case I will never rotate around the Y axis, that's why I used the composedZXY() in that specific order.

My code look like this now:

//Setting the position at the origin
mpPlayerSpectator->setWorldPosition(Unigine::Math::vec3::ZERO);

//The rotation around the axis I need to do 
Unigine::Math::vec3 intialRotation = Unigine::Math::vec3(90.0f, 0.0f, 180.0f);
Unigine::Math::vec3 currentEulerAngles = Unigine::Math::vec3(static_cast<float>(mTowerPitch)-static_cast<float>(verticalOffset), 0.0f, static_cast<float>(mTowerHeading)-static_cast<float>(horizontalOffset));
Unigine::Math::vec3 polarRotation = Unigine::Math::vec3(static_cast<float>(mPhy), 0.0f, static_cast<float>(mTheta));

//Creating a rotation martix
Unigine::Math::mat4 composedMat = Unigine::Math::composeRotationZXY(currentEulerAngles + polarRotation + intialRotation);
mpPlayerSpectator->setWorldRotation(Unigine::Math::quat(composedMat));

//Setting the new position
mpPlayerSpectator->setWorldPosition(mTowerPosition + mpPlayerSpectator->getViewDirection() * static_cast<float>(mDistance));

 

 

Link to post