From 2cf2e693b93415a492a247a0a4fd7b66383dbb56 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 12:27:57 -0800 Subject: [PATCH 01/29] fix debug to properly work with outputBufferBits() --- interface/src/Application.cpp | 10 ++++++---- libraries/shared/src/SharedUtil.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca87c812d3..d0d071a141 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -101,10 +101,12 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D const int STATS_PELS_PER_LINE = 20; -void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) { - QString messageWithNewLine = message + "\n"; - fprintf(stdout, "%s", messageWithNewLine.toLocal8Bit().constData()); - Application::getInstance()->getLogger()->addMessage(messageWithNewLine.toLocal8Bit().constData()); +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { + if (message.size() > 0) { + QString messageWithNewLine = message + "\n"; + fprintf(stdout, "%s", messageWithNewLine.toLocal8Bit().constData()); + Application::getInstance()->getLogger()->addMessage(messageWithNewLine.toLocal8Bit().constData()); + } } Application::Application(int& argc, char** argv, timeval &startup_time) : diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 3b869e0ece..f22c81a71a 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -65,6 +65,8 @@ bool shouldDo(float desiredInterval, float deltaTime) { return randFloat() < deltaTime / desiredInterval; } + + void outputBufferBits(const unsigned char* buffer, int length, QDebug* continuedDebug) { for (int i = 0; i < length; i++) { outputBits(buffer[i], continuedDebug); @@ -76,6 +78,7 @@ void outputBits(unsigned char byte, QDebug* continuedDebug) { if (continuedDebug) { debug = *continuedDebug; + debug.nospace(); } QString resultString; @@ -85,12 +88,12 @@ void outputBits(unsigned char byte, QDebug* continuedDebug) { } else { resultString.sprintf("[ %d (0x%x): ", byte, byte); } - debug << resultString; - + debug << qPrintable(resultString); + for (int i = 0; i < 8; i++) { resultString.sprintf("%d", byte >> (7 - i) & 1); + debug << qPrintable(resultString); } - debug << resultString; debug << " ]"; } From 1ad2171952678fddcfecf16ca8c34051dd55c20a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 4 Feb 2014 15:23:10 -0800 Subject: [PATCH 02/29] Fix #1862 camera should not follow head orientation when using faceshift --- interface/src/avatar/Head.cpp | 4 +--- interface/src/avatar/Head.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 2269d1d4a6..f8faed56ed 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -37,7 +37,6 @@ Head::Head(Avatar* owningAvatar) : _leftEyeBlinkVelocity(0.0f), _rightEyeBlinkVelocity(0.0f), _timeWithoutTalking(0.0f), - _cameraYaw(_yaw), _isCameraMoving(false), _faceModel(this) { @@ -189,8 +188,7 @@ glm::quat Head::getOrientation() const { glm::quat Head::getCameraOrientation () const { Avatar* owningAvatar = static_cast(_owningAvatar); - return owningAvatar->getWorldAlignedOrientation() - * glm::quat(glm::radians(glm::vec3(_pitch, _cameraYaw, 0.0f))); + return owningAvatar->getWorldAlignedOrientation(); } glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 94b8bd3dc7..169f2af749 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -96,7 +96,6 @@ private: float _leftEyeBlinkVelocity; float _rightEyeBlinkVelocity; float _timeWithoutTalking; - float _cameraYaw; bool _isCameraMoving; FaceModel _faceModel; From 305e34e834ab03e750be6e7499784b520dd5fcc5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 20:18:45 -0800 Subject: [PATCH 03/29] more tweaks to particles with models rendering to make space invaders work --- interface/src/ParticleTreeRenderer.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/ParticleTreeRenderer.cpp b/interface/src/ParticleTreeRenderer.cpp index 7ba714ae93..7a1991ca93 100644 --- a/interface/src/ParticleTreeRenderer.cpp +++ b/interface/src/ParticleTreeRenderer.cpp @@ -84,12 +84,11 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg const float alpha = 1.0f; Model* model = getModel(particle.getModelURL()); - - glm::vec3 translationAdjustment = particle.getModelTranslation(); - + glm::vec3 translationAdjustment = particle.getModelTranslation() * radius; + // set the position - glm::vec3 translation(position.x, position.y, position.z); - model->setTranslation(translation + translationAdjustment); + glm::vec3 translation = position + translationAdjustment; + model->setTranslation(translation); // set the rotation glm::quat rotation = particle.getModelRotation(); @@ -100,14 +99,20 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg const float MODEL_SCALE = 0.00575f; glm::vec3 scale(1.0f,1.0f,1.0f); - // TODO: There is some kind of a bug in packing of the particle packets which is causing modelscale to - // sometimes be garbage. - float modelScale = 2.0f; /// particle.getModelScale() + float modelScale = particle.getModelScale(); model->setScale(scale * MODEL_SCALE * radius * modelScale); model->simulate(0.0f); model->render(alpha); // TODO: should we allow particles to have alpha on their models? + const bool wantDebugSphere = false; + if (wantDebugSphere) { + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glutWireSphere(radius, 15, 15); + glPopMatrix(); + } + glPopMatrix(); } else { glPushMatrix(); From a35e5eeb92725602ad2ca1608531fb811d512780 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 20:20:06 -0800 Subject: [PATCH 04/29] move modelScale before translation and rotation since that seems to fix the corruption --- libraries/particles/src/Particle.cpp | 103 ++++++++++++++------------- libraries/particles/src/Particle.h | 14 ++-- 2 files changed, 59 insertions(+), 58 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 12b59d28c9..69ad2c03fc 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -190,6 +190,12 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendRawData((const unsigned char*)qPrintable(_modelURL), modelURLLength); } } + + // modelScale + if (success) { + success = packetData->appendValue(getModelScale()); + } + // modelTranslation if (success) { success = packetData->appendValue(getModelTranslation()); @@ -198,11 +204,6 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { if (success) { success = packetData->appendValue(getModelRotation()); } - // modelScale - if (success) { - success = packetData->appendValue(getModelScale()); - } - return success; } @@ -319,6 +320,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += modelURLLength; bytesRead += modelURLLength; + // modelScale + memcpy(&_modelScale, dataAt, sizeof(_modelScale)); + dataAt += sizeof(_modelScale); + bytesRead += sizeof(_modelScale); + // modelTranslation memcpy(&_modelTranslation, dataAt, sizeof(_modelTranslation)); dataAt += sizeof(_modelTranslation); @@ -329,11 +335,6 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += bytes; bytesRead += bytes; - // modelScale - memcpy(&_modelScale, dataAt, sizeof(_modelScale)); - dataAt += sizeof(_modelScale); - bytesRead += sizeof(_modelScale); - //printf("Particle::readParticleDataFromBuffer()... "); debugDump(); } return bytesRead; @@ -498,6 +499,13 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr processedBytes += modelURLLength; } + // modelScale + if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { + memcpy(&newParticle._modelScale, dataAt, sizeof(newParticle._modelScale)); + dataAt += sizeof(newParticle._modelScale); + processedBytes += sizeof(newParticle._modelScale); + } + // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { memcpy(&newParticle._modelTranslation, dataAt, sizeof(newParticle._modelTranslation)); @@ -512,13 +520,6 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr processedBytes += bytes; } - // modelScale - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - memcpy(&newParticle._modelScale, dataAt, sizeof(newParticle._modelScale)); - dataAt += sizeof(newParticle._modelScale); - processedBytes += sizeof(newParticle._modelScale); - } - const bool wantDebugging = false; if (wantDebugging) { qDebug("Particle::fromEditPacket()..."); @@ -696,6 +697,14 @@ bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID i sizeOut += urlLength; } + // modelScale + if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { + float modelScale = properties.getModelScale(); + memcpy(copyAt, &modelScale, sizeof(modelScale)); + copyAt += sizeof(modelScale); + sizeOut += sizeof(modelScale); + } + // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { glm::vec3 modelTranslation = properties.getModelTranslation(); // should this be relative to TREE_SCALE?? @@ -711,14 +720,6 @@ bool Particle::encodeParticleEditMessageDetails(PacketType command, ParticleID i sizeOut += bytes; } - // modelScale - if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - float modelScale = properties.getModelScale(); - memcpy(copyAt, &modelScale, sizeof(modelScale)); - copyAt += sizeof(modelScale); - sizeOut += sizeof(modelScale); - } - bool wantDebugging = false; if (wantDebugging) { printf("encodeParticleEditMessageDetails()....\n"); @@ -931,9 +932,9 @@ ParticleProperties::ParticleProperties() : _inHand(false), _shouldDie(false), _modelURL(""), + _modelScale(DEFAULT_MODEL_SCALE), _modelTranslation(DEFAULT_MODEL_TRANSLATION), _modelRotation(DEFAULT_MODEL_ROTATION), - _modelScale(DEFAULT_MODEL_SCALE), _id(UNKNOWN_PARTICLE_ID), _idSet(false), @@ -950,9 +951,9 @@ ParticleProperties::ParticleProperties() : _inHandChanged(false), _shouldDieChanged(false), _modelURLChanged(false), + _modelScaleChanged(false), _modelTranslationChanged(false), _modelRotationChanged(false), - _modelScaleChanged(false), _defaultSettings(true) { } @@ -1004,6 +1005,10 @@ uint16_t ParticleProperties::getChangedBits() const { changedBits += CONTAINS_MODEL_URL; } + if (_modelScaleChanged) { + changedBits += CONTAINS_MODEL_SCALE; + } + if (_modelTranslationChanged) { changedBits += CONTAINS_MODEL_TRANSLATION; } @@ -1012,10 +1017,6 @@ uint16_t ParticleProperties::getChangedBits() const { changedBits += CONTAINS_MODEL_ROTATION; } - if (_modelScaleChanged) { - changedBits += CONTAINS_MODEL_SCALE; - } - return changedBits; } @@ -1045,14 +1046,14 @@ QScriptValue ParticleProperties::copyToScriptValue(QScriptEngine* engine) const properties.setProperty("modelURL", _modelURL); + properties.setProperty("modelScale", _modelScale); + QScriptValue modelTranslation = vec3toScriptValue(engine, _modelTranslation); properties.setProperty("modelTranslation", modelTranslation); QScriptValue modelRotation = quatToScriptValue(engine, _modelRotation); properties.setProperty("modelRotation", modelRotation); - properties.setProperty("modelScale", _modelScale); - if (_idSet) { properties.setProperty("id", _id); @@ -1203,7 +1204,17 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) { _modelURLChanged = true; } } - + + QScriptValue modelScale = object.property("modelScale"); + if (modelScale.isValid()) { + float newModelScale; + newModelScale = modelScale.toVariant().toFloat(); + if (_defaultSettings || newModelScale != _modelScale) { + _modelScale = newModelScale; + _modelScaleChanged = true; + } + } + QScriptValue modelTranslation = object.property("modelTranslation"); if (modelTranslation.isValid()) { QScriptValue x = modelTranslation.property("x"); @@ -1241,16 +1252,6 @@ void ParticleProperties::copyFromScriptValue(const QScriptValue &object) { } } - QScriptValue modelScale = object.property("modelScale"); - if (modelScale.isValid()) { - float newModelScale; - newModelScale = modelScale.toVariant().toFloat(); - if (_defaultSettings || newModelScale != _modelScale) { - _modelScale = newModelScale; - _modelScaleChanged = true; - } - } - _lastEdited = usecTimestampNow(); } @@ -1310,6 +1311,11 @@ void ParticleProperties::copyToParticle(Particle& particle) const { particle.setModelURL(_modelURL); somethingChanged = true; } + + if (_modelScaleChanged) { + particle.setModelScale(_modelScale); + somethingChanged = true; + } if (_modelTranslationChanged) { particle.setModelTranslation(_modelTranslation); @@ -1321,11 +1327,6 @@ void ParticleProperties::copyToParticle(Particle& particle) const { somethingChanged = true; } - if (_modelScaleChanged) { - particle.setModelScale(_modelScale); - somethingChanged = true; - } - if (somethingChanged) { bool wantDebug = false; if (wantDebug) { @@ -1350,9 +1351,9 @@ void ParticleProperties::copyFromParticle(const Particle& particle) { _inHand = particle.getInHand(); _shouldDie = particle.getShouldDie(); _modelURL = particle.getModelURL(); + _modelScale = particle.getModelScale(); _modelTranslation = particle.getModelTranslation(); _modelRotation = particle.getModelRotation(); - _modelScale = particle.getModelScale(); _id = particle.getID(); _idSet = true; @@ -1368,9 +1369,9 @@ void ParticleProperties::copyFromParticle(const Particle& particle) { _inHandChanged = false; _shouldDieChanged = false; _modelURLChanged = false; + _modelScaleChanged = false; _modelTranslationChanged = false; _modelRotationChanged = false; - _modelScaleChanged = false; _defaultSettings = false; } diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 925227055f..6d22e75810 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -88,9 +88,9 @@ public: bool getInHand() const { return _inHand; } bool getShouldDie() const { return _shouldDie; } const QString& getModelURL() const { return _modelURL; } + float getModelScale() const { return _modelScale; } const glm::vec3& getModelTranslation() const { return _modelTranslation; } const glm::quat& getModelRotation() const { return _modelRotation; } - float getModelScale() const { return _modelScale; } quint64 getLastEdited() const { return _lastEdited; } uint16_t getChangedBits() const; @@ -113,10 +113,10 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; _modelURLChanged = true; } + void setModelScale(float scale) { _modelScale = scale; _modelScaleChanged = true; } void setModelTranslation(const glm::vec3& translation) { _modelTranslation = translation; _modelTranslationChanged = true; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; _modelRotationChanged = true; } - void setModelScale(float scale) { _modelScale = scale; _modelScaleChanged = true; } /// used by ParticleScriptingInterface to return ParticleProperties for unknown particles void setIsUnknownID() { _id = UNKNOWN_PARTICLE_ID; _idSet = true; } @@ -133,9 +133,9 @@ private: bool _inHand; bool _shouldDie; QString _modelURL; + float _modelScale; glm::vec3 _modelTranslation; glm::quat _modelRotation; - float _modelScale; uint32_t _id; bool _idSet; @@ -152,9 +152,9 @@ private: bool _inHandChanged; bool _shouldDieChanged; bool _modelURLChanged; + bool _modelScaleChanged; bool _modelTranslationChanged; bool _modelRotationChanged; - bool _modelScaleChanged; bool _defaultSettings; }; Q_DECLARE_METATYPE(ParticleProperties); @@ -227,9 +227,9 @@ public: // model related properties bool hasModel() const { return !_modelURL.isEmpty(); } const QString& getModelURL() const { return _modelURL; } + float getModelScale() const { return _modelScale; } const glm::vec3& getModelTranslation() const { return _modelTranslation; } const glm::quat& getModelRotation() const { return _modelRotation; } - float getModelScale() const { return _modelScale; } ParticleID getParticleID() const { return ParticleID(getID(), getCreatorTokenID(), getID() != UNKNOWN_PARTICLE_ID); } ParticleProperties getProperties() const; @@ -277,9 +277,9 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } + void setModelScale(float scale) { _modelScale = scale; } void setModelTranslation(const glm::vec3& translation) { _modelTranslation = translation; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; } - void setModelScale(float scale) { _modelScale = scale; } void setProperties(const ParticleProperties& properties); @@ -344,9 +344,9 @@ protected: // model related items QString _modelURL; + float _modelScale; glm::vec3 _modelTranslation; glm::quat _modelRotation; - float _modelScale; uint32_t _creatorTokenID; bool _newlyCreated; From 13d9b710f1ce422064ad14dc6082121c7412ab1f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 20:23:12 -0800 Subject: [PATCH 05/29] bump packet version --- libraries/shared/src/PacketHeaders.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 3fd51949f9..67b534bc34 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -44,6 +44,8 @@ int packArithmeticallyCodedValue(int value, char* destination) { PacketVersion versionForPacketType(PacketType type) { switch (type) { + case PacketTypeParticleData: + return 1; default: return 0; } From 2f14b265a8d289a4252b9513cf503ef96881433c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 20:24:08 -0800 Subject: [PATCH 06/29] make sure SVO files with version details are supported --- interface/src/renderer/FBXReader.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index e2c3bfafdd..5a27b51b70 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -1632,7 +1632,18 @@ FBXGeometry readSVO(const QByteArray& model) { VoxelTree tree; ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); - tree.readBitstreamToTree((unsigned char*)model.data(), model.size(), args); + + unsigned char* dataAt = (unsigned char*)model.data(); + size_t dataSize = model.size(); + + if (tree.getWantSVOfileVersions()) { + // skip the type/version + dataAt += sizeof(PacketType); + dataSize -= sizeof(PacketType); + dataAt += sizeof(PacketVersion); + dataSize -= sizeof(PacketVersion); + } + tree.readBitstreamToTree(dataAt, dataSize, args); tree.recurseTreeWithOperation(addMeshVoxelsOperation, &mesh); geometry.meshes.append(mesh); From 758c1e0817e167aa6298b53375bba552e1ef6c39 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 20:28:11 -0800 Subject: [PATCH 07/29] add examples for setting model scale and translation --- examples/particleModelExample.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/particleModelExample.js b/examples/particleModelExample.js index e95cc0c2bf..2f36445d1a 100644 --- a/examples/particleModelExample.js +++ b/examples/particleModelExample.js @@ -11,7 +11,7 @@ var count = 0; var stopAfter = 100; -var modelProperties = { +var modelPropertiesA = { position: { x: 1, y: 1, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, gravity: { x: 0, y: 0, z: 0 }, @@ -21,6 +21,18 @@ var modelProperties = { lifetime: 20 }; +var modelPropertiesB = { + position: { x: 1, y: 1.5, z: 1 }, + velocity: { x: 0.5, y: 0, z: 0.5 }, + gravity: { x: 0, y: 0, z: 0 }, + damping: 0, + radius : 0.25, + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + lifetime: 20 +}; + var ballProperties = { position: { x: 1, y: 0.5, z: 1 }, velocity: { x: 0.5, y: 0, z: 0.5 }, @@ -31,7 +43,8 @@ var ballProperties = { lifetime: 20 }; -var modelParticleID = Particles.addParticle(modelProperties); +var modelAParticleID = Particles.addParticle(modelPropertiesA); +var modelBParticleID = Particles.addParticle(modelPropertiesB); var ballParticleID = Particles.addParticle(ballProperties); function endAfterAWhile() { From 15be49cb8d55d70950c8dbef8b1dd6bfe7d541c0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 21:08:12 -0800 Subject: [PATCH 08/29] latest changes to space invaders --- examples/spaceInvadersExample.js | 98 ++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 17 deletions(-) diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index 6c8473b4d7..cff8aded74 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -17,7 +17,8 @@ var invaderStepsPerCycle = 120; // the number of update steps it takes then inva var invaderStepOfCycle = 0; // current iteration in the cycle var invaderMoveDirection = 1; // 1 for moving to right, -1 for moving to left -var itemLifetimes = 60 * 2; // 2 minutes +// game length... +var itemLifetimes = 60; // 1 minute // position the game to be basically near the avatar running the game... @@ -51,7 +52,8 @@ var gameAt = { x: gameAtX, y: gameAtY, z: gameAtZ }; var middleX = gameAt.x + (gameSize.x/2); var middleY = gameAt.y + (gameSize.y/2); -var shipSize = 0.2; +var invaderSize = 0.4; +var shipSize = 0.25; var missileSize = 0.1; var myShip; var myShipProperties; @@ -88,16 +90,54 @@ var currentMoveSound = 0; var numberOfSounds = 4; var stepsPerSound = invaderStepsPerCycle / numberOfSounds; +// if you set this to false, sounds will come from the location of particles instead of the player's head +var soundInMyHead = true; + +// models... +var invaderModels = new Array(); +invaderModels[0] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-purple.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[1] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-large-cyan.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[2] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-cyan.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[3] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-medium-green.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; +invaderModels[4] = { + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/newInvader16x16-small-green.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, + }; + + + +//modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", +//modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/invader.svo", +// "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/spaceInvader3.fbx" + function initializeMyShip() { myShipProperties = { - position: { x: middleX , y: gameAt.y, z: gameAt.z }, - velocity: { x: 0, y: 0, z: 0 }, - gravity: { x: 0, y: 0, z: 0 }, - damping: 0, - radius: shipSize, - color: { red: 0, green: 255, blue: 0 }, - lifetime: itemLifetimes - }; + position: { x: middleX , y: gameAt.y, z: gameAt.z }, + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + damping: 0, + radius: shipSize, + color: { red: 0, green: 255, blue: 0 }, + //modelURL: myShipModel, + lifetime: itemLifetimes + }; myShip = Particles.addParticle(myShipProperties); } @@ -131,9 +171,11 @@ function initializeInvaders() { velocity: { x: 0, y: 0, z: 0 }, gravity: { x: 0, y: 0, z: 0 }, damping: 0, - radius: shipSize, + radius: invaderSize, color: { red: 255, green: 0, blue: 0 }, - modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", + modelURL: invaderModels[row].modelURL, + modelScale: invaderModels[row].modelScale, + modelTranslation: invaderModels[row].modelTranslation, lifetime: itemLifetimes }); @@ -171,8 +213,15 @@ function update() { if (invaderStepOfCycle % stepsPerSound == 0) { // play the move sound var options = new AudioInjectionOptions();
 - options.position = getInvaderPosition(invadersPerRow / 2, numberOfRows / 2); - options.volume = 10.0; + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = getInvaderPosition(invadersPerRow / 2, numberOfRows / 2); + } + print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); + options.volume = 1.0; Audio.playSound(moveSounds[currentMoveSound], options); // get ready for next move sound @@ -274,7 +323,14 @@ function fireMissile() { }); var options = new AudioInjectionOptions();
 - options.position = missilePosition; + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = missilePosition; + } + print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); options.volume = 1.0; Audio.playSound(shootSound, options); @@ -318,8 +374,14 @@ function deleteIfInvader(possibleInvaderParticle) { // play the hit sound var options = new AudioInjectionOptions();
 - var invaderPosition = getInvaderPosition(row, column); - options.position = invaderPosition; + if (soundInMyHead) { + options.position = { x: MyAvatar.position.x + 0.0, + y: MyAvatar.position.y + 0.1, + z: MyAvatar.position.z + 0.0 }; + } else { + options.position = getInvaderPosition(row, column); + } + print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); options.volume = 1.0; Audio.playSound(hitSound, options); } @@ -346,4 +408,6 @@ Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle); initializeMyShip(); initializeInvaders(); +// shut down the game after 1 minute +var gameTimer = Script.setTimeout(endGame, itemLifetimes * 1000); From 7ffe73bf6eaf0c919abe08d2001319b81555003c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 21:14:49 -0800 Subject: [PATCH 09/29] added the cannon as voxels --- examples/spaceInvadersExample.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index cff8aded74..6e21b6be30 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -135,7 +135,9 @@ function initializeMyShip() { damping: 0, radius: shipSize, color: { red: 0, green: 255, blue: 0 }, - //modelURL: myShipModel, + modelURL: "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/myCannon16x16.svo", + modelScale: 450, + modelTranslation: { x: -1.3, y: -1.3, z: -1.3 }, lifetime: itemLifetimes }; myShip = Particles.addParticle(myShipProperties); From 5afe184c3bbfdc746077be203ff9d956e50556ab Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 21:16:07 -0800 Subject: [PATCH 10/29] removed debug --- examples/spaceInvadersExample.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index 6e21b6be30..79e6837f21 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -222,7 +222,6 @@ function update() { } else { options.position = getInvaderPosition(invadersPerRow / 2, numberOfRows / 2); } - print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); options.volume = 1.0; Audio.playSound(moveSounds[currentMoveSound], options); @@ -332,7 +331,6 @@ function fireMissile() { } else { options.position = missilePosition; } - print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); options.volume = 1.0; Audio.playSound(shootSound, options); @@ -383,7 +381,6 @@ function deleteIfInvader(possibleInvaderParticle) { } else { options.position = getInvaderPosition(row, column); } - print("options.position=" + options.position.x + ", " + options.position.y + ", " + options.position.z ); options.volume = 1.0; Audio.playSound(hitSound, options); } From b0c41b086d2f77cef10defc8aeedabfbf130032a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 22:54:55 -0800 Subject: [PATCH 11/29] fix voxel packet corruption --- interface/src/DatagramProcessor.cpp | 12 ++++----- interface/src/VoxelSystem.cpp | 26 +++++++++---------- .../octree-server/src/OctreeQueryNode.cpp | 9 ++++--- libraries/octree/src/OctreePacketData.h | 4 +-- libraries/octree/src/OctreeRenderer.cpp | 2 +- libraries/voxels/src/VoxelPacketData.h | 14 ---------- 6 files changed, 28 insertions(+), 39 deletions(-) diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 2938be80ea..24ec956c62 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -73,12 +73,12 @@ void DatagramProcessor::processDatagrams() { if (wantExtraDebugging && packetTypeForPacket(incomingPacket) == PacketTypeVoxelData) { int numBytesPacketHeader = numBytesForPacketHeader(incomingPacket); unsigned char* dataAt = reinterpret_cast(incomingPacket.data()) + numBytesPacketHeader; - dataAt += sizeof(VOXEL_PACKET_FLAGS); - VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SEQUENCE); - VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SENT_TIME); - VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); + dataAt += sizeof(OCTREE_PACKET_FLAGS); + OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; printf("got PacketType_VOXEL_DATA, sequence:%d flightTime:%d\n", sequence, flightTime); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 3297750fb9..2342aa9de1 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -561,30 +561,30 @@ int VoxelSystem::parseData(const QByteArray& packet) { const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; - VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt)); - dataAt += sizeof(VOXEL_PACKET_FLAGS); - VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SEQUENCE); + OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt)); + dataAt += sizeof(OCTREE_PACKET_FLAGS); + OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); - VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); - dataAt += sizeof(VOXEL_PACKET_SENT_TIME); + OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SENT_TIME); bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); - VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt; - VOXEL_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packet.size() - VOXEL_PACKET_HEADER_SIZE; + OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; + int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { if (packetIsCompressed) { - if (dataBytes > sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE)) { - sectionLength = (*(VOXEL_PACKET_INTERNAL_SECTION_SIZE*)dataAt); - dataAt += sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); - dataBytes -= sizeof(VOXEL_PACKET_INTERNAL_SECTION_SIZE); + if (dataBytes > sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) { + sectionLength = (*(OCTREE_PACKET_INTERNAL_SECTION_SIZE*)dataAt); + dataAt += sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); + dataBytes -= sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); } else { sectionLength = 0; dataBytes = 0; // stop looping something is wrong diff --git a/libraries/octree-server/src/OctreeQueryNode.cpp b/libraries/octree-server/src/OctreeQueryNode.cpp index f9363d9d80..58aea5c792 100644 --- a/libraries/octree-server/src/OctreeQueryNode.cpp +++ b/libraries/octree-server/src/OctreeQueryNode.cpp @@ -46,9 +46,12 @@ void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, con bool OctreeQueryNode::packetIsDuplicate() const { // since our packets now include header information, like sequence number, and createTime, we can't just do a memcmp // of the entire packet, we need to compare only the packet content... + int numBytesPacketHeader = numBytesForPacketHeaderGivenPacketType(getMyPacketType()); + if (_lastOctreePacketLength == getPacketLength()) { - if (memcmp(_lastOctreePacket + OCTREE_PACKET_HEADER_SIZE, - _octreePacket + OCTREE_PACKET_HEADER_SIZE , getPacketLength() - OCTREE_PACKET_HEADER_SIZE) == 0) { + if (memcmp(_lastOctreePacket + (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE), + _octreePacket + (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE), + getPacketLength() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE)) == 0) { return true; } } @@ -125,7 +128,7 @@ void OctreeQueryNode::resetOctreePacket(bool lastWasSurpressed) { *sequenceAt = _sequenceNumber; _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); _octreePacketAvailableBytes -= sizeof(OCTREE_PACKET_SEQUENCE); - if (!(lastWasSurpressed || _lastOctreePacketLength == OCTREE_PACKET_HEADER_SIZE)) { + if (!(lastWasSurpressed || _lastOctreePacketLength == (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE))) { _sequenceNumber++; } diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index f004b45d14..bd9ab6227c 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,10 +30,10 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const int OCTREE_PACKET_HEADER_SIZE = MAX_PACKET_HEADER_BYTES + sizeof(OCTREE_PACKET_FLAGS) +const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - OCTREE_PACKET_HEADER_SIZE; +const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (OCTREE_PACKET_EXTRA_HEADERS_SIZE); const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 0fe56cd936..b636d9baac 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -64,7 +64,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Hifi int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packetLength - OCTREE_PACKET_HEADER_SIZE; + int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" diff --git a/libraries/voxels/src/VoxelPacketData.h b/libraries/voxels/src/VoxelPacketData.h index bf2a759225..637a91d0ec 100644 --- a/libraries/voxels/src/VoxelPacketData.h +++ b/libraries/voxels/src/VoxelPacketData.h @@ -26,20 +26,6 @@ #include "VoxelConstants.h" #include "VoxelTreeElement.h" -typedef unsigned char VOXEL_PACKET_FLAGS; -typedef uint16_t VOXEL_PACKET_SEQUENCE; -typedef quint64 VOXEL_PACKET_SENT_TIME; -typedef uint16_t VOXEL_PACKET_INTERNAL_SECTION_SIZE; -const int MAX_VOXEL_PACKET_SIZE = MAX_PACKET_SIZE; - -// this is overly conservative - uses 8 bytes for PacketType which could be as compact as a single byte -const int VOXEL_PACKET_HEADER_SIZE = MAX_PACKET_HEADER_BYTES + sizeof(VOXEL_PACKET_FLAGS) - + sizeof(VOXEL_PACKET_SEQUENCE) + sizeof(VOXEL_PACKET_SENT_TIME); - -const int MAX_VOXEL_PACKET_DATA_SIZE = MAX_PACKET_SIZE - VOXEL_PACKET_HEADER_SIZE; - -const int MAX_VOXEL_UNCOMRESSED_PACKET_SIZE = MAX_VOXEL_PACKET_DATA_SIZE; - /// Handles packing of the data portion of PacketType_VOXEL_DATA messages. class VoxelPacketData : public OctreePacketData { public: From 1b9cc4f5a5130a94de193825ddf1c87906f351cd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 4 Feb 2014 23:02:56 -0800 Subject: [PATCH 12/29] more fixup to octree packets --- libraries/octree/src/OctreePacketData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index bd9ab6227c..76bb138516 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -33,7 +33,7 @@ const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (OCTREE_PACKET_EXTRA_HEADERS_SIZE); +const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; From 53e7cd7797e5f02900eef96e45c3475f08cbd7b5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 10:16:43 -0800 Subject: [PATCH 13/29] fix particle init --- libraries/particles/src/Particle.cpp | 8 ++++++++ libraries/particles/src/Particle.h | 1 + 2 files changed, 9 insertions(+) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 69ad2c03fc..d9f0beb81a 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -92,6 +92,10 @@ Particle::Particle(const ParticleID& particleID, const ParticleProperties& prope _script = DEFAULT_SCRIPT; _inHand = NOT_IN_HAND; _shouldDie = false; + _modelURL = DEFAULT_MODEL_URL; + _modelTranslation = DEFAULT_MODEL_TRANSLATION; + _modelRotation = DEFAULT_MODEL_ROTATION; + _modelScale = DEFAULT_MODEL_SCALE; setProperties(properties); } @@ -124,6 +128,10 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _script = updateScript; _inHand = inHand; _shouldDie = false; + _modelURL = DEFAULT_MODEL_URL; + _modelTranslation = DEFAULT_MODEL_TRANSLATION; + _modelRotation = DEFAULT_MODEL_ROTATION; + _modelScale = DEFAULT_MODEL_SCALE; } void Particle::setMass(float value) { diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 6d22e75810..0f01e943f7 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -56,6 +56,7 @@ const float DEFAULT_RADIUS = 0.1f / TREE_SCALE; const float MINIMUM_PARTICLE_ELEMENT_SIZE = (1.0f / 100000.0f) / TREE_SCALE; // smallest size container const glm::vec3 DEFAULT_GRAVITY(0, (-9.8f / TREE_SCALE), 0); const QString DEFAULT_SCRIPT(""); +const QString DEFAULT_MODEL_URL(""); const glm::vec3 DEFAULT_MODEL_TRANSLATION(0, 0, 0); const glm::quat DEFAULT_MODEL_ROTATION(0, 0, 0, 0); const float DEFAULT_MODEL_SCALE = 1.0f; From 6b3b03228ee33e7c9355df3dd8e1514605d7a6cf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Feb 2014 10:22:07 -0800 Subject: [PATCH 14/29] audio repairs so buffers do not climb --- interface/src/Audio.cpp | 99 ++++++++++++++++++----------------------- interface/src/Audio.h | 5 ++- 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9fede84a93..d6ddaee6f1 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -56,6 +56,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _numOutputCallbackBytes(0), _loopbackAudioOutput(NULL), _loopbackOutputDevice(NULL), + _proceduralAudioOutput(NULL), + _proceduralOutputDevice(NULL), _inputRingBuffer(0), _ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL), _scope(scope), @@ -75,7 +77,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _muted(false) { // clear the array of locally injected samples - memset(_localInjectedSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); } void Audio::init(QGLWidget *parent) { @@ -272,6 +274,9 @@ void Audio::start() { // setup a loopback audio output device _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); + + // setup a procedural audio output device + _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); gettimeofday(&_lastReceiveTime, NULL); } @@ -332,7 +337,7 @@ void Audio::handleAudioInput() { memset(monoAudioSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); // zero out the locally injected audio in preparation for audio procedural sounds - memset(_localInjectedSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); + memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); if (!_muted) { // we aren't muted, downsample the input audio @@ -363,6 +368,22 @@ void Audio::handleAudioInput() { // add procedural effects to the appropriate input samples addProceduralSounds(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + + if (!_proceduralOutputDevice) { + _proceduralOutputDevice = _proceduralAudioOutput->start(); + } + + // send whatever procedural sounds we want to locally loop back to the _proceduralOutputDevice + QByteArray proceduralOutput; + proceduralOutput.resize(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4 * sizeof(int16_t)); + + linearResampling(_localProceduralSamples, + reinterpret_cast(proceduralOutput.data()), + NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL, + NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4, + _desiredInputFormat, _outputFormat); + + _proceduralOutputDevice->write(proceduralOutput); NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -431,12 +452,6 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { static float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float) _outputFormat.sampleRate()) * (_desiredOutputFormat.channelCount() / (float) _outputFormat.channelCount()); - - static int numRequiredOutputSamples = NETWORK_BUFFER_LENGTH_SAMPLES_STEREO / networkOutputToOutputRatio; - - QByteArray outputBuffer; - outputBuffer.resize(numRequiredOutputSamples * sizeof(int16_t)); - if (!_ringBuffer.isStarved() && _audioOutput->bytesFree() == _audioOutput->bufferSize()) { // we don't have any audio data left in the output buffer @@ -448,6 +463,14 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // if there is anything in the ring buffer, decide what to do if (_ringBuffer.samplesAvailable() > 0) { + + + int numNetworkOutputSamples = _ringBuffer.samplesAvailable(); + int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio; + + QByteArray outputBuffer; + outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t)); + if (!_ringBuffer.isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (_jitterBufferSamples * 2))) { // starved and we don't have enough to start, keep waiting @@ -458,52 +481,17 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // copy the samples we'll resample from the ring buffer - this also // pushes the read pointer of the ring buffer forwards - int16_t ringBufferSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; - _ringBuffer.readSamples(ringBufferSamples, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); - - // add the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL from each QByteArray - // in our _localInjectionByteArrays QVector to the _localInjectedSamples - - // add to the output samples whatever is in the _localAudioOutput byte array - // that lets this user hear sound effects and loopback (if enabled) - - for (int b = 0; b < _localInjectionByteArrays.size(); b++) { - QByteArray audioByteArray = _localInjectionByteArrays.at(b); - - int16_t* byteArraySamples = (int16_t*) audioByteArray.data(); - - int samplesToRead = qMin((int)(audioByteArray.size() / sizeof(int16_t)), - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); - - for (int i = 0; i < samplesToRead; i++) { - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + byteArraySamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } - - if (samplesToRead < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // there isn't anything left to inject from this byte array, remove it from the vector - _localInjectionByteArrays.remove(b); - } else { - // pull out the bytes we just read for outputs - audioByteArray.remove(0, samplesToRead * sizeof(int16_t)); - - // still data left to read - replace the byte array in the QVector with the smaller one - _localInjectionByteArrays.replace(b, audioByteArray); - } - } - - for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { - ringBufferSamples[i * 2] = glm::clamp(ringBufferSamples[i * 2] + _localInjectedSamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - ringBufferSamples[(i * 2) + 1] = glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i], - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } + int16_t ringBufferSamples[numNetworkOutputSamples]; + _ringBuffer.readSamples(ringBufferSamples, numNetworkOutputSamples); + + // add the next numNetworkOutputSamples from each QByteArray + // in our _localInjectionByteArrays QVector to the localInjectedSamples // copy the packet from the RB to the output linearResampling(ringBufferSamples, (int16_t*) outputBuffer.data(), - NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, - numRequiredOutputSamples, + numNetworkOutputSamples, + numDeviceOutputSamples, _desiredOutputFormat, _outputFormat); if (_outputDevice) { @@ -512,8 +500,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // add output (@speakers) data just written to the scope QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, - Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, - NETWORK_BUFFER_LENGTH_BYTES_STEREO)), + Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numDeviceOutputSamples)), Q_ARG(bool, true), Q_ARG(bool, false)); } } @@ -672,7 +659,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + collisionSample, + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _collisionSoundMagnitude *= _collisionSoundDuration; @@ -696,7 +683,7 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _localInjectedSamples[i] = glm::clamp(_localInjectedSamples[i] + collisionSample, + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); _drumSoundVolume *= (1.f - _drumSoundDecay); @@ -727,8 +714,8 @@ void Audio::startDrumSound(float volume, float frequency, float duration, float } void Audio::handleAudioByteArray(const QByteArray& audioByteArray) { - // add this byte array to our QVector - _localInjectionByteArrays.append(audioByteArray); + // TODO: either create a new audio device (up to the limit of the sound card or a hard limit) + // or send to the mixer and use delayed loopback } void Audio::renderToolIcon(int screenHeight) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index cc5a43d8e0..fa4fb62adf 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -86,8 +86,7 @@ private: QAudioFormat _inputFormat; QIODevice* _inputDevice; int _numInputCallbackBytes; - int16_t _localInjectedSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL]; - QVector _localInjectionByteArrays; + int16_t _localProceduralSamples[NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL]; QAudioOutput* _audioOutput; QAudioFormat _desiredOutputFormat; QAudioFormat _outputFormat; @@ -95,6 +94,8 @@ private: int _numOutputCallbackBytes; QAudioOutput* _loopbackAudioOutput; QIODevice* _loopbackOutputDevice; + QAudioOutput* _proceduralAudioOutput; + QIODevice* _proceduralOutputDevice; AudioRingBuffer _inputRingBuffer; AudioRingBuffer _ringBuffer; From 76bc4564ad2744619e77604c420ab362b7628664 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 10:24:00 -0800 Subject: [PATCH 15/29] push to force rebuild --- libraries/particles/src/Particle.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 0f01e943f7..84efdd2916 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -63,7 +63,6 @@ const float DEFAULT_MODEL_SCALE = 1.0f; const bool IN_HAND = true; // it's in a hand const bool NOT_IN_HAND = !IN_HAND; // it's not in a hand - /// A collection of properties of a particle used in the scripting API. Translates between the actual properties of a particle /// and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete set of /// particle properties via JavaScript hashes/QScriptValues From 96fd73a7661aa6fd73cd0da4f40b1dec264425c0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Feb 2014 11:39:03 -0800 Subject: [PATCH 16/29] fixed wrapped read of samples from end of buffer --- interface/src/Audio.cpp | 3 +-- libraries/audio/src/AudioRingBuffer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index d6ddaee6f1..6b6de5a51d 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -495,12 +495,11 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { _desiredOutputFormat, _outputFormat); if (_outputDevice) { - _outputDevice->write(outputBuffer); // add output (@speakers) data just written to the scope QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, - Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numDeviceOutputSamples)), + Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numNetworkOutputSamples)), Q_ARG(bool, true), Q_ARG(bool, false)); } } diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 8a444e50fd..9bac210c39 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -70,9 +70,9 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { // read to the end of the buffer int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); - + // read the rest from the beginning of the buffer - memcpy(data + numSamplesToEnd, _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); + memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); } else { // read the data memcpy(data, _nextOutput, numReadSamples * sizeof(int16_t)); From 3e08a0b48b44026424846c88e1b1692b84049b41 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 13:26:46 -0800 Subject: [PATCH 17/29] fix spacebar capture --- examples/spaceInvadersExample.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/spaceInvadersExample.js b/examples/spaceInvadersExample.js index 79e6837f21..c817afcdd4 100644 --- a/examples/spaceInvadersExample.js +++ b/examples/spaceInvadersExample.js @@ -275,6 +275,9 @@ function cleanupGame() { if (missileFired) { Particles.deleteParticle(myMissile); } + + Controller.releaseKeyEvents({text: " "}); + Script.stop(); } Script.scriptEnding.connect(cleanupGame); From a05e07460f919e6b7489474aa7662bff4d27df13 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 5 Feb 2014 13:54:17 -0800 Subject: [PATCH 18/29] fix windows build errors and warnings --- interface/src/Audio.cpp | 3 ++- libraries/metavoxels/src/DatagramSequencer.cpp | 2 +- libraries/shared/src/NodeList.cpp | 2 +- libraries/shared/src/PacketHeaders.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 6b6de5a51d..d7aae8e6f3 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -481,7 +481,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { // copy the samples we'll resample from the ring buffer - this also // pushes the read pointer of the ring buffer forwards - int16_t ringBufferSamples[numNetworkOutputSamples]; + int16_t* ringBufferSamples= new int16_t[numNetworkOutputSamples]; _ringBuffer.readSamples(ringBufferSamples, numNetworkOutputSamples); // add the next numNetworkOutputSamples from each QByteArray @@ -502,6 +502,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numNetworkOutputSamples)), Q_ARG(bool, true), Q_ARG(bool, false)); } + delete[] ringBufferSamples; } } diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index 83ef641b39..8daec16511 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -138,7 +138,7 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) { } // read and dispatch the high-priority messages - quint32 highPriorityMessageCount; + int highPriorityMessageCount; _incomingPacketStream >> highPriorityMessageCount; int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; for (int i = 0; i < highPriorityMessageCount; i++) { diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index cd9356ab15..d6b8005263 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -337,7 +337,7 @@ void NodeList::processSTUNResponse(const QByteArray& packet) { const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); - size_t attributeStartIndex = NUM_BYTES_STUN_HEADER; + int attributeStartIndex = NUM_BYTES_STUN_HEADER; if (memcmp(packet.data() + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 67b534bc34..16e7cca1c1 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -37,7 +37,7 @@ int packArithmeticallyCodedValue(int value, char* destination) { return 1; } else { // pack 255 and then recursively pack on - destination[0] = 255; + ((unsigned char*)destination)[0] = 255; return 1 + packArithmeticallyCodedValue(value - 255, destination + 1); } } From b0ccedd1a6d35de490642f8f43445f6964ea82c6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 13:59:17 -0800 Subject: [PATCH 19/29] fix spacing --- interface/src/Audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index d7aae8e6f3..9fb2f6d932 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -417,7 +417,7 @@ void Audio::handleAudioInput() { Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); } - delete[] inputAudioSamples; + delete[] inputAudioSamples; } } From 8cc4666f2a249478e9261ddda6bb1b390acc817d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 14:00:17 -0800 Subject: [PATCH 20/29] fix spacing --- interface/src/Audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9fb2f6d932..3689c4462e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -502,7 +502,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { Q_ARG(QByteArray, QByteArray((char*) ringBufferSamples, numNetworkOutputSamples)), Q_ARG(bool, true), Q_ARG(bool, false)); } - delete[] ringBufferSamples; + delete[] ringBufferSamples; } } From 5059f27067f6e2d4fa94d3190bfdfd8311ab9d1e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 14:08:42 -0800 Subject: [PATCH 21/29] update README to reference build notes for Windows and Ubuntu and Qt 5.2 --- README.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a42bbd1626..5678312f6f 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,18 @@ send your resume to hiring@highfidelity.io Building Interface & other High Fidelity Components ========= -Interface is our OS X and Linux build-able client for accessing our virtual +Interface is our Windows, OS X, and Linux build-able client for accessing our virtual world. +For detailed notes on building for Windows, please refer to the following wiki page: +https://github.com/highfidelity/hifi/wiki/Building-on-Windows + +For detailed notes on building for Ubuntu, please refer to the following wiki page: +https://github.com/highfidelity/hifi/wiki/Building-on-Ubuntu-13.04 + +Building on Mac OS X and Linux: +-------------------------------- + CMake ----- Hifi uses CMake to generate build files and project files @@ -45,9 +54,9 @@ If Cmake throws you an error related to Qt5 it likely cannot find your Qt5 cmake You can solve this by setting an environment variable, QT_CMAKE_PREFIX_PATH, to the location of the folder distributed with Qt5 that contains them. -For example, a Qt5 5.1.1 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). +For example, a Qt5 5.2.0 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). - export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.1.1/clang_64/lib/cmake/ + export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.0/clang_64/lib/cmake/ The path it needs to be set to will depend on where and how Qt5 was installed. @@ -64,7 +73,7 @@ components located in the build/target_name/Debug directories. Other dependencies & information ---- -In addition to CMake, Qt 5.1 is required to build all components. +In addition to CMake, Qt 5.2 is required to build all components. What can I build on? We have successfully built on OS X 10.8, Ubuntu and a few other modern Linux From ce30e831136d46414207ce961618cfa8c396f609 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 14:56:00 -0800 Subject: [PATCH 22/29] fix crash in octree server related to getActiveSocket() returning NULL --- .../octree-server/src/OctreeSendThread.cpp | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/octree-server/src/OctreeSendThread.cpp b/libraries/octree-server/src/OctreeSendThread.cpp index 26df0ffb0b..a016553e5f 100644 --- a/libraries/octree-server/src/OctreeSendThread.cpp +++ b/libraries/octree-server/src/OctreeSendThread.cpp @@ -92,6 +92,13 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in bool packetSent = false; // did we send a packet? int packetsSent = 0; + + // double check that the node has an active socket, otherwise, don't send... + const HifiSockAddr* nodeAddress = node->getActiveSocket(); + if (!nodeAddress) { + return packetsSent; // without sending... + } + // Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently // obscure the packet and not send it. This allows the callers and upper level logic to not need to know about // this rate control savings. @@ -136,14 +143,14 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in // actually send it NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; } else { // not enough room in the packet, send two packets NodeList::getInstance()->getNodeSocket().writeDatagram((char*) statsMessage, statsMessageLength, - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since // there was nothing else to send. @@ -162,8 +169,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in packetsSent++; NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; @@ -183,8 +190,8 @@ int OctreeSendThread::handlePacketSend(Node* node, OctreeQueryNode* nodeData, in if (nodeData->isPacketWaiting()) { // just send the voxel packet NodeList::getInstance()->getNodeSocket().writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), - node->getActiveSocket()->getAddress(), - node->getActiveSocket()->getPort()); + nodeAddress->getAddress(), + nodeAddress->getPort()); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); From 9694a622b5bec8f8d7c7882f817680570131dd1a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Feb 2014 15:35:13 -0800 Subject: [PATCH 23/29] update placeholder and give edit packet senders to Agent --- assignment-client/src/Agent.cpp | 6 +++++- assignment-client/src/Agent.h | 5 +++++ domain-server/resources/web/assignment/placeholder.js | 10 +++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 2694bf83e2..93ec4bf991 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -23,8 +23,12 @@ #include "Agent.h" Agent::Agent(const QByteArray& packet) : - ThreadedAssignment(packet) + ThreadedAssignment(packet), + _voxelEditSender(), + _particleEditSender() { + _scriptEngine.getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); + _scriptEngine.getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); } void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 8b2038a8b0..7495fc06bf 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -15,9 +15,12 @@ #include #include +#include #include #include #include +#include + class Agent : public ThreadedAssignment { Q_OBJECT @@ -39,6 +42,8 @@ signals: private: ScriptEngine _scriptEngine; ParticleTree _particleTree; + VoxelEditPacketSender _voxelEditSender; + ParticleEditPacketSender _particleEditSender; }; #endif /* defined(__hifi__Agent__) */ diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js index ee8f89cdd6..7c84767f31 100644 --- a/domain-server/resources/web/assignment/placeholder.js +++ b/domain-server/resources/web/assignment/placeholder.js @@ -8,11 +8,9 @@ var NUMBER_OF_CELLS = NUMBER_OF_CELLS_EACH_DIMENSION * NUMBER_OF_CELLS_EACH_DIME var currentCells = []; var nextCells = []; -var METER_LENGTH = 1 / TREE_SCALE; +var METER_LENGTH = 1; var cellScale = (NUMBER_OF_CELLS_EACH_DIMENSION * METER_LENGTH) / NUMBER_OF_CELLS_EACH_DIMENSION; -print("TREE_SCALE = " + TREE_SCALE + "\n"); - // randomly populate the cell start values for (var i = 0; i < NUMBER_OF_CELLS_EACH_DIMENSION; i++) { // create the array to hold this row @@ -108,7 +106,7 @@ function sendNextCells() { // queue a packet to add a voxel for the new cell var color = (nextCells[i][j] == 1) ? 255 : 1; - Voxels.queueDestructiveVoxelAdd(x, y, 0, cellScale, color, color, color); + Voxels.setVoxel(x, y, 0, cellScale, color, color, color); } } } @@ -128,4 +126,6 @@ function step() { sendNextCells(); } -Agent.willSendVisualDataCallback.connect(step); \ No newline at end of file + +Script.willSendVisualDataCallback.connect(step); +Voxels.setPacketsPerSecond(200); \ No newline at end of file From aa3a1a9a72458c06e2ccd7a170b4c7bb350ea6b5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 5 Feb 2014 15:35:57 -0800 Subject: [PATCH 24/29] Stop rendering our head in first person camera mode. --- interface/src/Application.cpp | 3 ++- interface/src/Camera.cpp | 13 +++++++++++++ interface/src/Camera.h | 3 +++ interface/src/avatar/Avatar.cpp | 4 +++- interface/src/avatar/AvatarManager.cpp | 3 +-- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d0d071a141..24d31b9442 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2884,7 +2884,8 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } } - _avatarManager.renderAvatars(whichCamera.getMode() == CAMERA_MODE_MIRROR, selfAvatarOnly); + bool renderMyHead = (whichCamera.getInterpolatedMode() != CAMERA_MODE_FIRST_PERSON); + _avatarManager.renderAvatars(renderMyHead, selfAvatarOnly); if (!selfAvatarOnly) { // Render the world box diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 94bc693c2b..d3a126c38a 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -36,6 +36,7 @@ Camera::Camera() { _modeShiftRate = 1.0f; _linearModeShift = 0.0f; _mode = CAMERA_MODE_THIRD_PERSON; + _prevMode = CAMERA_MODE_THIRD_PERSON; _tightness = 10.0f; // default _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES; _aspectRatio = 16.f/9.f; @@ -123,6 +124,7 @@ void Camera::setModeShiftRate ( float rate ) { void Camera::setMode(CameraMode m) { + _prevMode = _mode; _mode = m; _modeShift = 0.0; _linearModeShift = 0.0; @@ -199,6 +201,17 @@ bool Camera::getFrustumNeedsReshape() const { return _frustumNeedsReshape; } +// call this when deciding whether to render the head or not +CameraMode Camera::getInterpolatedMode() const { + const float SHIFT_THRESHOLD_INTO_FIRST_PERSON = 0.7f; + const float SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON = 0.6f; + if (_mode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_INTO_FIRST_PERSON || + _prevMode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON) { + return _prevMode; + } + return _mode; +} + // call this after reshaping the view frustum void Camera::setFrustumWasReshaped() { _frustumNeedsReshape = false; diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 615135bc80..7fc9b47634 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -61,6 +61,8 @@ public: const glm::quat& getEyeOffsetOrientation () const { return _eyeOffsetOrientation; } float getScale () const { return _scale; } + CameraMode getInterpolatedMode() const; + bool getFrustumNeedsReshape() const; // call to find out if the view frustum needs to be reshaped void setFrustumWasReshaped(); // call this after reshaping the view frustum. @@ -68,6 +70,7 @@ private: bool _needsToInitialize; CameraMode _mode; + CameraMode _prevMode; bool _frustumNeedsReshape; glm::vec3 _position; glm::vec3 _idealPosition; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4b4c189729..259bf994e0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -242,7 +242,9 @@ void Avatar::renderBody(bool forceRenderHead) { glm::vec3 pos = getPosition(); //printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z); _skeletonModel.render(1.0f); - _head.render(1.0f); + if (forceRenderHead) { + _head.render(1.0f); + } _hand.render(false); } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d98d30cf6a..a4a85f5770 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -75,7 +75,6 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); if (!selfAvatarOnly) { - // Render avatars of other nodes foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { Avatar* avatar = static_cast(avatarPointer.data()); if (!avatar->isInitialized()) { @@ -84,7 +83,7 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (avatar == static_cast(_myAvatar.data())) { avatar->render(forceRenderHead); } else { - avatar->render(false); + avatar->render(true); } avatar->setDisplayingLookatVectors(renderLookAtVectors); } From f4fe2bb7549b414dd98d9679e13647d8f8f86b2a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Feb 2014 16:04:23 -0800 Subject: [PATCH 25/29] move octree-server libs to assignment-client --- assignment-client/CMakeLists.txt | 3 -- assignment-client/src/AssignmentFactory.cpp | 6 +-- .../octree}/OctreeInboundPacketProcessor.cpp | 0 .../octree}/OctreeInboundPacketProcessor.h | 0 .../src/octree}/OctreeQueryNode.cpp | 0 .../src/octree}/OctreeQueryNode.h | 0 .../src/octree}/OctreeSendThread.cpp | 0 .../src/octree}/OctreeSendThread.h | 0 .../src/octree}/OctreeServer.cpp | 0 .../src/octree}/OctreeServer.h | 0 .../src/octree}/OctreeServerConsts.h | 0 .../src/particles}/ParticleNodeData.h | 3 +- .../src/particles}/ParticleServer.cpp | 0 .../src/particles}/ParticleServer.h | 2 +- .../src/particles}/ParticleServerConsts.h | 0 .../src/voxels}/VoxelNodeData.h | 5 ++- .../src/voxels}/VoxelServer.cpp | 0 .../src/voxels}/VoxelServer.h | 3 +- .../src/voxels}/VoxelServerConsts.h | 0 libraries/octree-server/CMakeLists.txt | 36 ------------------ libraries/particle-server/CMakeLists.txt | 37 ------------------- libraries/voxel-server/CMakeLists.txt | 37 ------------------- 22 files changed, 9 insertions(+), 123 deletions(-) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeInboundPacketProcessor.cpp (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeInboundPacketProcessor.h (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeQueryNode.cpp (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeQueryNode.h (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeSendThread.cpp (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeSendThread.h (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeServer.cpp (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeServer.h (100%) rename {libraries/octree-server/src => assignment-client/src/octree}/OctreeServerConsts.h (100%) rename {libraries/particle-server/src => assignment-client/src/particles}/ParticleNodeData.h (95%) rename {libraries/particle-server/src => assignment-client/src/particles}/ParticleServer.cpp (100%) rename {libraries/particle-server/src => assignment-client/src/particles}/ParticleServer.h (97%) rename {libraries/particle-server/src => assignment-client/src/particles}/ParticleServerConsts.h (100%) rename {libraries/voxel-server/src => assignment-client/src/voxels}/VoxelNodeData.h (79%) rename {libraries/voxel-server/src => assignment-client/src/voxels}/VoxelServer.cpp (100%) rename {libraries/voxel-server/src => assignment-client/src/voxels}/VoxelServer.h (98%) rename {libraries/voxel-server/src => assignment-client/src/voxels}/VoxelServerConsts.h (100%) delete mode 100644 libraries/octree-server/CMakeLists.txt delete mode 100644 libraries/particle-server/CMakeLists.txt delete mode 100644 libraries/voxel-server/CMakeLists.txt diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 51a91621da..60b9d75338 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -30,9 +30,6 @@ link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(metavoxels ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(particle-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxel-server ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(script-engine ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 5bf0417f22..cde5666ab9 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -8,15 +8,13 @@ #include -#include - -#include - #include "Agent.h" #include "AssignmentFactory.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" #include "metavoxels/MetavoxelServer.h" +#include "particles/ParticleServer.h" +#include "voxels/VoxelServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { QDataStream packetStream(packet); diff --git a/libraries/octree-server/src/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp similarity index 100% rename from libraries/octree-server/src/OctreeInboundPacketProcessor.cpp rename to assignment-client/src/octree/OctreeInboundPacketProcessor.cpp diff --git a/libraries/octree-server/src/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h similarity index 100% rename from libraries/octree-server/src/OctreeInboundPacketProcessor.h rename to assignment-client/src/octree/OctreeInboundPacketProcessor.h diff --git a/libraries/octree-server/src/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp similarity index 100% rename from libraries/octree-server/src/OctreeQueryNode.cpp rename to assignment-client/src/octree/OctreeQueryNode.cpp diff --git a/libraries/octree-server/src/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h similarity index 100% rename from libraries/octree-server/src/OctreeQueryNode.h rename to assignment-client/src/octree/OctreeQueryNode.h diff --git a/libraries/octree-server/src/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp similarity index 100% rename from libraries/octree-server/src/OctreeSendThread.cpp rename to assignment-client/src/octree/OctreeSendThread.cpp diff --git a/libraries/octree-server/src/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h similarity index 100% rename from libraries/octree-server/src/OctreeSendThread.h rename to assignment-client/src/octree/OctreeSendThread.h diff --git a/libraries/octree-server/src/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp similarity index 100% rename from libraries/octree-server/src/OctreeServer.cpp rename to assignment-client/src/octree/OctreeServer.cpp diff --git a/libraries/octree-server/src/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h similarity index 100% rename from libraries/octree-server/src/OctreeServer.h rename to assignment-client/src/octree/OctreeServer.h diff --git a/libraries/octree-server/src/OctreeServerConsts.h b/assignment-client/src/octree/OctreeServerConsts.h similarity index 100% rename from libraries/octree-server/src/OctreeServerConsts.h rename to assignment-client/src/octree/OctreeServerConsts.h diff --git a/libraries/particle-server/src/ParticleNodeData.h b/assignment-client/src/particles/ParticleNodeData.h similarity index 95% rename from libraries/particle-server/src/ParticleNodeData.h rename to assignment-client/src/particles/ParticleNodeData.h index 4ab16cb33a..450767613e 100644 --- a/libraries/particle-server/src/ParticleNodeData.h +++ b/assignment-client/src/particles/ParticleNodeData.h @@ -10,9 +10,10 @@ #ifndef __hifi__ParticleNodeData__ #define __hifi__ParticleNodeData__ -#include #include +#include "../octree/OctreeQueryNode.h" + class ParticleNodeData : public OctreeQueryNode { public: ParticleNodeData() : diff --git a/libraries/particle-server/src/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp similarity index 100% rename from libraries/particle-server/src/ParticleServer.cpp rename to assignment-client/src/particles/ParticleServer.cpp diff --git a/libraries/particle-server/src/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h similarity index 97% rename from libraries/particle-server/src/ParticleServer.h rename to assignment-client/src/particles/ParticleServer.h index 1c1e3b5be9..345ebe86e3 100644 --- a/libraries/particle-server/src/ParticleServer.h +++ b/assignment-client/src/particles/ParticleServer.h @@ -10,7 +10,7 @@ #ifndef __particle_server__ParticleServer__ #define __particle_server__ParticleServer__ -#include +#include "../octree/OctreeServer.h" #include "Particle.h" #include "ParticleServerConsts.h" diff --git a/libraries/particle-server/src/ParticleServerConsts.h b/assignment-client/src/particles/ParticleServerConsts.h similarity index 100% rename from libraries/particle-server/src/ParticleServerConsts.h rename to assignment-client/src/particles/ParticleServerConsts.h diff --git a/libraries/voxel-server/src/VoxelNodeData.h b/assignment-client/src/voxels/VoxelNodeData.h similarity index 79% rename from libraries/voxel-server/src/VoxelNodeData.h rename to assignment-client/src/voxels/VoxelNodeData.h index 54ef9da5b6..c24bfad6ce 100644 --- a/libraries/voxel-server/src/VoxelNodeData.h +++ b/assignment-client/src/voxels/VoxelNodeData.h @@ -3,15 +3,16 @@ // hifi // // Created by Stephen Birarda on 3/21/13. -// +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. // #ifndef __hifi__VoxelNodeData__ #define __hifi__VoxelNodeData__ -#include #include +#include "../octree/OctreeQueryNode.h" + class VoxelNodeData : public OctreeQueryNode { public: VoxelNodeData() : OctreeQueryNode() { }; diff --git a/libraries/voxel-server/src/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp similarity index 100% rename from libraries/voxel-server/src/VoxelServer.cpp rename to assignment-client/src/voxels/VoxelServer.cpp diff --git a/libraries/voxel-server/src/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h similarity index 98% rename from libraries/voxel-server/src/VoxelServer.h rename to assignment-client/src/voxels/VoxelServer.h index 183224b2a7..526a3b2c54 100644 --- a/libraries/voxel-server/src/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -17,8 +17,7 @@ #include #include -#include - +#include "../octree/OctreeServer.h" #include "VoxelServerConsts.h" diff --git a/libraries/voxel-server/src/VoxelServerConsts.h b/assignment-client/src/voxels/VoxelServerConsts.h similarity index 100% rename from libraries/voxel-server/src/VoxelServerConsts.h rename to assignment-client/src/voxels/VoxelServerConsts.h diff --git a/libraries/octree-server/CMakeLists.txt b/libraries/octree-server/CMakeLists.txt deleted file mode 100644 index 64c73a4bd4..0000000000 --- a/libraries/octree-server/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME octree-server) - -find_package(Qt5Network REQUIRED) -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Network Widgets) - -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link in the hifi octree library -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) - -# link the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) diff --git a/libraries/particle-server/CMakeLists.txt b/libraries/particle-server/CMakeLists.txt deleted file mode 100644 index 9c63645e8d..0000000000 --- a/libraries/particle-server/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME particle-server) - -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Widgets) - -# inluce GLM -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR}) - -# link in the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/libraries/voxel-server/CMakeLists.txt b/libraries/voxel-server/CMakeLists.txt deleted file mode 100644 index 594d037767..0000000000 --- a/libraries/voxel-server/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(ROOT_DIR ../..) -set(MACRO_DIR ${ROOT_DIR}/cmake/macros) - -# setup for find modules -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/modules/") - -set(TARGET_NAME voxel-server) - -find_package(Qt5Widgets REQUIRED) - -include(${MACRO_DIR}/SetupHifiLibrary.cmake) - -setup_hifi_library(${TARGET_NAME} ${OPTIONAL_SRCS}) - -qt5_use_modules(${TARGET_NAME} Widgets) - -include(${MACRO_DIR}/IncludeGLM.cmake) -include_glm(${TARGET_NAME} ${ROOT_DIR}) - -# link ZLIB -find_package(ZLIB) -include_directories(${ZLIB_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# link in the shared library -include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link in the embedded webserver -link_hifi_library(embedded-webserver ${TARGET_NAME} ${ROOT_DIR}) - -# link in the hifi octree library -link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(octree-server ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file From f657a3efe9d5478066ba652b49d92fb20d06ad10 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 5 Feb 2014 20:02:01 -0800 Subject: [PATCH 26/29] remove local cache option --- interface/src/Application.cpp | 63 ++--------------------------------- interface/src/Application.h | 5 --- interface/src/Menu.cpp | 1 - interface/src/Menu.h | 1 - 4 files changed, 2 insertions(+), 68 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d0d071a141..b0629bf6de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -154,8 +154,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _resetRecentMaxPacketsSoon(true), _swatch(NULL), _pasteMode(false), - _logger(new FileLogger(this)), - _persistThread(NULL) + _logger(new FileLogger(this)) { _myAvatar = _avatarManager.getMyAvatar(); @@ -316,12 +315,7 @@ Application::~Application() { _voxelHideShowThread.terminate(); _voxelEditSender.terminate(); _particleEditSender.terminate(); - if (_persistThread) { - _persistThread->terminate(); - _persistThread->deleteLater(); - _persistThread = NULL; - } - + storeSizeAndPosition(); saveScripts(); _sharedVoxelSystem.changeTree(new VoxelTree); @@ -1907,9 +1901,6 @@ void Application::init() { connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - - - updateLocalOctreeCache(true); } void Application::closeMirrorView() { @@ -2207,9 +2198,6 @@ void Application::updateThreads(float deltaTime) { _voxelHideShowThread.threadRoutine(); _voxelEditSender.threadRoutine(); _particleEditSender.threadRoutine(); - if (_persistThread) { - _persistThread->threadRoutine(); - } } } @@ -3882,10 +3870,6 @@ void Application::domainChanged(const QString& domainHostname) { // reset the particle renderer _particles.clear(); - - // reset our persist thread - qDebug() << "Domain changed to" << domainHostname << ". Swapping persist cache."; - updateLocalOctreeCache(); } void Application::nodeKilled(SharedNodePointer node) { @@ -4155,49 +4139,6 @@ void Application::initAvatarAndViewFrustum() { updateMyAvatar(0.f); } -QString Application::getLocalVoxelCacheFileName() { - QString fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - QDir logDir(fileName); - if (!logDir.exists(fileName)) { - logDir.mkdir(fileName); - } - - fileName.append(QString("/hifi.voxelscache.")); - fileName.append(_profile.getLastDomain()); - fileName.append(QString(".svo")); - - return fileName; -} - - -void Application::updateLocalOctreeCache(bool firstTime) { - // only do this if we've already got a persistThread or we're told this is the first time - if (firstTime || _persistThread) { - - if (_persistThread) { - _persistThread->terminate(); - _persistThread->deleteLater(); - _persistThread = NULL; - } - - QString localVoxelCacheFileName = getLocalVoxelCacheFileName(); - const int LOCAL_CACHE_PERSIST_INTERVAL = 1000 * 10; // every 10 seconds - - if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableLocalVoxelCache)) { - _persistThread = new OctreePersistThread(_voxels.getTree(), - localVoxelCacheFileName.toLocal8Bit().constData(),LOCAL_CACHE_PERSIST_INTERVAL); - - qDebug() << "updateLocalOctreeCache()... localVoxelCacheFileName=" << localVoxelCacheFileName; - } - - if (_persistThread) { - _voxels.beginLoadingLocalVoxelCache(); // while local voxels are importing, don't do individual node VBO updates - connect(_persistThread, SIGNAL(loadCompleted()), &_voxels, SLOT(localVoxelCacheLoaded())); - _persistThread->initialize(true); - } - } -} - void Application::checkVersion() { QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL))); latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); diff --git a/interface/src/Application.h b/interface/src/Application.h index bf9981a160..e82eaf1d6c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -484,11 +484,6 @@ private: FileLogger* _logger; - OctreePersistThread* _persistThread; - - QString getLocalVoxelCacheFileName(); - void updateLocalOctreeCache(bool firstTime = false); - void checkVersion(); void displayUpdateDialog(); bool shouldSkipVersion(QString latestVersion); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 67eaa8782c..709f848a2f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -317,7 +317,6 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges); addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools())); - addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableLocalVoxelCache); QMenu* voxelProtoOptionsMenu = voxelOptionsMenu->addMenu("Voxel Server Protocol Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 5e49ca6fd1..6f7986fcc3 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -176,7 +176,6 @@ namespace MenuOption { const QString DestructiveAddVoxel = "Create Voxel is Destructive"; const QString DisableColorVoxels = "Disable Colored Voxels"; const QString DisableDeltaSending = "Disable Delta Sending"; - const QString DisableLocalVoxelCache = "Disable Local Voxel Cache"; const QString DisableLowRes = "Disable Lower Resolution While Moving"; const QString DisplayFrustum = "Display Frustum"; const QString DisplayLeapHands = "Display Leap Hands"; From 4f5a27796ff2fa3228f3b684ba8cc35f6332d3f5 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 5 Feb 2014 20:46:17 -0800 Subject: [PATCH 27/29] fix warning --- interface/src/Camera.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index d3a126c38a..7ec4f90eef 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -205,8 +205,8 @@ bool Camera::getFrustumNeedsReshape() const { CameraMode Camera::getInterpolatedMode() const { const float SHIFT_THRESHOLD_INTO_FIRST_PERSON = 0.7f; const float SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON = 0.6f; - if (_mode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_INTO_FIRST_PERSON || - _prevMode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON) { + if ((_mode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_INTO_FIRST_PERSON) || + (_prevMode == CAMERA_MODE_FIRST_PERSON && _linearModeShift < SHIFT_THRESHOLD_OUT_OF_FIRST_PERSON)) { return _prevMode; } return _mode; From a16b3a34e40d3157e5291d921241626f06d4a728 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 6 Feb 2014 02:18:28 -0800 Subject: [PATCH 28/29] fix stutter while spinning --- interface/src/Application.cpp | 2 +- interface/src/VoxelSystem.cpp | 135 ++++++++++++++++------------------ interface/src/VoxelSystem.h | 9 --- 3 files changed, 63 insertions(+), 83 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ee4bf7f27c..f55332f5b6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2053,7 +2053,7 @@ void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& f glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s); // only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled, // and make sure the tree is not already busy... because otherwise you'll have to wait. - if (!(_voxels.treeIsBusy() || _mousePressed)) { + if (!_mousePressed) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); _isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face); diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 2342aa9de1..1ffc6c3e5e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -99,8 +99,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) _culledOnce = false; _inhideOutOfView = false; - _treeIsBusy = false; - } void VoxelSystem::elementDeleted(OctreeElement* element) { @@ -594,9 +592,10 @@ int VoxelSystem::parseData(const QByteArray& packet) { } if (sectionLength) { + PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData() section"); // ask the VoxelTree to read the bitstream into the tree ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID()); - lockTree(); + _tree->lockForWrite(); VoxelPacketData packetData(packetIsCompressed); packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { @@ -608,7 +607,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.getUncompressedSize()); } _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); - unlockTree(); + _tree->unlock(); dataBytes -= sectionLength; dataAt += sectionLength; @@ -1395,9 +1394,11 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { int VoxelSystem::_nodeCount = 0; void VoxelSystem::killLocalVoxels() { - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::killLocalVoxels()"); + _tree->lockForWrite(); _tree->eraseAllOctreeElements(); - unlockTree(); + _tree->unlock(); clearFreeBufferIndexes(); _voxelsInReadArrays = 0; // do we need to do this? setupNewVoxelsForDrawing(); @@ -1416,10 +1417,12 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void } void VoxelSystem::clearAllNodesBufferIndex() { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::clearAllNodesBufferIndex()"); _nodeCount = 0; - lockTree(); + _tree->lockForRead(); // we won't change the tree so it's ok to treat this as a read _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); - unlockTree(); + _tree->unlock(); if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { qDebug("clearing buffer index of %d nodes", _nodeCount); } @@ -1481,7 +1484,8 @@ bool VoxelSystem::trueColorizeOperation(OctreeElement* element, void* extraData) } void VoxelSystem::trueColorize() { - PerformanceWarning warn(true, "trueColorize()",true); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "trueColorize()",true); _nodeCount = 0; _tree->recurseTreeWithOperation(trueColorizeOperation); qDebug("setting true color for %d nodes", _nodeCount); @@ -1951,9 +1955,13 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { return; } - lockTree(); - _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); - unlockTree(); + { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::... recurseTreeWithOperation(hideOutOfViewOperation)"); + _tree->lockForRead(); + _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); + _tree->unlock(); + } _lastCulledViewFrustum = args.thisViewFrustum; // save last stable _culledOnce = true; @@ -2150,35 +2158,47 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance, BoxFace& face) { - lockTree(); - OctreeElement* element; - if (!_tree->findRayIntersection(origin, direction, element, distance, face)) { - unlockTree(); - return false; + + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findRayIntersection()"); + bool result = false; // assume no intersection + if (_tree->tryLockForRead()) { + OctreeElement* element; + result = _tree->findRayIntersection(origin, direction, element, distance, face); + if (result) { + VoxelTreeElement* voxel = (VoxelTreeElement*)element; + detail.x = voxel->getCorner().x; + detail.y = voxel->getCorner().y; + detail.z = voxel->getCorner().z; + detail.s = voxel->getScale(); + detail.red = voxel->getColor()[0]; + detail.green = voxel->getColor()[1]; + detail.blue = voxel->getColor()[2]; + } + _tree->unlock(); } - VoxelTreeElement* voxel = (VoxelTreeElement*)element; - detail.x = voxel->getCorner().x; - detail.y = voxel->getCorner().y; - detail.z = voxel->getCorner().z; - detail.s = voxel->getScale(); - detail.red = voxel->getColor()[0]; - detail.green = voxel->getColor()[1]; - detail.blue = voxel->getColor()[2]; - unlockTree(); - return true; + return result; } bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) { - lockTree(); - bool result = _tree->findSpherePenetration(center, radius, penetration); - unlockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findSpherePenetration()"); + bool result = false; // assume no penetration + if (_tree->tryLockForRead()) { + result = _tree->findSpherePenetration(center, radius, penetration); + _tree->unlock(); + } return result; } bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) { - lockTree(); - bool result = _tree->findCapsulePenetration(start, end, radius, penetration); - unlockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::findCapsulePenetration()"); + bool result = false; // assume no penetration + if (_tree->tryLockForRead()) { + result = _tree->findCapsulePenetration(start, end, radius, penetration); + _tree->unlock(); + } return result; } @@ -2354,13 +2374,14 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::deleteVoxelAt()"); + _tree->lockForWrite(); _tree->deleteVoxelAt(x, y, z, s); - unlockTree(); + _tree->unlock(); // redraw! setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? - }; VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { @@ -2370,10 +2391,12 @@ VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) co void VoxelSystem::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { - //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s); - lockTree(); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "VoxelSystem::createVoxel()"); + + _tree->lockForWrite(); _tree->createVoxel(x, y, z, s, red, green, blue, destructive); - unlockTree(); + _tree->unlock(); setupNewVoxelsForDrawing(); }; @@ -2744,37 +2767,3 @@ unsigned long VoxelSystem::getVoxelMemoryUsageGPU() { return (_initialMemoryUsageGPU - currentFreeMemory); } -void VoxelSystem::lockTree() { - _treeLock.lock(); - _treeIsBusy = true; -} - -void VoxelSystem::unlockTree() { - _treeIsBusy = false; - _treeLock.unlock(); -} - - -void VoxelSystem::localVoxelCacheLoaded() { - qDebug() << "localVoxelCacheLoaded()"; - - // Make sure that the application has properly set up the view frustum for our loaded state - Application::getInstance()->initAvatarAndViewFrustum(); - - _tree->setDirtyBit(); // make sure the tree thinks it's dirty - _setupNewVoxelsForDrawingLastFinished = 0; // don't allow the setupNewVoxelsForDrawing() shortcuts - _writeRenderFullVBO = true; // this will disable individual node updates, was reset by killLocalVoxels() - setupNewVoxelsForDrawing(); - _inhideOutOfView = false; // reenable hideOutOfView behavior -} - -void VoxelSystem::beginLoadingLocalVoxelCache() { - qDebug() << "beginLoadingLocalVoxelCache()"; - _writeRenderFullVBO = true; // this will disable individual node updates - _inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded - killLocalVoxels(); - qDebug() << "DONE beginLoadingLocalVoxelCache()"; -} - - - diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index ca90424b70..d1404668bf 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -110,8 +110,6 @@ public: virtual void elementDeleted(OctreeElement* element); virtual void elementUpdated(OctreeElement* element); - bool treeIsBusy() const { return _treeIsBusy; } - VoxelTreeElement* getVoxelEnclosing(const glm::vec3& point); signals: @@ -144,9 +142,6 @@ public slots: void setUseVoxelShader(bool useVoxelShader); void setVoxelsAsPoints(bool voxelsAsPoints); - void localVoxelCacheLoaded(); - void beginLoadingLocalVoxelCache(); - protected: float _treeScale; unsigned long _maxVoxels; @@ -304,10 +299,6 @@ private: bool _useFastVoxelPipeline; bool _inhideOutOfView; - bool _treeIsBusy; // is the tree mutex locked? if so, it's busy, and if you can avoid it, don't access the tree - - void lockTree(); - void unlockTree(); }; #endif From 8fbce359443ca977e4adc48c51081f8011218e55 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 6 Feb 2014 03:44:21 -0800 Subject: [PATCH 29/29] fix slight glitch in last child delete from larger voxel --- interface/src/Application.cpp | 3 ++- libraries/voxels/src/VoxelTreeElement.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ee4bf7f27c..c86495381b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1256,7 +1256,8 @@ void Application::mousePressEvent(QMouseEvent* event) { pasteVoxels(); } - if (MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) && + MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { _hoverVoxelOriginalColor[0] = _hoverVoxel.red; _hoverVoxelOriginalColor[1] = _hoverVoxel.green; _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index c98ed77b74..6fd3997165 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -54,6 +54,8 @@ void VoxelTreeElement::splitChildren() { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { addChildAtIndex(i)->setColor(ourColor); } + nodeColor noColor = { 0, 0, 0, 0}; + setColor(noColor); // set our own color to noColor so we are a pure non-leaf } } @@ -143,7 +145,11 @@ void VoxelTreeElement::setColor(const nodeColor& color) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } _isDirty = true; - _density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed. + if (color[3]) { + _density = 1.0f; // If color set, assume leaf, re-averaging will update density if needed. + } else { + _density = 0.0f; + } markWithChangedTime(); } }