From 38623e108a621fe55e193e4d87108c358697874c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 11 Jul 2014 15:37:59 -0700 Subject: [PATCH 01/16] Delete persister when its thread finishes, copy metavoxel nodes on subdivision so that we'll know that they changed. --- .../src/metavoxels/MetavoxelServer.cpp | 1 + .../metavoxels/src/AttributeRegistry.cpp | 6 ++- libraries/metavoxels/src/MetavoxelData.cpp | 46 +++++++++++++------ libraries/metavoxels/src/MetavoxelData.h | 7 +-- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 4d9c45ed6c..598d8ea722 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -55,6 +55,7 @@ void MetavoxelServer::run() { _persister = new MetavoxelPersister(this); QThread* persistenceThread = new QThread(this); _persister->moveToThread(persistenceThread); + _persister->connect(persistenceThread, SIGNAL(finished()), SLOT(deleteLater())); persistenceThread->start(); // queue up the load diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 64b2646261..670f0be389 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -213,7 +213,11 @@ void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNo } void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { - data.getRoot(state.attribute)->readSubdivision(state); + // copy if changed + MetavoxelNode* root = data.getRoot(state.attribute); + if (root->readSubdivision(state)) { + data.setRoot(state.attribute, new MetavoxelNode(state.attribute, root)); + } } void Attribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 1362731a8a..72d5392a39 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -603,12 +603,18 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO } } -MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { - MetavoxelNode*& root = _roots[attribute]; - if (root) { - root->decrementReferenceCount(attribute); +void MetavoxelData::setRoot(const AttributePointer& attribute, MetavoxelNode* root) { + MetavoxelNode*& rootReference = _roots[attribute]; + if (rootReference) { + rootReference->decrementReferenceCount(attribute); } - return root = new MetavoxelNode(attribute); + rootReference = root; +} + +MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { + MetavoxelNode* root = new MetavoxelNode(attribute); + setRoot(attribute, root); + return root; } bool MetavoxelData::deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod) const { @@ -843,10 +849,12 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta _children[i] = new MetavoxelNode(state.attribute); _children[i]->readDelta(*reference._children[i], nextState); } else { - _children[i] = reference._children[i]; - _children[i]->incrementReferenceCount(); - if (nextState.becameSubdivided()) { - _children[i]->readSubdivision(nextState); + if (nextState.becameSubdivided() && reference._children[i]->readSubdivision(nextState)) { + _children[i] = new MetavoxelNode(state.attribute, reference._children[i]); + + } else { + _children[i] = reference._children[i]; + _children[i]->incrementReferenceCount(); } } } @@ -888,7 +896,7 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt } } -void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { +bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { bool leaf; bool subdivideReference = state.shouldSubdivideReference(); if (!subdivideReference) { @@ -897,7 +905,7 @@ void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { leaf = isLeaf(); } if (leaf) { - clearChildren(state.attribute); + return clearChildren(state.attribute); } else { MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, @@ -909,13 +917,22 @@ void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { _children[i] = new MetavoxelNode(state.attribute); _children[i]->read(nextState); } + return true; + } else { + bool changed = false; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); if (nextState.becameSubdivided()) { - _children[i]->readSubdivision(nextState); + if (_children[i]->readSubdivision(nextState)) { + MetavoxelNode* oldNode = _children[i]; + _children[i] = new MetavoxelNode(state.attribute, oldNode); + oldNode->decrementReferenceCount(state.attribute); + changed = true; + } } } + return changed; } } } @@ -1042,13 +1059,16 @@ void MetavoxelNode::destroy(const AttributePointer& attribute) { } } -void MetavoxelNode::clearChildren(const AttributePointer& attribute) { +bool MetavoxelNode::clearChildren(const AttributePointer& attribute) { + bool cleared = false; for (int i = 0; i < CHILD_COUNT; i++) { if (_children[i]) { _children[i]->decrementReferenceCount(attribute); _children[i] = NULL; + cleared = true; } } + return cleared; } bool MetavoxelNode::deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index f558bf8e80..ac8f0cc023 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -118,7 +118,8 @@ public: void writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, Bitstream& out, const MetavoxelLOD& lod) const; - MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } + void setRoot(const AttributePointer& attribute, MetavoxelNode* root); + MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } MetavoxelNode* createRoot(const AttributePointer& attribute); /// Performs a deep comparison between this data and the specified other (as opposed to the == operator, which does a @@ -200,7 +201,7 @@ public: void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state); void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const; - void readSubdivision(MetavoxelStreamState& state); + bool readSubdivision(MetavoxelStreamState& state); void writeSubdivision(MetavoxelStreamState& state) const; void writeSpanners(MetavoxelStreamState& state) const; @@ -216,7 +217,7 @@ public: void destroy(const AttributePointer& attribute); - void clearChildren(const AttributePointer& attribute); + bool clearChildren(const AttributePointer& attribute); /// Performs a deep comparison between this and the specified other node. bool deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, From 5e34bcc4233b8caec3442fcc47c8e25e26915c5b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 11 Jul 2014 15:51:36 -0700 Subject: [PATCH 02/16] Some additional comments. --- libraries/metavoxels/src/DatagramSequencer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.h b/libraries/metavoxels/src/DatagramSequencer.h index 4a01679c68..9a1f5a4ae0 100644 --- a/libraries/metavoxels/src/DatagramSequencer.h +++ b/libraries/metavoxels/src/DatagramSequencer.h @@ -426,9 +426,9 @@ private: int _writePositionResetPacketNumber; SpanList _acknowledged; bool _messagesEnabled; - int _messageLengthPlaceholder; - int _messageReceivedOffset; - int _messageSize; + int _messageLengthPlaceholder; ///< the location in the buffer of the message length for the current message + int _messageReceivedOffset; ///< when reached, indicates that the most recent sent message has been received + int _messageSize; ///< the size of the most recent sent message; only valid when _messageReceivedOffset has been set }; #endif // hifi_DatagramSequencer_h From e32bab5b0469a741e73da94f279f26c50d419031 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 14 Jul 2014 14:32:55 -0700 Subject: [PATCH 03/16] Beginnings of some metavoxel scriptability, to create some test landscapes. --- interface/src/Application.cpp | 1 + libraries/metavoxels/src/Bitstream.cpp | 7 +++++++ libraries/metavoxels/src/Bitstream.h | 5 +++++ .../metavoxels/src/MetavoxelClientManager.cpp | 19 +++++++++++++++++++ .../metavoxels/src/MetavoxelClientManager.h | 4 ++++ 5 files changed, 36 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f13a92bba0..7219a019d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3641,6 +3641,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine->registerGlobalObject("AnimationCache", &_animationCache); scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 0d4f8a52b4..2e9e641d88 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,12 @@ QList Bitstream::getMetaObjectSubClasses(const QMetaObject* return getMetaObjectSubClasses().values(metaObject); } +void Bitstream::configureScriptEngine(QScriptEngine* engine) { + foreach (const QMetaObject* metaObject, getMetaObjects()) { + engine->globalObject().setProperty(metaObject->className(), engine->newQMetaObject(metaObject)); + } +} + Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, GenericsMode genericsMode, QObject* parent) : QObject(parent), _underlying(underlying), diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index dacfeb2ee9..04b4dc97fc 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -32,6 +32,7 @@ class QByteArray; class QColor; class QDataStream; +class QScriptEngine; class QScriptValue; class QUrl; @@ -320,6 +321,10 @@ public: /// subclasses. static QList getMetaObjectSubClasses(const QMetaObject* metaObject); + /// Configures the supplied script engine with our registered meta-objects, allowing all of them to be instantiated from + /// scripts. + static void configureScriptEngine(QScriptEngine* engine); + enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA }; enum GenericsMode { NO_GENERICS, FALLBACK_GENERICS, ALL_GENERICS }; diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index f3ea1ae8c5..ff02398b85 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "MetavoxelClientManager.h" #include "MetavoxelMessages.h" @@ -53,7 +55,24 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons return closestSpanner; } +void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, QRgb color) { + Sphere* sphere = new Sphere(); + sphere->setTranslation(center); + sphere->setScale(radius); + sphere->setColor(color); + setSpanner(sphere); +} + +void MetavoxelClientManager::setSpanner(const SharedObjectPointer& object, bool reliable) { + MetavoxelEditMessage edit = { QVariant::fromValue(SetSpannerEdit(object)) }; + applyEdit(edit, reliable); +} + void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool reliable) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable)); + return; + } foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index ad6c86c8fc..7537d7f971 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -28,6 +28,10 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance); + + Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, QRgb color = 0x808080); + + Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false); Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); From 9d5510008797e288ffa4f79620a1fc2059e2b1de Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 09:31:23 -0700 Subject: [PATCH 04/16] Merge (but don't clear redundant nodes) after reading subdivisions. --- libraries/metavoxels/src/MetavoxelData.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 72d5392a39..fdce323708 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -767,7 +767,7 @@ void MetavoxelNode::mergeChildren(const AttributePointer& attribute, bool postRe childValues[i] = _children[i]->_attributeValue; allLeaves &= _children[i]->isLeaf(); } - if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves) { + if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves && !postRead) { clearChildren(attribute); } } @@ -917,6 +917,7 @@ bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { _children[i] = new MetavoxelNode(state.attribute); _children[i]->read(nextState); } + mergeChildren(state.attribute, true); return true; } else { @@ -932,6 +933,9 @@ bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { } } } + if (changed) { + mergeChildren(state.attribute, true); + } return changed; } } From 0068428c7c7c399c5a3980344db84c0bc9c1bd4e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 15 Jul 2014 10:41:29 -0700 Subject: [PATCH 05/16] fixed some warnings --- interface/src/devices/MIDIManager.cpp | 2 + libraries/particles/src/Particle.cpp | 40 +++++++++---------- .../particles/src/ParticleCollisionSystem.cpp | 3 -- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/interface/src/devices/MIDIManager.cpp b/interface/src/devices/MIDIManager.cpp index 52ae2eb645..54428d273d 100644 --- a/interface/src/devices/MIDIManager.cpp +++ b/interface/src/devices/MIDIManager.cpp @@ -44,7 +44,9 @@ MIDIManager::~MIDIManager() { #endif } +#ifdef HAVE_RTMIDI const int DEFAULT_MIDI_PORT = 0; +#endif void MIDIManager::openDefaultPort() { #ifdef HAVE_RTMIDI diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 814da636c1..5fffefd8b1 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -368,7 +368,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr uint32_t editID; // check to make sure we have enough content to keep reading... - if (length - processedBytes - sizeof(editID) < 0) { + if (length - (processedBytes + (int)sizeof(editID)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -387,7 +387,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr uint32_t creatorTokenID; // check to make sure we have enough content to keep reading... - if (length - processedBytes - sizeof(creatorTokenID) < 0) { + if (length - (processedBytes + (int)sizeof(creatorTokenID)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -426,7 +426,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // lastEdited // check to make sure we have enough content to keep reading... - if (length - processedBytes - sizeof(newParticle._lastEdited) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._lastEdited)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -439,7 +439,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // properties included bits uint16_t packetContainsBits = 0; if (!isNewParticle) { - if (length - processedBytes - sizeof(packetContainsBits) < 0) { + if (length - (processedBytes + (int)sizeof(packetContainsBits)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -452,7 +452,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // radius if (isNewParticle || ((packetContainsBits & CONTAINS_RADIUS) == CONTAINS_RADIUS)) { - if (length - processedBytes - sizeof(newParticle._radius) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._radius)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -464,7 +464,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // position if (isNewParticle || ((packetContainsBits & CONTAINS_POSITION) == CONTAINS_POSITION)) { - if (length - processedBytes - sizeof(newParticle._position) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._position)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -476,7 +476,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // color if (isNewParticle || ((packetContainsBits & CONTAINS_COLOR) == CONTAINS_COLOR)) { - if (length - processedBytes - sizeof(newParticle._color) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._color)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -488,7 +488,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // velocity if (isNewParticle || ((packetContainsBits & CONTAINS_VELOCITY) == CONTAINS_VELOCITY)) { - if (length - processedBytes - sizeof(newParticle._velocity) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._velocity)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -500,7 +500,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // gravity if (isNewParticle || ((packetContainsBits & CONTAINS_GRAVITY) == CONTAINS_GRAVITY)) { - if (length - processedBytes - sizeof(newParticle._gravity) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._gravity)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -512,7 +512,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // damping if (isNewParticle || ((packetContainsBits & CONTAINS_DAMPING) == CONTAINS_DAMPING)) { - if (length - processedBytes - sizeof(newParticle._damping) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._damping)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -524,7 +524,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // lifetime if (isNewParticle || ((packetContainsBits & CONTAINS_LIFETIME) == CONTAINS_LIFETIME)) { - if (length - processedBytes - sizeof(newParticle._lifetime) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._lifetime)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -537,7 +537,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // TODO: make inHand and shouldDie into single bits // inHand if (isNewParticle || ((packetContainsBits & CONTAINS_INHAND) == CONTAINS_INHAND)) { - if (length - processedBytes - sizeof(newParticle._inHand) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._inHand)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -549,7 +549,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // shouldDie if (isNewParticle || ((packetContainsBits & CONTAINS_SHOULDDIE) == CONTAINS_SHOULDDIE)) { - if (length - processedBytes - sizeof(newParticle._shouldDie) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._shouldDie)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -562,7 +562,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // script if (isNewParticle || ((packetContainsBits & CONTAINS_SCRIPT) == CONTAINS_SCRIPT)) { uint16_t scriptLength; - if (length - processedBytes - sizeof(scriptLength) < 0) { + if (length - (processedBytes + (int)sizeof(scriptLength)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -571,7 +571,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr dataAt += sizeof(scriptLength); processedBytes += sizeof(scriptLength); - if (length - processedBytes - scriptLength < 0) { + if (length - (processedBytes + (int)scriptLength) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -585,7 +585,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelURL if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_URL) == CONTAINS_MODEL_URL)) { uint16_t modelURLLength; - if (length - processedBytes - sizeof(modelURLLength) < 0) { + if (length - (processedBytes + (int)sizeof(modelURLLength)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -594,7 +594,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr dataAt += sizeof(modelURLLength); processedBytes += sizeof(modelURLLength); - if (length - processedBytes - modelURLLength < 0) { + if (length - (processedBytes + (int)modelURLLength) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -607,7 +607,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelScale if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - if (length - processedBytes - sizeof(newParticle._modelScale) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._modelScale)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -619,7 +619,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { - if (length - processedBytes - sizeof(newParticle._modelTranslation) < 0) { + if (length - (processedBytes + (int)sizeof(newParticle._modelTranslation)) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -632,7 +632,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelRotation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_ROTATION) == CONTAINS_MODEL_ROTATION)) { const int expectedBytesForPackedQuat = sizeof(uint16_t) * 4; // this is how we pack the quats - if (length - processedBytes - expectedBytesForPackedQuat < 0) { + if (length - (processedBytes + expectedBytesForPackedQuat) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 0291690c3d..17d1dd3bc6 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -181,9 +181,6 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA) } } -// MIN_VALID_SPEED is obtained by computing speed gained at one gravity after the shortest expected frame -const float MIN_EXPECTED_FRAME_PERIOD = 0.0167f; // 1/60th of a second - void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { // particles that are in hand, don't collide with avatars if (!_avatars || particle->getInHand()) { From a1b2bf59e9ebcb5b367fb808ff63f3aad130d9f5 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 15 Jul 2014 12:23:02 -0700 Subject: [PATCH 06/16] disabled SIMD adds in AudioMixer for windows --- assignment-client/src/audio/AudioMixer.cpp | 35 +++++++++++++++++-- .../audio/src/PositionalAudioRingBuffer.cpp | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index c86d37e283..60f905f20a 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -231,6 +231,12 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; +#ifdef _WIN32 + _clientSamples[s + goodChannelOffset] += correctBufferSample[0]; + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] += correctBufferSample[1]; + _clientSamples[delayedChannelIndex] += delayBufferSample[0]; + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] += delayBufferSample[1]; +#else __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET], _clientSamples[delayedChannelIndex], @@ -247,6 +253,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2]; _clientSamples[delayedChannelIndex] = shortResults[1]; _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0]; +#endif } // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid @@ -271,6 +278,13 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf while (i + 3 < numSamplesDelay) { // handle the first cases where we can MMX add four samples at once int parentIndex = i * 2; + +#ifdef _WIN32 + _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio; +#else __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], @@ -286,7 +300,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0]; - +#endif + // push the index i += 4; } @@ -296,6 +311,11 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf if (i + 2 < numSamplesDelay) { // MMX add only three delayed samples +#ifdef _WIN32 + _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio; +#else __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], @@ -310,8 +330,15 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; +#endif + } else if (i + 1 < numSamplesDelay) { + +#ifdef _WIN32 + _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; +#else // MMX add two delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], @@ -324,9 +351,12 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - +#endif } else if (i < numSamplesDelay) { // MMX add a single delayed sample +#ifdef _WIN32 + _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; +#else __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0); @@ -334,6 +364,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; +#endif } } } else { diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 8cba6d72b0..c9a58b2210 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -149,6 +149,7 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { // fixes bug on Windows where _nextOutputTrailingLoudness sometimes becomes NaN. In that case, // revert _nextOutputTrailingLoudness to its previous value if (isNaN(_nextOutputTrailingLoudness)) { + printf("next output trailling loudness NaN!! --------------------------------------\n"); _nextOutputTrailingLoudness = oldNextOutputTrailingLoudness; } } From 828410b7d6b80f930de864aaace331437e7669a3 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 15 Jul 2014 12:23:54 -0700 Subject: [PATCH 07/16] removed isNan check for _nextOutputTrailingLoudness --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index c9a58b2210..a0ce74dbaf 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -145,13 +145,6 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { _nextOutputTrailingLoudness = 0; } } - - // fixes bug on Windows where _nextOutputTrailingLoudness sometimes becomes NaN. In that case, - // revert _nextOutputTrailingLoudness to its previous value - if (isNaN(_nextOutputTrailingLoudness)) { - printf("next output trailling loudness NaN!! --------------------------------------\n"); - _nextOutputTrailingLoudness = oldNextOutputTrailingLoudness; - } } bool PositionalAudioRingBuffer::shouldBeAddedToMix() { From 871aa2790a6f380e6b256e6bafe22455d208db36 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 15 Jul 2014 12:24:28 -0700 Subject: [PATCH 08/16] forgot unused variable --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index a0ce74dbaf..6c7ecd1cad 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -135,7 +135,6 @@ void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; const float LOUDNESS_EPSILON = 0.000001f; - float oldNextOutputTrailingLoudness = _nextOutputTrailingLoudness; if (nextLoudness >= _nextOutputTrailingLoudness) { _nextOutputTrailingLoudness = nextLoudness; } else { From e2c8bdbdbed6468d4c72b056d54faf36ca707e1a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 13:22:50 -0700 Subject: [PATCH 09/16] Create new nodes on subdivision. --- .../metavoxels/src/AttributeRegistry.cpp | 7 +- libraries/metavoxels/src/MetavoxelData.cpp | 97 +++++++++---------- libraries/metavoxels/src/MetavoxelData.h | 2 +- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 670f0be389..1cd41500fc 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -214,9 +214,10 @@ void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNo void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { // copy if changed - MetavoxelNode* root = data.getRoot(state.attribute); - if (root->readSubdivision(state)) { - data.setRoot(state.attribute, new MetavoxelNode(state.attribute, root)); + MetavoxelNode* oldRoot = data.getRoot(state.attribute); + MetavoxelNode* newRoot = oldRoot->readSubdivision(state); + if (newRoot != oldRoot) { + data.setRoot(state.attribute, newRoot); } } diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index fdce323708..a3ea5ca189 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -849,9 +849,11 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta _children[i] = new MetavoxelNode(state.attribute); _children[i]->readDelta(*reference._children[i], nextState); } else { - if (nextState.becameSubdivided() && reference._children[i]->readSubdivision(nextState)) { - _children[i] = new MetavoxelNode(state.attribute, reference._children[i]); - + if (nextState.becameSubdivided()) { + _children[i] = reference._children[i]->readSubdivision(nextState); + if (_children[i] == reference._children[i]) { + _children[i]->incrementReferenceCount(); + } } else { _children[i] = reference._children[i]; _children[i]->incrementReferenceCount(); @@ -896,71 +898,68 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt } } -bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { - bool leaf; - bool subdivideReference = state.shouldSubdivideReference(); - if (!subdivideReference) { +MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { + if (!state.shouldSubdivideReference()) { + bool leaf; state.stream >> leaf; - } else { - leaf = isLeaf(); - } - if (leaf) { - return clearChildren(state.attribute); - - } else { - MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, - state.stream, state.lod, state.referenceLOD }; - if (!subdivideReference) { - clearChildren(state.attribute); - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new MetavoxelNode(state.attribute); - _children[i]->read(nextState); - } - mergeChildren(state.attribute, true); - return true; + if (leaf) { + return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.attribute)); } else { - bool changed = false; + MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.attribute)); + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - if (_children[i]->readSubdivision(nextState)) { - MetavoxelNode* oldNode = _children[i]; - _children[i] = new MetavoxelNode(state.attribute, oldNode); - oldNode->decrementReferenceCount(state.attribute); - changed = true; + newNode->_children[i] = new MetavoxelNode(state.attribute); + newNode->_children[i]->read(nextState); + } + return newNode; + } + } else if (!isLeaf()) { + MetavoxelNode* node = this; + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdivided()) { + MetavoxelNode* child = _children[i]->readSubdivision(nextState); + if (child != _children[i]) { + if (node == this) { + node = new MetavoxelNode(state.attribute, this); } + node->_children[i] = child; + _children[i]->decrementReferenceCount(state.attribute); } } - if (changed) { - mergeChildren(state.attribute, true); - } - return changed; } + if (node != this) { + node->mergeChildren(state.attribute, true); + } + return node; } + return this; } void MetavoxelNode::writeSubdivision(MetavoxelStreamState& state) const { bool leaf = isLeaf(); - bool subdivideReference = state.shouldSubdivideReference(); - if (!subdivideReference) { + if (!state.shouldSubdivideReference()) { state.stream << leaf; - } - if (!leaf) { - MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, - state.stream, state.lod, state.referenceLOD }; - if (!subdivideReference) { + if (!leaf) { + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); _children[i]->write(nextState); } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } + } + } else if (!leaf) { + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdivided()) { + _children[i]->writeSubdivision(nextState); } } } diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index ac8f0cc023..eeab5bd0f4 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -201,7 +201,7 @@ public: void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state); void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const; - bool readSubdivision(MetavoxelStreamState& state); + MetavoxelNode* readSubdivision(MetavoxelStreamState& state); void writeSubdivision(MetavoxelStreamState& state) const; void writeSpanners(MetavoxelStreamState& state) const; From d5a30ff6eedbb00bf0d850f903a68686b776b7c9 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 15 Jul 2014 14:43:08 -0700 Subject: [PATCH 10/16] removed SIMD stuff from AudioMixer for all builds --- assignment-client/src/audio/AudioMixer.cpp | 111 +-------------------- 1 file changed, 2 insertions(+), 109 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 60f905f20a..076769d989 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -231,29 +231,10 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; -#ifdef _WIN32 _clientSamples[s + goodChannelOffset] += correctBufferSample[0]; _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] += correctBufferSample[1]; _clientSamples[delayedChannelIndex] += delayBufferSample[0]; _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] += delayBufferSample[1]; -#else - __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], - _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET], - _clientSamples[delayedChannelIndex], - _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET]); - __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], - delayBufferSample[0], delayBufferSample[1]); - - // perform the MMX add (with saturation) of two correct and delayed samples - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addedSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - // assign the results from the result of the mmx arithmetic - _clientSamples[s + goodChannelOffset] = shortResults[3]; - _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2]; - _clientSamples[delayedChannelIndex] = shortResults[1]; - _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0]; -#endif } // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid @@ -273,98 +254,10 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; } - int i = 0; - - while (i + 3 < numSamplesDelay) { - // handle the first cases where we can MMX add four samples at once + + for (int i = 0; i < numSamplesDelay; i++) { int parentIndex = i * 2; - -#ifdef _WIN32 _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio; -#else - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio); - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; - _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0]; -#endif - - // push the index - i += 4; - } - - int parentIndex = i * 2; - - if (i + 2 < numSamplesDelay) { - // MMX add only three delayed samples - -#ifdef _WIN32 - _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio; -#else - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], - 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, - 0); - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; -#endif - - - } else if (i + 1 < numSamplesDelay) { - -#ifdef _WIN32 - _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] += delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio; -#else - // MMX add two delayed samples - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], - 0, 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, - delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); - - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; -#endif - } else if (i < numSamplesDelay) { - // MMX add a single delayed sample -#ifdef _WIN32 - _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; -#else - __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0); - __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0); - - __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); - int16_t* shortResults = reinterpret_cast(&mmxResult); - - _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; -#endif } } } else { From abca4661f4e6dfdd863dcd6d2964d9d3972ed0ef Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 15 Jul 2014 14:48:26 -0700 Subject: [PATCH 11/16] removed space --- assignment-client/src/audio/AudioMixer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 076769d989..b008a20aa7 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -254,7 +254,6 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; } - for (int i = 0; i < numSamplesDelay; i++) { int parentIndex = i * 2; _clientSamples[parentIndex + delayedChannelOffset] += delayNextOutputStart[i] * attenuationAndWeakChannelRatio; From ebcb8d00d61c2ddf99afbac30dd82f9f5fe94c73 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 15:47:31 -0700 Subject: [PATCH 12/16] Unfortunately, the early test for subdivision doesn't work, which means that, for now, we need to traverse the entire tree to find subdivided nodes. To be revisited. --- libraries/metavoxels/src/MetavoxelData.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index a3ea5ca189..41cf2b2a20 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -47,13 +47,8 @@ bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size, if (!shouldSubdivide(minimum, size, multiplier)) { return false; // this one must be subdivided } - // the general check is whether we've gotten closer (as multiplied by the threshold) to any point in the volume, - // which we approximate as a sphere for simplicity - float halfSize = size * 0.5f; - glm::vec3 center = minimum + glm::vec3(halfSize, halfSize, halfSize); - float radius = sqrtf(3 * halfSize * halfSize); - return qMax(0.0f, glm::distance(position, center) - radius) * threshold <= - qMax(0.0f, glm::distance(reference.position, center) - radius) * reference.threshold; + // TODO: find some way of culling subtrees that can't possibly contain subdivided nodes + return true; } MetavoxelData::MetavoxelData() : _size(1.0f) { From 469e31cc051ff84c40c78f244e46c2859d32e7f9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:44:02 -0700 Subject: [PATCH 13/16] Script bindings for QColor. --- .../metavoxels/src/MetavoxelClientManager.cpp | 2 +- .../metavoxels/src/MetavoxelClientManager.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 26 +++++++++++++++++++ libraries/shared/src/RegisteredMetaTypes.h | 5 ++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index ff02398b85..0b9e3f3d8c 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -55,7 +55,7 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons return closestSpanner; } -void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, QRgb color) { +void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) { Sphere* sphere = new Sphere(); sphere->setTranslation(center); sphere->setScale(radius); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index 7537d7f971..191af794f7 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -29,7 +29,7 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance); - Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, QRgb color = 0x808080); + Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, const QColor& color = QColor(Qt::gray)); Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false); diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 3e21a72fd5..afc439c586 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "RegisteredMetaTypes.h" static int vec4MetaTypeId = qRegisterMetaType(); @@ -25,6 +27,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue); + qScriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue); qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue); qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); } @@ -101,6 +104,29 @@ void xColorFromScriptValue(const QScriptValue &object, xColor& color) { color.blue = object.property("blue").toVariant().toInt(); } +QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color) { + QScriptValue object = engine->newObject(); + object.setProperty("red", color.red()); + object.setProperty("green", color.green()); + object.setProperty("blue", color.blue()); + object.setProperty("alpha", color.alpha()); + return object; +} + +void qColorFromScriptValue(const QScriptValue& object, QColor& color) { + if (object.isNumber()) { + color.setRgb(object.toUInt32()); + + } else if (object.isString()) { + color.setNamedColor(object.toString()); + + } else { + QScriptValue alphaValue = object.property("alpha"); + color.setRgb(object.property("red").toInt32(), object.property("green").toInt32(), object.property("blue").toInt32(), + alphaValue.isNumber() ? alphaValue.toInt32() : 255); + } +} + QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay) { QScriptValue obj = engine->newObject(); QScriptValue origin = vec3toScriptValue(engine, pickRay.origin); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index d876965723..b925639e8a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -19,6 +19,8 @@ #include "CollisionInfo.h" #include "SharedUtil.h" +class QColor; + Q_DECLARE_METATYPE(glm::vec4) Q_DECLARE_METATYPE(glm::vec3) Q_DECLARE_METATYPE(glm::vec2) @@ -42,6 +44,9 @@ void quatFromScriptValue(const QScriptValue &object, glm::quat& quat); QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color); void xColorFromScriptValue(const QScriptValue &object, xColor& color); +QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color); +void qColorFromScriptValue(const QScriptValue& object, QColor& color); + class PickRay { public: PickRay() : origin(0), direction(0) { }; From ce0210bf0428c135f4684713db5161d8fc954475 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:52:17 -0700 Subject: [PATCH 14/16] The weak shared object hash can be accessed by multiple threads, so it must be locked. --- libraries/metavoxels/src/SharedObject.cpp | 5 +++++ libraries/metavoxels/src/SharedObject.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index d0a1842d31..fc72218e2e 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "Bitstream.h" #include "MetavoxelUtil.h" @@ -27,10 +28,12 @@ SharedObject::SharedObject() : _remoteID(0), _remoteOriginID(0) { + QWriteLocker locker(&_weakHashLock); _weakHash.insert(_id, this); } void SharedObject::setID(int id) { + QWriteLocker locker(&_weakHashLock); _weakHash.remove(_id); _weakHash.insert(_id = id, this); } @@ -41,6 +44,7 @@ void SharedObject::incrementReferenceCount() { void SharedObject::decrementReferenceCount() { if (!_referenceCount.deref()) { + QWriteLocker locker(&_weakHashLock); _weakHash.remove(_id); delete this; } @@ -127,6 +131,7 @@ void SharedObject::dump(QDebug debug) const { int SharedObject::_lastID = 0; WeakSharedObjectHash SharedObject::_weakHash; +QReadWriteLock SharedObject::_weakHashLock; void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash) { for (WeakSharedObjectHash::iterator it = hash.begin(); it != hash.end(); ) { diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index ba643b449c..5ff5aa9680 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,9 @@ public: /// Returns the weak hash under which all local shared objects are registered. static const WeakSharedObjectHash& getWeakHash() { return _weakHash; } + /// Returns a reference to the weak hash lock. + static QReadWriteLock& getWeakHashLock() { return _weakHashLock; } + Q_INVOKABLE SharedObject(); /// Returns the unique local ID for this object. @@ -85,6 +89,7 @@ private: static int _lastID; static WeakSharedObjectHash _weakHash; + static QReadWriteLock _weakHashLock; }; /// Removes the null references from the supplied hash. From a13d8559e6083191f05cb717c3a322a7b5fb3066 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:55:52 -0700 Subject: [PATCH 15/16] Better scoping. --- libraries/metavoxels/src/SharedObject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index fc72218e2e..efc6aa4be6 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -44,8 +44,10 @@ void SharedObject::incrementReferenceCount() { void SharedObject::decrementReferenceCount() { if (!_referenceCount.deref()) { - QWriteLocker locker(&_weakHashLock); - _weakHash.remove(_id); + { + QWriteLocker locker(&_weakHashLock); + _weakHash.remove(_id); + } delete this; } } From 2d4134afafdb629ff01f9b4c1de5375ab9cdb75a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 17:58:31 -0700 Subject: [PATCH 16/16] Provide basic conversions to/from SharedObjectPointer (still have to work out how to handle reference counting correctly). --- libraries/metavoxels/src/Bitstream.cpp | 11 ++++++++++- libraries/metavoxels/src/Bitstream.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 2e9e641d88..f49ae1c04f 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -129,10 +129,19 @@ QList Bitstream::getMetaObjectSubClasses(const QMetaObject* return getMetaObjectSubClasses().values(metaObject); } -void Bitstream::configureScriptEngine(QScriptEngine* engine) { +QScriptValue sharedObjectPointerToScriptValue(QScriptEngine* engine, const SharedObjectPointer& pointer) { + return pointer ? engine->newQObject(pointer.data()) : engine->nullValue(); +} + +void sharedObjectPointerFromScriptValue(const QScriptValue& object, SharedObjectPointer& pointer) { + pointer = qobject_cast(object.toQObject()); +} + +void Bitstream::registerTypes(QScriptEngine* engine) { foreach (const QMetaObject* metaObject, getMetaObjects()) { engine->globalObject().setProperty(metaObject->className(), engine->newQMetaObject(metaObject)); } + qScriptRegisterMetaType(engine, sharedObjectPointerToScriptValue, sharedObjectPointerFromScriptValue); } Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, GenericsMode genericsMode, QObject* parent) : diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 04b4dc97fc..7602424ded 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -323,7 +323,7 @@ public: /// Configures the supplied script engine with our registered meta-objects, allowing all of them to be instantiated from /// scripts. - static void configureScriptEngine(QScriptEngine* engine); + static void registerTypes(QScriptEngine* engine); enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cd7c2670ec..c5d5019b1f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ void ScriptEngine::init() { registerMenuItemProperties(&_engine); registerAnimationTypes(&_engine); registerAvatarTypes(&_engine); + Bitstream::registerTypes(&_engine); qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue); qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);