mirror of
https://github.com/overte-org/overte.git
synced 2025-04-11 13:42:38 +02:00
Merge branch 'master' into tablet-ui
This commit is contained in:
commit
00980366d6
173 changed files with 5930 additions and 1768 deletions
|
@ -499,7 +499,8 @@ void Agent::processAgentAvatar() {
|
|||
if (!_scriptEngine->isFinished() && _isAvatar) {
|
||||
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
|
||||
|
||||
QByteArray avatarByteArray = scriptedAvatar->toByteArray(true, randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO);
|
||||
QByteArray avatarByteArray = scriptedAvatar->toByteArray((randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO)
|
||||
? AvatarData::SendAllData : AvatarData::CullSmallData);
|
||||
scriptedAvatar->doneEncoding(true);
|
||||
|
||||
static AvatarDataSequenceNumber sequenceNumber = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
|
@ -27,7 +28,6 @@
|
|||
#include <UUID.h>
|
||||
#include <TryLocker.h>
|
||||
|
||||
#include "AvatarMixerClientData.h"
|
||||
#include "AvatarMixer.h"
|
||||
|
||||
const QString AVATAR_MIXER_LOGGING_NAME = "avatar-mixer";
|
||||
|
@ -44,6 +44,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
|||
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled);
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
|
||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||
|
@ -67,10 +68,26 @@ AvatarMixer::~AvatarMixer() {
|
|||
// assuming 60 htz update rate.
|
||||
const float IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f;
|
||||
|
||||
void AvatarMixer::sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
|
||||
QByteArray individualData = nodeData->getAvatar().identityByteArray();
|
||||
|
||||
auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size());
|
||||
|
||||
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122());
|
||||
|
||||
identityPacket->write(individualData);
|
||||
|
||||
DependencyManager::get<NodeList>()->sendPacket(std::move(identityPacket), *destinationNode);
|
||||
|
||||
++_sumIdentityPackets;
|
||||
}
|
||||
|
||||
// NOTE: some additional optimizations to consider.
|
||||
// 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present
|
||||
// if the avatar is not in view or in the keyhole.
|
||||
void AvatarMixer::broadcastAvatarData() {
|
||||
_broadcastRate.increment();
|
||||
|
||||
int idleTime = AVATAR_DATA_SEND_INTERVAL_MSECS;
|
||||
|
||||
if (_lastFrameTimestamp.time_since_epoch().count() > 0) {
|
||||
|
@ -159,6 +176,7 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
return;
|
||||
}
|
||||
++_sumListeners;
|
||||
nodeData->resetInViewStats();
|
||||
|
||||
AvatarData& avatar = nodeData->getAvatar();
|
||||
glm::vec3 myPosition = avatar.getClientGlobalPosition();
|
||||
|
@ -227,6 +245,27 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
// setup a PacketList for the avatarPackets
|
||||
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
||||
|
||||
if (avatar.getSessionDisplayName().isEmpty() && // We haven't set it yet...
|
||||
nodeData->getReceivedIdentity()) { // ... but we have processed identity (with possible displayName).
|
||||
QString baseName = avatar.getDisplayName().trimmed();
|
||||
const QRegularExpression curses{ "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
||||
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
|
||||
const QRegularExpression trailingDigits{ "\\s*_\\d+$" }; // whitespace "_123"
|
||||
baseName = baseName.remove(trailingDigits);
|
||||
if (baseName.isEmpty()) {
|
||||
baseName = "anonymous";
|
||||
}
|
||||
|
||||
QPair<int, int>& soFar = _sessionDisplayNames[baseName]; // Inserts and answers 0, 0 if not already present, which is what we want.
|
||||
int& highWater = soFar.first;
|
||||
nodeData->setBaseDisplayName(baseName);
|
||||
avatar.setSessionDisplayName((highWater > 0) ? baseName + "_" + QString::number(highWater) : baseName);
|
||||
highWater++;
|
||||
soFar.second++; // refcount
|
||||
nodeData->flagIdentityChange();
|
||||
sendIdentityPacket(nodeData, node); // Tell new node about its sessionUUID. Others will find out below.
|
||||
}
|
||||
|
||||
// this is an AGENT we have received head data from
|
||||
// send back a packet with other active node data to this node
|
||||
nodeList->eachMatchingNode(
|
||||
|
@ -295,17 +334,7 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
|| otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp
|
||||
|| distribution(generator) < IDENTITY_SEND_PROBABILITY)) {
|
||||
|
||||
QByteArray individualData = otherNodeData->getAvatar().identityByteArray();
|
||||
|
||||
auto identityPacket = NLPacket::create(PacketType::AvatarIdentity, individualData.size());
|
||||
|
||||
individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122());
|
||||
|
||||
identityPacket->write(individualData);
|
||||
|
||||
nodeList->sendPacket(std::move(identityPacket), *node);
|
||||
|
||||
++_sumIdentityPackets;
|
||||
sendIdentityPacket(otherNodeData, node);
|
||||
}
|
||||
|
||||
AvatarData& otherAvatar = otherNodeData->getAvatar();
|
||||
|
@ -354,9 +383,22 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
// start a new segment in the PacketList for this avatar
|
||||
avatarPacketList->startSegment();
|
||||
|
||||
// determine if avatar is in view, to determine how much data to include...
|
||||
glm::vec3 otherNodeBoxScale = (otherNodeData->getPosition() - otherNodeData->getGlobalBoundingBoxCorner()) * 2.0f;
|
||||
AABox otherNodeBox(otherNodeData->getGlobalBoundingBoxCorner(), otherNodeBoxScale);
|
||||
|
||||
AvatarData::AvatarDataDetail detail;
|
||||
if (!nodeData->otherAvatarInView(otherNodeBox)) {
|
||||
detail = AvatarData::MinimumData;
|
||||
nodeData->incrementAvatarOutOfView();
|
||||
} else {
|
||||
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO
|
||||
? AvatarData::SendAllData : AvatarData::IncludeSmallData;
|
||||
nodeData->incrementAvatarInView();
|
||||
}
|
||||
|
||||
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
|
||||
numAvatarDataBytes +=
|
||||
avatarPacketList->write(otherAvatar.toByteArray(false, distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO));
|
||||
numAvatarDataBytes += avatarPacketList->write(otherAvatar.toByteArray(detail));
|
||||
|
||||
avatarPacketList->endSegment();
|
||||
});
|
||||
|
@ -385,6 +427,9 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
|
||||
// We're done encoding this version of the otherAvatars. Update their "lastSent" joint-states so
|
||||
// that we can notice differences, next time around.
|
||||
//
|
||||
// FIXME - this seems suspicious, the code seems to consider all avatars, but not all avatars will
|
||||
// have had their joints sent, so actually we should consider the time since they actually were sent????
|
||||
nodeList->eachMatchingNode(
|
||||
[&](const SharedNodePointer& otherNode)->bool {
|
||||
if (!otherNode->getLinkedData()) {
|
||||
|
@ -409,6 +454,18 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
});
|
||||
|
||||
_lastFrameTimestamp = p_high_resolution_clock::now();
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
auto sinceLastDebug = p_high_resolution_clock::now() - _lastDebugMessage;
|
||||
auto sinceLastDebugUsecs = std::chrono::duration_cast<std::chrono::microseconds>(sinceLastDebug).count();
|
||||
quint64 DEBUG_INTERVAL = USECS_PER_SECOND * 5;
|
||||
|
||||
if (sinceLastDebugUsecs > DEBUG_INTERVAL) {
|
||||
qDebug() << "broadcast rate:" << _broadcastRate.rate() << "hz";
|
||||
_lastDebugMessage = p_high_resolution_clock::now();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||
|
@ -416,6 +473,16 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
|||
&& killedNode->getLinkedData()) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
{ // decrement sessionDisplayNames table and possibly remove
|
||||
QMutexLocker nodeDataLocker(&killedNode->getLinkedData()->getMutex());
|
||||
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(killedNode->getLinkedData());
|
||||
const QString& baseDisplayName = nodeData->getBaseDisplayName();
|
||||
// No sense guarding against very rare case of a node with no entry, as this will work without the guard and do one less lookup in the common case.
|
||||
if (--_sessionDisplayNames[baseDisplayName].second <= 0) {
|
||||
_sessionDisplayNames.remove(baseDisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
// this was an avatar we were sending to other people
|
||||
// send a kill packet for it to our other nodes
|
||||
auto killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason));
|
||||
|
@ -448,6 +515,18 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarMixer::handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->getOrCreateLinkedData(senderNode);
|
||||
|
||||
if (senderNode->getLinkedData()) {
|
||||
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
|
||||
if (nodeData != nullptr) {
|
||||
nodeData->readViewFrustumPacket(message->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarMixer::handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->updateNodeWithDataFromPacket(message, senderNode);
|
||||
|
@ -468,6 +547,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
|||
if (avatar.processAvatarIdentity(identity)) {
|
||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||
nodeData->flagIdentityChange();
|
||||
nodeData->setReceivedIdentity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -493,6 +573,7 @@ void AvatarMixer::sendStatsPacket() {
|
|||
|
||||
statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100;
|
||||
statsObject["performance_throttling_ratio"] = _performanceThrottlingRatio;
|
||||
statsObject["broadcast_loop_rate"] = _broadcastRate.rate();
|
||||
|
||||
QJsonObject avatarsObject;
|
||||
|
||||
|
@ -545,6 +626,7 @@ void AvatarMixer::run() {
|
|||
|
||||
// setup the timer that will be fired on the broadcast thread
|
||||
_broadcastTimer = new QTimer;
|
||||
_broadcastTimer->setTimerType(Qt::PreciseTimer);
|
||||
_broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS);
|
||||
_broadcastTimer->moveToThread(&_broadcastThread);
|
||||
|
||||
|
@ -564,7 +646,7 @@ void AvatarMixer::domainSettingsRequestComplete() {
|
|||
float domainMaximumScale = _domainMaximumScale;
|
||||
|
||||
nodeList->linkedDataCreateCallback = [domainMinimumScale, domainMaximumScale] (Node* node) {
|
||||
auto clientData = std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData };
|
||||
auto clientData = std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData(node->getUUID()) };
|
||||
clientData->getAvatar().setDomainMinimumScale(domainMinimumScale);
|
||||
clientData->getAvatar().setDomainMaximumScale(domainMaximumScale);
|
||||
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
#ifndef hifi_AvatarMixer_h
|
||||
#define hifi_AvatarMixer_h
|
||||
|
||||
#include <shared/RateCounter.h>
|
||||
#include <PortableHighResolutionClock.h>
|
||||
|
||||
#include <ThreadedAssignment.h>
|
||||
#include "AvatarMixerClientData.h"
|
||||
|
||||
/// Handles assignments of type AvatarMixer - distribution of avatar data to various clients
|
||||
class AvatarMixer : public ThreadedAssignment {
|
||||
|
@ -34,6 +36,7 @@ public slots:
|
|||
void sendStatsPacket() override;
|
||||
|
||||
private slots:
|
||||
void handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
|
||||
|
@ -46,6 +49,7 @@ private slots:
|
|||
private:
|
||||
void broadcastAvatarData();
|
||||
void parseDomainServerSettings(const QJsonObject& domainSettings);
|
||||
void sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
|
||||
|
||||
QThread _broadcastThread;
|
||||
|
||||
|
@ -64,6 +68,10 @@ private:
|
|||
float _domainMaximumScale { MAX_AVATAR_SCALE };
|
||||
|
||||
QTimer* _broadcastTimer = nullptr;
|
||||
|
||||
RateCounter<> _broadcastRate;
|
||||
p_high_resolution_clock::time_point _lastDebugMessage;
|
||||
QHash<QString, QPair<int, int>> _sessionDisplayNames;
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarMixer_h
|
||||
|
|
|
@ -57,6 +57,14 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) {
|
||||
_currentViewFrustum.fromByteArray(message);
|
||||
}
|
||||
|
||||
bool AvatarMixerClientData::otherAvatarInView(const AABox& otherAvatarBox) {
|
||||
return _currentViewFrustum.boxIntersectsKeyhole(otherAvatarBox);
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
|
||||
jsonObject["display_name"] = _avatar->getDisplayName();
|
||||
jsonObject["full_rate_distance"] = _fullRateDistance;
|
||||
|
@ -70,4 +78,6 @@ void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
|
|||
jsonObject[INBOUND_AVATAR_DATA_STATS_KEY] = _avatar->getAverageBytesReceivedPerSecond() / (float) BYTES_PER_KILOBIT;
|
||||
|
||||
jsonObject["av_data_receive_rate"] = _avatar->getReceiveRate();
|
||||
jsonObject["recent_other_av_in_view"] = _recentOtherAvatarsInView;
|
||||
jsonObject["recent_other_av_out_of_view"] = _recentOtherAvatarsOutOfView;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <PortableHighResolutionClock.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
#include <UUIDHasher.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps";
|
||||
const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps";
|
||||
|
@ -34,6 +35,8 @@ const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps";
|
|||
class AvatarMixerClientData : public NodeData {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvatarMixerClientData(const QUuid& nodeID = QUuid()) : NodeData(nodeID) { _currentViewFrustum.invalidate(); }
|
||||
virtual ~AvatarMixerClientData() {}
|
||||
using HRCTime = p_high_resolution_clock::time_point;
|
||||
|
||||
int parseData(ReceivedMessage& message) override;
|
||||
|
@ -50,6 +53,8 @@ public:
|
|||
|
||||
HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
||||
void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); }
|
||||
bool getReceivedIdentity() const { return _gotIdentity; }
|
||||
void setReceivedIdentity() { _gotIdentity = true; }
|
||||
|
||||
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
||||
float getFullRateDistance() const { return _fullRateDistance; }
|
||||
|
@ -87,6 +92,16 @@ public:
|
|||
void removeFromRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.erase(other); }
|
||||
void ignoreOther(SharedNodePointer self, SharedNodePointer other);
|
||||
|
||||
void readViewFrustumPacket(const QByteArray& message);
|
||||
|
||||
bool otherAvatarInView(const AABox& otherAvatarBox);
|
||||
|
||||
void resetInViewStats() { _recentOtherAvatarsInView = _recentOtherAvatarsOutOfView = 0; }
|
||||
void incrementAvatarInView() { _recentOtherAvatarsInView++; }
|
||||
void incrementAvatarOutOfView() { _recentOtherAvatarsOutOfView++; }
|
||||
const QString& getBaseDisplayName() { return _baseDisplayName; }
|
||||
void setBaseDisplayName(const QString& baseDisplayName) { _baseDisplayName = baseDisplayName; }
|
||||
|
||||
private:
|
||||
AvatarSharedPointer _avatar { new AvatarData() };
|
||||
|
||||
|
@ -95,6 +110,7 @@ private:
|
|||
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
|
||||
|
||||
HRCTime _identityChangeTimestamp;
|
||||
bool _gotIdentity { false };
|
||||
|
||||
float _fullRateDistance = FLT_MAX;
|
||||
float _maxAvatarDistance = FLT_MAX;
|
||||
|
@ -108,6 +124,11 @@ private:
|
|||
|
||||
SimpleMovingAverage _avgOtherAvatarDataRate;
|
||||
std::unordered_set<QUuid> _radiusIgnoredOthers;
|
||||
ViewFrustum _currentViewFrustum;
|
||||
|
||||
int _recentOtherAvatarsInView { 0 };
|
||||
int _recentOtherAvatarsOutOfView { 0 };
|
||||
QString _baseDisplayName{}; // The santized key used in determinging unique sessionDisplayName, so that we can remove from dictionary.
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarMixerClientData_h
|
||||
|
|
8
cmake/externals/quazip/CMakeLists.txt
vendored
8
cmake/externals/quazip/CMakeLists.txt
vendored
|
@ -38,13 +38,13 @@ set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/lib CACHE FILEPATH "Location
|
|||
|
||||
if (APPLE)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.1.0.0.dylib CACHE FILEPATH "Location of QuaZip release library")
|
||||
elseif (WIN32)
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
|
||||
else ()
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
|
||||
endif ()
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
|
@ -52,4 +52,4 @@ select_library_configurations(${EXTERNAL_NAME_UPPER})
|
|||
|
||||
# Force selected libraries into the cache
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
|
|
|
@ -800,7 +800,12 @@ void DomainServerSettingsManager::processUsernameFromIDRequestPacket(QSharedPoin
|
|||
usernameFromIDReplyPacket->write(nodeUUID.toRfc4122());
|
||||
usernameFromIDReplyPacket->writeString(verifiedUsername);
|
||||
|
||||
qDebug() << "Sending username" << verifiedUsername << "associated with node" << nodeUUID;
|
||||
// now put in the machine fingerprint
|
||||
DomainServerNodeData* nodeData = reinterpret_cast<DomainServerNodeData*>(matchingNode->getLinkedData());
|
||||
QUuid machineFingerprint = nodeData ? nodeData->getMachineFingerprint() : QUuid();
|
||||
usernameFromIDReplyPacket->write(machineFingerprint.toRfc4122());
|
||||
|
||||
qDebug() << "Sending username" << verifiedUsername << "and machine fingerprint" << machineFingerprint << "associated with node" << nodeUUID;
|
||||
|
||||
// Ship it!
|
||||
limitedNodeList->sendPacket(std::move(usernameFromIDReplyPacket), *sendingNode);
|
||||
|
|
BIN
interface/resources/icons/defaultNameCardUser.png
Normal file
BIN
interface/resources/icons/defaultNameCardUser.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
|
@ -21,9 +21,9 @@ Original.CheckBox {
|
|||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
|
||||
readonly property int boxSize: 14
|
||||
property int boxSize: 14
|
||||
readonly property int boxRadius: 3
|
||||
readonly property int checkSize: 10
|
||||
readonly property int checkSize: Math.max(boxSize - 8, 10)
|
||||
readonly property int checkRadius: 2
|
||||
|
||||
style: CheckBoxStyle {
|
||||
|
@ -32,21 +32,35 @@ Original.CheckBox {
|
|||
width: boxSize
|
||||
height: boxSize
|
||||
radius: boxRadius
|
||||
border.width: 1
|
||||
border.color: pressed || hovered
|
||||
? hifi.colors.checkboxCheckedBorder
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: pressed || hovered
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
|
||||
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
|
||||
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: pressed || hovered
|
||||
anchors.centerIn: parent
|
||||
id: innerBox
|
||||
width: checkSize - 4
|
||||
height: width
|
||||
radius: checkRadius
|
||||
color: hifi.colors.checkboxCheckedBorder
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: check
|
||||
width: checkSize
|
||||
|
@ -54,7 +68,7 @@ Original.CheckBox {
|
|||
radius: checkRadius
|
||||
anchors.centerIn: parent
|
||||
color: hifi.colors.checkboxChecked
|
||||
border.width: 1
|
||||
border.width: 2
|
||||
border.color: hifi.colors.checkboxCheckedBorder
|
||||
visible: checked && !pressed || !checked && pressed
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ TableView {
|
|||
property int colorScheme: hifi.colorSchemes.light
|
||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||
property bool expandSelectedRow: false
|
||||
property bool centerHeaderText: false
|
||||
|
||||
model: ListModel { }
|
||||
|
||||
|
@ -34,9 +35,12 @@ TableView {
|
|||
size: hifi.fontSizes.tableHeading
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: hifi.dimensions.tablePadding
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.tablePadding
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +52,7 @@ TableView {
|
|||
size: hifi.fontSizes.tableHeadingIcon
|
||||
anchors {
|
||||
left: titleText.right
|
||||
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3
|
||||
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3 - (centerHeaderText ? 3 : 0)
|
||||
right: parent.right
|
||||
rightMargin: hifi.dimensions.tablePadding
|
||||
verticalCenter: titleText.verticalCenter
|
||||
|
|
|
@ -9,28 +9,128 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import Hifi 1.0 as Hifi
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../styles-uit"
|
||||
|
||||
|
||||
Column {
|
||||
property string displayName: "";
|
||||
property string userName: "";
|
||||
property int displayTextHeight: 18;
|
||||
property int usernameTextHeight: 12;
|
||||
|
||||
RalewaySemiBold {
|
||||
text: parent.displayName;
|
||||
size: parent.displayTextHeight;
|
||||
elide: Text.ElideRight;
|
||||
width: parent.width;
|
||||
Row {
|
||||
id: thisNameCard
|
||||
// Spacing
|
||||
spacing: 10
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors {
|
||||
topMargin: (parent.height - contentHeight)/2
|
||||
bottomMargin: (parent.height - contentHeight)/2
|
||||
leftMargin: 10
|
||||
rightMargin: 10
|
||||
}
|
||||
RalewayLight {
|
||||
visible: parent.displayName;
|
||||
text: parent.userName;
|
||||
size: parent.usernameTextHeight;
|
||||
elide: Text.ElideRight;
|
||||
width: parent.width;
|
||||
|
||||
// Properties
|
||||
property int contentHeight: 50
|
||||
property string displayName: ""
|
||||
property string userName: ""
|
||||
property int displayTextHeight: 18
|
||||
property int usernameTextHeight: 12
|
||||
property real audioLevel: 0.0
|
||||
|
||||
Column {
|
||||
id: avatarImage
|
||||
// Size
|
||||
height: contentHeight
|
||||
width: height
|
||||
Image {
|
||||
id: userImage
|
||||
source: "../../icons/defaultNameCardUser.png"
|
||||
// Anchors
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
}
|
||||
}
|
||||
Column {
|
||||
id: textContainer
|
||||
// Size
|
||||
width: parent.width - avatarImage.width - parent.anchors.leftMargin - parent.anchors.rightMargin - parent.spacing
|
||||
height: contentHeight
|
||||
|
||||
// DisplayName Text
|
||||
FiraSansSemiBold {
|
||||
id: displayNameText
|
||||
// Properties
|
||||
text: thisNameCard.displayName
|
||||
elide: Text.ElideRight
|
||||
// Size
|
||||
width: parent.width
|
||||
// Text Size
|
||||
size: thisNameCard.displayTextHeight
|
||||
// Text Positioning
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// UserName Text
|
||||
FiraSansRegular {
|
||||
id: userNameText
|
||||
// Properties
|
||||
text: thisNameCard.userName
|
||||
elide: Text.ElideRight
|
||||
visible: thisNameCard.displayName
|
||||
// Size
|
||||
width: parent.width
|
||||
// Text Size
|
||||
size: thisNameCard.usernameTextHeight
|
||||
// Text Positioning
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
height: 4
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
// VU Meter
|
||||
Rectangle { // CHANGEME to the appropriate type!
|
||||
id: nameCardVUMeter
|
||||
// Size
|
||||
width: parent.width
|
||||
height: 8
|
||||
// Style
|
||||
radius: 4
|
||||
// Rectangle for the VU meter base
|
||||
Rectangle {
|
||||
id: vuMeterBase
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
// Style
|
||||
color: "#dbdbdb" // Very appropriate hex value here
|
||||
radius: parent.radius
|
||||
}
|
||||
// Rectangle for the VU meter audio level
|
||||
Rectangle {
|
||||
id: vuMeterLevel
|
||||
// Size
|
||||
width: (thisNameCard.audioLevel) * parent.width
|
||||
// Style
|
||||
color: "#dbdbdb" // Very appropriate hex value here
|
||||
radius: parent.radius
|
||||
// Anchors
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
}
|
||||
// Gradient for the VU meter audio level
|
||||
LinearGradient {
|
||||
anchors.fill: vuMeterLevel
|
||||
source: vuMeterLevel
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(parent.width, 0)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.05; color: "#00CFEF" }
|
||||
GradientStop { position: 0.5; color: "#9450A5" }
|
||||
GradientStop { position: 0.95; color: "#EA4C5F" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,19 +28,314 @@
|
|||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
|
||||
Rectangle {
|
||||
id: pal;
|
||||
property int keepFromHorizontalScroll: 1;
|
||||
width: parent.width - keepFromHorizontalScroll;
|
||||
height: parent.height;
|
||||
Item {
|
||||
id: pal
|
||||
// Size
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
// Properties
|
||||
property int myCardHeight: 70
|
||||
property int rowHeight: 70
|
||||
property int actionButtonWidth: 75
|
||||
property int nameCardWidth: width - actionButtonWidth*(iAmAdmin ? 4 : 2)
|
||||
|
||||
property int nameWidth: width/2;
|
||||
property int actionWidth: nameWidth / (table.columnCount - 1);
|
||||
property int rowHeight: 50;
|
||||
property var userData: [];
|
||||
property var myData: ({displayName: "", userName: ""}); // valid dummy until set
|
||||
property bool iAmAdmin: false;
|
||||
// This contains the current user's NameCard and will contain other information in the future
|
||||
Rectangle {
|
||||
id: myInfo
|
||||
// Size
|
||||
width: pal.width
|
||||
height: myCardHeight + 20
|
||||
// Anchors
|
||||
anchors.top: pal.top
|
||||
// Properties
|
||||
radius: hifi.dimensions.borderRadius
|
||||
// This NameCard refers to the current user's NameCard (the one above the table)
|
||||
NameCard {
|
||||
id: myCard
|
||||
// Properties
|
||||
displayName: myData.displayName
|
||||
userName: myData.userName
|
||||
audioLevel: myData.audioLevel
|
||||
// Size
|
||||
width: nameCardWidth
|
||||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
}
|
||||
}
|
||||
// Rectangles used to cover up rounded edges on bottom of MyInfo Rectangle
|
||||
Rectangle {
|
||||
color: "#FFFFFF"
|
||||
width: pal.width
|
||||
height: 10
|
||||
anchors.top: myInfo.bottom
|
||||
anchors.left: parent.left
|
||||
}
|
||||
Rectangle {
|
||||
color: "#FFFFFF"
|
||||
width: pal.width
|
||||
height: 10
|
||||
anchors.bottom: table.top
|
||||
anchors.left: parent.left
|
||||
}
|
||||
// Rectangle that houses "ADMIN" string
|
||||
Rectangle {
|
||||
id: adminTab
|
||||
// Size
|
||||
width: actionButtonWidth * 2 - 2
|
||||
height: 40
|
||||
// Anchors
|
||||
anchors.bottom: myInfo.bottom
|
||||
anchors.bottomMargin: -10
|
||||
anchors.right: myInfo.right
|
||||
// Properties
|
||||
visible: iAmAdmin
|
||||
// Style
|
||||
color: hifi.colors.tableRowLightEven
|
||||
radius: hifi.dimensions.borderRadius
|
||||
border.color: hifi.colors.lightGrayText
|
||||
border.width: 2
|
||||
// "ADMIN" text
|
||||
RalewaySemiBold {
|
||||
text: "ADMIN"
|
||||
// Text size
|
||||
size: hifi.fontSizes.tableHeading + 2
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
// Style
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: hifi.colors.redHighlight
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
}
|
||||
}
|
||||
// This TableView refers to the table (below the current user's NameCard)
|
||||
HifiControls.Table {
|
||||
id: table
|
||||
// Size
|
||||
height: pal.height - myInfo.height - 4
|
||||
width: pal.width - 4
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
anchors.top: myInfo.bottom
|
||||
// Properties
|
||||
centerHeaderText: true
|
||||
sortIndicatorVisible: true
|
||||
headerVisible: true
|
||||
onSortIndicatorColumnChanged: sortModel()
|
||||
onSortIndicatorOrderChanged: sortModel()
|
||||
|
||||
TableViewColumn {
|
||||
role: "displayName"
|
||||
title: "NAMES"
|
||||
width: nameCardWidth
|
||||
movable: false
|
||||
resizable: false
|
||||
}
|
||||
TableViewColumn {
|
||||
role: "personalMute"
|
||||
title: "MUTE"
|
||||
width: actionButtonWidth
|
||||
movable: false
|
||||
resizable: false
|
||||
}
|
||||
TableViewColumn {
|
||||
role: "ignore"
|
||||
title: "IGNORE"
|
||||
width: actionButtonWidth
|
||||
movable: false
|
||||
resizable: false
|
||||
}
|
||||
TableViewColumn {
|
||||
visible: iAmAdmin
|
||||
role: "mute"
|
||||
title: "SILENCE"
|
||||
width: actionButtonWidth
|
||||
movable: false
|
||||
resizable: false
|
||||
}
|
||||
TableViewColumn {
|
||||
visible: iAmAdmin
|
||||
role: "kick"
|
||||
title: "BAN"
|
||||
width: actionButtonWidth
|
||||
movable: false
|
||||
resizable: false
|
||||
}
|
||||
model: userModel
|
||||
|
||||
// This Rectangle refers to each Row in the table.
|
||||
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
||||
// Size
|
||||
height: rowHeight
|
||||
color: styleData.selected
|
||||
? "#afafaf"
|
||||
: styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd
|
||||
}
|
||||
|
||||
// This Item refers to the contents of each Cell
|
||||
itemDelegate: Item {
|
||||
id: itemCell
|
||||
property bool isCheckBox: typeof(styleData.value) === 'boolean'
|
||||
// This NameCard refers to the cell that contains an avatar's
|
||||
// DisplayName and UserName
|
||||
NameCard {
|
||||
id: nameCard
|
||||
// Properties
|
||||
displayName: styleData.value
|
||||
userName: model.userName
|
||||
audioLevel: model.audioLevel
|
||||
visible: !isCheckBox
|
||||
// Size
|
||||
width: nameCardWidth
|
||||
height: parent.height
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
}
|
||||
|
||||
// This CheckBox belongs in the columns that contain the action buttons ("Mute", "Ban", etc)
|
||||
HifiControls.CheckBox {
|
||||
visible: isCheckBox
|
||||
anchors.centerIn: parent
|
||||
boxSize: 24
|
||||
onClicked: {
|
||||
var newValue = !model[styleData.role]
|
||||
var datum = userData[model.userIndex]
|
||||
datum[styleData.role] = model[styleData.role] = newValue
|
||||
Users[styleData.role](model.sessionId)
|
||||
// Just for now, while we cannot undo things:
|
||||
userData.splice(model.userIndex, 1)
|
||||
sortModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Refresh button
|
||||
Rectangle {
|
||||
// Size
|
||||
width: hifi.dimensions.tableHeaderHeight-1
|
||||
height: hifi.dimensions.tableHeaderHeight-1
|
||||
// Anchors
|
||||
anchors.left: table.left
|
||||
anchors.leftMargin: 4
|
||||
anchors.top: table.top
|
||||
// Style
|
||||
color: hifi.colors.tableBackgroundLight
|
||||
// Actual refresh icon
|
||||
HiFiGlyphs {
|
||||
id: reloadButton
|
||||
text: hifi.glyphs.reloadSmall
|
||||
// Size
|
||||
size: parent.width*1.5
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
// Style
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: hifi.colors.darkGray
|
||||
}
|
||||
MouseArea {
|
||||
id: reloadButtonArea
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
// Everyone likes a responsive refresh button!
|
||||
// So use onPressed instead of onClicked
|
||||
onPressed: {
|
||||
reloadButton.color = hifi.colors.lightGrayText
|
||||
pal.sendToScript({method: 'refresh'})
|
||||
}
|
||||
onReleased: reloadButton.color = (containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.darkGray)
|
||||
onEntered: reloadButton.color = hifi.colors.baseGrayHighlight
|
||||
onExited: reloadButton.color = (pressed ? hifi.colors.lightGrayText: hifi.colors.darkGray)
|
||||
}
|
||||
}
|
||||
|
||||
// Separator between user and admin functions
|
||||
Rectangle {
|
||||
// Size
|
||||
width: 2
|
||||
height: table.height
|
||||
// Anchors
|
||||
anchors.left: adminTab.left
|
||||
anchors.top: table.top
|
||||
// Properties
|
||||
visible: iAmAdmin
|
||||
color: hifi.colors.lightGrayText
|
||||
}
|
||||
// This Rectangle refers to the [?] popup button
|
||||
Rectangle {
|
||||
color: hifi.colors.tableBackgroundLight
|
||||
width: 20
|
||||
height: hifi.dimensions.tableHeaderHeight - 2
|
||||
anchors.left: table.left
|
||||
anchors.top: table.top
|
||||
anchors.topMargin: 1
|
||||
anchors.leftMargin: nameCardWidth/2 + 24
|
||||
RalewayRegular {
|
||||
id: helpText
|
||||
text: "[?]"
|
||||
size: hifi.fontSizes.tableHeading + 2
|
||||
font.capitalization: Font.AllUppercase
|
||||
color: hifi.colors.darkGray
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.fill: parent
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
onClicked: namesPopup.visible = true
|
||||
onEntered: helpText.color = hifi.colors.baseGrayHighlight
|
||||
onExited: helpText.color = hifi.colors.darkGray
|
||||
}
|
||||
}
|
||||
// Explanitory popup upon clicking "[?]"
|
||||
Item {
|
||||
visible: false
|
||||
id: namesPopup
|
||||
anchors.fill: pal
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
opacity: 0.5
|
||||
radius: hifi.dimensions.borderRadius
|
||||
}
|
||||
Rectangle {
|
||||
width: Math.min(parent.width * 0.75, 400)
|
||||
height: popupText.contentHeight*2
|
||||
anchors.centerIn: parent
|
||||
radius: hifi.dimensions.borderRadius
|
||||
color: "white"
|
||||
FiraSansSemiBold {
|
||||
id: popupText
|
||||
text: "This is temporary text. It will eventually be used to explain what 'Names' means."
|
||||
size: hifi.fontSizes.textFieldInput
|
||||
color: hifi.colors.darkGray
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.fill: parent
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
namesPopup.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property var userData: []
|
||||
property var myData: ({displayName: "", userName: "", audioLevel: 0.0}) // valid dummy until set
|
||||
property bool iAmAdmin: false
|
||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||
var i, data = optionalData || userData, length = data.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
|
@ -90,6 +385,21 @@ Rectangle {
|
|||
userData[userIndex].userName = userName; // Defensive programming
|
||||
}
|
||||
break;
|
||||
case 'updateAudioLevel':
|
||||
for (var userId in message.params) {
|
||||
var audioLevel = message.params[userId];
|
||||
// If the userId is 0, we're updating "myData".
|
||||
if (userId == 0) {
|
||||
myData.audioLevel = audioLevel;
|
||||
myCard.audioLevel = audioLevel; // Defensive programming
|
||||
} else {
|
||||
console.log("userid:" + userId);
|
||||
var userIndex = findSessionIndex(userId);
|
||||
userModel.get(userIndex).audioLevel = audioLevel;
|
||||
userData[userIndex].audioLevel = audioLevel; // Defensive programming
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message:', JSON.stringify(message));
|
||||
}
|
||||
|
@ -118,7 +428,7 @@ Rectangle {
|
|||
datum[property] = false;
|
||||
}
|
||||
}
|
||||
['ignore', 'spacer', 'mute', 'kick'].forEach(init);
|
||||
['personalMute', 'ignore', 'mute', 'kick'].forEach(init);
|
||||
datum.userIndex = userIndex++;
|
||||
userModel.append(datum);
|
||||
});
|
||||
|
@ -135,91 +445,4 @@ Rectangle {
|
|||
target: table.selection
|
||||
onSelectionChanged: pal.noticeSelection()
|
||||
}
|
||||
|
||||
Column {
|
||||
NameCard {
|
||||
id: myCard;
|
||||
width: nameWidth;
|
||||
displayName: myData.displayName;
|
||||
userName: myData.userName;
|
||||
}
|
||||
TableView {
|
||||
id: table;
|
||||
TableViewColumn {
|
||||
role: "displayName";
|
||||
title: "Name";
|
||||
width: nameWidth
|
||||
}
|
||||
TableViewColumn {
|
||||
role: "ignore";
|
||||
title: "Ignore"
|
||||
width: actionWidth
|
||||
}
|
||||
TableViewColumn {
|
||||
title: "";
|
||||
width: actionWidth
|
||||
}
|
||||
TableViewColumn {
|
||||
visible: iAmAdmin;
|
||||
role: "mute";
|
||||
title: "Mute";
|
||||
width: actionWidth
|
||||
}
|
||||
TableViewColumn {
|
||||
visible: iAmAdmin;
|
||||
role: "kick";
|
||||
title: "Ban"
|
||||
width: actionWidth
|
||||
}
|
||||
model: userModel;
|
||||
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
||||
height: rowHeight;
|
||||
// The rest of this is cargo-culted to restore the default styling
|
||||
SystemPalette {
|
||||
id: myPalette;
|
||||
colorGroup: SystemPalette.Active
|
||||
}
|
||||
color: {
|
||||
var baseColor = styleData.alternate?myPalette.alternateBase:myPalette.base
|
||||
return styleData.selected?myPalette.highlight:baseColor
|
||||
}
|
||||
}
|
||||
itemDelegate: Item {
|
||||
id: itemCell;
|
||||
property bool isCheckBox: typeof(styleData.value) === 'boolean';
|
||||
NameCard {
|
||||
id: nameCard;
|
||||
visible: !isCheckBox;
|
||||
width: nameWidth;
|
||||
displayName: styleData.value;
|
||||
userName: model.userName;
|
||||
}
|
||||
Rectangle {
|
||||
radius: itemCell.height / 4;
|
||||
visible: isCheckBox;
|
||||
color: styleData.value ? "green" : "red";
|
||||
anchors.fill: parent;
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
acceptedButtons: Qt.LeftButton;
|
||||
hoverEnabled: true;
|
||||
onClicked: {
|
||||
var newValue = !model[styleData.role];
|
||||
var datum = userData[model.userIndex];
|
||||
datum[styleData.role] = model[styleData.role] = newValue;
|
||||
Users[styleData.role](model.sessionId);
|
||||
// Just for now, while we cannot undo things:
|
||||
userData.splice(model.userIndex, 1);
|
||||
sortModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
height: pal.height - myCard.height;
|
||||
width: pal.width;
|
||||
sortIndicatorVisible: true;
|
||||
onSortIndicatorColumnChanged: sortModel();
|
||||
onSortIndicatorOrderChanged: sortModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ ScrollingWindow {
|
|||
objectName: "RunningScripts"
|
||||
title: "Running Scripts"
|
||||
resizable: true
|
||||
destroyOnHidden: true
|
||||
destroyOnHidden: false
|
||||
implicitWidth: 424
|
||||
implicitHeight: isHMD ? 695 : 728
|
||||
minSize: Qt.vector2d(424, 300)
|
||||
|
|
|
@ -89,8 +89,8 @@ Item {
|
|||
readonly property color transparent: "#00ffffff"
|
||||
|
||||
// Control specific colors
|
||||
readonly property color tableRowLightOdd: "#eaeaea" // Equivalent to white50 over #e3e3e3 background
|
||||
readonly property color tableRowLightEven: "#c6c6c6" // Equivavlent to "#1a575757" over #e3e3e3 background
|
||||
readonly property color tableRowLightOdd: "#fafafa"
|
||||
readonly property color tableRowLightEven: "#eeeeee" // Equivavlent to "#1a575757" over #e3e3e3 background
|
||||
readonly property color tableRowDarkOdd: "#2e2e2e" // Equivalent to "#80393939" over #404040 background
|
||||
readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
|
||||
readonly property color tableBackgroundLight: tableRowLightEven
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include <ErrorDialog.h>
|
||||
#include <FileScriptingInterface.h>
|
||||
#include <Finally.h>
|
||||
#include <FingerprintUtils.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
|
@ -616,9 +615,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us
|
||||
|
||||
// TODO: This is temporary, while developing
|
||||
FingerprintUtils::getMachineFingerprint();
|
||||
// End TODO
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
// Set up a watchdog thread to intentionally crash the application on deadlocks
|
||||
|
@ -1141,7 +1137,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&_settingsThread, SIGNAL(finished()), &_settingsTimer, SLOT(stop()));
|
||||
_settingsTimer.moveToThread(&_settingsThread);
|
||||
_settingsTimer.setSingleShot(false);
|
||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL);
|
||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
||||
_settingsThread.start();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
||||
|
@ -1246,7 +1242,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// Periodically send fps as a user activity event
|
||||
QTimer* sendStatsTimer = new QTimer(this);
|
||||
sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS);
|
||||
sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS); // 10s, Qt::CoarseTimer acceptable
|
||||
connect(sendStatsTimer, &QTimer::timeout, this, [this]() {
|
||||
|
||||
QJsonObject properties = {};
|
||||
|
@ -1277,6 +1273,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["sim_rate"] = getAverageSimsPerSecond();
|
||||
properties["avatar_sim_rate"] = getAvatarSimrate();
|
||||
properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection();
|
||||
properties["hardware_stats"] = displayPlugin->getHardwareStats();
|
||||
|
||||
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||
properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond();
|
||||
|
@ -1347,7 +1344,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
// Periodically check for count of nearby avatars
|
||||
static int lastCountOfNearbyAvatars = -1;
|
||||
QTimer* checkNearbyAvatarsTimer = new QTimer(this);
|
||||
checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS);
|
||||
checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); // 10 seconds, Qt::CoarseTimer ok
|
||||
connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(),
|
||||
|
@ -1505,16 +1502,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// Monitor model assets (e.g., from Clara.io) added to the world that may need resizing.
|
||||
static const int ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS = 1000;
|
||||
_addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS);
|
||||
_addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable
|
||||
connect(&_addAssetToWorldResizeTimer, &QTimer::timeout, this, &Application::addAssetToWorldCheckModelSize);
|
||||
|
||||
// Auto-update and close adding asset to world info message box.
|
||||
static const int ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS = 5000;
|
||||
_addAssetToWorldInfoTimer.setInterval(ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS);
|
||||
_addAssetToWorldInfoTimer.setInterval(ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS); // 5s, Qt::CoarseTimer acceptable
|
||||
_addAssetToWorldInfoTimer.setSingleShot(true);
|
||||
connect(&_addAssetToWorldInfoTimer, &QTimer::timeout, this, &Application::addAssetToWorldInfoTimeout);
|
||||
static const int ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS = 8000;
|
||||
_addAssetToWorldErrorTimer.setInterval(ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS);
|
||||
_addAssetToWorldErrorTimer.setInterval(ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS); // 8s, Qt::CoarseTimer acceptable
|
||||
_addAssetToWorldErrorTimer.setSingleShot(true);
|
||||
connect(&_addAssetToWorldErrorTimer, &QTimer::timeout, this, &Application::addAssetToWorldErrorTimeout);
|
||||
|
||||
|
@ -4326,7 +4323,7 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// AvatarManager update
|
||||
{
|
||||
PerformanceTimer perfTimer("AvatarManger");
|
||||
PerformanceTimer perfTimer("AvatarManager");
|
||||
_avatarSimCounter.increment();
|
||||
|
||||
{
|
||||
|
@ -4376,6 +4373,7 @@ void Application::update(float deltaTime) {
|
|||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
|
||||
}
|
||||
sendAvatarViewFrustum();
|
||||
_lastQueriedViewFrustum = _viewFrustum;
|
||||
}
|
||||
}
|
||||
|
@ -4415,6 +4413,14 @@ void Application::update(float deltaTime) {
|
|||
AnimDebugDraw::getInstance().update();
|
||||
}
|
||||
|
||||
void Application::sendAvatarViewFrustum() {
|
||||
QByteArray viewFrustumByteArray = _viewFrustum.toByteArray();
|
||||
auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
|
||||
avatarPacket->write(viewFrustumByteArray);
|
||||
|
||||
DependencyManager::get<NodeList>()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
|
||||
}
|
||||
|
||||
|
||||
int Application::sendNackPackets() {
|
||||
|
||||
|
@ -5397,6 +5403,12 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
auto scriptingInterface = DependencyManager::get<controller::ScriptingInterface>();
|
||||
scriptEngine->registerGlobalObject("Controller", scriptingInterface.data());
|
||||
UserInputMapper::registerControllerTypes(scriptEngine);
|
||||
|
||||
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
|
||||
connect(scriptEngine, &ScriptEngine::printedMessage, DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
|
||||
connect(scriptEngine, &ScriptEngine::errorMessage, DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onErrorMessage);
|
||||
connect(scriptEngine, &ScriptEngine::warningMessage, DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onWarningMessage);
|
||||
connect(scriptEngine, &ScriptEngine::infoMessage, DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onInfoMessage);
|
||||
}
|
||||
|
||||
bool Application::canAcceptURL(const QString& urlString) const {
|
||||
|
|
|
@ -444,6 +444,7 @@ private:
|
|||
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool isZoomed);
|
||||
|
||||
int sendNackPackets();
|
||||
void sendAvatarViewFrustum();
|
||||
|
||||
std::shared_ptr<MyAvatar> getMyAvatar() const;
|
||||
|
||||
|
|
|
@ -704,6 +704,15 @@ Menu::Menu() {
|
|||
addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L,
|
||||
qApp, SLOT(toggleLogDialog()));
|
||||
|
||||
action = addActionToQMenuAndActionHash(developerMenu, "Script Log (HMD friendly)...");
|
||||
connect(action, &QAction::triggered, [] {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
QUrl defaultScriptsLoc = defaultScriptsLocation();
|
||||
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js");
|
||||
scriptEngines->loadScript(defaultScriptsLoc.toString());
|
||||
});
|
||||
|
||||
|
||||
// Developer > Stats
|
||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats);
|
||||
|
||||
|
|
|
@ -75,6 +75,19 @@ namespace render {
|
|||
}
|
||||
}
|
||||
|
||||
static uint64_t timeProcessingJoints = 0;
|
||||
static int32_t numJointsProcessed = 0;
|
||||
|
||||
float Avatar::getNumJointsProcessedPerSecond() {
|
||||
float rate = 0.0f;
|
||||
if (timeProcessingJoints > 0) {
|
||||
rate = (float)(numJointsProcessed * USECS_PER_SECOND) / (float)timeProcessingJoints;
|
||||
}
|
||||
timeProcessingJoints = 0;
|
||||
numJointsProcessed = 0;
|
||||
return rate;
|
||||
}
|
||||
|
||||
Avatar::Avatar(RigPointer rig) :
|
||||
AvatarData(),
|
||||
_skeletonOffset(0.0f),
|
||||
|
@ -262,13 +275,16 @@ void Avatar::updateAvatarEntities() {
|
|||
}
|
||||
|
||||
AvatarEntityIDs recentlyDettachedAvatarEntities = getAndClearRecentlyDetachedIDs();
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
if (!recentlyDettachedAvatarEntities.empty()) {
|
||||
// only lock this thread when absolutely necessary
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
foreach (auto entityID, recentlyDettachedAvatarEntities) {
|
||||
if (!_avatarEntityData.contains(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (success) {
|
||||
|
@ -286,18 +302,25 @@ void Avatar::simulate(float deltaTime) {
|
|||
}
|
||||
animateScaleChanges(deltaTime);
|
||||
|
||||
bool avatarPositionInView = false;
|
||||
bool avatarMeshInView = false;
|
||||
bool avatarInView = false;
|
||||
{ // update the shouldAnimate flag to match whether or not we will render the avatar.
|
||||
PerformanceTimer perfTimer("cull");
|
||||
ViewFrustum viewFrustum;
|
||||
{
|
||||
PerformanceTimer perfTimer("LOD");
|
||||
// simple frustum check
|
||||
PerformanceTimer perfTimer("inView");
|
||||
ViewFrustum viewFrustum;
|
||||
qApp->copyDisplayViewFrustum(viewFrustum);
|
||||
avatarInView = viewFrustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())
|
||||
|| viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
|
||||
}
|
||||
PerformanceTimer lodPerfTimer("LOD");
|
||||
if (avatarInView) {
|
||||
const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
|
||||
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
|
||||
ViewFrustum viewFrustum;
|
||||
qApp->copyViewFrustum(viewFrustum);
|
||||
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
|
||||
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
||||
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
|
||||
if (!_shouldAnimate) {
|
||||
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
|
||||
_shouldAnimate = true;
|
||||
|
@ -308,18 +331,11 @@ void Avatar::simulate(float deltaTime) {
|
|||
qCDebug(interfaceapp) << "Optimizing" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for visibility" << visibility;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("inView");
|
||||
// simple frustum check
|
||||
float boundingRadius = getBoundingRadius();
|
||||
qApp->copyDisplayViewFrustum(viewFrustum);
|
||||
avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
|
||||
avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
|
||||
}
|
||||
}
|
||||
|
||||
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
|
||||
uint64_t start = usecTimestampNow();
|
||||
// CRUFT? _shouldSkipRender is never set 'true'
|
||||
if (_shouldAnimate && avatarInView && !_shouldSkipRender) {
|
||||
{
|
||||
PerformanceTimer perfTimer("skeleton");
|
||||
_skeletonModel->getRig()->copyJointsFromJointData(_jointData);
|
||||
|
@ -345,6 +361,8 @@ void Avatar::simulate(float deltaTime) {
|
|||
PerformanceTimer perfTimer("skeleton");
|
||||
_skeletonModel->simulate(deltaTime, false);
|
||||
}
|
||||
timeProcessingJoints += usecTimestampNow() - start;
|
||||
numJointsProcessed += _jointData.size();
|
||||
|
||||
// update animation for display name fade in/out
|
||||
if ( _displayNameTargetAlpha != _displayNameAlpha) {
|
||||
|
@ -709,7 +727,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
|
|||
glm::vec3 bodyUpDirection = getBodyUpDirection();
|
||||
DEBUG_VALUE("bodyUpDirection =", bodyUpDirection);
|
||||
|
||||
if (getSkeletonModel()->getNeckPosition(namePosition)) {
|
||||
if (_skeletonModel->getNeckPosition(namePosition)) {
|
||||
float headHeight = getHeadHeight();
|
||||
DEBUG_VALUE("namePosition =", namePosition);
|
||||
DEBUG_VALUE("headHeight =", headHeight);
|
||||
|
@ -1228,8 +1246,8 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
|
|||
return leftPalmPosition;
|
||||
}
|
||||
// avatar didn't have a LeftHandMiddle1 joint, fall back on this:
|
||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
|
||||
getSkeletonModel()->getLeftHandPosition(leftPalmPosition);
|
||||
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
|
||||
_skeletonModel->getLeftHandPosition(leftPalmPosition);
|
||||
leftPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(leftPalmRotation);
|
||||
return leftPalmPosition;
|
||||
}
|
||||
|
@ -1237,7 +1255,7 @@ glm::vec3 Avatar::getUncachedLeftPalmPosition() const {
|
|||
glm::quat Avatar::getUncachedLeftPalmRotation() const {
|
||||
assert(QThread::currentThread() == thread()); // main thread access only
|
||||
glm::quat leftPalmRotation;
|
||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getLeftHandJointIndex(), leftPalmRotation);
|
||||
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getLeftHandJointIndex(), leftPalmRotation);
|
||||
return leftPalmRotation;
|
||||
}
|
||||
|
||||
|
@ -1249,8 +1267,8 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
|
|||
return rightPalmPosition;
|
||||
}
|
||||
// avatar didn't have a RightHandMiddle1 joint, fall back on this:
|
||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
|
||||
getSkeletonModel()->getRightHandPosition(rightPalmPosition);
|
||||
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
|
||||
_skeletonModel->getRightHandPosition(rightPalmPosition);
|
||||
rightPalmPosition += HAND_TO_PALM_OFFSET * glm::inverse(rightPalmRotation);
|
||||
return rightPalmPosition;
|
||||
}
|
||||
|
@ -1258,7 +1276,7 @@ glm::vec3 Avatar::getUncachedRightPalmPosition() const {
|
|||
glm::quat Avatar::getUncachedRightPalmRotation() const {
|
||||
assert(QThread::currentThread() == thread()); // main thread access only
|
||||
glm::quat rightPalmRotation;
|
||||
getSkeletonModel()->getJointRotationInWorldFrame(getSkeletonModel()->getRightHandJointIndex(), rightPalmRotation);
|
||||
_skeletonModel->getJointRotationInWorldFrame(_skeletonModel->getRightHandJointIndex(), rightPalmRotation);
|
||||
return rightPalmRotation;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ class Avatar : public AvatarData {
|
|||
Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset)
|
||||
|
||||
public:
|
||||
static float getNumJointsProcessedPerSecond();
|
||||
|
||||
explicit Avatar(RigPointer rig = nullptr);
|
||||
~Avatar();
|
||||
|
||||
|
@ -119,6 +121,7 @@ public:
|
|||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||
|
||||
void setShowDisplayName(bool showDisplayName);
|
||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op
|
||||
|
||||
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
|
||||
|
||||
|
@ -189,6 +192,10 @@ public slots:
|
|||
protected:
|
||||
friend class AvatarManager;
|
||||
|
||||
virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send.
|
||||
QString _empty{};
|
||||
virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter!
|
||||
|
||||
void setMotionState(AvatarMotionState* motionState);
|
||||
|
||||
SkeletonModelPointer _skeletonModel;
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <Rig.h>
|
||||
#include <SettingHandle.h>
|
||||
#include <UsersScriptingInterface.h>
|
||||
#include <UUID.h>
|
||||
#include <AvatarData.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
|
@ -124,6 +124,9 @@ void AvatarManager::updateMyAvatar(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Q_LOGGING_CATEGORY(trace_simulation_avatar, "trace.simulation.avatar");
|
||||
|
||||
void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||
// lock the hash for read to check the size
|
||||
QReadLocker lock(&_hashLock);
|
||||
|
@ -143,6 +146,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
// simulate avatars
|
||||
auto hashCopy = getHashCopy();
|
||||
|
||||
uint64_t start = usecTimestampNow();
|
||||
AvatarHash::iterator avatarIterator = hashCopy.begin();
|
||||
while (avatarIterator != hashCopy.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(avatarIterator.value());
|
||||
|
@ -165,6 +169,10 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
|
||||
// simulate avatar fades
|
||||
simulateAvatarFades(deltaTime);
|
||||
|
||||
PROFILE_COUNTER(simulation_avatar, "NumAvatarsPerSec",
|
||||
{ { "NumAvatarsPerSec", (float)(size() * USECS_PER_SECOND) / (float)(usecTimestampNow() - start) } });
|
||||
PROFILE_COUNTER(simulation_avatar, "NumJointsPerSec", { { "NumJointsPerSec", Avatar::getNumJointsProcessedPerSecond() } });
|
||||
}
|
||||
|
||||
void AvatarManager::postUpdate(float deltaTime) {
|
||||
|
|
|
@ -226,7 +226,7 @@ void MyAvatar::simulateAttachments(float deltaTime) {
|
|||
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()
|
||||
}
|
||||
|
||||
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
QByteArray MyAvatar::toByteArray(AvatarDataDetail dataDetail) {
|
||||
CameraMode mode = qApp->getCamera()->getMode();
|
||||
_globalPosition = getPosition();
|
||||
_globalBoundingBoxCorner.x = _characterController.getCapsuleRadius();
|
||||
|
@ -237,12 +237,12 @@ QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
// fake the avatar position that is sent up to the AvatarMixer
|
||||
glm::vec3 oldPosition = getPosition();
|
||||
setPosition(getSkeletonPosition());
|
||||
QByteArray array = AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
QByteArray array = AvatarData::toByteArray(dataDetail);
|
||||
// copy the correct position back
|
||||
setPosition(oldPosition);
|
||||
return array;
|
||||
}
|
||||
return AvatarData::toByteArray(cullSmallChanges, sendAll);
|
||||
return AvatarData::toByteArray(dataDetail);
|
||||
}
|
||||
|
||||
void MyAvatar::centerBody() {
|
||||
|
|
|
@ -333,7 +333,7 @@ private:
|
|||
|
||||
glm::vec3 getWorldBodyPosition() const;
|
||||
glm::quat getWorldBodyOrientation() const;
|
||||
QByteArray toByteArray(bool cullSmallChanges, bool sendAll) override;
|
||||
QByteArray toByteArray(AvatarDataDetail dataDetail) override;
|
||||
void simulate(float deltaTime);
|
||||
void updateFromTrackers(float deltaTime);
|
||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
|
||||
|
|
|
@ -5,15 +5,18 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include "TestScriptingInterface.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
TestScriptingInterface* TestScriptingInterface::getInstance() {
|
||||
static TestScriptingInterface sharedInstance;
|
||||
|
@ -25,12 +28,47 @@ void TestScriptingInterface::quit() {
|
|||
}
|
||||
|
||||
void TestScriptingInterface::waitForTextureIdle() {
|
||||
waitForCondition(0, []()->bool {
|
||||
return (0 == gpu::Context::getTextureGPUTransferCount());
|
||||
});
|
||||
}
|
||||
|
||||
void TestScriptingInterface::waitForDownloadIdle() {
|
||||
waitForCondition(0, []()->bool {
|
||||
return (0 == ResourceCache::getLoadingRequestCount()) && (0 == ResourceCache::getPendingRequestCount());
|
||||
});
|
||||
}
|
||||
|
||||
void TestScriptingInterface::waitForProcessingIdle() {
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
waitForCondition(0, [statTracker]()->bool {
|
||||
return (0 == statTracker->getStat("Processing").toInt() && 0 == statTracker->getStat("PendingProcessing").toInt());
|
||||
});
|
||||
}
|
||||
|
||||
void TestScriptingInterface::waitIdle() {
|
||||
// Initial wait for some incoming work
|
||||
QThread::sleep(1);
|
||||
waitForDownloadIdle();
|
||||
waitForProcessingIdle();
|
||||
waitForTextureIdle();
|
||||
}
|
||||
|
||||
bool TestScriptingInterface::loadTestScene(QString scene) {
|
||||
static const QString TEST_ROOT = "https://raw.githubusercontent.com/highfidelity/hifi_tests/master/";
|
||||
static const QString TEST_BINARY_ROOT = "https://hifi-public.s3.amazonaws.com/test_scene_data/";
|
||||
static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/";
|
||||
static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/";
|
||||
return DependencyManager::get<OffscreenUi>()->returnFromUiThread([scene]()->QVariant {
|
||||
ResourceManager::setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/");
|
||||
auto tree = qApp->getEntities()->getTree();
|
||||
auto treeIsClient = tree->getIsClient();
|
||||
// Force the tree to accept the load regardless of permissions
|
||||
tree->setIsClient(false);
|
||||
auto result = tree->readFromURL(TEST_SCENES_ROOT + scene + ".json");
|
||||
tree->setIsClient(treeIsClient);
|
||||
return result;
|
||||
}).toBool();
|
||||
}
|
||||
|
||||
bool TestScriptingInterface::startTracing(QString logrules) {
|
||||
|
@ -55,4 +93,35 @@ bool TestScriptingInterface::stopTracing(QString filename) {
|
|||
tracer->stopTracing();
|
||||
tracer->serialize(filename);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void TestScriptingInterface::clear() {
|
||||
qApp->postLambdaEvent([] {
|
||||
qApp->getEntities()->clear();
|
||||
});
|
||||
}
|
||||
|
||||
bool TestScriptingInterface::waitForConnection(qint64 maxWaitMs) {
|
||||
// Wait for any previous connection to die
|
||||
QThread::sleep(1);
|
||||
return waitForCondition(maxWaitMs, []()->bool {
|
||||
return DependencyManager::get<NodeList>()->getDomainHandler().isConnected();
|
||||
});
|
||||
}
|
||||
|
||||
void TestScriptingInterface::wait(int milliseconds) {
|
||||
QThread::msleep(milliseconds);
|
||||
}
|
||||
|
||||
bool TestScriptingInterface::waitForCondition(qint64 maxWaitMs, std::function<bool()> condition) {
|
||||
QElapsedTimer elapsed;
|
||||
elapsed.start();
|
||||
while (!condition()) {
|
||||
if (maxWaitMs > 0 && elapsed.elapsed() > maxWaitMs) {
|
||||
return false;
|
||||
}
|
||||
QThread::msleep(1);
|
||||
}
|
||||
return condition();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef hifi_TestScriptingInterface_h
|
||||
#define hifi_TestScriptingInterface_h
|
||||
|
||||
#include <functional>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class TestScriptingInterface : public QObject {
|
||||
|
@ -34,10 +35,24 @@ public slots:
|
|||
void waitForDownloadIdle();
|
||||
|
||||
/**jsdoc
|
||||
* Waits for all pending downloads and texture transfers to be complete
|
||||
* Waits for all file parsing operations to be complete
|
||||
*/
|
||||
void waitForProcessingIdle();
|
||||
|
||||
/**jsdoc
|
||||
* Waits for all pending downloads, parsing and texture transfers to be complete
|
||||
*/
|
||||
void waitIdle();
|
||||
|
||||
|
||||
bool waitForConnection(qint64 maxWaitMs = 10000);
|
||||
|
||||
void wait(int milliseconds);
|
||||
|
||||
bool loadTestScene(QString sceneFile);
|
||||
|
||||
void clear();
|
||||
|
||||
/**jsdoc
|
||||
* Start recording Chrome compatible tracing events
|
||||
* logRules can be used to specify a set of logging category rules to limit what gets captured
|
||||
|
@ -49,6 +64,9 @@ public slots:
|
|||
* Using a filename with a .gz extension will automatically compress the output file
|
||||
*/
|
||||
bool stopTracing(QString filename);
|
||||
|
||||
private:
|
||||
bool waitForCondition(qint64 maxWaitMs, std::function<bool()> condition);
|
||||
};
|
||||
|
||||
#endif // hifi_TestScriptingInterface_h
|
||||
|
|
|
@ -91,7 +91,7 @@ void DiskCacheEditor::makeDialog() {
|
|||
|
||||
static const int REFRESH_INTERVAL = 100; // msec
|
||||
_refreshTimer = new QTimer(_dialog);
|
||||
_refreshTimer->setInterval(REFRESH_INTERVAL);
|
||||
_refreshTimer->setInterval(REFRESH_INTERVAL); // Qt::CoarseTimer acceptable, no need for real time accuracy
|
||||
_refreshTimer->setSingleShot(false);
|
||||
QObject::connect(_refreshTimer.data(), &QTimer::timeout, this, &DiskCacheEditor::refresh);
|
||||
_refreshTimer->start();
|
||||
|
|
|
@ -19,7 +19,6 @@ QString const Circle3DOverlay::TYPE = "circle3d";
|
|||
Circle3DOverlay::Circle3DOverlay() {
|
||||
memset(&_minorTickMarksColor, 0, sizeof(_minorTickMarksColor));
|
||||
memset(&_majorTickMarksColor, 0, sizeof(_majorTickMarksColor));
|
||||
qDebug() << "Building circle3d overlay";
|
||||
}
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
||||
|
@ -40,7 +39,6 @@ Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
|||
_majorTicksVerticesID(GeometryCache::UNKNOWN_ID),
|
||||
_minorTicksVerticesID(GeometryCache::UNKNOWN_ID)
|
||||
{
|
||||
qDebug() << "Building circle3d overlay";
|
||||
}
|
||||
|
||||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
|
@ -59,7 +57,6 @@ Circle3DOverlay::~Circle3DOverlay() {
|
|||
geometryCache->releaseID(_minorTicksVerticesID);
|
||||
}
|
||||
}
|
||||
qDebug() << "Destroying circle3d overlay";
|
||||
}
|
||||
void Circle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
|
|
|
@ -19,7 +19,6 @@ QString const Line3DOverlay::TYPE = "line3d";
|
|||
Line3DOverlay::Line3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
qDebug() << "Building line3D overlay";
|
||||
}
|
||||
|
||||
Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) :
|
||||
|
@ -28,11 +27,9 @@ Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) :
|
|||
_end(line3DOverlay->_end),
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
qDebug() << "Building line3D overlay";
|
||||
}
|
||||
|
||||
Line3DOverlay::~Line3DOverlay() {
|
||||
qDebug() << "Destryoing line3D overlay";
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_geometryCacheID && geometryCache) {
|
||||
geometryCache->releaseID(_geometryCacheID);
|
||||
|
|
|
@ -161,6 +161,7 @@ void Rig::destroyAnimGraph() {
|
|||
_internalPoseSet._absolutePoses.clear();
|
||||
_internalPoseSet._overridePoses.clear();
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_numOverrides = 0;
|
||||
}
|
||||
|
||||
void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset) {
|
||||
|
@ -180,6 +181,7 @@ void Rig::initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOff
|
|||
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||
_numOverrides = 0;
|
||||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
||||
|
@ -207,6 +209,7 @@ void Rig::reset(const FBXGeometry& geometry) {
|
|||
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints(), false);
|
||||
_numOverrides = 0;
|
||||
|
||||
buildAbsoluteRigPoses(_animSkeleton->getRelativeDefaultPoses(), _absoluteDefaultPoses);
|
||||
|
||||
|
@ -276,13 +279,17 @@ void Rig::setModelOffset(const glm::mat4& modelOffsetMat) {
|
|||
|
||||
void Rig::clearJointState(int index) {
|
||||
if (isIndexValid(index)) {
|
||||
_internalPoseSet._overrideFlags[index] = false;
|
||||
if (_internalPoseSet._overrideFlags[index]) {
|
||||
_internalPoseSet._overrideFlags[index] = false;
|
||||
--_numOverrides;
|
||||
}
|
||||
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::clearJointStates() {
|
||||
_internalPoseSet._overrideFlags.clear();
|
||||
_numOverrides = 0;
|
||||
if (_animSkeleton) {
|
||||
_internalPoseSet._overrideFlags.resize(_animSkeleton->getNumJoints());
|
||||
_internalPoseSet._overridePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
|
@ -291,7 +298,10 @@ void Rig::clearJointStates() {
|
|||
|
||||
void Rig::clearJointAnimationPriority(int index) {
|
||||
if (isIndexValid(index)) {
|
||||
_internalPoseSet._overrideFlags[index] = false;
|
||||
if (_internalPoseSet._overrideFlags[index]) {
|
||||
_internalPoseSet._overrideFlags[index] = false;
|
||||
--_numOverrides;
|
||||
}
|
||||
_internalPoseSet._overridePoses[index] = _animSkeleton->getRelativeDefaultPose(index);
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +330,10 @@ void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translatio
|
|||
if (isIndexValid(index)) {
|
||||
if (valid) {
|
||||
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
if (!_internalPoseSet._overrideFlags[index]) {
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
++_numOverrides;
|
||||
}
|
||||
_internalPoseSet._overridePoses[index].trans = translation;
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +342,10 @@ void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translatio
|
|||
void Rig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) {
|
||||
if (isIndexValid(index)) {
|
||||
assert(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
if (!_internalPoseSet._overrideFlags[index]) {
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
++_numOverrides;
|
||||
}
|
||||
_internalPoseSet._overridePoses[index].rot = rotation;
|
||||
_internalPoseSet._overridePoses[index].trans = translation;
|
||||
}
|
||||
|
@ -339,7 +355,10 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo
|
|||
if (isIndexValid(index)) {
|
||||
if (valid) {
|
||||
ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
if (!_internalPoseSet._overrideFlags[index]) {
|
||||
_internalPoseSet._overrideFlags[index] = true;
|
||||
++_numOverrides;
|
||||
}
|
||||
_internalPoseSet._overridePoses[index].rot = rotation;
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +537,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
|||
|
||||
// sine wave LFO var for testing.
|
||||
static float t = 0.0f;
|
||||
_animVars.set("sine", 2.0f * static_cast<float>(0.5 * sin(t) + 0.5));
|
||||
_animVars.set("sine", 2.0f * 0.5f * sinf(t) + 0.5f);
|
||||
|
||||
float moveForwardAlpha = 0.0f;
|
||||
float moveBackwardAlpha = 0.0f;
|
||||
|
@ -884,10 +903,12 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
||||
|
||||
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xffff00ff, 0);
|
||||
PerformanceTimer perfTimer("updateAnimations");
|
||||
|
||||
setModelOffset(rootTransform);
|
||||
|
||||
if (_animNode) {
|
||||
PerformanceTimer perfTimer("handleTriggers");
|
||||
|
||||
updateAnimationStateHandlers();
|
||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
|
@ -904,7 +925,6 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
|
|||
_animVars.setTrigger(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
applyOverridePoses();
|
||||
buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses);
|
||||
|
||||
|
@ -1176,7 +1196,8 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
|
|||
}
|
||||
|
||||
void Rig::applyOverridePoses() {
|
||||
if (!_animSkeleton) {
|
||||
PerformanceTimer perfTimer("override");
|
||||
if (_numOverrides == 0 || !_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1192,28 +1213,24 @@ void Rig::applyOverridePoses() {
|
|||
}
|
||||
|
||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
||||
PerformanceTimer perfTimer("buildAbsolute");
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(_animSkeleton->getNumJoints() == (int)relativePoses.size());
|
||||
|
||||
// flatten all poses out so they are absolute not relative
|
||||
absolutePosesOut.resize(relativePoses.size());
|
||||
AnimPose geometryToRigTransform(_geometryToRigTransform);
|
||||
for (int i = 0; i < (int)relativePoses.size(); i++) {
|
||||
int parentIndex = _animSkeleton->getParentIndex(i);
|
||||
if (parentIndex == -1) {
|
||||
absolutePosesOut[i] = relativePoses[i];
|
||||
// transform all root absolute poses into rig space
|
||||
absolutePosesOut[i] = geometryToRigTransform * relativePoses[i];
|
||||
} else {
|
||||
absolutePosesOut[i] = absolutePosesOut[parentIndex] * relativePoses[i];
|
||||
}
|
||||
}
|
||||
|
||||
// transform all absolute poses into rig space.
|
||||
AnimPose geometryToRigTransform(_geometryToRigTransform);
|
||||
for (int i = 0; i < (int)absolutePosesOut.size(); i++) {
|
||||
absolutePosesOut[i] = geometryToRigTransform * absolutePosesOut[i];
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 Rig::getJointTransform(int jointIndex) const {
|
||||
|
@ -1251,62 +1268,36 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
|
||||
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
||||
PerformanceTimer perfTimer("copyJoints");
|
||||
if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._overrideFlags.size()) {
|
||||
|
||||
// transform all the default poses into rig space.
|
||||
const AnimPose geometryToRigPose(_geometryToRigTransform);
|
||||
std::vector<bool> overrideFlags(_internalPoseSet._overridePoses.size(), false);
|
||||
|
||||
// start with the default rotations in absolute rig frame
|
||||
if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._relativePoses.size()) {
|
||||
// make a vector of rotations in absolute-geometry-frame
|
||||
const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses();
|
||||
std::vector<glm::quat> rotations;
|
||||
rotations.reserve(_animSkeleton->getAbsoluteDefaultPoses().size());
|
||||
for (auto& pose : _animSkeleton->getAbsoluteDefaultPoses()) {
|
||||
rotations.push_back(geometryToRigPose.rot * pose.rot);
|
||||
}
|
||||
|
||||
// start translations in relative frame but scaled to meters.
|
||||
std::vector<glm::vec3> translations;
|
||||
translations.reserve(_animSkeleton->getRelativeDefaultPoses().size());
|
||||
for (auto& pose : _animSkeleton->getRelativeDefaultPoses()) {
|
||||
translations.push_back(_geometryOffset.scale * pose.trans);
|
||||
}
|
||||
|
||||
ASSERT(overrideFlags.size() == rotations.size());
|
||||
|
||||
// copy over rotations from the jointDataVec, which is also in absolute rig frame
|
||||
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||
if (isIndexValid(i)) {
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
if (data.rotationSet) {
|
||||
overrideFlags[i] = true;
|
||||
rotations[i] = data.rotation;
|
||||
}
|
||||
if (data.translationSet) {
|
||||
overrideFlags[i] = true;
|
||||
translations[i] = data.translation;
|
||||
}
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
if (data.rotationSet) {
|
||||
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
|
||||
rotations.push_back(rigToGeometryRot * data.rotation);
|
||||
} else {
|
||||
rotations.push_back(absoluteDefaultPoses[i].rot);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(_internalPoseSet._overrideFlags.size() == _internalPoseSet._overridePoses.size());
|
||||
|
||||
// convert resulting rotations into geometry space.
|
||||
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||
for (auto& rot : rotations) {
|
||||
rot = rigToGeometryRot * rot;
|
||||
}
|
||||
|
||||
// convert all rotations from absolute to parent relative.
|
||||
// convert rotations from absolute to parent relative.
|
||||
_animSkeleton->convertAbsoluteRotationsToRelative(rotations);
|
||||
|
||||
// copy the geometry space parent relative poses into _overridePoses
|
||||
// store new relative poses
|
||||
const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||
if (overrideFlags[i]) {
|
||||
_internalPoseSet._overrideFlags[i] = true;
|
||||
_internalPoseSet._overridePoses[i].scale = Vectors::ONE;
|
||||
_internalPoseSet._overridePoses[i].rot = rotations[i];
|
||||
// scale translations from meters back into geometry units.
|
||||
_internalPoseSet._overridePoses[i].trans = _invGeometryOffset.scale * translations[i];
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
_internalPoseSet._relativePoses[i].scale = Vectors::ONE;
|
||||
_internalPoseSet._relativePoses[i].rot = rotations[i];
|
||||
if (data.translationSet) {
|
||||
// JointData translations are in scaled relative-frame so we scale back to regular relative-frame
|
||||
_internalPoseSet._relativePoses[i].trans = _invGeometryOffset.scale * data.translation;
|
||||
} else {
|
||||
_internalPoseSet._relativePoses[i].trans = relativeDefaultPoses[i].trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,6 +311,7 @@ protected:
|
|||
|
||||
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
||||
|
||||
int32_t _numOverrides { 0 };
|
||||
bool _lastEnableInverseKinematics { true };
|
||||
bool _enableInverseKinematics { true };
|
||||
|
||||
|
|
|
@ -16,6 +16,14 @@
|
|||
#include "AudioHRTF.h"
|
||||
#include "AudioHRTFData.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGN32 __declspec(align(32))
|
||||
#elif defined(__GNUC__)
|
||||
#define ALIGN32 __attribute__((aligned(32)))
|
||||
#else
|
||||
#define ALIGN32
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
@ -30,7 +38,7 @@
|
|||
// Transients in the time-varying Thiran allpass filter are eliminated by the initial delay.
|
||||
// Valimaki, Laakso. "Elimination of Transients in Time-Varying Allpass Fractional Delay Filters"
|
||||
//
|
||||
static const float crossfadeTable[HRTF_BLOCK] = {
|
||||
ALIGN32 static const float crossfadeTable[HRTF_BLOCK] = {
|
||||
1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f,
|
||||
0.9999545513f, 0.9998182135f, 0.9995910114f, 0.9992729863f, 0.9988641959f, 0.9983647147f, 0.9977746334f, 0.9970940592f,
|
||||
0.9963231160f, 0.9954619438f, 0.9945106993f, 0.9934695553f, 0.9923387012f, 0.9911183425f, 0.9898087010f, 0.9884100149f,
|
||||
|
@ -192,25 +200,29 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float
|
|||
|
||||
for (int k = 0; k < HRTF_TAPS; k += 4) {
|
||||
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-0]), _mm_loadu_ps(&ps[k+0])));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-0]), _mm_loadu_ps(&ps[k+0])));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-0]), _mm_loadu_ps(&ps[k+0])));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-0]), _mm_loadu_ps(&ps[k+0])));
|
||||
__m128 x0 = _mm_loadu_ps(&ps[k+0]);
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-0]), x0));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-0]), x0));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-0]), x0));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-0]), x0));
|
||||
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-1]), _mm_loadu_ps(&ps[k+1])));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-1]), _mm_loadu_ps(&ps[k+1])));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-1]), _mm_loadu_ps(&ps[k+1])));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-1]), _mm_loadu_ps(&ps[k+1])));
|
||||
__m128 x1 = _mm_loadu_ps(&ps[k+1]);
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-1]), x1));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-1]), x1));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-1]), x1));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-1]), x1));
|
||||
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-2]), _mm_loadu_ps(&ps[k+2])));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-2]), _mm_loadu_ps(&ps[k+2])));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-2]), _mm_loadu_ps(&ps[k+2])));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-2]), _mm_loadu_ps(&ps[k+2])));
|
||||
__m128 x2 = _mm_loadu_ps(&ps[k+2]);
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-2]), x2));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-2]), x2));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-2]), x2));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-2]), x2));
|
||||
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-3]), _mm_loadu_ps(&ps[k+3])));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-3]), _mm_loadu_ps(&ps[k+3])));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-3]), _mm_loadu_ps(&ps[k+3])));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-3]), _mm_loadu_ps(&ps[k+3])));
|
||||
__m128 x3 = _mm_loadu_ps(&ps[k+3]);
|
||||
acc0 = _mm_add_ps(acc0, _mm_mul_ps(_mm_load1_ps(&coef0[-k-3]), x3));
|
||||
acc1 = _mm_add_ps(acc1, _mm_mul_ps(_mm_load1_ps(&coef1[-k-3]), x3));
|
||||
acc2 = _mm_add_ps(acc2, _mm_mul_ps(_mm_load1_ps(&coef2[-k-3]), x3));
|
||||
acc3 = _mm_add_ps(acc3, _mm_mul_ps(_mm_load1_ps(&coef3[-k-3]), x3));
|
||||
}
|
||||
|
||||
_mm_storeu_ps(&dst0[i], acc0);
|
||||
|
@ -226,11 +238,11 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float
|
|||
|
||||
#include "CPUDetect.h"
|
||||
|
||||
void FIR_1x4_AVX(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames);
|
||||
void FIR_1x4_AVX2(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 = cpuSupportsAVX() ? FIR_1x4_AVX : FIR_1x4_SSE;
|
||||
static auto f = cpuSupportsAVX2() ? FIR_1x4_AVX2 : FIR_1x4_SSE;
|
||||
(*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch
|
||||
}
|
||||
|
||||
|
@ -842,12 +854,12 @@ void AudioHRTF::render(int16_t* input, float* output, int index, float azimuth,
|
|||
assert(index < HRTF_TABLES);
|
||||
assert(numFrames == HRTF_BLOCK);
|
||||
|
||||
float in[HRTF_TAPS + HRTF_BLOCK]; // mono
|
||||
float firCoef[4][HRTF_TAPS]; // 4-channel
|
||||
float firBuffer[4][HRTF_DELAY + HRTF_BLOCK]; // 4-channel
|
||||
float bqCoef[5][8]; // 4-channel (interleaved)
|
||||
float bqBuffer[4 * HRTF_BLOCK]; // 4-channel (interleaved)
|
||||
int delay[4]; // 4-channel (interleaved)
|
||||
ALIGN32 float in[HRTF_TAPS + HRTF_BLOCK]; // mono
|
||||
ALIGN32 float firCoef[4][HRTF_TAPS]; // 4-channel
|
||||
ALIGN32 float firBuffer[4][HRTF_DELAY + HRTF_BLOCK]; // 4-channel
|
||||
ALIGN32 float bqCoef[5][8]; // 4-channel (interleaved)
|
||||
ALIGN32 float bqBuffer[4 * HRTF_BLOCK]; // 4-channel (interleaved)
|
||||
int delay[4]; // 4-channel (interleaved)
|
||||
|
||||
// to avoid polluting the cache, old filters are recomputed instead of stored
|
||||
setFilters(firCoef, bqCoef, delay, index, _azimuthState, _distanceState, _gainState, L0);
|
||||
|
|
|
@ -30,6 +30,14 @@
|
|||
// 6) Truncate filter length to 2.5ms using rectangular window with 8-tap Hanning taper
|
||||
//
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGN32 __declspec(align(32))
|
||||
#elif defined(__GNUC__)
|
||||
#define ALIGN32 __attribute__((aligned(32)))
|
||||
#else
|
||||
#define ALIGN32
|
||||
#endif
|
||||
|
||||
static const float itd_1002_table[HRTF_AZIMUTHS] = {
|
||||
-0.07851f, 0.85414f, 1.77170f, 2.71137f, 3.71065f, 4.74907f, 5.79892f, 6.82396f,
|
||||
7.82837f, 8.80796f, 9.75426f, 10.68332f, 11.59979f, 12.48520f, 13.36135f, 14.19234f,
|
||||
|
@ -42,7 +50,7 @@ static const float itd_1002_table[HRTF_AZIMUTHS] = {
|
|||
-8.39670f, -7.23606f, -6.09663f, -5.05593f, -4.06186f, -3.07465f, -2.06122f, -1.05417f,
|
||||
};
|
||||
|
||||
static const float ir_1002_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1002_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.341559e-01f, 1.886116e-02f, 2.677664e-01f, -7.037183e-02f, -4.147236e-02f, -2.761588e-01f, 2.310035e-01f, -1.643133e-01f,
|
||||
|
@ -1497,7 +1505,7 @@ static const float itd_1003_table[HRTF_AZIMUTHS] = {
|
|||
-6.64380f, -5.73462f, -4.83364f, -3.97025f, -3.08925f, -2.16621f, -1.19364f, -0.20709f,
|
||||
};
|
||||
|
||||
static const float ir_1003_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1003_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.266240e-01f, 1.260510e-01f, 5.051008e-02f, -3.536678e-01f, 2.462246e-02f, 4.465557e-02f, 6.813228e-02f, -6.063477e-02f,
|
||||
|
@ -2952,7 +2960,7 @@ static const float itd_1004_table[HRTF_AZIMUTHS] = {
|
|||
-7.55720f, -6.55578f, -5.59246f, -4.69657f, -3.80733f, -2.88567f, -1.90337f, -0.89923f,
|
||||
};
|
||||
|
||||
static const float ir_1004_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1004_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.326633e-01f, 4.279429e-01f, -5.910516e-02f, -2.480760e-01f, -9.903029e-02f, 9.215562e-02f, -2.893536e-02f, 5.464364e-02f,
|
||||
|
@ -4407,7 +4415,7 @@ static const float itd_1005_table[HRTF_AZIMUTHS] = {
|
|||
-6.80079f, -6.03878f, -5.25100f, -4.34973f, -3.39268f, -2.41226f, -1.45444f, -0.50375f,
|
||||
};
|
||||
|
||||
static const float ir_1005_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1005_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.515557e-01f, 1.208618e-01f, 3.238278e-01f, -3.605847e-01f, -3.354420e-02f, -1.829174e-01f, 2.309960e-01f, -1.744711e-01f,
|
||||
|
@ -5862,7 +5870,7 @@ static const float itd_1007_table[HRTF_AZIMUTHS] = {
|
|||
-7.68135f, -6.69801f, -5.72186f, -4.72708f, -3.74413f, -2.77373f, -1.79032f, -0.81823f,
|
||||
};
|
||||
|
||||
static const float ir_1007_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1007_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
6.544936e-01f, 2.820574e-01f, 1.850652e-01f, -2.597811e-01f, -5.585250e-02f, -7.975905e-02f, 8.143960e-02f, -5.044548e-02f,
|
||||
|
@ -7317,7 +7325,7 @@ static const float itd_1012_table[HRTF_AZIMUTHS] = {
|
|||
-7.32159f, -6.30684f, -5.31969f, -4.40260f, -3.50567f, -2.60925f, -1.70893f, -0.80401f,
|
||||
};
|
||||
|
||||
static const float ir_1012_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1012_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.505165e-01f, 9.074762e-02f, 3.296598e-01f, -5.213905e-01f, 1.348379e-01f, -1.828924e-01f, 1.400077e-01f, -4.071996e-02f,
|
||||
|
@ -8772,7 +8780,7 @@ static const float itd_1014_table[HRTF_AZIMUTHS] = {
|
|||
-7.51312f, -6.52705f, -5.56262f, -4.72113f, -3.90664f, -3.07768f, -2.22719f, -1.37514f,
|
||||
};
|
||||
|
||||
static const float ir_1014_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1014_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
6.542071e-01f, 4.575563e-01f, 1.118072e-02f, -1.823464e-01f, -2.222339e-01f, 1.371357e-01f, 7.027919e-03f, -5.534852e-02f,
|
||||
|
@ -10227,7 +10235,7 @@ static const float itd_1017_table[HRTF_AZIMUTHS] = {
|
|||
-7.46925f, -6.49073f, -5.52501f, -4.62178f, -3.74041f, -2.86207f, -1.97362f, -1.07512f,
|
||||
};
|
||||
|
||||
static const float ir_1017_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1017_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.470867e-01f, 2.686078e-01f, 2.097923e-01f, -2.935018e-01f, -8.687224e-02f, -4.547367e-02f, 6.920631e-03f, 3.752071e-02f,
|
||||
|
@ -11682,7 +11690,7 @@ static const float itd_1020_table[HRTF_AZIMUTHS] = {
|
|||
-8.28071f, -7.36311f, -6.43732f, -5.49298f, -4.53728f, -3.57601f, -2.59830f, -1.63297f,
|
||||
};
|
||||
|
||||
static const float ir_1020_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1020_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
6.953847e-01f, 3.081256e-01f, 2.474324e-01f, -3.025226e-01f, -1.119181e-01f, -4.966299e-02f, 5.727889e-02f, 6.715016e-03f,
|
||||
|
@ -13137,7 +13145,7 @@ static const float itd_1021_table[HRTF_AZIMUTHS] = {
|
|||
-8.12772f, -7.17689f, -6.23068f, -5.27554f, -4.32391f, -3.38489f, -2.46445f, -1.54407f,
|
||||
};
|
||||
|
||||
static const float ir_1021_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1021_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.807186e-01f, 3.835520e-01f, 1.208801e-01f, -4.044311e-01f, -5.188029e-02f, -7.750225e-02f, 1.739668e-01f, -6.599168e-02f,
|
||||
|
@ -14592,7 +14600,7 @@ static const float itd_1022_table[HRTF_AZIMUTHS] = {
|
|||
-7.19675f, -6.30334f, -5.39609f, -4.47018f, -3.53964f, -2.62393f, -1.75389f, -0.90222f,
|
||||
};
|
||||
|
||||
static const float ir_1022_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1022_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.053226e-01f, 2.645844e-01f, 2.462055e-01f, -2.145682e-01f, -1.333283e-01f, -1.751403e-01f, 2.721890e-01f, -1.743790e-01f,
|
||||
|
@ -16047,7 +16055,7 @@ static const float itd_1026_table[HRTF_AZIMUTHS] = {
|
|||
-7.45209f, -6.46598f, -5.49746f, -4.54220f, -3.60610f, -2.68084f, -1.74087f, -0.80841f,
|
||||
};
|
||||
|
||||
static const float ir_1026_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1026_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.150396e-01f, 3.144234e-01f, 9.132840e-02f, -2.128668e-01f, -1.899010e-01f, 1.362356e-01f, -4.105226e-02f, 4.896281e-02f,
|
||||
|
@ -17502,7 +17510,7 @@ static const float itd_1028_table[HRTF_AZIMUTHS] = {
|
|||
-7.80099f, -6.89255f, -5.95721f, -5.04107f, -4.11968f, -3.20233f, -2.33316f, -1.46289f,
|
||||
};
|
||||
|
||||
static const float ir_1028_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1028_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.491360e-01f, 2.952796e-01f, -1.585342e-01f, -3.497386e-01f, 1.204260e-01f, -4.886012e-02f, 5.238760e-02f, -8.209077e-03f,
|
||||
|
@ -18957,7 +18965,7 @@ static const float itd_1038_table[HRTF_AZIMUTHS] = {
|
|||
-6.69661f, -5.65906f, -4.62851f, -3.63493f, -2.66802f, -1.71997f, -0.76853f, 0.18497f,
|
||||
};
|
||||
|
||||
static const float ir_1038_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1038_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.325991e-01f, 1.817283e-01f, 5.397613e-02f, -4.121773e-01f, -7.921759e-03f, -4.009945e-02f, 1.499187e-01f, -1.838252e-02f,
|
||||
|
@ -20412,7 +20420,7 @@ static const float itd_1041_table[HRTF_AZIMUTHS] = {
|
|||
-7.03257f, -6.07458f, -5.13664f, -4.24453f, -3.37177f, -2.49083f, -1.55807f, -0.62014f,
|
||||
};
|
||||
|
||||
static const float ir_1041_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1041_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.012368e-01f, 2.006662e-01f, 3.173636e-01f, -2.865733e-01f, 1.345042e-01f, -5.030394e-01f, 3.717757e-01f, -1.138039e-01f,
|
||||
|
@ -21867,7 +21875,7 @@ static const float itd_1042_table[HRTF_AZIMUTHS] = {
|
|||
-7.79822f, -6.84403f, -5.88862f, -4.94525f, -3.99704f, -3.03547f, -2.06207f, -1.07916f,
|
||||
};
|
||||
|
||||
static const float ir_1042_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1042_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.114429e-01f, 2.201994e-03f, 3.703525e-01f, -4.825957e-01f, 1.210277e-01f, -2.471091e-01f, 1.766662e-01f, -5.840113e-03f,
|
||||
|
@ -23322,7 +23330,7 @@ static const float itd_1043_table[HRTF_AZIMUTHS] = {
|
|||
-6.81973f, -5.86664f, -4.92096f, -3.99232f, -3.07973f, -2.16321f, -1.20142f, -0.22538f,
|
||||
};
|
||||
|
||||
static const float ir_1043_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1043_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.339447e-01f, 1.339343e-01f, 4.031645e-01f, -4.891909e-01f, 8.751389e-02f, -2.110783e-01f, 2.573841e-01f, -1.050324e-01f,
|
||||
|
@ -24777,7 +24785,7 @@ static const float itd_1044_table[HRTF_AZIMUTHS] = {
|
|||
-7.31965f, -6.37963f, -5.45379f, -4.54748f, -3.59370f, -2.59525f, -1.67705f, -0.73882f,
|
||||
};
|
||||
|
||||
static const float ir_1044_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1044_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.028871e-01f, 2.381998e-01f, 4.686725e-01f, -5.412304e-01f, 1.262568e-01f, -3.198619e-01f, 1.963468e-01f, -4.016186e-02f,
|
||||
|
@ -26232,7 +26240,7 @@ static const float itd_1047_table[HRTF_AZIMUTHS] = {
|
|||
-9.01225f, -7.93667f, -6.85884f, -5.78919f, -4.72064f, -3.66640f, -2.66295f, -1.65780f,
|
||||
};
|
||||
|
||||
static const float ir_1047_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1047_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
7.788578e-01f, 1.598904e-01f, 2.366520e-01f, -3.524184e-01f, -8.784474e-03f, -5.144472e-02f, 8.679429e-02f, -1.634258e-02f,
|
||||
|
@ -27687,7 +27695,7 @@ static const float itd_1048_table[HRTF_AZIMUTHS] = {
|
|||
-7.15985f, -6.30472f, -5.41513f, -4.54994f, -3.62385f, -2.66142f, -1.79111f, -0.94033f,
|
||||
};
|
||||
|
||||
static const float ir_1048_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1048_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.865287e-01f, 2.972076e-01f, -1.305391e-01f, -1.213860e-01f, -1.948535e-01f, 1.458427e-01f, -8.912857e-02f, 9.493978e-02f,
|
||||
|
@ -29142,7 +29150,7 @@ static const float itd_1050_table[HRTF_AZIMUTHS] = {
|
|||
-6.52690f, -5.58085f, -4.64474f, -3.71658f, -2.80444f, -1.92096f, -1.07543f, -0.23450f,
|
||||
};
|
||||
|
||||
static const float ir_1050_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1050_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.005889e-01f, -6.452200e-02f, 3.675525e-01f, -4.309962e-01f, 7.086621e-02f, -9.161573e-02f, -4.290351e-02f, 9.057393e-02f,
|
||||
|
@ -30597,7 +30605,7 @@ static const float itd_1052_table[HRTF_AZIMUTHS] = {
|
|||
-6.50194f, -5.61262f, -4.72534f, -3.84869f, -2.97504f, -2.10269f, -1.23783f, -0.36766f,
|
||||
};
|
||||
|
||||
static const float ir_1052_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1052_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
6.650009e-01f, 3.507944e-01f, -3.274164e-02f, -1.830690e-01f, -7.720853e-02f, 1.030789e-01f, 3.877069e-02f, -5.674440e-02f,
|
||||
|
@ -32052,7 +32060,7 @@ static const float itd_1054_table[HRTF_AZIMUTHS] = {
|
|||
-7.35642f, -6.36606f, -5.37262f, -4.40394f, -3.44967f, -2.51333f, -1.59834f, -0.68300f,
|
||||
};
|
||||
|
||||
static const float ir_1054_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1054_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.629450e-01f, 1.677356e-01f, 1.467365e-01f, -3.248726e-01f, -5.105235e-02f, -5.031096e-02f, 1.796471e-01f, -1.298094e-01f,
|
||||
|
@ -33507,7 +33515,7 @@ static const float itd_1056_table[HRTF_AZIMUTHS] = {
|
|||
-6.99437f, -5.82430f, -4.73408f, -3.76713f, -2.88870f, -2.05251f, -1.18172f, -0.32736f,
|
||||
};
|
||||
|
||||
static const float ir_1056_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1056_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
8.031418e-01f, 2.411323e-01f, 1.417951e-01f, -2.476192e-01f, -1.076012e-01f, 1.009190e-01f, 7.761394e-02f, -1.250722e-01f,
|
||||
|
@ -34962,7 +34970,7 @@ static const float itd_1058_table[HRTF_AZIMUTHS] = {
|
|||
-7.78555f, -6.81447f, -5.85685f, -4.89466f, -3.93902f, -2.98660f, -2.01925f, -1.05758f,
|
||||
};
|
||||
|
||||
static const float ir_1058_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
ALIGN32 static const float ir_1058_table[HRTF_AZIMUTHS][2][HRTF_TAPS] = {
|
||||
// azimuth = 0
|
||||
{{
|
||||
9.307292e-01f, 5.592706e-02f, 2.567367e-01f, -4.525413e-01f, 1.378666e-01f, -2.503950e-01f, 1.983286e-01f, 5.925522e-03f,
|
||||
|
|
|
@ -208,7 +208,7 @@ qint64 writeStringToStream(const QString& string, QDataStream& stream) {
|
|||
|
||||
int64_t AudioInjector::injectNextFrame() {
|
||||
if (stateHas(AudioInjectorState::NetworkInjectionFinished)) {
|
||||
qDebug() << "AudioInjector::injectNextFrame called but AudioInjector has finished and was not restarted. Returning.";
|
||||
qCDebug(audio) << "AudioInjector::injectNextFrame called but AudioInjector has finished and was not restarted. Returning.";
|
||||
return NEXT_FRAME_DELTA_ERROR_OR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ int64_t AudioInjector::injectNextFrame() {
|
|||
auto numSamples = static_cast<int>(_audioData.size() / sampleSize);
|
||||
auto targetSize = numSamples * sampleSize;
|
||||
if (targetSize != _audioData.size()) {
|
||||
qDebug() << "Resizing audio that doesn't end at multiple of sample size, resizing from "
|
||||
qCDebug(audio) << "Resizing audio that doesn't end at multiple of sample size, resizing from "
|
||||
<< _audioData.size() << " to " << targetSize;
|
||||
_audioData.resize(targetSize);
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ int64_t AudioInjector::injectNextFrame() {
|
|||
|
||||
} else {
|
||||
// no samples to inject, return immediately
|
||||
qDebug() << "AudioInjector::injectNextFrame() called with no samples to inject. Returning.";
|
||||
qCDebug(audio) << "AudioInjector::injectNextFrame() called with no samples to inject. Returning.";
|
||||
return NEXT_FRAME_DELTA_ERROR_OR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ int64_t AudioInjector::injectNextFrame() {
|
|||
|
||||
if (currentFrameBasedOnElapsedTime - _nextFrame > MAX_ALLOWED_FRAMES_TO_FALL_BEHIND) {
|
||||
// If we are falling behind by more frames than our threshold, let's skip the frames ahead
|
||||
qDebug() << this << "injectNextFrame() skipping ahead, fell behind by " << (currentFrameBasedOnElapsedTime - _nextFrame) << " frames";
|
||||
qCDebug(audio) << this << "injectNextFrame() skipping ahead, fell behind by " << (currentFrameBasedOnElapsedTime - _nextFrame) << " frames";
|
||||
_nextFrame = currentFrameBasedOnElapsedTime;
|
||||
_currentSendOffset = _nextFrame * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL * (_options.stereo ? 2 : 1) % _audioData.size();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "AudioConstants.h"
|
||||
#include "AudioInjector.h"
|
||||
#include "AudioLogging.h"
|
||||
|
||||
AudioInjectorManager::~AudioInjectorManager() {
|
||||
_shouldStop = true;
|
||||
|
@ -131,7 +132,7 @@ static const int MAX_INJECTORS_PER_THREAD = 40; // calculated based on AudioInje
|
|||
|
||||
bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a lock.
|
||||
if (_injectors.size() >= MAX_INJECTORS_PER_THREAD) {
|
||||
qDebug() << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of"
|
||||
qCDebug(audio) << "AudioInjectorManager::threadInjector could not thread AudioInjector - at max of"
|
||||
<< MAX_INJECTORS_PER_THREAD << "current audio injectors.";
|
||||
return true;
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ bool AudioInjectorManager::wouldExceedLimits() { // Should be called inside of a
|
|||
|
||||
bool AudioInjectorManager::threadInjector(AudioInjector* injector) {
|
||||
if (_shouldStop) {
|
||||
qDebug() << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down.";
|
||||
qCDebug(audio) << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,7 +170,7 @@ bool AudioInjectorManager::threadInjector(AudioInjector* injector) {
|
|||
|
||||
bool AudioInjectorManager::restartFinishedInjector(AudioInjector* injector) {
|
||||
if (_shouldStop) {
|
||||
qDebug() << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down.";
|
||||
qCDebug(audio) << "AudioInjectorManager::threadInjector asked to thread injector but is shutting down.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,6 +211,49 @@ static inline int32_t peaklog2(float* input0, float* input1) {
|
|||
return (e << LOG2_FRACBITS) - (c2 >> 3);
|
||||
}
|
||||
|
||||
//
|
||||
// Peak detection and -log2(x) for float input (quad)
|
||||
// x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff
|
||||
// x > 2^LOG2_HEADROOM undefined
|
||||
//
|
||||
static inline int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) {
|
||||
|
||||
// float as integer bits
|
||||
int32_t u0 = *(int32_t*)input0;
|
||||
int32_t u1 = *(int32_t*)input1;
|
||||
int32_t u2 = *(int32_t*)input2;
|
||||
int32_t u3 = *(int32_t*)input3;
|
||||
|
||||
// max absolute value
|
||||
u0 &= IEEE754_FABS_MASK;
|
||||
u1 &= IEEE754_FABS_MASK;
|
||||
u2 &= IEEE754_FABS_MASK;
|
||||
u3 &= IEEE754_FABS_MASK;
|
||||
int32_t peak = MAX(MAX(u0, u1), MAX(u2, u3));
|
||||
|
||||
// split into e and x - 1.0
|
||||
int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM;
|
||||
int32_t x = (peak << (31 - IEEE754_MANT_BITS)) & 0x7fffffff;
|
||||
|
||||
// saturate
|
||||
if (e > 31) {
|
||||
return 0x7fffffff;
|
||||
}
|
||||
|
||||
int k = x >> (31 - LOG2_TABBITS);
|
||||
|
||||
// polynomial for log2(1+x) over x=[0,1]
|
||||
int32_t c0 = log2Table[k][0];
|
||||
int32_t c1 = log2Table[k][1];
|
||||
int32_t c2 = log2Table[k][2];
|
||||
|
||||
c1 += MULHI(c0, x);
|
||||
c2 += MULHI(c1, x);
|
||||
|
||||
// reconstruct result in Q26
|
||||
return (e << LOG2_FRACBITS) - (c2 >> 3);
|
||||
}
|
||||
|
||||
//
|
||||
// Compute exp2(-x) for x=[0,32] in Q26, result in Q31
|
||||
// x < 0 undefined
|
||||
|
@ -258,7 +301,7 @@ class PeakFilterT {
|
|||
static_assert((CIC1 - 1) + (CIC2 - 1) == (N - 1), "Total CIC delay must be N-1");
|
||||
|
||||
int32_t _buffer[2*N] = {}; // shared FIFO
|
||||
int _index = 0;
|
||||
size_t _index = 0;
|
||||
|
||||
int32_t _acc1 = 0; // CIC1 integrator
|
||||
int32_t _acc2 = 0; // CIC2 integrator
|
||||
|
@ -267,21 +310,21 @@ public:
|
|||
PeakFilterT() {
|
||||
|
||||
// fill history
|
||||
for (int n = 0; n < N-1; n++) {
|
||||
for (size_t n = 0; n < N-1; n++) {
|
||||
process(0x7fffffff);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t process(int32_t x) {
|
||||
|
||||
const int MASK = 2*N - 1; // buffer wrap
|
||||
int i = _index;
|
||||
const size_t MASK = 2*N - 1; // buffer wrap
|
||||
size_t i = _index;
|
||||
|
||||
// Fast peak-hold using a running-min filter. Finds the peak (min) value
|
||||
// in the sliding window of N-1 samples, using only log2(N) comparisons.
|
||||
// Hold time of N-1 samples exactly cancels the step response of FIR filter.
|
||||
|
||||
for (int n = 1; n < N; n <<= 1) {
|
||||
for (size_t n = 1; n < N; n <<= 1) {
|
||||
|
||||
_buffer[i] = x;
|
||||
i = (i + n) & MASK;
|
||||
|
@ -329,13 +372,13 @@ class MonoDelay {
|
|||
static_assert((N & (N - 1)) == 0, "N must be a power of 2");
|
||||
|
||||
float _buffer[N] = {};
|
||||
int _index = 0;
|
||||
size_t _index = 0;
|
||||
|
||||
public:
|
||||
void process(float& x) {
|
||||
|
||||
const int MASK = N - 1; // buffer wrap
|
||||
int i = _index;
|
||||
const size_t MASK = N - 1; // buffer wrap
|
||||
size_t i = _index;
|
||||
|
||||
_buffer[i] = x;
|
||||
|
||||
|
@ -356,13 +399,13 @@ class StereoDelay {
|
|||
static_assert((N & (N - 1)) == 0, "N must be a power of 2");
|
||||
|
||||
float _buffer[2*N] = {};
|
||||
int _index = 0;
|
||||
size_t _index = 0;
|
||||
|
||||
public:
|
||||
void process(float& x0, float& x1) {
|
||||
|
||||
const int MASK = 2*N - 1; // buffer wrap
|
||||
int i = _index;
|
||||
const size_t MASK = 2*N - 1; // buffer wrap
|
||||
size_t i = _index;
|
||||
|
||||
_buffer[i+0] = x0;
|
||||
_buffer[i+1] = x1;
|
||||
|
@ -376,6 +419,39 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// N-1 sample delay (quad)
|
||||
//
|
||||
template<int N>
|
||||
class QuadDelay {
|
||||
|
||||
static_assert((N & (N - 1)) == 0, "N must be a power of 2");
|
||||
|
||||
float _buffer[4*N] = {};
|
||||
size_t _index = 0;
|
||||
|
||||
public:
|
||||
void process(float& x0, float& x1, float& x2, float& x3) {
|
||||
|
||||
const size_t MASK = 4*N - 1; // buffer wrap
|
||||
size_t i = _index;
|
||||
|
||||
_buffer[i+0] = x0;
|
||||
_buffer[i+1] = x1;
|
||||
_buffer[i+2] = x2;
|
||||
_buffer[i+3] = x3;
|
||||
|
||||
i = (i + 4*(N - 1)) & MASK;
|
||||
|
||||
x0 = _buffer[i+0];
|
||||
x1 = _buffer[i+1];
|
||||
x2 = _buffer[i+2];
|
||||
x3 = _buffer[i+3];
|
||||
|
||||
_index = i;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Limiter (common)
|
||||
//
|
||||
|
@ -428,7 +504,7 @@ LimiterImpl::LimiterImpl(int sampleRate) {
|
|||
//
|
||||
void LimiterImpl::setThreshold(float threshold) {
|
||||
|
||||
const double OUT_CEILING = -0.3;
|
||||
const double OUT_CEILING = -0.3; // cannot be 0.0, due to dither
|
||||
const double Q31_TO_Q15 = 32768 / 2147483648.0;
|
||||
|
||||
// limiter threshold = -48dB to 0dB
|
||||
|
@ -537,12 +613,12 @@ int32_t LimiterImpl::envelope(int32_t attn) {
|
|||
// arc = (attn-rms)*6/attn for attn = 1dB to 6dB
|
||||
// arc = (attn-rms)*6/6 for attn > 6dB
|
||||
|
||||
int bits = MIN(attn >> 20, 0x3f); // saturate 1/attn at 6dB
|
||||
_arc = MAX(attn - _rms, 0); // peak/rms = (attn-rms)
|
||||
_arc = MULHI(_arc, invTable[bits]); // normalized peak/rms = (attn-rms)/attn
|
||||
_arc = MIN(_arc, NARC - 1); // saturate at 6dB
|
||||
size_t bits = MIN(attn >> 20, 0x3f); // saturate 1/attn at 6dB
|
||||
_arc = MAX(attn - _rms, 0); // peak/rms = (attn-rms)
|
||||
_arc = MULHI(_arc, invTable[bits]); // normalized peak/rms = (attn-rms)/attn
|
||||
_arc = MIN(_arc, NARC - 1); // saturate at 6dB
|
||||
|
||||
_arcRelease = 0x7fffffff; // reset release
|
||||
_arcRelease = 0x7fffffff; // reset release
|
||||
}
|
||||
_attn = attn;
|
||||
|
||||
|
@ -571,8 +647,8 @@ public:
|
|||
};
|
||||
|
||||
template<int N>
|
||||
void LimiterMono<N>::process(float* input, int16_t* output, int numFrames)
|
||||
{
|
||||
void LimiterMono<N>::process(float* input, int16_t* output, int numFrames) {
|
||||
|
||||
for (int n = 0; n < numFrames; n++) {
|
||||
|
||||
// peak detect and convert to log2 domain
|
||||
|
@ -623,8 +699,8 @@ public:
|
|||
};
|
||||
|
||||
template<int N>
|
||||
void LimiterStereo<N>::process(float* input, int16_t* output, int numFrames)
|
||||
{
|
||||
void LimiterStereo<N>::process(float* input, int16_t* output, int numFrames) {
|
||||
|
||||
for (int n = 0; n < numFrames; n++) {
|
||||
|
||||
// peak detect and convert to log2 domain
|
||||
|
@ -663,6 +739,71 @@ void LimiterStereo<N>::process(float* input, int16_t* output, int numFrames)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Limiter (quad)
|
||||
//
|
||||
template<int N>
|
||||
class LimiterQuad : public LimiterImpl {
|
||||
|
||||
PeakFilter<N> _filter;
|
||||
QuadDelay<N> _delay;
|
||||
|
||||
public:
|
||||
LimiterQuad(int sampleRate) : LimiterImpl(sampleRate) {}
|
||||
|
||||
// interleaved quad input/output
|
||||
void process(float* input, int16_t* output, int numFrames) override;
|
||||
};
|
||||
|
||||
template<int N>
|
||||
void LimiterQuad<N>::process(float* input, int16_t* output, int numFrames) {
|
||||
|
||||
for (int n = 0; n < numFrames; n++) {
|
||||
|
||||
// peak detect and convert to log2 domain
|
||||
int32_t peak = peaklog2(&input[4*n+0], &input[4*n+1], &input[4*n+2], &input[4*n+3]);
|
||||
|
||||
// compute limiter attenuation
|
||||
int32_t attn = MAX(_threshold - peak, 0);
|
||||
|
||||
// apply envelope
|
||||
attn = envelope(attn);
|
||||
|
||||
// convert from log2 domain
|
||||
attn = fixexp2(attn);
|
||||
|
||||
// lowpass filter
|
||||
attn = _filter.process(attn);
|
||||
float gain = attn * _outGain;
|
||||
|
||||
// delay audio
|
||||
float x0 = input[4*n+0];
|
||||
float x1 = input[4*n+1];
|
||||
float x2 = input[4*n+2];
|
||||
float x3 = input[4*n+3];
|
||||
_delay.process(x0, x1, x2, x3);
|
||||
|
||||
// apply gain
|
||||
x0 *= gain;
|
||||
x1 *= gain;
|
||||
x2 *= gain;
|
||||
x3 *= gain;
|
||||
|
||||
// apply dither
|
||||
float d = dither();
|
||||
x0 += d;
|
||||
x1 += d;
|
||||
x2 += d;
|
||||
x3 += d;
|
||||
|
||||
// store 16-bit output
|
||||
output[4*n+0] = (int16_t)floatToInt(x0);
|
||||
output[4*n+1] = (int16_t)floatToInt(x1);
|
||||
output[4*n+2] = (int16_t)floatToInt(x2);
|
||||
output[4*n+3] = (int16_t)floatToInt(x3);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Public API
|
||||
//
|
||||
|
@ -695,6 +836,19 @@ AudioLimiter::AudioLimiter(int sampleRate, int numChannels) {
|
|||
_impl = new LimiterStereo<128>(sampleRate);
|
||||
}
|
||||
|
||||
} else if (numChannels == 4) {
|
||||
|
||||
// ~1.5ms lookahead for all rates
|
||||
if (sampleRate < 16000) {
|
||||
_impl = new LimiterQuad<16>(sampleRate);
|
||||
} else if (sampleRate < 32000) {
|
||||
_impl = new LimiterQuad<32>(sampleRate);
|
||||
} else if (sampleRate < 64000) {
|
||||
_impl = new LimiterQuad<64>(sampleRate);
|
||||
} else {
|
||||
_impl = new LimiterQuad<128>(sampleRate);
|
||||
}
|
||||
|
||||
} else {
|
||||
assert(0); // unsupported
|
||||
}
|
||||
|
|
|
@ -99,18 +99,22 @@ static void cubicInterpolation(const float* input, float* output, int inputSize,
|
|||
}
|
||||
}
|
||||
|
||||
int AudioSRC::createRationalFilter(int upFactor, int downFactor, float gain) {
|
||||
int numTaps = PROTOTYPE_TAPS;
|
||||
int AudioSRC::createRationalFilter(int upFactor, int downFactor, float gain, Quality quality) {
|
||||
|
||||
int prototypeTaps = prototypeFilterTable[quality].taps;
|
||||
int prototypeCoefs = prototypeFilterTable[quality].coefs;
|
||||
const float* prototypeFilter = prototypeFilterTable[quality].filter;
|
||||
|
||||
int numTaps = prototypeTaps;
|
||||
int numPhases = upFactor;
|
||||
int numCoefs = numTaps * numPhases;
|
||||
int oldCoefs = numCoefs;
|
||||
int prototypeCoefs = PROTOTYPE_TAPS * PROTOTYPE_PHASES;
|
||||
|
||||
//
|
||||
// When downsampling, we can lower the filter cutoff by downFactor/upFactor using the
|
||||
// time-scaling property of the Fourier transform. The gain is adjusted accordingly.
|
||||
//
|
||||
if (downFactor > upFactor) {
|
||||
int oldCoefs = numCoefs;
|
||||
numCoefs = ((int64_t)oldCoefs * downFactor) / upFactor;
|
||||
numTaps = (numCoefs + upFactor - 1) / upFactor;
|
||||
gain *= (float)oldCoefs / numCoefs;
|
||||
|
@ -149,18 +153,22 @@ int AudioSRC::createRationalFilter(int upFactor, int downFactor, float gain) {
|
|||
return numTaps;
|
||||
}
|
||||
|
||||
int AudioSRC::createIrrationalFilter(int upFactor, int downFactor, float gain) {
|
||||
int numTaps = PROTOTYPE_TAPS;
|
||||
int AudioSRC::createIrrationalFilter(int upFactor, int downFactor, float gain, Quality quality) {
|
||||
|
||||
int prototypeTaps = prototypeFilterTable[quality].taps;
|
||||
int prototypeCoefs = prototypeFilterTable[quality].coefs;
|
||||
const float* prototypeFilter = prototypeFilterTable[quality].filter;
|
||||
|
||||
int numTaps = prototypeTaps;
|
||||
int numPhases = upFactor;
|
||||
int numCoefs = numTaps * numPhases;
|
||||
int oldCoefs = numCoefs;
|
||||
int prototypeCoefs = PROTOTYPE_TAPS * PROTOTYPE_PHASES;
|
||||
|
||||
//
|
||||
// When downsampling, we can lower the filter cutoff by downFactor/upFactor using the
|
||||
// time-scaling property of the Fourier transform. The gain is adjusted accordingly.
|
||||
//
|
||||
if (downFactor > upFactor) {
|
||||
int oldCoefs = numCoefs;
|
||||
numCoefs = ((int64_t)oldCoefs * downFactor) / upFactor;
|
||||
numTaps = (numCoefs + upFactor - 1) / upFactor;
|
||||
gain *= (float)oldCoefs / numCoefs;
|
||||
|
@ -1405,7 +1413,8 @@ int AudioSRC::render(float** inputs, float** outputs, int inputFrames) {
|
|||
return outputFrames;
|
||||
}
|
||||
|
||||
AudioSRC::AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels) {
|
||||
AudioSRC::AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels, Quality quality) {
|
||||
|
||||
assert(inputSampleRate > 0);
|
||||
assert(outputSampleRate > 0);
|
||||
assert(numChannels > 0);
|
||||
|
@ -1433,9 +1442,9 @@ AudioSRC::AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels) {
|
|||
|
||||
// create the polyphase filter
|
||||
if (_step == 0) {
|
||||
_numTaps = createRationalFilter(_upFactor, _downFactor, 1.0f);
|
||||
_numTaps = createRationalFilter(_upFactor, _downFactor, 1.0f, quality);
|
||||
} else {
|
||||
_numTaps = createIrrationalFilter(_upFactor, _downFactor, 1.0f);
|
||||
_numTaps = createIrrationalFilter(_upFactor, _downFactor, 1.0f, quality);
|
||||
}
|
||||
|
||||
//printf("up=%d down=%.3f taps=%d\n", _upFactor, _downFactor + (LO32(_step)<<SRC_PHASEBITS) * Q32_TO_FLOAT, _numTaps);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
static const int SRC_MAX_CHANNELS = 4;
|
||||
|
||||
// polyphase filter
|
||||
static const int SRC_PHASEBITS = 8;
|
||||
static const int SRC_PHASEBITS = 9;
|
||||
static const int SRC_PHASES = (1 << SRC_PHASEBITS);
|
||||
static const int SRC_FRACBITS = 32 - SRC_PHASEBITS;
|
||||
static const uint32_t SRC_FRACMASK = (1 << SRC_FRACBITS) - 1;
|
||||
|
@ -31,7 +31,13 @@ static const int SRC_BLOCK = 256;
|
|||
class AudioSRC {
|
||||
|
||||
public:
|
||||
AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels);
|
||||
enum Quality {
|
||||
LOW_QUALITY,
|
||||
MEDIUM_QUALITY,
|
||||
HIGH_QUALITY
|
||||
};
|
||||
|
||||
AudioSRC(int inputSampleRate, int outputSampleRate, int numChannels, Quality quality = MEDIUM_QUALITY);
|
||||
~AudioSRC();
|
||||
|
||||
// deinterleaved float input/output (native format)
|
||||
|
@ -70,8 +76,8 @@ private:
|
|||
int64_t _offset;
|
||||
int64_t _step;
|
||||
|
||||
int createRationalFilter(int upFactor, int downFactor, float gain);
|
||||
int createIrrationalFilter(int upFactor, int downFactor, float gain);
|
||||
int createRationalFilter(int upFactor, int downFactor, float gain, Quality quality);
|
||||
int createIrrationalFilter(int upFactor, int downFactor, float gain, Quality quality);
|
||||
|
||||
int multirateFilter1(const float* input0, float* output0, int inputFrames);
|
||||
int multirateFilter2(const float* input0, const float* input1, float* output0, float* output1, int inputFrames);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -153,7 +153,7 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
auto afterProperties = message.readWithoutCopy(message.getBytesLeftToRead());
|
||||
parseAudioData(message.getType(), afterProperties);
|
||||
} else {
|
||||
qDebug() << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
|
||||
writeDroppableSilentFrames(networkFrames);
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
//
|
||||
// AudioHRTF_avx.cpp
|
||||
// libraries/audio/src/avx
|
||||
//
|
||||
// Created by Ken Cooke on 1/17/16.
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
#include <assert.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "../AudioHRTF.h"
|
||||
|
||||
#ifndef __AVX__
|
||||
#error Must be compiled with /arch:AVX or -mavx.
|
||||
#endif
|
||||
|
||||
// 1 channel input, 4 channel output
|
||||
void FIR_1x4_AVX(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) {
|
||||
|
||||
float* coef0 = coef[0] + HRTF_TAPS - 1; // process backwards
|
||||
float* coef1 = coef[1] + HRTF_TAPS - 1;
|
||||
float* coef2 = coef[2] + HRTF_TAPS - 1;
|
||||
float* coef3 = coef[3] + HRTF_TAPS - 1;
|
||||
|
||||
assert(numFrames % 8 == 0);
|
||||
|
||||
for (int i = 0; i < numFrames; i += 8) {
|
||||
|
||||
__m256 acc0 = _mm256_setzero_ps();
|
||||
__m256 acc1 = _mm256_setzero_ps();
|
||||
__m256 acc2 = _mm256_setzero_ps();
|
||||
__m256 acc3 = _mm256_setzero_ps();
|
||||
|
||||
float* ps = &src[i - HRTF_TAPS + 1]; // process forwards
|
||||
|
||||
assert(HRTF_TAPS % 8 == 0);
|
||||
|
||||
for (int k = 0; k < HRTF_TAPS; k += 8) {
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-0]), _mm256_loadu_ps(&ps[k+0])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-0]), _mm256_loadu_ps(&ps[k+0])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-0]), _mm256_loadu_ps(&ps[k+0])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-0]), _mm256_loadu_ps(&ps[k+0])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-1]), _mm256_loadu_ps(&ps[k+1])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-1]), _mm256_loadu_ps(&ps[k+1])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-1]), _mm256_loadu_ps(&ps[k+1])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-1]), _mm256_loadu_ps(&ps[k+1])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-2]), _mm256_loadu_ps(&ps[k+2])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-2]), _mm256_loadu_ps(&ps[k+2])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-2]), _mm256_loadu_ps(&ps[k+2])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-2]), _mm256_loadu_ps(&ps[k+2])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-3]), _mm256_loadu_ps(&ps[k+3])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-3]), _mm256_loadu_ps(&ps[k+3])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-3]), _mm256_loadu_ps(&ps[k+3])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-3]), _mm256_loadu_ps(&ps[k+3])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-4]), _mm256_loadu_ps(&ps[k+4])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-4]), _mm256_loadu_ps(&ps[k+4])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-4]), _mm256_loadu_ps(&ps[k+4])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-4]), _mm256_loadu_ps(&ps[k+4])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-5]), _mm256_loadu_ps(&ps[k+5])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-5]), _mm256_loadu_ps(&ps[k+5])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-5]), _mm256_loadu_ps(&ps[k+5])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-5]), _mm256_loadu_ps(&ps[k+5])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-6]), _mm256_loadu_ps(&ps[k+6])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-6]), _mm256_loadu_ps(&ps[k+6])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-6]), _mm256_loadu_ps(&ps[k+6])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-6]), _mm256_loadu_ps(&ps[k+6])));
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, _mm256_mul_ps(_mm256_broadcast_ss(&coef0[-k-7]), _mm256_loadu_ps(&ps[k+7])));
|
||||
acc1 = _mm256_add_ps(acc1, _mm256_mul_ps(_mm256_broadcast_ss(&coef1[-k-7]), _mm256_loadu_ps(&ps[k+7])));
|
||||
acc2 = _mm256_add_ps(acc2, _mm256_mul_ps(_mm256_broadcast_ss(&coef2[-k-7]), _mm256_loadu_ps(&ps[k+7])));
|
||||
acc3 = _mm256_add_ps(acc3, _mm256_mul_ps(_mm256_broadcast_ss(&coef3[-k-7]), _mm256_loadu_ps(&ps[k+7])));
|
||||
}
|
||||
|
||||
_mm256_storeu_ps(&dst0[i], acc0);
|
||||
_mm256_storeu_ps(&dst1[i], acc1);
|
||||
_mm256_storeu_ps(&dst2[i], acc2);
|
||||
_mm256_storeu_ps(&dst3[i], acc3);
|
||||
}
|
||||
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
|
||||
#endif
|
94
libraries/audio/src/avx2/AudioHRTF_avx2.cpp
Normal file
94
libraries/audio/src/avx2/AudioHRTF_avx2.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
//
|
||||
// AudioHRTF_avx2.cpp
|
||||
// libraries/audio/src
|
||||
//
|
||||
// Created by Ken Cooke on 1/17/16.
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
#include <assert.h>
|
||||
#include <immintrin.h> // AVX2
|
||||
|
||||
#include "../AudioHRTF.h"
|
||||
|
||||
#ifndef __AVX2__
|
||||
#error Must be compiled with /arch:AVX2 or -mavx2 -mfma.
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
// for some reason, GCC -O2 results in poorly optimized code
|
||||
#pragma GCC optimize("Os")
|
||||
#endif
|
||||
|
||||
// 1 channel input, 4 channel output
|
||||
void FIR_1x4_AVX2(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) {
|
||||
|
||||
float* coef0 = coef[0] + HRTF_TAPS - 1; // process backwards
|
||||
float* coef1 = coef[1] + HRTF_TAPS - 1;
|
||||
float* coef2 = coef[2] + HRTF_TAPS - 1;
|
||||
float* coef3 = coef[3] + HRTF_TAPS - 1;
|
||||
|
||||
assert(numFrames % 8 == 0);
|
||||
|
||||
for (int i = 0; i < numFrames; i += 8) {
|
||||
|
||||
__m256 acc0 = _mm256_setzero_ps();
|
||||
__m256 acc1 = _mm256_setzero_ps();
|
||||
__m256 acc2 = _mm256_setzero_ps();
|
||||
__m256 acc3 = _mm256_setzero_ps();
|
||||
__m256 acc4 = _mm256_setzero_ps();
|
||||
__m256 acc5 = _mm256_setzero_ps();
|
||||
__m256 acc6 = _mm256_setzero_ps();
|
||||
__m256 acc7 = _mm256_setzero_ps();
|
||||
|
||||
float* ps = &src[i - HRTF_TAPS + 1]; // process forwards
|
||||
|
||||
assert(HRTF_TAPS % 4 == 0);
|
||||
|
||||
for (int k = 0; k < HRTF_TAPS; k += 4) {
|
||||
|
||||
__m256 x0 = _mm256_loadu_ps(&ps[k+0]);
|
||||
acc0 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef0[-k-0]), x0, acc0);
|
||||
acc1 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef1[-k-0]), x0, acc1);
|
||||
acc2 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef2[-k-0]), x0, acc2);
|
||||
acc3 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef3[-k-0]), x0, acc3);
|
||||
|
||||
__m256 x1 = _mm256_loadu_ps(&ps[k+1]);
|
||||
acc4 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef0[-k-1]), x1, acc4);
|
||||
acc5 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef1[-k-1]), x1, acc5);
|
||||
acc6 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef2[-k-1]), x1, acc6);
|
||||
acc7 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef3[-k-1]), x1, acc7);
|
||||
|
||||
__m256 x2 = _mm256_loadu_ps(&ps[k+2]);
|
||||
acc0 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef0[-k-2]), x2, acc0);
|
||||
acc1 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef1[-k-2]), x2, acc1);
|
||||
acc2 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef2[-k-2]), x2, acc2);
|
||||
acc3 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef3[-k-2]), x2, acc3);
|
||||
|
||||
__m256 x3 = _mm256_loadu_ps(&ps[k+3]);
|
||||
acc4 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef0[-k-3]), x3, acc4);
|
||||
acc5 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef1[-k-3]), x3, acc5);
|
||||
acc6 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef2[-k-3]), x3, acc6);
|
||||
acc7 = _mm256_fmadd_ps(_mm256_broadcast_ss(&coef3[-k-3]), x3, acc7);
|
||||
}
|
||||
|
||||
acc0 = _mm256_add_ps(acc0, acc4);
|
||||
acc1 = _mm256_add_ps(acc1, acc5);
|
||||
acc2 = _mm256_add_ps(acc2, acc6);
|
||||
acc3 = _mm256_add_ps(acc3, acc7);
|
||||
|
||||
_mm256_storeu_ps(&dst0[i], acc0);
|
||||
_mm256_storeu_ps(&dst1[i], acc1);
|
||||
_mm256_storeu_ps(&dst2[i], acc2);
|
||||
_mm256_storeu_ps(&dst3[i], acc3);
|
||||
}
|
||||
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -50,9 +50,20 @@ const glm::vec3 DEFAULT_LOCAL_AABOX_SCALE(1.0f);
|
|||
const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData";
|
||||
|
||||
namespace AvatarDataPacket {
|
||||
|
||||
// NOTE: AvatarDataPackets start with a uint16_t sequence number that is not reflected in the Header structure.
|
||||
|
||||
PACKED_BEGIN struct Header {
|
||||
uint8_t packetStateFlags; // state flags, currently used to indicate if the packet is a minimal or fuller packet
|
||||
} PACKED_END;
|
||||
const size_t HEADER_SIZE = 1;
|
||||
|
||||
PACKED_BEGIN struct MinimalAvatarInfo {
|
||||
float globalPosition[3]; // avatar's position
|
||||
} PACKED_END;
|
||||
const size_t MINIMAL_AVATAR_INFO_SIZE = 12;
|
||||
|
||||
PACKED_BEGIN struct AvatarInfo {
|
||||
float position[3]; // skeletal model's position
|
||||
float globalPosition[3]; // avatar's position
|
||||
float globalBoundingBoxCorner[3]; // global position of the lowest corner of the avatar's bounding box
|
||||
|
@ -65,16 +76,16 @@ namespace AvatarDataPacket {
|
|||
float sensorToWorldTrans[3]; // fourth column of sensor to world matrix
|
||||
uint8_t flags;
|
||||
} PACKED_END;
|
||||
const size_t HEADER_SIZE = 81;
|
||||
const size_t AVATAR_INFO_SIZE = 81;
|
||||
|
||||
// only present if HAS_REFERENTIAL flag is set in header.flags
|
||||
// only present if HAS_REFERENTIAL flag is set in AvatarInfo.flags
|
||||
PACKED_BEGIN struct ParentInfo {
|
||||
uint8_t parentUUID[16]; // rfc 4122 encoded
|
||||
uint16_t parentJointIndex;
|
||||
} PACKED_END;
|
||||
const size_t PARENT_INFO_SIZE = 18;
|
||||
|
||||
// only present if IS_FACESHIFT_CONNECTED flag is set in header.flags
|
||||
// only present if IS_FACESHIFT_CONNECTED flag is set in AvatarInfo.flags
|
||||
PACKED_BEGIN struct FaceTrackerInfo {
|
||||
float leftEyeBlink;
|
||||
float rightEyeBlink;
|
||||
|
@ -124,6 +135,8 @@ AvatarData::AvatarData() :
|
|||
setBodyRoll(0.0f);
|
||||
|
||||
ASSERT(sizeof(AvatarDataPacket::Header) == AvatarDataPacket::HEADER_SIZE);
|
||||
ASSERT(sizeof(AvatarDataPacket::MinimalAvatarInfo) == AvatarDataPacket::MINIMAL_AVATAR_INFO_SIZE);
|
||||
ASSERT(sizeof(AvatarDataPacket::AvatarInfo) == AvatarDataPacket::AVATAR_INFO_SIZE);
|
||||
ASSERT(sizeof(AvatarDataPacket::ParentInfo) == AvatarDataPacket::PARENT_INFO_SIZE);
|
||||
ASSERT(sizeof(AvatarDataPacket::FaceTrackerInfo) == AvatarDataPacket::FACE_TRACKER_INFO_SIZE);
|
||||
}
|
||||
|
@ -132,9 +145,9 @@ AvatarData::~AvatarData() {
|
|||
delete _headData;
|
||||
}
|
||||
|
||||
// We cannot have a file-level variable (const or otherwise) in the header if it uses PathUtils, because that references Application, which will not yet initialized.
|
||||
// We cannot have a file-level variable (const or otherwise) in the AvatarInfo if it uses PathUtils, because that references Application, which will not yet initialized.
|
||||
// Thus we have a static class getter, referencing a static class var.
|
||||
QUrl AvatarData::_defaultFullAvatarModelUrl = {}; // In C++, if this initialization were in the header, every file would have it's own copy, even for class vars.
|
||||
QUrl AvatarData::_defaultFullAvatarModelUrl = {}; // In C++, if this initialization were in the AvatarInfo, every file would have it's own copy, even for class vars.
|
||||
const QUrl& AvatarData::defaultFullAvatarModelUrl() {
|
||||
if (_defaultFullAvatarModelUrl.isEmpty()) {
|
||||
_defaultFullAvatarModelUrl = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst");
|
||||
|
@ -147,14 +160,14 @@ void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
|||
bool success;
|
||||
Transform trans = getTransform(success);
|
||||
if (!success) {
|
||||
qDebug() << "Warning -- AvatarData::nextAttitude failed";
|
||||
qCWarning(avatars) << "Warning -- AvatarData::nextAttitude failed";
|
||||
return;
|
||||
}
|
||||
trans.setTranslation(position);
|
||||
trans.setRotation(orientation);
|
||||
SpatiallyNestable::setTransform(trans, success);
|
||||
if (!success) {
|
||||
qDebug() << "Warning -- AvatarData::nextAttitude failed";
|
||||
qCWarning(avatars) << "Warning -- AvatarData::nextAttitude failed";
|
||||
}
|
||||
updateAttitude();
|
||||
}
|
||||
|
@ -181,7 +194,11 @@ void AvatarData::setHandPosition(const glm::vec3& handPosition) {
|
|||
_handPosition = glm::inverse(getOrientation()) * (handPosition - getPosition());
|
||||
}
|
||||
|
||||
QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||
|
||||
QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
|
||||
bool cullSmallChanges = (dataDetail == CullSmallData);
|
||||
bool sendAll = (dataDetail == SendAllData);
|
||||
bool sendMinimum = (dataDetail == MinimumData);
|
||||
// TODO: DRY this up to a shared method
|
||||
// that can pack any type given the number of bytes
|
||||
// and return the number of bytes to push the pointer
|
||||
|
@ -199,207 +216,221 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
|||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(avatarDataByteArray.data());
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
|
||||
auto header = reinterpret_cast<AvatarDataPacket::Header*>(destinationBuffer);
|
||||
header->position[0] = getLocalPosition().x;
|
||||
header->position[1] = getLocalPosition().y;
|
||||
header->position[2] = getLocalPosition().z;
|
||||
header->globalPosition[0] = _globalPosition.x;
|
||||
header->globalPosition[1] = _globalPosition.y;
|
||||
header->globalPosition[2] = _globalPosition.z;
|
||||
header->globalBoundingBoxCorner[0] = getPosition().x - _globalBoundingBoxCorner.x;
|
||||
header->globalBoundingBoxCorner[1] = getPosition().y - _globalBoundingBoxCorner.y;
|
||||
header->globalBoundingBoxCorner[2] = getPosition().z - _globalBoundingBoxCorner.z;
|
||||
|
||||
glm::vec3 bodyEulerAngles = glm::degrees(safeEulerAngles(getLocalOrientation()));
|
||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 0), bodyEulerAngles.y);
|
||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 1), bodyEulerAngles.x);
|
||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 2), bodyEulerAngles.z);
|
||||
packFloatRatioToTwoByte((uint8_t*)(&header->scale), getDomainLimitedScale());
|
||||
header->lookAtPosition[0] = _headData->_lookAtPosition.x;
|
||||
header->lookAtPosition[1] = _headData->_lookAtPosition.y;
|
||||
header->lookAtPosition[2] = _headData->_lookAtPosition.z;
|
||||
header->audioLoudness = _headData->_audioLoudness;
|
||||
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
packOrientationQuatToSixBytes(header->sensorToWorldQuat, glmExtractRotation(sensorToWorldMatrix));
|
||||
glm::vec3 scale = extractScale(sensorToWorldMatrix);
|
||||
packFloatScalarToSignedTwoByteFixed((uint8_t*)&header->sensorToWorldScale, scale.x, SENSOR_TO_WORLD_SCALE_RADIX);
|
||||
header->sensorToWorldTrans[0] = sensorToWorldMatrix[3][0];
|
||||
header->sensorToWorldTrans[1] = sensorToWorldMatrix[3][1];
|
||||
header->sensorToWorldTrans[2] = sensorToWorldMatrix[3][2];
|
||||
|
||||
setSemiNibbleAt(header->flags, KEY_STATE_START_BIT, _keyState);
|
||||
// hand state
|
||||
bool isFingerPointing = _handState & IS_FINGER_POINTING_FLAG;
|
||||
setSemiNibbleAt(header->flags, HAND_STATE_START_BIT, _handState & ~IS_FINGER_POINTING_FLAG);
|
||||
if (isFingerPointing) {
|
||||
setAtBit(header->flags, HAND_STATE_FINGER_POINTING_BIT);
|
||||
}
|
||||
// faceshift state
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
setAtBit(header->flags, IS_FACESHIFT_CONNECTED);
|
||||
}
|
||||
// eye tracker state
|
||||
if (_headData->_isEyeTrackerConnected) {
|
||||
setAtBit(header->flags, IS_EYE_TRACKER_CONNECTED);
|
||||
}
|
||||
// referential state
|
||||
QUuid parentID = getParentID();
|
||||
if (!parentID.isNull()) {
|
||||
setAtBit(header->flags, HAS_REFERENTIAL);
|
||||
}
|
||||
destinationBuffer += sizeof(AvatarDataPacket::Header);
|
||||
|
||||
if (!parentID.isNull()) {
|
||||
auto parentInfo = reinterpret_cast<AvatarDataPacket::ParentInfo*>(destinationBuffer);
|
||||
QByteArray referentialAsBytes = parentID.toRfc4122();
|
||||
memcpy(parentInfo->parentUUID, referentialAsBytes.data(), referentialAsBytes.size());
|
||||
parentInfo->parentJointIndex = _parentJointIndex;
|
||||
destinationBuffer += sizeof(AvatarDataPacket::ParentInfo);
|
||||
// Leading flags, to indicate how much data is actually included in the packet...
|
||||
uint8_t packetStateFlags = 0;
|
||||
if (sendMinimum) {
|
||||
setAtBit(packetStateFlags, AVATARDATA_FLAGS_MINIMUM);
|
||||
}
|
||||
|
||||
// If it is connected, pack up the data
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer);
|
||||
memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags));
|
||||
destinationBuffer += sizeof(packetStateFlags);
|
||||
|
||||
faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink;
|
||||
faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink;
|
||||
faceTrackerInfo->averageLoudness = _headData->_averageLoudness;
|
||||
faceTrackerInfo->browAudioLift = _headData->_browAudioLift;
|
||||
faceTrackerInfo->numBlendshapeCoefficients = _headData->_blendshapeCoefficients.size();
|
||||
destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo);
|
||||
if (sendMinimum) {
|
||||
memcpy(destinationBuffer, &_globalPosition, sizeof(_globalPosition));
|
||||
destinationBuffer += sizeof(_globalPosition);
|
||||
} else {
|
||||
auto avatarInfo = reinterpret_cast<AvatarDataPacket::AvatarInfo*>(destinationBuffer);
|
||||
avatarInfo->position[0] = getLocalPosition().x;
|
||||
avatarInfo->position[1] = getLocalPosition().y;
|
||||
avatarInfo->position[2] = getLocalPosition().z;
|
||||
avatarInfo->globalPosition[0] = _globalPosition.x;
|
||||
avatarInfo->globalPosition[1] = _globalPosition.y;
|
||||
avatarInfo->globalPosition[2] = _globalPosition.z;
|
||||
avatarInfo->globalBoundingBoxCorner[0] = getPosition().x - _globalBoundingBoxCorner.x;
|
||||
avatarInfo->globalBoundingBoxCorner[1] = getPosition().y - _globalBoundingBoxCorner.y;
|
||||
avatarInfo->globalBoundingBoxCorner[2] = getPosition().z - _globalBoundingBoxCorner.z;
|
||||
|
||||
// followed by a variable number of float coefficients
|
||||
memcpy(destinationBuffer, _headData->_blendshapeCoefficients.data(), _headData->_blendshapeCoefficients.size() * sizeof(float));
|
||||
destinationBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float);
|
||||
}
|
||||
glm::vec3 bodyEulerAngles = glm::degrees(safeEulerAngles(getLocalOrientation()));
|
||||
packFloatAngleToTwoByte((uint8_t*)(avatarInfo->localOrientation + 0), bodyEulerAngles.y);
|
||||
packFloatAngleToTwoByte((uint8_t*)(avatarInfo->localOrientation + 1), bodyEulerAngles.x);
|
||||
packFloatAngleToTwoByte((uint8_t*)(avatarInfo->localOrientation + 2), bodyEulerAngles.z);
|
||||
packFloatRatioToTwoByte((uint8_t*)(&avatarInfo->scale), getDomainLimitedScale());
|
||||
avatarInfo->lookAtPosition[0] = _headData->_lookAtPosition.x;
|
||||
avatarInfo->lookAtPosition[1] = _headData->_lookAtPosition.y;
|
||||
avatarInfo->lookAtPosition[2] = _headData->_lookAtPosition.z;
|
||||
avatarInfo->audioLoudness = _headData->_audioLoudness;
|
||||
|
||||
QReadLocker readLock(&_jointDataLock);
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
packOrientationQuatToSixBytes(avatarInfo->sensorToWorldQuat, glmExtractRotation(sensorToWorldMatrix));
|
||||
glm::vec3 scale = extractScale(sensorToWorldMatrix);
|
||||
packFloatScalarToSignedTwoByteFixed((uint8_t*)&avatarInfo->sensorToWorldScale, scale.x, SENSOR_TO_WORLD_SCALE_RADIX);
|
||||
avatarInfo->sensorToWorldTrans[0] = sensorToWorldMatrix[3][0];
|
||||
avatarInfo->sensorToWorldTrans[1] = sensorToWorldMatrix[3][1];
|
||||
avatarInfo->sensorToWorldTrans[2] = sensorToWorldMatrix[3][2];
|
||||
|
||||
// joint rotation data
|
||||
*destinationBuffer++ = _jointData.size();
|
||||
unsigned char* validityPosition = destinationBuffer;
|
||||
unsigned char validity = 0;
|
||||
int validityBit = 0;
|
||||
setSemiNibbleAt(avatarInfo->flags, KEY_STATE_START_BIT, _keyState);
|
||||
// hand state
|
||||
bool isFingerPointing = _handState & IS_FINGER_POINTING_FLAG;
|
||||
setSemiNibbleAt(avatarInfo->flags, HAND_STATE_START_BIT, _handState & ~IS_FINGER_POINTING_FLAG);
|
||||
if (isFingerPointing) {
|
||||
setAtBit(avatarInfo->flags, HAND_STATE_FINGER_POINTING_BIT);
|
||||
}
|
||||
// faceshift state
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
setAtBit(avatarInfo->flags, IS_FACESHIFT_CONNECTED);
|
||||
}
|
||||
// eye tracker state
|
||||
if (_headData->_isEyeTrackerConnected) {
|
||||
setAtBit(avatarInfo->flags, IS_EYE_TRACKER_CONNECTED);
|
||||
}
|
||||
// referential state
|
||||
QUuid parentID = getParentID();
|
||||
if (!parentID.isNull()) {
|
||||
setAtBit(avatarInfo->flags, HAS_REFERENTIAL);
|
||||
}
|
||||
destinationBuffer += sizeof(AvatarDataPacket::AvatarInfo);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
int rotationSentCount = 0;
|
||||
unsigned char* beforeRotations = destinationBuffer;
|
||||
#endif
|
||||
if (!parentID.isNull()) {
|
||||
auto parentInfo = reinterpret_cast<AvatarDataPacket::ParentInfo*>(destinationBuffer);
|
||||
QByteArray referentialAsBytes = parentID.toRfc4122();
|
||||
memcpy(parentInfo->parentUUID, referentialAsBytes.data(), referentialAsBytes.size());
|
||||
parentInfo->parentJointIndex = _parentJointIndex;
|
||||
destinationBuffer += sizeof(AvatarDataPacket::ParentInfo);
|
||||
}
|
||||
|
||||
_lastSentJointData.resize(_jointData.size());
|
||||
// If it is connected, pack up the data
|
||||
if (_headData->_isFaceTrackerConnected) {
|
||||
auto faceTrackerInfo = reinterpret_cast<AvatarDataPacket::FaceTrackerInfo*>(destinationBuffer);
|
||||
|
||||
for (int i=0; i < _jointData.size(); i++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (sendAll || _lastSentJointData[i].rotation != data.rotation) {
|
||||
if (sendAll ||
|
||||
!cullSmallChanges ||
|
||||
fabsf(glm::dot(data.rotation, _lastSentJointData[i].rotation)) <= AVATAR_MIN_ROTATION_DOT) {
|
||||
if (data.rotationSet) {
|
||||
validity |= (1 << validityBit);
|
||||
#ifdef WANT_DEBUG
|
||||
rotationSentCount++;
|
||||
#endif
|
||||
faceTrackerInfo->leftEyeBlink = _headData->_leftEyeBlink;
|
||||
faceTrackerInfo->rightEyeBlink = _headData->_rightEyeBlink;
|
||||
faceTrackerInfo->averageLoudness = _headData->_averageLoudness;
|
||||
faceTrackerInfo->browAudioLift = _headData->_browAudioLift;
|
||||
faceTrackerInfo->numBlendshapeCoefficients = _headData->_blendshapeCoefficients.size();
|
||||
destinationBuffer += sizeof(AvatarDataPacket::FaceTrackerInfo);
|
||||
|
||||
// followed by a variable number of float coefficients
|
||||
memcpy(destinationBuffer, _headData->_blendshapeCoefficients.data(), _headData->_blendshapeCoefficients.size() * sizeof(float));
|
||||
destinationBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float);
|
||||
}
|
||||
|
||||
QReadLocker readLock(&_jointDataLock);
|
||||
|
||||
// joint rotation data
|
||||
*destinationBuffer++ = _jointData.size();
|
||||
unsigned char* validityPosition = destinationBuffer;
|
||||
unsigned char validity = 0;
|
||||
int validityBit = 0;
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
int rotationSentCount = 0;
|
||||
unsigned char* beforeRotations = destinationBuffer;
|
||||
#endif
|
||||
|
||||
_lastSentJointData.resize(_jointData.size());
|
||||
|
||||
for (int i=0; i < _jointData.size(); i++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (sendAll || _lastSentJointData[i].rotation != data.rotation) {
|
||||
if (sendAll ||
|
||||
!cullSmallChanges ||
|
||||
fabsf(glm::dot(data.rotation, _lastSentJointData[i].rotation)) <= AVATAR_MIN_ROTATION_DOT) {
|
||||
if (data.rotationSet) {
|
||||
validity |= (1 << validityBit);
|
||||
#ifdef WANT_DEBUG
|
||||
rotationSentCount++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
*destinationBuffer++ = validity;
|
||||
validityBit = validity = 0;
|
||||
}
|
||||
}
|
||||
if (validityBit != 0) {
|
||||
*destinationBuffer++ = validity;
|
||||
}
|
||||
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
for (int i = 0; i < _jointData.size(); i ++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (validity & (1 << validityBit)) {
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation);
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// joint translation data
|
||||
validityPosition = destinationBuffer;
|
||||
validity = 0;
|
||||
validityBit = 0;
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
int translationSentCount = 0;
|
||||
unsigned char* beforeTranslations = destinationBuffer;
|
||||
#endif
|
||||
|
||||
float maxTranslationDimension = 0.0;
|
||||
for (int i=0; i < _jointData.size(); i++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (sendAll || _lastSentJointData[i].translation != data.translation) {
|
||||
if (sendAll ||
|
||||
!cullSmallChanges ||
|
||||
glm::distance(data.translation, _lastSentJointData[i].translation) > AVATAR_MIN_TRANSLATION) {
|
||||
if (data.translationSet) {
|
||||
validity |= (1 << validityBit);
|
||||
#ifdef WANT_DEBUG
|
||||
translationSentCount++;
|
||||
#endif
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension);
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
*destinationBuffer++ = validity;
|
||||
validityBit = validity = 0;
|
||||
}
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
if (validityBit != 0) {
|
||||
*destinationBuffer++ = validity;
|
||||
validityBit = validity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (validityBit != 0) {
|
||||
*destinationBuffer++ = validity;
|
||||
}
|
||||
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
for (int i = 0; i < _jointData.size(); i ++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (validity & (1 << validityBit)) {
|
||||
destinationBuffer +=
|
||||
packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
for (int i = 0; i < _jointData.size(); i ++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (validity & (1 << validityBit)) {
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation);
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
}
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
|
||||
|
||||
// joint translation data
|
||||
validityPosition = destinationBuffer;
|
||||
validity = 0;
|
||||
validityBit = 0;
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
int translationSentCount = 0;
|
||||
unsigned char* beforeTranslations = destinationBuffer;
|
||||
#endif
|
||||
|
||||
float maxTranslationDimension = 0.0;
|
||||
for (int i=0; i < _jointData.size(); i++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (sendAll || _lastSentJointData[i].translation != data.translation) {
|
||||
if (sendAll ||
|
||||
!cullSmallChanges ||
|
||||
glm::distance(data.translation, _lastSentJointData[i].translation) > AVATAR_MIN_TRANSLATION) {
|
||||
if (data.translationSet) {
|
||||
validity |= (1 << validityBit);
|
||||
#ifdef WANT_DEBUG
|
||||
translationSentCount++;
|
||||
#endif
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
*destinationBuffer++ = validity;
|
||||
validityBit = validity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// faux joints
|
||||
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
if (validityBit != 0) {
|
||||
*destinationBuffer++ = validity;
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
if (sendAll) {
|
||||
qDebug() << "AvatarData::toByteArray" << cullSmallChanges << sendAll
|
||||
<< "rotations:" << rotationSentCount << "translations:" << translationSentCount
|
||||
<< "largest:" << maxTranslationDimension
|
||||
<< "size:"
|
||||
<< (beforeRotations - startPosition) << "+"
|
||||
<< (beforeTranslations - beforeRotations) << "+"
|
||||
<< (destinationBuffer - beforeTranslations) << "="
|
||||
<< (destinationBuffer - startPosition);
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
for (int i = 0; i < _jointData.size(); i ++) {
|
||||
const JointData& data = _jointData[i];
|
||||
if (validity & (1 << validityBit)) {
|
||||
destinationBuffer +=
|
||||
packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
|
||||
}
|
||||
if (++validityBit == BITS_IN_BYTE) {
|
||||
validityBit = 0;
|
||||
validity = *validityPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
// faux joints
|
||||
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
if (sendAll) {
|
||||
qCDebug(avatars) << "AvatarData::toByteArray" << cullSmallChanges << sendAll
|
||||
<< "rotations:" << rotationSentCount << "translations:" << translationSentCount
|
||||
<< "largest:" << maxTranslationDimension
|
||||
<< "size:"
|
||||
<< (beforeRotations - startPosition) << "+"
|
||||
<< (beforeTranslations - beforeRotations) << "+"
|
||||
<< (destinationBuffer - beforeTranslations) << "="
|
||||
<< (destinationBuffer - startPosition);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return avatarDataByteArray.left(destinationBuffer - startPosition);
|
||||
}
|
||||
|
@ -474,18 +505,31 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
_headData = new HeadData(this);
|
||||
}
|
||||
|
||||
uint8_t packetStateFlags = buffer.at(0);
|
||||
bool minimumSent = oneAtBit(packetStateFlags, AVATARDATA_FLAGS_MINIMUM);
|
||||
|
||||
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(buffer.data());
|
||||
const unsigned char* endPosition = startPosition + buffer.size();
|
||||
const unsigned char* sourceBuffer = startPosition;
|
||||
const unsigned char* sourceBuffer = startPosition + sizeof(packetStateFlags); // skip the flags!!
|
||||
|
||||
// if this is the minimum, then it only includes the flags
|
||||
if (minimumSent) {
|
||||
memcpy(&_globalPosition, sourceBuffer, sizeof(_globalPosition));
|
||||
sourceBuffer += sizeof(_globalPosition);
|
||||
int numBytesRead = (sourceBuffer - startPosition);
|
||||
_averageBytesReceived.updateAverage(numBytesRead);
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
PACKET_READ_CHECK(Header, sizeof(AvatarDataPacket::Header));
|
||||
auto header = reinterpret_cast<const AvatarDataPacket::Header*>(sourceBuffer);
|
||||
sourceBuffer += sizeof(AvatarDataPacket::Header);
|
||||
PACKET_READ_CHECK(AvatarInfo, sizeof(AvatarDataPacket::AvatarInfo));
|
||||
auto avatarInfo = reinterpret_cast<const AvatarDataPacket::AvatarInfo*>(sourceBuffer);
|
||||
sourceBuffer += sizeof(AvatarDataPacket::AvatarInfo);
|
||||
|
||||
glm::vec3 position = glm::vec3(header->position[0], header->position[1], header->position[2]);
|
||||
_globalPosition = glm::vec3(header->globalPosition[0], header->globalPosition[1], header->globalPosition[2]);
|
||||
_globalBoundingBoxCorner = glm::vec3(header->globalBoundingBoxCorner[0], header->globalBoundingBoxCorner[1], header->globalBoundingBoxCorner[2]);
|
||||
glm::vec3 position = glm::vec3(avatarInfo->position[0], avatarInfo->position[1], avatarInfo->position[2]);
|
||||
_globalPosition = glm::vec3(avatarInfo->globalPosition[0], avatarInfo->globalPosition[1], avatarInfo->globalPosition[2]);
|
||||
_globalBoundingBoxCorner = glm::vec3(avatarInfo->globalBoundingBoxCorner[0], avatarInfo->globalBoundingBoxCorner[1], avatarInfo->globalBoundingBoxCorner[2]);
|
||||
if (isNaN(position)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCWarning(avatars) << "Discard AvatarData packet: position NaN, uuid " << getSessionUUID();
|
||||
|
@ -495,9 +539,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
setLocalPosition(position);
|
||||
|
||||
float pitch, yaw, roll;
|
||||
unpackFloatAngleFromTwoByte(header->localOrientation + 0, &yaw);
|
||||
unpackFloatAngleFromTwoByte(header->localOrientation + 1, &pitch);
|
||||
unpackFloatAngleFromTwoByte(header->localOrientation + 2, &roll);
|
||||
unpackFloatAngleFromTwoByte(avatarInfo->localOrientation + 0, &yaw);
|
||||
unpackFloatAngleFromTwoByte(avatarInfo->localOrientation + 1, &pitch);
|
||||
unpackFloatAngleFromTwoByte(avatarInfo->localOrientation + 2, &roll);
|
||||
if (isNaN(yaw) || isNaN(pitch) || isNaN(roll)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCWarning(avatars) << "Discard AvatarData packet: localOriention is NaN, uuid " << getSessionUUID();
|
||||
|
@ -514,7 +558,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
|
||||
float scale;
|
||||
unpackFloatRatioFromTwoByte((uint8_t*)&header->scale, scale);
|
||||
unpackFloatRatioFromTwoByte((uint8_t*)&avatarInfo->scale, scale);
|
||||
if (isNaN(scale)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCWarning(avatars) << "Discard AvatarData packet: scale NaN, uuid " << getSessionUUID();
|
||||
|
@ -523,7 +567,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
setTargetScale(scale);
|
||||
|
||||
glm::vec3 lookAt = glm::vec3(header->lookAtPosition[0], header->lookAtPosition[1], header->lookAtPosition[2]);
|
||||
glm::vec3 lookAt = glm::vec3(avatarInfo->lookAtPosition[0], avatarInfo->lookAtPosition[1], avatarInfo->lookAtPosition[2]);
|
||||
if (isNaN(lookAt)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCWarning(avatars) << "Discard AvatarData packet: lookAtPosition is NaN, uuid " << getSessionUUID();
|
||||
|
@ -532,7 +576,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
_headData->_lookAtPosition = lookAt;
|
||||
|
||||
float audioLoudness = header->audioLoudness;
|
||||
float audioLoudness = avatarInfo->audioLoudness;
|
||||
if (isNaN(audioLoudness)) {
|
||||
if (shouldLogError(now)) {
|
||||
qCWarning(avatars) << "Discard AvatarData packet: audioLoudness is NaN, uuid " << getSessionUUID();
|
||||
|
@ -542,16 +586,16 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
_headData->_audioLoudness = audioLoudness;
|
||||
|
||||
glm::quat sensorToWorldQuat;
|
||||
unpackOrientationQuatFromSixBytes(header->sensorToWorldQuat, sensorToWorldQuat);
|
||||
unpackOrientationQuatFromSixBytes(avatarInfo->sensorToWorldQuat, sensorToWorldQuat);
|
||||
float sensorToWorldScale;
|
||||
unpackFloatScalarFromSignedTwoByteFixed((int16_t*)&header->sensorToWorldScale, &sensorToWorldScale, SENSOR_TO_WORLD_SCALE_RADIX);
|
||||
glm::vec3 sensorToWorldTrans(header->sensorToWorldTrans[0], header->sensorToWorldTrans[1], header->sensorToWorldTrans[2]);
|
||||
unpackFloatScalarFromSignedTwoByteFixed((int16_t*)&avatarInfo->sensorToWorldScale, &sensorToWorldScale, SENSOR_TO_WORLD_SCALE_RADIX);
|
||||
glm::vec3 sensorToWorldTrans(avatarInfo->sensorToWorldTrans[0], avatarInfo->sensorToWorldTrans[1], avatarInfo->sensorToWorldTrans[2]);
|
||||
glm::mat4 sensorToWorldMatrix = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), sensorToWorldQuat, sensorToWorldTrans);
|
||||
|
||||
_sensorToWorldMatrixCache.set(sensorToWorldMatrix);
|
||||
|
||||
{ // bitFlags and face data
|
||||
uint8_t bitItems = header->flags;
|
||||
uint8_t bitItems = avatarInfo->flags;
|
||||
|
||||
// key state, stored as a semi-nibble in the bitItems
|
||||
_keyState = (KeyState)getSemiNibbleAt(bitItems, KEY_STATE_START_BIT);
|
||||
|
@ -678,7 +722,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
|
||||
#ifdef WANT_DEBUG
|
||||
if (numValidJointRotations > 15) {
|
||||
qDebug() << "RECEIVING -- rotations:" << numValidJointRotations
|
||||
qCDebug(avatars) << "RECEIVING -- rotations:" << numValidJointRotations
|
||||
<< "translations:" << numValidJointTranslations
|
||||
<< "size:" << (int)(sourceBuffer - startPosition);
|
||||
}
|
||||
|
@ -984,7 +1028,7 @@ QStringList AvatarData::getJointNames() const {
|
|||
void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut) {
|
||||
QDataStream packetStream(data);
|
||||
|
||||
packetStream >> identityOut.uuid >> identityOut.skeletonModelURL >> identityOut.attachmentData >> identityOut.displayName >> identityOut.avatarEntityData;
|
||||
packetStream >> identityOut.uuid >> identityOut.skeletonModelURL >> identityOut.attachmentData >> identityOut.displayName >> identityOut.sessionDisplayName >> identityOut.avatarEntityData;
|
||||
}
|
||||
|
||||
static const QUrl emptyURL("");
|
||||
|
@ -1006,6 +1050,7 @@ bool AvatarData::processAvatarIdentity(const Identity& identity) {
|
|||
setDisplayName(identity.displayName);
|
||||
hasIdentityChanged = true;
|
||||
}
|
||||
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
|
||||
|
||||
if (identity.attachmentData != _attachmentData) {
|
||||
setAttachmentData(identity.attachmentData);
|
||||
|
@ -1030,7 +1075,7 @@ QByteArray AvatarData::identityByteArray() {
|
|||
const QUrl& urlToSend = cannonicalSkeletonModelURL(emptyURL);
|
||||
|
||||
_avatarEntitiesLock.withReadLock([&] {
|
||||
identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << _avatarEntityData;
|
||||
identityStream << getSessionUUID() << urlToSend << _attachmentData << _displayName << getSessionDisplayNameForTransport() << _avatarEntityData;
|
||||
});
|
||||
|
||||
return identityData;
|
||||
|
@ -1180,9 +1225,9 @@ void AvatarData::sendAvatarDataPacket() {
|
|||
|
||||
// about 2% of the time, we send a full update (meaning, we transmit all the joint data), even if nothing has changed.
|
||||
// this is to guard against a joint moving once, the packet getting lost, and the joint never moving again.
|
||||
bool sendFullUpdate = randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO;
|
||||
QByteArray avatarByteArray = toByteArray(true, sendFullUpdate);
|
||||
doneEncoding(true);
|
||||
QByteArray avatarByteArray = toByteArray((randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO) ? SendAllData : CullSmallData);
|
||||
|
||||
doneEncoding(true); // FIXME - doneEncoding() takes a bool for culling small changes, that's janky!
|
||||
|
||||
static AvatarDataSequenceNumber sequenceNumber = 0;
|
||||
|
||||
|
@ -1385,6 +1430,7 @@ static const QString JSON_AVATAR_HEAD = QStringLiteral("head");
|
|||
static const QString JSON_AVATAR_HEAD_MODEL = QStringLiteral("headModel");
|
||||
static const QString JSON_AVATAR_BODY_MODEL = QStringLiteral("bodyModel");
|
||||
static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName");
|
||||
// It isn't meaningful to persist sessionDisplayName.
|
||||
static const QString JSON_AVATAR_ATTACHEMENTS = QStringLiteral("attachments");
|
||||
static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
|
||||
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
|
||||
|
@ -1448,7 +1494,7 @@ QJsonObject AvatarData::toJson() const {
|
|||
bool success;
|
||||
Transform avatarTransform = getTransform(success);
|
||||
if (!success) {
|
||||
qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform";
|
||||
qCWarning(avatars) << "Warning -- AvatarData::toJson couldn't get avatar transform";
|
||||
}
|
||||
avatarTransform.setScale(getDomainLimitedScale());
|
||||
if (recordingBasis) {
|
||||
|
@ -1593,7 +1639,7 @@ QByteArray AvatarData::toFrame(const AvatarData& avatar) {
|
|||
{
|
||||
QJsonObject obj = root;
|
||||
obj.remove(JSON_AVATAR_JOINT_ARRAY);
|
||||
qDebug().noquote() << QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Indented);
|
||||
qCDebug(avatars).noquote() << QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Indented);
|
||||
}
|
||||
#endif
|
||||
return QJsonDocument(root).toBinaryData();
|
||||
|
@ -1606,7 +1652,7 @@ void AvatarData::fromFrame(const QByteArray& frameData, AvatarData& result) {
|
|||
{
|
||||
QJsonObject obj = doc.object();
|
||||
obj.remove(JSON_AVATAR_JOINT_ARRAY);
|
||||
qDebug().noquote() << QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Indented);
|
||||
qCDebug(avatars).noquote() << QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Indented);
|
||||
}
|
||||
#endif
|
||||
result.fromJson(doc.object());
|
||||
|
|
|
@ -106,6 +106,11 @@ const char LEFT_HAND_POINTING_FLAG = 1;
|
|||
const char RIGHT_HAND_POINTING_FLAG = 2;
|
||||
const char IS_FINGER_POINTING_FLAG = 4;
|
||||
|
||||
// AvatarData state flags - we store the details about the packet encoding in the first byte,
|
||||
// before the "header" structure
|
||||
const char AVATARDATA_FLAGS_MINIMUM = 0;
|
||||
|
||||
|
||||
static const float MAX_AVATAR_SCALE = 1000.0f;
|
||||
static const float MIN_AVATAR_SCALE = .005f;
|
||||
|
||||
|
@ -171,6 +176,9 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
|||
Q_PROPERTY(float audioAverageLoudness READ getAudioAverageLoudness WRITE setAudioAverageLoudness)
|
||||
|
||||
Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName)
|
||||
// sessionDisplayName is sanitized, defaulted version displayName that is defined by the AvatarMixer rather than by Interface clients.
|
||||
// The result is unique among all avatars present at the time.
|
||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName)
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||
|
||||
|
@ -201,7 +209,14 @@ public:
|
|||
glm::vec3 getHandPosition() const;
|
||||
void setHandPosition(const glm::vec3& handPosition);
|
||||
|
||||
virtual QByteArray toByteArray(bool cullSmallChanges, bool sendAll);
|
||||
typedef enum {
|
||||
MinimumData,
|
||||
CullSmallData,
|
||||
IncludeSmallData,
|
||||
SendAllData
|
||||
} AvatarDataDetail;
|
||||
|
||||
virtual QByteArray toByteArray(AvatarDataDetail dataDetail);
|
||||
virtual void doneEncoding(bool cullSmallChanges);
|
||||
|
||||
/// \return true if an error should be logged
|
||||
|
@ -313,6 +328,7 @@ public:
|
|||
QUrl skeletonModelURL;
|
||||
QVector<AttachmentData> attachmentData;
|
||||
QString displayName;
|
||||
QString sessionDisplayName;
|
||||
AvatarEntityMap avatarEntityData;
|
||||
};
|
||||
|
||||
|
@ -325,9 +341,11 @@ public:
|
|||
|
||||
const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; }
|
||||
const QString& getDisplayName() const { return _displayName; }
|
||||
const QString& getSessionDisplayName() const { return _sessionDisplayName; }
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
virtual void setDisplayName(const QString& displayName);
|
||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) { _sessionDisplayName = sessionDisplayName; };
|
||||
|
||||
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
||||
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
||||
|
@ -390,6 +408,8 @@ public slots:
|
|||
|
||||
protected:
|
||||
glm::vec3 _handPosition;
|
||||
virtual const QString& getSessionDisplayNameForTransport() const { return _sessionDisplayName; }
|
||||
virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) { } // No-op in AvatarMixer
|
||||
|
||||
// Body scale
|
||||
float _targetScale;
|
||||
|
@ -417,6 +437,7 @@ protected:
|
|||
QUrl _skeletonFBXURL;
|
||||
QVector<AttachmentData> _attachmentData;
|
||||
QString _displayName;
|
||||
QString _sessionDisplayName { };
|
||||
const QUrl& cannonicalSkeletonModelURL(const QUrl& empty);
|
||||
|
||||
float _displayNameTargetAlpha;
|
||||
|
|
|
@ -133,6 +133,18 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
|
|||
|
||||
// make sure this isn't for an ignored avatar
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
static auto EMPTY = QUuid();
|
||||
|
||||
{
|
||||
QReadLocker locker(&_hashLock);
|
||||
auto me = _avatarHash.find(EMPTY);
|
||||
if ((me != _avatarHash.end()) && (identity.uuid == me.value()->getSessionUUID())) {
|
||||
// We add MyAvatar to _avatarHash with an empty UUID. Code relies on this. In order to correctly handle an
|
||||
// identity packet for ourself (such as when we are assigned a sessionDisplayName by the mixer upon joining),
|
||||
// we make things match here.
|
||||
identity.uuid = EMPTY;
|
||||
}
|
||||
}
|
||||
if (!nodeList->isIgnoringNode(identity.uuid)) {
|
||||
// mesh URL for a UUID, find avatar in our list
|
||||
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
|
||||
|
@ -160,7 +172,7 @@ void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason remo
|
|||
}
|
||||
|
||||
void AvatarHashMap::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) {
|
||||
qDebug() << "Removed avatar with UUID" << uuidStringWithoutCurlyBraces(removedAvatar->getSessionUUID())
|
||||
qCDebug(avatars) << "Removed avatar with UUID" << uuidStringWithoutCurlyBraces(removedAvatar->getSessionUUID())
|
||||
<< "from AvatarHashMap";
|
||||
emit avatarRemovedEvent(removedAvatar->getSessionUUID());
|
||||
}
|
||||
|
|
|
@ -152,7 +152,6 @@ CompositorHelper::CompositorHelper() :
|
|||
// auto cursor = Cursor::Manager::instance().getCursor();
|
||||
// cursor->setIcon(Cursor::Icon::DEFAULT);
|
||||
// if (!_tooltipId.isEmpty()) {
|
||||
// qDebug() << "Closing tooltip " << _tooltipId;
|
||||
// Tooltip::closeTip(_tooltipId);
|
||||
// _tooltipId.clear();
|
||||
// }
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
Lock lock(_mutex);
|
||||
_shutdown = true;
|
||||
_condition.wait(lock, [&] { return !_shutdown; });
|
||||
qDebug() << "Present thread shutdown";
|
||||
qCDebug(displayPlugins) << "Present thread shutdown";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -741,7 +741,6 @@ void HmdDisplayPlugin::compositeExtra() {
|
|||
}
|
||||
|
||||
HmdDisplayPlugin::~HmdDisplayPlugin() {
|
||||
qDebug() << "Destroying HmdDisplayPlugin";
|
||||
}
|
||||
|
||||
float HmdDisplayPlugin::stutterRate() const {
|
||||
|
|
|
@ -286,7 +286,7 @@ bool RenderableModelEntityItem::getAnimationFrame() {
|
|||
|
||||
resizeJointArrays();
|
||||
if (_jointMapping.size() != _model->getJointStateCount()) {
|
||||
qDebug() << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
||||
qCDebug(entities) << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
||||
<< _jointMapping.size() << _model->getJointStateCount();
|
||||
assert(false);
|
||||
return false;
|
||||
|
|
|
@ -890,7 +890,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() {
|
|||
if (voxelXSize == 0 || voxelXSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION ||
|
||||
voxelYSize == 0 || voxelYSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION ||
|
||||
voxelZSize == 0 || voxelZSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION) {
|
||||
qDebug() << "voxelSize is not reasonable, skipping decompressions."
|
||||
qCDebug(entities) << "voxelSize is not reasonable, skipping decompressions."
|
||||
<< voxelXSize << voxelYSize << voxelZSize << getName() << getID();
|
||||
entity->setVoxelDataDirty(false);
|
||||
return;
|
||||
|
@ -903,7 +903,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() {
|
|||
QByteArray uncompressedData = qUncompress(compressedData);
|
||||
|
||||
if (uncompressedData.size() != rawSize) {
|
||||
qDebug() << "PolyVox decompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")"
|
||||
qCDebug(entities) << "PolyVox decompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")"
|
||||
<< "so expected uncompressed length of" << rawSize << "but length is" << uncompressedData.size()
|
||||
<< getName() << getID();
|
||||
entity->setVoxelDataDirty(false);
|
||||
|
@ -973,7 +973,7 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacket() {
|
|||
if (newVoxelData.size() > 1150) {
|
||||
// HACK -- until we have a way to allow for properties larger than MTU, don't update.
|
||||
// revert the active voxel-space to the last version that fit.
|
||||
qDebug() << "compressed voxel data is too large" << entity->getName() << entity->getID();
|
||||
qCDebug(entities) << "compressed voxel data is too large" << entity->getName() << entity->getID();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ EntityItemPointer RenderableWebEntityItem::factory(const EntityItemID& entityID,
|
|||
|
||||
RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemID) :
|
||||
WebEntityItem(entityItemID) {
|
||||
|
||||
qCDebug(entities) << "Created web entity " << getID();
|
||||
|
||||
_touchDevice.setCapabilities(QTouchDevice::Position);
|
||||
_touchDevice.setType(QTouchDevice::TouchScreen);
|
||||
_touchDevice.setName("RenderableWebEntityItemTouchDevice");
|
||||
|
@ -55,6 +58,9 @@ RenderableWebEntityItem::RenderableWebEntityItem(const EntityItemID& entityItemI
|
|||
|
||||
RenderableWebEntityItem::~RenderableWebEntityItem() {
|
||||
destroyWebSurface();
|
||||
|
||||
qCDebug(entities) << "Destroyed web entity " << getID();
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
|
@ -88,6 +94,8 @@ bool RenderableWebEntityItem::buildWebSurface(QSharedPointer<EntityTreeRenderer>
|
|||
|
||||
++_currentWebCount;
|
||||
|
||||
qCDebug(entities) << "Building web surface: " << getID() << ", #" << _currentWebCount << ", url = " << _sourceUrl;
|
||||
|
||||
QSurface * currentSurface = currentContext->surface();
|
||||
|
||||
auto deleter = [](OffscreenQmlSurface* webSurface) {
|
||||
|
@ -268,6 +276,9 @@ void RenderableWebEntityItem::loadSourceURL() {
|
|||
|
||||
void RenderableWebEntityItem::setSourceUrl(const QString& value) {
|
||||
if (_sourceUrl != value) {
|
||||
|
||||
qCDebug(entities) << "Setting web entity source URL to " << value;
|
||||
|
||||
_sourceUrl = value;
|
||||
if (_webSurface) {
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||
|
@ -386,6 +397,8 @@ void RenderableWebEntityItem::destroyWebSurface() {
|
|||
QObject::disconnect(_hoverLeaveConnection);
|
||||
_hoverLeaveConnection = QMetaObject::Connection();
|
||||
_webSurface.reset();
|
||||
|
||||
qCDebug(entities) << "Delete web surface: " << getID() << ", #" << _currentWebCount << ", url = " << _sourceUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -167,10 +167,10 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
|||
|
||||
|
||||
void AnimationPropertyGroup::debugDump() const {
|
||||
qDebug() << " AnimationPropertyGroup: ---------------------------------------------";
|
||||
qDebug() << " url:" << getURL() << " has changed:" << urlChanged();
|
||||
qDebug() << " fps:" << getFPS() << " has changed:" << fpsChanged();
|
||||
qDebug() << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged();
|
||||
qCDebug(entities) << " AnimationPropertyGroup: ---------------------------------------------";
|
||||
qCDebug(entities) << " url:" << getURL() << " has changed:" << urlChanged();
|
||||
qCDebug(entities) << " fps:" << getFPS() << " has changed:" << fpsChanged();
|
||||
qCDebug(entities) << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged();
|
||||
}
|
||||
|
||||
void AnimationPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||
|
|
|
@ -104,7 +104,7 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS
|
|||
return ACTION_TYPE_TRAVEL_ORIENTED;
|
||||
}
|
||||
|
||||
qDebug() << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString;
|
||||
qCDebug(entities) << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString;
|
||||
return ACTION_TYPE_NONE;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return glm::vec3(0.0f);
|
||||
|
@ -137,14 +137,14 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
|
|||
|
||||
QVariant resultV = arguments[argumentName];
|
||||
if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) {
|
||||
qDebug() << objectName << "argument" << argumentName << "must be a map";
|
||||
qCDebug(entities) << objectName << "argument" << argumentName << "must be a map";
|
||||
ok = false;
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
QVariantMap resultVM = resultV.toMap();
|
||||
if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z")) {
|
||||
qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, z";
|
||||
qCDebug(entities) << objectName << "argument" << argumentName << "must be a map with keys: x, y, z";
|
||||
ok = false;
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian
|
|||
float y = yV.toFloat(&yOk);
|
||||
float z = zV.toFloat(&zOk);
|
||||
if (!xOk || !yOk || !zOk) {
|
||||
qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, and z of type float.";
|
||||
qCDebug(entities) << objectName << "argument" << argumentName << "must be a map with keys: x, y, and z of type float.";
|
||||
ok = false;
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return glm::quat();
|
||||
|
@ -186,14 +186,14 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
|
|||
|
||||
QVariant resultV = arguments[argumentName];
|
||||
if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) {
|
||||
qDebug() << objectName << "argument" << argumentName << "must be a map, not" << resultV.typeName();
|
||||
qCDebug(entities) << objectName << "argument" << argumentName << "must be a map, not" << resultV.typeName();
|
||||
ok = false;
|
||||
return glm::quat();
|
||||
}
|
||||
|
||||
QVariantMap resultVM = resultV.toMap();
|
||||
if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z") || !resultVM.contains("w")) {
|
||||
qDebug() << objectName << "argument" << argumentName << "must be a map with keys: x, y, z, and w";
|
||||
qCDebug(entities) << objectName << "argument" << argumentName << "must be a map with keys: x, y, z, and w";
|
||||
ok = false;
|
||||
return glm::quat();
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian
|
|||
float z = zV.toFloat(&zOk);
|
||||
float w = wV.toFloat(&wOk);
|
||||
if (!xOk || !yOk || !zOk || !wOk) {
|
||||
qDebug() << objectName << "argument" << argumentName
|
||||
qCDebug(entities) << objectName << "argument" << argumentName
|
||||
<< "must be a map with keys: x, y, z, and w of type float.";
|
||||
ok = false;
|
||||
return glm::quat();
|
||||
|
@ -231,7 +231,7 @@ float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMa
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return 0.0f;
|
||||
|
@ -253,7 +253,7 @@ int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMa
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return 0.0f;
|
||||
|
@ -275,7 +275,7 @@ QString EntityActionInterface::extractStringArgument(QString objectName, QVarian
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return "";
|
||||
|
@ -287,7 +287,7 @@ bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantM
|
|||
QString argumentName, bool& ok, bool required) {
|
||||
if (!arguments.contains(argumentName)) {
|
||||
if (required) {
|
||||
qDebug() << objectName << "requires argument:" << argumentName;
|
||||
qCDebug(entities) << objectName << "requires argument:" << argumentName;
|
||||
}
|
||||
ok = false;
|
||||
return false;
|
||||
|
|
|
@ -52,12 +52,12 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type,
|
|||
assert(_myAvatar);
|
||||
|
||||
if (!entityTree) {
|
||||
qDebug() << "EntityEditPacketSender::queueEditEntityMessage null entityTree.";
|
||||
qCDebug(entities) << "EntityEditPacketSender::queueEditEntityMessage null entityTree.";
|
||||
return;
|
||||
}
|
||||
EntityItemPointer entity = entityTree->findEntityByEntityItemID(entityItemID);
|
||||
if (!entity) {
|
||||
qDebug() << "EntityEditPacketSender::queueEditEntityMessage can't find entity.";
|
||||
qCDebug(entities) << "EntityEditPacketSender::queueEditEntityMessage can't find entity.";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
|||
}
|
||||
|
||||
if (propertiesWithSimID.getParentID() == AVATAR_SELF_ID) {
|
||||
qDebug() << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
|
||||
qCDebug(entities) << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
|
||||
propertiesWithSimID.setParentID(QUuid());
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
if (!scriptSideProperties.parentIDChanged()) {
|
||||
properties.setParentID(entity->getParentID());
|
||||
} else if (scriptSideProperties.getParentID() == AVATAR_SELF_ID) {
|
||||
qDebug() << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
|
||||
qCDebug(entities) << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
|
||||
properties.setParentID(QUuid());
|
||||
}
|
||||
if (!scriptSideProperties.parentJointIndexChanged()) {
|
||||
|
@ -931,12 +931,12 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
|
|||
EntitySimulationPointer simulation = _entityTree->getSimulation();
|
||||
entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (!entity) {
|
||||
qDebug() << "actionWorker -- unknown entity" << entityID;
|
||||
qCDebug(entities) << "actionWorker -- unknown entity" << entityID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!simulation) {
|
||||
qDebug() << "actionWorker -- no simulation" << entityID;
|
||||
qCDebug(entities) << "actionWorker -- no simulation" << entityID;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1051,7 @@ EntityItemPointer EntityScriptingInterface::checkForTreeEntityAndTypeMatch(const
|
|||
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||
if (!entity) {
|
||||
qDebug() << "EntityScriptingInterface::checkForTreeEntityAndTypeMatch - no entity with ID" << entityID;
|
||||
qCDebug(entities) << "EntityScriptingInterface::checkForTreeEntityAndTypeMatch - no entity with ID" << entityID;
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1311,7 @@ QVector<QUuid> EntityScriptingInterface::getChildrenIDs(const QUuid& parentID) {
|
|||
|
||||
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(parentID);
|
||||
if (!entity) {
|
||||
qDebug() << "EntityScriptingInterface::getChildrenIDs - no entity with ID" << parentID;
|
||||
qCDebug(entities) << "EntityScriptingInterface::getChildrenIDs - no entity with ID" << parentID;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
|||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
if (!nodeList) {
|
||||
qDebug() << "EntityTree::addEntity -- can't get NodeList";
|
||||
qCDebug(entities) << "EntityTree::addEntity -- can't get NodeList";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1243,7 +1243,7 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) {
|
|||
if (hasSomethingNewer) {
|
||||
int elapsed = usecTimestampNow() - considerEntitiesSince;
|
||||
int difference = considerEntitiesSince - sinceTime;
|
||||
qDebug() << "EntityTree::hasEntitiesDeletedSince() sinceTime:" << sinceTime
|
||||
qCDebug(entities) << "EntityTree::hasEntitiesDeletedSince() sinceTime:" << sinceTime
|
||||
<< "considerEntitiesSince:" << considerEntitiesSince << "elapsed:" << elapsed << "difference:" << difference;
|
||||
}
|
||||
#endif
|
||||
|
@ -1276,7 +1276,7 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
|
|||
// TODO: consider consolidating processEraseMessageDetails() and processEraseMessage()
|
||||
int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << "EntityTree::processEraseMessage()";
|
||||
qCDebug(entities) << "EntityTree::processEraseMessage()";
|
||||
#endif
|
||||
withWriteLock([&] {
|
||||
message.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME));
|
||||
|
@ -1296,7 +1296,7 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo
|
|||
|
||||
QUuid entityID = QUuid::fromRfc4122(message.readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << " ---- EntityTree::processEraseMessage() contained ID:" << entityID;
|
||||
qCDebug(entities) << " ---- EntityTree::processEraseMessage() contained ID:" << entityID;
|
||||
#endif
|
||||
|
||||
EntityItemID entityItemID(entityID);
|
||||
|
@ -1318,7 +1318,7 @@ int EntityTree::processEraseMessage(ReceivedMessage& message, const SharedNodePo
|
|||
// TODO: consider consolidating processEraseMessageDetails() and processEraseMessage()
|
||||
int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << "EntityTree::processEraseMessageDetails()";
|
||||
qCDebug(entities) << "EntityTree::processEraseMessageDetails()";
|
||||
#endif
|
||||
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
|
||||
const unsigned char* dataAt = packetData;
|
||||
|
@ -1347,7 +1347,7 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons
|
|||
processedBytes += encodedID.size();
|
||||
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID;
|
||||
qCDebug(entities) << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID;
|
||||
#endif
|
||||
|
||||
EntityItemID entityItemID(entityID);
|
||||
|
|
|
@ -329,7 +329,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
includeThisEntity = false; // too small, don't include it
|
||||
|
||||
#ifdef WANT_LOD_DEBUGGING
|
||||
qDebug() << "skipping entity - TOO SMALL - \n"
|
||||
qCDebug(entities) << "skipping entity - TOO SMALL - \n"
|
||||
<< "......id:" << entity->getID() << "\n"
|
||||
<< "....name:" << entity->getName() << "\n"
|
||||
<< "..bounds:" << entityBounds << "\n"
|
||||
|
@ -341,7 +341,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
|
|||
|
||||
if (includeThisEntity) {
|
||||
#ifdef WANT_LOD_DEBUGGING
|
||||
qDebug() << "including entity - \n"
|
||||
qCDebug(entities) << "including entity - \n"
|
||||
<< "......id:" << entity->getID() << "\n"
|
||||
<< "....name:" << entity->getName() << "\n"
|
||||
<< "....cell:" << getAACube();
|
||||
|
@ -472,7 +472,7 @@ bool EntityTreeElement::bestFitEntityBounds(EntityItemPointer entity) const {
|
|||
bool success;
|
||||
auto queryCube = entity->getQueryAACube(success);
|
||||
if (!success) {
|
||||
qDebug() << "EntityTreeElement::bestFitEntityBounds couldn't get queryCube for" << entity->getName() << entity->getID();
|
||||
qCDebug(entities) << "EntityTreeElement::bestFitEntityBounds couldn't get queryCube for" << entity->getName() << entity->getID();
|
||||
return false;
|
||||
}
|
||||
return bestFitBounds(queryCube);
|
||||
|
@ -973,7 +973,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
}
|
||||
} else {
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "Received packet for previously deleted entity [" <<
|
||||
qCDebug(entities) << "Received packet for previously deleted entity [" <<
|
||||
entityItem->getID() << "] ignoring. (inside " << __FUNCTION__ << ")";
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <OctreeRenderer.h> // for RenderArgs
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
|
||||
class EntityItem;
|
||||
using EntityItemPointer = std::shared_ptr<EntityItem>;
|
||||
using EntityItemWeakPointer = std::weak_ptr<EntityItem>;
|
||||
|
@ -77,7 +79,7 @@ private:
|
|||
struct EntityRegistrationChecker {
|
||||
EntityRegistrationChecker(bool result, const char* debugMessage) {
|
||||
if (!result) {
|
||||
qDebug() << debugMessage;
|
||||
qCDebug(entities) << debugMessage;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -60,12 +60,12 @@ void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) {
|
|||
|
||||
|
||||
void KeyLightPropertyGroup::debugDump() const {
|
||||
qDebug() << " KeyLightPropertyGroup: ---------------------------------------------";
|
||||
qDebug() << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
|
||||
qDebug() << " intensity:" << getIntensity();
|
||||
qDebug() << " direction:" << getDirection();
|
||||
qDebug() << " ambientIntensity:" << getAmbientIntensity();
|
||||
qDebug() << " ambientURL:" << getAmbientURL();
|
||||
qCDebug(entities) << " KeyLightPropertyGroup: ---------------------------------------------";
|
||||
qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
|
||||
qCDebug(entities) << " intensity:" << getIntensity();
|
||||
qCDebug(entities) << " direction:" << getDirection();
|
||||
qCDebug(entities) << " ambientIntensity:" << getAmbientIntensity();
|
||||
qCDebug(entities) << " ambientURL:" << getAmbientURL();
|
||||
}
|
||||
|
||||
void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||
|
|
|
@ -80,12 +80,12 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
bool LineEntityItem::appendPoint(const glm::vec3& point) {
|
||||
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
|
||||
qDebug() << "MAX POINTS REACHED!";
|
||||
qCDebug(entities) << "MAX POINTS REACHED!";
|
||||
return false;
|
||||
}
|
||||
glm::vec3 halfBox = getDimensions() * 0.5f;
|
||||
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
|
||||
qDebug() << "Point is outside entity's bounding box";
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
_points << point;
|
||||
|
@ -101,7 +101,7 @@ bool LineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
|||
for (int i = 0; i < points.size(); i++) {
|
||||
glm::vec3 point = points.at(i);
|
||||
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
|
||||
qDebug() << "Point is outside entity's bounding box";
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,12 +89,12 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
|
||||
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
|
||||
qDebug() << "MAX POINTS REACHED!";
|
||||
qCDebug(entities) << "MAX POINTS REACHED!";
|
||||
return false;
|
||||
}
|
||||
glm::vec3 halfBox = getDimensions() * 0.5f;
|
||||
if ((point.x < -halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < -halfBox.z || point.z > halfBox.z)) {
|
||||
qDebug() << "Point is outside entity's bounding box";
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
_points << point;
|
||||
|
@ -142,7 +142,7 @@ bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
|||
if ((point.x < -halfBox.x || point.x > halfBox.x) ||
|
||||
(point.y < -halfBox.y || point.y > halfBox.y) ||
|
||||
(point.z < -halfBox.z || point.z > halfBox.z)) {
|
||||
qDebug() << "Point is outside entity's bounding box";
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,29 +71,29 @@ void PolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) {
|
|||
|
||||
_voxelVolumeSize = glm::vec3(roundf(voxelVolumeSize.x), roundf(voxelVolumeSize.y), roundf(voxelVolumeSize.z));
|
||||
if (_voxelVolumeSize.x < 1) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping x of" << _voxelVolumeSize.x << "to 1";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping x of" << _voxelVolumeSize.x << "to 1";
|
||||
_voxelVolumeSize.x = 1;
|
||||
}
|
||||
if (_voxelVolumeSize.x > MAX_VOXEL_DIMENSION) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping x of" << _voxelVolumeSize.x << "to max";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping x of" << _voxelVolumeSize.x << "to max";
|
||||
_voxelVolumeSize.x = MAX_VOXEL_DIMENSION;
|
||||
}
|
||||
|
||||
if (_voxelVolumeSize.y < 1) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping y of" << _voxelVolumeSize.y << "to 1";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping y of" << _voxelVolumeSize.y << "to 1";
|
||||
_voxelVolumeSize.y = 1;
|
||||
}
|
||||
if (_voxelVolumeSize.y > MAX_VOXEL_DIMENSION) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping y of" << _voxelVolumeSize.y << "to max";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping y of" << _voxelVolumeSize.y << "to max";
|
||||
_voxelVolumeSize.y = MAX_VOXEL_DIMENSION;
|
||||
}
|
||||
|
||||
if (_voxelVolumeSize.z < 1) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping z of" << _voxelVolumeSize.z << "to 1";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping z of" << _voxelVolumeSize.z << "to 1";
|
||||
_voxelVolumeSize.z = 1;
|
||||
}
|
||||
if (_voxelVolumeSize.z > MAX_VOXEL_DIMENSION) {
|
||||
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping z of" << _voxelVolumeSize.z << "to max";
|
||||
qCDebug(entities) << "PolyVoxEntityItem::setVoxelVolumeSize clamping z of" << _voxelVolumeSize.z << "to max";
|
||||
_voxelVolumeSize.z = MAX_VOXEL_DIMENSION;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -34,9 +34,9 @@ void SkyboxPropertyGroup::merge(const SkyboxPropertyGroup& other) {
|
|||
|
||||
|
||||
void SkyboxPropertyGroup::debugDump() const {
|
||||
qDebug() << " SkyboxPropertyGroup: ---------------------------------------------";
|
||||
qDebug() << " Color:" << getColor() << " has changed:" << colorChanged();
|
||||
qDebug() << " URL:" << getURL() << " has changed:" << urlChanged();
|
||||
qCDebug(entities) << " SkyboxPropertyGroup: ---------------------------------------------";
|
||||
qCDebug(entities) << " Color:" << getColor() << " has changed:" << colorChanged();
|
||||
qCDebug(entities) << " URL:" << getURL() << " has changed:" << urlChanged();
|
||||
}
|
||||
|
||||
void SkyboxPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||
|
|
|
@ -67,14 +67,14 @@ void StagePropertyGroup::merge(const StagePropertyGroup& other) {
|
|||
|
||||
|
||||
void StagePropertyGroup::debugDump() const {
|
||||
qDebug() << " StagePropertyGroup: ---------------------------------------------";
|
||||
qDebug() << " _sunModelEnabled:" << _sunModelEnabled;
|
||||
qDebug() << " _latitude:" << _latitude;
|
||||
qDebug() << " _longitude:" << _longitude;
|
||||
qDebug() << " _altitude:" << _altitude;
|
||||
qDebug() << " _day:" << _day;
|
||||
qDebug() << " _hour:" << _hour;
|
||||
qDebug() << " _automaticHourDay:" << _automaticHourDay;
|
||||
qCDebug(entities) << " StagePropertyGroup: ---------------------------------------------";
|
||||
qCDebug(entities) << " _sunModelEnabled:" << _sunModelEnabled;
|
||||
qCDebug(entities) << " _latitude:" << _latitude;
|
||||
qCDebug(entities) << " _longitude:" << _longitude;
|
||||
qCDebug(entities) << " _altitude:" << _altitude;
|
||||
qCDebug(entities) << " _day:" << _day;
|
||||
qCDebug(entities) << " _hour:" << _hour;
|
||||
qCDebug(entities) << " _automaticHourDay:" << _automaticHourDay;
|
||||
}
|
||||
|
||||
void StagePropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||
|
|
|
@ -194,7 +194,6 @@ QVariantHash FSTReader::downloadMapping(const QString& url) {
|
|||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
||||
qDebug() << "Downloading avatar file at " << url;
|
||||
QEventLoop loop;
|
||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
|
|
|
@ -103,11 +103,14 @@ public:
|
|||
}
|
||||
|
||||
void report() {
|
||||
uint64_t now = usecTimestampNow();
|
||||
if ((now - _lastReport) > USECS_PER_SECOND * 5) {
|
||||
_lastReport = now;
|
||||
qCDebug(glLogging) << "Current offscreen texture count " << _allTextureCount;
|
||||
qCDebug(glLogging) << "Current offscreen active texture count " << _activeTextureCount;
|
||||
if (randFloat() < 0.01f) {
|
||||
PROFILE_COUNTER(render_qml_gl, "offscreenTextures", {
|
||||
{ "total", QVariant::fromValue(_allTextureCount.load()) },
|
||||
{ "active", QVariant::fromValue(_activeTextureCount.load()) },
|
||||
});
|
||||
PROFILE_COUNTER(render_qml_gl, "offscreenTextureMemory", {
|
||||
{ "value", QVariant::fromValue(_totalTextureUsage) }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +192,6 @@ private:
|
|||
std::unordered_map<GLuint, uvec2> _textureSizes;
|
||||
Mutex _mutex;
|
||||
std::list<OffscreenQmlSurface::TextureAndFence> _returnedTextures;
|
||||
uint64_t _lastReport { 0 };
|
||||
size_t _totalTextureUsage { 0 };
|
||||
} offscreenTextures;
|
||||
|
||||
|
@ -424,7 +426,8 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
// a timer with a small interval is used to get better performance.
|
||||
QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
|
||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &OffscreenQmlSurface::onAboutToQuit);
|
||||
_updateTimer.setInterval(MIN_TIMER_MS);
|
||||
_updateTimer.setTimerType(Qt::PreciseTimer);
|
||||
_updateTimer.setInterval(MIN_TIMER_MS); // 5ms, Qt::PreciseTimer required
|
||||
_updateTimer.start();
|
||||
|
||||
auto rootContext = getRootContext();
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "GLBackend.h"
|
||||
#include "GLState.h"
|
||||
|
||||
#include <gpu/GPULogging.h>
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
|
||||
|
@ -172,7 +174,7 @@ void GLBackend::do_setStateDepthTest(State::DepthTest test) {
|
|||
glDepthFunc(COMPARISON_TO_GL[test.getFunction()]);
|
||||
}
|
||||
if (CHECK_GL_ERROR()) {
|
||||
qDebug() << "DepthTest" << (test.isEnabled() ? "Enabled" : "Disabled")
|
||||
qCDebug(gpulogging) << "DepthTest" << (test.isEnabled() ? "Enabled" : "Disabled")
|
||||
<< "Mask=" << (test.getWriteMask() ? "Write" : "no Write")
|
||||
<< "Func=" << test.getFunction()
|
||||
<< "Raw=" << test.getRaw();
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <gl/GLHelpers.h>
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include <gpu/GPULogging.h>
|
||||
|
||||
#include "GLShared.h"
|
||||
#include "GLTexture.h"
|
||||
|
||||
|
@ -155,7 +157,7 @@ bool GLTextureTransferHelper::process() {
|
|||
auto lastReportInterval = now - lastReport;
|
||||
if (lastReportInterval > USECS_PER_SECOND * 4) {
|
||||
lastReport = now;
|
||||
qDebug() << "Texture list " << _transferringTextures.size();
|
||||
qCDebug(gpulogging) << "Texture list " << _transferringTextures.size();
|
||||
}
|
||||
|
||||
size_t transferCount = 0;
|
||||
|
|
|
@ -398,9 +398,13 @@ bool GL45Texture::continueTransfer() {
|
|||
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
||||
// DSA ARB does not work on AMD, so use EXT
|
||||
// glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData());
|
||||
auto target = CUBE_FACE_LAYOUT[face];
|
||||
glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||
// unless EXT is not available on the driver
|
||||
if (glTextureSubImage2DEXT) {
|
||||
auto target = CUBE_FACE_LAYOUT[face];
|
||||
glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||
} else {
|
||||
glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData());
|
||||
}
|
||||
} else {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#if _DEBUG
|
||||
#include <QtCore/QDebug>
|
||||
#include "GPULogging.h"
|
||||
#endif
|
||||
|
||||
#include "Forward.h"
|
||||
|
@ -318,13 +319,13 @@ public:
|
|||
template <typename T> const T& get() const {
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
qCDebug(gpulogging) << "Accessing null gpu::buffer!";
|
||||
}
|
||||
if (sizeof(T) > (_buffer->getSize() - _offset)) {
|
||||
qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
|
||||
qCDebug(gpulogging) << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
|
||||
}
|
||||
if (sizeof(T) > _size) {
|
||||
qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
|
||||
qCDebug(gpulogging) << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
|
||||
}
|
||||
#endif
|
||||
const T* t = (reinterpret_cast<const T*> (_buffer->getData() + _offset));
|
||||
|
@ -334,13 +335,13 @@ public:
|
|||
template <typename T> T& edit() {
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
qCDebug(gpulogging) << "Accessing null gpu::buffer!";
|
||||
}
|
||||
if (sizeof(T) > (_buffer->getSize() - _offset)) {
|
||||
qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
|
||||
qCDebug(gpulogging) << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
|
||||
}
|
||||
if (sizeof(T) > _size) {
|
||||
qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
|
||||
qCDebug(gpulogging) << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
|
||||
}
|
||||
#endif
|
||||
_buffer->markDirty(_offset, sizeof(T));
|
||||
|
@ -352,13 +353,13 @@ public:
|
|||
Resource::Size elementOffset = index * _stride + _offset;
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
qCDebug(gpulogging) << "Accessing null gpu::buffer!";
|
||||
}
|
||||
if (sizeof(T) > (_buffer->getSize() - elementOffset)) {
|
||||
qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
|
||||
qCDebug(gpulogging) << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
|
||||
}
|
||||
if (index > getNum<T>()) {
|
||||
qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
|
||||
qCDebug(gpulogging) << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
|
||||
}
|
||||
#endif
|
||||
return *(reinterpret_cast<const T*> (_buffer->getData() + elementOffset));
|
||||
|
@ -368,13 +369,13 @@ public:
|
|||
Resource::Size elementOffset = index * _stride + _offset;
|
||||
#if _DEBUG
|
||||
if (!_buffer) {
|
||||
qDebug() << "Accessing null gpu::buffer!";
|
||||
qCDebug(gpulogging) << "Accessing null gpu::buffer!";
|
||||
}
|
||||
if (sizeof(T) > (_buffer->getSize() - elementOffset)) {
|
||||
qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
|
||||
qCDebug(gpulogging) << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
|
||||
}
|
||||
if (index > getNum<T>()) {
|
||||
qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
|
||||
qCDebug(gpulogging) << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
|
||||
}
|
||||
#endif
|
||||
_buffer->markDirty(elementOffset, sizeof(T));
|
||||
|
|
|
@ -42,7 +42,7 @@ std::atomic<bool> Texture::_enableSparseTextures { recommendedSparseTextures };
|
|||
|
||||
struct ReportTextureState {
|
||||
ReportTextureState() {
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT]"
|
||||
qCDebug(gpulogging) << "[TEXTURE TRANSFER SUPPORT]"
|
||||
<< "\n\tidealThreadCount:" << QThread::idealThreadCount()
|
||||
<< "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures;
|
||||
}
|
||||
|
@ -50,10 +50,10 @@ struct ReportTextureState {
|
|||
|
||||
void Texture::setEnableSparseTextures(bool enabled) {
|
||||
#ifdef Q_OS_WIN
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled;
|
||||
qCDebug(gpulogging) << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled;
|
||||
_enableSparseTextures = enabled;
|
||||
#else
|
||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform.";
|
||||
qCDebug(gpulogging) << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform.";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ Texture::Size Texture::getAllowedGPUMemoryUsage() {
|
|||
}
|
||||
|
||||
void Texture::setAllowedGPUMemoryUsage(Size size) {
|
||||
qDebug() << "New MAX texture memory " << BYTES_TO_MB(size) << " MB";
|
||||
qCDebug(gpulogging) << "New MAX texture memory " << BYTES_TO_MB(size) << " MB";
|
||||
_allowedCPUMemoryUsage = size;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) {
|
|||
}
|
||||
|
||||
if (targetSize != srcImageSize) {
|
||||
qDebug() << "Resizing texture from " << srcImageSize.x << "x" << srcImageSize.y << " to " << targetSize.x << "x" << targetSize.y;
|
||||
qDebug(modelLog) << "Resizing texture from " << srcImageSize.x << "x" << srcImageSize.y << " to " << targetSize.x << "x" << targetSize.y;
|
||||
return srcImage.scaled(fromGlm(targetSize));
|
||||
}
|
||||
|
||||
|
|
|
@ -633,7 +633,7 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI
|
|||
_isWaitingForKeypairResponse = true;
|
||||
|
||||
// clear the current private key
|
||||
qDebug() << "Clearing current private key in DataServerAccountInfo";
|
||||
qCDebug(networking) << "Clearing current private key in DataServerAccountInfo";
|
||||
_accountInfo.setPrivateKey(QByteArray());
|
||||
|
||||
// setup a new QThread to generate the keypair on, in case it takes a while
|
||||
|
@ -727,7 +727,7 @@ void AccountManager::processGeneratedKeypair() {
|
|||
}
|
||||
|
||||
void AccountManager::publicKeyUploadSucceeded(QNetworkReply& reply) {
|
||||
qDebug() << "Uploaded public key to Metaverse API. RSA keypair generation is completed.";
|
||||
qCDebug(networking) << "Uploaded public key to Metaverse API. RSA keypair generation is completed.";
|
||||
|
||||
// public key upload complete - store the matching private key and persist the account to settings
|
||||
_accountInfo.setPrivateKey(_pendingPrivateKey);
|
||||
|
|
|
@ -76,7 +76,7 @@ void AssetResourceRequest::requestMappingForPath(const AssetPath& path) {
|
|||
switch (request->getError()) {
|
||||
case MappingRequest::NoError:
|
||||
// we have no error, we should have a resulting hash - use that to send of a request for that asset
|
||||
qDebug() << "Got mapping for:" << path << "=>" << request->getHash();
|
||||
qCDebug(networking) << "Got mapping for:" << path << "=>" << request->getHash();
|
||||
|
||||
requestHash(request->getHash());
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ DomainHandler::DomainHandler(QObject* parent) :
|
|||
|
||||
// setup a timeout for failure on settings requests
|
||||
static const int DOMAIN_SETTINGS_TIMEOUT_MS = 5000;
|
||||
_settingsTimer.setInterval(DOMAIN_SETTINGS_TIMEOUT_MS);
|
||||
_settingsTimer.setInterval(DOMAIN_SETTINGS_TIMEOUT_MS); // 5s, Qt::CoarseTimer acceptable
|
||||
connect(&_settingsTimer, &QTimer::timeout, this, &DomainHandler::settingsReceiveFail);
|
||||
|
||||
// setup the API refresh timer for auto connection information refresh from API when failing to connect
|
||||
const int API_REFRESH_TIMEOUT_MSEC = 2500;
|
||||
_apiRefreshTimer.setInterval(API_REFRESH_TIMEOUT_MSEC);
|
||||
_apiRefreshTimer.setInterval(API_REFRESH_TIMEOUT_MSEC); // 2.5s, Qt::CoarseTimer acceptable
|
||||
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
connect(&_apiRefreshTimer, &QTimer::timeout, addressManager.data(), &AddressManager::refreshPreviousLookup);
|
||||
|
@ -247,7 +247,7 @@ void DomainHandler::completedHostnameLookup(const QHostInfo& hostInfo) {
|
|||
}
|
||||
|
||||
void DomainHandler::completedIceServerHostnameLookup() {
|
||||
qDebug() << "ICE server socket is at" << _iceServerSockAddr;
|
||||
qCDebug(networking) << "ICE server socket is at" << _iceServerSockAddr;
|
||||
|
||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetICEServerSocket);
|
||||
|
||||
|
@ -335,7 +335,7 @@ void DomainHandler::processDTLSRequirementPacket(QSharedPointer<ReceivedMessage>
|
|||
|
||||
void DomainHandler::processICEResponsePacket(QSharedPointer<ReceivedMessage> message) {
|
||||
if (_icePeer.hasSockets()) {
|
||||
qDebug() << "Received an ICE peer packet for domain-server but we already have sockets. Not processing.";
|
||||
qCDebug(networking) << "Received an ICE peer packet for domain-server but we already have sockets. Not processing.";
|
||||
// bail on processing this packet if our ice peer already has sockets
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
|
||||
#include "FingerprintUtils.h"
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
@ -42,7 +43,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
IOObjectRelease(ioRegistryRoot);
|
||||
uuidString = QString::fromCFString(uuidCf);
|
||||
CFRelease(uuidCf);
|
||||
qDebug() << "Mac serial number: " << uuidString;
|
||||
qCDebug(networking) << "Mac serial number: " << uuidString;
|
||||
#endif //Q_OS_MAC
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -53,7 +54,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
// users of this lib don't necessarily do so.
|
||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres)) {
|
||||
qDebug() << "Failed to initialize COM library!";
|
||||
qCDebug(networking) << "Failed to initialize COM library!";
|
||||
return uuidString;
|
||||
}
|
||||
|
||||
|
@ -65,7 +66,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
IID_IWbemLocator, (LPVOID *) &pLoc);
|
||||
|
||||
if (FAILED(hres)) {
|
||||
qDebug() << "Failed to initialize WbemLocator";
|
||||
qCDebug(networking) << "Failed to initialize WbemLocator";
|
||||
return uuidString;
|
||||
}
|
||||
|
||||
|
@ -88,7 +89,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
|
||||
if (FAILED(hres)) {
|
||||
pLoc->Release();
|
||||
qDebug() << "Failed to connect to WMI";
|
||||
qCDebug(networking) << "Failed to connect to WMI";
|
||||
return uuidString;
|
||||
}
|
||||
|
||||
|
@ -107,7 +108,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
qDebug() << "Failed to set security on proxy blanket";
|
||||
qCDebug(networking) << "Failed to set security on proxy blanket";
|
||||
return uuidString;
|
||||
}
|
||||
|
||||
|
@ -123,7 +124,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
if (FAILED(hres)) {
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
qDebug() << "query to get Win32_ComputerSystemProduct info";
|
||||
qCDebug(networking) << "query to get Win32_ComputerSystemProduct info";
|
||||
return uuidString;
|
||||
}
|
||||
|
||||
|
@ -161,7 +162,7 @@ QString FingerprintUtils::getMachineFingerprintString() {
|
|||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
|
||||
qDebug() << "Windows BIOS UUID: " << uuidString;
|
||||
qCDebug(networking) << "Windows BIOS UUID: " << uuidString;
|
||||
#endif //Q_OS_WIN
|
||||
|
||||
return uuidString;
|
||||
|
@ -185,12 +186,12 @@ QUuid FingerprintUtils::getMachineFingerprint() {
|
|||
// read fallback key (if any)
|
||||
Settings settings;
|
||||
uuid = QUuid(settings.value(FALLBACK_FINGERPRINT_KEY).toString());
|
||||
qDebug() << "read fallback maching fingerprint: " << uuid.toString();
|
||||
qCDebug(networking) << "read fallback maching fingerprint: " << uuid.toString();
|
||||
if (uuid == QUuid()) {
|
||||
// no fallback yet, set one
|
||||
uuid = QUuid::createUuid();
|
||||
settings.setValue(FALLBACK_FINGERPRINT_KEY, uuid.toString());
|
||||
qDebug() << "no fallback machine fingerprint, setting it to: " << uuid.toString();
|
||||
qCDebug(networking) << "no fallback machine fingerprint, setting it to: " << uuid.toString();
|
||||
}
|
||||
}
|
||||
return uuid;
|
||||
|
|
|
@ -108,7 +108,7 @@ void HTTPResourceRequest::onRequestFinished() {
|
|||
case QNetworkReply::UnknownServerError: // Script.include('QUrl("https://httpbin.org/status/504")')
|
||||
case QNetworkReply::InternalServerError: // Script.include('QUrl("https://httpbin.org/status/500")')
|
||||
default:
|
||||
qDebug() << "HTTPResourceRequest error:" << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(_reply->error());
|
||||
qCDebug(networking) << "HTTPResourceRequest error:" << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(_reply->error());
|
||||
_result = Error;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -902,7 +902,7 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() {
|
|||
connect(_initialSTUNTimer.data(), &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest);
|
||||
|
||||
const int STUN_INITIAL_UPDATE_INTERVAL_MSECS = 250;
|
||||
_initialSTUNTimer->setInterval(STUN_INITIAL_UPDATE_INTERVAL_MSECS);
|
||||
_initialSTUNTimer->setInterval(STUN_INITIAL_UPDATE_INTERVAL_MSECS); // 250ms, Qt::CoarseTimer acceptable
|
||||
|
||||
// if we don't know the STUN IP yet we need to wait until it is known to start STUN requests
|
||||
if (_stunSockAddr.getAddress().isNull()) {
|
||||
|
|
|
@ -158,7 +158,7 @@ void NetworkPeer::activateMatchingOrNewSymmetricSocket(const HifiSockAddr& match
|
|||
}
|
||||
|
||||
void NetworkPeer::softReset() {
|
||||
qDebug() << "Soft reset ";
|
||||
qCDebug(networking) << "Soft reset ";
|
||||
// a soft reset should clear the sockets and reset the number of connection attempts
|
||||
_localSocket.clear();
|
||||
_publicSocket.clear();
|
||||
|
|
|
@ -102,7 +102,7 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
|
|||
connect(this, &LimitedNodeList::nodeActivated, this, &NodeList::maybeSendIgnoreSetToNode);
|
||||
|
||||
// setup our timer to send keepalive pings (it's started and stopped on domain connect/disconnect)
|
||||
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS);
|
||||
_keepAlivePingTimer.setInterval(KEEPALIVE_PING_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable
|
||||
connect(&_keepAlivePingTimer, &QTimer::timeout, this, &NodeList::sendKeepAlivePings);
|
||||
connect(&_domainHandler, SIGNAL(connectedToDomain(QString)), &_keepAlivePingTimer, SLOT(start()));
|
||||
connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, &_keepAlivePingTimer, &QTimer::stop);
|
||||
|
@ -373,9 +373,9 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
|
||||
packetStream << hardwareAddress;
|
||||
|
||||
// add in machine fingerprint
|
||||
QUuid machineFingerprint = FingerprintUtils::getMachineFingerprint();
|
||||
packetStream << machineFingerprint;
|
||||
// now add the machine fingerprint - a null UUID if logged in, real one if not logged in
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
packetStream << (accountManager->isLoggedIn() ? QUuid() : FingerprintUtils::getMachineFingerprint());
|
||||
}
|
||||
|
||||
// pack our data to send to the domain-server including
|
||||
|
@ -401,7 +401,7 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
|
||||
// so emit our signal that says that
|
||||
qDebug() << "Limit of silent domain checkins reached";
|
||||
qCDebug(networking) << "Limit of silent domain checkins reached";
|
||||
emit limitOfSilentDomainCheckInsReached();
|
||||
}
|
||||
|
||||
|
@ -629,7 +629,7 @@ void NodeList::processDomainServerAddedNode(QSharedPointer<ReceivedMessage> mess
|
|||
void NodeList::processDomainServerRemovedNode(QSharedPointer<ReceivedMessage> message) {
|
||||
// read the UUID from the packet, remove it if it exists
|
||||
QUuid nodeUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
qDebug() << "Received packet from domain-server to remove node with UUID" << uuidStringWithoutCurlyBraces(nodeUUID);
|
||||
qCDebug(networking) << "Received packet from domain-server to remove node with UUID" << uuidStringWithoutCurlyBraces(nodeUUID);
|
||||
killNodeWithUUID(nodeUUID);
|
||||
}
|
||||
|
||||
|
@ -793,7 +793,7 @@ void NodeList::ignoreNodeBySessionID(const QUuid& nodeID) {
|
|||
// write the node ID to the packet
|
||||
ignorePacket->write(nodeID.toRfc4122());
|
||||
|
||||
qDebug() << "Sending packet to ignore node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
qCDebug(networking) << "Sending packet to ignore node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
|
||||
// send off this ignore packet reliably to the matching node
|
||||
sendPacket(std::move(ignorePacket), *destinationNode);
|
||||
|
@ -855,7 +855,7 @@ void NodeList::kickNodeBySessionID(const QUuid& nodeID) {
|
|||
// write the node ID to the packet
|
||||
kickPacket->write(nodeID.toRfc4122());
|
||||
|
||||
qDebug() << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
qCDebug(networking) << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
|
||||
sendPacket(std::move(kickPacket), _domainHandler.getSockAddr());
|
||||
} else {
|
||||
|
@ -880,7 +880,7 @@ void NodeList::muteNodeBySessionID(const QUuid& nodeID) {
|
|||
// write the node ID to the packet
|
||||
mutePacket->write(nodeID.toRfc4122());
|
||||
|
||||
qDebug() << "Sending packet to mute node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
qCDebug(networking) << "Sending packet to mute node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
|
||||
sendPacket(std::move(mutePacket), *audioMixer);
|
||||
} else {
|
||||
|
@ -909,7 +909,7 @@ void NodeList::requestUsernameFromSessionID(const QUuid& nodeID) {
|
|||
usernameFromIDRequestPacket->write(nodeID.toRfc4122());
|
||||
}
|
||||
|
||||
qDebug() << "Sending packet to get username of node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
qCDebug(networking) << "Sending packet to get username of node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||
|
||||
sendPacket(std::move(usernameFromIDRequestPacket), _domainHandler.getSockAddr());
|
||||
} else {
|
||||
|
@ -923,8 +923,10 @@ void NodeList::processUsernameFromIDReply(QSharedPointer<ReceivedMessage> messag
|
|||
QString nodeUUIDString = (QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID))).toString();
|
||||
// read the username from the packet
|
||||
QString username = message->readString();
|
||||
// read the machine fingerprint from the packet
|
||||
QString machineFingerprintString = (QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID))).toString();
|
||||
|
||||
qDebug() << "Got username" << username << "for node" << nodeUUIDString;
|
||||
qCDebug(networking) << "Got username" << username << "and machine fingerprint" << machineFingerprintString << "for node" << nodeUUIDString;
|
||||
|
||||
emit usernameFromIDReply(nodeUUIDString, username);
|
||||
emit usernameFromIDReply(nodeUUIDString, username, machineFingerprintString);
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ signals:
|
|||
void receivedDomainServerList();
|
||||
void ignoredNode(const QUuid& nodeID);
|
||||
void ignoreRadiusEnabledChanged(bool isIgnored);
|
||||
void usernameFromIDReply(const QString& nodeID, const QString& username);
|
||||
void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint);
|
||||
|
||||
private slots:
|
||||
void stopKeepalivePingTimer();
|
||||
|
|
|
@ -324,8 +324,6 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer<ReceivedMessage> recei
|
|||
listenerIsDead = true;
|
||||
}
|
||||
} else {
|
||||
// qDebug() << "Got verified unsourced packet list: " << QString(nlPacketList->getMessage());
|
||||
|
||||
// one final check on the QPointer before we invoke
|
||||
if (listener.object) {
|
||||
success = listener.method.invoke(listener.object,
|
||||
|
|
|
@ -71,6 +71,11 @@ QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() {
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t ResourceCacheSharedItems::getLoadingRequestsCount() const {
|
||||
Lock lock(_mutex);
|
||||
return _loadingRequests.size();
|
||||
}
|
||||
|
||||
void ResourceCacheSharedItems::removeRequest(QWeakPointer<Resource> resource) {
|
||||
Lock lock(_mutex);
|
||||
|
||||
|
@ -463,6 +468,10 @@ int ResourceCache::getPendingRequestCount() {
|
|||
return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount();
|
||||
}
|
||||
|
||||
int ResourceCache::getLoadingRequestCount() {
|
||||
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequestsCount();
|
||||
}
|
||||
|
||||
bool ResourceCache::attemptRequest(QSharedPointer<Resource> resource) {
|
||||
Q_ASSERT(!resource.isNull());
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
uint32_t getPendingRequestsCount() const;
|
||||
QList<QSharedPointer<Resource>> getLoadingRequests();
|
||||
QSharedPointer<Resource> getHighestPendingRequest();
|
||||
uint32_t getLoadingRequestsCount() const;
|
||||
|
||||
private:
|
||||
ResourceCacheSharedItems() = default;
|
||||
|
@ -241,6 +242,8 @@ public:
|
|||
|
||||
static int getPendingRequestCount();
|
||||
|
||||
static int getLoadingRequestCount();
|
||||
|
||||
ResourceCache(QObject* parent = nullptr);
|
||||
virtual ~ResourceCache();
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "FileResourceRequest.h"
|
||||
#include "HTTPResourceRequest.h"
|
||||
#include "NetworkAccessManager.h"
|
||||
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
QThread ResourceManager::_thread;
|
||||
ResourceManager::PrefixMap ResourceManager::_prefixMap;
|
||||
|
@ -51,7 +51,7 @@ QString ResourceManager::normalizeURL(const QString& urlString) {
|
|||
const auto& prefix = entry.first;
|
||||
const auto& replacement = entry.second;
|
||||
if (result.startsWith(prefix)) {
|
||||
qDebug() << "Replacing " << prefix << " with " << replacement;
|
||||
qCDebug(networking) << "Replacing " << prefix << " with " << replacement;
|
||||
result.replace(0, prefix.size(), replacement);
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ ResourceRequest* ResourceManager::createResourceRequest(QObject* parent, const Q
|
|||
} else if (scheme == URL_SCHEME_ATP) {
|
||||
request = new AssetResourceRequest(normalizedURL);
|
||||
} else {
|
||||
qDebug() << "Unknown scheme (" << scheme << ") for URL: " << url.url();
|
||||
qCDebug(networking) << "Unknown scheme (" << scheme << ") for URL: " << url.url();
|
||||
return nullptr;
|
||||
}
|
||||
Q_ASSERT(request);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "SandboxUtils.h"
|
||||
#include "NetworkAccessManager.h"
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
|
||||
void SandboxUtils::ifLocalSandboxRunningElse(std::function<void()> localSandboxRunningDoThis,
|
||||
|
@ -64,10 +65,10 @@ void SandboxUtils::ifLocalSandboxRunningElse(std::function<void()> localSandboxR
|
|||
void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) {
|
||||
QString applicationDirPath = QFileInfo(QCoreApplication::applicationFilePath()).path();
|
||||
QString serverPath = applicationDirPath + "/server-console/server-console.exe";
|
||||
qDebug() << "Application dir path is: " << applicationDirPath;
|
||||
qDebug() << "Server path is: " << serverPath;
|
||||
qDebug() << "autoShutdown: " << autoShutdown;
|
||||
qDebug() << "noUpdater: " << noUpdater;
|
||||
qCDebug(networking) << "Application dir path is: " << applicationDirPath;
|
||||
qCDebug(networking) << "Server path is: " << serverPath;
|
||||
qCDebug(networking) << "autoShutdown: " << autoShutdown;
|
||||
qCDebug(networking) << "noUpdater: " << noUpdater;
|
||||
|
||||
bool hasContentPath = !contentPath.isEmpty();
|
||||
bool passArgs = autoShutdown || hasContentPath || noUpdater;
|
||||
|
@ -92,9 +93,9 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri
|
|||
args << "--noUpdater";
|
||||
}
|
||||
|
||||
qDebug() << applicationDirPath;
|
||||
qDebug() << "Launching sandbox with:" << args;
|
||||
qDebug() << QProcess::startDetached(serverPath, args);
|
||||
qCDebug(networking) << applicationDirPath;
|
||||
qCDebug(networking) << "Launching sandbox with:" << args;
|
||||
qCDebug(networking) << QProcess::startDetached(serverPath, args);
|
||||
|
||||
// Sleep a short amount of time to give the server a chance to start
|
||||
usleep(2000000); /// do we really need this??
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "ThreadedAssignment.h"
|
||||
|
||||
#include "NetworkLogging.h"
|
||||
|
||||
ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
|
||||
Assignment(message),
|
||||
_isFinished(false),
|
||||
|
@ -25,11 +27,11 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
|
|||
_statsTimer(this)
|
||||
{
|
||||
static const int STATS_TIMEOUT_MS = 1000;
|
||||
_statsTimer.setInterval(STATS_TIMEOUT_MS);
|
||||
_statsTimer.setInterval(STATS_TIMEOUT_MS); // 1s, Qt::CoarseTimer acceptable
|
||||
connect(&_statsTimer, &QTimer::timeout, this, &ThreadedAssignment::sendStatsPacket);
|
||||
|
||||
connect(&_domainServerTimer, &QTimer::timeout, this, &ThreadedAssignment::checkInWithDomainServerOrExit);
|
||||
_domainServerTimer.setInterval(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||
_domainServerTimer.setInterval(DOMAIN_SERVER_CHECK_IN_MSECS); // 1s, Qt::CoarseTimer acceptable
|
||||
|
||||
// if the NL tells us we got a DS response, clear our member variable of queued check-ins
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
@ -42,7 +44,7 @@ void ThreadedAssignment::setFinished(bool isFinished) {
|
|||
|
||||
if (_isFinished) {
|
||||
|
||||
qDebug() << "ThreadedAssignment::setFinished(true) called - finishing up.";
|
||||
qCDebug(networking) << "ThreadedAssignment::setFinished(true) called - finishing up.";
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
|
@ -109,7 +111,7 @@ void ThreadedAssignment::checkInWithDomainServerOrExit() {
|
|||
// verify that the number of queued check-ins is not >= our max
|
||||
// the number of queued check-ins is cleared anytime we get a response from the domain-server
|
||||
if (_numQueuedCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
qDebug() << "At least" << MAX_SILENT_DOMAIN_SERVER_CHECK_INS << "have been queued without a response from domain-server"
|
||||
qCDebug(networking) << "At least" << MAX_SILENT_DOMAIN_SERVER_CHECK_INS << "have been queued without a response from domain-server"
|
||||
<< "Stopping the current assignment";
|
||||
setFinished(true);
|
||||
} else {
|
||||
|
@ -122,6 +124,6 @@ void ThreadedAssignment::checkInWithDomainServerOrExit() {
|
|||
}
|
||||
|
||||
void ThreadedAssignment::domainSettingsRequestFailed() {
|
||||
qDebug() << "Failed to retreive settings object from domain-server. Bailing on assignment.";
|
||||
qCDebug(networking) << "Failed to retreive settings object from domain-server. Bailing on assignment.";
|
||||
setFinished(true);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "BasePacket.h"
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
||||
using namespace udt;
|
||||
|
||||
const qint64 BasePacket::PACKET_WRITE_ERROR = -1;
|
||||
|
@ -131,7 +133,7 @@ void BasePacket::setPayloadSize(qint64 payloadSize) {
|
|||
Q_ASSERT(payloadSize <= _payloadCapacity);
|
||||
_payloadSize = payloadSize;
|
||||
} else {
|
||||
qDebug() << "You can not call setPayloadSize for a non-writeable Packet.";
|
||||
qCDebug(networking) << "You can not call setPayloadSize for a non-writeable Packet.";
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "Socket.h"
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
||||
using namespace udt;
|
||||
|
||||
int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*");
|
||||
|
@ -106,7 +108,7 @@ Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& se
|
|||
}
|
||||
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*");
|
||||
qDebug() << qPrintable(debugString);
|
||||
qCDebug(networking) << qPrintable(debugString);
|
||||
#endif
|
||||
|
||||
obfuscate(NoObfuscation); // Undo obfuscation
|
||||
|
|
|
@ -44,7 +44,7 @@ const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
|
|||
PacketVersion versionForPacketType(PacketType packetType) {
|
||||
switch (packetType) {
|
||||
case PacketType::DomainList:
|
||||
return static_cast<PacketVersion>(DomainListVersion::GetUsernameFromUUIDSupport);
|
||||
return static_cast<PacketVersion>(DomainListVersion::GetMachineFingerprintFromUUIDSupport);
|
||||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
|
@ -53,7 +53,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::HasKillAvatarReason);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SessionDisplayName);
|
||||
case PacketType::ICEServerHeartbeat:
|
||||
return 18; // ICE Server Heartbeat signing
|
||||
case PacketType::AssetGetInfo:
|
||||
|
|
|
@ -103,7 +103,8 @@ public:
|
|||
RadiusIgnoreRequest,
|
||||
UsernameFromIDRequest,
|
||||
UsernameFromIDReply,
|
||||
LAST_PACKET_TYPE = UsernameFromIDReply
|
||||
ViewFrustum,
|
||||
LAST_PACKET_TYPE = ViewFrustum
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -205,7 +206,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
AbsoluteSixByteRotations,
|
||||
SensorToWorldMat,
|
||||
HandControllerJoints,
|
||||
HasKillAvatarReason
|
||||
HasKillAvatarReason,
|
||||
SessionDisplayName
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
@ -230,7 +232,8 @@ enum class DomainServerAddedNodeVersion : PacketVersion {
|
|||
enum class DomainListVersion : PacketVersion {
|
||||
PrePermissionsGrid = 18,
|
||||
PermissionsGrid,
|
||||
GetUsernameFromUUIDSupport
|
||||
GetUsernameFromUUIDSupport,
|
||||
GetMachineFingerprintFromUUIDSupport
|
||||
};
|
||||
|
||||
enum class AudioVersion : PacketVersion {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "PacketList.h"
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
using namespace udt;
|
||||
|
@ -102,7 +104,7 @@ std::unique_ptr<Packet> PacketList::createPacketWithExtendedHeader() {
|
|||
if (!_extendedHeader.isEmpty()) {
|
||||
// add the extended header to the front of the packet
|
||||
if (packet->write(_extendedHeader) == -1) {
|
||||
qDebug() << "Could not write extendedHeader in PacketList::createPacketWithExtendedHeader"
|
||||
qCDebug(networking) << "Could not write extendedHeader in PacketList::createPacketWithExtendedHeader"
|
||||
<< "- make sure that _extendedHeader is not larger than the payload capacity.";
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +197,7 @@ qint64 PacketList::writeData(const char* data, qint64 maxSize) {
|
|||
if (segmentSize + sizeRemaining > newPacket->getPayloadCapacity()) {
|
||||
// this is an unsupported case - the segment is bigger than the size of an individual packet
|
||||
// but the PacketList is not going to be sent ordered
|
||||
qDebug() << "Error in PacketList::writeData - attempted to write a segment to an unordered packet that is"
|
||||
qCDebug(networking) << "Error in PacketList::writeData - attempted to write a segment to an unordered packet that is"
|
||||
<< "larger than the payload size.";
|
||||
Q_ASSERT(false);
|
||||
|
||||
|
@ -220,7 +222,7 @@ qint64 PacketList::writeData(const char* data, qint64 maxSize) {
|
|||
if (sizeRemaining > newPacket->getPayloadCapacity()) {
|
||||
// this is an unsupported case - attempting to write a block of data larger
|
||||
// than the capacity of a new packet in an unordered PacketList
|
||||
qDebug() << "Error in PacketList::writeData - attempted to write data to an unordered packet that is"
|
||||
qCDebug(networking) << "Error in PacketList::writeData - attempted to write data to an unordered packet that is"
|
||||
<< "larger than the payload size.";
|
||||
Q_ASSERT(false);
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <Trace.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
||||
using namespace udt;
|
||||
using namespace std::chrono;
|
||||
|
||||
|
@ -299,12 +301,12 @@ void SendQueue::run() {
|
|||
// we've already been asked to stop before we even got a chance to start
|
||||
// don't start now
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
qDebug() << "SendQueue asked to run after being told to stop. Will not run.";
|
||||
qCDebug(networking) << "SendQueue asked to run after being told to stop. Will not run.";
|
||||
#endif
|
||||
return;
|
||||
} else if (_state == State::Running) {
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
qDebug() << "SendQueue asked to run but is already running (according to state). Will not re-run.";
|
||||
qCDebug(networking) << "SendQueue asked to run but is already running (according to state). Will not re-run.";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -282,7 +282,7 @@ void Socket::clearConnections() {
|
|||
|
||||
if (_connectionsHash.size() > 0) {
|
||||
// clear all of the current connections in the socket
|
||||
qDebug() << "Clearing all remaining connections in Socket.";
|
||||
qCDebug(networking) << "Clearing all remaining connections in Socket.";
|
||||
_connectionsHash.clear();
|
||||
}
|
||||
}
|
||||
|
|
16
libraries/octree/src/Logging.h
Normal file
16
libraries/octree/src/Logging.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Created by Brad Hefta-Gaub on 2016-12-19
|
||||
// Copyright 2013-2016 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
|
||||
//
|
||||
|
||||
#ifndef hifi_octree_Logging_h
|
||||
#define hifi_octree_Logging_h
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(octree)
|
||||
|
||||
#endif // hifi_octree_Logging_h
|
|
@ -23,6 +23,7 @@
|
|||
#include <PerfStat.h>
|
||||
|
||||
#include "AACube.h"
|
||||
#include "Logging.h"
|
||||
#include "OctalCode.h"
|
||||
#include "Octree.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
@ -444,18 +445,12 @@ void OctreeElement::printDebugDetails(const char* label) const {
|
|||
}
|
||||
}
|
||||
|
||||
QDebug elementDebug = qDebug().nospace();
|
||||
|
||||
QString resultString;
|
||||
resultString.sprintf("%s - Voxel at corner=(%f,%f,%f) size=%f\n isLeaf=%s isDirty=%s shouldRender=%s\n children=", label,
|
||||
(double)_cube.getCorner().x, (double)_cube.getCorner().y, (double)_cube.getCorner().z,
|
||||
(double)_cube.getScale(),
|
||||
debug::valueOf(isLeaf()), debug::valueOf(isDirty()), debug::valueOf(getShouldRender()));
|
||||
elementDebug << resultString;
|
||||
|
||||
outputBits(childBits, &elementDebug);
|
||||
qDebug("octalCode=");
|
||||
printOctalCode(getOctalCode());
|
||||
qCDebug(octree).nospace() << resultString;
|
||||
}
|
||||
|
||||
float OctreeElement::getEnclosingRadius() const {
|
||||
|
|
|
@ -234,7 +234,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
static QString repeatedMessage =
|
||||
LogHandler::getInstance().addRepeatedMessageRegex("EntityMotionState::setWorldTransform "
|
||||
"setPosition failed.*");
|
||||
qDebug() << "EntityMotionState::setWorldTransform setPosition failed" << _entity->getID();
|
||||
qCDebug(physics) << "EntityMotionState::setWorldTransform setPosition failed" << _entity->getID();
|
||||
}
|
||||
bool orientationSuccess;
|
||||
_entity->setOrientation(bulletToGLM(worldTrans.getRotation()), orientationSuccess, false);
|
||||
|
@ -242,7 +242,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
|
|||
static QString repeatedMessage =
|
||||
LogHandler::getInstance().addRepeatedMessageRegex("EntityMotionState::setWorldTransform "
|
||||
"setOrientation failed.*");
|
||||
qDebug() << "EntityMotionState::setWorldTransform setOrientation failed" << _entity->getID();
|
||||
qCDebug(physics) << "EntityMotionState::setWorldTransform setOrientation failed" << _entity->getID();
|
||||
}
|
||||
_entity->setVelocity(getBodyLinearVelocity());
|
||||
_entity->setAngularVelocity(getBodyAngularVelocity());
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#include "ObjectAction.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
|
||||
ObjectAction::ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
btActionInterface(),
|
||||
EntityActionInterface(type, id),
|
||||
|
@ -32,7 +35,7 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta
|
|||
});
|
||||
|
||||
if (!ownerEntity) {
|
||||
qDebug() << "warning -- action with no entity removing self from btCollisionWorld.";
|
||||
qCDebug(physics) << "warning -- action with no entity removing self from btCollisionWorld.";
|
||||
btDynamicsWorld* dynamicsWorld = static_cast<btDynamicsWorld*>(collisionWorld);
|
||||
if (dynamicsWorld) {
|
||||
dynamicsWorld->removeAction(this);
|
||||
|
@ -242,7 +245,7 @@ void ObjectAction::activateBody(bool forceActivation) {
|
|||
if (rigidBody) {
|
||||
rigidBody->activate(forceActivation);
|
||||
} else {
|
||||
qDebug() << "ObjectAction::activateBody -- no rigid body" << (void*)rigidBody;
|
||||
qCDebug(physics) << "ObjectAction::activateBody -- no rigid body" << (void*)rigidBody;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#include "ObjectActionOffset.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
|
||||
const uint16_t ObjectActionOffset::offsetVersion = 1;
|
||||
|
||||
ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
|
@ -22,13 +25,13 @@ ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerE
|
|||
_linearTimeScale(FLT_MAX),
|
||||
_positionalTargetSet(false) {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionOffset::ObjectActionOffset";
|
||||
qCDebug(physics) << "ObjectActionOffset::ObjectActionOffset";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionOffset::~ObjectActionOffset() {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionOffset::~ObjectActionOffset";
|
||||
qCDebug(physics) << "ObjectActionOffset::~ObjectActionOffset";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -47,7 +50,7 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
|
|||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
||||
if (!rigidBody) {
|
||||
qDebug() << "ObjectActionOffset::updateActionWorker no rigidBody";
|
||||
qCDebug(physics) << "ObjectActionOffset::updateActionWorker no rigidBody";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "ObjectActionSpring.h"
|
||||
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
const float SPRING_MAX_SPEED = 10.0f;
|
||||
|
||||
const uint16_t ObjectActionSpring::springVersion = 1;
|
||||
|
@ -29,13 +31,13 @@ ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerE
|
|||
_angularTimeScale(FLT_MAX),
|
||||
_rotationalTargetSet(true) {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionSpring::ObjectActionSpring";
|
||||
qCDebug(physics) << "ObjectActionSpring::ObjectActionSpring";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionSpring::~ObjectActionSpring() {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionSpring::~ObjectActionSpring";
|
||||
qCDebug(physics) << "ObjectActionSpring::~ObjectActionSpring";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -126,7 +128,7 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
||||
if (!rigidBody) {
|
||||
qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody";
|
||||
qCDebug(physics) << "ObjectActionSpring::updateActionWorker no rigidBody";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "QVariantGLM.h"
|
||||
#include "ObjectActionTravelOriented.h"
|
||||
#include "PhysicsLogging.h"
|
||||
|
||||
const uint16_t ObjectActionTravelOriented::actionVersion = 1;
|
||||
|
||||
|
@ -20,13 +21,13 @@ const uint16_t ObjectActionTravelOriented::actionVersion = 1;
|
|||
ObjectActionTravelOriented::ObjectActionTravelOriented(const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
ObjectAction(ACTION_TYPE_TRAVEL_ORIENTED, id, ownerEntity) {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionTravelOriented::ObjectActionTravelOriented";
|
||||
qCDebug(physics) << "ObjectActionTravelOriented::ObjectActionTravelOriented";
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionTravelOriented::~ObjectActionTravelOriented() {
|
||||
#if WANT_DEBUG
|
||||
qDebug() << "ObjectActionTravelOriented::~ObjectActionTravelOriented";
|
||||
qCDebug(physics) << "ObjectActionTravelOriented::~ObjectActionTravelOriented";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -43,7 +44,7 @@ void ObjectActionTravelOriented::updateActionWorker(btScalar deltaTimeStep) {
|
|||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
||||
if (!rigidBody) {
|
||||
qDebug() << "ObjectActionTravelOriented::updateActionWorker no rigidBody";
|
||||
qCDebug(physics) << "ObjectActionTravelOriented::updateActionWorker no rigidBody";
|
||||
return;
|
||||
}
|
||||
const float MAX_TIMESCALE = 600.0f; // 10 min is a long time
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <QtCore/QSize>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
@ -194,6 +195,9 @@ public:
|
|||
virtual float newFramePresentRate() const { return -1.0f; }
|
||||
// Rate at which rendered frames are being skipped
|
||||
virtual float droppedFrameRate() const { return -1.0f; }
|
||||
|
||||
// Hardware specific stats
|
||||
virtual QJsonObject getHardwareStats() const { return QJsonObject(); }
|
||||
|
||||
uint32_t presentCount() const { return _presentedFrameIndex; }
|
||||
// Time since last call to incrementPresentCount (only valid if DEBUG_PAINT_DELAY is defined)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue