dongju.jeong Posted July 10, 2019 Posted July 10, 2019 quat a = quat(10.f, 20.f, 30.f); mat3 d = mat3(a); vec3 dd = decomposeRotationXYZ(d); Log::message("%f, %f, %f\n", dd.x,dd.y,dd.z); // is correct (9.999999,19.99999,30) Log::message("%f, %f, %f\n", a.getAngle(vec3(1, 0, 0)), a.getAngle(vec3(0, 1, 0)), a.getAngle(vec3(0, 0, 1))); // not correct. (15.xxx, 17.xxxx, 31.xxx). How do I get an auler angle by the getAngle?
cash-metall Posted July 11, 2019 Posted July 11, 2019 Hello! getAngle - returns the rotation angle of the quaternion for a given rotation axis (the angle of the quaternion`s direction projection on the axis) I try to explain: the quaternion constructor does the XYZ order. therefore, with XYZ decomposition, you get the correct result. You can try the decomposition in a different order to see that the result will change. the figure shows how the rotation is applied 10, 20, 30 1. red x 2. green y 3. blue for z If you look at the final rotation of the x axis (orange line), you will see that the angle is greater than 10 (x` - its getAngle result). Quaternions do not know anything about how to apply turns. 1
dongju.jeong Posted July 16, 2019 Author Posted July 16, 2019 thank you. then, Is there any way to get the Euler's angle from the quaternion ? when don't use decomposeRotationXYZ().
cash-metall Posted July 16, 2019 Posted July 16, 2019 The quaternions knows nothing about Euler angles. The quaternion is a vector and a rotation. Euler angles need to count. Why don't you want to use decompose? And why do you constantly need Euler angles? Can it be better to work with quaternions? Maybe these examples will help you too: quat eulerENUToRotation(const vec3 &euler) { return quat(composeRotationZYX(euler)); } vec3 rotationToEulerENU(const quat &rotation) { return decomposeRotationZYX(mat3(rotation)); } quat eulerNEDToRotation(const vec3 &euler) { return quat(0.0f, 0.0f, -1.0f, euler.z) * quat(1.0f, 0.0f, 0.0f, euler.y) * quat(0.0f, 1.0f, 0.0f, euler.x); } vec3 rotationToEulerNED(const quat &rotation) { mat3 t = mat3(rotation); vec3 r = vec3::ZERO; if (t.m20 < 1.0f) { if (t.m20 > -1.0f) { r.x = -Math::atan2(t.m20, t.m22); r.y = Math::asin(t.m21); r.z = Math::atan2(t.m01, t.m11); } else { r.x = UNIGINE_PI05; r.z = -Math::atan2(-t.m01, t.m02); } } else { r.x = -UNIGINE_PI05; r.z = Math::atan2(t.m01, -t.m02); } return r * UNIGINE_RAD2DEG; } 1
dongju.jeong Posted July 16, 2019 Author Posted July 16, 2019 (edited) Thank you for make the sample. I needed a value for how much the object rotated. In frame units or a certain period of time. And I wanted to apply the opposite value of that angle difference to any other object. For example, if A rotates to the left, B rotates to the right as much as A. (each on the current rotation basis) B.rotate (- A's angle's gap) in my case, B is camera node. I plan to use this code that seems to seems to be usable in VR sample. ( not used auler angle) vec3 dir = direction; dir.z = 0; dir = normalize(dir); quat rot = conjugate(quat(lookAt(Vec3(0, 0, 0), Vec3(dir), vec3(0, 0, 1)))); vec3 angles = decomposeRotationYXZ(mat3(hmd_transform)); player->setRotation(rot * quat(0.0f, -angles.y, 0.0f)); ↓ vec3 dir = vec3(0,1,0); dir.z = 0; dir = normalize(dir); quat rot = conjugate(quat(lookAt(Vec3(0, 0, 0), Vec3(dir), vec3(0, 0, 1)))); vec3 angles = decomposeRotationXYZ(mat3(headBase->getWorldTransform())); player->setRotation(rot * quat(-angles.x, -angles.z, angles.y)); The headBase is the normal object node type and starts at the initial rotation value of 0,0,0. The camera is initially looking forward (world-based Y-axis) As much as the headbase has rotated, it will rotate the camera in reverse. Edited July 16, 2019 by dongju.jeong
dongju.jeong Posted July 16, 2019 Author Posted July 16, 2019 I've solved the problem of rotation. But there was another problem. If the camera player in the VR environment is rotated directly, it does not only rotate on the actual screen, but also moves. Mat4 hmd_transform = Mat4(vive.getDevicePose(HMD_DEVICE_0)); Mat4 hmd_transform_world = player_transform * hmd_transform; Vec3 head_offset = (vive.isDeviceConnected(HMD_DEVICE_0) && HMD_DEVICE_0 != -1) ? player_transform.getTranslate() - hmd_transform_world.getTranslate() : Vec3::ZERO; head_offset.z = 0; head->setWorldTransform(hmd_transform_world); because, It seems that the actual camera transform is done like that code. [ Mat4 hmd_transform_world = player_transform * hmd_transform;] What should I do if I only want to rotate intentionally in a VR environment?
Recommended Posts