diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 1c6600cf3f..06da18148f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -40,11 +40,9 @@ QmlCommerce::QmlCommerce() { connect(ledger.data(), &Ledger::transferAssetToUsernameResult, this, &QmlCommerce::transferAssetToUsernameResult); connect(ledger.data(), &Ledger::availableUpdatesResult, this, &QmlCommerce::availableUpdatesResult); connect(ledger.data(), &Ledger::updateItemResult, this, &QmlCommerce::updateItemResult); - + auto accountManager = DependencyManager::get(); - connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { - setPassphrase(""); - }); + connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); }); _appsPath = PathUtils::getAppDataPath() + "Apps/"; } @@ -105,7 +103,11 @@ void QmlCommerce::balance() { } } -void QmlCommerce::inventory(const QString& editionFilter, const QString& typeFilter, const QString& titleFilter, const int& page, const int& perPage) { +void QmlCommerce::inventory(const QString& editionFilter, + const QString& typeFilter, + const QString& titleFilter, + const int& page, + const int& perPage) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList cachedPublicKeys = wallet->listPublicKeys(); @@ -166,24 +168,30 @@ void QmlCommerce::certificateInfo(const QString& certificateId) { ledger->certificateInfo(certificateId); } -void QmlCommerce::transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage) { +void QmlCommerce::transferAssetToNode(const QString& nodeID, + const QString& certificateID, + const int& amount, + const QString& optionalMessage) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList keys = wallet->listPublicKeys(); if (keys.count() == 0) { - QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } }; + QJsonObject result{ { "status", "fail" }, { "message", "Uninitialized Wallet." } }; return emit transferAssetToNodeResult(result); } QString key = keys[0]; ledger->transferAssetToNode(key, nodeID, certificateID, amount, optionalMessage); } -void QmlCommerce::transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage) { +void QmlCommerce::transferAssetToUsername(const QString& username, + const QString& certificateID, + const int& amount, + const QString& optionalMessage) { auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); QStringList keys = wallet->listPublicKeys(); if (keys.count() == 0) { - QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } }; + QJsonObject result{ { "status", "fail" }, { "message", "Uninitialized Wallet." } }; return emit transferAssetToUsernameResult(result); } QString key = keys[0]; @@ -194,10 +202,7 @@ void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& cert auto ledger = DependencyManager::get(); ledger->updateLocation(certificateID, DependencyManager::get()->getPlaceName(), true); qApp->replaceDomainContent(itemHref); - QJsonObject messageProperties = { - { "status", "SuccessfulRequestToReplaceContent" }, - { "content_set_url", itemHref } - }; + QJsonObject messageProperties = { { "status", "SuccessfulRequestToReplaceContent" }, { "content_set_url", itemHref } }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); emit contentSetChanged(itemHref); @@ -214,10 +219,7 @@ QString QmlCommerce::getInstalledApps(const QString& justInstalledAppID) { QDir directory(_appsPath); QStringList apps = directory.entryList(QStringList("*.app.json")); - foreach(QString appFileName, apps) { - installedAppsFromMarketplace += appFileName; - installedAppsFromMarketplace += ","; - + foreach (QString appFileName, apps) { // If we were supplied a "justInstalledAppID" argument, that means we're entering this function // to get the new list of installed apps immediately after installing an app. // In that case, the app we installed may not yet have its associated script running - @@ -243,10 +245,12 @@ QString QmlCommerce::getInstalledApps(const QString& justInstalledAppID) { // delete the .app.json from the user's local disk. if (!runningScripts.contains(scriptURL)) { if (!appFile.remove()) { - qCWarning(commerce) - << "Couldn't delete local .app.json file (app's script isn't running). App filename is:" - << appFileName; + qCWarning(commerce) << "Couldn't delete local .app.json file (app's script isn't running). App filename is:" + << appFileName; } + } else { + installedAppsFromMarketplace += appFileName; + installedAppsFromMarketplace += ","; } } else { qCDebug(commerce) << "Couldn't open local .app.json file for reading."; @@ -317,7 +321,9 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { // Read from the file to know what .js script to stop QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::ReadOnly)) { - qCDebug(commerce) << "Couldn't open local .app.json file for deletion. Cannot continue with app uninstallation. App filename is:" << appHref.fileName(); + qCDebug(commerce) + << "Couldn't open local .app.json file for deletion. Cannot continue with app uninstallation. App filename is:" + << appHref.fileName(); return false; } QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); @@ -325,13 +331,15 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { QString scriptUrl = appFileJsonObject["scriptURL"].toString(); if (!DependencyManager::get()->stopScript(scriptUrl.trimmed(), false)) { - qCWarning(commerce) << "Couldn't stop script during app uninstall. Continuing anyway. ScriptURL is:" << scriptUrl.trimmed(); + qCWarning(commerce) << "Couldn't stop script during app uninstall. Continuing anyway. ScriptURL is:" + << scriptUrl.trimmed(); } // Delete the .app.json from the filesystem // remove() closes the file first. if (!appFile.remove()) { - qCWarning(commerce) << "Couldn't delete local .app.json file during app uninstall. Continuing anyway. App filename is:" << appHref.fileName(); + qCWarning(commerce) << "Couldn't delete local .app.json file during app uninstall. Continuing anyway. App filename is:" + << appHref.fileName(); } QFileInfo appFileInfo(appFile); @@ -352,7 +360,8 @@ bool QmlCommerce::openApp(const QString& itemHref) { QJsonObject appFileJsonObject = appFileJsonDocument.object(); QString homeUrl = appFileJsonObject["homeURL"].toString(); - auto tablet = dynamic_cast(DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); + auto tablet = dynamic_cast( + DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); if (homeUrl.contains(".qml", Qt::CaseInsensitive)) { tablet->loadQMLSource(homeUrl); } else if (homeUrl.contains(".html", Qt::CaseInsensitive)) { @@ -377,7 +386,7 @@ void QmlCommerce::updateItem(const QString& certificateId) { auto wallet = DependencyManager::get(); QStringList keys = wallet->listPublicKeys(); if (keys.count() == 0) { - QJsonObject result{ { "status", "fail" },{ "message", "Uninitialized Wallet." } }; + QJsonObject result{ { "status", "fail" }, { "message", "Uninitialized Wallet." } }; return emit updateItemResult(result); } QString key = keys[0]; diff --git a/libraries/audio/src/AudioHRTF.cpp b/libraries/audio/src/AudioHRTF.cpp index 23adcde0c5..b639301404 100644 --- a/libraries/audio/src/AudioHRTF.cpp +++ b/libraries/audio/src/AudioHRTF.cpp @@ -240,7 +240,7 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float float* ps = &src[i - HRTF_TAPS + 1]; // process forwards - assert(HRTF_TAPS % 4 == 0); + static_assert(HRTF_TAPS % 4 == 0, "HRTF_TAPS must be a multiple of 4"); for (int k = 0; k < HRTF_TAPS; k += 4) { @@ -276,23 +276,8 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float } } -// -// Runtime CPU dispatch -// - -#include "CPUDetect.h" - -void FIR_1x4_AVX2(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); -void FIR_1x4_AVX512(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); - -static void FIR_1x4(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) { - - static auto f = cpuSupportsAVX512() ? FIR_1x4_AVX512 : (cpuSupportsAVX2() ? FIR_1x4_AVX2 : FIR_1x4_SSE); - (*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch -} - // 4 channel planar to interleaved -static void interleave_4x4(float* src0, float* src1, float* src2, float* src3, float* dst, int numFrames) { +static void interleave_4x4_SSE(float* src0, float* src1, float* src2, float* src3, float* dst, int numFrames) { assert(numFrames % 4 == 0); @@ -323,7 +308,7 @@ static void interleave_4x4(float* src0, float* src1, float* src2, float* src3, f // process 2 cascaded biquads on 4 channels (interleaved) // biquads computed in parallel, by adding one sample of delay -static void biquad2_4x4(float* src, float* dst, float coef[5][8], float state[3][8], int numFrames) { +static void biquad2_4x4_SSE(float* src, float* dst, float coef[5][8], float state[3][8], int numFrames) { // enable flush-to-zero mode to prevent denormals unsigned int ftz = _MM_GET_FLUSH_ZERO_MODE(); @@ -388,7 +373,7 @@ static void biquad2_4x4(float* src, float* dst, float coef[5][8], float state[3] } // crossfade 4 inputs into 2 outputs with accumulation (interleaved) -static void crossfade_4x2(float* src, float* dst, const float* win, int numFrames) { +static void crossfade_4x2_SSE(float* src, float* dst, const float* win, int numFrames) { assert(numFrames % 4 == 0); @@ -435,12 +420,12 @@ static void crossfade_4x2(float* src, float* dst, const float* win, int numFrame } // linear interpolation with gain -static void interpolate(float* dst, const float* src0, const float* src1, float frac, float gain) { +static void interpolate_SSE(const float* src0, const float* src1, float* dst, float frac, float gain) { __m128 f0 = _mm_set1_ps(gain * (1.0f - frac)); __m128 f1 = _mm_set1_ps(gain * frac); - assert(HRTF_TAPS % 4 == 0); + static_assert(HRTF_TAPS % 4 == 0, "HRTF_TAPS must be a multiple of 4"); for (int k = 0; k < HRTF_TAPS; k += 4) { @@ -453,6 +438,44 @@ static void interpolate(float* dst, const float* src0, const float* src1, float } } +// +// Runtime CPU dispatch +// + +#include "CPUDetect.h" + +void FIR_1x4_AVX2(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); +void FIR_1x4_AVX512(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); +void interleave_4x4_AVX2(float* src0, float* src1, float* src2, float* src3, float* dst, int numFrames); +void biquad2_4x4_AVX2(float* src, float* dst, float coef[5][8], float state[3][8], int numFrames); +void crossfade_4x2_AVX2(float* src, float* dst, const float* win, int numFrames); +void interpolate_AVX2(const float* src0, const float* src1, float* dst, float frac, float gain); + +static void FIR_1x4(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) { + static auto f = cpuSupportsAVX512() ? FIR_1x4_AVX512 : (cpuSupportsAVX2() ? FIR_1x4_AVX2 : FIR_1x4_SSE); + (*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch +} + +static void interleave_4x4(float* src0, float* src1, float* src2, float* src3, float* dst, int numFrames) { + static auto f = cpuSupportsAVX2() ? interleave_4x4_AVX2 : interleave_4x4_SSE; + (*f)(src0, src1, src2, src3, dst, numFrames); // dispatch +} + +static void biquad2_4x4(float* src, float* dst, float coef[5][8], float state[3][8], int numFrames) { + static auto f = cpuSupportsAVX2() ? biquad2_4x4_AVX2 : biquad2_4x4_SSE; + (*f)(src, dst, coef, state, numFrames); // dispatch +} + +static void crossfade_4x2(float* src, float* dst, const float* win, int numFrames) { + static auto f = cpuSupportsAVX2() ? crossfade_4x2_AVX2 : crossfade_4x2_SSE; + (*f)(src, dst, win, numFrames); // dispatch +} + +static void interpolate(const float* src0, const float* src1, float* dst, float frac, float gain) { + static auto f = cpuSupportsAVX2() ? interpolate_AVX2 : interpolate_SSE; + (*f)(src0, src1, dst, frac, gain); // dispatch +} + #else // portable reference code // 1 channel input, 4 channel output @@ -489,7 +512,7 @@ static void FIR_1x4(float* src, float* dst0, float* dst1, float* dst2, float* ds float* ps = &src[i - HRTF_TAPS + 1]; // process forwards - assert(HRTF_TAPS % 4 == 0); + static_assert(HRTF_TAPS % 4 == 0, "HRTF_TAPS must be a multiple of 4"); for (int k = 0; k < HRTF_TAPS; k += 4) { @@ -715,7 +738,7 @@ static void crossfade_4x2(float* src, float* dst, const float* win, int numFrame } // linear interpolation with gain -static void interpolate(float* dst, const float* src0, const float* src1, float frac, float gain) { +static void interpolate(const float* src0, const float* src1, float* dst, float frac, float gain) { float f0 = gain * (1.0f - frac); float f1 = gain * frac; @@ -967,8 +990,8 @@ static void setFilters(float firCoef[4][HRTF_TAPS], float bqCoef[5][8], int dela azimuthToIndex(azimuth, az0, az1, frac); // interpolate FIR - interpolate(firCoef[channel+0], ir_table_table[index][azL0][0], ir_table_table[index][azL1][0], fracL, gain * gainL); - interpolate(firCoef[channel+1], ir_table_table[index][azR0][1], ir_table_table[index][azR1][1], fracR, gain * gainR); + interpolate(ir_table_table[index][azL0][0], ir_table_table[index][azL1][0], firCoef[channel+0], fracL, gain * gainL); + interpolate(ir_table_table[index][azR0][1], ir_table_table[index][azR1][1], firCoef[channel+1], fracR, gain * gainR); // interpolate ITD float itd = (1.0f - frac) * itd_table_table[index][az0] + frac * itd_table_table[index][az1]; diff --git a/libraries/audio/src/avx2/AudioHRTF_avx2.cpp b/libraries/audio/src/avx2/AudioHRTF_avx2.cpp index e89128b173..aadbb2d0cd 100644 --- a/libraries/audio/src/avx2/AudioHRTF_avx2.cpp +++ b/libraries/audio/src/avx2/AudioHRTF_avx2.cpp @@ -44,7 +44,7 @@ void FIR_1x4_AVX2(float* src, float* dst0, float* dst1, float* dst2, float* dst3 float* ps = &src[i - HRTF_TAPS + 1]; // process forwards - assert(HRTF_TAPS % 4 == 0); + static_assert(HRTF_TAPS % 4 == 0, "HRTF_TAPS must be a multiple of 4"); for (int k = 0; k < HRTF_TAPS; k += 4) { @@ -87,4 +87,165 @@ void FIR_1x4_AVX2(float* src, float* dst0, float* dst1, float* dst2, float* dst3 _mm256_zeroupper(); } +// 4 channel planar to interleaved +void interleave_4x4_AVX2(float* src0, float* src1, float* src2, float* src3, float* dst, int numFrames) { + + assert(numFrames % 8 == 0); + + for (int i = 0; i < numFrames; i += 8) { + + __m256 x0 = _mm256_loadu_ps(&src0[i]); + __m256 x1 = _mm256_loadu_ps(&src1[i]); + __m256 x2 = _mm256_loadu_ps(&src2[i]); + __m256 x3 = _mm256_loadu_ps(&src3[i]); + + // interleave (4x4 matrix transpose) + __m256 t0 = _mm256_unpacklo_ps(x0, x1); + __m256 t1 = _mm256_unpackhi_ps(x0, x1); + __m256 t2 = _mm256_unpacklo_ps(x2, x3); + __m256 t3 = _mm256_unpackhi_ps(x2, x3); + + x0 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0)); + x1 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2)); + x2 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0)); + x3 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2)); + + t0 = _mm256_permute2f128_ps(x0, x1, 0x20); + t1 = _mm256_permute2f128_ps(x2, x3, 0x20); + t2 = _mm256_permute2f128_ps(x0, x1, 0x31); + t3 = _mm256_permute2f128_ps(x2, x3, 0x31); + + _mm256_storeu_ps(&dst[4*i+0], t0); + _mm256_storeu_ps(&dst[4*i+8], t1); + _mm256_storeu_ps(&dst[4*i+16], t2); + _mm256_storeu_ps(&dst[4*i+24], t3); + } + + _mm256_zeroupper(); +} + +// process 2 cascaded biquads on 4 channels (interleaved) +// biquads are computed in parallel, by adding one sample of delay +void biquad2_4x4_AVX2(float* src, float* dst, float coef[5][8], float state[3][8], int numFrames) { + + // enable flush-to-zero mode to prevent denormals + unsigned int ftz = _MM_GET_FLUSH_ZERO_MODE(); + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + + // restore state + __m256 x0 = _mm256_setzero_ps(); + __m256 y0 = _mm256_loadu_ps(state[0]); + __m256 w1 = _mm256_loadu_ps(state[1]); + __m256 w2 = _mm256_loadu_ps(state[2]); + + // biquad coefs + __m256 b0 = _mm256_loadu_ps(coef[0]); + __m256 b1 = _mm256_loadu_ps(coef[1]); + __m256 b2 = _mm256_loadu_ps(coef[2]); + __m256 a1 = _mm256_loadu_ps(coef[3]); + __m256 a2 = _mm256_loadu_ps(coef[4]); + + for (int i = 0; i < numFrames; i++) { + + // x0 = (first biquad output << 128) | input + x0 = _mm256_insertf128_ps(_mm256_permute2f128_ps(y0, y0, 0x01), _mm_loadu_ps(&src[4*i]), 0); + + // transposed Direct Form II + y0 = _mm256_fmadd_ps(x0, b0, w1); + w1 = _mm256_fmadd_ps(x0, b1, w2); + w2 = _mm256_mul_ps(x0, b2); + w1 = _mm256_fnmadd_ps(y0, a1, w1); + w2 = _mm256_fnmadd_ps(y0, a2, w2); + + _mm_storeu_ps(&dst[4*i], _mm256_extractf128_ps(y0, 1)); // second biquad output + } + + // save state + _mm256_storeu_ps(state[0], y0); + _mm256_storeu_ps(state[1], w1); + _mm256_storeu_ps(state[2], w2); + + _MM_SET_FLUSH_ZERO_MODE(ftz); + _mm256_zeroupper(); +} + +// crossfade 4 inputs into 2 outputs with accumulation (interleaved) +void crossfade_4x2_AVX2(float* src, float* dst, const float* win, int numFrames) { + + assert(numFrames % 8 == 0); + + for (int i = 0; i < numFrames; i += 8) { + + __m256 f0 = _mm256_loadu_ps(&win[i]); + + __m256 x0 = _mm256_castps128_ps256(_mm_loadu_ps(&src[4*i+0])); + __m256 x1 = _mm256_castps128_ps256(_mm_loadu_ps(&src[4*i+4])); + __m256 x2 = _mm256_castps128_ps256(_mm_loadu_ps(&src[4*i+8])); + __m256 x3 = _mm256_castps128_ps256(_mm_loadu_ps(&src[4*i+12])); + + x0 = _mm256_insertf128_ps(x0, _mm_loadu_ps(&src[4*i+16]), 1); + x1 = _mm256_insertf128_ps(x1, _mm_loadu_ps(&src[4*i+20]), 1); + x2 = _mm256_insertf128_ps(x2, _mm_loadu_ps(&src[4*i+24]), 1); + x3 = _mm256_insertf128_ps(x3, _mm_loadu_ps(&src[4*i+28]), 1); + + __m256 y0 = _mm256_loadu_ps(&dst[2*i+0]); + __m256 y1 = _mm256_loadu_ps(&dst[2*i+8]); + + // deinterleave (4x4 matrix transpose) + __m256 t0 = _mm256_unpacklo_ps(x0, x1); + __m256 t1 = _mm256_unpackhi_ps(x0, x1); + __m256 t2 = _mm256_unpacklo_ps(x2, x3); + __m256 t3 = _mm256_unpackhi_ps(x2, x3); + + x0 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(1,0,1,0)); + x1 = _mm256_shuffle_ps(t0, t2, _MM_SHUFFLE(3,2,3,2)); + x2 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(1,0,1,0)); + x3 = _mm256_shuffle_ps(t1, t3, _MM_SHUFFLE(3,2,3,2)); + + // crossfade + x0 = _mm256_sub_ps(x0, x2); + x1 = _mm256_sub_ps(x1, x3); + x2 = _mm256_fmadd_ps(f0, x0, x2); + x3 = _mm256_fmadd_ps(f0, x1, x3); + + // interleave + t0 = _mm256_unpacklo_ps(x2, x3); + t1 = _mm256_unpackhi_ps(x2, x3); + + x0 = _mm256_permute2f128_ps(t0, t1, 0x20); + x1 = _mm256_permute2f128_ps(t0, t1, 0x31); + + // accumulate + y0 = _mm256_add_ps(y0, x0); + y1 = _mm256_add_ps(y1, x1); + + _mm256_storeu_ps(&dst[2*i+0], y0); + _mm256_storeu_ps(&dst[2*i+8], y1); + } + + _mm256_zeroupper(); +} + +// linear interpolation with gain +void interpolate_AVX2(const float* src0, const float* src1, float* dst, float frac, float gain) { + + __m256 f0 = _mm256_set1_ps(gain * (1.0f - frac)); + __m256 f1 = _mm256_set1_ps(gain * frac); + + static_assert(HRTF_TAPS % 8 == 0, "HRTF_TAPS must be a multiple of 8"); + + for (int k = 0; k < HRTF_TAPS; k += 8) { + + __m256 x0 = _mm256_loadu_ps(&src0[k]); + __m256 x1 = _mm256_loadu_ps(&src1[k]); + + x0 = _mm256_mul_ps(f0, x0); + x0 = _mm256_fmadd_ps(f1, x1, x0); + + _mm256_storeu_ps(&dst[k], x0); + } + + _mm256_zeroupper(); +} + #endif diff --git a/libraries/audio/src/avx512/AudioHRTF_avx512.cpp b/libraries/audio/src/avx512/AudioHRTF_avx512.cpp index a8bb62be35..fcec81fa4c 100644 --- a/libraries/audio/src/avx512/AudioHRTF_avx512.cpp +++ b/libraries/audio/src/avx512/AudioHRTF_avx512.cpp @@ -44,7 +44,7 @@ void FIR_1x4_AVX512(float* src, float* dst0, float* dst1, float* dst2, float* ds float* ps = &src[i - HRTF_TAPS + 1]; // process forwards - assert(HRTF_TAPS % 4 == 0); + static_assert(HRTF_TAPS % 4 == 0, "HRTF_TAPS must be a multiple of 4"); for (int k = 0; k < HRTF_TAPS; k += 4) { diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index caac08f777..c46a1e234c 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -263,15 +263,19 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { default: materials[matName] = currentMaterial; #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader Last material illumination model:" << currentMaterial.illuminationModel << - " shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << - " diffuse color:" << currentMaterial.diffuseColor << " specular color:" << - currentMaterial.specularColor << " emissive color:" << currentMaterial.emissiveColor << - " diffuse texture:" << currentMaterial.diffuseTextureFilename << " specular texture:" << - currentMaterial.specularTextureFilename << " emissive texture:" << - currentMaterial.emissiveTextureFilename << " bump texture:" << - currentMaterial.bumpTextureFilename; - #endif + qCDebug(modelformat) << + "OBJ Reader Last material illumination model:" << currentMaterial.illuminationModel << + " shininess:" << currentMaterial.shininess << + " opacity:" << currentMaterial.opacity << + " diffuse color:" << currentMaterial.diffuseColor << + " specular color:" << currentMaterial.specularColor << + " emissive color:" << currentMaterial.emissiveColor << + " diffuse texture:" << currentMaterial.diffuseTextureFilename << + " specular texture:" << currentMaterial.specularTextureFilename << + " emissive texture:" << currentMaterial.emissiveTextureFilename << + " bump texture:" << currentMaterial.bumpTextureFilename << + " opacity texture:" << currentMaterial.opacityTextureFilename; +#endif return; } QByteArray token = tokenizer.getDatum(); @@ -289,6 +293,8 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.emissiveTextureFilename = ""; currentMaterial.specularTextureFilename = ""; currentMaterial.bumpTextureFilename = ""; + currentMaterial.opacityTextureFilename = ""; + } else if (token == "Ns") { currentMaterial.shininess = tokenizer.getFloat(); } else if (token == "Ni") { @@ -321,7 +327,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.emissiveColor = tokenizer.getVec3(); } else if (token == "Ks") { currentMaterial.specularColor = tokenizer.getVec3(); - } else if ((token == "map_Kd") || (token == "map_Ke") || (token == "map_Ks") || (token == "map_bump") || (token == "bump")) { + } else if ((token == "map_Kd") || (token == "map_Ke") || (token == "map_Ks") || (token == "map_bump") || (token == "bump") || (token == "map_d")) { const QByteArray textureLine = tokenizer.getLineAsDatum(); QByteArray filename; OBJMaterialTextureOptions textureOptions; @@ -341,6 +347,8 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } else if ((token == "map_bump") || (token == "bump")) { currentMaterial.bumpTextureFilename = filename; currentMaterial.bumpTextureOptions = textureOptions; + } else if (token == "map_d") { + currentMaterial.opacityTextureFilename = filename; } } } @@ -900,6 +908,9 @@ FBXGeometry::Pointer OBJReader::readOBJ(QByteArray& model, const QVariantHash& m fbxMaterial.normalTexture.isBumpmap = true; fbxMaterial.bumpMultiplier = objMaterial.bumpTextureOptions.bumpMultiplier; } + if (!objMaterial.opacityTextureFilename.isEmpty()) { + fbxMaterial.opacityTexture.filename = objMaterial.opacityTextureFilename; + } modelMaterial->setEmissive(fbxMaterial.emissiveColor); modelMaterial->setAlbedo(fbxMaterial.diffuseColor); diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJReader.h index 13ddc6e21c..e432a3ea51 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJReader.h @@ -66,6 +66,8 @@ public: QByteArray specularTextureFilename; QByteArray emissiveTextureFilename; QByteArray bumpTextureFilename; + QByteArray opacityTextureFilename; + OBJMaterialTextureOptions bumpTextureOptions; int illuminationModel; bool used { false }; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 925cfee740..2c130274bc 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -778,8 +778,10 @@ void EntityMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& ma bool EntityMotionState::shouldSendBid() const { // NOTE: this method is only ever called when the entity's simulation is NOT locally owned - return _body->isActive() && (_region == workload::Region::R1) && - glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) >= _entity->getSimulationPriority(); + return _body->isActive() + && (_region == workload::Region::R1) + && glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) >= _entity->getSimulationPriority() + && !_entity->getLocked(); } uint8_t EntityMotionState::computeFinalBidPriority() const { diff --git a/libraries/shared/src/shared/FileUtils.cpp b/libraries/shared/src/shared/FileUtils.cpp index 9bdd65bf11..0709a53602 100644 --- a/libraries/shared/src/shared/FileUtils.cpp +++ b/libraries/shared/src/shared/FileUtils.cpp @@ -156,10 +156,12 @@ bool FileUtils::canCreateFile(const QString& fullPath) { qDebug(shared) << "unable to overwrite file '" << fullPath << "'"; return false; } - QDir dir(fileInfo.absolutePath()); + + QString absolutePath = fileInfo.absolutePath(); + QDir dir(absolutePath); if (!dir.exists()) { - if (!dir.mkpath(fullPath)) { - qDebug(shared) << "unable to create dir '" << dir.absolutePath() << "'"; + if (!dir.mkpath(absolutePath)) { + qDebug(shared) << "unable to create dir '" << absolutePath << "'"; return false; } }