Skip to content

Commit

Permalink
Calculate I3dm instance rotations by converting basis to a matrix
Browse files Browse the repository at this point in the history
The previous approach tried to create rotations directly from the up
and right vectors that encode the instance rotation, but it naïvely
didn't handle rotations of 180 degrees of the up and right vector. It
is reliable to create the rotation matrix, filling in the Z column
by doing a cross-product, and then let the algorithm for converting a
rotation matrix to a quaternion do its robust thing.
  • Loading branch information
timoore committed Dec 16, 2024
1 parent 854db41 commit 4726870
Showing 1 changed file with 7 additions and 19 deletions.
26 changes: 7 additions & 19 deletions Cesium3DTilesContent/src/I3dmToGltfConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,29 +143,17 @@ glm::vec3 decodeOct32P(const uint16_t rawOct[2]) {

/*
Calculate the rotation quaternion described by the up, right vectors passed
in NORMAL_UP and NORMAL_RIGHT. This is composed of two rotations:
+ The rotation that takes the up vector to its new position;
+ The rotation around the new up vector that takes the right vector to its
new position.
in NORMAL_UP and NORMAL_RIGHT.
I like to think of each rotation as describing a coordinate frame. The
calculation of the second rotation must take place within the first frame.
The rotations are calculated by finding the rotation that takes one vector to
another.
There may be a faster method that avoids creating a rotation matrix, but it is
hard to get the exceptional cases correct e.g., rotations of 180 degrees about
an axis.
*/

glm::quat rotationFromUpRight(const glm::vec3& up, const glm::vec3& right) {
// First rotation: up
auto upRot = CesiumUtility::Math::rotation(glm::vec3(0.0f, 1.0f, 0.0f), up);
// We can rotate a point vector by a quaternion using q * (0, v) *
// conj(q). But here we are doing an inverse rotation of the right vector into
// the "up frame."
glm::quat temp = glm::conjugate(upRot) * glm::quat(0.0f, right) * upRot;
glm::vec3 innerRight(temp.x, temp.y, temp.z);
glm::quat rightRot =
CesiumUtility::Math::rotation(glm::vec3(1.0f, 0.0f, 0.0f), innerRight);
return upRot * rightRot;
glm::vec3 forward = cross(right, up);
glm::mat3x3 rotMat(right, up, forward);
return glm::quat(rotMat);
}

struct ConvertedI3dm {
Expand Down

0 comments on commit 4726870

Please sign in to comment.