From 7ba42f0e76ec8269b5b6cd7a35deb625c09a870b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Jan 2018 15:52:56 +1300 Subject: [PATCH 1/3] Update JSDoc per recent changes in Window API --- interface/src/scripting/WindowScriptingInterface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index af9c03a218..6d7a10c580 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -42,7 +42,7 @@ void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptR * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. Read-only. * @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other - * chrome) plus the height of the menu bar, in pixels. Read-only. + * chrome), in pixels. Read-only. * @property {object} location - Provides facilities for working with your current metaverse location. See {@link location}. * @property {number} x - The x coordinate of the top left corner of the Interface window on the display. Read-only. * @property {number} y - The y coordinate of the top left corner of the Interface window on the display. Read-only. @@ -555,7 +555,7 @@ signals: /**jsdoc * Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with - * includeAnimated = false. + * includeAnimated = false or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}. * @function Window.stillSnapshotTaken * @param {string} pathStillSnapshot - The path and name of the snapshot image file. * @param {boolean} notify - The value of the notify parameter that {@link Window.takeSnapshot|takeSnapshot} From a543d90090968a0457d7b9e65eaf21ad69fb92d3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Jan 2018 15:53:45 +1300 Subject: [PATCH 2/3] Miscellaneous fixes --- interface/src/scripting/WindowScriptingInterface.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 6d7a10c580..bfad5644bf 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -301,7 +301,7 @@ public slots: /**jsdoc * Get Interface's build number. * @function Window.checkVersion - * @returns {string} - Interface's build number. + * @returns {string} Interface's build number. */ QString checkVersion(); @@ -327,7 +327,7 @@ public slots: * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. * @example Using the snapshot function and signals. - * function onStillSnapshottaken(path, notify) { + * function onStillSnapshotTaken(path, notify) { * print("Still snapshot taken: " + path); * print("Notify: " + notify); * } @@ -340,7 +340,7 @@ public slots: * print("Animated snapshot taken: " + animatedPath); * } * - * Window.stillSnapshotTaken.connect(onStillSnapshottaken); + * Window.stillSnapshotTaken.connect(onStillSnapshotTaken); * Window.processingGifStarted.connect(onProcessingGifStarted); * Window.processingGifCompleted.connect(onProcessingGifCompleted); * From 67218a697b461ec94f071a8fa02f80fe74161e5c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Jan 2018 14:01:20 +1300 Subject: [PATCH 3/3] Support FBX files that have nodes with non-XYZ rotation order --- libraries/fbx/src/FBXReader.cpp | 65 +++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 659d6dfa1e..42d25c96ea 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -148,6 +148,59 @@ glm::vec3 parseVec3(const QString& string) { return value; } +enum RotationOrder { + OrderXYZ = 0, + OrderXZY, + OrderYZX, + OrderYXZ, + OrderZXY, + OrderZYX, + OrderSphericXYZ +}; + +bool haveReportedUnhandledRotationOrder = false; // Report error only once per FBX file. + +glm::vec3 convertRotationToXYZ(int rotationOrder, const glm::vec3& rotation) { + // Convert rotation with given rotation order to have order XYZ. + if (rotationOrder == OrderXYZ) { + return rotation; + } + + glm::quat xyzRotation; + + switch (rotationOrder) { + case OrderXZY: + xyzRotation = glm::quat(glm::radians(glm::vec3(0, rotation.y, 0))) + * (glm::quat(glm::radians(glm::vec3(0, 0, rotation.z))) * glm::quat(glm::radians(glm::vec3(rotation.x, 0, 0)))); + break; + case OrderYZX: + xyzRotation = glm::quat(glm::radians(glm::vec3(rotation.x, 0, 0))) + * (glm::quat(glm::radians(glm::vec3(0, 0, rotation.z))) * glm::quat(glm::radians(glm::vec3(0, rotation.y, 0)))); + break; + case OrderYXZ: + xyzRotation = glm::quat(glm::radians(glm::vec3(0, 0, rotation.z))) + * (glm::quat(glm::radians(glm::vec3(rotation.x, 0, 0))) * glm::quat(glm::radians(glm::vec3(0, rotation.y, 0)))); + break; + case OrderZXY: + xyzRotation = glm::quat(glm::radians(glm::vec3(0, rotation.y, 0))) + * (glm::quat(glm::radians(glm::vec3(rotation.x, 0, 0))) * glm::quat(glm::radians(glm::vec3(0, 0, rotation.z)))); + break; + case OrderZYX: + xyzRotation = glm::quat(glm::radians(glm::vec3(rotation.x, 0, 0))) + * (glm::quat(glm::radians(glm::vec3(0, rotation.y, 0))) * glm::quat(glm::radians(glm::vec3(0, 0, rotation.z)))); + break; + default: + // FIXME: Handle OrderSphericXYZ. + if (!haveReportedUnhandledRotationOrder) { + qCDebug(modelformat) << "ERROR: Unhandled rotation order in FBX file:" << rotationOrder; + haveReportedUnhandledRotationOrder = true; + } + return rotation; + } + + return glm::degrees(safeEulerAngles(xyzRotation)); +} + QString processID(const QString& id) { // Blender (at least) prepends a type to the ID, so strip it out return id.mid(id.lastIndexOf(':') + 1); @@ -630,6 +683,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS glm::vec3 ambientColor; QString hifiGlobalNodeID; unsigned int meshIndex = 0; + haveReportedUnhandledRotationOrder = false; foreach (const FBXNode& child, node.children) { if (child.name == "FBXHeaderExtension") { @@ -731,6 +785,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS glm::vec3 translation; // NOTE: the euler angles as supplied by the FBX file are in degrees glm::vec3 rotationOffset; + int rotationOrder = OrderXYZ; // Default rotation order set in "Definitions" node is assumed to be XYZ. glm::vec3 preRotation, rotation, postRotation; glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f); glm::vec3 scalePivot, rotationPivot, scaleOffset; @@ -764,6 +819,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS index = 4; } if (properties) { + static const QVariant ROTATION_ORDER = QByteArray("RotationOrder"); static const QVariant GEOMETRIC_TRANSLATION = QByteArray("GeometricTranslation"); static const QVariant GEOMETRIC_ROTATION = QByteArray("GeometricRotation"); static const QVariant GEOMETRIC_SCALING = QByteArray("GeometricScaling"); @@ -790,6 +846,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (childProperty == LCL_TRANSLATION) { translation = getVec3(property.properties, index); + } else if (childProperty == ROTATION_ORDER) { + rotationOrder = property.properties.at(index).toInt(); + } else if (childProperty == ROTATION_OFFSET) { rotationOffset = getVec3(property.properties, index); @@ -797,13 +856,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS rotationPivot = getVec3(property.properties, index); } else if (childProperty == PRE_ROTATION) { - preRotation = getVec3(property.properties, index); + preRotation = convertRotationToXYZ(rotationOrder, getVec3(property.properties, index)); } else if (childProperty == LCL_ROTATION) { - rotation = getVec3(property.properties, index); + rotation = convertRotationToXYZ(rotationOrder, getVec3(property.properties, index)); } else if (childProperty == POST_ROTATION) { - postRotation = getVec3(property.properties, index); + postRotation = convertRotationToXYZ(rotationOrder, getVec3(property.properties, index)); } else if (childProperty == SCALING_PIVOT) { scalePivot = getVec3(property.properties, index);