From 472687021ea8aa791dfdb806b6f7e6dfa3d414cc Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Fri, 13 Dec 2024 15:23:39 +0100 Subject: [PATCH 1/2] Calculate I3dm instance rotations by converting basis to a matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../src/I3dmToGltfConverter.cpp | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp b/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp index beb2d3c0f..3e64bd4b8 100644 --- a/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp +++ b/Cesium3DTilesContent/src/I3dmToGltfConverter.cpp @@ -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 { From a4952a67fedf02d8437421bf3d9281a66db2b9b9 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 24 Dec 2024 14:28:25 +1100 Subject: [PATCH 2/2] Update CHANGES.md. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e1c989de5..154086047 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - Fixed a bug in the `Tileset` selection algorithm that could cause detail to disappear during load in some cases. - Improved the "kicking" mechanism in the tileset selection algorithm. The new criteria allows holes in a `Tileset`, when they do occur, to be filled with loaded tiles more incrementally. - Fixed a bug in `SharedAssetDepot` that could lead to crashes and other undefined behavior when an asset in the depot outlived the depot itself. +- Fixed a bug that could cause some rotations in an Instanced 3D Model (.i3dm) to be represented incorrectly. ### v0.42.0 - 2024-12-02