Antoine Posted December 22, 2020 Share Posted December 22, 2020 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 comment
rohit.gonsalves Posted December 23, 2020 Share Posted December 23, 2020 (edited) 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 December 23, 2020 by rohit.gonsalves Link to comment
Antoine Posted January 13, 2021 Author Share Posted January 13, 2021 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 comment
Recommended Posts