From d98e7d5bc673cb56d6b2e8c56175aaff2c8a1b14 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 23 May 2017 00:26:12 +0100 Subject: [PATCH 01/25] adding left and right arm --- interface/src/Application.cpp | 6 +- interface/src/avatar/MyAvatar.cpp | 56 +++++++++++++++++++ interface/src/avatar/MyAvatar.h | 4 ++ .../controllers/src/controllers/Actions.cpp | 2 + .../controllers/src/controllers/Actions.h | 2 + libraries/controllers/src/controllers/Input.h | 6 +- .../src/controllers/StandardController.cpp | 2 + plugins/openvr/src/ViveControllerManager.cpp | 43 +++++++------- plugins/openvr/src/ViveControllerManager.h | 13 ++++- 9 files changed, 112 insertions(+), 22 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1d31a84ed4..9deb92374f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4368,7 +4368,11 @@ void Application::update(float deltaTime) { myAvatar->getSpine2CalibrationMat(), myAvatar->getHipsCalibrationMat(), myAvatar->getLeftFootCalibrationMat(), - myAvatar->getRightFootCalibrationMat() + myAvatar->getRightFootCalibrationMat(), + myAvatar->getRightArmCalibrationMat(), + myAvatar->getLeftArmCalibrationMat(), + myAvatar->getRightHandCalibrationMat(), + myAvatar->getLeftHandCalibrationMat() }; InputPluginPointer keyboardMousePlugin; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b8d6a4cfa4..5814385de5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -90,6 +90,14 @@ const float MyAvatar::ZOOM_DEFAULT = 1.5f; // static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; +static const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; +static const glm::quat DEFAULT_AVATAR_RIGHTARM_ROT { -0.536241f, 0.536241f, -0.460918f, -0.460918f }; +static const glm::vec3 DEFAULT_AVATAR_LEFTARM_POS { 0.134795f, 0.396349f, -0.0515881f }; +static const glm::quat DEFAULT_AVATAR_LEFTARM_ROT { 0.536257f, 0.536258f, -0.460899f, 0.4609f }; +static const glm::vec3 DEFAULT_AVATAR_RIGHTHAND_POS { -0.72768f, 0.396349f, -0.0515779f }; +static const glm::quat DEFAULT_AVATAR_RIGHTHAND_ROT { 0.479184f, -0.520013f, 0.522537f, 0.476365f}; +static const glm::vec3 DEFAULT_AVATAR_LEFTHAND_POS { 0.727588f, 0.39635f, -0.0515878f }; +static const glm::quat DEFAULT_AVATAR_LEFTHAND_ROT { -0.479181f, -0.52001f, 0.52254f, -0.476369f }; static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f }; static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f }; static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f }; @@ -2790,6 +2798,54 @@ glm::mat4 MyAvatar::getRightFootCalibrationMat() const { } } + +glm::mat4 MyAvatar::getRightArmCalibrationMat() const { + int rightArmIndex = _rig->indexOfJoint("RightArm"); + if (rightArmIndex >= 0) { + auto rightArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightArmIndex); + auto rightArmRot = getAbsoluteDefaultJointRotationInObjectFrame(rightArmIndex); + return createMatFromQuatAndPos(rightArmRot, rightArmPos); + } else { + return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS); + } +} + +glm::mat4 MyAvatar::getLeftArmCalibrationMat() const { + int leftArmIndex = _rig->indexOfJoint("LeftArm"); + auto skeleton = _rig->getAnimSkeleton(); + if (leftArmIndex >= 0) { + auto leftArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftArmIndex); + auto leftArmRot = getAbsoluteDefaultJointRotationInObjectFrame(leftArmIndex); + return createMatFromQuatAndPos(leftArmRot, leftArmPos); + } else { + return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS); + } +} + +glm::mat4 MyAvatar::getRightHandCalibrationMat() const { + int rightHandIndex = _rig->indexOfJoint("RightHand"); + auto skeleton = _rig->getAnimSkeleton(); + if (rightHandIndex >= 0) { + auto rightHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightHandIndex); + auto rightHandRot = getAbsoluteDefaultJointRotationInObjectFrame(rightHandIndex); + return createMatFromQuatAndPos(rightHandRot, rightHandPos); + } else { + return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTHAND_ROT, DEFAULT_AVATAR_RIGHTHAND_POS); + } +} + +glm::mat4 MyAvatar::getLeftHandCalibrationMat() const { + int leftHandIndex = _rig->indexOfJoint("LeftHand"); + auto skeleton = _rig->getAnimSkeleton(); + if (leftHandIndex >= 0) { + auto leftHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftHandIndex); + auto leftHandRot = getAbsoluteDefaultJointRotationInObjectFrame(leftHandIndex); + return createMatFromQuatAndPos(leftHandRot, leftHandPos); + } else { + return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTHAND_ROT, DEFAULT_AVATAR_LEFTHAND_POS); + } +} + bool MyAvatar::pinJoint(int index, const glm::vec3& position, const glm::quat& orientation) { auto hipsIndex = getJointIndex("Hips"); if (index != hipsIndex) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 95643f3bd4..aa96b75211 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -488,6 +488,10 @@ public: glm::mat4 getHipsCalibrationMat() const; glm::mat4 getLeftFootCalibrationMat() const; glm::mat4 getRightFootCalibrationMat() const; + glm::mat4 getRightArmCalibrationMat() const; + glm::mat4 getLeftArmCalibrationMat() const; + glm::mat4 getLeftHandCalibrationMat() const; + glm::mat4 getRightHandCalibrationMat() const; void addHoldAction(AvatarActionHold* holdAction); // thread-safe void removeHoldAction(AvatarActionHold* holdAction); // thread-safe diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 62a10c851f..96e433bcc8 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -51,6 +51,8 @@ namespace controller { makePosePair(Action::LEFT_HAND, "LeftHand"), makePosePair(Action::RIGHT_HAND, "RightHand"), + makePosePair(Action::RIGHT_ARM, "RightArm"), + makePosePair(Action::LEFT_ARM, "LeftArm"), makePosePair(Action::LEFT_FOOT, "LeftFoot"), makePosePair(Action::RIGHT_FOOT, "RightFoot"), makePosePair(Action::HIPS, "Hips"), diff --git a/libraries/controllers/src/controllers/Actions.h b/libraries/controllers/src/controllers/Actions.h index 534f01d865..5727d4906e 100644 --- a/libraries/controllers/src/controllers/Actions.h +++ b/libraries/controllers/src/controllers/Actions.h @@ -42,6 +42,8 @@ enum class Action { LEFT_HAND = NUM_COMBINED_AXES, RIGHT_HAND, + LEFT_ARM, + RIGHT_ARM, LEFT_FOOT, RIGHT_FOOT, HIPS, diff --git a/libraries/controllers/src/controllers/Input.h b/libraries/controllers/src/controllers/Input.h index 65c78cd6ea..7780e91769 100644 --- a/libraries/controllers/src/controllers/Input.h +++ b/libraries/controllers/src/controllers/Input.h @@ -24,7 +24,11 @@ struct InputCalibrationData { glm::mat4 defaultSpine2; // default pose for spine2 joint in avatar space glm::mat4 defaultHips; // default pose for hips joint in avatar space glm::mat4 defaultLeftFoot; // default pose for leftFoot joint in avatar space - glm::mat4 defaultRightFoot; // default pose for leftFoot joint in avatar space + glm::mat4 defaultRightFoot; // default pose for rightFoot joint in avatar space + glm::mat4 defaultRigtArm; // default pose for rightArm joint in avatar space + glm::mat4 defaultLeftArm; // default pose for leftArm joint in avatar space + glm::mat4 defaultRightHand; // default pose for rightHand joint in avatar space + glm::mat4 defaultLeftHand; // default pose for leftHand joint in avatar space }; enum class ChannelType { diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index d8c98eb63b..8e49bb0ebf 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -104,6 +104,8 @@ Input::NamedVector StandardController::getAvailableInputs() const { makePair(RIGHT_HAND, "RightHand"), makePair(LEFT_FOOT, "LeftFoot"), makePair(RIGHT_FOOT, "RightFoot"), + makePair(RIGHT_ARM, "RightArm"), + makePair(LEFT_ARM, "LeftArm"), makePair(HIPS, "Hips"), makePair(SPINE2, "Spine2"), makePair(HEAD, "Head"), diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 3bda481243..8fa6f8b9f6 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -49,6 +49,9 @@ static const char* RENDER_CONTROLLERS = "Render Hand Controllers"; static const int MIN_PUCK_COUNT = 2; static const int MIN_FEET_AND_HIPS = 3; static const int MIN_FEET_HIPS_CHEST = 4; +static const int MIN_FEET_HIPS_SHOULDERS = 5; +static const int MIN_FEET_HIPS_CHEST_AND_HANDS = 6; +static const int MIN_FEET_HIPS_SHOULDERS_AND_HANDS = 7; static const int FIRST_FOOT = 0; static const int SECOND_FOOT = 1; static const int HIP = 2; @@ -330,26 +333,23 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; - auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; - controller::Pose& firstFootPose = firstFoot.second; - controller::Pose& secondFootPose = secondFoot.second; - - if (firstFootPose.translation.x < secondFootPose.translation.x) { - _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); - - } else { - _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, firstFootPose); - } - if (_config == Config::Feet) { - // done + auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; + auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; + controller::Pose& firstFootPose = firstFoot.second; + controller::Pose& secondFootPose = secondFoot.second; + + if (firstFootPose.translation.x < secondFootPose.translation.x) { + _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); + } else { + _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, firstFootPose); + } } else if (_config == Config::FeetAndHips && puckCount >= MIN_FEET_AND_HIPS) { _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); @@ -358,6 +358,7 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); + } else if (_config == Config::FeetHipsAndShoulders && puckCount >= MIN_FEET_HIPS_SHOULDERS){ } else { qDebug() << "Puck Calibration: " << configToString(_config) << " Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); @@ -379,6 +380,8 @@ void ViveControllerManager::InputDevice::updateCalibratedLimbs() { _poseStateMap[controller::RIGHT_FOOT] = addOffsetToPuckPose(controller::RIGHT_FOOT); _poseStateMap[controller::HIPS] = addOffsetToPuckPose(controller::HIPS); _poseStateMap[controller::SPINE2] = addOffsetToPuckPose(controller::SPINE2); + _poseStateMap[controller::RIGHT_ARM] = addOffsetToPuckPose(controller::RIGHT_ARM); + _poseStateMap[controller::LEFT_ARM] = addOffsetToPuckPose(controller::LEFT_ARM); } controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(int joint) const { @@ -707,6 +710,8 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(HIPS, "Hips"), makePair(SPINE2, "Spine2"), makePair(HEAD, "Head"), + makePair(LEFT_ARM, "LeftArm"), + makePair(RIGHT_ARM, "RightArm"), // 16 tracked poses makePair(TRACKED_OBJECT_00, "TrackedObject00"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index fa2566da45..186917de51 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -102,7 +102,17 @@ private: float _timer { 0.0f }; glm::vec2 _stick { 0.0f, 0.0f }; }; - enum class Config { Feet, FeetAndHips, FeetHipsAndChest, Auto }; + enum class Config { + Auto, + Feet, + Hands, + Shoulders, + FeetAndHips, + FeetHipsAndChest, + FeetHipsAndShoulders, + FeetHipsChestAndHands, + FeetHipsShouldersAndHands + }; Config _config { Config::Auto }; Config _preferedConfig { Config::Auto }; FilteredStick _filteredLeftStick; @@ -128,6 +138,7 @@ private: bool _triggersPressedHandled { false }; bool _calibrated { false }; bool _timeTilCalibrationSet { false }; + bool overrideHands { false }; mutable std::recursive_mutex _lock; QString configToString(Config config); From 10eb353126afa9239720adb59e36a75a1f29b459 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 May 2017 18:26:08 -0700 Subject: [PATCH 02/25] Ensure user never loses its running scripts --- interface/src/Application.cpp | 1 - libraries/script-engine/src/ScriptEngines.cpp | 101 +++++++++--------- libraries/script-engine/src/ScriptEngines.h | 1 - 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd66a96879..fc7ea6e692 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1622,7 +1622,6 @@ void Application::cleanupBeforeQuit() { // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); - DependencyManager::get()->saveScripts(); DependencyManager::get()->shutdownScripting(); // stop all currently running global scripts DependencyManager::destroy(); diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 2076657288..1cb0c117da 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -26,8 +26,12 @@ #define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: " static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - static const bool HIFI_SCRIPT_DEBUGGABLES { true }; +static const QString SETTINGS_KEY { "RunningScripts" }; +static const QUrl DEFAULT_SCRIPTS_LOCATION { "file:///~//defaultScripts.js" }; +// Using a QVariantList so this is human-readable in the settings file +static Setting::Handle runningScriptsHandle(SETTINGS_KEY, { QVariant(DEFAULT_SCRIPTS_LOCATION) }); + ScriptsModel& getScriptsModel() { static ScriptsModel scriptsModel; @@ -61,19 +65,6 @@ ScriptEngines::ScriptEngines(ScriptEngine::Context context) _scriptsModelFilter.setSourceModel(&_scriptsModel); _scriptsModelFilter.sort(0, Qt::AscendingOrder); _scriptsModelFilter.setDynamicSortFilter(true); - - static const int SCRIPT_SAVE_COUNTDOWN_INTERVAL_MS = 5000; - QTimer* scriptSaveTimer = new QTimer(this); - scriptSaveTimer->setSingleShot(true); - QMetaObject::Connection timerConnection = connect(scriptSaveTimer, &QTimer::timeout, [] { - DependencyManager::get()->saveScripts(); - }); - connect(qApp, &QCoreApplication::aboutToQuit, [=] { - disconnect(timerConnection); - }); - connect(this, &ScriptEngines::scriptCountChanged, this, [scriptSaveTimer] { - scriptSaveTimer->start(SCRIPT_SAVE_COUNTDOWN_INTERVAL_MS); - }, Qt::QueuedConnection); } QUrl normalizeScriptURL(const QUrl& rawScriptURL) { @@ -280,13 +271,8 @@ QVariantList ScriptEngines::getRunning() { return result; } - -static const QString SETTINGS_KEY = "RunningScripts"; - void ScriptEngines::loadDefaultScripts() { - QUrl defaultScriptsLoc = defaultScriptsLocation(); - defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "/defaultScripts.js"); - loadScript(defaultScriptsLoc.toString()); + loadScript(DEFAULT_SCRIPTS_LOCATION); } void ScriptEngines::loadOneScript(const QString& scriptFilename) { @@ -294,17 +280,11 @@ void ScriptEngines::loadOneScript(const QString& scriptFilename) { } void ScriptEngines::loadScripts() { - // check first run... - Setting::Handle firstRun { Settings::firstRun, true }; - if (firstRun.get()) { - qCDebug(scriptengine) << "This is a first run..."; - // clear the scripts, and set out script to our default scripts - clearScripts(); - loadDefaultScripts(); - return; - } - - // loads all saved scripts + // START BACKWARD COMPATIBILITY CODE + // The following code makes sure people don't lose all their scripts + // This should be removed after a reasonable ammount of time went by + // Load old setting format if present + bool foundDeprecatedSetting = false; Settings settings; int size = settings.beginReadArray(SETTINGS_KEY); for (int i = 0; i < size; ++i) { @@ -312,35 +292,51 @@ void ScriptEngines::loadScripts() { QString string = settings.value("script").toString(); if (!string.isEmpty()) { loadScript(string); + foundDeprecatedSetting = true; } } settings.endArray(); -} + if (foundDeprecatedSetting) { + // Remove old settings found and return + settings.beginWriteArray(SETTINGS_KEY); + settings.remove(""); + settings.endArray(); + settings.remove(SETTINGS_KEY + "/size"); + return; + } + // END BACKWARD COMPATIBILITY CODE -void ScriptEngines::clearScripts() { - // clears all scripts from the settingsSettings settings; - Settings settings; - settings.beginWriteArray(SETTINGS_KEY); - settings.remove(""); - settings.endArray(); + // loads all saved scripts + auto runningScripts = runningScriptsHandle.get(); + for (auto script : runningScripts) { + auto string = script.toString(); + if (!string.isEmpty()) { + loadScript(string); + } + } } void ScriptEngines::saveScripts() { - // Saves all currently running user-loaded scripts - Settings settings; - settings.beginWriteArray(SETTINGS_KEY); - settings.remove(""); + // Do not save anything if we are in the process of shutting down + if (qApp->closingDown()) { + qWarning() << "Trying to save scripts during shutdown."; + return; + } - QStringList runningScripts = getRunningScripts(); - int i = 0; - for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) { - if (getScriptEngine(*it)->isUserLoaded()) { - settings.setArrayIndex(i); - settings.setValue("script", normalizeScriptURL(*it).toString()); - ++i; + // Saves all currently running user-loaded scripts + QVariantList list; + + { + QReadLocker lock(&_scriptEnginesHashLock); + for (auto it = _scriptEnginesHash.begin(); it != _scriptEnginesHash.end(); ++it) { + if (it.value() && it.value()->isUserLoaded()) { + auto normalizedUrl = normalizeScriptURL(it.key()); + list.append(normalizedUrl.toString()); + } } } - settings.endArray(); + + runningScriptsHandle.set(list); } QStringList ScriptEngines::getRunningScripts() { @@ -513,6 +509,9 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { QUrl normalized = normalizeScriptURL(url); _scriptEnginesHash.insertMulti(normalized, scriptEngine); } + + // Update settings with new script + saveScripts(); emit scriptCountChanged(); } @@ -553,6 +552,8 @@ void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEngine* } if (removed) { + // Update settings with removed script + saveScripts(); emit scriptCountChanged(); } } diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 63b7e8f11c..5152c3952a 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -40,7 +40,6 @@ public: void loadScripts(); void saveScripts(); - void clearScripts(); QString getScriptsLocation() const; void loadDefaultScripts(); From ac3c9655ec105a72a5b5575d1b2838f52f903cab Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 24 May 2017 01:28:08 +0100 Subject: [PATCH 03/25] added arms --- .../resources/avatar/avatar-animation.json | 18 +++ interface/resources/controllers/standard.json | 4 +- interface/resources/controllers/vive.json | 4 +- interface/src/Application.cpp | 4 + interface/src/avatar/MyAvatar.cpp | 42 +++++-- interface/src/avatar/MyAvatar.h | 10 ++ interface/src/avatar/MySkeletonModel.cpp | 20 ++++ libraries/animation/src/Rig.cpp | 11 ++ libraries/animation/src/Rig.h | 6 + libraries/controllers/src/controllers/Input.h | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 112 ++++++++++++++---- plugins/openvr/src/ViveControllerManager.h | 17 ++- 12 files changed, 215 insertions(+), 35 deletions(-) diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index f88e322d99..7171d4c223 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -114,6 +114,24 @@ "weightVar": "headWeight", "weight": 4.0, "flexCoefficients": [1, 0.05, 0.25, 0.25, 0.25] + }, + { + "jointName": "LeftArm", + "positionVar": "leftArmPosition", + "rotationVar": "leftArmRotation", + "typeVar": "leftArmType", + "weightVar": "leftArmWeight", + "weight": 1.0, + "flexCoefficients": [1, 0.5, 0.25, 0.0, 0.0, 0.0] + }, + { + "jointName": "RightArm", + "positionVar": "rightArmPosition", + "rotationVar": "rightArmRotation", + "typeVar": "rightArmType", + "weightVar": "rightArmWeight", + "weight": 1.0, + "flexCoefficients": [1, 0.5, 0.25, 0.0, 0.0, 0.0] } ] }, diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 62eec9bc3c..75b4821118 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -66,6 +66,8 @@ { "from": "Standard.Hips", "to": "Actions.Hips" }, { "from": "Standard.Spine2", "to": "Actions.Spine2" }, - { "from": "Standard.Head", "to": "Actions.Head" } + { "from": "Standard.Head", "to": "Actions.Head" }, + { "from": "Standard.LeftArm", "to": "Actions.LeftArm" }, + { "from": "Standard.RightArm", "to": "Actions.RightArm" } ] } diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index 4491507a9c..803914670c 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -40,6 +40,8 @@ { "from": "Vive.RightFoot", "to" : "Standard.RightFoot", "when": [ "Application.InHMD"] }, { "from": "Vive.Hips", "to" : "Standard.Hips", "when": [ "Application.InHMD"] }, { "from": "Vive.Spine2", "to" : "Standard.Spine2", "when": [ "Application.InHMD"] }, - { "from": "Vive.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] } + { "from": "Vive.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] }, + { "from": "Vive.RightArm", "to" : "Standard.RightArm", "when" : [ "Application.InHMD"] }, + { "from": "Vive.LeftArm", "to" : "Standard.LeftArm", "when" : [ "Application.InHMD"] } ] } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3dfcbbe2c6..4f38877477 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4427,6 +4427,10 @@ void Application::update(float deltaTime) { controller::Pose headPose = userInputMapper->getPoseState(controller::Action::HEAD); myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); + controller::Pose leftArmPose = userInputMapper->getPoseState(controller::Action::LEFT_ARM); + controller::Pose rightArmPose = userInputMapper->getPoseState(controller::Action::RIGHT_ARM); + myAvatar->setArmControllerPosesInSensorFrame(leftArmPose.transform(avatarToSensorMatrix), rightArmPose.transform(avatarToSensorMatrix)); + updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateDialogs(deltaTime); // update various stats dialogs if present diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 647b7f6f05..9104111712 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1479,6 +1479,37 @@ controller::Pose MyAvatar::getHeadControllerPoseInAvatarFrame() const { return getHeadControllerPoseInWorldFrame().transform(invAvatarMatrix); } +void MyAvatar::setArmControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right) { + _leftArmControllerPoseInSensorFrameCache.set(left); + _rightArmControllerPoseInSensorFrameCache.set(right); +} + +controller::Pose MyAvatar::getLeftArmControllerInSensorFrame() const { + return _leftArmControllerPoseInSensorFrameCache.get(); +} + +controller::Pose MyAvatar::getRightArmControllerInSensorFrame() const { + return _rightArmControllerPoseInSensorFrameCache.get(); +} + +controller::Pose MyAvatar::getLeftArmControllerInWorldFrame() const { + return getLeftArmControllerInSensorFrame().transform(getSensorToWorldMatrix()); +} + +controller::Pose MyAvatar::getRightArmControllerInWorldFrame() const { + return getRightArmControllerInSensorFrame().transform(getSensorToWorldMatrix()); +} + +controller::Pose MyAvatar::getLeftArmControllerInAvatarFrame() const { + glm::mat4 worldToAvatarMat = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getLeftArmControllerInWorldFrame().transform(worldToAvatarMat); +} + +controller::Pose MyAvatar::getRightArmControllerInAvatarFrame() const { + glm::mat4 worldToAvatarMat = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getRightArmControllerInWorldFrame().transform(worldToAvatarMat); +} + void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; @@ -2794,7 +2825,7 @@ glm::mat4 MyAvatar::getRightFootCalibrationMat() const { glm::mat4 MyAvatar::getRightArmCalibrationMat() const { - int rightArmIndex = _rig->indexOfJoint("RightArm"); + int rightArmIndex = _skeletonModel->getRig().indexOfJoint("RightArm"); if (rightArmIndex >= 0) { auto rightArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightArmIndex); auto rightArmRot = getAbsoluteDefaultJointRotationInObjectFrame(rightArmIndex); @@ -2805,8 +2836,7 @@ glm::mat4 MyAvatar::getRightArmCalibrationMat() const { } glm::mat4 MyAvatar::getLeftArmCalibrationMat() const { - int leftArmIndex = _rig->indexOfJoint("LeftArm"); - auto skeleton = _rig->getAnimSkeleton(); + int leftArmIndex = _skeletonModel->getRig().indexOfJoint("LeftArm"); if (leftArmIndex >= 0) { auto leftArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftArmIndex); auto leftArmRot = getAbsoluteDefaultJointRotationInObjectFrame(leftArmIndex); @@ -2817,8 +2847,7 @@ glm::mat4 MyAvatar::getLeftArmCalibrationMat() const { } glm::mat4 MyAvatar::getRightHandCalibrationMat() const { - int rightHandIndex = _rig->indexOfJoint("RightHand"); - auto skeleton = _rig->getAnimSkeleton(); + int rightHandIndex = _skeletonModel->getRig().indexOfJoint("RightHand"); if (rightHandIndex >= 0) { auto rightHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightHandIndex); auto rightHandRot = getAbsoluteDefaultJointRotationInObjectFrame(rightHandIndex); @@ -2829,8 +2858,7 @@ glm::mat4 MyAvatar::getRightHandCalibrationMat() const { } glm::mat4 MyAvatar::getLeftHandCalibrationMat() const { - int leftHandIndex = _rig->indexOfJoint("LeftHand"); - auto skeleton = _rig->getAnimSkeleton(); + int leftHandIndex = _skeletonModel->getRig().indexOfJoint("LeftHand"); if (leftHandIndex >= 0) { auto leftHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftHandIndex); auto leftHandRot = getAbsoluteDefaultJointRotationInObjectFrame(leftHandIndex); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index f896518b08..9bbdbd7b23 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -471,6 +471,14 @@ public: controller::Pose getHeadControllerPoseInWorldFrame() const; controller::Pose getHeadControllerPoseInAvatarFrame() const; + void setArmControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right); + controller::Pose getLeftArmControllerInSensorFrame() const; + controller::Pose getRightArmControllerInSensorFrame() const; + controller::Pose getLeftArmControllerInWorldFrame() const; + controller::Pose getRightArmControllerInWorldFrame() const; + controller::Pose getLeftArmControllerInAvatarFrame() const; + controller::Pose getRightArmControllerInAvatarFrame() const; + bool hasDriveInput() const; Q_INVOKABLE void setCollisionsEnabled(bool enabled); @@ -741,6 +749,8 @@ private: ThreadSafeValueCache _hipsControllerPoseInSensorFrameCache{ controller::Pose() }; ThreadSafeValueCache _spine2ControllerPoseInSensorFrameCache{ controller::Pose() }; ThreadSafeValueCache _headControllerPoseInSensorFrameCache{ controller::Pose() }; + ThreadSafeValueCache _leftArmControllerPoseInSensorFrameCache{ controller::Pose() }; + ThreadSafeValueCache _rightArmControllerPoseInSensorFrameCache{ controller::Pose() }; bool _hmdLeanRecenterEnabled = true; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 828a5f8a01..ea97e3d0fe 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -92,6 +92,26 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { headParams.spine2Enabled = false; } + auto avatarRightArmPose = myAvatar->getRightArmControllerInAvatarFrame(); + if (avatarRightArmPose.isValid()) { + glm::mat4 rightArmMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarRightArmPose.getRotation(), avatarRightArmPose.getTranslation()); + headParams.rightArmPosition = extractTranslation(rightArmMat); + headParams.rightArmRotation = glmExtractRotation(rightArmMat); + headParams.rightArmEnabled = true; + } else { + headParams.rightArmEnabled = false; + } + + auto avatarLeftArmPose = myAvatar->getLeftArmControllerInAvatarFrame(); + if (avatarLeftArmPose.isValid()) { + glm::mat4 leftArmMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarLeftArmPose.getRotation(), avatarLeftArmPose.getTranslation()); + headParams.leftArmPosition = extractTranslation(leftArmMat); + headParams.leftArmRotation = glmExtractRotation(leftArmMat); + headParams.leftArmEnabled = true; + } else { + headParams.leftArmEnabled = false; + } + headParams.isTalking = head->getTimeWithoutTalking() <= 1.5f; _rig.updateFromHeadParameters(headParams, deltaTime); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 99d2deb323..c74b8c478b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1047,6 +1047,17 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { } else { _animVars.set("spine2Type", (int)IKTarget::Type::Unknown); } + + if (params.leftArmEnabled) { + + } else { + _animVars.set("leftArmType", (int)IKTarget::Type::Unknown); + } + + if (params.rightArmEnabled) { + } else { + _animVars.set("rightArmType", (int)IKTarget::Type::Unknown); + } } void Rig::updateFromEyeParameters(const EyeParameters& params) { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 18780d6e64..c9d52d8c72 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -46,9 +46,15 @@ public: glm::mat4 spine2Matrix = glm::mat4(); // rig space glm::quat rigHeadOrientation = glm::quat(); // rig space (-z forward) glm::vec3 rigHeadPosition = glm::vec3(); // rig space + glm::vec3 rightArmPosition = glm::vec3(); // rig space + glm::quat rightArmRotation = glm::quat(); // rig space + glm::vec3 leftArmPosition = glm::vec3(); // rig space + glm::quat leftArmRotation = glm::quat(); // rig space bool hipsEnabled = false; bool headEnabled = false; bool spine2Enabled = false; + bool leftArmEnabled = false; + bool rightArmEnabled = false; bool isTalking = false; }; diff --git a/libraries/controllers/src/controllers/Input.h b/libraries/controllers/src/controllers/Input.h index 7780e91769..b74ad48c6f 100644 --- a/libraries/controllers/src/controllers/Input.h +++ b/libraries/controllers/src/controllers/Input.h @@ -25,7 +25,7 @@ struct InputCalibrationData { glm::mat4 defaultHips; // default pose for hips joint in avatar space glm::mat4 defaultLeftFoot; // default pose for leftFoot joint in avatar space glm::mat4 defaultRightFoot; // default pose for rightFoot joint in avatar space - glm::mat4 defaultRigtArm; // default pose for rightArm joint in avatar space + glm::mat4 defaultRightArm; // default pose for rightArm joint in avatar space glm::mat4 defaultLeftArm; // default pose for leftArm joint in avatar space glm::mat4 defaultRightHand; // default pose for rightHand joint in avatar space glm::mat4 defaultLeftHand; // default pose for leftHand joint in avatar space diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8fa6f8b9f6..5e509f43b8 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -33,6 +33,7 @@ #include + extern PoseData _nextSimPoseData; vr::IVRSystem* acquireOpenVrSystem(); @@ -73,10 +74,14 @@ static glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaul return glm::inverse(poseMat) * referenceJointMat; } -static bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { +static bool sortPucksYPosition(PuckPosePair firstPuck, PuckPosePair secondPuck) { return (firstPuck.second.translation.y < secondPuck.second.translation.y); } +static bool sortPucksXPosition(PuckPosePair firstPuck, PuckPosePair secondPuck) { + return (firstPuck.second.translation.x < secondPuck.second.translation.x); +} + static QString deviceTrackingResultToString(vr::ETrackingResult trackingResult) { QString result; auto iterator = TRACKING_RESULT_TO_STRING.find(trackingResult); @@ -172,6 +177,8 @@ ViveControllerManager::InputDevice::InputDevice(vr::IVRSystem*& system) : contro _configStringMap[Config::Feet] = QString("Feet"); _configStringMap[Config::FeetAndHips] = QString("FeetAndHips"); _configStringMap[Config::FeetHipsAndChest] = QString("FeetHipsAndChest"); + _configStringMap[Config::FeetHipsAndShoulders] = QString("FeetHipsAndShoulders"); + _configStringMap[Config::FeetAndShoulders] = QString("FeetAndShoulders"); } void ViveControllerManager::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { @@ -334,31 +341,25 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); if (_config == Config::Feet) { - auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; - auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; - controller::Pose& firstFootPose = firstFoot.second; - controller::Pose& secondFootPose = secondFoot.second; - - if (firstFootPose.translation.x < secondFootPose.translation.x) { - _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); - } else { - _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); - _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; - _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, firstFootPose); - } + calibrateFeet(defaultToReferenceMat, inputCalibration); + } else if (_config == Config::FeetAndShoulders && puckCount >= MIN_FEET_HIPS_CHEST) { + calibrateFeet(defaultToReferenceMat, inputCalibration); + int firstShoulder = 2; + int secondShoulder = 3; + calibrateShoulders(defaultToReferenceMat, inputCalibration, firstShoulder, secondShoulder); } else if (_config == Config::FeetAndHips && puckCount >= MIN_FEET_AND_HIPS) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; - _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); + calibrateFeet(defaultToReferenceMat, inputCalibration); + calibrateHips(defaultToReferenceMat, inputCalibration); } else if (_config == Config::FeetHipsAndChest && puckCount >= MIN_FEET_HIPS_CHEST) { - _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; - _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); - _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; - _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); + calibrateFeet(defaultToReferenceMat, inputCalibration); + calibrateHips(defaultToReferenceMat, inputCalibration); + calibrateChest(defaultToReferenceMat, inputCalibration); } else if (_config == Config::FeetHipsAndShoulders && puckCount >= MIN_FEET_HIPS_SHOULDERS){ + calibrateFeet(defaultToReferenceMat, inputCalibration); + calibrateHips(defaultToReferenceMat, inputCalibration); + int firstShoulderIndex = 3; + int secondShoulderIndex = 4; + calibrateShoulders(defaultToReferenceMat, inputCalibration, firstShoulderIndex, secondShoulderIndex); } else { qDebug() << "Puck Calibration: " << configToString(_config) << " Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); @@ -615,6 +616,65 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef } } +void ViveControllerManager::InputDevice::calibrateFeet(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { + auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; + auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; + controller::Pose& firstFootPose = firstFoot.second; + controller::Pose& secondFootPose = secondFoot.second; + + if (firstFootPose.translation.x < secondFootPose.translation.x) { + _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); + } else { + _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); + _jointToPuckMap[controller::RIGHT_FOOT] = firstFoot.first; + _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, firstFootPose); + } +} + +void ViveControllerManager::InputDevice::calibrateHips(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { + _jointToPuckMap[controller::HIPS] = _validTrackedObjects[HIP].first; + _pucksOffset[_validTrackedObjects[HIP].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHips, _validTrackedObjects[HIP].second); +} + +void ViveControllerManager::InputDevice::calibrateChest(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { + _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; + _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); +} + +void ViveControllerManager::InputDevice::calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, + int firstShoulderIndex, int secondShoulderIndex) { + qDebug() << "calibrate shoulders"; + const PuckPosePair& firstShoulder = _validTrackedObjects[firstShoulderIndex]; + const PuckPosePair& secondShoulder = _validTrackedObjects[secondShoulderIndex]; + const controller::Pose& firstShoulderPose = firstShoulder.second; + const controller::Pose& secondShoulderPose = secondShoulder.second; + + if (firstShoulderPose.translation.x < secondShoulderPose.translation.x) { + _jointToPuckMap[controller::LEFT_ARM] = firstShoulder.first; + _pucksOffset[firstShoulder.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftArm, firstShoulder.second); + _jointToPuckMap[controller::RIGHT_ARM] = secondShoulder.first; + _pucksOffset[secondShoulder.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightArm, secondShoulder.second); + } else { + _jointToPuckMap[controller::LEFT_ARM] = secondShoulder.first; + _pucksOffset[secondShoulder.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftArm, secondShoulder.second); + _jointToPuckMap[controller::RIGHT_ARM] = firstShoulder.first; + _pucksOffset[firstShoulder.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightArm, firstShoulder.second); + } +} + +void ViveControllerManager::InputDevice::calibrateHands(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, + PuckPosePair firstHand, PuckPosePair secondHand) { +} + +void ViveControllerManager::InputDevice::calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { + int headIndex = _validTrackedObjects.size() - 1; +} + + void ViveControllerManager::InputDevice::loadSettings() { Settings settings; settings.beginGroup("PUCK_CONFIG"); @@ -646,6 +706,10 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu _preferedConfig = Config::FeetAndHips; } else if (value == "FeetHipsAndChest") { _preferedConfig = Config::FeetHipsAndChest; + } else if (value == "FeetHipsAndShoulders") { + _preferedConfig = Config::FeetHipsAndShoulders; + } else if (value == "FeetAndShoulders") { + _preferedConfig = Config::FeetAndShoulders; } } @@ -658,7 +722,7 @@ void ViveControllerManager::InputDevice::createPreferences() { auto getter = [this]()->QString { return _configStringMap[_preferedConfig]; }; auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); - QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest"); + QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest" << "FeetAndShoulders"); preference->setItems(list); preferences->addPreference(preference); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 186917de51..1fd11ccfe6 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -27,6 +27,8 @@ #include #include "OpenVrHelpers.h" +using PuckPosePair = std::pair; + namespace vr { class IVRSystem; } @@ -104,10 +106,12 @@ private: }; enum class Config { Auto, + Head, Feet, Hands, Shoulders, FeetAndHips, + FeetAndShoulders, FeetHipsAndChest, FeetHipsAndShoulders, FeetHipsChestAndHands, @@ -118,7 +122,7 @@ private: FilteredStick _filteredLeftStick; FilteredStick _filteredRightStick; - std::vector> _validTrackedObjects; + std::vector _validTrackedObjects; std::map _pucksOffset; std::map _jointToPuckMap; std::map _configStringMap; @@ -145,6 +149,17 @@ private: void setConfigFromString(const QString& value); void loadSettings(); void saveSettings() const; + void calibrateFeet(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + void calibrateHips(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + void calibrateChest(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + + void calibrateHands(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, + PuckPosePair firstHand, PuckPosePair secondHand); + + void calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, + int firstShoulderIndex, int secondShoulderIndex); + + void calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); friend class ViveControllerManager; }; From 077e56a96fc98d0892485a25b1c94e2882ef9ff3 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 13 May 2017 18:07:35 -0700 Subject: [PATCH 04/25] Add KTX validation routines --- libraries/ktx/src/ktx/KTX.h | 169 ++++++------ libraries/ktx/src/ktx/Validation.cpp | 376 +++++++++++++++++++++++++++ tests/ktx/src/main.cpp | 60 ++++- 3 files changed, 522 insertions(+), 83 deletions(-) create mode 100644 libraries/ktx/src/ktx/Validation.cpp diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 3f220abac3..6dc8e01131 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -180,105 +180,107 @@ namespace ktx { RGB16F = 0x881B, RGBA16F = 0x881A, - R32F = 0x822E, - RG32F = 0x8230, - RGB32F = 0x8815, - RGBA32F = 0x8814, + R32F = 0x822E, + RG32F = 0x8230, + RGB32F = 0x8815, + RGBA32F = 0x8814, - R11F_G11F_B10F = 0x8C3A, - RGB9_E5 = 0x8C3D, + R11F_G11F_B10F = 0x8C3A, + RGB9_E5 = 0x8C3D, - R8I = 0x8231, - R8UI = 0x8232, - R16I = 0x8233, - R16UI = 0x8234, - R32I = 0x8235, - R32UI = 0x8236, - RG8I = 0x8237, - RG8UI = 0x8238, - RG16I = 0x8239, - RG16UI = 0x823A, - RG32I = 0x823B, - RG32UI = 0x823C, + R8I = 0x8231, + R8UI = 0x8232, + R16I = 0x8233, + R16UI = 0x8234, + R32I = 0x8235, + R32UI = 0x8236, + RG8I = 0x8237, + RG8UI = 0x8238, + RG16I = 0x8239, + RG16UI = 0x823A, + RG32I = 0x823B, + RG32UI = 0x823C, - RGB8I = 0x8D8F, - RGB8UI = 0x8D7D, - RGB16I = 0x8D89, - RGB16UI = 0x8D77, + RGB8I = 0x8D8F, + RGB8UI = 0x8D7D, + RGB16I = 0x8D89, + RGB16UI = 0x8D77, - RGB32I = 0x8D83, - RGB32UI = 0x8D71, - RGBA8I = 0x8D8E, - RGBA8UI = 0x8D7C, - RGBA16I = 0x8D88, - RGBA16UI = 0x8D76, - RGBA32I = 0x8D82, + RGB32I = 0x8D83, + RGB32UI = 0x8D71, + RGBA8I = 0x8D8E, + RGBA8UI = 0x8D7C, + RGBA16I = 0x8D88, + RGBA16UI = 0x8D76, + RGBA32I = 0x8D82, - RGBA32UI = 0x8D70, + RGBA32UI = 0x8D70, // GL 4.4 Table 8.13 - DEPTH_COMPONENT16 = 0x81A5, - DEPTH_COMPONENT24 = 0x81A6, - DEPTH_COMPONENT32 = 0x81A7, + DEPTH_COMPONENT16 = 0x81A5, + DEPTH_COMPONENT24 = 0x81A6, + DEPTH_COMPONENT32 = 0x81A7, - DEPTH_COMPONENT32F = 0x8CAC, - DEPTH24_STENCIL8 = 0x88F0, - DEPTH32F_STENCIL8 = 0x8CAD, + DEPTH_COMPONENT32F = 0x8CAC, + DEPTH24_STENCIL8 = 0x88F0, + DEPTH32F_STENCIL8 = 0x8CAD, - STENCIL_INDEX1 = 0x8D46, - STENCIL_INDEX4 = 0x8D47, - STENCIL_INDEX8 = 0x8D48, - STENCIL_INDEX16 = 0x8D49, + STENCIL_INDEX1 = 0x8D46, + STENCIL_INDEX4 = 0x8D47, + STENCIL_INDEX8 = 0x8D48, + STENCIL_INDEX16 = 0x8D49, }; enum class GLInternalFormat_Compressed : uint32_t { // GL 4.4 Table 8.14 - COMPRESSED_RED = 0x8225, - COMPRESSED_RG = 0x8226, - COMPRESSED_RGB = 0x84ED, - COMPRESSED_RGBA = 0x84EE, + COMPRESSED_RED = 0x8225, + COMPRESSED_RG = 0x8226, + COMPRESSED_RGB = 0x84ED, + COMPRESSED_RGBA = 0x84EE, - COMPRESSED_SRGB = 0x8C48, - COMPRESSED_SRGB_ALPHA = 0x8C49, + COMPRESSED_SRGB = 0x8C48, + COMPRESSED_SRGB_ALPHA = 0x8C49, - COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, - COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D, - COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E, - COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, + COMPRESSED_ETC1_RGB8_OES = 0x8D64, - COMPRESSED_RED_RGTC1 = 0x8DBB, - COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, - COMPRESSED_RG_RGTC2 = 0x8DBD, - COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE, + COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D, + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E, + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, - COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C, - COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D, - COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E, - COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F, + COMPRESSED_RED_RGTC1 = 0x8DBB, + COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, + COMPRESSED_RG_RGTC2 = 0x8DBD, + COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE, - COMPRESSED_RGB8_ETC2 = 0x9274, - COMPRESSED_SRGB8_ETC2 = 0x9275, - COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276, - COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277, - COMPRESSED_RGBA8_ETC2_EAC = 0x9278, - COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279, + COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C, + COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D, + COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E, + COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F, - COMPRESSED_R11_EAC = 0x9270, - COMPRESSED_SIGNED_R11_EAC = 0x9271, - COMPRESSED_RG11_EAC = 0x9272, - COMPRESSED_SIGNED_RG11_EAC = 0x9273, + COMPRESSED_RGB8_ETC2 = 0x9274, + COMPRESSED_SRGB8_ETC2 = 0x9275, + COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276, + COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277, + COMPRESSED_RGBA8_ETC2_EAC = 0x9278, + COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279, + + COMPRESSED_R11_EAC = 0x9270, + COMPRESSED_SIGNED_R11_EAC = 0x9271, + COMPRESSED_RG11_EAC = 0x9272, + COMPRESSED_SIGNED_RG11_EAC = 0x9273, }; enum class GLBaseInternalFormat : uint32_t { // GL 4.4 Table 8.11 - DEPTH_COMPONENT = 0x1902, - DEPTH_STENCIL = 0x84F9, - RED = 0x1903, - RG = 0x8227, - RGB = 0x1907, - RGBA = 0x1908, - STENCIL_INDEX = 0x1901, + DEPTH_COMPONENT = 0x1902, + DEPTH_STENCIL = 0x84F9, + RED = 0x1903, + RG = 0x8227, + RGB = 0x1907, + RGBA = 0x1908, + STENCIL_INDEX = 0x1901, }; enum CubeMapFace { @@ -316,14 +318,14 @@ namespace ktx { Byte identifier[IDENTIFIER_LENGTH]; uint32_t endianness { ENDIAN_TEST }; - uint32_t glType; + uint32_t glType { static_cast(GLType::UNSIGNED_BYTE) }; uint32_t glTypeSize { 0 }; - uint32_t glFormat; - uint32_t glInternalFormat; - uint32_t glBaseInternalFormat; + uint32_t glFormat { static_cast(GLFormat::RGBA) }; + uint32_t glInternalFormat { static_cast(GLInternalFormat_Uncompressed::RGBA8) }; + uint32_t glBaseInternalFormat { static_cast(GLBaseInternalFormat::RGBA) }; uint32_t pixelWidth { 1 }; - uint32_t pixelHeight { 0 }; + uint32_t pixelHeight { 1 }; uint32_t pixelDepth { 0 }; uint32_t numberOfArrayElements { 0 }; uint32_t numberOfFaces { 1 }; @@ -386,8 +388,12 @@ namespace ktx { void setCube(uint32_t width, uint32_t height) { setDimensions(width, height, 0, 0, NUM_CUBEMAPFACES); } void setCubeArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1), NUM_CUBEMAPFACES); } + bool isValid() const; + + // Generate a set of image descriptors based on the assumption that the full mip pyramid is populated ImageDescriptors generateImageDescriptors() const; }; + static const size_t KTX_HEADER_SIZE = 64; static_assert(sizeof(Header) == KTX_HEADER_SIZE, "KTX Header size is static and should not change from the spec"); static const size_t KV_SIZE_WIDTH = 4; // Number of bytes for keyAndValueByteSize @@ -426,6 +432,7 @@ namespace ktx { const uint32_t _imageSize; const uint32_t _faceSize; const uint32_t _padding; + ImageHeader(bool cube, size_t imageOffset, uint32_t imageSize, uint32_t padding) : _numFaces(cube ? NUM_CUBEMAPFACES : 1), _imageOffset(imageOffset), @@ -486,6 +493,8 @@ namespace ktx { public: ~KTX(); + static bool validate(const StoragePointer& src); + // Define a KTX object manually to write it somewhere (in a file on disk?) // This path allocate the Storage where to store header, keyvalues and copy mips // Then COPY all the data diff --git a/libraries/ktx/src/ktx/Validation.cpp b/libraries/ktx/src/ktx/Validation.cpp new file mode 100644 index 0000000000..74af58d311 --- /dev/null +++ b/libraries/ktx/src/ktx/Validation.cpp @@ -0,0 +1,376 @@ +// +// Created by Bradley Austin Davis on 2017/05/13 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "KTX.h" + +#include +#include + +using namespace ktx; + +static const std::unordered_set VALID_GL_TYPES { + (uint32_t)GLType::UNSIGNED_BYTE, + (uint32_t)GLType::BYTE, + (uint32_t)GLType::UNSIGNED_SHORT, + (uint32_t)GLType::SHORT, + (uint32_t)GLType::UNSIGNED_INT, + (uint32_t)GLType::INT, + (uint32_t)GLType::HALF_FLOAT, + (uint32_t)GLType::FLOAT, + (uint32_t)GLType::UNSIGNED_BYTE_3_3_2, + (uint32_t)GLType::UNSIGNED_BYTE_2_3_3_REV, + (uint32_t)GLType::UNSIGNED_SHORT_5_6_5, + (uint32_t)GLType::UNSIGNED_SHORT_5_6_5_REV, + (uint32_t)GLType::UNSIGNED_SHORT_4_4_4_4, + (uint32_t)GLType::UNSIGNED_SHORT_4_4_4_4_REV, + (uint32_t)GLType::UNSIGNED_SHORT_5_5_5_1, + (uint32_t)GLType::UNSIGNED_SHORT_1_5_5_5_REV, + (uint32_t)GLType::UNSIGNED_INT_8_8_8_8, + (uint32_t)GLType::UNSIGNED_INT_8_8_8_8_REV, + (uint32_t)GLType::UNSIGNED_INT_10_10_10_2, + (uint32_t)GLType::UNSIGNED_INT_2_10_10_10_REV, + (uint32_t)GLType::UNSIGNED_INT_24_8, + (uint32_t)GLType::UNSIGNED_INT_10F_11F_11F_REV, + (uint32_t)GLType::UNSIGNED_INT_5_9_9_9_REV, + (uint32_t)GLType::FLOAT_32_UNSIGNED_INT_24_8_REV, +}; + +static const std::unordered_set VALID_GL_FORMATS { + (uint32_t)GLFormat::STENCIL_INDEX, + (uint32_t)GLFormat::DEPTH_COMPONENT, + (uint32_t)GLFormat::DEPTH_STENCIL, + (uint32_t)GLFormat::RED, + (uint32_t)GLFormat::GREEN, + (uint32_t)GLFormat::BLUE, + (uint32_t)GLFormat::RG, + (uint32_t)GLFormat::RGB, + (uint32_t)GLFormat::RGBA, + (uint32_t)GLFormat::BGR, + (uint32_t)GLFormat::BGRA, + (uint32_t)GLFormat::RG_INTEGER, + (uint32_t)GLFormat::RED_INTEGER, + (uint32_t)GLFormat::GREEN_INTEGER, + (uint32_t)GLFormat::BLUE_INTEGER, + (uint32_t)GLFormat::RGB_INTEGER, + (uint32_t)GLFormat::RGBA_INTEGER, + (uint32_t)GLFormat::BGR_INTEGER, + (uint32_t)GLFormat::BGRA_INTEGER, +}; + +static const std::unordered_set VALID_GL_INTERNAL_FORMATS { + (uint32_t)GLInternalFormat_Uncompressed::R8, + (uint32_t)GLInternalFormat_Uncompressed::R8_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::R16, + (uint32_t)GLInternalFormat_Uncompressed::R16_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::RG8, + (uint32_t)GLInternalFormat_Uncompressed::RG8_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::RG16, + (uint32_t)GLInternalFormat_Uncompressed::RG16_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::R3_G3_B2, + (uint32_t)GLInternalFormat_Uncompressed::RGB4, + (uint32_t)GLInternalFormat_Uncompressed::RGB5, + (uint32_t)GLInternalFormat_Uncompressed::RGB565, + (uint32_t)GLInternalFormat_Uncompressed::RGB8, + (uint32_t)GLInternalFormat_Uncompressed::RGB8_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::RGB10, + (uint32_t)GLInternalFormat_Uncompressed::RGB12, + (uint32_t)GLInternalFormat_Uncompressed::RGB16, + (uint32_t)GLInternalFormat_Uncompressed::RGB16_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::RGBA2, + (uint32_t)GLInternalFormat_Uncompressed::RGBA4, + (uint32_t)GLInternalFormat_Uncompressed::RGB5_A1, + (uint32_t)GLInternalFormat_Uncompressed::RGBA8, + (uint32_t)GLInternalFormat_Uncompressed::RGBA8_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::RGB10_A2, + (uint32_t)GLInternalFormat_Uncompressed::RGB10_A2UI, + (uint32_t)GLInternalFormat_Uncompressed::RGBA12, + (uint32_t)GLInternalFormat_Uncompressed::RGBA16, + (uint32_t)GLInternalFormat_Uncompressed::RGBA16_SNORM, + (uint32_t)GLInternalFormat_Uncompressed::SRGB8, + (uint32_t)GLInternalFormat_Uncompressed::SRGB8_ALPHA8, + (uint32_t)GLInternalFormat_Uncompressed::R16F, + (uint32_t)GLInternalFormat_Uncompressed::RG16F, + (uint32_t)GLInternalFormat_Uncompressed::RGB16F, + (uint32_t)GLInternalFormat_Uncompressed::RGBA16F, + (uint32_t)GLInternalFormat_Uncompressed::R32F, + (uint32_t)GLInternalFormat_Uncompressed::RG32F, + (uint32_t)GLInternalFormat_Uncompressed::RGBA32F, + (uint32_t)GLInternalFormat_Uncompressed::R11F_G11F_B10F, + (uint32_t)GLInternalFormat_Uncompressed::RGB9_E5, + (uint32_t)GLInternalFormat_Uncompressed::R8I, + (uint32_t)GLInternalFormat_Uncompressed::R8UI, + (uint32_t)GLInternalFormat_Uncompressed::R16I, + (uint32_t)GLInternalFormat_Uncompressed::R16UI, + (uint32_t)GLInternalFormat_Uncompressed::R32I, + (uint32_t)GLInternalFormat_Uncompressed::R32UI, + (uint32_t)GLInternalFormat_Uncompressed::RG8I, + (uint32_t)GLInternalFormat_Uncompressed::RG8UI, + (uint32_t)GLInternalFormat_Uncompressed::RG16I, + (uint32_t)GLInternalFormat_Uncompressed::RG16UI, + (uint32_t)GLInternalFormat_Uncompressed::RG32I, + (uint32_t)GLInternalFormat_Uncompressed::RG32UI, + (uint32_t)GLInternalFormat_Uncompressed::RGB8I, + (uint32_t)GLInternalFormat_Uncompressed::RGB8UI, + (uint32_t)GLInternalFormat_Uncompressed::RGB16I, + (uint32_t)GLInternalFormat_Uncompressed::RGB16UI, + (uint32_t)GLInternalFormat_Uncompressed::RGB32I, + (uint32_t)GLInternalFormat_Uncompressed::RGB32UI, + (uint32_t)GLInternalFormat_Uncompressed::RGBA8I, + (uint32_t)GLInternalFormat_Uncompressed::RGBA8UI, + (uint32_t)GLInternalFormat_Uncompressed::RGBA16I, + (uint32_t)GLInternalFormat_Uncompressed::RGBA16UI, + (uint32_t)GLInternalFormat_Uncompressed::RGBA32I, + (uint32_t)GLInternalFormat_Uncompressed::RGBA32UI, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT16, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT24, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32F, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH24_STENCIL8, + (uint32_t)GLInternalFormat_Uncompressed::DEPTH32F_STENCIL8, + (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX1, + (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX4, + (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX8, + (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX16, +}; + +static const std::unordered_set VALID_GL_INTERNAL_COMPRESSED_FORMATS { + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_ETC1_RGB8_OES, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RED_RGTC1, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG_RGTC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA_BPTC_UNORM, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_SIGNED_FLOAT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_ETC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ETC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA8_ETC2_EAC, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_R11_EAC, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_R11_EAC, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG11_EAC, + (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG11_EAC, +}; + +static const std::unordered_set VALID_GL_BASE_INTERNAL_FORMATS { + (uint32_t)GLBaseInternalFormat::DEPTH_COMPONENT, + (uint32_t)GLBaseInternalFormat::DEPTH_STENCIL, + (uint32_t)GLBaseInternalFormat::RED, + (uint32_t)GLBaseInternalFormat::RG, + (uint32_t)GLBaseInternalFormat::RGB, + (uint32_t)GLBaseInternalFormat::RGBA, + (uint32_t)GLBaseInternalFormat::STENCIL_INDEX, +}; + +bool Header::isValid() const { + if (0 != memcmp(identifier, IDENTIFIER.data(), IDENTIFIER_LENGTH)) { + qDebug() << "Invalid header identifier"; + return false; + } + + if (endianness != ENDIAN_TEST && endianness != REVERSE_ENDIAN_TEST) { + qDebug("Invalid endian marker 0x%x", endianness); + return false; + } + + // + // GL enum validity + // + if (VALID_GL_BASE_INTERNAL_FORMATS.count(glBaseInternalFormat) != 1) { + qDebug("Invalid base internal format 0x%x", glBaseInternalFormat); + return false; + } + + if (glFormat == (uint32_t)GLFormat::COMPRESSED_FORMAT && glType == (uint32_t)GLType::COMPRESSED_TYPE) { + if (VALID_GL_INTERNAL_COMPRESSED_FORMATS.count(glInternalFormat) != 1) { + qDebug("Invalid compressed internal format 0x%x", glInternalFormat); + return false; + } + } else { + if (VALID_GL_TYPES.count(glType) != 1) { + qDebug("Invalid type 0x%x", glType); + return false; + } + + if (VALID_GL_FORMATS.count(glFormat) != 1) { + qDebug("Invalid format 0x%x", glFormat); + return false; + } + + if (VALID_GL_INTERNAL_FORMATS.count(glInternalFormat) != 1) { + qDebug("Invalid internal format 0x%x", glInternalFormat); + return false; + } + } + + // + // Dimensions validity + // + + // Textures must at least have a width + // If they have a depth, they must have a height + if ((pixelWidth == 0) || (pixelDepth != 0 && pixelHeight == 0)) { + qDebug() << "Invalid dimensions " << pixelWidth << "x" << pixelHeight << "x" << pixelDepth; + return false; + } + + + if (numberOfFaces != 1 && numberOfFaces != NUM_CUBEMAPFACES) { + qDebug() << "Invalid number of faces " << numberOfFaces; + return false; + } + + // FIXME validate numberOfMipmapLevels based on the dimensions? + + if ((bytesOfKeyValueData % 4) != 0) { + qDebug() << "Invalid keyvalue data size " << numberOfFaces; + return false; + } + + return true; +} + +struct AlignedStreamBuffer { + AlignedStreamBuffer(size_t size, const uint8_t* data) + : _size(size), _data(data) { } + + AlignedStreamBuffer(const StoragePointer& storage) + : AlignedStreamBuffer(storage->size(), storage->data()) { } + + + template + bool read(T& t) { + // Ensure we don't read more than we have + if (sizeof(T) > _size) { + return false; + } + + // Grab the data + memcpy(&t, _data, sizeof(T)); + + // Advance the pointer + return skip(sizeof(T)); + } + + bool skip(size_t skipSize) { + if ((skipSize % 4) != 0) { + skipSize += (3 - ((skipSize + 3) % 4)); + } + if (skipSize > _size) { + return false; + } + _data += skipSize; + _size -= skipSize; + return true; + } + + AlignedStreamBuffer front(size_t size) const { + return AlignedStreamBuffer { std::min(size, _size), _data }; + } + + bool empty() const { + return _size == 0; + } + +private: + size_t _size; + const uint8_t* _data; +}; + +bool validateKeyValueData(AlignedStreamBuffer kvbuffer) { + while (!kvbuffer.empty()) { + uint32_t keyValueSize; + // Try to fetch the size of the next key value block + if (!kvbuffer.read(keyValueSize)) { + qDebug() << "Unable to read past key value size"; + return false; + } + if (!kvbuffer.skip(keyValueSize)) { + qDebug() << "Unable to skip past key value data"; + return false; + } + } + + return true; +} + +bool KTX::validate(const StoragePointer& src) { + if ((src->size() % 4) != 0) { + // All KTX data is 4-byte aligned + qDebug() << "Invalid size, not 4 byte aligned"; + return false; + } + + Header header; + AlignedStreamBuffer buffer { src }; + if (!buffer.read(header)) { + qDebug() << "Unable to read header"; + return false; + } + + // Basic header validation, are the enums and size valid? + if (!header.isValid()) { + qDebug() << "Invalid header"; + return false; + } + + // Validate the key value pairs + if (!validateKeyValueData(buffer.front(header.bytesOfKeyValueData))) { + qDebug() << "Invalid key value data"; + return false; + } + + // now skip the KV data + if (!buffer.skip(header.bytesOfKeyValueData)) { + qDebug() << "Unable to read past key value data"; + return false; + } + + + // Validate the images + for (uint32_t mip = 0; mip < header.numberOfMipmapLevels; ++mip) { + uint32_t imageSize; + if (!buffer.read(imageSize)) { + qDebug() << "Unable to read image size"; + return false; + } + + if (header.numberOfArrayElements == 0 && header.numberOfFaces == 6) { + for (uint8_t face = 0; face < NUM_CUBEMAPFACES; ++face) { + if (!buffer.skip(imageSize)) { + qDebug() << "Unable to skip past cubemap data"; + return false; + } + } + } else { + if (!buffer.skip(imageSize)) { + return false; + } + } + } + + // The buffer should be empty afer we've skipped all of the KTX data + if (!buffer.empty()) { + return false; + } + + return true; +} diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 225fcbb2ed..92b9091533 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -38,14 +38,12 @@ #include #include - #include #include #include #include #include - QSharedPointer logger; gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = true); @@ -59,7 +57,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt OutputDebugStringA(logMessage.toLocal8Bit().constData()); OutputDebugStringA("\n"); #endif - logger->addMessage(qPrintable(logMessage + "\n")); + if (logger) { + logger->addMessage(qPrintable(logMessage + "\n")); + } } } @@ -149,5 +149,59 @@ int main(int argc, char** argv) { return 0; } +#if 0 +static const QString TEST_FOLDER { "H:/ktx_cacheold" }; +//static const QString TEST_FOLDER { "C:/Users/bdavis/Git/KTX/testimages" }; + +//static const QString EXTENSIONS { "4bbdf8f786470e4ab3e672d44b8e8df2.ktx" }; +static const QString EXTENSIONS { "*.ktx" }; + +int mainTemp(int, char**) { + qInstallMessageHandler(messageHandler); + auto fileInfoList = QDir { TEST_FOLDER }.entryInfoList(QStringList { EXTENSIONS }); + for (auto fileInfo : fileInfoList) { + qDebug() << fileInfo.filePath(); + std::shared_ptr storage { new storage::FileStorage { fileInfo.filePath() } }; + + if (!ktx::KTX::validate(storage)) { + qDebug() << "KTX invalid"; + } + + auto ktxFile = ktx::KTX::create(storage); + ktx::KTXDescriptor ktxDescriptor = ktxFile->toDescriptor(); + assert(ktxFile->_keyValues == ktxDescriptor.keyValues); + + qDebug() << "Contains " << ktxDescriptor.keyValues.size() << " key value pairs"; + for (const auto& kv : ktxDescriptor.keyValues) { + qDebug() << "\t" << kv._key.c_str(); + } + + auto offsetToMinMipKV = ktxDescriptor.getValueOffsetForKey(ktx::HIFI_MIN_POPULATED_MIP_KEY); + if (offsetToMinMipKV) { + auto data = storage->data() + ktx::KTX_HEADER_SIZE + offsetToMinMipKV; + auto minMipLevelAvailable = *data; + qDebug() << "\tMin mip available " << minMipLevelAvailable; + assert(minMipLevelAvailable < ktxDescriptor.header.numberOfMipmapLevels); + } + auto storageSize = storage->size(); + for (const auto& faceImageDesc : ktxDescriptor.images) { + //assert(0 == (faceImageDesc._faceSize % 4)); + for (const auto& faceOffset : faceImageDesc._faceOffsets) { + assert(0 == (faceOffset % 4)); + auto faceEndOffset = faceOffset + faceImageDesc._faceSize; + assert(faceEndOffset <= storageSize); + } + } + + for (const auto& faceImage : ktxFile->_images) { + for (const ktx::Byte* faceBytes : faceImage._faceBytes) { + assert(0 == (reinterpret_cast(faceBytes) % 4)); + } + } + } + return 0; +} +#endif + #include "main.moc" From 191b633081e1c8a89d475c4c820f7fdba10d9f3a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 15 May 2017 10:23:08 -0700 Subject: [PATCH 05/25] Refactor KTX defines and validation --- libraries/gpu/src/gpu/Texture_ktx.cpp | 50 ++-- libraries/ktx/src/khronos/KHR.h | 238 +++++++++++++++++++ libraries/ktx/src/ktx/KTX.cpp | 98 ++++---- libraries/ktx/src/ktx/KTX.h | 327 +++++++------------------- libraries/ktx/src/ktx/Reader.cpp | 4 +- libraries/ktx/src/ktx/Validation.cpp | 265 +++++++++++++-------- libraries/ktx/src/ktx/Writer.cpp | 8 +- tests/ktx/src/main.cpp | 24 +- 8 files changed, 570 insertions(+), 444 deletions(-) create mode 100644 libraries/ktx/src/khronos/KHR.h diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 5f677d7424..f455fde009 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -510,29 +510,29 @@ TexturePointer Texture::unserialize(const std::string& ktxfile, const ktx::KTXDe bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header) { if (texelFormat == Format::COLOR_RGBA_32 && mipFormat == Format::COLOR_BGRA_32) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat::RGBA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_RGBA_32 && mipFormat == Format::COLOR_RGBA_32) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat::RGBA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_SRGBA_32 && mipFormat == Format::COLOR_SBGRA_32) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::BGRA, ktx::GLInternalFormat::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_SRGBA_32 && mipFormat == Format::COLOR_SRGBA_32) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RGBA, ktx::GLInternalFormat::SRGB8_ALPHA8, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_R_8 && mipFormat == Format::COLOR_R_8) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat_Uncompressed::R8, ktx::GLBaseInternalFormat::RED); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat::R8, ktx::GLBaseInternalFormat::RED); } else if (texelFormat == Format::VEC2NU8_XY && mipFormat == Format::VEC2NU8_XY) { - header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RG, ktx::GLInternalFormat_Uncompressed::RG8, ktx::GLBaseInternalFormat::RG); + header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RG, ktx::GLInternalFormat::RG8, ktx::GLBaseInternalFormat::RG); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGB && mipFormat == Format::COLOR_COMPRESSED_SRGB) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_SRGBA_MASK) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA); } else if (texelFormat == Format::COLOR_COMPRESSED_RED && mipFormat == Format::COLOR_COMPRESSED_RED) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED); } else if (texelFormat == Format::COLOR_COMPRESSED_XY && mipFormat == Format::COLOR_COMPRESSED_XY) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG); } else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH) { - header.setCompressed(ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); + header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); } else { return false; } @@ -542,20 +542,20 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat) { if (header.getGLFormat() == ktx::GLFormat::BGRA && header.getGLType() == ktx::GLType::UNSIGNED_BYTE && header.getTypeSize() == 1) { - if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::RGBA8) { + if (header.getGLInternaFormat() == ktx::GLInternalFormat::RGBA8) { mipFormat = Format::COLOR_BGRA_32; texelFormat = Format::COLOR_RGBA_32; - } else if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::SRGB8_ALPHA8) { mipFormat = Format::COLOR_SBGRA_32; texelFormat = Format::COLOR_SRGBA_32; } else { return false; } } else if (header.getGLFormat() == ktx::GLFormat::RGBA && header.getGLType() == ktx::GLType::UNSIGNED_BYTE && header.getTypeSize() == 1) { - if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::RGBA8) { + if (header.getGLInternaFormat() == ktx::GLInternalFormat::RGBA8) { mipFormat = Format::COLOR_RGBA_32; texelFormat = Format::COLOR_RGBA_32; - } else if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::SRGB8_ALPHA8) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::SRGB8_ALPHA8) { mipFormat = Format::COLOR_SRGBA_32; texelFormat = Format::COLOR_SRGBA_32; } else { @@ -563,35 +563,35 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E } } else if (header.getGLFormat() == ktx::GLFormat::RED && header.getGLType() == ktx::GLType::UNSIGNED_BYTE && header.getTypeSize() == 1) { mipFormat = Format::COLOR_R_8; - if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::R8) { + if (header.getGLInternaFormat() == ktx::GLInternalFormat::R8) { texelFormat = Format::COLOR_R_8; } else { return false; } } else if (header.getGLFormat() == ktx::GLFormat::RG && header.getGLType() == ktx::GLType::UNSIGNED_BYTE && header.getTypeSize() == 1) { mipFormat = Format::VEC2NU8_XY; - if (header.getGLInternaFormat_Uncompressed() == ktx::GLInternalFormat_Uncompressed::RG8) { + if (header.getGLInternaFormat() == ktx::GLInternalFormat::RG8) { texelFormat = Format::VEC2NU8_XY; } else { return false; } - } else if (header.getGLFormat() == ktx::GLFormat::COMPRESSED_FORMAT && header.getGLType() == ktx::GLType::COMPRESSED_TYPE) { - if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT) { + } else if (header.isCompressed()) { + if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) { mipFormat = Format::COLOR_COMPRESSED_SRGB; texelFormat = Format::COLOR_COMPRESSED_SRGB; - } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { mipFormat = Format::COLOR_COMPRESSED_SRGBA_MASK; texelFormat = Format::COLOR_COMPRESSED_SRGBA_MASK; - } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { mipFormat = Format::COLOR_COMPRESSED_SRGBA; texelFormat = Format::COLOR_COMPRESSED_SRGBA; - } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) { mipFormat = Format::COLOR_COMPRESSED_RED; texelFormat = Format::COLOR_COMPRESSED_RED; - } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) { mipFormat = Format::COLOR_COMPRESSED_XY; texelFormat = Format::COLOR_COMPRESSED_XY; - } else if (header.getGLInternaFormat_Compressed() == ktx::GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { + } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { mipFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH; texelFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH; } else { diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h new file mode 100644 index 0000000000..7b3e3453c7 --- /dev/null +++ b/libraries/ktx/src/khronos/KHR.h @@ -0,0 +1,238 @@ +// +// Created by Bradley Austin Davis on 2017/05/13 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef khronos_khr_hpp +#define khronos_khr_hpp + +namespace khronos { + + namespace gl { + + enum class Type : uint32_t { + // GL 4.4 Table 8.2 + UNSIGNED_BYTE = 0x1401, + BYTE = 0x1400, + UNSIGNED_SHORT = 0x1403, + SHORT = 0x1402, + UNSIGNED_INT = 0x1405, + INT = 0x1404, + HALF_FLOAT = 0x140B, + FLOAT = 0x1406, + UNSIGNED_BYTE_3_3_2 = 0x8032, + UNSIGNED_BYTE_2_3_3_REV = 0x8362, + UNSIGNED_SHORT_5_6_5 = 0x8363, + UNSIGNED_SHORT_5_6_5_REV = 0x8364, + UNSIGNED_SHORT_4_4_4_4 = 0x8033, + UNSIGNED_SHORT_4_4_4_4_REV = 0x8365, + UNSIGNED_SHORT_5_5_5_1 = 0x8034, + UNSIGNED_SHORT_1_5_5_5_REV = 0x8366, + UNSIGNED_INT_8_8_8_8 = 0x8035, + UNSIGNED_INT_8_8_8_8_REV = 0x8367, + UNSIGNED_INT_10_10_10_2 = 0x8036, + UNSIGNED_INT_2_10_10_10_REV = 0x8368, + UNSIGNED_INT_24_8 = 0x84FA, + UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, + UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, + FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD, + }; + + namespace texture { + + enum class Format : uint32_t { + COMPRESSED_FORMAT = 0, + + // GL 4.4 Table 8.3 + STENCIL_INDEX = 0x1901, + DEPTH_COMPONENT = 0x1902, + DEPTH_STENCIL = 0x84F9, + + RED = 0x1903, + GREEN = 0x1904, + BLUE = 0x1905, + RG = 0x8227, + RGB = 0x1907, + RGBA = 0x1908, + BGR = 0x80E0, + BGRA = 0x80E1, + + RG_INTEGER = 0x8228, + RED_INTEGER = 0x8D94, + GREEN_INTEGER = 0x8D95, + BLUE_INTEGER = 0x8D96, + RGB_INTEGER = 0x8D98, + RGBA_INTEGER = 0x8D99, + BGR_INTEGER = 0x8D9A, + BGRA_INTEGER = 0x8D9B, + }; + + enum class InternalFormat : uint32_t { + // GL 4.4 Table 8.12 + R8 = 0x8229, + R8_SNORM = 0x8F94, + + R16 = 0x822A, + R16_SNORM = 0x8F98, + + RG8 = 0x822B, + RG8_SNORM = 0x8F95, + + RG16 = 0x822C, + RG16_SNORM = 0x8F99, + + R3_G3_B2 = 0x2A10, + RGB4 = 0x804F, + RGB5 = 0x8050, + RGB565 = 0x8D62, + + RGB8 = 0x8051, + RGB8_SNORM = 0x8F96, + RGB10 = 0x8052, + RGB12 = 0x8053, + + RGB16 = 0x8054, + RGB16_SNORM = 0x8F9A, + + RGBA2 = 0x8055, + RGBA4 = 0x8056, + RGB5_A1 = 0x8057, + RGBA8 = 0x8058, + RGBA8_SNORM = 0x8F97, + + RGB10_A2 = 0x8059, + RGB10_A2UI = 0x906F, + + RGBA12 = 0x805A, + RGBA16 = 0x805B, + RGBA16_SNORM = 0x8F9B, + + SRGB8 = 0x8C41, + SRGB8_ALPHA8 = 0x8C43, + + R16F = 0x822D, + RG16F = 0x822F, + RGB16F = 0x881B, + RGBA16F = 0x881A, + + R32F = 0x822E, + RG32F = 0x8230, + RGB32F = 0x8815, + RGBA32F = 0x8814, + + R11F_G11F_B10F = 0x8C3A, + RGB9_E5 = 0x8C3D, + + + R8I = 0x8231, + R8UI = 0x8232, + R16I = 0x8233, + R16UI = 0x8234, + R32I = 0x8235, + R32UI = 0x8236, + RG8I = 0x8237, + RG8UI = 0x8238, + RG16I = 0x8239, + RG16UI = 0x823A, + RG32I = 0x823B, + RG32UI = 0x823C, + + RGB8I = 0x8D8F, + RGB8UI = 0x8D7D, + RGB16I = 0x8D89, + RGB16UI = 0x8D77, + + RGB32I = 0x8D83, + RGB32UI = 0x8D71, + RGBA8I = 0x8D8E, + RGBA8UI = 0x8D7C, + RGBA16I = 0x8D88, + RGBA16UI = 0x8D76, + RGBA32I = 0x8D82, + + RGBA32UI = 0x8D70, + + // GL 4.4 Table 8.13 + DEPTH_COMPONENT16 = 0x81A5, + DEPTH_COMPONENT24 = 0x81A6, + DEPTH_COMPONENT32 = 0x81A7, + + DEPTH_COMPONENT32F = 0x8CAC, + DEPTH24_STENCIL8 = 0x88F0, + DEPTH32F_STENCIL8 = 0x8CAD, + + STENCIL_INDEX1 = 0x8D46, + STENCIL_INDEX4 = 0x8D47, + STENCIL_INDEX8 = 0x8D48, + STENCIL_INDEX16 = 0x8D49, + + // GL 4.4 Table 8.14 + COMPRESSED_RED = 0x8225, + COMPRESSED_RG = 0x8226, + COMPRESSED_RGB = 0x84ED, + COMPRESSED_RGBA = 0x84EE, + + COMPRESSED_SRGB = 0x8C48, + COMPRESSED_SRGB_ALPHA = 0x8C49, + + COMPRESSED_ETC1_RGB8_OES = 0x8D64, + + COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D, + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E, + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, + + COMPRESSED_RED_RGTC1 = 0x8DBB, + COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, + COMPRESSED_RG_RGTC2 = 0x8DBD, + COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE, + + COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C, + COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D, + COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E, + COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F, + + COMPRESSED_RGB8_ETC2 = 0x9274, + COMPRESSED_SRGB8_ETC2 = 0x9275, + COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276, + COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277, + COMPRESSED_RGBA8_ETC2_EAC = 0x9278, + COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279, + + COMPRESSED_R11_EAC = 0x9270, + COMPRESSED_SIGNED_R11_EAC = 0x9271, + COMPRESSED_RG11_EAC = 0x9272, + COMPRESSED_SIGNED_RG11_EAC = 0x9273, + }; + + enum class BaseInternalFormat : uint32_t { + // GL 4.4 Table 8.11 + DEPTH_COMPONENT = 0x1902, + DEPTH_STENCIL = 0x84F9, + RED = 0x1903, + RG = 0x8227, + RGB = 0x1907, + RGBA = 0x1908, + STENCIL_INDEX = 0x1901, + }; + + enum CubeMapFace { + POS_X = 0, + NEG_X = 1, + POS_Y = 2, + NEG_Y = 3, + POS_Z = 4, + NEG_Z = 5, + NUM_CUBEMAPFACES = 6, + }; + } + + } + +} + +#endif // khronos_khr_hpp diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index c366daf7ed..1900c4a4b1 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -16,16 +16,6 @@ using namespace ktx; -uint32_t Header::evalPadding(size_t byteSize) { - //auto padding = byteSize % PACKING_SIZE; - // return (uint32_t) (padding ? PACKING_SIZE - padding : 0); - return (uint32_t) (3 - (byteSize + 3) % PACKING_SIZE);// padding ? PACKING_SIZE - padding : 0); -} - -bool Header::checkAlignment(size_t byteSize) { - return ((byteSize & 0x3) == 0); -} - const Header::Identifier ktx::Header::IDENTIFIER {{ 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }}; @@ -40,24 +30,24 @@ uint32_t Header::evalMaxDimension() const { uint32_t Header::evalPixelOrBlockWidth(uint32_t level) const { auto pixelWidth = std::max(getPixelWidth() >> level, 1U); - if (getGLType() == GLType::COMPRESSED_TYPE) { - return (pixelWidth + 3) / 4; + if (isCompressed()) { + return evalAlignedCount(pixelWidth); } else { return pixelWidth; } } uint32_t Header::evalPixelOrBlockHeight(uint32_t level) const { auto pixelWidth = std::max(getPixelHeight() >> level, 1U); - if (getGLType() == GLType::COMPRESSED_TYPE) { - auto format = getGLInternaFormat_Compressed(); + if (glType == COMPRESSED_TYPE) { + auto format = getGLInternaFormat(); switch (format) { - case GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT: // BC1 - case GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: // BC1A - case GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: // BC3 - case GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1: // BC4 - case GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2: // BC5 - case GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 - return (pixelWidth + 3) / 4; + case GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: // BC1 + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: // BC1A + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: // BC3 + case GLInternalFormat::COMPRESSED_RED_RGTC1: // BC4 + case GLInternalFormat::COMPRESSED_RG_RGTC2: // BC5 + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 + return evalAlignedCount(pixelWidth); default: throw std::runtime_error("Unknown format"); } @@ -70,31 +60,33 @@ uint32_t Header::evalPixelOrBlockDepth(uint32_t level) const { } size_t Header::evalPixelOrBlockSize() const { - if (getGLType() == GLType::COMPRESSED_TYPE) { - auto format = getGLInternaFormat_Compressed(); - if (format == GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT) { - return 8; - } else if (format == GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { - return 8; - } else if (format == GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { - return 16; - } else if (format == GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1) { - return 8; - } else if (format == GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2) { - return 16; - } else if (format == GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { - return 16; + if (isCompressed()) { + auto format = getGLInternaFormat(); + switch (format) { + case GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GLInternalFormat::COMPRESSED_RED_RGTC1: + return 8; + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GLInternalFormat::COMPRESSED_RG_RGTC2: + return 16; + default: + break; } } else { auto baseFormat = getGLBaseInternalFormat(); - if (baseFormat == GLBaseInternalFormat::RED) { - return 1; - } else if (baseFormat == GLBaseInternalFormat::RG) { - return 2; - } else if (baseFormat == GLBaseInternalFormat::RGB) { - return 3; - } else if (baseFormat == GLBaseInternalFormat::RGBA) { - return 4; + switch (baseFormat) { + case GLBaseInternalFormat::RED: + return 1; + case GLBaseInternalFormat::RG: + return 2; + case GLBaseInternalFormat::RGB: + return 3; + case GLBaseInternalFormat::RGBA: + return 4; + default: + break; } } @@ -108,16 +100,16 @@ size_t Header::evalRowSize(uint32_t level) const { if (pixSize == 0) { return 0; } - auto netSize = pixWidth * pixSize; - auto padding = evalPadding(netSize); - return netSize + padding; + return evalPadded(pixWidth * pixSize); } + size_t Header::evalFaceSize(uint32_t level) const { auto pixHeight = evalPixelOrBlockHeight(level); auto pixDepth = evalPixelOrBlockDepth(level); auto rowSize = evalRowSize(level); return pixDepth * pixHeight * rowSize; } + size_t Header::evalImageSize(uint32_t level) const { auto faceSize = evalFaceSize(level); if (!checkAlignment(faceSize)) { @@ -192,7 +184,7 @@ KeyValue::KeyValue(const std::string& key, const std::string& value) : } uint32_t KeyValue::serializedByteSize() const { - return (uint32_t) (sizeof(uint32_t) + _byteSize + Header::evalPadding(_byteSize)); + return (uint32_t)sizeof(uint32_t) + evalPadded(_byteSize); } uint32_t KeyValue::serializedKeyValuesByteSize(const KeyValues& keyValues) { @@ -200,14 +192,8 @@ uint32_t KeyValue::serializedKeyValuesByteSize(const KeyValues& keyValues) { for (auto& keyval : keyValues) { keyValuesSize += keyval.serializedByteSize(); } - return (keyValuesSize + Header::evalPadding(keyValuesSize)); -} - - -KTX::KTX() { -} - -KTX::~KTX() { + Q_ASSERT(keyValuesSize % 4 == 0); + return keyValuesSize; } void KTX::resetStorage(const StoragePointer& storage) { @@ -230,7 +216,7 @@ size_t KTX::getTexelsDataSize() const { if (!_storage) { return 0; } - return (_storage->data() + _storage->size()) - getTexelsData(); + return _storage->size() - sizeof(Header) - getKeyValueDataSize(); } const Byte* KTX::getKeyValueData() const { diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 6dc8e01131..c6570f87c6 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -22,7 +22,14 @@ #include -/* KTX Spec: +#include "../khronos/KHR.h" + +/* + +KTX Specification: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ + + +**** A KTX header is 64 bytes layed out as follows Byte[12] identifier UInt32 endianness @@ -38,6 +45,8 @@ UInt32 numberOfArrayElements UInt32 numberOfFaces UInt32 numberOfMipmapLevels UInt32 bytesOfKeyValueData + +**** Each KTX key value pair block is 4 byte aligned for each keyValuePair that fits in bytesOfKeyValueData UInt32 keyAndValueByteSize @@ -45,6 +54,8 @@ for each keyValuePair that fits in bytesOfKeyValueData Byte valuePadding[3 - ((keyAndValueByteSize + 3) % 4)] end +**** Each mip and cube face is 4 byte aligned + for each mipmap_level in numberOfMipmapLevels* UInt32 imageSize; for each array_element in numberOfArrayElements* @@ -67,231 +78,23 @@ end ** Uncompressed texture data matches a GL_UNPACK_ALIGNMENT of 4. */ - - namespace ktx { - const uint32_t PACKING_SIZE { sizeof(uint32_t) }; - const std::string HIFI_MIN_POPULATED_MIP_KEY{ "hifi.minMip" }; + // Alignment constants + static const uint32_t ALIGNMENT { sizeof(uint32_t) }; + static const uint32_t ALIGNMENT_REMAINDER { ALIGNMENT - 1 }; + static const uint32_t NUM_CUBEMAPFACES = khronos::gl::texture::CubeMapFace::NUM_CUBEMAPFACES; + + // FIXME move out of this header, not specific to ktx + const std::string HIFI_MIN_POPULATED_MIP_KEY { "hifi.minMip" }; + using Byte = uint8_t; - enum class GLType : uint32_t { - COMPRESSED_TYPE = 0, - - // GL 4.4 Table 8.2 - UNSIGNED_BYTE = 0x1401, - BYTE = 0x1400, - UNSIGNED_SHORT = 0x1403, - SHORT = 0x1402, - UNSIGNED_INT = 0x1405, - INT = 0x1404, - HALF_FLOAT = 0x140B, - FLOAT = 0x1406, - UNSIGNED_BYTE_3_3_2 = 0x8032, - UNSIGNED_BYTE_2_3_3_REV = 0x8362, - UNSIGNED_SHORT_5_6_5 = 0x8363, - UNSIGNED_SHORT_5_6_5_REV = 0x8364, - UNSIGNED_SHORT_4_4_4_4 = 0x8033, - UNSIGNED_SHORT_4_4_4_4_REV = 0x8365, - UNSIGNED_SHORT_5_5_5_1 = 0x8034, - UNSIGNED_SHORT_1_5_5_5_REV = 0x8366, - UNSIGNED_INT_8_8_8_8 = 0x8035, - UNSIGNED_INT_8_8_8_8_REV = 0x8367, - UNSIGNED_INT_10_10_10_2 = 0x8036, - UNSIGNED_INT_2_10_10_10_REV = 0x8368, - UNSIGNED_INT_24_8 = 0x84FA, - UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, - UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, - FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD, - }; - - enum class GLFormat : uint32_t { - COMPRESSED_FORMAT = 0, - - // GL 4.4 Table 8.3 - STENCIL_INDEX = 0x1901, - DEPTH_COMPONENT = 0x1902, - DEPTH_STENCIL = 0x84F9, - - RED = 0x1903, - GREEN = 0x1904, - BLUE = 0x1905, - RG = 0x8227, - RGB = 0x1907, - RGBA = 0x1908, - BGR = 0x80E0, - BGRA = 0x80E1, - - RG_INTEGER = 0x8228, - RED_INTEGER = 0x8D94, - GREEN_INTEGER = 0x8D95, - BLUE_INTEGER = 0x8D96, - RGB_INTEGER = 0x8D98, - RGBA_INTEGER = 0x8D99, - BGR_INTEGER = 0x8D9A, - BGRA_INTEGER = 0x8D9B, - }; - - enum class GLInternalFormat_Uncompressed : uint32_t { - // GL 4.4 Table 8.12 - R8 = 0x8229, - R8_SNORM = 0x8F94, - - R16 = 0x822A, - R16_SNORM = 0x8F98, - - RG8 = 0x822B, - RG8_SNORM = 0x8F95, - - RG16 = 0x822C, - RG16_SNORM = 0x8F99, - - R3_G3_B2 = 0x2A10, - RGB4 = 0x804F, - RGB5 = 0x8050, - RGB565 = 0x8D62, - - RGB8 = 0x8051, - RGB8_SNORM = 0x8F96, - RGB10 = 0x8052, - RGB12 = 0x8053, - - RGB16 = 0x8054, - RGB16_SNORM = 0x8F9A, - - RGBA2 = 0x8055, - RGBA4 = 0x8056, - RGB5_A1 = 0x8057, - RGBA8 = 0x8058, - RGBA8_SNORM = 0x8F97, - - RGB10_A2 = 0x8059, - RGB10_A2UI = 0x906F, - - RGBA12 = 0x805A, - RGBA16 = 0x805B, - RGBA16_SNORM = 0x8F9B, - - SRGB8 = 0x8C41, - SRGB8_ALPHA8 = 0x8C43, - - R16F = 0x822D, - RG16F = 0x822F, - RGB16F = 0x881B, - RGBA16F = 0x881A, - - R32F = 0x822E, - RG32F = 0x8230, - RGB32F = 0x8815, - RGBA32F = 0x8814, - - R11F_G11F_B10F = 0x8C3A, - RGB9_E5 = 0x8C3D, - - - R8I = 0x8231, - R8UI = 0x8232, - R16I = 0x8233, - R16UI = 0x8234, - R32I = 0x8235, - R32UI = 0x8236, - RG8I = 0x8237, - RG8UI = 0x8238, - RG16I = 0x8239, - RG16UI = 0x823A, - RG32I = 0x823B, - RG32UI = 0x823C, - - RGB8I = 0x8D8F, - RGB8UI = 0x8D7D, - RGB16I = 0x8D89, - RGB16UI = 0x8D77, - - RGB32I = 0x8D83, - RGB32UI = 0x8D71, - RGBA8I = 0x8D8E, - RGBA8UI = 0x8D7C, - RGBA16I = 0x8D88, - RGBA16UI = 0x8D76, - RGBA32I = 0x8D82, - - RGBA32UI = 0x8D70, - - // GL 4.4 Table 8.13 - DEPTH_COMPONENT16 = 0x81A5, - DEPTH_COMPONENT24 = 0x81A6, - DEPTH_COMPONENT32 = 0x81A7, - - DEPTH_COMPONENT32F = 0x8CAC, - DEPTH24_STENCIL8 = 0x88F0, - DEPTH32F_STENCIL8 = 0x8CAD, - - STENCIL_INDEX1 = 0x8D46, - STENCIL_INDEX4 = 0x8D47, - STENCIL_INDEX8 = 0x8D48, - STENCIL_INDEX16 = 0x8D49, - }; - - enum class GLInternalFormat_Compressed : uint32_t { - // GL 4.4 Table 8.14 - COMPRESSED_RED = 0x8225, - COMPRESSED_RG = 0x8226, - COMPRESSED_RGB = 0x84ED, - COMPRESSED_RGBA = 0x84EE, - - COMPRESSED_SRGB = 0x8C48, - COMPRESSED_SRGB_ALPHA = 0x8C49, - - COMPRESSED_ETC1_RGB8_OES = 0x8D64, - - COMPRESSED_SRGB_S3TC_DXT1_EXT = 0x8C4C, - COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = 0x8C4D, - COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = 0x8C4E, - COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = 0x8C4F, - - COMPRESSED_RED_RGTC1 = 0x8DBB, - COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, - COMPRESSED_RG_RGTC2 = 0x8DBD, - COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE, - - COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C, - COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D, - COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E, - COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F, - - COMPRESSED_RGB8_ETC2 = 0x9274, - COMPRESSED_SRGB8_ETC2 = 0x9275, - COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276, - COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277, - COMPRESSED_RGBA8_ETC2_EAC = 0x9278, - COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279, - - COMPRESSED_R11_EAC = 0x9270, - COMPRESSED_SIGNED_R11_EAC = 0x9271, - COMPRESSED_RG11_EAC = 0x9272, - COMPRESSED_SIGNED_RG11_EAC = 0x9273, - }; - - enum class GLBaseInternalFormat : uint32_t { - // GL 4.4 Table 8.11 - DEPTH_COMPONENT = 0x1902, - DEPTH_STENCIL = 0x84F9, - RED = 0x1903, - RG = 0x8227, - RGB = 0x1907, - RGBA = 0x1908, - STENCIL_INDEX = 0x1901, - }; - - enum CubeMapFace { - POS_X = 0, - NEG_X = 1, - POS_Y = 2, - NEG_Y = 3, - POS_Z = 4, - NEG_Z = 5, - NUM_CUBEMAPFACES = 6, - }; + using GLType = khronos::gl::Type; + using GLFormat = khronos::gl::texture::Format; + using GLInternalFormat = khronos::gl::texture::InternalFormat; + using GLBaseInternalFormat = khronos::gl::texture::BaseInternalFormat; + using CubeMapFace = khronos::gl::texture::CubeMapFace; using Storage = storage::Storage; using StoragePointer = std::shared_ptr; @@ -301,18 +104,41 @@ namespace ktx { bool checkIdentifier(const Byte* identifier); + // Returns the number of bytes required be added to the passed value to make it 4 byte aligned + template + inline uint8_t evalPadding(T value) { + return ALIGNMENT_REMAINDER - ((value + ALIGNMENT_REMAINDER) % ALIGNMENT); + } + + // Returns the passed value rounded up to the next 4 byte aligned value, if it's not already 4 byte aligned + template + inline T evalPadded(T value) { + return (value + ALIGNMENT_REMAINDER) & ~(T)ALIGNMENT_REMAINDER; + } + + template + inline T evalAlignedCount(T value) { + return (value + ALIGNMENT_REMAINDER) / ALIGNMENT; + } + + template + inline bool checkAlignment(T value) { + return ((value & 0x3) == 0); + } + + // Header struct Header { - static const size_t IDENTIFIER_LENGTH = 12; + static const uint32_t COMPRESSED_FORMAT { 0 }; + static const uint32_t COMPRESSED_TYPE { 0 }; + static const uint32_t COMPRESSED_TYPE_SIZE { 1 }; + static const size_t IDENTIFIER_LENGTH { 12 }; using Identifier = std::array; static const Identifier IDENTIFIER; static const uint32_t ENDIAN_TEST = 0x04030201; static const uint32_t REVERSE_ENDIAN_TEST = 0x01020304; - static uint32_t evalPadding(size_t byteSize); - static bool checkAlignment(size_t byteSize); - Header(); Byte identifier[IDENTIFIER_LENGTH]; @@ -321,7 +147,7 @@ namespace ktx { uint32_t glType { static_cast(GLType::UNSIGNED_BYTE) }; uint32_t glTypeSize { 0 }; uint32_t glFormat { static_cast(GLFormat::RGBA) }; - uint32_t glInternalFormat { static_cast(GLInternalFormat_Uncompressed::RGBA8) }; + uint32_t glInternalFormat { static_cast(GLInternalFormat::RGBA8) }; uint32_t glBaseInternalFormat { static_cast(GLBaseInternalFormat::RGBA) }; uint32_t pixelWidth { 1 }; @@ -338,6 +164,7 @@ namespace ktx { uint32_t getPixelDepth() const { return (pixelDepth ? pixelDepth : 1); } uint32_t getNumberOfSlices() const { return (numberOfArrayElements ? numberOfArrayElements : 1); } uint32_t getNumberOfLevels() const { return (numberOfMipmapLevels ? numberOfMipmapLevels : 1); } + bool isCompressed() const { return glFormat == COMPRESSED_FORMAT; } uint32_t evalMaxDimension() const; uint32_t evalPixelOrBlockWidth(uint32_t level) const; @@ -349,17 +176,21 @@ namespace ktx { size_t evalFaceSize(uint32_t level) const; size_t evalImageSize(uint32_t level) const; - void setUncompressed(GLType type, uint32_t typeSize, GLFormat format, GLInternalFormat_Uncompressed internalFormat, GLBaseInternalFormat baseInternalFormat) { + // FIXME base internal format should automatically be determined by internal format + // FIXME type size should automatically be determined by type + void setUncompressed(GLType type, uint32_t typeSize, GLFormat format, GLInternalFormat internalFormat, GLBaseInternalFormat baseInternalFormat) { glType = (uint32_t) type; glTypeSize = typeSize; glFormat = (uint32_t) format; glInternalFormat = (uint32_t) internalFormat; glBaseInternalFormat = (uint32_t) baseInternalFormat; } - void setCompressed(GLInternalFormat_Compressed internalFormat, GLBaseInternalFormat baseInternalFormat) { - glType = (uint32_t) GLType::COMPRESSED_TYPE; - glTypeSize = 1; - glFormat = (uint32_t) GLFormat::COMPRESSED_FORMAT; + + // FIXME base internal format should automatically be determined by internal format + void setCompressed(GLInternalFormat internalFormat, GLBaseInternalFormat baseInternalFormat) { + glType = COMPRESSED_TYPE; + glFormat = COMPRESSED_FORMAT; + glTypeSize = COMPRESSED_TYPE_SIZE; glInternalFormat = (uint32_t) internalFormat; glBaseInternalFormat = (uint32_t) baseInternalFormat; } @@ -367,18 +198,9 @@ namespace ktx { GLType getGLType() const { return (GLType)glType; } uint32_t getTypeSize() const { return glTypeSize; } GLFormat getGLFormat() const { return (GLFormat)glFormat; } - GLInternalFormat_Uncompressed getGLInternaFormat_Uncompressed() const { return (GLInternalFormat_Uncompressed)glInternalFormat; } - GLInternalFormat_Compressed getGLInternaFormat_Compressed() const { return (GLInternalFormat_Compressed)glInternalFormat; } + GLInternalFormat getGLInternaFormat() const { return (GLInternalFormat)glInternalFormat; } GLBaseInternalFormat getGLBaseInternalFormat() const { return (GLBaseInternalFormat)glBaseInternalFormat; } - - void setDimensions(uint32_t width, uint32_t height = 0, uint32_t depth = 0, uint32_t numSlices = 0, uint32_t numFaces = 1) { - pixelWidth = (width > 0 ? width : 1); - pixelHeight = height; - pixelDepth = depth; - numberOfArrayElements = numSlices; - numberOfFaces = ((numFaces == 1) || (numFaces == NUM_CUBEMAPFACES) ? numFaces : 1); - } void set1D(uint32_t width) { setDimensions(width); } void set1DArray(uint32_t width, uint32_t numSlices) { setDimensions(width, 0, 0, (numSlices > 0 ? numSlices : 1)); } void set2D(uint32_t width, uint32_t height) { setDimensions(width, height); } @@ -392,12 +214,22 @@ namespace ktx { // Generate a set of image descriptors based on the assumption that the full mip pyramid is populated ImageDescriptors generateImageDescriptors() const; + + private: + void setDimensions(uint32_t width, uint32_t height = 0, uint32_t depth = 0, uint32_t numSlices = 0, uint32_t numFaces = 1) { + pixelWidth = (width > 0 ? width : 1); + pixelHeight = height; + pixelDepth = depth; + numberOfArrayElements = numSlices; + numberOfFaces = numFaces; + } }; - static const size_t KTX_HEADER_SIZE = 64; + // Size as specified by the KTX specification + static const size_t KTX_HEADER_SIZE { 64 }; static_assert(sizeof(Header) == KTX_HEADER_SIZE, "KTX Header size is static and should not change from the spec"); - static const size_t KV_SIZE_WIDTH = 4; // Number of bytes for keyAndValueByteSize - static const size_t IMAGE_SIZE_WIDTH = 4; // Number of bytes for imageSize + static const size_t KV_SIZE_WIDTH { ALIGNMENT }; // Number of bytes for keyAndValueByteSize + static const size_t IMAGE_SIZE_WIDTH { ALIGNMENT }; // Number of bytes for imageSize // Key Values struct KeyValue { @@ -488,11 +320,9 @@ namespace ktx { class KTX { void resetStorage(const StoragePointer& src); - KTX(); + KTX() {} KTX(const StoragePointer& storage, const Header& header, const KeyValues& keyValues, const Images& images); public: - ~KTX(); - static bool validate(const StoragePointer& src); // Define a KTX object manually to write it somewhere (in a file on disk?) @@ -539,6 +369,7 @@ namespace ktx { KTXDescriptor toDescriptor() const; size_t getKeyValueDataSize() const; size_t getTexelsDataSize() const; + bool isValid() const; Header _header; StoragePointer _storage; diff --git a/libraries/ktx/src/ktx/Reader.cpp b/libraries/ktx/src/ktx/Reader.cpp index 1b63af5262..cfd9111ee3 100644 --- a/libraries/ktx/src/ktx/Reader.cpp +++ b/libraries/ktx/src/ktx/Reader.cpp @@ -151,7 +151,7 @@ namespace ktx { auto expectedImageSize = header.evalImageSize((uint32_t) images.size()); if (imageSize != expectedImageSize) { break; - } else if (!Header::checkAlignment(imageSize)) { + } else if (!checkAlignment(imageSize)) { break; } @@ -163,7 +163,7 @@ namespace ktx { // If enough data ahead then capture the pointer if ((currentPtr - srcBytes) + imageSize <= (srcSize)) { - auto padding = Header::evalPadding(imageSize); + auto padding = evalPadding(imageSize); if (numFaces == NUM_CUBEMAPFACES) { Image::FaceBytes faces(NUM_CUBEMAPFACES); diff --git a/libraries/ktx/src/ktx/Validation.cpp b/libraries/ktx/src/ktx/Validation.cpp index 74af58d311..a59dde92f1 100644 --- a/libraries/ktx/src/ktx/Validation.cpp +++ b/libraries/ktx/src/ktx/Validation.cpp @@ -63,111 +63,111 @@ static const std::unordered_set VALID_GL_FORMATS { }; static const std::unordered_set VALID_GL_INTERNAL_FORMATS { - (uint32_t)GLInternalFormat_Uncompressed::R8, - (uint32_t)GLInternalFormat_Uncompressed::R8_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::R16, - (uint32_t)GLInternalFormat_Uncompressed::R16_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::RG8, - (uint32_t)GLInternalFormat_Uncompressed::RG8_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::RG16, - (uint32_t)GLInternalFormat_Uncompressed::RG16_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::R3_G3_B2, - (uint32_t)GLInternalFormat_Uncompressed::RGB4, - (uint32_t)GLInternalFormat_Uncompressed::RGB5, - (uint32_t)GLInternalFormat_Uncompressed::RGB565, - (uint32_t)GLInternalFormat_Uncompressed::RGB8, - (uint32_t)GLInternalFormat_Uncompressed::RGB8_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::RGB10, - (uint32_t)GLInternalFormat_Uncompressed::RGB12, - (uint32_t)GLInternalFormat_Uncompressed::RGB16, - (uint32_t)GLInternalFormat_Uncompressed::RGB16_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::RGBA2, - (uint32_t)GLInternalFormat_Uncompressed::RGBA4, - (uint32_t)GLInternalFormat_Uncompressed::RGB5_A1, - (uint32_t)GLInternalFormat_Uncompressed::RGBA8, - (uint32_t)GLInternalFormat_Uncompressed::RGBA8_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::RGB10_A2, - (uint32_t)GLInternalFormat_Uncompressed::RGB10_A2UI, - (uint32_t)GLInternalFormat_Uncompressed::RGBA12, - (uint32_t)GLInternalFormat_Uncompressed::RGBA16, - (uint32_t)GLInternalFormat_Uncompressed::RGBA16_SNORM, - (uint32_t)GLInternalFormat_Uncompressed::SRGB8, - (uint32_t)GLInternalFormat_Uncompressed::SRGB8_ALPHA8, - (uint32_t)GLInternalFormat_Uncompressed::R16F, - (uint32_t)GLInternalFormat_Uncompressed::RG16F, - (uint32_t)GLInternalFormat_Uncompressed::RGB16F, - (uint32_t)GLInternalFormat_Uncompressed::RGBA16F, - (uint32_t)GLInternalFormat_Uncompressed::R32F, - (uint32_t)GLInternalFormat_Uncompressed::RG32F, - (uint32_t)GLInternalFormat_Uncompressed::RGBA32F, - (uint32_t)GLInternalFormat_Uncompressed::R11F_G11F_B10F, - (uint32_t)GLInternalFormat_Uncompressed::RGB9_E5, - (uint32_t)GLInternalFormat_Uncompressed::R8I, - (uint32_t)GLInternalFormat_Uncompressed::R8UI, - (uint32_t)GLInternalFormat_Uncompressed::R16I, - (uint32_t)GLInternalFormat_Uncompressed::R16UI, - (uint32_t)GLInternalFormat_Uncompressed::R32I, - (uint32_t)GLInternalFormat_Uncompressed::R32UI, - (uint32_t)GLInternalFormat_Uncompressed::RG8I, - (uint32_t)GLInternalFormat_Uncompressed::RG8UI, - (uint32_t)GLInternalFormat_Uncompressed::RG16I, - (uint32_t)GLInternalFormat_Uncompressed::RG16UI, - (uint32_t)GLInternalFormat_Uncompressed::RG32I, - (uint32_t)GLInternalFormat_Uncompressed::RG32UI, - (uint32_t)GLInternalFormat_Uncompressed::RGB8I, - (uint32_t)GLInternalFormat_Uncompressed::RGB8UI, - (uint32_t)GLInternalFormat_Uncompressed::RGB16I, - (uint32_t)GLInternalFormat_Uncompressed::RGB16UI, - (uint32_t)GLInternalFormat_Uncompressed::RGB32I, - (uint32_t)GLInternalFormat_Uncompressed::RGB32UI, - (uint32_t)GLInternalFormat_Uncompressed::RGBA8I, - (uint32_t)GLInternalFormat_Uncompressed::RGBA8UI, - (uint32_t)GLInternalFormat_Uncompressed::RGBA16I, - (uint32_t)GLInternalFormat_Uncompressed::RGBA16UI, - (uint32_t)GLInternalFormat_Uncompressed::RGBA32I, - (uint32_t)GLInternalFormat_Uncompressed::RGBA32UI, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT16, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT24, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH_COMPONENT32F, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH24_STENCIL8, - (uint32_t)GLInternalFormat_Uncompressed::DEPTH32F_STENCIL8, - (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX1, - (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX4, - (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX8, - (uint32_t)GLInternalFormat_Uncompressed::STENCIL_INDEX16, + (uint32_t)GLInternalFormat::R8, + (uint32_t)GLInternalFormat::R8_SNORM, + (uint32_t)GLInternalFormat::R16, + (uint32_t)GLInternalFormat::R16_SNORM, + (uint32_t)GLInternalFormat::RG8, + (uint32_t)GLInternalFormat::RG8_SNORM, + (uint32_t)GLInternalFormat::RG16, + (uint32_t)GLInternalFormat::RG16_SNORM, + (uint32_t)GLInternalFormat::R3_G3_B2, + (uint32_t)GLInternalFormat::RGB4, + (uint32_t)GLInternalFormat::RGB5, + (uint32_t)GLInternalFormat::RGB565, + (uint32_t)GLInternalFormat::RGB8, + (uint32_t)GLInternalFormat::RGB8_SNORM, + (uint32_t)GLInternalFormat::RGB10, + (uint32_t)GLInternalFormat::RGB12, + (uint32_t)GLInternalFormat::RGB16, + (uint32_t)GLInternalFormat::RGB16_SNORM, + (uint32_t)GLInternalFormat::RGBA2, + (uint32_t)GLInternalFormat::RGBA4, + (uint32_t)GLInternalFormat::RGB5_A1, + (uint32_t)GLInternalFormat::RGBA8, + (uint32_t)GLInternalFormat::RGBA8_SNORM, + (uint32_t)GLInternalFormat::RGB10_A2, + (uint32_t)GLInternalFormat::RGB10_A2UI, + (uint32_t)GLInternalFormat::RGBA12, + (uint32_t)GLInternalFormat::RGBA16, + (uint32_t)GLInternalFormat::RGBA16_SNORM, + (uint32_t)GLInternalFormat::SRGB8, + (uint32_t)GLInternalFormat::SRGB8_ALPHA8, + (uint32_t)GLInternalFormat::R16F, + (uint32_t)GLInternalFormat::RG16F, + (uint32_t)GLInternalFormat::RGB16F, + (uint32_t)GLInternalFormat::RGBA16F, + (uint32_t)GLInternalFormat::R32F, + (uint32_t)GLInternalFormat::RG32F, + (uint32_t)GLInternalFormat::RGBA32F, + (uint32_t)GLInternalFormat::R11F_G11F_B10F, + (uint32_t)GLInternalFormat::RGB9_E5, + (uint32_t)GLInternalFormat::R8I, + (uint32_t)GLInternalFormat::R8UI, + (uint32_t)GLInternalFormat::R16I, + (uint32_t)GLInternalFormat::R16UI, + (uint32_t)GLInternalFormat::R32I, + (uint32_t)GLInternalFormat::R32UI, + (uint32_t)GLInternalFormat::RG8I, + (uint32_t)GLInternalFormat::RG8UI, + (uint32_t)GLInternalFormat::RG16I, + (uint32_t)GLInternalFormat::RG16UI, + (uint32_t)GLInternalFormat::RG32I, + (uint32_t)GLInternalFormat::RG32UI, + (uint32_t)GLInternalFormat::RGB8I, + (uint32_t)GLInternalFormat::RGB8UI, + (uint32_t)GLInternalFormat::RGB16I, + (uint32_t)GLInternalFormat::RGB16UI, + (uint32_t)GLInternalFormat::RGB32I, + (uint32_t)GLInternalFormat::RGB32UI, + (uint32_t)GLInternalFormat::RGBA8I, + (uint32_t)GLInternalFormat::RGBA8UI, + (uint32_t)GLInternalFormat::RGBA16I, + (uint32_t)GLInternalFormat::RGBA16UI, + (uint32_t)GLInternalFormat::RGBA32I, + (uint32_t)GLInternalFormat::RGBA32UI, + (uint32_t)GLInternalFormat::DEPTH_COMPONENT16, + (uint32_t)GLInternalFormat::DEPTH_COMPONENT24, + (uint32_t)GLInternalFormat::DEPTH_COMPONENT32, + (uint32_t)GLInternalFormat::DEPTH_COMPONENT32F, + (uint32_t)GLInternalFormat::DEPTH24_STENCIL8, + (uint32_t)GLInternalFormat::DEPTH32F_STENCIL8, + (uint32_t)GLInternalFormat::STENCIL_INDEX1, + (uint32_t)GLInternalFormat::STENCIL_INDEX4, + (uint32_t)GLInternalFormat::STENCIL_INDEX8, + (uint32_t)GLInternalFormat::STENCIL_INDEX16, }; static const std::unordered_set VALID_GL_INTERNAL_COMPRESSED_FORMATS { - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_ETC1_RGB8_OES, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_S3TC_DXT1_EXT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RED_RGTC1, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RED_RGTC1, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG_RGTC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG_RGTC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA_BPTC_UNORM, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_SIGNED_FLOAT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_ETC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ETC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RGBA8_ETC2_EAC, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_R11_EAC, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_R11_EAC, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_RG11_EAC, - (uint32_t)GLInternalFormat_Compressed::COMPRESSED_SIGNED_RG11_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_RED, + (uint32_t)GLInternalFormat::COMPRESSED_RG, + (uint32_t)GLInternalFormat::COMPRESSED_RGB, + (uint32_t)GLInternalFormat::COMPRESSED_RGBA, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_ALPHA, + (uint32_t)GLInternalFormat::COMPRESSED_ETC1_RGB8_OES, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + (uint32_t)GLInternalFormat::COMPRESSED_RED_RGTC1, + (uint32_t)GLInternalFormat::COMPRESSED_SIGNED_RED_RGTC1, + (uint32_t)GLInternalFormat::COMPRESSED_RG_RGTC2, + (uint32_t)GLInternalFormat::COMPRESSED_SIGNED_RG_RGTC2, + (uint32_t)GLInternalFormat::COMPRESSED_RGBA_BPTC_UNORM, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, + (uint32_t)GLInternalFormat::COMPRESSED_RGB_BPTC_SIGNED_FLOAT, + (uint32_t)GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, + (uint32_t)GLInternalFormat::COMPRESSED_RGB8_ETC2, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB8_ETC2, + (uint32_t)GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + (uint32_t)GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_R11_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_SIGNED_R11_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_RG11_EAC, + (uint32_t)GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC, }; static const std::unordered_set VALID_GL_BASE_INTERNAL_FORMATS { @@ -199,7 +199,17 @@ bool Header::isValid() const { return false; } - if (glFormat == (uint32_t)GLFormat::COMPRESSED_FORMAT && glType == (uint32_t)GLType::COMPRESSED_TYPE) { + if (isCompressed()) { + if (glType != COMPRESSED_TYPE) { + qDebug("Invalid type for compressed texture 0x%x", glType); + return false; + } + + if (glTypeSize != COMPRESSED_TYPE_SIZE) { + qDebug("Invalid type size for compressed texture %d", glTypeSize); + return false; + } + if (VALID_GL_INTERNAL_COMPRESSED_FORMATS.count(glInternalFormat) != 1) { qDebug("Invalid compressed internal format 0x%x", glInternalFormat); return false; @@ -241,7 +251,7 @@ bool Header::isValid() const { // FIXME validate numberOfMipmapLevels based on the dimensions? if ((bytesOfKeyValueData % 4) != 0) { - qDebug() << "Invalid keyvalue data size " << numberOfFaces; + qDebug() << "Invalid keyvalue data size " << bytesOfKeyValueData; return false; } @@ -374,3 +384,50 @@ bool KTX::validate(const StoragePointer& src) { return true; } + + + +bool KTX::isValid() const { + if (!_header.isValid()) { + return false; + } + + if (_images.size() != _header.numberOfMipmapLevels) { + return false; + } + + const auto start = _storage->data(); + const auto end = start + _storage->size(); + + // FIXME, do key value checks? + + for (const auto& image : _images) { + if (image._numFaces != _header.numberOfFaces) { + return false; + } + + for (const auto& facePointer : image._faceBytes) { + if (facePointer + image._faceSize > end) { + return false; + } + } + } + + + for (uint8_t mip = 0; mip < _header.numberOfMipmapLevels; ++mip) { + for (uint8_t face = 0; face < _header.numberOfFaces; ++face) { + auto faceStorage = getMipFaceTexelsData(mip, face); + // The face start offset must be 4 byte aligned + if (!checkAlignment(faceStorage->data() - start)) { + return false; + } + + // The face size must be 4 byte aligned + if (!checkAlignment(faceStorage->size())) { + return false; + } + } + } + + return true; +} \ No newline at end of file diff --git a/libraries/ktx/src/ktx/Writer.cpp b/libraries/ktx/src/ktx/Writer.cpp index 23f9d05596..e18a3f1adb 100644 --- a/libraries/ktx/src/ktx/Writer.cpp +++ b/libraries/ktx/src/ktx/Writer.cpp @@ -70,8 +70,7 @@ namespace ktx { for (uint32_t l = 0; l < numMips; l++) { if (images.size() > l) { storageSize += sizeof(uint32_t); - storageSize += images[l]._imageSize; - storageSize += Header::evalPadding(images[l]._imageSize); + storageSize += evalPadded(images[l]._imageSize); } } return storageSize; @@ -89,8 +88,7 @@ namespace ktx { for (uint32_t l = 0; l < numMips; l++) { if (imageDescriptors.size() > l) { storageSize += sizeof(uint32_t); - storageSize += imageDescriptors[l]._imageSize; - storageSize += Header::evalPadding(imageDescriptors[l]._imageSize); + storageSize += evalPadded(imageDescriptors[l]._imageSize); } } return storageSize; @@ -221,7 +219,7 @@ namespace ktx { // If enough data ahead then capture the copy source pointer if (currentDataSize + imageSize <= (allocatedImagesDataSize)) { - auto padding = Header::evalPadding(imageSize); + auto padding = evalPadding(imageSize); // Single face vs cubes if (srcImages[l]._numFaces == 1) { diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 92b9091533..282c537ed2 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,20 @@ int main(int argc, char** argv) { QCoreApplication::setOrganizationDomain("highfidelity.com"); logger.reset(new FileLogger()); + Q_ASSERT(ktx::evalPadding(0) == 0); + Q_ASSERT(ktx::evalPadding(1) == 3); + Q_ASSERT(ktx::evalPadding(2) == 2); + Q_ASSERT(ktx::evalPadding(3) == 1); + Q_ASSERT(ktx::evalPadding(4) == 0); + Q_ASSERT(ktx::evalPadding(1024) == 0); + Q_ASSERT(ktx::evalPadding(1025) == 3); + Q_ASSERT(ktx::evalPadded(0) == 0); + Q_ASSERT(ktx::evalPadded(1) == 4); + Q_ASSERT(ktx::evalPadded(2) == 4); + Q_ASSERT(ktx::evalPadded(3) == 4); + Q_ASSERT(ktx::evalPadded(4) == 4); + Q_ASSERT(ktx::evalPadded(1024) == 1024); + Q_ASSERT(ktx::evalPadded(1025) == 1028); Q_ASSERT(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13)); DependencyManager::set(); @@ -100,8 +115,10 @@ int main(int argc, char** argv) { auto ktxMemory = gpu::Texture::serialize(*testTexture); { const auto& ktxStorage = ktxMemory->getStorage(); - QFile outFile(TEST_IMAGE_KTX); - if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) { + Q_ASSERT_X(ktx::KTX::validate(ktxStorage), __FUNCTION__, "KTX storage validation failed"); + Q_ASSERT_X(ktxMemory->isValid(), __FUNCTION__, "KTX self-validation failed"); + QSaveFile outFile(TEST_IMAGE_KTX); + if (!outFile.open(QFile::WriteOnly)) { throw std::runtime_error("Unable to open file"); } auto ktxSize = ktxStorage->size(); @@ -109,7 +126,7 @@ int main(int argc, char** argv) { auto dest = outFile.map(0, ktxSize); memcpy(dest, ktxStorage->data(), ktxSize); outFile.unmap(dest); - outFile.close(); + outFile.commit(); } { @@ -169,7 +186,6 @@ int mainTemp(int, char**) { auto ktxFile = ktx::KTX::create(storage); ktx::KTXDescriptor ktxDescriptor = ktxFile->toDescriptor(); - assert(ktxFile->_keyValues == ktxDescriptor.keyValues); qDebug() << "Contains " << ktxDescriptor.keyValues.size() << " key value pairs"; for (const auto& kv : ktxDescriptor.keyValues) { From 0fdf1362511bba33acfce53d87e78fae0ef14555 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 24 May 2017 19:31:48 +0100 Subject: [PATCH 06/25] got the shoulders working --- interface/resources/avatar/avatar-animation.json | 8 ++++---- libraries/animation/src/Rig.cpp | 6 ++++++ plugins/openvr/src/ViveControllerManager.cpp | 14 +------------- plugins/openvr/src/ViveControllerManager.h | 8 +------- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index 7171d4c223..35f2d4b9af 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -121,8 +121,8 @@ "rotationVar": "leftArmRotation", "typeVar": "leftArmType", "weightVar": "leftArmWeight", - "weight": 1.0, - "flexCoefficients": [1, 0.5, 0.25, 0.0, 0.0, 0.0] + "weight": 0.75, + "flexCoefficients": [1.0, 0.35, 0.2, 0.1, 0.05, 0.0, 0.0, 0.0] }, { "jointName": "RightArm", @@ -130,8 +130,8 @@ "rotationVar": "rightArmRotation", "typeVar": "rightArmType", "weightVar": "rightArmWeight", - "weight": 1.0, - "flexCoefficients": [1, 0.5, 0.25, 0.0, 0.0, 0.0] + "weight": 0.75, + "flexCoefficients": [1.0, 0.35, 0.2, 0.1, 0.05, 0.0, 0.0, 0.0] } ] }, diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index c74b8c478b..a423c45597 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1049,12 +1049,18 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { } if (params.leftArmEnabled) { + _animVars.set("leftArmType", (int)IKTarget::Type::RotationAndPosition); + _animVars.set("leftArmPosition", params.leftArmPosition); + _animVars.set("leftArmRotation", params.leftArmRotation); } else { _animVars.set("leftArmType", (int)IKTarget::Type::Unknown); } if (params.rightArmEnabled) { + _animVars.set("rightArmType", (int)IKTarget::Type::RotationAndPosition); + _animVars.set("rightArmPosition", params.rightArmPosition); + _animVars.set("rightArmRotation", params.rightArmRotation); } else { _animVars.set("rightArmType", (int)IKTarget::Type::Unknown); } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 5e509f43b8..bb0e415af5 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -178,7 +178,6 @@ ViveControllerManager::InputDevice::InputDevice(vr::IVRSystem*& system) : contro _configStringMap[Config::FeetAndHips] = QString("FeetAndHips"); _configStringMap[Config::FeetHipsAndChest] = QString("FeetHipsAndChest"); _configStringMap[Config::FeetHipsAndShoulders] = QString("FeetHipsAndShoulders"); - _configStringMap[Config::FeetAndShoulders] = QString("FeetAndShoulders"); } void ViveControllerManager::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { @@ -342,11 +341,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (_config == Config::Feet) { calibrateFeet(defaultToReferenceMat, inputCalibration); - } else if (_config == Config::FeetAndShoulders && puckCount >= MIN_FEET_HIPS_CHEST) { - calibrateFeet(defaultToReferenceMat, inputCalibration); - int firstShoulder = 2; - int secondShoulder = 3; - calibrateShoulders(defaultToReferenceMat, inputCalibration, firstShoulder, secondShoulder); } else if (_config == Config::FeetAndHips && puckCount >= MIN_FEET_AND_HIPS) { calibrateFeet(defaultToReferenceMat, inputCalibration); calibrateHips(defaultToReferenceMat, inputCalibration); @@ -666,10 +660,6 @@ void ViveControllerManager::InputDevice::calibrateShoulders(glm::mat4& defaultTo } } -void ViveControllerManager::InputDevice::calibrateHands(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, - PuckPosePair firstHand, PuckPosePair secondHand) { -} - void ViveControllerManager::InputDevice::calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { int headIndex = _validTrackedObjects.size() - 1; } @@ -708,8 +698,6 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu _preferedConfig = Config::FeetHipsAndChest; } else if (value == "FeetHipsAndShoulders") { _preferedConfig = Config::FeetHipsAndShoulders; - } else if (value == "FeetAndShoulders") { - _preferedConfig = Config::FeetAndShoulders; } } @@ -722,7 +710,7 @@ void ViveControllerManager::InputDevice::createPreferences() { auto getter = [this]()->QString { return _configStringMap[_preferedConfig]; }; auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); - QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest" << "FeetAndShoulders"); + QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest" << "FeetHipsAndShoulders"); preference->setItems(list); preferences->addPreference(preference); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 1fd11ccfe6..bc9558beaa 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -108,14 +108,11 @@ private: Auto, Head, Feet, - Hands, Shoulders, FeetAndHips, - FeetAndShoulders, FeetHipsAndChest, FeetHipsAndShoulders, - FeetHipsChestAndHands, - FeetHipsShouldersAndHands + FeetHipsChestAndHead }; Config _config { Config::Auto }; Config _preferedConfig { Config::Auto }; @@ -153,9 +150,6 @@ private: void calibrateHips(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); void calibrateChest(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); - void calibrateHands(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, - PuckPosePair firstHand, PuckPosePair secondHand); - void calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, int firstShoulderIndex, int secondShoulderIndex); From da41b5dc003ba3801fdd5996af3c21fef8ff635f Mon Sep 17 00:00:00 2001 From: seefo Date: Thu, 25 May 2017 09:20:04 -0700 Subject: [PATCH 07/25] Focus is now changed when adding a new list item in DS settings --- domain-server/resources/web/settings/js/settings.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index 69bdf1df3f..8066223318 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -1379,6 +1379,8 @@ function addTableRow(row) { var setting_name = table.attr("name"); row.addClass(Settings.DATA_ROW_CLASS + " " + Settings.NEW_ROW_CLASS); + var focusChanged = false; + _.each(row.children(), function(element) { if ($(element).hasClass("numbered")) { // Index row @@ -1429,6 +1431,11 @@ function addTableRow(row) { }); } + if (!focusChanged) { + input.focus(); + focusChanged = true; + } + if (isCheckbox) { $(input).find("input").attr("data-changed", "true"); } else { From 80e641b6d4bf6891b534130e8e43b629fd98c77d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 25 May 2017 09:47:02 -0700 Subject: [PATCH 08/25] fix code that was using old raypickInfo.properties field --- .../system/controllers/handControllerGrab.js | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index f5c3e6eafa..0a08b60281 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1036,8 +1036,8 @@ function getControllerJointIndex(hand) { "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND"); } - - return MyAvatar.getJointIndex("Head"); + + return MyAvatar.getJointIndex("Head"); } // global EquipHotspotBuddy instance @@ -1331,7 +1331,7 @@ function MyController(hand) { if (this.stylus) { return; } - + var stylusProperties = { name: "stylus", url: Script.resourcesPath() + "meshes/tablet-stylus-fat.fbx", @@ -2134,7 +2134,7 @@ function MyController(hand) { return null; } }; - + this.chooseNearEquipHotspotsForFarToNearEquip = function(candidateEntities, distance) { var equippableHotspots = flatten(candidateEntities.map(function(entityID) { return _this.collectEquipHotspots(entityID); @@ -2291,7 +2291,7 @@ function MyController(hand) { return; } } - + if (isInEditMode()) { this.searchIndicatorOn(rayPickInfo.searchRay); if (this.triggerSmoothedGrab()) { @@ -2347,10 +2347,11 @@ function MyController(hand) { var avatar = AvatarList.getAvatar(this.otherGrabbingUUID); var IN_FRONT_OF_AVATAR = { x: 0, y: 0.2, z: 0.4 }; // Up from hips and in front of avatar. var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); - var finishPisition = Vec3.sum(rayPickInfo.properties.position, // Entity's centroid. - Vec3.multiplyQbyV(rayPickInfo.properties.rotation , - Vec3.multiplyVbyV(rayPickInfo.properties.dimensions, - Vec3.subtract(DEFAULT_REGISTRATION_POINT, rayPickInfo.properties.registrationPoint)))); + var rayHitProps = entityPropertiesCache.getProps(rayPickInfo.entityID); + var finishPisition = Vec3.sum(rayHitProps.position, // Entity's centroid. + Vec3.multiplyQbyV(rayHitProps.rotation , + Vec3.multiplyVbyV(rayHitProps.dimensions, + Vec3.subtract(DEFAULT_REGISTRATION_POINT, rayHitProps.registrationPoint)))); this.otherGrabbingLineOn(startPosition, finishPisition, COLORS_GRAB_DISTANCE_HOLD); } else { this.otherGrabbingLineOff(); @@ -3442,14 +3443,14 @@ function MyController(hand) { }; this.offEnter = function() { - // Reuse the existing search distance if lasers were active since + // Reuse the existing search distance if lasers were active since // they will be shown in OFF state while in edit mode. var existingSearchDistance = this.searchSphereDistance; this.release(); - + if (isInEditMode()) { this.searchSphereDistance = existingSearchDistance; - } + } }; this.entityLaserTouchingEnter = function() { @@ -4154,7 +4155,7 @@ var updateWrapper = function () { } Script.setTimeout(updateWrapper, UPDATE_SLEEP_MS); -} +}; Script.setTimeout(updateWrapper, UPDATE_SLEEP_MS); function cleanup() { From de40604042c52902d8b03fe5e9d230458322d247 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 25 May 2017 09:54:40 -0700 Subject: [PATCH 09/25] whitespace --- scripts/system/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 0a08b60281..993cf22d83 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2349,7 +2349,7 @@ function MyController(hand) { var startPosition = Vec3.sum(avatar.position, Vec3.multiplyQbyV(avatar.rotation, IN_FRONT_OF_AVATAR)); var rayHitProps = entityPropertiesCache.getProps(rayPickInfo.entityID); var finishPisition = Vec3.sum(rayHitProps.position, // Entity's centroid. - Vec3.multiplyQbyV(rayHitProps.rotation , + Vec3.multiplyQbyV(rayHitProps.rotation, Vec3.multiplyVbyV(rayHitProps.dimensions, Vec3.subtract(DEFAULT_REGISTRATION_POINT, rayHitProps.registrationPoint)))); this.otherGrabbingLineOn(startPosition, finishPisition, COLORS_GRAB_DISTANCE_HOLD); From babae456d28b96376e4c3472c4ad7e1b0a73b8e1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 24 May 2017 19:28:46 -0700 Subject: [PATCH 10/25] Fix infinite loop in fbx reader --- libraries/fbx/src/FBXReader.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 64ee0bc869..bde8e83fc5 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -212,7 +212,10 @@ public: glm::mat4 getGlobalTransform(const QMultiMap& _connectionParentMap, const QHash& models, QString nodeID, bool mixamoHack) { glm::mat4 globalTransform; + QVector visitedNodes; // Used to prevent following a cycle while (!nodeID.isNull()) { + visitedNodes.append(nodeID); // Append each node we visit + const FBXModel& model = models.value(nodeID); globalTransform = glm::translate(model.translation) * model.preTransform * glm::mat4_cast(model.preRotation * model.rotation * model.postRotation) * model.postTransform * globalTransform; @@ -223,7 +226,7 @@ glm::mat4 getGlobalTransform(const QMultiMap& _connectionParen QList parentIDs = _connectionParentMap.values(nodeID); nodeID = QString(); foreach (const QString& parentID, parentIDs) { - if (models.contains(parentID)) { + if (models.contains(parentID) && !visitedNodes.contains(parentID)) { nodeID = parentID; break; } @@ -349,9 +352,12 @@ void addBlendshapes(const ExtractedBlendshape& extracted, const QList& connectionParentMap, const QHash& models, const QString& modelID) { QString topID = modelID; + QVector visitedNodes; // Used to prevent following a cycle forever { + visitedNodes.append(topID); // Append each node we visit + foreach (const QString& parentID, connectionParentMap.values(topID)) { - if (models.contains(parentID)) { + if (models.contains(parentID) && !visitedNodes.contains(parentID)) { topID = parentID; goto outerContinue; } From ea870881eeb4111b2ea94a27785b36256dba2157 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 25 May 2017 12:48:21 -0700 Subject: [PATCH 11/25] Log warning when we detect a connection loop --- libraries/fbx/src/FBXReader.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index bde8e83fc5..236daf6443 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -210,7 +210,7 @@ public: }; glm::mat4 getGlobalTransform(const QMultiMap& _connectionParentMap, - const QHash& models, QString nodeID, bool mixamoHack) { + const QHash& models, QString nodeID, bool mixamoHack, const QString& url) { glm::mat4 globalTransform; QVector visitedNodes; // Used to prevent following a cycle while (!nodeID.isNull()) { @@ -226,7 +226,12 @@ glm::mat4 getGlobalTransform(const QMultiMap& _connectionParen QList parentIDs = _connectionParentMap.values(nodeID); nodeID = QString(); foreach (const QString& parentID, parentIDs) { - if (models.contains(parentID) && !visitedNodes.contains(parentID)) { + if (visitedNodes.contains(parentID)) { + qCWarning(modelformat) << "Ignoring loop detected in FBX connection map for" << url; + continue; + } + + if (models.contains(parentID)) { nodeID = parentID; break; } @@ -350,14 +355,19 @@ void addBlendshapes(const ExtractedBlendshape& extracted, const QList& connectionParentMap, - const QHash& models, const QString& modelID) { + const QHash& models, const QString& modelID, const QString& url) { QString topID = modelID; QVector visitedNodes; // Used to prevent following a cycle forever { visitedNodes.append(topID); // Append each node we visit foreach (const QString& parentID, connectionParentMap.values(topID)) { - if (models.contains(parentID) && !visitedNodes.contains(parentID)) { + if (visitedNodes.contains(parentID)) { + qCWarning(modelformat) << "Ignoring loop detected in FBX connection map for" << url; + continue; + } + + if (models.contains(parentID)) { topID = parentID; goto outerContinue; } @@ -1313,7 +1323,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (!clusters.contains(clusterID)) { continue; } - QString topID = getTopModelID(_connectionParentMap, models, _connectionChildMap.value(clusterID)); + QString topID = getTopModelID(_connectionParentMap, models, _connectionChildMap.value(clusterID), url); _connectionChildMap.remove(_connectionParentMap.take(model.key()), model.key()); _connectionParentMap.insert(model.key(), topID); goto outerBreak; @@ -1335,7 +1345,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS first = id; } } - QString topID = getTopModelID(_connectionParentMap, models, first); + QString topID = getTopModelID(_connectionParentMap, models, first, url); appendModelIDs(_connectionParentMap.value(topID), _connectionChildMap, models, remainingModels, modelIDs); } @@ -1517,7 +1527,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS // accumulate local transforms QString modelID = models.contains(it.key()) ? it.key() : _connectionParentMap.value(it.key()); - glm::mat4 modelTransform = getGlobalTransform(_connectionParentMap, models, modelID, geometry.applicationName == "mixamo.com"); + glm::mat4 modelTransform = getGlobalTransform(_connectionParentMap, models, modelID, geometry.applicationName == "mixamo.com", url); // compute the mesh extents from the transformed vertices foreach (const glm::vec3& vertex, extracted.mesh.vertices) { From 4d791211eef403095e8b6ea459d9a6d6c5cf5999 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 10:11:16 -0700 Subject: [PATCH 12/25] Make the changes - big thanks to Andrew! --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 9 ++++++--- libraries/entities/src/EntityItemProperties.cpp | 7 ++++++- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityScriptingInterface.cpp | 10 ++++++---- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 09308baabb..d62181c651 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1091,15 +1091,18 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // trigger scripted collision sounds and events for locally owned objects EntityItemPointer entityA = entityTree->findEntityByEntityItemID(idA); - if ((bool)entityA && myNodeID == entityA->getSimulatorID()) { + EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); + QUuid entityASimulatorID = entityA->getSimulatorID(); + QUuid entityBSimulatorID = entityB->getSimulatorID(); + if ((bool)entityA && (myNodeID == entityASimulatorID || ((bool)entityB && myNodeID == entityBSimulatorID && entityASimulatorID.isNull()))) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); } } - EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); - if ((bool)entityB && myNodeID == entityB->getSimulatorID()) { + + if ((bool)entityB && (myNodeID == entityBSimulatorID || ((bool)entityA && myNodeID == entityASimulatorID && entityBSimulatorID.isNull()))) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1ed020e592..4595ebf70d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1824,10 +1824,15 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged; } +bool EntityItemProperties::hasDynamicPhysicsChanges() const { + return _dynamicChanged || _velocityChanged || _angularVelocityChanged || _accelerationChanged; +} + bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged; + _compoundShapeURLChanged || _collisionlessChanged || _collisionMaskChanged || + _rotationChanged || _positionChanged; } void EntityItemProperties::clearSimulationOwner() { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 590298e102..697c634c67 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -274,6 +274,7 @@ public: void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; + bool hasDynamicPhysicsChanges() const; bool hasMiscPhysicsChanges() const; void clearSimulationOwner(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index b184d648da..367343cb60 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -414,15 +414,17 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& entityFound = true; // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); - bool hasTerseUpdateChanges = properties.hasTerseUpdateChanges(); - bool hasPhysicsChanges = properties.hasMiscPhysicsChanges() || hasTerseUpdateChanges; - if (_bidOnSimulationOwnership && hasPhysicsChanges) { + bool hasMiscPhysicsChanges = properties.hasMiscPhysicsChanges(); + bool hasDynamicsChanges = properties.hasDynamicPhysicsChanges(); + // _bidOnSimulationOwnership is set per-instance of the scripting interface. + // It essentially corresponds to "Am I an AC or an Interface client?" - ACs will never bid. + if ((_bidOnSimulationOwnership && ((hasMiscPhysicsChanges && entity->isMoving()) || hasDynamicsChanges))) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties - if (hasTerseUpdateChanges) { + if (properties.hasTerseUpdateChanges()) { entity->getAllTerseUpdateProperties(properties); } // TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object From acd85b379f67d3ab12836cc814c9d2374a422755 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 12:50:43 -0700 Subject: [PATCH 13/25] Make this PR a protocol change --- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index f88015a4e4..0dbbcd771f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -114,7 +114,8 @@ public: EntityServerScriptLog, AdjustAvatarSorting, OctreeFileReplacement, - LAST_PACKET_TYPE = OctreeFileReplacement + SimulationBiddingChanges, + LAST_PACKET_TYPE = SimulationBiddingChanges }; }; From 0ef507c03791c399e5aebc4430275e060243b2e5 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 23 May 2017 14:41:02 -0700 Subject: [PATCH 14/25] Revert 'dynamicChanged' to be a 'misc' physics property --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4595ebf70d..fa4df72387 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1825,13 +1825,13 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { } bool EntityItemProperties::hasDynamicPhysicsChanges() const { - return _dynamicChanged || _velocityChanged || _angularVelocityChanged || _accelerationChanged; + return _velocityChanged || _angularVelocityChanged || _accelerationChanged; } bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _collisionlessChanged || _collisionMaskChanged || + _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged || _rotationChanged || _positionChanged; } From f6195cdb1eb712c61c6965abdc99c05b95146eec Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 10:16:51 -0700 Subject: [PATCH 15/25] Committing checkpoint changes, then testing --- .../src/EntityTreeRenderer.cpp | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index d62181c651..7b2333ade9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1092,24 +1092,29 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons // trigger scripted collision sounds and events for locally owned objects EntityItemPointer entityA = entityTree->findEntityByEntityItemID(idA); EntityItemPointer entityB = entityTree->findEntityByEntityItemID(idB); - QUuid entityASimulatorID = entityA->getSimulatorID(); - QUuid entityBSimulatorID = entityB->getSimulatorID(); - if ((bool)entityA && (myNodeID == entityASimulatorID || ((bool)entityB && myNodeID == entityBSimulatorID && entityASimulatorID.isNull()))) { - playEntityCollisionSound(entityA, collision); - emit collisionWithEntity(idA, idB, collision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); - } - } + if ((bool)entityA && (bool)entityB) { + QUuid entityASimulatorID = entityA->getSimulatorID(); + QUuid entityBSimulatorID = entityB->getSimulatorID(); + bool entityAIsStatic = !entityA->getDynamic() && !entityA->isMoving(); + bool entityBIsStatic = !entityB->getDynamic() && !entityB->isMoving(); - if ((bool)entityB && (myNodeID == entityBSimulatorID || ((bool)entityA && myNodeID == entityASimulatorID && entityBSimulatorID.isNull()))) { - playEntityCollisionSound(entityB, collision); - // since we're swapping A and B we need to send the inverted collision - Collision invertedCollision(collision); - invertedCollision.invert(); - emit collisionWithEntity(idB, idA, invertedCollision); - if (_entitiesScriptEngine) { - _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, invertedCollision); + if (myNodeID == entityASimulatorID || (myNodeID == entityBSimulatorID && entityAIsStatic)) { + playEntityCollisionSound(entityA, collision); + emit collisionWithEntity(idA, idB, collision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idA, "collisionWithEntity", idB, collision); + } + } + + if (myNodeID == entityBSimulatorID || (myNodeID == entityASimulatorID && entityBIsStatic)) { + playEntityCollisionSound(entityB, collision); + // since we're swapping A and B we need to send the inverted collision + Collision invertedCollision(collision); + invertedCollision.invert(); + emit collisionWithEntity(idB, idA, invertedCollision); + if (_entitiesScriptEngine) { + _entitiesScriptEngine->callEntityScriptMethod(idB, "collisionWithEntity", idA, invertedCollision); + } } } } From be398749997c78c8acf3e4de35afe03e866244ce Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 11:17:03 -0700 Subject: [PATCH 16/25] Changes after discussion with Brad --- .../src/EntityTreeRenderer.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 7b2333ade9..fccc6f512f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1095,10 +1095,20 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons if ((bool)entityA && (bool)entityB) { QUuid entityASimulatorID = entityA->getSimulatorID(); QUuid entityBSimulatorID = entityB->getSimulatorID(); - bool entityAIsStatic = !entityA->getDynamic() && !entityA->isMoving(); - bool entityBIsStatic = !entityB->getDynamic() && !entityB->isMoving(); + bool entityAIsDynamic = entityA->getDynamic(); + bool entityBIsDynamic = entityB->getDynamic(); - if (myNodeID == entityASimulatorID || (myNodeID == entityBSimulatorID && entityAIsStatic)) { +#ifdef WANT_DEBUG + bool bothEntitiesStatic = !entityAIsDynamic && !entityBIsDynamic; + if (bothEntitiesStatic) { + qCDebug(entities) << "A collision has occurred between two static entities!"; + qCDebug(entities) << "Entity A ID:" << entityA->getID(); + qCDebug(entities) << "Entity B ID:" << entityB->getID(); + } + assert(!bothEntitiesStatic); +#endif + + if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && !entityAIsDynamic)) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { @@ -1106,7 +1116,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons } } - if (myNodeID == entityBSimulatorID || (myNodeID == entityASimulatorID && entityBIsStatic)) { + if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && !entityBIsDynamic)) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); From b86b07c08f03b8c11b0f593d97a6f68d92845269 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 24 May 2017 14:15:59 -0700 Subject: [PATCH 17/25] Pull out ownership bidding changes --- libraries/entities/src/EntityItemProperties.cpp | 7 +------ libraries/entities/src/EntityItemProperties.h | 1 - libraries/entities/src/EntityScriptingInterface.cpp | 10 ++++------ libraries/networking/src/udt/PacketHeaders.h | 4 ++-- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fa4df72387..1ed020e592 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1824,15 +1824,10 @@ bool EntityItemProperties::hasTerseUpdateChanges() const { return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged; } -bool EntityItemProperties::hasDynamicPhysicsChanges() const { - return _velocityChanged || _angularVelocityChanged || _accelerationChanged; -} - bool EntityItemProperties::hasMiscPhysicsChanges() const { return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged || _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged || - _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged || - _rotationChanged || _positionChanged; + _compoundShapeURLChanged || _dynamicChanged || _collisionlessChanged || _collisionMaskChanged; } void EntityItemProperties::clearSimulationOwner() { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 697c634c67..590298e102 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -274,7 +274,6 @@ public: void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; - bool hasDynamicPhysicsChanges() const; bool hasMiscPhysicsChanges() const; void clearSimulationOwner(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 367343cb60..b184d648da 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -414,17 +414,15 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& entityFound = true; // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); - bool hasMiscPhysicsChanges = properties.hasMiscPhysicsChanges(); - bool hasDynamicsChanges = properties.hasDynamicPhysicsChanges(); - // _bidOnSimulationOwnership is set per-instance of the scripting interface. - // It essentially corresponds to "Am I an AC or an Interface client?" - ACs will never bid. - if ((_bidOnSimulationOwnership && ((hasMiscPhysicsChanges && entity->isMoving()) || hasDynamicsChanges))) { + bool hasTerseUpdateChanges = properties.hasTerseUpdateChanges(); + bool hasPhysicsChanges = properties.hasMiscPhysicsChanges() || hasTerseUpdateChanges; + if (_bidOnSimulationOwnership && hasPhysicsChanges) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties - if (properties.hasTerseUpdateChanges()) { + if (hasTerseUpdateChanges) { entity->getAllTerseUpdateProperties(properties); } // TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0dbbcd771f..2cc3a2c42e 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -114,8 +114,8 @@ public: EntityServerScriptLog, AdjustAvatarSorting, OctreeFileReplacement, - SimulationBiddingChanges, - LAST_PACKET_TYPE = SimulationBiddingChanges + CollisionEventChanges, + LAST_PACKET_TYPE = CollisionEventChanges }; }; From f2fab5718735e5ffce04dc8fca8a9cf6612514da Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 25 May 2017 09:28:11 -0700 Subject: [PATCH 18/25] Update conditional to handle 'other unowned' case --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fccc6f512f..e029ca6ada 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1108,7 +1108,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons assert(!bothEntitiesStatic); #endif - if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && !entityAIsDynamic)) { + if ((myNodeID == entityASimulatorID && entityAIsDynamic) || (myNodeID == entityBSimulatorID && (!entityAIsDynamic || entityASimulatorID.isNull()))) { playEntityCollisionSound(entityA, collision); emit collisionWithEntity(idA, idB, collision); if (_entitiesScriptEngine) { @@ -1116,7 +1116,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons } } - if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && !entityBIsDynamic)) { + if ((myNodeID == entityBSimulatorID && entityBIsDynamic) || (myNodeID == entityASimulatorID && (!entityBIsDynamic || entityBSimulatorID.isNull()))) { playEntityCollisionSound(entityB, collision); // since we're swapping A and B we need to send the inverted collision Collision invertedCollision(collision); From 108c444cc7a375a84327aace34a4ef6386d2dfa3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 25 May 2017 21:59:06 +0100 Subject: [PATCH 19/25] clean up code --- interface/src/avatar/MyAvatar.cpp | 20 ++++++++-------- interface/src/avatar/MyAvatar.h | 12 +++++----- interface/src/avatar/MySkeletonModel.cpp | 4 ++-- plugins/openvr/src/ViveControllerManager.cpp | 6 +---- plugins/openvr/src/ViveControllerManager.h | 24 ++++++++------------ 5 files changed, 28 insertions(+), 38 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 34ad767460..72a9281564 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1447,30 +1447,30 @@ void MyAvatar::setArmControllerPosesInSensorFrame(const controller::Pose& left, _rightArmControllerPoseInSensorFrameCache.set(right); } -controller::Pose MyAvatar::getLeftArmControllerInSensorFrame() const { +controller::Pose MyAvatar::getLeftArmControllerPoseInSensorFrame() const { return _leftArmControllerPoseInSensorFrameCache.get(); } -controller::Pose MyAvatar::getRightArmControllerInSensorFrame() const { +controller::Pose MyAvatar::getRightArmControllerPoseInSensorFrame() const { return _rightArmControllerPoseInSensorFrameCache.get(); } -controller::Pose MyAvatar::getLeftArmControllerInWorldFrame() const { - return getLeftArmControllerInSensorFrame().transform(getSensorToWorldMatrix()); +controller::Pose MyAvatar::getLeftArmControllerPoseInWorldFrame() const { + return getLeftArmControllerPoseInSensorFrame().transform(getSensorToWorldMatrix()); } -controller::Pose MyAvatar::getRightArmControllerInWorldFrame() const { - return getRightArmControllerInSensorFrame().transform(getSensorToWorldMatrix()); +controller::Pose MyAvatar::getRightArmControllerPoseInWorldFrame() const { + return getRightArmControllerPoseInSensorFrame().transform(getSensorToWorldMatrix()); } -controller::Pose MyAvatar::getLeftArmControllerInAvatarFrame() const { +controller::Pose MyAvatar::getLeftArmControllerPoseInAvatarFrame() const { glm::mat4 worldToAvatarMat = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); - return getLeftArmControllerInWorldFrame().transform(worldToAvatarMat); + return getLeftArmControllerPoseInWorldFrame().transform(worldToAvatarMat); } -controller::Pose MyAvatar::getRightArmControllerInAvatarFrame() const { +controller::Pose MyAvatar::getRightArmControllerPoseInAvatarFrame() const { glm::mat4 worldToAvatarMat = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); - return getRightArmControllerInWorldFrame().transform(worldToAvatarMat); + return getRightArmControllerPoseInWorldFrame().transform(worldToAvatarMat); } void MyAvatar::updateMotors() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9bbdbd7b23..e0a3a1559e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -472,12 +472,12 @@ public: controller::Pose getHeadControllerPoseInAvatarFrame() const; void setArmControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right); - controller::Pose getLeftArmControllerInSensorFrame() const; - controller::Pose getRightArmControllerInSensorFrame() const; - controller::Pose getLeftArmControllerInWorldFrame() const; - controller::Pose getRightArmControllerInWorldFrame() const; - controller::Pose getLeftArmControllerInAvatarFrame() const; - controller::Pose getRightArmControllerInAvatarFrame() const; + controller::Pose getLeftArmControllerPoseInSensorFrame() const; + controller::Pose getRightArmControllerPoseInSensorFrame() const; + controller::Pose getLeftArmControllerPoseInWorldFrame() const; + controller::Pose getRightArmControllerPoseInWorldFrame() const; + controller::Pose getLeftArmControllerPoseInAvatarFrame() const; + controller::Pose getRightArmControllerPoseInAvatarFrame() const; bool hasDriveInput() const; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index ea97e3d0fe..a88631f47f 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -92,7 +92,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { headParams.spine2Enabled = false; } - auto avatarRightArmPose = myAvatar->getRightArmControllerInAvatarFrame(); + auto avatarRightArmPose = myAvatar->getRightArmControllerPoseInAvatarFrame(); if (avatarRightArmPose.isValid()) { glm::mat4 rightArmMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarRightArmPose.getRotation(), avatarRightArmPose.getTranslation()); headParams.rightArmPosition = extractTranslation(rightArmMat); @@ -102,7 +102,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { headParams.rightArmEnabled = false; } - auto avatarLeftArmPose = myAvatar->getLeftArmControllerInAvatarFrame(); + auto avatarLeftArmPose = myAvatar->getLeftArmControllerPoseInAvatarFrame(); if (avatarLeftArmPose.isValid()) { glm::mat4 leftArmMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarLeftArmPose.getRotation(), avatarLeftArmPose.getTranslation()); headParams.leftArmPosition = extractTranslation(leftArmMat); diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 016b2a1c55..2563e8f218 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -661,11 +661,7 @@ void ViveControllerManager::InputDevice::calibrateShoulders(glm::mat4& defaultTo _jointToPuckMap[controller::RIGHT_ARM] = firstShoulder.first; _pucksOffset[firstShoulder.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightArm, firstShoulder.second); } -} - -void ViveControllerManager::InputDevice::calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { - int headIndex = _validTrackedObjects.size() - 1; -} +} void ViveControllerManager::InputDevice::loadSettings() { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index bc9558beaa..a76adaa8f9 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -80,6 +80,15 @@ private: const vec3& angularVelocity); void partitionTouchpad(int sButton, int xAxis, int yAxis, int centerPsuedoButton, int xPseudoButton, int yPseudoButton); void printDeviceTrackingResultChange(uint32_t deviceIndex); + void setConfigFromString(const QString& value); + void loadSettings(); + void saveSettings() const; + void calibrateFeet(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + void calibrateHips(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + void calibrateChest(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); + + void calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, + int firstShoulderIndex, int secondShoulderIndex); class FilteredStick { public: @@ -106,13 +115,10 @@ private: }; enum class Config { Auto, - Head, Feet, - Shoulders, FeetAndHips, FeetHipsAndChest, FeetHipsAndShoulders, - FeetHipsChestAndHead }; Config _config { Config::Auto }; Config _preferedConfig { Config::Auto }; @@ -139,21 +145,9 @@ private: bool _triggersPressedHandled { false }; bool _calibrated { false }; bool _timeTilCalibrationSet { false }; - bool overrideHands { false }; mutable std::recursive_mutex _lock; QString configToString(Config config); - void setConfigFromString(const QString& value); - void loadSettings(); - void saveSettings() const; - void calibrateFeet(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); - void calibrateHips(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); - void calibrateChest(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); - - void calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, - int firstShoulderIndex, int secondShoulderIndex); - - void calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration); friend class ViveControllerManager; }; From cce19f702742e7f6f23b66f70bfa017f896a1526 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 25 May 2017 22:07:51 +0100 Subject: [PATCH 20/25] removed unnessary code --- plugins/openvr/src/ViveControllerManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2563e8f218..2b746e6983 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -51,8 +51,6 @@ static const int MIN_PUCK_COUNT = 2; static const int MIN_FEET_AND_HIPS = 3; static const int MIN_FEET_HIPS_CHEST = 4; static const int MIN_FEET_HIPS_SHOULDERS = 5; -static const int MIN_FEET_HIPS_CHEST_AND_HANDS = 6; -static const int MIN_FEET_HIPS_SHOULDERS_AND_HANDS = 7; static const int FIRST_FOOT = 0; static const int SECOND_FOOT = 1; static const int HIP = 2; From aa5aba428a218a4871e56358fe27b0c9ea6dfcb4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 25 May 2017 11:49:32 -0700 Subject: [PATCH 21/25] PR feedback --- libraries/ktx/src/khronos/KHR.h | 87 ++++++++++++++++++++++++---- libraries/ktx/src/ktx/KTX.cpp | 79 +++++++++---------------- libraries/ktx/src/ktx/KTX.h | 14 +++-- libraries/ktx/src/ktx/Validation.cpp | 17 ++---- libraries/ktx/src/ktx/Writer.cpp | 4 +- tests/ktx/src/main.cpp | 14 ++--- 6 files changed, 128 insertions(+), 87 deletions(-) diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h index 7b3e3453c7..d710ca7b40 100644 --- a/libraries/ktx/src/khronos/KHR.h +++ b/libraries/ktx/src/khronos/KHR.h @@ -209,6 +209,44 @@ namespace khronos { COMPRESSED_SIGNED_RG11_EAC = 0x9273, }; + template + inline uint32_t evalAlignedCompressedBlockCount(uint32_t value) { + // FIXME add static assert that ALIGNMENT is a power of 2 + return (value + (ALIGNMENT - 1) / ALIGNMENT); + } + + inline uint8_t evalBlockAlignemnt(InternalFormat format, uint32_t value) { + switch (format) { + case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: // BC1 + case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: // BC1A + case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: // BC3 + case InternalFormat::COMPRESSED_RED_RGTC1: // BC4 + case InternalFormat::COMPRESSED_RG_RGTC2: // BC5 + case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 + return evalAlignedCompressedBlockCount<4>(value); + + default: + throw std::runtime_error("Unknown format"); + } + } + + inline uint8_t evalCompressedBlockSize(InternalFormat format) { + switch (format) { + case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: + case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case InternalFormat::COMPRESSED_RED_RGTC1: + return 8; + + case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: + case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case InternalFormat::COMPRESSED_RG_RGTC2: + return 16; + + default: + return 0; + } + } + enum class BaseInternalFormat : uint32_t { // GL 4.4 Table 8.11 DEPTH_COMPONENT = 0x1902, @@ -220,19 +258,46 @@ namespace khronos { STENCIL_INDEX = 0x1901, }; - enum CubeMapFace { - POS_X = 0, - NEG_X = 1, - POS_Y = 2, - NEG_Y = 3, - POS_Z = 4, - NEG_Z = 5, - NUM_CUBEMAPFACES = 6, - }; + inline uint8_t evalComponentCount(BaseInternalFormat format) { + switch (format) { + case BaseInternalFormat::DEPTH_COMPONENT: + case BaseInternalFormat::STENCIL_INDEX: + case BaseInternalFormat::RED: + return 1; + + case BaseInternalFormat::DEPTH_STENCIL: + case BaseInternalFormat::RG: + return 2; + + case BaseInternalFormat::RGB: + return 3; + + case BaseInternalFormat::RGBA: + return 4; + + default: + break; + } + + return 0; + } + + namespace cubemap { + enum Constants { + NUM_CUBEMAPFACES = 6, + }; + + enum class Face { + POSITIVE_X = 0x8515, + NEGATIVE_X = 0x8516, + POSITIVE_Y = 0x8517, + NEGATIVE_Y = 0x8518, + POSITIVE_Z = 0x8519, + NEGATIVE_Z = 0x851A, + }; + } } - } - } #endif // khronos_khr_hpp diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index 1900c4a4b1..d6faee4cc7 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -28,70 +28,45 @@ uint32_t Header::evalMaxDimension() const { return std::max(getPixelWidth(), std::max(getPixelHeight(), getPixelDepth())); } -uint32_t Header::evalPixelOrBlockWidth(uint32_t level) const { - auto pixelWidth = std::max(getPixelWidth() >> level, 1U); +uint32_t Header::evalPixelOrBlockDimension(uint32_t pixelDimension) const { if (isCompressed()) { - return evalAlignedCount(pixelWidth); - } else { - return pixelWidth; - } + return khronos::gl::texture::evalBlockAlignemnt(getGLInternaFormat(), pixelDimension); + } + return pixelDimension; } + +uint32_t Header::evalMipPixelOrBlockDimension(uint32_t mipLevel, uint32_t pixelDimension) const { + uint32_t mipPixelDimension = evalMipDimension(mipLevel, pixelDimension); + return evalPixelOrBlockDimension(mipPixelDimension); +} + +uint32_t Header::evalPixelOrBlockWidth(uint32_t level) const { + return evalMipPixelOrBlockDimension(level, getPixelWidth()); +} + uint32_t Header::evalPixelOrBlockHeight(uint32_t level) const { - auto pixelWidth = std::max(getPixelHeight() >> level, 1U); - if (glType == COMPRESSED_TYPE) { - auto format = getGLInternaFormat(); - switch (format) { - case GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: // BC1 - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: // BC1A - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: // BC3 - case GLInternalFormat::COMPRESSED_RED_RGTC1: // BC4 - case GLInternalFormat::COMPRESSED_RG_RGTC2: // BC5 - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 - return evalAlignedCount(pixelWidth); - default: - throw std::runtime_error("Unknown format"); - } - } else { - return pixelWidth; - } + return evalMipPixelOrBlockDimension(level, getPixelHeight()); } + uint32_t Header::evalPixelOrBlockDepth(uint32_t level) const { - return std::max(getPixelDepth() >> level, 1U); + return evalMipDimension(level, getPixelDepth()); } size_t Header::evalPixelOrBlockSize() const { + size_t result = 0; if (isCompressed()) { auto format = getGLInternaFormat(); - switch (format) { - case GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GLInternalFormat::COMPRESSED_RED_RGTC1: - return 8; - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - case GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GLInternalFormat::COMPRESSED_RG_RGTC2: - return 16; - default: - break; - } + result = khronos::gl::texture::evalCompressedBlockSize(format); } else { + // FIXME should really be using the internal format, not the base internal format auto baseFormat = getGLBaseInternalFormat(); - switch (baseFormat) { - case GLBaseInternalFormat::RED: - return 1; - case GLBaseInternalFormat::RG: - return 2; - case GLBaseInternalFormat::RGB: - return 3; - case GLBaseInternalFormat::RGBA: - return 4; - default: - break; - } + result = khronos::gl::texture::evalComponentCount(baseFormat); } - qWarning() << "Unknown ktx format: " << glFormat << " " << glBaseInternalFormat << " " << glInternalFormat; - return 0; + if (0 == result) { + qWarning() << "Unknown ktx format: " << glFormat << " " << glBaseInternalFormat << " " << glInternalFormat; + } + return result; } size_t Header::evalRowSize(uint32_t level) const { @@ -100,7 +75,7 @@ size_t Header::evalRowSize(uint32_t level) const { if (pixSize == 0) { return 0; } - return evalPadded(pixWidth * pixSize); + return evalPaddedSize(pixWidth * pixSize); } size_t Header::evalFaceSize(uint32_t level) const { @@ -184,7 +159,7 @@ KeyValue::KeyValue(const std::string& key, const std::string& value) : } uint32_t KeyValue::serializedByteSize() const { - return (uint32_t)sizeof(uint32_t) + evalPadded(_byteSize); + return (uint32_t)sizeof(uint32_t) + evalPaddedSize(_byteSize); } uint32_t KeyValue::serializedKeyValuesByteSize(const KeyValues& keyValues) { diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index c6570f87c6..b02e2ada75 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -82,7 +82,7 @@ namespace ktx { // Alignment constants static const uint32_t ALIGNMENT { sizeof(uint32_t) }; static const uint32_t ALIGNMENT_REMAINDER { ALIGNMENT - 1 }; - static const uint32_t NUM_CUBEMAPFACES = khronos::gl::texture::CubeMapFace::NUM_CUBEMAPFACES; + static const uint32_t NUM_CUBEMAPFACES = khronos::gl::texture::cubemap::NUM_CUBEMAPFACES; // FIXME move out of this header, not specific to ktx const std::string HIFI_MIN_POPULATED_MIP_KEY { "hifi.minMip" }; @@ -94,7 +94,6 @@ namespace ktx { using GLFormat = khronos::gl::texture::Format; using GLInternalFormat = khronos::gl::texture::InternalFormat; using GLBaseInternalFormat = khronos::gl::texture::BaseInternalFormat; - using CubeMapFace = khronos::gl::texture::CubeMapFace; using Storage = storage::Storage; using StoragePointer = std::shared_ptr; @@ -112,7 +111,7 @@ namespace ktx { // Returns the passed value rounded up to the next 4 byte aligned value, if it's not already 4 byte aligned template - inline T evalPadded(T value) { + inline T evalPaddedSize(T value) { return (value + ALIGNMENT_REMAINDER) & ~(T)ALIGNMENT_REMAINDER; } @@ -123,7 +122,7 @@ namespace ktx { template inline bool checkAlignment(T value) { - return ((value & 0x3) == 0); + return ((value & ALIGNMENT_REMAINDER) == 0); } @@ -216,6 +215,13 @@ namespace ktx { ImageDescriptors generateImageDescriptors() const; private: + uint32_t evalPixelOrBlockDimension(uint32_t pixelDimension) const; + uint32_t evalMipPixelOrBlockDimension(uint32_t level, uint32_t pixelDimension) const; + + static inline uint32_t evalMipDimension(uint32_t mipLevel, uint32_t pixelDimension) { + return std::max(pixelDimension >> mipLevel, 1U); + } + void setDimensions(uint32_t width, uint32_t height = 0, uint32_t depth = 0, uint32_t numSlices = 0, uint32_t numFaces = 1) { pixelWidth = (width > 0 ? width : 1); pixelHeight = height; diff --git a/libraries/ktx/src/ktx/Validation.cpp b/libraries/ktx/src/ktx/Validation.cpp index a59dde92f1..c54a259ab1 100644 --- a/libraries/ktx/src/ktx/Validation.cpp +++ b/libraries/ktx/src/ktx/Validation.cpp @@ -281,9 +281,7 @@ struct AlignedStreamBuffer { } bool skip(size_t skipSize) { - if ((skipSize % 4) != 0) { - skipSize += (3 - ((skipSize + 3) % 4)); - } + skipSize = ktx::evalPaddedSize(skipSize); if (skipSize > _size) { return false; } @@ -323,7 +321,7 @@ bool validateKeyValueData(AlignedStreamBuffer kvbuffer) { } bool KTX::validate(const StoragePointer& src) { - if ((src->size() % 4) != 0) { + if (!checkAlignment(src->size())) { // All KTX data is 4-byte aligned qDebug() << "Invalid size, not 4 byte aligned"; return false; @@ -363,17 +361,14 @@ bool KTX::validate(const StoragePointer& src) { return false; } - if (header.numberOfArrayElements == 0 && header.numberOfFaces == 6) { - for (uint8_t face = 0; face < NUM_CUBEMAPFACES; ++face) { + uint32_t arrayElements = header.numberOfArrayElements == 0 ? 1 : header.numberOfArrayElements; + for (uint32_t arrayElement = 0; arrayElement < arrayElements; ++arrayElement) { + for (uint8_t face = 0; face < header.numberOfFaces; ++face) { if (!buffer.skip(imageSize)) { - qDebug() << "Unable to skip past cubemap data"; + qDebug() << "Unable to skip past image data"; return false; } } - } else { - if (!buffer.skip(imageSize)) { - return false; - } } } diff --git a/libraries/ktx/src/ktx/Writer.cpp b/libraries/ktx/src/ktx/Writer.cpp index e18a3f1adb..c94856e598 100644 --- a/libraries/ktx/src/ktx/Writer.cpp +++ b/libraries/ktx/src/ktx/Writer.cpp @@ -70,7 +70,7 @@ namespace ktx { for (uint32_t l = 0; l < numMips; l++) { if (images.size() > l) { storageSize += sizeof(uint32_t); - storageSize += evalPadded(images[l]._imageSize); + storageSize += evalPaddedSize(images[l]._imageSize); } } return storageSize; @@ -88,7 +88,7 @@ namespace ktx { for (uint32_t l = 0; l < numMips; l++) { if (imageDescriptors.size() > l) { storageSize += sizeof(uint32_t); - storageSize += evalPadded(imageDescriptors[l]._imageSize); + storageSize += evalPaddedSize(imageDescriptors[l]._imageSize); } } return storageSize; diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index 282c537ed2..3b62b89948 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -96,13 +96,13 @@ int main(int argc, char** argv) { Q_ASSERT(ktx::evalPadding(4) == 0); Q_ASSERT(ktx::evalPadding(1024) == 0); Q_ASSERT(ktx::evalPadding(1025) == 3); - Q_ASSERT(ktx::evalPadded(0) == 0); - Q_ASSERT(ktx::evalPadded(1) == 4); - Q_ASSERT(ktx::evalPadded(2) == 4); - Q_ASSERT(ktx::evalPadded(3) == 4); - Q_ASSERT(ktx::evalPadded(4) == 4); - Q_ASSERT(ktx::evalPadded(1024) == 1024); - Q_ASSERT(ktx::evalPadded(1025) == 1028); + Q_ASSERT(ktx::evalPaddedSize(0) == 0); + Q_ASSERT(ktx::evalPaddedSize(1) == 4); + Q_ASSERT(ktx::evalPaddedSize(2) == 4); + Q_ASSERT(ktx::evalPaddedSize(3) == 4); + Q_ASSERT(ktx::evalPaddedSize(4) == 4); + Q_ASSERT(ktx::evalPaddedSize(1024) == 1024); + Q_ASSERT(ktx::evalPaddedSize(1025) == 1028); Q_ASSERT(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13)); DependencyManager::set(); From d317d9236fd248033d75965a94cc50b56ef9e102 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 26 May 2017 16:40:21 +0100 Subject: [PATCH 22/25] made requested changes --- libraries/animation/src/Rig.cpp | 3 +-- plugins/openvr/src/ViveControllerManager.cpp | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index a423c45597..add3a461af 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1051,8 +1051,7 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { if (params.leftArmEnabled) { _animVars.set("leftArmType", (int)IKTarget::Type::RotationAndPosition); _animVars.set("leftArmPosition", params.leftArmPosition); - _animVars.set("leftArmRotation", params.leftArmRotation); - + _animVars.set("leftArmRotation", params.leftArmRotation); } else { _animVars.set("leftArmType", (int)IKTarget::Type::Unknown); } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2b746e6983..53500a3353 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -349,7 +349,7 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr calibrateFeet(defaultToReferenceMat, inputCalibration); calibrateHips(defaultToReferenceMat, inputCalibration); calibrateChest(defaultToReferenceMat, inputCalibration); - } else if (_config == Config::FeetHipsAndShoulders && puckCount >= MIN_FEET_HIPS_SHOULDERS){ + } else if (_config == Config::FeetHipsAndShoulders && puckCount >= MIN_FEET_HIPS_SHOULDERS) { calibrateFeet(defaultToReferenceMat, inputCalibration); calibrateHips(defaultToReferenceMat, inputCalibration); int firstShoulderIndex = 3; @@ -621,7 +621,7 @@ void ViveControllerManager::InputDevice::calibrateFeet(glm::mat4& defaultToRefer _jointToPuckMap[controller::LEFT_FOOT] = firstFoot.first; _pucksOffset[firstFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, firstFootPose); _jointToPuckMap[controller::RIGHT_FOOT] = secondFoot.first; - _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); + _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultRightFoot, secondFootPose); } else { _jointToPuckMap[controller::LEFT_FOOT] = secondFoot.first; _pucksOffset[secondFoot.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultLeftFoot, secondFootPose); @@ -642,7 +642,6 @@ void ViveControllerManager::InputDevice::calibrateChest(glm::mat4& defaultToRefe void ViveControllerManager::InputDevice::calibrateShoulders(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, int firstShoulderIndex, int secondShoulderIndex) { - qDebug() << "calibrate shoulders"; const PuckPosePair& firstShoulder = _validTrackedObjects[firstShoulderIndex]; const PuckPosePair& secondShoulder = _validTrackedObjects[secondShoulderIndex]; const controller::Pose& firstShoulderPose = firstShoulder.second; @@ -707,7 +706,7 @@ void ViveControllerManager::InputDevice::createPreferences() { auto getter = [this]()->QString { return _configStringMap[_preferedConfig]; }; auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); - QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest" << "FeetHipsAndShoulders"); + QStringList list = {"Auto", "Feet", "FeetAndHips", "FeetHipsAndChest", "FeetHipsAndShoulders"}; preference->setItems(list); preferences->addPreference(preference); From f663573f1903bc0d37a96a3cf90cefcb9a762f41 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 26 May 2017 11:25:15 -0700 Subject: [PATCH 23/25] Fix compressed KTX loading --- libraries/ktx/src/khronos/KHR.h | 5 +++-- libraries/ktx/src/ktx/KTX.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h index d710ca7b40..a98f2cc0d4 100644 --- a/libraries/ktx/src/khronos/KHR.h +++ b/libraries/ktx/src/khronos/KHR.h @@ -212,10 +212,11 @@ namespace khronos { template inline uint32_t evalAlignedCompressedBlockCount(uint32_t value) { // FIXME add static assert that ALIGNMENT is a power of 2 - return (value + (ALIGNMENT - 1) / ALIGNMENT); + static uint32_t ALIGNMENT_REMAINDER = ALIGNMENT - 1; + return (value + ALIGNMENT_REMAINDER) / ALIGNMENT; } - inline uint8_t evalBlockAlignemnt(InternalFormat format, uint32_t value) { + inline uint32_t evalCompressedBlockCount(InternalFormat format, uint32_t value) { switch (format) { case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: // BC1 case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: // BC1A diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index d6faee4cc7..788ec54a47 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -30,7 +30,7 @@ uint32_t Header::evalMaxDimension() const { uint32_t Header::evalPixelOrBlockDimension(uint32_t pixelDimension) const { if (isCompressed()) { - return khronos::gl::texture::evalBlockAlignemnt(getGLInternaFormat(), pixelDimension); + return khronos::gl::texture::evalCompressedBlockCount(getGLInternaFormat(), pixelDimension); } return pixelDimension; } From 07440e325ffdce499df865dd5109eac753c448db Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 26 May 2017 12:04:35 -0700 Subject: [PATCH 24/25] fix force of BC3 instead of BC1a compression --- libraries/image/src/image/Image.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index dcc65e8995..f274dc54f8 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -493,10 +493,6 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s if (validAlpha) { processTextureAlpha(image, validAlpha, alphaAsMask); - - // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures - // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). - alphaAsMask = false; } gpu::TexturePointer theTexture = nullptr; @@ -506,7 +502,9 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(const QImage& s gpu::Element formatGPU; if (isColorTexturesCompressionEnabled()) { if (validAlpha) { - formatGPU = alphaAsMask ? gpu::Element::COLOR_COMPRESSED_SRGBA_MASK : gpu::Element::COLOR_COMPRESSED_SRGBA; + // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures + // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). + formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; } else { formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB; } From 6c2758e4eaa0d063b45fc96eb865394c9d65d4ac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 26 May 2017 14:37:24 -0700 Subject: [PATCH 25/25] fix reference to pending transfer count for progress/stats --- scripts/developer/utilities/render/stats.qml | 13 ++++++------- scripts/system/progress.js | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/developer/utilities/render/stats.qml b/scripts/developer/utilities/render/stats.qml index 7acf678570..54e0dc4ce8 100644 --- a/scripts/developer/utilities/render/stats.qml +++ b/scripts/developer/utilities/render/stats.qml @@ -20,9 +20,9 @@ Item { id: stats spacing: 8 anchors.fill:parent - + property var config: Render.getConfig("Stats") - + function evalEvenHeight() { // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ? return (height - spacing * (children.length - 1)) / children.length @@ -81,7 +81,7 @@ Item { color: "#1AC567" }, { - prop: "textureGPUTransferCount", + prop: "texturePendingGPUTransferCount", label: "Transfer", color: "#9495FF" } @@ -158,7 +158,7 @@ Item { } ] } - + PlotPerf { title: "State Changes" height: parent.evalEvenHeight() @@ -180,7 +180,7 @@ Item { color: "#1AC567" } ] - } + } property var drawOpaqueConfig: Render.getConfig("DrawOpaqueDeferred") property var drawTransparentConfig: Render.getConfig("DrawTransparentDeferred") @@ -211,7 +211,7 @@ Item { color: "#FED959" } ] - } + } PlotPerf { title: "Timing" @@ -250,4 +250,3 @@ Item { } } - diff --git a/scripts/system/progress.js b/scripts/system/progress.js index 81da38c8c2..f4741c5b6a 100644 --- a/scripts/system/progress.js +++ b/scripts/system/progress.js @@ -261,7 +261,7 @@ } } - gpuTextures = Render.getConfig("Stats").textureGPUTransferCount; + gpuTextures = Render.getConfig("Stats").texturePendingGPUTransferCount; // Update state if (!visible) { // Not visible because no recent downloads @@ -290,7 +290,7 @@ }, FADE_OUT_WAIT); } } else { - if (displayProgress < 100 || gpuTextures > 0) { // Was finished and waiting to fade out but have resumed so + if (displayProgress < 100 || gpuTextures > 0) { // Was finished and waiting to fade out but have resumed so // don't fade out Script.clearInterval(fadeWaitTimer); fadeWaitTimer = null;