From 7b70562a1b68ca2fb0d858dc282bdd81f6059145 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 15:51:43 -0800 Subject: [PATCH 01/67] update RenderableModelEntityItem::_model during simulate rather than during render --- .../src/RenderableModelEntityItem.cpp | 91 ++++++++++--------- .../src/RenderableModelEntityItem.h | 1 + libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f1be8611e1..bbc230ec1d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,6 +210,53 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } +void RenderableModelEntityItem::simulate(const quint64& now) { + EntityItem::simulate(now); + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } +} // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. @@ -259,50 +306,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) { EntityTreeRenderer* renderer = static_cast(args->_renderer); getModel(renderer); } - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index c4e36c240a..3d7ca73624 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,6 +47,7 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void simulate(const quint64& now); virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5ceccef4b1..6514c955e8 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -183,7 +183,7 @@ public: quint64 getLastUpdated() const { return _lastUpdated; } // perform linear extrapolation for SimpleEntitySimulation - void simulate(const quint64& now); + virtual void simulate(const quint64& now); void simulateKinematicMotion(float timeElapsed, bool setFlags=true); virtual bool needsToCallUpdate() const { return false; } From 89e5b11f9eea009336b5795d9978a61ec5b7b3bc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:17:22 -0800 Subject: [PATCH 02/67] do this from update rather than simulate --- .../src/RenderableModelEntityItem.cpp | 96 +++++++++---------- .../src/RenderableModelEntityItem.h | 2 - libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 47 insertions(+), 53 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index bbc230ec1d..6985d1a617 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,54 +210,6 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } -void RenderableModelEntityItem::simulate(const quint64& now) { - EntityItem::simulate(now); - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } -} - // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. void RenderableModelEntityItem::render(RenderArgs* args) { @@ -369,14 +321,58 @@ void RenderableModelEntityItem::update(const quint64& now) { EntityItemProperties properties; auto extents = _model->getMeshExtents(); properties.setDimensions(extents.maximum - extents.minimum); - + qCDebug(entitiesrenderer) << "Autoresizing:" << (!getName().isEmpty() ? getName() : getModelURL()); QMetaObject::invokeMethod(DependencyManager::get().data(), "editEntity", Qt::QueuedConnection, Q_ARG(QUuid, getEntityItemID()), Q_ARG(EntityItemProperties, properties)); } - + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } + ModelEntityItem::update(now); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3d7ca73624..6c5bfc4423 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,8 +47,6 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); - virtual void simulate(const quint64& now); - virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 6514c955e8..5ceccef4b1 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -183,7 +183,7 @@ public: quint64 getLastUpdated() const { return _lastUpdated; } // perform linear extrapolation for SimpleEntitySimulation - virtual void simulate(const quint64& now); + void simulate(const quint64& now); void simulateKinematicMotion(float timeElapsed, bool setFlags=true); virtual bool needsToCallUpdate() const { return false; } From 283ad7ffd938a858510f815bb4442e13e89ef0ff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:39:19 -0800 Subject: [PATCH 03/67] try, try again --- .../src/RenderableModelEntityItem.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 6985d1a617..3d9a336e83 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -313,7 +313,27 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); + if (EntityItem::needsToCallUpdate()) { + return true; + } + // these if statements match the structure of those in RenderableModelEntityItem::update + if (!_dimensionsInitialized && _model && _model->isActive()) { + return true; + } + if (_model) { + if (hasAnimation()) { + return true; + } + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + return true; + } + } } void RenderableModelEntityItem::update(const quint64& now) { From cfcff42004cd134224bbd46ff49dcf35c07a7b63 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:41:16 -0800 Subject: [PATCH 04/67] missed a line --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3d9a336e83..31d3e3ca78 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -334,6 +334,8 @@ bool RenderableModelEntityItem::needsToCallUpdate() const { return true; } } + + return false; } void RenderableModelEntityItem::update(const quint64& now) { From 5cd047da15cfdc65d4e2a23700a0f3ed99ebd5b0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:49:36 -0800 Subject: [PATCH 05/67] move some more code over --- .../src/RenderableModelEntityItem.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 31d3e3ca78..2fedc02a2f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -247,18 +247,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->setVisibleInScene(getVisible(), scene); } - remapTextures(); - { - // float alpha = getLocalRenderAlpha(); - - if (!_model || _needsModelReload) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - EntityTreeRenderer* renderer = static_cast(args->_renderer); - getModel(renderer); - } - } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; @@ -317,6 +306,11 @@ bool RenderableModelEntityItem::needsToCallUpdate() const { return true; } // these if statements match the structure of those in RenderableModelEntityItem::update + if (hasModel() && _myRenderer) { + if (!_model || _needsModelReload) { + return true; + } + } if (!_dimensionsInitialized && _model && _model->isActive()) { return true; } @@ -351,6 +345,12 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + getModel(_myRenderer); + } + if (_model) { // handle animations.. if (hasAnimation()) { From 09f14bc9a56bc7bb54c2c24a773058b9beed7ab0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 16:51:17 -0800 Subject: [PATCH 06/67] guard against nullptr deferenece --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2fedc02a2f..ade96901dc 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -345,7 +345,7 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } - if (!_model || _needsModelReload) { + if (_myRenderer && (!_model || _needsModelReload)) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); getModel(_myRenderer); From 9320623ff5f3bfe1d1a61220028bc3762c8fc474 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 12 Nov 2015 18:07:23 -0800 Subject: [PATCH 07/67] Add AABox functionalities --- libraries/shared/src/AABox.cpp | 45 +++++++++++++++++++++++++++++++--- libraries/shared/src/AABox.h | 7 +++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index b514e171eb..7c001c570e 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -42,9 +42,48 @@ glm::vec3 AABox::calcCenter() const { return center; } -void AABox::scale(float scale) { - _corner = _corner * scale; - _scale = _scale * scale; +void AABox::rotate(const glm::quat& rotation) { + auto minimum = _corner; + auto maximum = _corner + _scale; + + glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z); + glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z); + glm::vec3 bottomLeftFar(minimum.x, minimum.y, maximum.z); + glm::vec3 bottomRightFar(maximum.x, minimum.y, maximum.z); + glm::vec3 topLeftNear(minimum.x, maximum.y, minimum.z); + glm::vec3 topRightNear(maximum.x, maximum.y, minimum.z); + glm::vec3 topLeftFar(minimum.x, maximum.y, maximum.z); + glm::vec3 topRightFar(maximum.x, maximum.y, maximum.z); + + glm::vec3 bottomLeftNearRotated = rotation * bottomLeftNear; + glm::vec3 bottomRightNearRotated = rotation * bottomRightNear; + glm::vec3 bottomLeftFarRotated = rotation * bottomLeftFar; + glm::vec3 bottomRightFarRotated = rotation * bottomRightFar; + glm::vec3 topLeftNearRotated = rotation * topLeftNear; + glm::vec3 topRightNearRotated = rotation * topRightNear; + glm::vec3 topLeftFarRotated = rotation * topLeftFar; + glm::vec3 topRightFarRotated = rotation * topRightFar; + + minimum = glm::min(bottomLeftNearRotated, + glm::min(bottomRightNearRotated, + glm::min(bottomLeftFarRotated, + glm::min(bottomRightFarRotated, + glm::min(topLeftNearRotated, + glm::min(topRightNearRotated, + glm::min(topLeftFarRotated, + topRightFarRotated))))))); + + maximum = glm::max(bottomLeftNearRotated, + glm::max(bottomRightNearRotated, + glm::max(bottomLeftFarRotated, + glm::max(bottomRightFarRotated, + glm::max(topLeftNearRotated, + glm::max(topRightNearRotated, + glm::max(topLeftFarRotated, + topRightFarRotated))))))); + + _corner = minimum; + _scale = maximum - minimum; } glm::vec3 AABox::getVertex(BoxVertex vertex) const { diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 1f5923dbd8..e5227ade44 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -40,7 +40,12 @@ public: void setBox(const glm::vec3& corner, float scale); glm::vec3 getVertexP(const glm::vec3& normal) const; glm::vec3 getVertexN(const glm::vec3& normal) const; - void scale(float scale); + + void shiftBy(const glm::vec3& delta) { _corner += delta; } + void rotate(const glm::quat& rotation); + void scale(float scale) { _corner *= scale; _scale *= scale; } + void scale(const glm::vec3& scale) { _corner *= scale; _scale *= scale; } + const glm::vec3& getCorner() const { return _corner; } const glm::vec3& getScale() const { return _scale; } const glm::vec3& getDimensions() const { return _scale; } From a71ed7b16657601a8f97bf97a4914b076a7f6fcf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 12 Nov 2015 18:23:09 -0800 Subject: [PATCH 08/67] Implement particle bounds with Extents --- .../RenderableParticleEffectEntityItem.cpp | 40 +++++-------------- .../entities/src/ParticleEffectEntityItem.cpp | 19 ++------- .../entities/src/ParticleEffectEntityItem.h | 6 +-- 3 files changed, 15 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 05fca343fd..ebe87dec9b 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -272,37 +272,17 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } // update transform - glm::quat rot = getRotation(); - glm::vec3 pos = getPosition(); - Transform t; - t.setRotation(rot); - payload.setModelTransform(t); + glm::vec3 position = getPosition(); + glm::quat rotation = getRotation(); + Transform transform; + transform.setTranslation(position); + transform.setRotation(rotation); + payload.setModelTransform(transform); - // transform _particleMinBound and _particleMaxBound corners into world coords - glm::vec3 d = _particleMaxBound - _particleMinBound; - const size_t NUM_BOX_CORNERS = 8; - glm::vec3 corners[NUM_BOX_CORNERS] = { - pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, 0.0f)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, 0.0f, d.z)), - pos + rot * (_particleMinBound + glm::vec3(d.x, 0.0f, d.z)), - pos + rot * (_particleMinBound + glm::vec3(0.0f, d.y, d.z)), - pos + rot * (_particleMinBound + glm::vec3(d.x, d.y, d.z)) - }; - glm::vec3 min(FLT_MAX, FLT_MAX, FLT_MAX); - glm::vec3 max = -min; - for (size_t i = 0; i < NUM_BOX_CORNERS; i++) { - min.x = std::min(min.x, corners[i].x); - min.y = std::min(min.y, corners[i].y); - min.z = std::min(min.z, corners[i].z); - max.x = std::max(max.x, corners[i].x); - max.y = std::max(max.y, corners[i].y); - max.z = std::max(max.z, corners[i].z); - } - AABox bound(min, max - min); - payload.setBound(bound); + AABox bounds(_particlesBounds); + bounds.rotate(rotation); + bounds.shiftBy(position); + payload.setBound(bounds); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 06fcdb495c..f3abeffc20 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -121,8 +121,6 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _alphaStarts(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), _alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)), - _particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) , _additiveBlending(DEFAULT_ADDITIVE_BLENDING) { @@ -631,15 +629,6 @@ void ParticleEffectEntityItem::updateAlpha(quint32 index, float age) { _alphaFinishes[index], age); } -void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { - _particleMinBound.x = glm::min(_particleMinBound.x, point.x); - _particleMinBound.y = glm::min(_particleMinBound.y, point.y); - _particleMinBound.z = glm::min(_particleMinBound.z, point.z); - _particleMaxBound.x = glm::max(_particleMaxBound.x, point.x); - _particleMaxBound.y = glm::max(_particleMaxBound.y, point.y); - _particleMaxBound.z = glm::max(_particleMaxBound.z, point.z); -} - void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { glm::vec3 accel = _particleAccelerations[index]; glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * accel; @@ -649,9 +638,7 @@ void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { - - _particleMinBound = glm::vec3(-1.0f, -1.0f, -1.0f); - _particleMaxBound = glm::vec3(1.0f, 1.0f, 1.0f); + _particlesBounds.reset(); // update particles between head and tail for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { @@ -667,7 +654,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { updateColor(i, age); updateAlpha(i, age); integrateParticle(i, deltaTime); - extendBounds(_particlePositions[i]); + _particlesBounds.addPoint(_particlePositions[i]); } } @@ -766,7 +753,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } integrateParticle(i, timeLeftInFrame); - extendBounds(_particlePositions[i]); + _particlesBounds.addPoint(_particlePositions[i]); // Color if (_colorSpread == xColor{ 0, 0, 0 }) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index e3c5cd895a..7ac115d8e5 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -224,7 +224,6 @@ protected: void updateRadius(quint32 index, float age); void updateColor(quint32 index, float age); void updateAlpha(quint32 index, float age); - void extendBounds(const glm::vec3& point); void integrateParticle(quint32 index, float deltaTime); quint32 getLivingParticleCount() const; // the properties of this entity @@ -289,9 +288,8 @@ protected: quint32 _particleTailIndex = 0; // bounding volume - glm::vec3 _particleMaxBound; - glm::vec3 _particleMinBound; - + Extents _particlesBounds; + bool _additiveBlending; }; From 395822c6cdeb8bc6c7a2c36a4ce342d6e52ffc96 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 11:47:33 -0800 Subject: [PATCH 09/67] Use make_shared --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ebe87dec9b..f4243db621 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -134,11 +134,11 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) { - auto particlePayload = std::shared_ptr(new ParticlePayload(shared_from_this())); + auto particlePayload = std::make_shared(shared_from_this()); particlePayload->setPipeline(_untexturedPipeline); _renderItemId = scene->allocateID(); auto renderData = ParticlePayload::Pointer(particlePayload); - auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData)); + auto renderPayload = std::make_shared(renderData); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); From 40e802bae766b60536b8574f44d8af356679a6c2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 12:05:43 -0800 Subject: [PATCH 10/67] Get rid of global variable for sort Fix rhs/lhs --- .../src/RenderableParticleEffectEntityItem.cpp | 16 +++++++--------- .../entities/src/ParticleEffectEntityItem.cpp | 6 +++--- libraries/shared/src/AABox.h | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f4243db621..5c65f0bee5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -184,11 +184,6 @@ public: uint32_t rgba; }; -static glm::vec3 zSortAxis; -static bool zSort(const ParticleDetails& rhs, const ParticleDetails& lhs) { - return glm::dot(rhs.position, ::zSortAxis) > glm::dot(lhs.position, ::zSortAxis); -} - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; @@ -201,7 +196,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto xcolor = _particleColors[i]; auto alpha = (uint8_t)(glm::clamp(_particleAlphas[i] * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.push_back(ParticleDetails(_particlePositions[i], _particleRadiuses[i], rgba)); + particleDetails.emplace_back(_particlePositions[i], _particleRadiuses[i], rgba); } // sort particles back to front @@ -210,9 +205,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); // No need to sort if we're doing additive blending - if (_additiveBlending != true) { - ::zSortAxis = frustum->getDirection(); - qSort(particleDetails.begin(), particleDetails.end(), zSort); + if (!_additiveBlending) { + glm::vec3 zSortAxis = frustum->getDirection(); + std::sort(particleDetails.begin(), particleDetails.end(), + [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { + return glm::dot(lhs.position, zSortAxis) > glm::dot(rhs.position, zSortAxis); + }); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f3abeffc20..9d802295f8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -106,9 +106,9 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte EntityItem(entityItemID), _lastSimulated(usecTimestampNow()), _particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f), - _particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), - _particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), - _particleAccelerations(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), + _particlePositions(DEFAULT_MAX_PARTICLES, Vectors::ZERO), + _particleVelocities(DEFAULT_MAX_PARTICLES, Vectors::ZERO), + _particleAccelerations(DEFAULT_MAX_PARTICLES, Vectors::ZERO), _particleRadiuses(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), _radiusStarts(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), _radiusMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index e5227ade44..8de0462138 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -34,7 +34,7 @@ public: AABox(const glm::vec3& corner, const glm::vec3& dimensions); AABox(); ~AABox() {}; - + void setBox(const glm::vec3& corner, const glm::vec3& scale); void setBox(const glm::vec3& corner, float scale); From c33b6205a80ee09d95f1c3be59705898f599bf5d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 14:02:52 -0800 Subject: [PATCH 11/67] Some cleanup --- .../RenderableParticleEffectEntityItem.cpp | 38 ++++++++----------- .../entities/src/ParticleEffectEntityItem.h | 1 + 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 5c65f0bee5..42b2296529 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -37,8 +37,8 @@ public: _vertexBuffer(std::make_shared()), _indexBuffer(std::make_shared()) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, 0); - _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv)); + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, offsetof(Vertex, xyz)); + _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element::VEC2F_UV, offsetof(Vertex, uv)); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(Vertex, rgba)); } @@ -134,16 +134,15 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) { + _scene = scene; + _renderItemId = _scene->allocateID(); auto particlePayload = std::make_shared(shared_from_this()); particlePayload->setPipeline(_untexturedPipeline); - _renderItemId = scene->allocateID(); - auto renderData = ParticlePayload::Pointer(particlePayload); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(particlePayload); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(_renderItemId, renderPayload); - _scene = scene; return true; } @@ -175,8 +174,7 @@ uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } -class ParticleDetails { -public: +struct ParticleDetails { ParticleDetails(glm::vec3 position, float radius, uint32_t rgba) : position(position), radius(radius), rgba(rgba) { } glm::vec3 position; @@ -201,15 +199,13 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // sort particles back to front // NOTE: this is view frustum might be one frame out of date. - - auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum(); + auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); // No need to sort if we're doing additive blending if (!_additiveBlending) { - glm::vec3 zSortAxis = frustum->getDirection(); std::sort(particleDetails.begin(), particleDetails.end(), [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { - return glm::dot(lhs.position, zSortAxis) > glm::dot(rhs.position, zSortAxis); + return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); }); } @@ -219,11 +215,9 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { _vertices.clear(); // build vertices from particle positions and radiuses - glm::vec3 dir = frustum->getDirection(); - for (auto&& particle : particleDetails) { - glm::vec3 right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), dir)); - glm::vec3 up = glm::normalize(glm::cross(right, dir)); - + glm::vec3 right = glm::normalize(glm::cross(direction, Vectors::UNIT_Y)); + glm::vec3 up = glm::normalize(glm::cross(right, direction)); + for (const auto& particle : particleDetails) { glm::vec3 upOffset = up * particle.radius; glm::vec3 rightOffset = right * particle.radius; // generate corners of quad aligned to face the camera. @@ -237,28 +231,26 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update vertex buffer auto vertexBuffer = payload.getVertexBuffer(); + auto indexBuffer = payload.getIndexBuffer(); size_t numBytes = sizeof(Vertex) * _vertices.size(); if (numBytes == 0) { vertexBuffer->resize(0); - auto indexBuffer = payload.getIndexBuffer(); indexBuffer->resize(0); return; } - + vertexBuffer->resize(numBytes); - gpu::Byte* data = vertexBuffer->editData(); - memcpy(data, &(_vertices[0]), numBytes); + memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); // FIXME, don't update index buffer if num particles has not changed. // update index buffer - auto indexBuffer = payload.getIndexBuffer(); const size_t NUM_VERTS_PER_PARTICLE = 4; const size_t NUM_INDICES_PER_PARTICLE = 6; auto numQuads = (_vertices.size() / NUM_VERTS_PER_PARTICLE); numBytes = sizeof(uint16_t) * numQuads * NUM_INDICES_PER_PARTICLE; indexBuffer->resize(numBytes); - data = indexBuffer->editData(); + gpu::Byte* data = indexBuffer->editData(); auto indexPtr = reinterpret_cast(data); for (size_t i = 0; i < numQuads; ++i) { indexPtr[i * NUM_INDICES_PER_PARTICLE + 0] = i * NUM_VERTS_PER_PARTICLE + 0; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 7ac115d8e5..94266402d2 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -226,6 +226,7 @@ protected: void updateAlpha(quint32 index, float age); void integrateParticle(quint32 index, float deltaTime); quint32 getLivingParticleCount() const; + // the properties of this entity rgbColor _color; xColor _colorStart = DEFAULT_COLOR; From 964ac5bad6be4e0ccb57c00cd46a0695f5b47e3d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 17:00:34 -0800 Subject: [PATCH 12/67] More cleanup --- .../RenderableParticleEffectEntityItem.cpp | 8 +- .../entities/src/ParticleEffectEntityItem.cpp | 230 +++++++----------- .../entities/src/ParticleEffectEntityItem.h | 84 +++---- 3 files changed, 135 insertions(+), 187 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 42b2296529..6e86eab135 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -190,11 +190,11 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // make a copy of each particle's details std::vector particleDetails; particleDetails.reserve(getLivingParticleCount()); - for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { - auto xcolor = _particleColors[i]; - auto alpha = (uint8_t)(glm::clamp(_particleAlphas[i] * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); + for (auto& particle : _particles) { + auto xcolor = particle.color; + auto alpha = (uint8_t)(glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.emplace_back(_particlePositions[i], _particleRadiuses[i], rgba); + particleDetails.emplace_back(particle.position, particle.radius, rgba); } // sort particles back to front diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 9d802295f8..f82c80a865 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -40,9 +40,6 @@ #include "EntityScriptingInterface.h" #include "ParticleEffectEntityItem.h" -const glm::vec3 X_AXIS = glm::vec3(1.0f, 0.0f, 0.0f); -const glm::vec3 Z_AXIS = glm::vec3(0.0f, 0.0f, 1.0f); - const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 }; @@ -66,8 +63,8 @@ const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; -const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point +const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_X); // Vertical +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = Vectors::ZERO; // Emit from point const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f; const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) @@ -104,35 +101,12 @@ EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID // our non-pure virtual subclass for now... ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : EntityItem(entityItemID), - _lastSimulated(usecTimestampNow()), - _particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f), - _particlePositions(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleVelocities(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleAccelerations(DEFAULT_MAX_PARTICLES, Vectors::ZERO), - _particleRadiuses(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusStarts(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _radiusFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_PARTICLE_RADIUS), - _particleColors(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorStarts(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _colorFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_COLOR), - _particleAlphas(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaStarts(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA), - _additiveBlending(DEFAULT_ADDITIVE_BLENDING) + _lastSimulated(usecTimestampNow()) { - _type = EntityTypes::ParticleEffect; - setColor(DEFAULT_COLOR); setProperties(properties); } -ParticleEffectEntityItem::~ParticleEffectEntityItem() { -} - - void ParticleEffectEntityItem::setAlpha(float alpha) { if (MINIMUM_ALPHA <= alpha && alpha <= MAXIMUM_ALPHA) { _alpha = alpha; @@ -307,8 +281,8 @@ void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error - glm::vec3 velocity = _emitSpeed * (_emitOrientation * Z_AXIS); - glm::vec3 velocitySpread = _speedSpread * (_emitOrientation * Z_AXIS); + glm::vec3 velocity = _emitSpeed * (_emitOrientation * Vectors::UNIT_Z); + glm::vec3 velocitySpread = _speedSpread * (_emitOrientation * Vectors::UNIT_Z); glm::vec3 maxVelocity = glm::abs(velocity) + velocitySpread; glm::vec3 maxAccleration = glm::abs(_acceleration) + _accelerationSpread; @@ -610,51 +584,50 @@ void ParticleEffectEntityItem::updateShapeType(ShapeType type) { } } -void ParticleEffectEntityItem::updateRadius(quint32 index, float age) { - _particleRadiuses[index] = Interpolate::interpolate3Points(_radiusStarts[index], _radiusMiddles[index], - _radiusFinishes[index], age); +void ParticleEffectEntityItem::updateRadius(Particle& particle, float age) { + particle.radius = Interpolate::interpolate3Points(particle.radiusStart, particle.radiusMiddle, + particle.radiusFinish, age); } -void ParticleEffectEntityItem::updateColor(quint32 index, float age) { - _particleColors[index].red = (int)Interpolate::interpolate3Points(_colorStarts[index].red, _colorMiddles[index].red, - _colorFinishes[index].red, age); - _particleColors[index].green = (int)Interpolate::interpolate3Points(_colorStarts[index].green, _colorMiddles[index].green, - _colorFinishes[index].green, age); - _particleColors[index].blue = (int)Interpolate::interpolate3Points(_colorStarts[index].blue, _colorMiddles[index].blue, - _colorFinishes[index].blue, age); +void ParticleEffectEntityItem::updateColor(Particle& particle, float age) { + particle.color.red = (int)Interpolate::interpolate3Points(particle.colorStart.red, particle.colorMiddle.red, + particle.colorFinish.red, age); + particle.color.green = (int)Interpolate::interpolate3Points(particle.colorStart.green, particle.colorMiddle.green, + particle.colorFinish.green, age); + particle.color.blue = (int)Interpolate::interpolate3Points(particle.colorStart.blue, particle.colorMiddle.blue, + particle.colorFinish.blue, age); } -void ParticleEffectEntityItem::updateAlpha(quint32 index, float age) { - _particleAlphas[index] = Interpolate::interpolate3Points(_alphaStarts[index], _alphaMiddles[index], - _alphaFinishes[index], age); +void ParticleEffectEntityItem::updateAlpha(Particle& particle, float age) { + particle.alpha = Interpolate::interpolate3Points(particle.alphaStart, particle.alphaMiddle, + particle.alphaFinish, age); } -void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 accel = _particleAccelerations[index]; - glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * accel; - glm::vec3 at = accel * deltaTime; - _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; - _particleVelocities[index] += at; +void ParticleEffectEntityItem::integrateParticle(Particle& particle, float deltaTime) { + glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * particle.acceleration; + glm::vec3 at = particle.acceleration * deltaTime; + particle.position += particle.velocity * deltaTime + atSquared; + particle.velocity += at; } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); // update particles between head and tail - for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) { - _particleLifetimes[i] += deltaTime; + for (Particle& particle : _particles) { + particle.lifetime += deltaTime; // if particle has died. - if (_particleLifetimes[i] >= _lifespan || _lifespan < EPSILON) { + if (particle.lifetime >= _lifespan || _lifespan < EPSILON) { // move head forward - _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; + _particles.pop_front(); } else { - float age = _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0 - updateRadius(i, age); - updateColor(i, age); - updateAlpha(i, age); - integrateParticle(i, deltaTime); - _particlesBounds.addPoint(_particlePositions[i]); + float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 + updateRadius(particle, age); + updateColor(particle, age); + updateAlpha(particle, age); + integrateParticle(particle, deltaTime); + _particlesBounds.addPoint(particle.position); } } @@ -667,15 +640,22 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { timeLeftInFrame -= _timeUntilNextEmit; _timeUntilNextEmit = 1.0f / _emitRate; + // overflow! move head forward by one. + // because the case of head == tail indicates an empty array, not a full one. + // This can drop an existing older particle, but this is by design, newer particles are a higher priority. + if (_particles.size() >= _maxParticles) { + _particles.pop_front(); + } + // emit a new particle at tail index. - quint32 i = _particleTailIndex; - _particleLifetimes[i] = 0.0f; + _particles.push_back(Particle()); + auto particle = _particles.back(); // Radius if (_radiusSpread == 0.0f) { - _radiusStarts[i] = getRadiusStart(); - _radiusMiddles[i] =_particleRadius; - _radiusFinishes[i] = getRadiusFinish(); + particle.radiusStart = getRadiusStart(); + particle.radiusMiddle = _particleRadius; + particle.radiusFinish = getRadiusFinish(); } else { float spreadMultiplier; if (_particleRadius > 0.0f) { @@ -683,23 +663,21 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } else { spreadMultiplier = 1.0f; } - _radiusStarts[i] = - glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusMiddles[i] = - glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - _radiusFinishes[i] = - glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); } - updateRadius(i, 0.0f); + updateRadius(particle, 0.0f); // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { // Emit along z-axis from position - _particlePositions[i] = getPosition(); - _particleVelocities[i] = - (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS); - _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + } else { // Emit around point or from ellipsoid // - Distribute directions evenly around point @@ -719,11 +697,9 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { glm::vec3 emitDirection; - if (_emitDimensions == glm::vec3()) { + if (_emitDimensions == Vectors::ZERO) { // Point - emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Z_AXIS; - - _particlePositions[i] = getPosition(); + emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; } else { // Ellipsoid float radiusScale = 1.0f; @@ -745,69 +721,59 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f )); - _particlePositions[i] = getPosition() + _emitOrientation * emitPosition; + particle.position = _emitOrientation * emitPosition; } - _particleVelocities[i] = - (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } - integrateParticle(i, timeLeftInFrame); - _particlesBounds.addPoint(_particlePositions[i]); + integrateParticle(particle, timeLeftInFrame); + _particlesBounds.addPoint(particle.position); // Color if (_colorSpread == xColor{ 0, 0, 0 }) { - _colorStarts[i] = getColorStart(); - _colorMiddles[i] = getXColor(); - _colorFinishes[i] = getColorFinish(); + particle.colorStart = getColorStart(); + particle.colorMiddle = getXColor(); + particle.colorFinish = getColorFinish(); } else { xColor startColor = getColorStart(); xColor middleColor = getXColor(); xColor finishColor = getColorFinish(); float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = + float spreadMultiplierRed = middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; float spreadMultiplierGreen = middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; float spreadMultiplierBlue = middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - _colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - _colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - _colorStarts[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); + particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); + particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); + particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - _colorMiddles[i].red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - _colorMiddles[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - _colorMiddles[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); + particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); + particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); + particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - _colorFinishes[i].red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - _colorFinishes[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - _colorFinishes[i].blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); + particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); + particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); + particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); } - updateColor(i, 0.0f); + updateColor(particle, 0.0f); // Alpha if (_alphaSpread == 0.0f) { - _alphaStarts[i] = getAlphaStart(); - _alphaMiddles[i] = _alpha; - _alphaFinishes[i] = getAlphaFinish(); + particle.alphaStart = getAlphaStart(); + particle.alphaMiddle = _alpha; + particle.alphaFinish = getAlphaFinish(); } else { float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - _alphaStarts[i] = spreadMultiplier * getAlphaStart(); - _alphaMiddles[i] = spreadMultiplier * _alpha; - _alphaFinishes[i] = spreadMultiplier * getAlphaFinish(); - } - updateAlpha(i, 0.0f); - - _particleTailIndex = (_particleTailIndex + 1) % _maxParticles; - - // overflow! move head forward by one. - // because the case of head == tail indicates an empty array, not a full one. - // This can drop an existing older particle, but this is by design, newer particles are a higher priority. - if (_particleTailIndex == _particleHeadIndex) { - _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; + particle.alphaStart = spreadMultiplier * getAlphaStart(); + particle.alphaMiddle = spreadMultiplier * _alpha; + particle.alphaFinish = spreadMultiplier * getAlphaFinish(); } + updateAlpha(particle, 0.0f); } _timeUntilNextEmit -= timeLeftInFrame; @@ -818,37 +784,17 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) { _maxParticles = maxParticles; - // TODO: try to do something smart here and preserve the state of existing particles. - - // resize vectors - _particleLifetimes.resize(_maxParticles); - _particlePositions.resize(_maxParticles); - _particleVelocities.resize(_maxParticles); - _particleRadiuses.resize(_maxParticles); - _radiusStarts.resize(_maxParticles); - _radiusMiddles.resize(_maxParticles); - _radiusFinishes.resize(_maxParticles); - _particleColors.resize(_maxParticles); - _colorStarts.resize(_maxParticles); - _colorMiddles.resize(_maxParticles); - _colorFinishes.resize(_maxParticles); - _particleAlphas.resize(_maxParticles); - _alphaStarts.resize(_maxParticles); - _alphaMiddles.resize(_maxParticles); - _alphaFinishes.resize(_maxParticles); + // Pop all the overflowing oldest particles + while (_particles.size() > _maxParticles) { + _particles.pop_front(); + } // effectively clear all particles and start emitting new ones from scratch. - _particleHeadIndex = 0; - _particleTailIndex = 0; _timeUntilNextEmit = 0.0f; } } // because particles are in a ring buffer, this isn't trivial quint32 ParticleEffectEntityItem::getLivingParticleCount() const { - if (_particleTailIndex >= _particleHeadIndex) { - return _particleTailIndex - _particleHeadIndex; - } else { - return (_maxParticles - _particleHeadIndex) + _particleTailIndex; - } + return _particles.size(); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 94266402d2..86b3f4fabc 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -11,19 +11,18 @@ #ifndef hifi_ParticleEffectEntityItem_h #define hifi_ParticleEffectEntityItem_h -#include +#include #include "EntityItem.h" class ParticleEffectEntityItem : public EntityItem { public: + ALLOW_INSTANTIATION // This class can be instantiated static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual ~ParticleEffectEntityItem(); - ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of this entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const; @@ -218,15 +217,43 @@ public: virtual bool supportsDetailedRayIntersection() const { return false; } protected: + struct Particle; + using Particles = std::deque; bool isAnimatingSomething() const; void stepSimulation(float deltaTime); - void updateRadius(quint32 index, float age); - void updateColor(quint32 index, float age); - void updateAlpha(quint32 index, float age); - void integrateParticle(quint32 index, float deltaTime); + void updateRadius(Particle& particle, float age); + void updateColor(Particle& particle, float age); + void updateAlpha(Particle& particle, float age); + void integrateParticle(Particle& particle, float deltaTime); quint32 getLivingParticleCount() const; + struct Particle { + float lifetime { 0.0f }; + glm::vec3 position { Vectors::ZERO}; + glm::vec3 velocity { Vectors::ZERO}; + glm::vec3 acceleration { Vectors::ZERO}; + float radius { DEFAULT_PARTICLE_RADIUS }; + xColor color = DEFAULT_COLOR; + float alpha { DEFAULT_ALPHA }; + + float radiusStart { DEFAULT_PARTICLE_RADIUS }; + float radiusMiddle { DEFAULT_PARTICLE_RADIUS }; + float radiusFinish { DEFAULT_PARTICLE_RADIUS }; + xColor colorStart = DEFAULT_COLOR; + xColor colorMiddle = DEFAULT_COLOR; + xColor colorFinish = DEFAULT_COLOR; + float alphaStart { DEFAULT_ALPHA }; + float alphaMiddle { DEFAULT_ALPHA }; + float alphaFinish { DEFAULT_ALPHA }; + }; + + // Particles container + Particles _particles; + + // bounding volume + Extents _particlesBounds; + // the properties of this entity rgbColor _color; xColor _colorStart = DEFAULT_COLOR; @@ -256,42 +283,17 @@ protected: float _radiusSpread = DEFAULT_RADIUS_SPREAD; - quint64 _lastSimulated; - bool _isEmitting = true; + quint64 _lastSimulated { 0 }; + bool _isEmitting { true }; - QString _textures = DEFAULT_TEXTURES; - bool _texturesChangedFlag = false; - ShapeType _shapeType = SHAPE_TYPE_NONE; - - // all the internals of running the particle sim - QVector _particleLifetimes; - QVector _particlePositions; - QVector _particleVelocities; - QVector _particleAccelerations; - QVector _particleRadiuses; - QVector _radiusStarts; - QVector _radiusMiddles; - QVector _radiusFinishes; - QVector _particleColors; - QVector _colorStarts; - QVector _colorMiddles; - QVector _colorFinishes; - QVector _particleAlphas; - QVector _alphaStarts; - QVector _alphaMiddles; - QVector _alphaFinishes; - - float _timeUntilNextEmit = 0.0f; - - // particle arrays are a ring buffer, use these indices - // to keep track of the living particles. - quint32 _particleHeadIndex = 0; - quint32 _particleTailIndex = 0; - - // bounding volume - Extents _particlesBounds; + QString _textures { DEFAULT_TEXTURES }; + bool _texturesChangedFlag { false }; + ShapeType _shapeType { SHAPE_TYPE_NONE }; - bool _additiveBlending; + float _timeUntilNextEmit { 0.0f }; + + + bool _additiveBlending { DEFAULT_ADDITIVE_BLENDING }; }; #endif // hifi_ParticleEffectEntityItem_h From 7d0a5677faf2ac81d2d1f203c7e979179078c837 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 17 Nov 2015 17:41:39 -0800 Subject: [PATCH 13/67] More code cleanup --- .../entities/src/ParticleEffectEntityItem.cpp | 277 +++++++++--------- .../entities/src/ParticleEffectEntityItem.h | 6 +- 2 files changed, 149 insertions(+), 134 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f82c80a865..b52cbcd90d 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -610,6 +610,14 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta particle.velocity += at; } +void ParticleEffectEntityItem::updateParticle(Particle& particle, float deltaTime) { + float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 + updateRadius(particle, age); + updateColor(particle, age); + updateAlpha(particle, age); + integrateParticle(particle, deltaTime); +} + void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); @@ -622,11 +630,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // move head forward _particles.pop_front(); } else { - float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 - updateRadius(particle, age); - updateColor(particle, age); - updateAlpha(particle, age); - integrateParticle(particle, deltaTime); + // Otherwise update it + updateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); } } @@ -636,10 +641,6 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { float timeLeftInFrame = deltaTime; while (_timeUntilNextEmit < timeLeftInFrame) { - - timeLeftInFrame -= _timeUntilNextEmit; - _timeUntilNextEmit = 1.0f / _emitRate; - // overflow! move head forward by one. // because the case of head == tail indicates an empty array, not a full one. // This can drop an existing older particle, but this is by design, newer particles are a higher priority. @@ -648,138 +649,148 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit a new particle at tail index. - _particles.push_back(Particle()); + _particles.push_back(createParticle()); auto particle = _particles.back(); - - // Radius - if (_radiusSpread == 0.0f) { - particle.radiusStart = getRadiusStart(); - particle.radiusMiddle = _particleRadius; - particle.radiusFinish = getRadiusFinish(); - } else { - float spreadMultiplier; - if (_particleRadius > 0.0f) { - spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; - } else { - spreadMultiplier = 1.0f; - } - particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - } - updateRadius(particle, 0.0f); - - // Position, velocity, and acceleration - if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { - // Emit along z-axis from position - particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); - particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - - } else { - // Emit around point or from ellipsoid - // - Distribute directions evenly around point - // - Distribute points relatively evenly over ellipsoid surface - // - Distribute points relatively evenly within ellipsoid volume - - float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); - float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); - float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); - - float azimuth; - if (_azimuthFinish >= _azimuthStart) { - azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); - } else { - azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); - } - - glm::vec3 emitDirection; - - if (_emitDimensions == Vectors::ZERO) { - // Point - emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; - } else { - // Ellipsoid - float radiusScale = 1.0f; - if (_emitRadiusStart < 1.0f) { - float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center - float randRadius = - emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart); - radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); - } - - glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; - float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); - float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); - float z = radiuses.z * glm::sin(elevation); - glm::vec3 emitPosition = glm::vec3(x, y, z); - emitDirection = glm::normalize(glm::vec3( - radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, - radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, - radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f - )); - - particle.position = _emitOrientation * emitPosition; - } - - particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; - } - integrateParticle(particle, timeLeftInFrame); + particle.lifetime += timeLeftInFrame; + + // Initialize it + updateParticle(particle, timeLeftInFrame); _particlesBounds.addPoint(particle.position); - - // Color - if (_colorSpread == xColor{ 0, 0, 0 }) { - particle.colorStart = getColorStart(); - particle.colorMiddle = getXColor(); - particle.colorFinish = getColorFinish(); - } else { - xColor startColor = getColorStart(); - xColor middleColor = getXColor(); - xColor finishColor = getColorFinish(); - - float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = - middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; - float spreadMultiplierGreen = - middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; - float spreadMultiplierBlue = - middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - - particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - - particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - - particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); - } - updateColor(particle, 0.0f); - - // Alpha - if (_alphaSpread == 0.0f) { - particle.alphaStart = getAlphaStart(); - particle.alphaMiddle = _alpha; - particle.alphaFinish = getAlphaFinish(); - } else { - float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - particle.alphaStart = spreadMultiplier * getAlphaStart(); - particle.alphaMiddle = spreadMultiplier * _alpha; - particle.alphaFinish = spreadMultiplier * getAlphaFinish(); - } - updateAlpha(particle, 0.0f); + + // Advance in frame + timeLeftInFrame -= _timeUntilNextEmit; + _timeUntilNextEmit = 1.0f / _emitRate; } _timeUntilNextEmit -= timeLeftInFrame; } } +ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { + Particle particle; + + // Radius + if (_radiusSpread == 0.0f) { + particle.radiusStart = getRadiusStart(); + particle.radiusMiddle = _particleRadius; + particle.radiusFinish = getRadiusFinish(); + } else { + float spreadMultiplier; + if (_particleRadius > 0.0f) { + spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; + } else { + spreadMultiplier = 1.0f; + } + particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), + MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + } + + // Position, velocity, and acceleration + if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { + // Emit along z-axis from position + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Vectors::UNIT_Z); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + + } else { + // Emit around point or from ellipsoid + // - Distribute directions evenly around point + // - Distribute points relatively evenly over ellipsoid surface + // - Distribute points relatively evenly within ellipsoid volume + + float elevationMinZ = sin(PI_OVER_TWO - _polarFinish); + float elevationMaxZ = sin(PI_OVER_TWO - _polarStart); + float elevation = asin(elevationMinZ + (elevationMaxZ - elevationMinZ) * randFloat()); + + float azimuth; + if (_azimuthFinish >= _azimuthStart) { + azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); + } else { + azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); + } + + glm::vec3 emitDirection; + + if (_emitDimensions == Vectors::ZERO) { + // Point + emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Vectors::UNIT_Z; + } else { + // Ellipsoid + float radiusScale = 1.0f; + if (_emitRadiusStart < 1.0f) { + float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center + float randRadius = + emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart); + radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); + } + + glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; + float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); + float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); + float z = radiuses.z * glm::sin(elevation); + glm::vec3 emitPosition = glm::vec3(x, y, z); + emitDirection = glm::normalize(glm::vec3( + radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, + radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, + radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f + )); + + particle.position = _emitOrientation * emitPosition; + } + + particle.velocity = (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; + } + + // Color + if (_colorSpread == xColor{ 0, 0, 0 }) { + particle.colorStart = getColorStart(); + particle.colorMiddle = getXColor(); + particle.colorFinish = getColorFinish(); + } else { + xColor startColor = getColorStart(); + xColor middleColor = getXColor(); + xColor finishColor = getColorFinish(); + + float spread = randFloatInRange(-1.0f, 1.0f); + float spreadMultiplierRed = + middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; + float spreadMultiplierGreen = + middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; + float spreadMultiplierBlue = + middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; + + particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); + particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); + particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); + + particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); + particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); + particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); + + particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); + particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); + particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); + } + + // Alpha + if (_alphaSpread == 0.0f) { + particle.alphaStart = getAlphaStart(); + particle.alphaMiddle = _alpha; + particle.alphaFinish = getAlphaFinish(); + } else { + float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; + particle.alphaStart = spreadMultiplier * getAlphaStart(); + particle.alphaMiddle = spreadMultiplier * _alpha; + particle.alphaFinish = spreadMultiplier * getAlphaFinish(); + } + + return particle; +} + void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) { _maxParticles = maxParticles; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 86b3f4fabc..7a3d515f45 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -221,12 +221,16 @@ protected: using Particles = std::deque; bool isAnimatingSomething() const; + quint32 getLivingParticleCount() const; + + Particle createParticle(); void stepSimulation(float deltaTime); + void updateParticle(Particle& particle, float deltaTime); + void updateRadius(Particle& particle, float age); void updateColor(Particle& particle, float age); void updateAlpha(Particle& particle, float age); void integrateParticle(Particle& particle, float deltaTime); - quint32 getLivingParticleCount() const; struct Particle { float lifetime { 0.0f }; From 230a413ec19e6796b124a73dbc0cea780444a5d0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 12:20:07 -0800 Subject: [PATCH 14/67] First pass at new particle shader --- .../RenderableParticleEffectEntityItem.cpp | 82 ++++++------------- .../src/RenderableParticleEffectEntityItem.h | 7 +- .../src/textured_particle.slf | 15 ++-- .../src/textured_particle.slv | 55 +++++++++++-- .../entities/src/ParticleEffectEntityItem.cpp | 2 +- .../entities/src/ParticleEffectEntityItem.h | 2 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 2 +- libraries/gpu/src/gpu/Stream.cpp | 2 +- libraries/gpu/src/gpu/Stream.h | 6 +- libraries/gpu/src/gpu/Transform.slh | 17 +++- 10 files changed, 104 insertions(+), 86 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 6e86eab135..06f5dde300 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -25,21 +25,23 @@ #include "textured_particle_frag.h" #include "textured_particle_alpha_discard_frag.h" +static const uint32_t VERTEX_PER_QUAD = 6; + class ParticlePayload { public: - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - typedef RenderableParticleEffectEntityItem::Vertex Vertex; + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + using Vertex = RenderableParticleEffectEntityItem::Vertex; ParticlePayload(EntityItemPointer entity) : _entity(entity), _vertexFormat(std::make_shared()), - _vertexBuffer(std::make_shared()), - _indexBuffer(std::make_shared()) { + _vertexBuffer(std::make_shared()) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, offsetof(Vertex, xyz)); - _vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element::VEC2F_UV, offsetof(Vertex, uv)); - _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(Vertex, rgba)); + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, + offsetof(Vertex, xyzw), VERTEX_PER_QUAD); + _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, + offsetof(Vertex, rgba), VERTEX_PER_QUAD); } void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } @@ -54,9 +56,6 @@ public: gpu::BufferPointer getVertexBuffer() { return _vertexBuffer; } const gpu::BufferPointer& getVertexBuffer() const { return _vertexBuffer; } - gpu::BufferPointer getIndexBuffer() { return _indexBuffer; } - const gpu::BufferPointer& getIndexBuffer() const { return _indexBuffer; } - void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } @@ -76,10 +75,9 @@ public: batch.setModelTransform(_modelTransform); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); - batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0); - auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t); - batch.drawIndexed(gpu::TRIANGLES, numIndices); + auto numVertices = _vertexBuffer->getSize() / sizeof(Vertex); + batch.draw(gpu::TRIANGLES, numVertices * VERTEX_PER_QUAD); } protected: @@ -89,7 +87,6 @@ protected: gpu::PipelinePointer _pipeline; gpu::Stream::FormatPointer _vertexFormat; gpu::BufferPointer _vertexBuffer; - gpu::BufferPointer _indexBuffer; gpu::TexturePointer _texture; bool _visibleFlag = true; }; @@ -197,70 +194,38 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { particleDetails.emplace_back(particle.position, particle.radius, rgba); } - // sort particles back to front - // NOTE: this is view frustum might be one frame out of date. - auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); - // No need to sort if we're doing additive blending if (!_additiveBlending) { + // sort particles back to front + // NOTE: this is view frustum might be one frame out of date. + auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); + // Get direction in the entity space + direction = glm::inverse(getRotation()) * direction; + std::sort(particleDetails.begin(), particleDetails.end(), [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); }); } - - - // allocate vertices - _vertices.clear(); - // build vertices from particle positions and radiuses - glm::vec3 right = glm::normalize(glm::cross(direction, Vectors::UNIT_Y)); - glm::vec3 up = glm::normalize(glm::cross(right, direction)); + _vertices.clear(); // clear vertices + _vertices.reserve(particleDetails.size()); // Reserve space for (const auto& particle : particleDetails) { - glm::vec3 upOffset = up * particle.radius; - glm::vec3 rightOffset = right * particle.radius; - // generate corners of quad aligned to face the camera. - _vertices.emplace_back(particle.position + rightOffset + upOffset, glm::vec2(1.0f, 1.0f), particle.rgba); - _vertices.emplace_back(particle.position - rightOffset + upOffset, glm::vec2(0.0f, 1.0f), particle.rgba); - _vertices.emplace_back(particle.position - rightOffset - upOffset, glm::vec2(0.0f, 0.0f), particle.rgba); - _vertices.emplace_back(particle.position + rightOffset - upOffset, glm::vec2(1.0f, 0.0f), particle.rgba); + _vertices.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update vertex buffer auto vertexBuffer = payload.getVertexBuffer(); - auto indexBuffer = payload.getIndexBuffer(); size_t numBytes = sizeof(Vertex) * _vertices.size(); - + vertexBuffer->resize(numBytes); if (numBytes == 0) { - vertexBuffer->resize(0); - indexBuffer->resize(0); return; } - - vertexBuffer->resize(numBytes); memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); - // FIXME, don't update index buffer if num particles has not changed. - // update index buffer - const size_t NUM_VERTS_PER_PARTICLE = 4; - const size_t NUM_INDICES_PER_PARTICLE = 6; - auto numQuads = (_vertices.size() / NUM_VERTS_PER_PARTICLE); - numBytes = sizeof(uint16_t) * numQuads * NUM_INDICES_PER_PARTICLE; - indexBuffer->resize(numBytes); - gpu::Byte* data = indexBuffer->editData(); - auto indexPtr = reinterpret_cast(data); - for (size_t i = 0; i < numQuads; ++i) { - indexPtr[i * NUM_INDICES_PER_PARTICLE + 0] = i * NUM_VERTS_PER_PARTICLE + 0; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 1] = i * NUM_VERTS_PER_PARTICLE + 1; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 2] = i * NUM_VERTS_PER_PARTICLE + 3; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 3] = i * NUM_VERTS_PER_PARTICLE + 1; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 4] = i * NUM_VERTS_PER_PARTICLE + 2; - indexPtr[i * NUM_INDICES_PER_PARTICLE + 5] = i * NUM_VERTS_PER_PARTICLE + 3; - } - // update transform glm::vec3 position = getPosition(); glm::quat rotation = getRotation(); @@ -323,8 +288,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { gpu::ShaderPointer fragShader; if (_additiveBlending) { fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); - } - else { + } else { //If we are sorting and have no additive blending, we want to discard pixels with low alpha to avoid inter-particle entity artifacts fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_alpha_discard_frag))); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 678f7eb904..5270a29dd5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -32,10 +32,9 @@ protected: render::ItemID _renderItemId; struct Vertex { - Vertex(glm::vec3 xyzIn, glm::vec2 uvIn, uint32_t rgbaIn) : xyz(xyzIn), uv(uvIn), rgba(rgbaIn) {} - glm::vec3 xyz; - glm::vec2 uv; - uint32_t rgba; + Vertex(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} + glm::vec4 xyzw; // Position + radius + uint32_t rgba; // Color }; void createPipelines(); diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 58a3103323..29e683bc4c 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -9,14 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -uniform sampler2D colorMap; - -in vec4 _color; -in vec2 _texCoord0; +in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; +uniform sampler2D tex; + void main(void) { - vec4 color = texture(colorMap, _texCoord0); - outFragColor = color * _color; + outFragColor = varColor;//texture(tex, varTexcoord.xy) * varColor; + + if (varColor == vec4(0,0,0,1)) { + discard; + } } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index c741af559d..012f1659ec 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -10,21 +10,58 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Inputs.slh@> - <@include gpu/Transform.slh@> <$declareStandardTransform()$> -out vec4 _color; -out vec2 _texCoord0; +in vec4 inPosition; +in vec4 inColor; + +out vec4 varColor; +out vec2 varTexcoord; void main(void) { - // pass along the color & uvs to fragment shader - _color = inColor; - _texCoord0 = inTexCoord0.xy; - + const int NUM_VERTICES_PER_PARTICLE = 6; + const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) + ); + + // anchor point in eye space + vec4 anchorPoint = vec4(inPosition.xyz, 1.0); + float radius = inPosition.w; + TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyePos(cam, obj, anchorPoint, anchorPoint)$> + + // Which icon are we dealing with ? + int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; + + // Which quad vertex pos? + int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; + vec4 quadPos = radius * UNIT_QUAD[twoTriID]; + + // Pass the texcoord and the z texcoord is representing the texture icon + varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); + varColor = inColor; + + if (particleID == 0) { + varColor = vec4(1,0,0,1); + } else if (particleID == 5) { + varColor = vec4(0,1,0,1); + } else if (particleID == 10) { + varColor = vec4(0,0,1,1); + } else { + varColor = vec4(0,0,0,1); + } + + vec4 clipPos; + vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); + <$transformEyeToClip(cam, eyePos, clipPos)$> + gl_Position = clipPos; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index b52cbcd90d..e12d7df488 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -91,7 +91,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; -const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false; +const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = true; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 7a3d515f45..62c9415749 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -211,7 +211,7 @@ public: static const bool DEFAULT_ADDITIVE_BLENDING; bool getAdditiveBlending() const { return _additiveBlending; } void setAdditiveBlending(bool additiveBlending) { - _additiveBlending = additiveBlending; + _additiveBlending = true; } virtual bool supportsDetailedRayIntersection() const { return false; } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 5a0ab93ec5..19fa94524e 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -154,7 +154,7 @@ GLBackend::GLShader* compileShader(const Shader& shader) { qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; qCWarning(gpulogging) << temp; - + /* filestream.open("debugshader.glsl.info.txt"); if (filestream.is_open()) { diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index 183f2137fb..d43999d3dd 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -59,7 +59,7 @@ void Stream::Format::evaluateCache() { } } -bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) { +bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, uint32 frequency) { _attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency); evaluateCache(); return true; diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 492af5f62a..6adf9a60a0 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -49,8 +49,8 @@ public: // Frequency describer enum Frequency { + PER_INSTANCE = -1, PER_VERTEX = 0, - PER_INSTANCE, }; // The attribute description @@ -59,7 +59,7 @@ public: public: Attribute() {} - Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -107,7 +107,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX); + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX); bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index e67fbf7f66..de7cdbf7af 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -74,6 +74,16 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + + { // transformModelToEyePos + vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); + } +<@endfunc@> + <@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> @@ -86,7 +96,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> - <@func transformModelToWorldPos(objectTransform, modelPos, worldPos)@> { // transformModelToWorldPos <$worldPos$> = (<$objectTransform$>._model * <$modelPos$>); @@ -140,4 +149,10 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func transformEyeToClip(cameraTransform, eyePos, clipPos)@> + { // transformEyeToClip + <$clipPos$> = <$cameraTransform$>._projection * <$eyePos$>; + } +<@endfunc@> + <@endif@> From cb14fbf4a1ea8326cf1594ef413bdcf403338645 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 15:52:42 -0800 Subject: [PATCH 15/67] Instance particle draw calls --- .../RenderableParticleEffectEntityItem.cpp | 40 +++++++++---------- .../src/RenderableParticleEffectEntityItem.h | 9 +++-- .../src/textured_particle.slf | 6 +-- .../src/textured_particle.slv | 14 +------ libraries/gpu/src/gpu/Stream.cpp | 12 +----- libraries/gpu/src/gpu/Stream.h | 11 ++--- 6 files changed, 32 insertions(+), 60 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 06f5dde300..f2978a4092 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -25,23 +25,23 @@ #include "textured_particle_frag.h" #include "textured_particle_alpha_discard_frag.h" -static const uint32_t VERTEX_PER_QUAD = 6; +static const size_t VERTEX_PER_PARTICLE = 4; class ParticlePayload { public: using Payload = render::Payload; using Pointer = Payload::DataPointer; - using Vertex = RenderableParticleEffectEntityItem::Vertex; + using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; ParticlePayload(EntityItemPointer entity) : _entity(entity), _vertexFormat(std::make_shared()), - _vertexBuffer(std::make_shared()) { + _particleBuffer(std::make_shared()) { _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, - offsetof(Vertex, xyzw), VERTEX_PER_QUAD); + offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, - offsetof(Vertex, rgba), VERTEX_PER_QUAD); + offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); } void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } @@ -53,8 +53,8 @@ public: const AABox& getBound() const { return _bound; } void setBound(AABox& bound) { _bound = bound; } - gpu::BufferPointer getVertexBuffer() { return _vertexBuffer; } - const gpu::BufferPointer& getVertexBuffer() const { return _vertexBuffer; } + gpu::BufferPointer getParticleBuffer() { return _particleBuffer; } + const gpu::BufferPointer& getParticleBuffer() const { return _particleBuffer; } void setTexture(gpu::TexturePointer texture) { _texture = texture; } const gpu::TexturePointer& getTexture() const { return _texture; } @@ -74,10 +74,10 @@ public: batch.setModelTransform(_modelTransform); batch.setInputFormat(_vertexFormat); - batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(Vertex)); + batch.setInputBuffer(0, _particleBuffer, 0, sizeof(ParticlePrimitive)); - auto numVertices = _vertexBuffer->getSize() / sizeof(Vertex); - batch.draw(gpu::TRIANGLES, numVertices * VERTEX_PER_QUAD); + auto numParticles = _particleBuffer->getSize() / sizeof(ParticlePrimitive); + batch.drawInstanced(numParticles, gpu::TRIANGLE_STRIP, VERTEX_PER_PARTICLE); } protected: @@ -86,7 +86,7 @@ protected: AABox _bound; gpu::PipelinePointer _pipeline; gpu::Stream::FormatPointer _vertexFormat; - gpu::BufferPointer _vertexBuffer; + gpu::BufferPointer _particleBuffer; gpu::TexturePointer _texture; bool _visibleFlag = true; }; @@ -208,23 +208,23 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { }); } - // build vertices from particle positions and radiuses - _vertices.clear(); // clear vertices - _vertices.reserve(particleDetails.size()); // Reserve space + // build primitives from particle positions and radiuses + _particlePrimitives.clear(); // clear primitives + _particlePrimitives.reserve(particleDetails.size()); // Reserve space for (const auto& particle : particleDetails) { - _vertices.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); + _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { - // update vertex buffer - auto vertexBuffer = payload.getVertexBuffer(); - size_t numBytes = sizeof(Vertex) * _vertices.size(); - vertexBuffer->resize(numBytes); + // update particle buffer + auto particleBuffer = payload.getParticleBuffer(); + size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); + particleBuffer->resize(numBytes); if (numBytes == 0) { return; } - memcpy(vertexBuffer->editData(), _vertices.data(), numBytes); + memcpy(particleBuffer->editData(), _particlePrimitives.data(), numBytes); // update transform glm::vec3 position = getPosition(); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 5270a29dd5..b385b6fe41 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,7 +16,7 @@ #include "RenderableEntityItem.h" class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { -friend class ParticlePayload; + friend class ParticlePayload; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); @@ -31,15 +31,16 @@ public: protected: render::ItemID _renderItemId; - struct Vertex { - Vertex(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} + struct ParticlePrimitive { + ParticlePrimitive(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} glm::vec4 xyzw; // Position + radius uint32_t rgba; // Color }; + using Particles = std::vector; void createPipelines(); - std::vector _vertices; + Particles _particlePrimitives; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 29e683bc4c..4c718c0b58 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -17,9 +17,5 @@ out vec4 outFragColor; uniform sampler2D tex; void main(void) { - outFragColor = varColor;//texture(tex, varTexcoord.xy) * varColor; - - if (varColor == vec4(0,0,0,1)) { - discard; - } + outFragColor = texture(tex, varTexcoord.xy) * varColor; } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 012f1659ec..615fd1a747 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -21,13 +21,11 @@ out vec4 varColor; out vec2 varTexcoord; void main(void) { - const int NUM_VERTICES_PER_PARTICLE = 6; + const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(1.0, -1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0) ); @@ -50,16 +48,6 @@ void main(void) { varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); varColor = inColor; - if (particleID == 0) { - varColor = vec4(1,0,0,1); - } else if (particleID == 5) { - varColor = vec4(0,1,0,1); - } else if (particleID == 10) { - varColor = vec4(0,0,1,1); - } else { - varColor = vec4(0,0,0,1); - } - vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); <$transformEyeToClip(cam, eyePos, clipPos)$> diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index d43999d3dd..ff765f3250 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -59,7 +59,7 @@ void Stream::Format::evaluateCache() { } } -bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, uint32 frequency) { +bool Stream::Format::setAttribute(Slot slot, Slot channel, Element element, Offset offset, Frequency frequency) { _attributes[slot] = Attribute((InputSlot) slot, channel, element, offset, frequency); evaluateCache(); return true; @@ -77,16 +77,6 @@ bool Stream::Format::setAttribute(Slot slot, Slot channel, Frequency frequency) return true; } - -BufferStream::BufferStream() : - _buffers(), - _offsets(), - _strides() -{} - -BufferStream::~BufferStream() { -} - void BufferStream::addBuffer(const BufferPointer& buffer, Offset offset, Offset stride) { _buffers.push_back(buffer); _offsets.push_back(offset); diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 6adf9a60a0..9966fceca9 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -49,8 +49,8 @@ public: // Frequency describer enum Frequency { - PER_INSTANCE = -1, PER_VERTEX = 0, + PER_INSTANCE = 1, }; // The attribute description @@ -59,7 +59,7 @@ public: public: Attribute() {} - Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX) : + Attribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX) : _slot(slot), _channel(channel), _element(element), @@ -107,7 +107,7 @@ public: uint32 getElementTotalSize() const { return _elementTotalSize; } - bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, uint32 frequency = PER_VERTEX); + bool setAttribute(Slot slot, Slot channel, Element element, Offset offset = 0, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); @@ -129,10 +129,7 @@ typedef std::vector< Offset > Offsets; // A Buffer Stream can be assigned to the Batch to set several stream channels in one call class BufferStream { public: - typedef Offsets Strides; - - BufferStream(); - ~BufferStream(); + using Strides = Offsets; void clear() { _buffers.clear(); _offsets.clear(); _strides.clear(); } void addBuffer(const BufferPointer& buffer, Offset offset, Offset stride); From ca17c756319fb02bed2662d243a7c8c36aa2f330 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 16:07:01 -0800 Subject: [PATCH 16/67] Save one array traversal --- .../RenderableParticleEffectEntityItem.cpp | 34 +++++-------------- .../entities/src/ParticleEffectEntityItem.cpp | 7 +--- .../entities/src/ParticleEffectEntityItem.h | 1 - 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f2978a4092..f4117dd790 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -171,27 +171,18 @@ uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } -struct ParticleDetails { - ParticleDetails(glm::vec3 position, float radius, uint32_t rgba) : position(position), radius(radius), rgba(rgba) { } - - glm::vec3 position; - float radius; - uint32_t rgba; -}; - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } - // make a copy of each particle's details - std::vector particleDetails; - particleDetails.reserve(getLivingParticleCount()); + // build primitives from particle positions and radiuses + _particlePrimitives.clear(); // clear primitives + _particlePrimitives.reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - auto xcolor = particle.color; - auto alpha = (uint8_t)(glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255.0f); - auto rgba = toRGBA(xcolor.red, xcolor.green, xcolor.blue, alpha); - particleDetails.emplace_back(particle.position, particle.radius, rgba); + auto alpha = glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255; + auto rgba = toRGBA(particle.color.red, particle.color.green, particle.color.blue, alpha); + _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), rgba); } // No need to sort if we're doing additive blending @@ -202,19 +193,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // Get direction in the entity space direction = glm::inverse(getRotation()) * direction; - std::sort(particleDetails.begin(), particleDetails.end(), - [&](const ParticleDetails& lhs, const ParticleDetails& rhs) { - return glm::dot(lhs.position, direction) > glm::dot(rhs.position, direction); + std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), + [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { + return glm::dot(glm::vec3(lhs.xyzw), direction) > glm::dot(glm::vec3(rhs.xyzw), direction); }); } - // build primitives from particle positions and radiuses - _particlePrimitives.clear(); // clear primitives - _particlePrimitives.reserve(particleDetails.size()); // Reserve space - for (const auto& particle : particleDetails) { - _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), particle.rgba); - } - render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { // update particle buffer diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index e12d7df488..e7475c30b1 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -549,7 +549,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, bool ParticleEffectEntityItem::isEmittingParticles() const { // keep emitting if there are particles still alive. - return (getIsEmitting() || getLivingParticleCount() > 0); + return (getIsEmitting() || !_particles.empty()); } bool ParticleEffectEntityItem::needsToCallUpdate() const { @@ -804,8 +804,3 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { _timeUntilNextEmit = 0.0f; } } - -// because particles are in a ring buffer, this isn't trivial -quint32 ParticleEffectEntityItem::getLivingParticleCount() const { - return _particles.size(); -} diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 62c9415749..08074f58fe 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -221,7 +221,6 @@ protected: using Particles = std::deque; bool isAnimatingSomething() const; - quint32 getLivingParticleCount() const; Particle createParticle(); void stepSimulation(float deltaTime); From 61511d57bba8c2ca2adc283133253c51404bbd0b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 16:23:31 -0800 Subject: [PATCH 17/67] Rename struct/Add type aliases --- .../RenderableParticleEffectEntityItem.cpp | 32 ++++++++++--------- .../src/RenderableParticleEffectEntityItem.h | 4 +-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f4117dd790..c971813bd0 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -32,20 +32,22 @@ public: using Payload = render::Payload; using Pointer = Payload::DataPointer; using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; + using PipelinePointer = gpu::PipelinePointer; + using FormatPointer = gpu::Stream::FormatPointer; + using BufferPointer = gpu::BufferPointer; + using TexturePointer = gpu::TexturePointer; + using Format = gpu::Stream::Format; + using Buffer = gpu::Buffer; - ParticlePayload(EntityItemPointer entity) : - _entity(entity), - _vertexFormat(std::make_shared()), - _particleBuffer(std::make_shared()) { - + ParticlePayload(EntityItemPointer entity) : _entity(entity) { _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); } - void setPipeline(gpu::PipelinePointer pipeline) { _pipeline = pipeline; } - const gpu::PipelinePointer& getPipeline() const { return _pipeline; } + void setPipeline(PipelinePointer pipeline) { _pipeline = pipeline; } + const PipelinePointer& getPipeline() const { return _pipeline; } const Transform& getModelTransform() const { return _modelTransform; } void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } @@ -53,11 +55,11 @@ public: const AABox& getBound() const { return _bound; } void setBound(AABox& bound) { _bound = bound; } - gpu::BufferPointer getParticleBuffer() { return _particleBuffer; } - const gpu::BufferPointer& getParticleBuffer() const { return _particleBuffer; } + BufferPointer getParticleBuffer() { return _particleBuffer; } + const BufferPointer& getParticleBuffer() const { return _particleBuffer; } - void setTexture(gpu::TexturePointer texture) { _texture = texture; } - const gpu::TexturePointer& getTexture() const { return _texture; } + void setTexture(TexturePointer texture) { _texture = texture; } + const TexturePointer& getTexture() const { return _texture; } bool getVisibleFlag() const { return _visibleFlag; } void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } @@ -84,10 +86,10 @@ protected: EntityItemPointer _entity; Transform _modelTransform; AABox _bound; - gpu::PipelinePointer _pipeline; - gpu::Stream::FormatPointer _vertexFormat; - gpu::BufferPointer _particleBuffer; - gpu::TexturePointer _texture; + PipelinePointer _pipeline; + FormatPointer _vertexFormat { std::make_shared() }; + BufferPointer _particleBuffer { std::make_shared() }; + TexturePointer _texture; bool _visibleFlag = true; }; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index b385b6fe41..4b3fb608ca 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -36,11 +36,11 @@ protected: glm::vec4 xyzw; // Position + radius uint32_t rgba; // Color }; - using Particles = std::vector; + using ParticlePrimitives = std::vector; void createPipelines(); - Particles _particlePrimitives; + ParticlePrimitives _particlePrimitives; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; From e25ea122d85029ac5559f6819fae1230c5ace630 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 23:07:06 -0800 Subject: [PATCH 18/67] Start moving update to shader --- .../RenderableParticleEffectEntityItem.cpp | 53 +++++++--- .../src/RenderableParticleEffectEntityItem.h | 33 +++++-- .../src/textured_particle.slf | 6 +- .../src/textured_particle.slv | 45 ++++++++- .../src/textured_particle_alpha_discard.slf | 8 +- .../entities/src/ParticleEffectEntityItem.cpp | 96 +------------------ .../entities/src/ParticleEffectEntityItem.h | 21 +--- libraries/model/src/model/Light.cpp | 2 +- libraries/model/src/model/Light.h | 2 - 9 files changed, 119 insertions(+), 147 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index c971813bd0..c7a2e4893c 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -32,18 +32,23 @@ public: using Payload = render::Payload; using Pointer = Payload::DataPointer; using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; + using ParticleUniforms = RenderableParticleEffectEntityItem::ParticleUniforms; using PipelinePointer = gpu::PipelinePointer; using FormatPointer = gpu::Stream::FormatPointer; using BufferPointer = gpu::BufferPointer; using TexturePointer = gpu::TexturePointer; using Format = gpu::Stream::Format; using Buffer = gpu::Buffer; + using BufferView = gpu::BufferView; ParticlePayload(EntityItemPointer entity) : _entity(entity) { - _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC4F_XYZW, - offsetof(ParticlePrimitive, xyzw), gpu::Stream::PER_INSTANCE); - _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::COLOR_RGBA_32, - offsetof(ParticlePrimitive, rgba), gpu::Stream::PER_INSTANCE); + ParticleUniforms uniforms; + _uniformBuffer = std::make_shared(sizeof(ParticleUniforms), (const gpu::Byte*) &uniforms); + + _vertexFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element::VEC3F_XYZ, + offsetof(ParticlePrimitive, xyz), gpu::Stream::PER_INSTANCE); + _vertexFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element::VEC2F_UV, + offsetof(ParticlePrimitive, uv), gpu::Stream::PER_INSTANCE); } void setPipeline(PipelinePointer pipeline) { _pipeline = pipeline; } @@ -57,6 +62,9 @@ public: BufferPointer getParticleBuffer() { return _particleBuffer; } const BufferPointer& getParticleBuffer() const { return _particleBuffer; } + + const ParticleUniforms& getParticleUniforms() const { return _uniformBuffer.get(); } + ParticleUniforms& editParticleUniforms() { return _uniformBuffer.edit(); } void setTexture(TexturePointer texture) { _texture = texture; } const TexturePointer& getTexture() const { return _texture; } @@ -75,6 +83,7 @@ public: } batch.setModelTransform(_modelTransform); + batch.setUniformBuffer(0, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(ParticlePrimitive)); @@ -89,6 +98,7 @@ protected: PipelinePointer _pipeline; FormatPointer _vertexFormat { std::make_shared() }; BufferPointer _particleBuffer { std::make_shared() }; + BufferView _uniformBuffer; TexturePointer _texture; bool _visibleFlag = true; }; @@ -169,22 +179,33 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); +glm::vec3 toGlm(const rgbColor& color) { + return glm::vec3(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]); } void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } - - // build primitives from particle positions and radiuses + + // Fill in Uniforms structure + _particleUniforms.radius.start = getRadiusStart(); + _particleUniforms.radius.middle = getParticleRadius(); + _particleUniforms.radius.finish = getRadiusFinish(); + _particleUniforms.radius.spread = getRadiusSpread(); + + _particleUniforms.color.start = glm::vec4(toGlm(getColorStart()), getAlphaStart()); + _particleUniforms.color.middle = glm::vec4(toGlm(getColor()), getAlpha()); + _particleUniforms.color.finish = glm::vec4(toGlm(getColorFinish()), getAlphaFinish()); + _particleUniforms.color.spread = glm::vec4(toGlm(getColorSpread()), getAlphaSpread()); + + _particleUniforms.lifespan = getLifespan(); + + // Build particle primitives _particlePrimitives.clear(); // clear primitives _particlePrimitives.reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - auto alpha = glm::clamp(particle.alpha * getLocalRenderAlpha(), 0.0f, 1.0f) * 255; - auto rgba = toRGBA(particle.color.red, particle.color.green, particle.color.blue, alpha); - _particlePrimitives.emplace_back(glm::vec4(particle.position, particle.radius), rgba); + _particlePrimitives.emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } // No need to sort if we're doing additive blending @@ -197,13 +218,16 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { - return glm::dot(glm::vec3(lhs.xyzw), direction) > glm::dot(glm::vec3(rhs.xyzw), direction); + return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); }); } render::PendingChanges pendingChanges; pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { - // update particle buffer + // Update particle uniforms + memcpy(&payload.editParticleUniforms(), &_particleUniforms, sizeof(ParticleUniforms)); + + // Update particle buffer auto particleBuffer = payload.getParticleBuffer(); size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); particleBuffer->resize(numBytes); @@ -243,8 +267,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { gpu::State::BlendArg destinationColorBlendArg; if (_additiveBlending) { destinationColorBlendArg = gpu::State::ONE; - } - else { + } else { destinationColorBlendArg = gpu::State::INV_SRC_ALPHA; writeToDepthBuffer = true; } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 4b3fb608ca..0e1dabb6a6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -29,18 +29,37 @@ public: virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; protected: - render::ItemID _renderItemId; - + struct ParticleUniforms { + struct { + float start; + float middle; + float finish; + float spread; + } radius; + + struct { + glm::vec4 start; + glm::vec4 middle; + glm::vec4 finish; + glm::vec4 spread; + } color; + + float lifespan; + }; + struct ParticlePrimitive { - ParticlePrimitive(glm::vec4 xyzwIn, uint32_t rgbaIn) : xyzw(xyzwIn), rgba(rgbaIn) {} - glm::vec4 xyzw; // Position + radius - uint32_t rgba; // Color + ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} + glm::vec3 xyz; // Position + glm::vec2 uv; // Lifetime + seed }; using ParticlePrimitives = std::vector; - + void createPipelines(); - + + render::ItemID _renderItemId; ParticlePrimitives _particlePrimitives; + ParticleUniforms _particleUniforms; + gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; diff --git a/libraries/entities-renderer/src/textured_particle.slf b/libraries/entities-renderer/src/textured_particle.slf index 4c718c0b58..e139c7cc01 100644 --- a/libraries/entities-renderer/src/textured_particle.slf +++ b/libraries/entities-renderer/src/textured_particle.slf @@ -9,13 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +uniform sampler2D colorMap; + in vec4 varColor; in vec2 varTexcoord; out vec4 outFragColor; -uniform sampler2D tex; - void main(void) { - outFragColor = texture(tex, varTexcoord.xy) * varColor; + outFragColor = texture(colorMap, varTexcoord.xy) * varColor; } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 615fd1a747..0027d70da3 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,12 +14,45 @@ <$declareStandardTransform()$> -in vec4 inPosition; -in vec4 inColor; +struct ParticleUniforms { + struct { + float start; + float middle; + float finish; + float spread; + } radius; + + struct { + vec4 start; + vec4 middle; + vec4 finish; + vec4 spread; + } color; + + float lifespan; +}; + +uniform particleBuffer { + ParticleUniforms particle; +}; + +in vec3 inPosition; +in vec2 inExtra; out vec4 varColor; out vec2 varTexcoord; +float mix(float start, float finish, float age) { + return start + (finish - start) * age; +} + +vec4 mixV(vec4 start, vec4 finish, float age) { + return vec4(mix(start.x, finish.x, age), + mix(start.y, finish.y, age), + mix(start.z, finish.z, age), + mix(start.w, finish.w, age)); +} + void main(void) { const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( @@ -29,9 +62,12 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); + float age = inExtra.x / particle.lifespan; + float seed = inExtra.y; + // anchor point in eye space vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = inPosition.w; + float radius = mix(particle.radius.start, particle.radius.finish , age); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -46,7 +82,8 @@ void main(void) { // Pass the texcoord and the z texcoord is representing the texture icon varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); - varColor = inColor; + varColor = mixV(particle.color.start, particle.color.finish , age); + varColor.w = particle.color.middle.w; vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); diff --git a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf index 389744449a..4d96da943b 100644 --- a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf +++ b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf @@ -11,15 +11,15 @@ uniform sampler2D colorMap; -in vec4 _color; -in vec2 _texCoord0; +in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; void main(void) { - vec4 color = texture(colorMap, _texCoord0); + vec4 color = texture(colorMap, varTexcoord); if (color.a < 0.1) { discard; } - outFragColor = color * _color; + outFragColor = color * varColor; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index e7475c30b1..4341dba187 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -91,7 +91,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; -const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = true; +const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false; EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { @@ -584,25 +584,6 @@ void ParticleEffectEntityItem::updateShapeType(ShapeType type) { } } -void ParticleEffectEntityItem::updateRadius(Particle& particle, float age) { - particle.radius = Interpolate::interpolate3Points(particle.radiusStart, particle.radiusMiddle, - particle.radiusFinish, age); -} - -void ParticleEffectEntityItem::updateColor(Particle& particle, float age) { - particle.color.red = (int)Interpolate::interpolate3Points(particle.colorStart.red, particle.colorMiddle.red, - particle.colorFinish.red, age); - particle.color.green = (int)Interpolate::interpolate3Points(particle.colorStart.green, particle.colorMiddle.green, - particle.colorFinish.green, age); - particle.color.blue = (int)Interpolate::interpolate3Points(particle.colorStart.blue, particle.colorMiddle.blue, - particle.colorFinish.blue, age); -} - -void ParticleEffectEntityItem::updateAlpha(Particle& particle, float age) { - particle.alpha = Interpolate::interpolate3Points(particle.alphaStart, particle.alphaMiddle, - particle.alphaFinish, age); -} - void ParticleEffectEntityItem::integrateParticle(Particle& particle, float deltaTime) { glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * particle.acceleration; glm::vec3 at = particle.acceleration * deltaTime; @@ -610,14 +591,6 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta particle.velocity += at; } -void ParticleEffectEntityItem::updateParticle(Particle& particle, float deltaTime) { - float age = particle.lifetime / _lifespan; // 0.0 .. 1.0 - updateRadius(particle, age); - updateColor(particle, age); - updateAlpha(particle, age); - integrateParticle(particle, deltaTime); -} - void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particlesBounds.reset(); @@ -631,7 +604,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particles.pop_front(); } else { // Otherwise update it - updateParticle(particle, deltaTime); + integrateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); } } @@ -654,7 +627,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { particle.lifetime += timeLeftInFrame; // Initialize it - updateParticle(particle, timeLeftInFrame); + integrateParticle(particle, deltaTime); _particlesBounds.addPoint(particle.position); // Advance in frame @@ -669,25 +642,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { Particle particle; - // Radius - if (_radiusSpread == 0.0f) { - particle.radiusStart = getRadiusStart(); - particle.radiusMiddle = _particleRadius; - particle.radiusFinish = getRadiusFinish(); - } else { - float spreadMultiplier; - if (_particleRadius > 0.0f) { - spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; - } else { - spreadMultiplier = 1.0f; - } - particle.radiusStart = glm::clamp(spreadMultiplier * getRadiusStart(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusMiddle = glm::clamp(spreadMultiplier * _particleRadius, - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - particle.radiusFinish = glm::clamp(spreadMultiplier * getRadiusFinish(), - MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); - } + particle.seed = randFloatInRange(0.0f, 1.0f); // Position, velocity, and acceleration if (_polarStart == 0.0f && _polarFinish == 0.0f && _emitDimensions.z == 0.0f) { @@ -745,49 +700,6 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { particle.acceleration = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } - // Color - if (_colorSpread == xColor{ 0, 0, 0 }) { - particle.colorStart = getColorStart(); - particle.colorMiddle = getXColor(); - particle.colorFinish = getColorFinish(); - } else { - xColor startColor = getColorStart(); - xColor middleColor = getXColor(); - xColor finishColor = getColorFinish(); - - float spread = randFloatInRange(-1.0f, 1.0f); - float spreadMultiplierRed = - middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; - float spreadMultiplierGreen = - middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; - float spreadMultiplierBlue = - middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; - - particle.colorStart.red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); - particle.colorStart.green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); - particle.colorStart.blue = (int)glm::clamp(spreadMultiplierBlue * (float)startColor.blue, 0.0f, 255.0f); - - particle.colorMiddle.red = (int)glm::clamp(spreadMultiplierRed * (float)middleColor.red, 0.0f, 255.0f); - particle.colorMiddle.green = (int)glm::clamp(spreadMultiplierGreen * (float)middleColor.green, 0.0f, 255.0f); - particle.colorMiddle.blue = (int)glm::clamp(spreadMultiplierBlue * (float)middleColor.blue, 0.0f, 255.0f); - - particle.colorFinish.red = (int)glm::clamp(spreadMultiplierRed * (float)finishColor.red, 0.0f, 255.0f); - particle.colorFinish.green = (int)glm::clamp(spreadMultiplierGreen * (float)finishColor.green, 0.0f, 255.0f); - particle.colorFinish.blue = (int)glm::clamp(spreadMultiplierBlue * (float)finishColor.blue, 0.0f, 255.0f); - } - - // Alpha - if (_alphaSpread == 0.0f) { - particle.alphaStart = getAlphaStart(); - particle.alphaMiddle = _alpha; - particle.alphaFinish = getAlphaFinish(); - } else { - float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; - particle.alphaStart = spreadMultiplier * getAlphaStart(); - particle.alphaMiddle = spreadMultiplier * _alpha; - particle.alphaFinish = spreadMultiplier * getAlphaFinish(); - } - return particle; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 08074f58fe..090c5e3a80 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -211,7 +211,7 @@ public: static const bool DEFAULT_ADDITIVE_BLENDING; bool getAdditiveBlending() const { return _additiveBlending; } void setAdditiveBlending(bool additiveBlending) { - _additiveBlending = true; + _additiveBlending = additiveBlending; } virtual bool supportsDetailedRayIntersection() const { return false; } @@ -224,31 +224,14 @@ protected: Particle createParticle(); void stepSimulation(float deltaTime); - void updateParticle(Particle& particle, float deltaTime); - - void updateRadius(Particle& particle, float age); - void updateColor(Particle& particle, float age); - void updateAlpha(Particle& particle, float age); void integrateParticle(Particle& particle, float deltaTime); struct Particle { + float seed { 0.0f }; float lifetime { 0.0f }; glm::vec3 position { Vectors::ZERO}; glm::vec3 velocity { Vectors::ZERO}; glm::vec3 acceleration { Vectors::ZERO}; - float radius { DEFAULT_PARTICLE_RADIUS }; - xColor color = DEFAULT_COLOR; - float alpha { DEFAULT_ALPHA }; - - float radiusStart { DEFAULT_PARTICLE_RADIUS }; - float radiusMiddle { DEFAULT_PARTICLE_RADIUS }; - float radiusFinish { DEFAULT_PARTICLE_RADIUS }; - xColor colorStart = DEFAULT_COLOR; - xColor colorMiddle = DEFAULT_COLOR; - xColor colorFinish = DEFAULT_COLOR; - float alphaStart { DEFAULT_ALPHA }; - float alphaMiddle { DEFAULT_ALPHA }; - float alphaFinish { DEFAULT_ALPHA }; }; // Particles container diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 823be727a4..917e3bed7e 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -18,7 +18,7 @@ Light::Light() : _transform() { // only if created from nothing shall we create the Buffer to store the properties Schema schema; - _schemaBuffer = gpu::BufferView(std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema)); + _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } Light::Light(const Light& light) : diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index efc02e3de4..de7a846a25 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -112,8 +112,6 @@ public: Vec4 _shadow{0.0f}; Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; - - Schema() {} }; const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } From 74278cad40f34c8f632f335ffc99397e9cd1c09c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Nov 2015 23:16:44 -0800 Subject: [PATCH 19/67] Fix particle texturing --- libraries/entities-renderer/src/textured_particle.slv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 0027d70da3..718c65a2dc 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -81,7 +81,7 @@ void main(void) { vec4 quadPos = radius * UNIT_QUAD[twoTriID]; // Pass the texcoord and the z texcoord is representing the texture icon - varTexcoord = vec2((quadPos.xy + 1.0) * 0.5); + varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); varColor = mixV(particle.color.start, particle.color.finish , age); varColor.w = particle.color.middle.w; From 2cb2ca29e6159cbb32645fd1291c404f28909ef4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Nov 2015 12:10:54 -0800 Subject: [PATCH 20/67] More particle shader work --- .../RenderableParticleEffectEntityItem.cpp | 12 +-- .../src/textured_particle.slv | 84 +++++++++++++++---- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index c7a2e4893c..ca543d0210 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -179,8 +179,8 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -glm::vec3 toGlm(const rgbColor& color) { - return glm::vec3(color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX]); +static glm::vec4 toGlm(const xColor& color, float alpha) { + return glm::vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); } void RenderableParticleEffectEntityItem::updateRenderItem() { @@ -194,10 +194,10 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { _particleUniforms.radius.finish = getRadiusFinish(); _particleUniforms.radius.spread = getRadiusSpread(); - _particleUniforms.color.start = glm::vec4(toGlm(getColorStart()), getAlphaStart()); - _particleUniforms.color.middle = glm::vec4(toGlm(getColor()), getAlpha()); - _particleUniforms.color.finish = glm::vec4(toGlm(getColorFinish()), getAlphaFinish()); - _particleUniforms.color.spread = glm::vec4(toGlm(getColorSpread()), getAlphaSpread()); + _particleUniforms.color.start = toGlm(getColorStart(), getAlphaStart()); + _particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); + _particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); + _particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); _particleUniforms.lifespan = getLifespan(); diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 718c65a2dc..7a9c91cb0f 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -37,22 +37,68 @@ uniform particleBuffer { }; in vec3 inPosition; -in vec2 inExtra; +in vec2 inColor; // This is actual Lifetime + Seed out vec4 varColor; out vec2 varTexcoord; -float mix(float start, float finish, float age) { - return start + (finish - start) * age; +float bezierInterpolate(float y1, float y2, float y3, float u) { + // https://en.wikipedia.org/wiki/Bezier_curve + return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; } -vec4 mixV(vec4 start, vec4 finish, float age) { - return vec4(mix(start.x, finish.x, age), - mix(start.y, finish.y, age), - mix(start.z, finish.z, age), - mix(start.w, finish.w, age)); +float interpolate3Floats(float y1, float y2, float y3, float u) { + if ((u <= 0.5 && y1 == y2) || (u >= 0.5 && y2 == y3)) { + // Flat line. + return y2; + } + + if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) { + // U or inverted-U shape. + // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. + if (u <= 0.5) { + return bezierInterpolate(y1, y2, y2, 2.0 * u); + } else { + return bezierInterpolate(y2, y2, y3, 2.0 * u - 1.0); + } + + } else { + // L or inverted and/or mirrored L shape. + // Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1 + // and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points. + // Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3. + float slope = y3 - y1; + float slope12 = y2 - y1; + float slope23 = y3 - y2; + if (abs(slope) > abs(2.0 * slope12)) { + slope = 2.0 * slope12; + } else if (abs(slope) > abs(2.0 * slope23)) { + slope = 2.0 * slope23; + } + + if (u <= 0.5) { + return bezierInterpolate(y1, y2 - slope / 2.0, y2, 2.0 * u); + } else { + return bezierInterpolate(y2, y2 + slope / 2.0, y3, 2.0 * u - 1.0); + } + +// float uGreaterHalf = step(0.5, u); +// float uSign = sign(uGreaterHalf - 0.5); +// vec4 y12 = mix(y1, y2, uGreaterHalf) +// vec4 y23 = mix(y2, y3, uGreaterHalf) +// +// return bezierInterpolate(y12, y2 + uSign * slope / 2.0, y23, 2.0 * u - uGreaterHalf); + } } +vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { + return vec4(interpolate3Floats(y1.x, y2.x, y3.x, u), + interpolate3Floats(y1.y, y2.y, y3.y, u), + interpolate3Floats(y1.z, y2.z, y3.z, u), + interpolate3Floats(y1.w, y2.w, y3.w, u)); +} + + void main(void) { const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( @@ -62,12 +108,12 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); - float age = inExtra.x / particle.lifespan; - float seed = inExtra.y; + float age = inColor.x / particle.lifespan; + float seed = inColor.y; // anchor point in eye space vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = mix(particle.radius.start, particle.radius.finish , age); + float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -80,13 +126,19 @@ void main(void) { int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; vec4 quadPos = radius * UNIT_QUAD[twoTriID]; - // Pass the texcoord and the z texcoord is representing the texture icon - varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); - varColor = mixV(particle.color.start, particle.color.finish , age); - varColor.w = particle.color.middle.w; - vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); <$transformEyeToClip(cam, eyePos, clipPos)$> gl_Position = clipPos; + + + // Pass the texcoord and the z texcoord is representing the texture icon + varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); + varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); + + // if (inColor.x == 0.0) { + // varColor = vec4(0, 1, 0, 1); + // } else { + // varColor = vec4(1, 0, 0, 1); + // } } From 0f316e6ae107eb174cb4ffa0a61c2f38d0f222ab Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 19 Nov 2015 15:24:36 -0800 Subject: [PATCH 21/67] Remove particles emiter bounds compute --- .../RenderableParticleEffectEntityItem.cpp | 9 ++--- .../entities/src/ParticleEffectEntityItem.cpp | 6 +-- .../entities/src/ParticleEffectEntityItem.h | 40 ++++++++++--------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index ca543d0210..e3de0f9555 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -58,7 +58,7 @@ public: void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } const AABox& getBound() const { return _bound; } - void setBound(AABox& bound) { _bound = bound; } + void setBound(const AABox& bound) { _bound = bound; } BufferPointer getParticleBuffer() { return _particleBuffer; } const BufferPointer& getParticleBuffer() const { return _particleBuffer; } @@ -242,12 +242,9 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { Transform transform; transform.setTranslation(position); transform.setRotation(rotation); + payload.setModelTransform(transform); - - AABox bounds(_particlesBounds); - bounds.rotate(rotation); - bounds.shiftBy(position); - payload.setBound(bounds); + payload.setBound(getAABox()); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 4341dba187..f598426e3c 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -592,20 +592,17 @@ void ParticleEffectEntityItem::integrateParticle(Particle& particle, float delta } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { - _particlesBounds.reset(); - // update particles between head and tail for (Particle& particle : _particles) { particle.lifetime += deltaTime; // if particle has died. - if (particle.lifetime >= _lifespan || _lifespan < EPSILON) { + if (particle.lifetime >= _lifespan) { // move head forward _particles.pop_front(); } else { // Otherwise update it integrateParticle(particle, deltaTime); - _particlesBounds.addPoint(particle.position); } } @@ -628,7 +625,6 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // Initialize it integrateParticle(particle, deltaTime); - _particlesBounds.addPoint(particle.position); // Advance in frame timeLeftInFrame -= _timeUntilNextEmit; diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 090c5e3a80..0789f5b95e 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -237,10 +237,7 @@ protected: // Particles container Particles _particles; - // bounding volume - Extents _particlesBounds; - - // the properties of this entity + // Particles properties rgbColor _color; xColor _colorStart = DEFAULT_COLOR; xColor _colorFinish = DEFAULT_COLOR; @@ -249,25 +246,30 @@ protected: float _alphaStart = DEFAULT_ALPHA_START; float _alphaFinish = DEFAULT_ALPHA_FINISH; float _alphaSpread = DEFAULT_ALPHA_SPREAD; - quint32 _maxParticles = DEFAULT_MAX_PARTICLES; - float _lifespan = DEFAULT_LIFESPAN; - float _emitRate = DEFAULT_EMIT_RATE; - float _emitSpeed = DEFAULT_EMIT_SPEED; - float _speedSpread = DEFAULT_SPEED_SPREAD; - glm::quat _emitOrientation = DEFAULT_EMIT_ORIENTATION; - glm::vec3 _emitDimensions = DEFAULT_EMIT_DIMENSIONS; - float _emitRadiusStart = DEFAULT_EMIT_RADIUS_START; - float _polarStart = DEFAULT_POLAR_START; - float _polarFinish = DEFAULT_POLAR_FINISH; - float _azimuthStart = DEFAULT_AZIMUTH_START; - float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; - glm::vec3 _emitAcceleration = DEFAULT_EMIT_ACCELERATION; - glm::vec3 _accelerationSpread = DEFAULT_ACCELERATION_SPREAD; float _particleRadius = DEFAULT_PARTICLE_RADIUS; float _radiusStart = DEFAULT_RADIUS_START; float _radiusFinish = DEFAULT_RADIUS_FINISH; float _radiusSpread = DEFAULT_RADIUS_SPREAD; - + float _lifespan = DEFAULT_LIFESPAN; + + // Emiter properties + quint32 _maxParticles = DEFAULT_MAX_PARTICLES; + + float _emitRate = DEFAULT_EMIT_RATE; + float _emitSpeed = DEFAULT_EMIT_SPEED; + float _speedSpread = DEFAULT_SPEED_SPREAD; + + glm::quat _emitOrientation = DEFAULT_EMIT_ORIENTATION; + glm::vec3 _emitDimensions = DEFAULT_EMIT_DIMENSIONS; + float _emitRadiusStart = DEFAULT_EMIT_RADIUS_START; + glm::vec3 _emitAcceleration = DEFAULT_EMIT_ACCELERATION; + glm::vec3 _accelerationSpread = DEFAULT_ACCELERATION_SPREAD; + + float _polarStart = DEFAULT_POLAR_START; + float _polarFinish = DEFAULT_POLAR_FINISH; + float _azimuthStart = DEFAULT_AZIMUTH_START; + float _azimuthFinish = DEFAULT_AZIMUTH_FINISH; + quint64 _lastSimulated { 0 }; bool _isEmitting { true }; From 9adc43755384684007be5a3d685559222ea8a093 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 20 Nov 2015 15:36:34 -0800 Subject: [PATCH 22/67] Make Particle's Payload/PendingChanges *almost* pointer free --- .../RenderableParticleEffectEntityItem.cpp | 99 ++++++++++++------- .../src/RenderableParticleEffectEntityItem.h | 34 +------ 2 files changed, 64 insertions(+), 69 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e3de0f9555..5c33d2e01e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -27,12 +27,30 @@ static const size_t VERTEX_PER_PARTICLE = 4; -class ParticlePayload { +template +struct InterpolationData { + T start; + T middle; + T finish; + T spread; +}; + +class ParticlePayloadData { public: - using Payload = render::Payload; + struct ParticleUniforms { + InterpolationData radius; + InterpolationData color; // rgba + float lifespan; + }; + + struct ParticlePrimitive { + ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} + glm::vec3 xyz; // Position + glm::vec2 uv; // Lifetime + seed + }; + + using Payload = render::Payload; using Pointer = Payload::DataPointer; - using ParticlePrimitive = RenderableParticleEffectEntityItem::ParticlePrimitive; - using ParticleUniforms = RenderableParticleEffectEntityItem::ParticleUniforms; using PipelinePointer = gpu::PipelinePointer; using FormatPointer = gpu::Stream::FormatPointer; using BufferPointer = gpu::BufferPointer; @@ -40,8 +58,9 @@ public: using Format = gpu::Stream::Format; using Buffer = gpu::Buffer; using BufferView = gpu::BufferView; - - ParticlePayload(EntityItemPointer entity) : _entity(entity) { + using ParticlePrimitives = std::vector; + + ParticlePayloadData() { ParticleUniforms uniforms; _uniformBuffer = std::make_shared(sizeof(ParticleUniforms), (const gpu::Byte*) &uniforms); @@ -92,7 +111,6 @@ public: } protected: - EntityItemPointer _entity; Transform _modelTransform; AABox _bound; PipelinePointer _pipeline; @@ -105,7 +123,7 @@ protected: namespace render { template <> - const ItemKey payloadGetKey(const ParticlePayload::Pointer& payload) { + const ItemKey payloadGetKey(const ParticlePayloadData::Pointer& payload) { if (payload->getVisibleFlag()) { return ItemKey::Builder::transparentShape(); } else { @@ -114,12 +132,12 @@ namespace render { } template <> - const Item::Bound payloadGetBound(const ParticlePayload::Pointer& payload) { + const Item::Bound payloadGetBound(const ParticlePayloadData::Pointer& payload) { return payload->getBound(); } template <> - void payloadRender(const ParticlePayload::Pointer& payload, RenderArgs* args) { + void payloadRender(const ParticlePayloadData::Pointer& payload, RenderArgs* args) { payload->render(args); } } @@ -145,9 +163,9 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, _scene = scene; _renderItemId = _scene->allocateID(); - auto particlePayload = std::make_shared(shared_from_this()); - particlePayload->setPipeline(_untexturedPipeline); - auto renderPayload = std::make_shared(particlePayload); + auto particlePayloadData = std::make_shared(); + particlePayloadData->setPipeline(_untexturedPipeline); + auto renderPayload = std::make_shared(particlePayloadData); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(shared_from_this(), statusGetters); renderPayload->addStatusGetters(statusGetters); @@ -187,25 +205,29 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; } + using ParticleUniforms = ParticlePayloadData::ParticleUniforms; + using ParticlePrimitive = ParticlePayloadData::ParticlePrimitive; + using ParticlePrimitives = ParticlePayloadData::ParticlePrimitives; + ParticleUniforms particleUniforms; // Fill in Uniforms structure - _particleUniforms.radius.start = getRadiusStart(); - _particleUniforms.radius.middle = getParticleRadius(); - _particleUniforms.radius.finish = getRadiusFinish(); - _particleUniforms.radius.spread = getRadiusSpread(); + particleUniforms.radius.start = getRadiusStart(); + particleUniforms.radius.middle = getParticleRadius(); + particleUniforms.radius.finish = getRadiusFinish(); + particleUniforms.radius.spread = getRadiusSpread(); - _particleUniforms.color.start = toGlm(getColorStart(), getAlphaStart()); - _particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); - _particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); - _particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); + particleUniforms.color.start = toGlm(getColorStart(), getAlphaStart()); + particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); + particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); + particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); - _particleUniforms.lifespan = getLifespan(); + particleUniforms.lifespan = getLifespan(); // Build particle primitives - _particlePrimitives.clear(); // clear primitives - _particlePrimitives.reserve(_particles.size()); // Reserve space + auto particlePrimitives = std::make_shared(); + particlePrimitives->reserve(_particles.size()); // Reserve space for (auto& particle : _particles) { - _particlePrimitives.emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); + particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } // No need to sort if we're doing additive blending @@ -216,35 +238,36 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { // Get direction in the entity space direction = glm::inverse(getRotation()) * direction; - std::sort(_particlePrimitives.begin(), _particlePrimitives.end(), + std::sort(particlePrimitives->begin(), particlePrimitives->end(), [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); }); } + + auto bounds = getAABox(); + auto position = getPosition(); + auto rotation = getRotation(); + Transform transform; + transform.setTranslation(position); + transform.setRotation(rotation); render::PendingChanges pendingChanges; - pendingChanges.updateItem(_renderItemId, [this](ParticlePayload& payload) { + pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { // Update particle uniforms - memcpy(&payload.editParticleUniforms(), &_particleUniforms, sizeof(ParticleUniforms)); + memcpy(&payload.editParticleUniforms(), &particleUniforms, sizeof(ParticleUniforms)); // Update particle buffer auto particleBuffer = payload.getParticleBuffer(); - size_t numBytes = sizeof(ParticlePrimitive) * _particlePrimitives.size(); + size_t numBytes = sizeof(ParticlePrimitive) * particlePrimitives->size(); particleBuffer->resize(numBytes); if (numBytes == 0) { return; } - memcpy(particleBuffer->editData(), _particlePrimitives.data(), numBytes); + memcpy(particleBuffer->editData(), particlePrimitives->data(), numBytes); - // update transform - glm::vec3 position = getPosition(); - glm::quat rotation = getRotation(); - Transform transform; - transform.setTranslation(position); - transform.setRotation(rotation); - + // Update transform and bounds payload.setModelTransform(transform); - payload.setBound(getAABox()); + payload.setBound(bounds); bool textured = _texture && _texture->isLoaded(); if (textured) { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 0e1dabb6a6..1fb9674682 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -16,7 +16,7 @@ #include "RenderableEntityItem.h" class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem { - friend class ParticlePayload; + friend class ParticlePayloadData; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); @@ -29,42 +29,14 @@ public: virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; protected: - struct ParticleUniforms { - struct { - float start; - float middle; - float finish; - float spread; - } radius; - - struct { - glm::vec4 start; - glm::vec4 middle; - glm::vec4 finish; - glm::vec4 spread; - } color; - - float lifespan; - }; - - struct ParticlePrimitive { - ParticlePrimitive(glm::vec3 xyzIn, glm::vec2 uvIn) : xyz(xyzIn), uv(uvIn) {} - glm::vec3 xyz; // Position - glm::vec2 uv; // Lifetime + seed - }; - using ParticlePrimitives = std::vector; - void createPipelines(); + render::ScenePointer _scene; render::ItemID _renderItemId; - ParticlePrimitives _particlePrimitives; - ParticleUniforms _particleUniforms; + NetworkTexturePointer _texture; gpu::PipelinePointer _untexturedPipeline; gpu::PipelinePointer _texturedPipeline; - - render::ScenePointer _scene; - NetworkTexturePointer _texture; }; From 28c8cf26f50d403672e7f60c56d1895c4f27c4b4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 15:19:41 -0800 Subject: [PATCH 23/67] Fix shader transform errors --- .../entities-renderer/src/textured_particle.slv | 2 +- libraries/gpu/src/gpu/Transform.slh | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 7a9c91cb0f..72b06e0228 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -128,7 +128,7 @@ void main(void) { vec4 clipPos; vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); - <$transformEyeToClip(cam, eyePos, clipPos)$> + <$transformEyeToClipPos(cam, eyePos, clipPos)$> gl_Position = clipPos; diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index de7cdbf7af..5d8be1137d 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -76,11 +76,10 @@ TransformCamera getTransformCamera() { <@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + //return camera._view * object._model * pos; !> { // transformModelToEyePos - vec4 _worldpos = (<$objectTransform$>._model * <$modelPos$>); + vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - // <$eyePos$> = (<$cameraTransform$>._projectionInverse * <$clipPos$>); } <@endfunc@> @@ -145,13 +144,13 @@ TransformCamera getTransformCamera() { <@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@> { // transformClipToEyeDir - <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); + <$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 0.0)); } <@endfunc@> -<@func transformEyeToClip(cameraTransform, eyePos, clipPos)@> - { // transformEyeToClip - <$clipPos$> = <$cameraTransform$>._projection * <$eyePos$>; +<@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> + { // transformEyeToClipPos + <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); } <@endfunc@> From d08a4d77dc172314e8e25c28f60e54b3c8d0eb9e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 16:11:23 -0800 Subject: [PATCH 24/67] Shader cleanup --- .../src/textured_particle.slv | 52 ++++++++----------- libraries/gpu/src/gpu/Transform.slh | 18 +++---- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 72b06e0228..9289c8f08d 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -42,6 +42,14 @@ in vec2 inColor; // This is actual Lifetime + Seed out vec4 varColor; out vec2 varTexcoord; +const int NUM_VERTICES_PER_PARTICLE = 4; +const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) +); + float bezierInterpolate(float y1, float y2, float y3, float u) { // https://en.wikipedia.org/wiki/Bezier_curve return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; @@ -100,45 +108,29 @@ vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { void main(void) { - const int NUM_VERTICES_PER_PARTICLE = 4; - const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 1.0) - ); - - float age = inColor.x / particle.lifespan; - float seed = inColor.y; - - // anchor point in eye space - vec4 anchorPoint = vec4(inPosition.xyz, 1.0); - float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); - TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToEyePos(cam, obj, anchorPoint, anchorPoint)$> // Which icon are we dealing with ? int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; - // Which quad vertex pos? int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; - vec4 quadPos = radius * UNIT_QUAD[twoTriID]; - - vec4 clipPos; - vec4 eyePos = vec4(anchorPoint.xyz + quadPos.xyz, 1.0); - <$transformEyeToClipPos(cam, eyePos, clipPos)$> - gl_Position = clipPos; - - + + // Particle properties + float age = inColor.x / particle.lifespan; + float seed = inColor.y; + // Pass the texcoord and the z texcoord is representing the texture icon varTexcoord = vec2((UNIT_QUAD[twoTriID].xy + 1.0) * 0.5); varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); - // if (inColor.x == 0.0) { - // varColor = vec4(0, 1, 0, 1); - // } else { - // varColor = vec4(1, 0, 0, 1); - // } + // anchor point in eye space + float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); + vec4 quadPos = radius * UNIT_QUAD[twoTriID]; + + vec4 anchorPoint; + <$transformModelToEyePos(cam, obj, inPosition, anchorPoint)$> + + vec4 eyePos = anchorPoint + quadPos; + <$transformEyeToClipPos(cam, eyePos, gl_Position)$> } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 5d8be1137d..9a866ca4d0 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -74,15 +74,6 @@ TransformCamera getTransformCamera() { } <@endfunc@> -<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> - - { // transformModelToEyePos - vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); - <$eyePos$> = (<$cameraTransform$>._view * _worldpos); - } -<@endfunc@> - <@func $transformInstancedModelToEyeAndClipPos(cameraTransform, objectTransform, modelPos, eyePos, clipPos)@> @@ -148,6 +139,15 @@ TransformCamera getTransformCamera() { } <@endfunc@> +<@func $transformModelToEyePos(cameraTransform, objectTransform, modelPos, eyePos)@> + + { // transformModelToEyePos + vec4 _worldpos = (<$objectTransform$>._model * vec4(<$modelPos$>.xyz, 1.0)); + <$eyePos$> = (<$cameraTransform$>._view * _worldpos); + } +<@endfunc@> + <@func transformEyeToClipPos(cameraTransform, eyePos, clipPos)@> { // transformEyeToClipPos <$clipPos$> = <$cameraTransform$>._projection * vec4(<$eyePos$>.xyz, 1.0); From 4827a96bfa3519673e8fa7d9a59e33878f966cc4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 17:53:22 -0800 Subject: [PATCH 25/67] Fix vertex shader (nested struct unsupported) --- .../RenderableParticleEffectEntityItem.cpp | 2 +- .../src/textured_particle.slv | 37 ++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 5c33d2e01e..f6e8298ec3 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -152,7 +152,7 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent ParticleEffectEntityItem(entityItemID, properties) { // lazy creation of particle system pipeline - if (!_untexturedPipeline && !_texturedPipeline) { + if (!_untexturedPipeline || !_texturedPipeline) { createPipelines(); } } diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 9289c8f08d..cd5dd75101 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,21 +14,22 @@ <$declareStandardTransform()$> +struct Radiuses { + float start; + float middle; + float finish; + float spread; +}; +struct Colors { + vec4 start; + vec4 middle; + vec4 finish; + vec4 spread; +}; + struct ParticleUniforms { - struct { - float start; - float middle; - float finish; - float spread; - } radius; - - struct { - vec4 start; - vec4 middle; - vec4 finish; - vec4 spread; - } color; - + Radiuses radius; + Colors color; float lifespan; }; @@ -44,10 +45,10 @@ out vec2 varTexcoord; const int NUM_VERTICES_PER_PARTICLE = 4; const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(1.0, -1.0, 0.0, 1.0), - vec4(-1.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 1.0) + vec4(-1.0, -1.0, 0.0, 0.0), + vec4(1.0, -1.0, 0.0, 0.0), + vec4(-1.0, 1.0, 0.0, 0.0), + vec4(1.0, 1.0, 0.0, 0.0) ); float bezierInterpolate(float y1, float y2, float y3, float u) { From 2dd494b5df2a6222a9bf03029f6ee07edfc1bfdc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 23 Nov 2015 21:00:54 -0800 Subject: [PATCH 26/67] Remove additive blending option (force it) --- .../RenderableParticleEffectEntityItem.cpp | 50 ++++--------------- .../src/textured_particle_alpha_discard.slf | 25 ---------- 2 files changed, 10 insertions(+), 65 deletions(-) delete mode 100644 libraries/entities-renderer/src/textured_particle_alpha_discard.slf diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f6e8298ec3..86a0603569 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,7 +23,6 @@ #include "untextured_particle_frag.h" #include "textured_particle_vert.h" #include "textured_particle_frag.h" -#include "textured_particle_alpha_discard_frag.h" static const size_t VERTEX_PER_PARTICLE = 4; @@ -229,20 +228,6 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { for (auto& particle : _particles) { particlePrimitives->emplace_back(particle.position, glm::vec2(particle.lifetime, particle.seed)); } - - // No need to sort if we're doing additive blending - if (!_additiveBlending) { - // sort particles back to front - // NOTE: this is view frustum might be one frame out of date. - auto direction = AbstractViewStateInterface::instance()->getCurrentViewFrustum()->getDirection(); - // Get direction in the entity space - direction = glm::inverse(getRotation()) * direction; - - std::sort(particlePrimitives->begin(), particlePrimitives->end(), - [&](const ParticlePrimitive& lhs, const ParticlePrimitive& rhs) { - return glm::dot(lhs.xyz, direction) > glm::dot(rhs.xyz, direction); - }); - } auto bounds = getAABox(); auto position = getPosition(); @@ -283,44 +268,29 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } void RenderableParticleEffectEntityItem::createPipelines() { - bool writeToDepthBuffer = false; - gpu::State::BlendArg destinationColorBlendArg; - if (_additiveBlending) { - destinationColorBlendArg = gpu::State::ONE; - } else { - destinationColorBlendArg = gpu::State::INV_SRC_ALPHA; - writeToDepthBuffer = true; - } if (!_untexturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - destinationColorBlendArg, gpu::State::FACTOR_ALPHA, - gpu::State::BLEND_OP_ADD, gpu::State::ONE); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert))); auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); _untexturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); } if (!_texturedPipeline) { auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_BACK); - + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - bool writeToDepthBuffer = !_additiveBlending; - state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - destinationColorBlendArg, gpu::State::FACTOR_ALPHA, - gpu::State::BLEND_OP_ADD, gpu::State::ONE); auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(textured_particle_vert))); - gpu::ShaderPointer fragShader; - if (_additiveBlending) { - fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); - } else { - //If we are sorting and have no additive blending, we want to discard pixels with low alpha to avoid inter-particle entity artifacts - fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_alpha_discard_frag))); - } + auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag))); + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader)); _texturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); diff --git a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf b/libraries/entities-renderer/src/textured_particle_alpha_discard.slf deleted file mode 100644 index 4d96da943b..0000000000 --- a/libraries/entities-renderer/src/textured_particle_alpha_discard.slf +++ /dev/null @@ -1,25 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// fragment shader -// -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -uniform sampler2D colorMap; - -in vec4 varColor; -in vec2 varTexcoord; - -out vec4 outFragColor; - -void main(void) { - vec4 color = texture(colorMap, varTexcoord); - if (color.a < 0.1) { - discard; - } - outFragColor = color * varColor; -} From 4ab2bfa85461d7e1fd7b298dfb08b8b10c1cbd2e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Nov 2015 08:35:28 -0800 Subject: [PATCH 27/67] clean up, minimize diff --- .../src/RenderableModelEntityItem.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e0923313c7..1221c53f24 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -210,6 +210,7 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. void RenderableModelEntityItem::render(RenderArgs* args) { @@ -249,6 +250,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->setVisibleInScene(getVisible(), scene); } + remapTextures(); } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); @@ -304,22 +306,23 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - if (EntityItem::needsToCallUpdate()) { + if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) { return true; } - // these if statements match the structure of those in RenderableModelEntityItem::update - if (hasModel() && _myRenderer) { - if (!_model || _needsModelReload) { - return true; - } - } + if (!_dimensionsInitialized && _model && _model->isActive()) { return true; } + + if (_myRenderer && (!_model || _needsModelReload)) { + return true; + } + if (_model) { - if (hasAnimation()) { + if (hasAnimation() || jointsMapped()) { return true; } + bool movingOrAnimating = isMoving() || isAnimatingSomething(); if ((movingOrAnimating || _needsInitialSimulation || @@ -339,14 +342,14 @@ void RenderableModelEntityItem::update(const quint64& now) { EntityItemProperties properties; auto extents = _model->getMeshExtents(); properties.setDimensions(extents.maximum - extents.minimum); - + qCDebug(entitiesrenderer) << "Autoresizing:" << (!getName().isEmpty() ? getName() : getModelURL()); QMetaObject::invokeMethod(DependencyManager::get().data(), "editEntity", Qt::QueuedConnection, Q_ARG(QUuid, getEntityItemID()), Q_ARG(EntityItemProperties, properties)); } - + if (_myRenderer && (!_model || _needsModelReload)) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); From 4b5fec4b008731a905e87ee669d0827a2af4d5f2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Nov 2015 08:36:41 -0800 Subject: [PATCH 28/67] clean up, minimize diff --- libraries/entities-renderer/src/RenderableModelEntityItem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6c5bfc4423..c4e36c240a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -47,6 +47,7 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, From 8ae05d8490f3c00c3b22089e63ade4b0a2213efe Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 16:40:41 -0800 Subject: [PATCH 29/67] Plugins target frame rate and period. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 3 ++- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 6 ++++++ .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 5 +++++ libraries/plugins/src/plugins/DisplayPlugin.h | 2 ++ plugins/oculus/src/OculusDisplayPlugin.h | 5 +++++ plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 5 +++++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9366ec4403..b0dffbb7bc 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -139,7 +139,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (FRAMERATE_30 == actionText) { _framerateTarget = 30; } - } + } + _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); qDebug() << newInterval; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f4655ab79f..f6052f82ca 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -9,6 +9,8 @@ #include "WindowOpenGLDisplayPlugin.h" +#define TARGET_FRAMERATE_Basic2DWindowOpenGL 60.0f + class QScreen; class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { Q_OBJECT @@ -16,6 +18,9 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual const QString & getName() const override; + virtual float getTargetFrameRate() { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } + virtual float getTargetFramePeriod() { return _inverseFrameRate; } + virtual void activate() override; virtual void deactivate() override; @@ -33,4 +38,5 @@ private: QScreen* getFullscreenTarget(); uint32_t _framerateTarget{ 0 }; int _fullscreenTarget{ -1 }; + float _inverseFrameRate{ 1.0f }; //seconds }; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 15d37d9de8..6116cd2283 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -14,12 +14,17 @@ #include "../WindowOpenGLDisplayPlugin.h" +#define TARGET_RATE_OpenVr 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. + class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual bool isSupported() const override; virtual const QString & getName() const override; virtual bool isHmd() const override { return true; } + virtual float getTargetFrameRate() { return TARGET_RATE_OpenVr; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OpenVr; } + virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 5b00391f09..ea6060010e 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -57,6 +57,8 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } + virtual float getTargetFrameRate() { return 0.0f; } + virtual float getTargetFramePeriod() { return 0.0f; } // Rendering support diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index c1224ecf3a..62cdf35fc7 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -12,12 +12,17 @@ struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; +#define TARGET_RATE_Oculus 75.0f; + class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: virtual void activate() override; virtual void deactivate() override; virtual const QString & getName() const override; + virtual float getTargetFrameRate() { return TARGET_RATE_Oculus; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_Oculus; } + protected: virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; virtual void customizeContext() override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 6e3f864aee..ca45e201f4 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -13,6 +13,8 @@ #include +#define TARGET_RATE_OculusLegacy 75.0f; + class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin { public: OculusLegacyDisplayPlugin(); @@ -25,6 +27,9 @@ public: virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual int getHmdScreen() const override; + virtual float getTargetFrameRate() { return TARGET_RATE_OculusLegacy; } + virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OculusLegacy; } + // Stereo specific methods virtual bool isHmd() const override { return true; } virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; From 53bfcd17e2537c7930faa3221ab1c74de5a2a482 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 16:41:16 -0800 Subject: [PATCH 30/67] Use plugins data for Application frame rate/period. --- interface/src/Application.cpp | 2 ++ interface/src/Application.h | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ef10ad4464..94aa3949cc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3246,6 +3246,8 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } +float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } +float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 730158c689..adef152ac5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -159,10 +159,8 @@ public: bool isForeground() const { return _isForeground; } float getFps() const { return _fps; } - float const HMD_TARGET_FRAME_RATE = 75.0f; - float const DESKTOP_TARGET_FRAME_RATE = 60.0f; - float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; } - float getTargetFramePeriod() { return isHMDMode() ? 1.0f / HMD_TARGET_FRAME_RATE : 1.0f / DESKTOP_TARGET_FRAME_RATE; } // same as 1/getTargetFrameRate, but w/compile-time division + float getTargetFrameRate(); // frames/second + float getTargetFramePeriod(); // seconds float getLastInstanteousFps() const { return _lastInstantaneousFps; } float getLastPaintWait() const { return _lastPaintWait; }; float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; } From ed86a880832d988e05b33b2c8e2b7739e309274b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 2 Dec 2015 21:48:06 -0800 Subject: [PATCH 31/67] Make various forms of throttling more consistent and give it a chance of actually reaching target. --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index b0dffbb7bc..ea8ffe1e2f 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -90,12 +90,8 @@ void Basic2DWindowOpenGLDisplayPlugin::display(GLuint sceneTexture, const glm::u int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { - static const int THROTTLED_PAINT_TIMER_DELAY_MS = MSECS_PER_SECOND / 15; static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; - if (_isThrottled) { - result = THROTTLED_PAINT_TIMER_DELAY_MS; - } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; } @@ -139,12 +135,18 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (FRAMERATE_30 == actionText) { _framerateTarget = 30; } + } else if (_isThrottled) { + _framerateTarget = 15; } _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); + if (_framerateTarget) { // For any target other than vsync, we have little hope of achieving it with timer alone: + const int ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER = 3; // ideally a windowed average of qApp->getLastPaintWait and then some, but not worth the complexity + newInterval -= ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER; // Otherwise, any controller expecting us to hit "target" will always be disappointed. + } qDebug() << newInterval; - _timer.start(getDesiredInterval()); + _timer.start(newInterval); } // FIXME target the screen the window is currently on From a989b926b054fce73e694221646c2c8c385a5db0 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 11:28:26 -0800 Subject: [PATCH 32/67] isVSynchronized, and proper override declarations. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 9 +++++---- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 5 +++-- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 4 ++-- libraries/plugins/src/plugins/DisplayPlugin.h | 1 + plugins/oculus/src/OculusDisplayPlugin.h | 4 ++-- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 4 ++-- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index ea8ffe1e2f..c0af5609ee 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -113,6 +113,9 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { return shouldThrottle; } +bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { + return (_framerateTarget == 0) && (!_vsyncAction || _vsyncAction->isChecked()); +} void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { QAction* checkedFramerate{ nullptr }; @@ -141,10 +144,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); - if (_framerateTarget) { // For any target other than vsync, we have little hope of achieving it with timer alone: - const int ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER = 3; // ideally a windowed average of qApp->getLastPaintWait and then some, but not worth the complexity - newInterval -= ALLOWANCE_FOR_DISPLAY_FINISHFRAME_AND_TIMER; // Otherwise, any controller expecting us to hit "target" will always be disappointed. - } + // Note: when not isVSynchronized, we are often not likely to hit target with a newInterval timer. + // We could try subtracting an allowance for qApp->getLastPaintWait() and qt timer machinery, but that starts getting complicated. qDebug() << newInterval; _timer.start(newInterval); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f6052f82ca..45d2545a94 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -18,8 +18,8 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual const QString & getName() const override; - virtual float getTargetFrameRate() { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } - virtual float getTargetFramePeriod() { return _inverseFrameRate; } + virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } + virtual float getTargetFramePeriod() override { return _inverseFrameRate; } virtual void activate() override; virtual void deactivate() override; @@ -27,6 +27,7 @@ public: virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override; virtual bool isThrottled() const override; + virtual bool isVSynchronized() const override; protected: int getDesiredInterval() const; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 6116cd2283..390ab4b539 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -22,8 +22,8 @@ public: virtual const QString & getName() const override; virtual bool isHmd() const override { return true; } - virtual float getTargetFrameRate() { return TARGET_RATE_OpenVr; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OpenVr; } + virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OpenVr; } virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index ea6060010e..729b62f124 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -57,6 +57,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } + virtual bool isVSynchronized() const { return true; } // false when throttled or run by non vsync timer virtual float getTargetFrameRate() { return 0.0f; } virtual float getTargetFramePeriod() { return 0.0f; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 62cdf35fc7..febfd5b08e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -20,8 +20,8 @@ public: virtual void deactivate() override; virtual const QString & getName() const override; - virtual float getTargetFrameRate() { return TARGET_RATE_Oculus; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_Oculus; } + virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_Oculus; } protected: virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index ca45e201f4..d0840d3a72 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -27,8 +27,8 @@ public: virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual int getHmdScreen() const override; - virtual float getTargetFrameRate() { return TARGET_RATE_OculusLegacy; } - virtual float getTargetFramePeriod() { return 1.0f / TARGET_RATE_OculusLegacy; } + virtual float getTargetFrameRate() override { return TARGET_RATE_OculusLegacy; } + virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OculusLegacy; } // Stereo specific methods virtual bool isHmd() const override { return true; } From 375211e13b454d64fc7b2d8a33c915119cc5b043 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 11:29:13 -0800 Subject: [PATCH 33/67] Use isVSynchronized in controller. --- interface/src/Application.cpp | 1 + interface/src/Application.h | 1 + interface/src/avatar/AvatarManager.cpp | 22 +++++++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 94aa3949cc..921c126ce6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3248,6 +3248,7 @@ bool Application::isHMDMode() const { } float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } +bool Application::isVSynchronized() const { return getActiveDisplayPlugin()->isVSynchronized(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index adef152ac5..5c952f462e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -124,6 +124,7 @@ public: PickRay computePickRay() const; bool isThrottleRendering() const; + bool isVSynchronized() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index e094f2e263..0ee07d15ec 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -146,13 +146,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { PerformanceTimer perfTimer("otherAvatars"); - _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. - // The PID controller raises the controlled value when the measured value goes up. - // The measured value is frame rate. When the controlled value (1 / render cutoff distance) - // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate - // goes up. - const float deduced = qApp->getLastDeducedNonVSyncFps(); - const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); + float distance; + if (qApp->isVSynchronized()) { + _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. + // The PID controller raises the controlled value when the measured value goes up. + // The measured value is frame rate. When the controlled value (1 / render cutoff distance) + // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate + // goes up. + const float deduced = qApp->getLastDeducedNonVSyncFps(); + distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); + } else { + // We could keep the controller running when not vsync'd, if getLastDeducedNonVSyncFps is still meaningful. + // But the basic 2d controller doesn't try to adjust the timer for qt load or getLastPaintWait, so running the + // Here we choose to just use the maximum render cutoff distance if: throttled, running without vsync, or 30-60 "fixed" targets. + distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); + } _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); int renderableCount = 0; From 30bbc82c245ddd357bb3f54abd9046f0c9f63a05 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 3 Dec 2015 13:00:07 -0800 Subject: [PATCH 34/67] Restore throttling interval code. --- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index c0af5609ee..8633628fef 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -88,10 +88,15 @@ void Basic2DWindowOpenGLDisplayPlugin::display(GLuint sceneTexture, const glm::u WindowOpenGLDisplayPlugin::display(sceneTexture, sceneSize); } - +#define THROTTLED_FRAMERATE 15 int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; + // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. + // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. + if (_isThrottled) { + result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; + } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; } @@ -139,7 +144,7 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _framerateTarget = 30; } } else if (_isThrottled) { - _framerateTarget = 15; + _framerateTarget = (float) THROTTLED_FRAMERATE; } _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated From f5b25791f466402549cdaaa066d1519854ad0532 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 3 Dec 2015 13:39:41 -0800 Subject: [PATCH 35/67] When throttling starts, we won't have noticed, so change test. --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 8633628fef..b3719265ea 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -119,7 +119,7 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { } bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { - return (_framerateTarget == 0) && (!_vsyncAction || _vsyncAction->isChecked()); + return (_framerateTarget == 0) && !_isThrottled; } void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { From 9c5486fb4b407e80a3876422ed04f3c6901f30ad Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Nov 2015 12:58:35 -0800 Subject: [PATCH 36/67] More particle work --- .../RenderableParticleEffectEntityItem.cpp | 24 +++++------ .../src/textured_particle.slv | 40 +------------------ 2 files changed, 12 insertions(+), 52 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 86a0603569..a03d2a9b14 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -26,16 +26,15 @@ static const size_t VERTEX_PER_PARTICLE = 4; -template -struct InterpolationData { - T start; - T middle; - T finish; - T spread; -}; - class ParticlePayloadData { public: + template + struct InterpolationData { + T start; + T middle; + T finish; + T spread; + }; struct ParticleUniforms { InterpolationData radius; InterpolationData color; // rgba @@ -207,19 +206,17 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { using ParticleUniforms = ParticlePayloadData::ParticleUniforms; using ParticlePrimitive = ParticlePayloadData::ParticlePrimitive; using ParticlePrimitives = ParticlePayloadData::ParticlePrimitives; - - ParticleUniforms particleUniforms; + // Fill in Uniforms structure + ParticleUniforms particleUniforms; particleUniforms.radius.start = getRadiusStart(); particleUniforms.radius.middle = getParticleRadius(); particleUniforms.radius.finish = getRadiusFinish(); particleUniforms.radius.spread = getRadiusSpread(); - particleUniforms.color.start = toGlm(getColorStart(), getAlphaStart()); particleUniforms.color.middle = toGlm(getXColor(), getAlpha()); particleUniforms.color.finish = toGlm(getColorFinish(), getAlphaFinish()); particleUniforms.color.spread = toGlm(getColorSpread(), getAlphaSpread()); - particleUniforms.lifespan = getLifespan(); // Build particle primitives @@ -254,8 +251,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { payload.setModelTransform(transform); payload.setBound(bounds); - bool textured = _texture && _texture->isLoaded(); - if (textured) { + if (_texture && _texture->isLoaded()) { payload.setTexture(_texture->getGPUTexture()); payload.setPipeline(_texturedPipeline); } else { diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index cd5dd75101..0d915a3468 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -61,43 +61,7 @@ float interpolate3Floats(float y1, float y2, float y3, float u) { // Flat line. return y2; } - - if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) { - // U or inverted-U shape. - // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. - if (u <= 0.5) { - return bezierInterpolate(y1, y2, y2, 2.0 * u); - } else { - return bezierInterpolate(y2, y2, y3, 2.0 * u - 1.0); - } - - } else { - // L or inverted and/or mirrored L shape. - // Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1 - // and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points. - // Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3. - float slope = y3 - y1; - float slope12 = y2 - y1; - float slope23 = y3 - y2; - if (abs(slope) > abs(2.0 * slope12)) { - slope = 2.0 * slope12; - } else if (abs(slope) > abs(2.0 * slope23)) { - slope = 2.0 * slope23; - } - - if (u <= 0.5) { - return bezierInterpolate(y1, y2 - slope / 2.0, y2, 2.0 * u); - } else { - return bezierInterpolate(y2, y2 + slope / 2.0, y3, 2.0 * u - 1.0); - } - -// float uGreaterHalf = step(0.5, u); -// float uSign = sign(uGreaterHalf - 0.5); -// vec4 y12 = mix(y1, y2, uGreaterHalf) -// vec4 y23 = mix(y2, y3, uGreaterHalf) -// -// return bezierInterpolate(y12, y2 + uSign * slope / 2.0, y23, 2.0 * u - uGreaterHalf); - } + return bezierInterpolate(y1, y2, y3, u); } vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { @@ -116,7 +80,7 @@ void main(void) { int particleID = gl_VertexID / NUM_VERTICES_PER_PARTICLE; // Which quad vertex pos? int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; - + // Particle properties float age = inColor.x / particle.lifespan; float seed = inColor.y; From bd23a4137ef395231eb7e2776dd63179d15d0897 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 25 Nov 2015 11:11:06 -0800 Subject: [PATCH 37/67] Move toGlm to GLMHelpers --- .../src/RenderableParticleEffectEntityItem.cpp | 7 ++----- libraries/shared/src/GLMHelpers.cpp | 4 ++++ libraries/shared/src/GLMHelpers.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a03d2a9b14..cabf616881 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -24,10 +24,11 @@ #include "textured_particle_vert.h" #include "textured_particle_frag.h" -static const size_t VERTEX_PER_PARTICLE = 4; class ParticlePayloadData { public: + static const size_t VERTEX_PER_PARTICLE = 4; + template struct InterpolationData { T start; @@ -195,10 +196,6 @@ void RenderableParticleEffectEntityItem::update(const quint64& now) { updateRenderItem(); } -static glm::vec4 toGlm(const xColor& color, float alpha) { - return glm::vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); -} - void RenderableParticleEffectEntityItem::updateRenderItem() { if (!_scene) { return; diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index fa010a85bd..d89457d761 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -345,6 +345,10 @@ QSize fromGlm(const glm::ivec2 & v) { return QSize(v.x, v.y); } +vec4 toGlm(const xColor& color, float alpha) { + return vec4((float)color.red / 255.0f, (float)color.green / 255.0f, (float)color.blue / 255.0f, alpha); +} + QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size) { QRectF result(pos.x, pos.y, size.x, size.y); return result; diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 8d3410aaf2..d518ab8ae4 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -154,6 +154,7 @@ vec2 toGlm(const QPointF& pt); vec3 toGlm(const xColor& color); vec4 toGlm(const QColor& color); ivec4 toGlm(const QRect& rect); +vec4 toGlm(const xColor& color, float alpha); QSize fromGlm(const glm::ivec2 & v); QMatrix4x4 fromGlm(const glm::mat4 & m); From 591025850b91fd1c209b0bac636168c45ae9a508 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 25 Nov 2015 11:38:59 -0800 Subject: [PATCH 38/67] Fix particle shader --- .../src/textured_particle.slv | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 0d915a3468..8572350de6 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -56,19 +56,11 @@ float bezierInterpolate(float y1, float y2, float y3, float u) { return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; } -float interpolate3Floats(float y1, float y2, float y3, float u) { - if ((u <= 0.5 && y1 == y2) || (u >= 0.5 && y2 == y3)) { - // Flat line. - return y2; - } - return bezierInterpolate(y1, y2, y3, u); -} - vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { - return vec4(interpolate3Floats(y1.x, y2.x, y3.x, u), - interpolate3Floats(y1.y, y2.y, y3.y, u), - interpolate3Floats(y1.z, y2.z, y3.z, u), - interpolate3Floats(y1.w, y2.w, y3.w, u)); + return vec4(bezierInterpolate(y1.x, y2.x, y3.x, u), + bezierInterpolate(y1.y, y2.y, y3.y, u), + bezierInterpolate(y1.z, y2.z, y3.z, u), + bezierInterpolate(y1.w, y2.w, y3.w, u)); } @@ -90,7 +82,7 @@ void main(void) { varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); // anchor point in eye space - float radius = interpolate3Floats(particle.radius.start, particle.radius.middle, particle.radius.finish , age); + float radius = bezierInterpolate(particle.radius.start, particle.radius.middle, particle.radius.finish , age); vec4 quadPos = radius * UNIT_QUAD[twoTriID]; vec4 anchorPoint; From 180ffcc456132efa5a0dab26f1a8206b95549484 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 1 Dec 2015 15:42:29 -0800 Subject: [PATCH 39/67] Typo (English is weird) --- .../entities-renderer/src/textured_particle.slv | 4 ++-- .../entities/src/ParticleEffectEntityItem.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 8572350de6..1e9275ec72 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -14,7 +14,7 @@ <$declareStandardTransform()$> -struct Radiuses { +struct Radii { float start; float middle; float finish; @@ -28,7 +28,7 @@ struct Colors { }; struct ParticleUniforms { - Radiuses radius; + Radii radius; Colors color; float lifespan; }; diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f598426e3c..27de4766f4 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -678,16 +678,16 @@ ParticleEffectEntityItem::Particle ParticleEffectEntityItem::createParticle() { radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); } - glm::vec3 radiuses = radiusScale * 0.5f * _emitDimensions; - float x = radiuses.x * glm::cos(elevation) * glm::cos(azimuth); - float y = radiuses.y * glm::cos(elevation) * glm::sin(azimuth); - float z = radiuses.z * glm::sin(elevation); + glm::vec3 radii = radiusScale * 0.5f * _emitDimensions; + float x = radii.x * glm::cos(elevation) * glm::cos(azimuth); + float y = radii.y * glm::cos(elevation) * glm::sin(azimuth); + float z = radii.z * glm::sin(elevation); glm::vec3 emitPosition = glm::vec3(x, y, z); emitDirection = glm::normalize(glm::vec3( - radiuses.x > 0.0f ? x / (radiuses.x * radiuses.x) : 0.0f, - radiuses.y > 0.0f ? y / (radiuses.y * radiuses.y) : 0.0f, - radiuses.z > 0.0f ? z / (radiuses.z * radiuses.z) : 0.0f - )); + radii.x > 0.0f ? x / (radii.x * radii.x) : 0.0f, + radii.y > 0.0f ? y / (radii.y * radii.y) : 0.0f, + radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f + )); particle.position = _emitOrientation * emitPosition; } From c8ab95bb53f12b7f8e03f8b2e81e97ee7ebc8f48 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 1 Dec 2015 16:25:08 -0800 Subject: [PATCH 40/67] Spacing --- libraries/entities/src/ParticleEffectEntityItem.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 0789f5b95e..ca6bcf8959 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -229,9 +229,9 @@ protected: struct Particle { float seed { 0.0f }; float lifetime { 0.0f }; - glm::vec3 position { Vectors::ZERO}; - glm::vec3 velocity { Vectors::ZERO}; - glm::vec3 acceleration { Vectors::ZERO}; + glm::vec3 position { Vectors::ZERO }; + glm::vec3 velocity { Vectors::ZERO }; + glm::vec3 acceleration { Vectors::ZERO }; }; // Particles container From 4dbfd3bfd936702e58ac90cc102d7df8bd4fe5a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Dec 2015 10:49:10 -0800 Subject: [PATCH 41/67] Fix concurrency issues for bools in ScriptEngine Several member variables were unsafely being accessed from multiple threads. Making these variables std::atomic makes this safe. --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..daadb0e394 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -183,7 +183,7 @@ void ScriptEngine::runInThread() { QSet ScriptEngine::_allKnownScriptEngines; QMutex ScriptEngine::_allScriptsMutex; -bool ScriptEngine::_stoppingAllScripts = false; +std::atomic ScriptEngine::_stoppingAllScripts = false; void ScriptEngine::stopAllScripts(QObject* application) { _allScriptsMutex.lock(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 90b99d46fd..82b91aed2e 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -166,8 +166,8 @@ signals: protected: QString _scriptContents; QString _parentURL; - bool _isFinished { false }; - bool _isRunning { false }; + std::atomic _isFinished { false }; + std::atomic _isRunning { false }; int _evaluatesPending { 0 }; bool _isInitialized { false }; QHash _timerFunctionMap; @@ -206,7 +206,7 @@ protected: static QSet _allKnownScriptEngines; static QMutex _allScriptsMutex; - static bool _stoppingAllScripts; + static std::atomic _stoppingAllScripts; }; #endif // hifi_ScriptEngine_h \ No newline at end of file From 1d65cbce882525243d5be7f54e70484058493e93 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 8 Dec 2015 18:08:57 -0800 Subject: [PATCH 42/67] Remove unneeded getTargetFramePeriod and isVSynchronized. --- interface/src/Application.cpp | 2 -- interface/src/Application.h | 1 - interface/src/avatar/AvatarManager.cpp | 6 ++---- .../display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 7 ------- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 3 --- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 1 - libraries/plugins/src/plugins/DisplayPlugin.h | 2 -- plugins/oculus/src/OculusDisplayPlugin.h | 1 - plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 1 - 9 files changed, 2 insertions(+), 22 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 24fd1d1ac9..e01899726a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3235,8 +3235,6 @@ bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } float Application::getTargetFrameRate() { return getActiveDisplayPlugin()->getTargetFrameRate(); } -float Application::getTargetFramePeriod() { return getActiveDisplayPlugin()->getTargetFramePeriod(); } -bool Application::isVSynchronized() const { return getActiveDisplayPlugin()->isVSynchronized(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0678477aaa..122b6ea3ae 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -124,7 +124,6 @@ public: PickRay computePickRay() const; bool isThrottleRendering() const; - bool isVSynchronized() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index dff6893bef..7c1a52f1b3 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -146,7 +146,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { PerformanceTimer perfTimer("otherAvatars"); float distance; - if (qApp->isVSynchronized()) { + if (!qApp->isThrottleRendering()) { _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. // The PID controller raises the controlled value when the measured value goes up. // The measured value is frame rate. When the controlled value (1 / render cutoff distance) @@ -155,9 +155,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float deduced = qApp->getLastUnsynchronizedFps(); distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); } else { - // We could keep the controller running when not vsync'd, if getLastDeducedNonVSyncFps is still meaningful. - // But the basic 2d controller doesn't try to adjust the timer for qt load or getLastPaintWait, so running the - // Here we choose to just use the maximum render cutoff distance if: throttled, running without vsync, or 30-60 "fixed" targets. + // Here we choose to just use the maximum render cutoff distance if throttled. distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); } _renderDistanceAverage.updateAverage(distance); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 97e12643a9..9139a9dcc9 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -113,10 +113,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { return shouldThrottle; } -bool Basic2DWindowOpenGLDisplayPlugin::isVSynchronized() const { - return (_framerateTarget == 0) && !_isThrottled; -} - void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { QAction* checkedFramerate{ nullptr }; foreach(auto action, _framerateActions) { @@ -141,11 +137,8 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } else if (_isThrottled) { _framerateTarget = (float) THROTTLED_FRAMERATE; } - _inverseFrameRate = _framerateTarget ? 1.0f / (float) _framerateTarget : 1.0f / TARGET_FRAMERATE_Basic2DWindowOpenGL; // not truncated int newInterval = getDesiredInterval(); - // Note: when not isVSynchronized, we are often not likely to hit target with a newInterval timer. - // We could try subtracting an allowance for qApp->getLastPaintWait() and qt timer machinery, but that starts getting complicated. qDebug() << newInterval; _timer.start(newInterval); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index bd5359e141..59c0e4e759 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -21,7 +21,6 @@ public: virtual const QString & getName() const override; virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } - virtual float getTargetFramePeriod() override { return _inverseFrameRate; } virtual void activate() override; @@ -30,7 +29,6 @@ public: virtual void internalPresent() override; virtual bool isThrottled() const override; - virtual bool isVSynchronized() const override; protected: int getDesiredInterval() const; @@ -44,6 +42,5 @@ private: QAction* _vsyncAction { nullptr }; uint32_t _framerateTarget { 0 }; int _fullscreenTarget{ -1 }; - float _inverseFrameRate{ 1.0f }; //seconds bool _wantVsync { true }; }; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index feb5c0716c..2b51c53d58 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -23,7 +23,6 @@ public: virtual bool isHmd() const override { return true; } virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OpenVr; } virtual void activate() override; virtual void deactivate() override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 5352cf9a87..7f3b38e4a2 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -58,9 +58,7 @@ public: /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } - virtual bool isVSynchronized() const { return true; } // false when throttled or run by non vsync timer virtual float getTargetFrameRate() { return 0.0f; } - virtual float getTargetFramePeriod() { return 0.0f; } // Rendering support diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 47b41b08b6..071dca0258 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -21,7 +21,6 @@ public: virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final; virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_Oculus; } protected: virtual void internalPresent() override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 67efcc6575..7fe721fc45 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -28,7 +28,6 @@ public: virtual int getHmdScreen() const override; virtual float getTargetFrameRate() override { return TARGET_RATE_OculusLegacy; } - virtual float getTargetFramePeriod() override { return 1.0f / TARGET_RATE_OculusLegacy; } // Stereo specific methods virtual bool isHmd() const override { return true; } From 4d60c7bbc035afe9dbaef3bc69e7140bb2893ec7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 9 Dec 2015 10:42:32 -0800 Subject: [PATCH 43/67] update model location with SpatiallyNestable's locationChanged call --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++++++ .../entities-renderer/src/RenderableModelEntityItem.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5b4704cabb..81c0554111 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -584,3 +584,11 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } return glm::vec3(0.0f); } + +void RenderableModelEntityItem::locationChanged() { + EntityItem::locationChanged(); + if (_model && _model->isActive()) { + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + } +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 5c05dc5b44..3f3fe11633 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,6 +71,8 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + void locationChanged(); + private: void remapTextures(); From 4bfce768ca68951d44d2f973d1bd408f46b5133c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:48:33 -0800 Subject: [PATCH 44/67] Add locks around read/writes of _scriptEnginesHash --- interface/src/Application.cpp | 113 +++++++++++++++++++++++----------- interface/src/Application.h | 1 + 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b29cdc892..8655d6b77e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4259,10 +4259,13 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser QUrl scriptUrl(scriptFilename); const QString& scriptURLString = scriptUrl.toString(); - if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor - && !_scriptEnginesHash[scriptURLString]->isFinished()) { + { + QReadLocker lock(&_scriptEnginesHashLock); + if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor + && !_scriptEnginesHash[scriptURLString]->isFinished()) { - return _scriptEnginesHash[scriptURLString]; + return _scriptEnginesHash[scriptURLString]; + } } ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); @@ -4302,7 +4305,11 @@ void Application::reloadScript(const QString& scriptName, bool isUserLoaded) { void Application::handleScriptEngineLoaded(const QString& scriptFilename) { ScriptEngine* scriptEngine = qobject_cast(sender()); - _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); + { + QWriteLocker lock(&_scriptEnginesHashLock); + _scriptEnginesHash.insertMulti(scriptFilename, scriptEngine); + } + _runningScriptsWidget->setRunningScripts(getRunningScripts()); UserActivityLogger::getInstance().loadedScript(scriptFilename); @@ -4317,55 +4324,86 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { QMessageBox::warning(getWindow(), "Error Loading Script", scriptFilename + " failed to load."); } -void Application::scriptFinished(const QString& scriptName) { - const QString& scriptURLString = QUrl(scriptName).toString(); - QHash::iterator it = _scriptEnginesHash.find(scriptURLString); - if (it != _scriptEnginesHash.end()) { - _scriptEnginesHash.erase(it); - _runningScriptsWidget->scriptStopped(scriptName); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - } +QStringList Application::getRunningScripts() { + QReadLocker lock(&_scriptEnginesHashLock); + return _scriptEnginesHash.keys(); } -void Application::stopAllScripts(bool restart) { - if (restart) { - // Delete all running scripts from cache so that they are re-downloaded when they are restarted - auto scriptCache = DependencyManager::get(); - for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); - it != _scriptEnginesHash.constEnd(); it++) { - if (!it.value()->isFinished()) { - scriptCache->deleteScript(it.key()); +ScriptEngine* Application::getScriptEngine(const QString& scriptHash) { + QReadLocker lock(&_scriptEnginesHashLock); + return _scriptEnginesHash.value(scriptHash, nullptr); +} + +void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine) { + bool removed = false; + { + QWriteLocker lock(&_scriptEnginesHashLock); + const QString& scriptURLString = QUrl(scriptName).toString(); + for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) { + if (it.value() == engine) { + _scriptEnginesHash.erase(it); + removed = true; + break; } } } + postLambdaEvent([this, scriptName]() { + _runningScriptsWidget->scriptStopped(scriptName); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + }); +} - // Stop and possibly restart all currently running scripts - for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); +void Application::stopAllScripts(bool restart) { + { + QReadLocker lock(&_scriptEnginesHashLock); + + if (restart) { + // Delete all running scripts from cache so that they are re-downloaded when they are restarted + auto scriptCache = DependencyManager::get(); + for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { - if (it.value()->isFinished()) { - continue; + if (!it.value()->isFinished()) { + scriptCache->deleteScript(it.key()); + } + } } - if (restart && it.value()->isUserLoaded()) { - connect(it.value(), SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&))); + + // Stop and possibly restart all currently running scripts + for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); + it != _scriptEnginesHash.constEnd(); it++) { + if (it.value()->isFinished()) { + continue; + } + if (restart && it.value()->isUserLoaded()) { + connect(it.value(), &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) { + reloadScript(scriptName); + }); + } + QMetaObject::invokeMethod(it.value(), "stop"); + //it.value()->stop(); + qCDebug(interfaceapp) << "stopping script..." << it.key(); } - it.value()->stop(); - qCDebug(interfaceapp) << "stopping script..." << it.key(); } getMyAvatar()->clearScriptableSettings(); } bool Application::stopScript(const QString& scriptHash, bool restart) { bool stoppedScript = false; - if (_scriptEnginesHash.contains(scriptHash)) { - ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash]; - if (restart) { - auto scriptCache = DependencyManager::get(); - scriptCache->deleteScript(QUrl(scriptHash)); - connect(scriptEngine, SIGNAL(finished(const QString&)), SLOT(reloadScript(const QString&))); + { + QReadLocker lock(&_scriptEnginesHashLock); + if (_scriptEnginesHash.contains(scriptHash)) { + ScriptEngine* scriptEngine = _scriptEnginesHash[scriptHash]; + if (restart) { + auto scriptCache = DependencyManager::get(); + scriptCache->deleteScript(QUrl(scriptHash)); + connect(scriptEngine, &ScriptEngine::finished, this, [this](QString scriptName, ScriptEngine* engine) { + reloadScript(scriptName); + }); + } + scriptEngine->stop(); + stoppedScript = true; + qCDebug(interfaceapp) << "stopping script..." << scriptHash; } - scriptEngine->stop(); - stoppedScript = true; - qCDebug(interfaceapp) << "stopping script..." << scriptHash; } if (_scriptEnginesHash.empty()) { getMyAvatar()->clearScriptableSettings(); @@ -4384,6 +4422,7 @@ void Application::reloadOneScript(const QString& scriptName) { } void Application::loadDefaultScripts() { + QReadLocker lock(&_scriptEnginesHashLock); if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) { loadScript(DEFAULT_SCRIPTS_JS_URL); } diff --git a/interface/src/Application.h b/interface/src/Application.h index ce33f051ef..2f4e33e52d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -505,6 +505,7 @@ private: TouchEvent _lastTouchEvent; + QReadWriteLock _scriptEnginesHashLock; RunningScriptsWidget* _runningScriptsWidget; QHash _scriptEnginesHash; bool _runningScriptsWidgetWasVisible; From fc6a78d9ef74483a861aea122fee0885c674628f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:49:05 -0800 Subject: [PATCH 45/67] Update scriptFinished signal to be a DirectConnection --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8655d6b77e..740b0062f0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4013,7 +4013,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Clipboard", clipboardScriptable); connect(scriptEngine, SIGNAL(finished(const QString&)), clipboardScriptable, SLOT(deleteLater())); - connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(scriptFinished(const QString&))); + connect(scriptEngine, &ScriptEngine::finished, this, &Application::scriptFinished, Qt::DirectConnection); connect(scriptEngine, SIGNAL(loadScript(const QString&, bool)), this, SLOT(loadScript(const QString&, bool))); connect(scriptEngine, SIGNAL(reloadScript(const QString&, bool)), this, SLOT(reloadScript(const QString&, bool))); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2f4e33e52d..0d5b920c10 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -202,8 +202,8 @@ public: NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } - QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } - ScriptEngine* getScriptEngine(const QString& scriptHash) { return _scriptEnginesHash.value(scriptHash, NULL); } + QStringList getRunningScripts(); + ScriptEngine* getScriptEngine(const QString& scriptHash); float getRenderResolutionScale() const; @@ -336,7 +336,7 @@ private slots: void loadSettings(); void saveSettings(); - void scriptFinished(const QString& scriptName); + void scriptFinished(const QString& scriptName, ScriptEngine* engine); void saveScripts(); void reloadScript(const QString& scriptName, bool isUserLoaded = true); From e7a1550b64e831a9b0eb820d277c72e324c8b189 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:09 -0800 Subject: [PATCH 46/67] Update ScriptEngine::finished to include --- libraries/script-engine/src/ScriptEngine.cpp | 4 ++-- libraries/script-engine/src/ScriptEngine.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index daadb0e394..42287bbea7 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -183,7 +183,7 @@ void ScriptEngine::runInThread() { QSet ScriptEngine::_allKnownScriptEngines; QMutex ScriptEngine::_allScriptsMutex; -std::atomic ScriptEngine::_stoppingAllScripts = false; +std::atomic ScriptEngine::_stoppingAllScripts { false }; void ScriptEngine::stopAllScripts(QObject* application) { _allScriptsMutex.lock(); @@ -752,7 +752,7 @@ void ScriptEngine::run() { } if (_wantSignals) { - emit finished(_fileNameString); + emit finished(_fileNameString, this); } _isRunning = false; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 82b91aed2e..f8da05135a 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -153,7 +153,7 @@ signals: void errorLoadingScript(const QString& scriptFilename); void update(float deltaTime); void scriptEnding(); - void finished(const QString& fileNameString); + void finished(const QString& fileNameString, ScriptEngine* engine); void cleanupMenuItem(const QString& menuItemString); void printedMessage(const QString& message); void errorMessage(const QString& message); From a21e07327d4da97256411cb6be691f13cedb8af2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:30 -0800 Subject: [PATCH 47/67] Update ScriptEngine::stop() to always run on its thread --- libraries/script-engine/src/ScriptEngine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 42287bbea7..e06fe2b209 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -775,6 +775,10 @@ void ScriptEngine::stopAllTimers() { void ScriptEngine::stop() { if (!_isFinished) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "stop"); + return; + } _isFinished = true; if (_wantSignals) { emit runningStateChanged(); From 5f60aeef2217e5fc1e3be0da0754a80982f933a4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 14:50:48 -0800 Subject: [PATCH 48/67] Update ScriptEngine::_isUserLoaded to be atomic --- libraries/script-engine/src/ScriptEngine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index f8da05135a..67a206d673 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -193,7 +193,7 @@ protected: Quat _quatLibrary; Vec3 _vec3Library; ScriptUUID _uuidLibrary; - bool _isUserLoaded { false }; + std::atomic _isUserLoaded { false }; bool _isReloading { false }; ArrayBufferClass* _arrayBufferClass; From ad0865171b53ca9030cf6875ae8afced602a2b39 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Dec 2015 15:52:30 -0800 Subject: [PATCH 49/67] Fix unused variable in scriptFinished --- interface/src/Application.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 740b0062f0..d648537155 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4347,10 +4347,12 @@ void Application::scriptFinished(const QString& scriptName, ScriptEngine* engine } } } - postLambdaEvent([this, scriptName]() { - _runningScriptsWidget->scriptStopped(scriptName); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - }); + if (removed) { + postLambdaEvent([this, scriptName]() { + _runningScriptsWidget->scriptStopped(scriptName); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + }); + } } void Application::stopAllScripts(bool restart) { From acb43e18d0a2c6b18b71c2081dd331a10fcfb68e Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 9 Dec 2015 15:54:49 -0800 Subject: [PATCH 50/67] coding standards --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h | 2 +- .../src/display-plugins/openvr/OpenVrDisplayPlugin.h | 2 +- plugins/oculus/src/OculusDisplayPlugin.h | 2 +- plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 59c0e4e759..e3633b5fe8 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -9,7 +9,7 @@ #include "WindowOpenGLDisplayPlugin.h" -#define TARGET_FRAMERATE_Basic2DWindowOpenGL 60.0f +const float TARGET_FRAMERATE_Basic2DWindowOpenGL = 60.0f; class QScreen; class QAction; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 2b51c53d58..d07add7ea5 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -14,7 +14,7 @@ #include "../WindowOpenGLDisplayPlugin.h" -#define TARGET_RATE_OpenVr 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. +const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 071dca0258..03c9ba7511 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -12,7 +12,7 @@ struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; -#define TARGET_RATE_Oculus 75.0f; +const float TARGET_RATE_Oculus = 75.0f; class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 7fe721fc45..d3e68585df 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -13,7 +13,7 @@ #include -#define TARGET_RATE_OculusLegacy 75.0f; +const float TARGET_RATE_OculusLegacy = 75.0f; class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin { public: From 3b372fd897aa9b4c011216037201c6c35ff92491 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 9 Dec 2015 16:12:34 -0800 Subject: [PATCH 51/67] coding standards --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9139a9dcc9..5beadffb1e 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -83,17 +83,16 @@ void Basic2DWindowOpenGLDisplayPlugin::internalPresent() { } WindowOpenGLDisplayPlugin::internalPresent(); } -#define THROTTLED_FRAMERATE 15 +const uint32_t THROTTLED_FRAMERATE = 15; int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; int result = ULIMIITED_PAINT_TIMER_DELAY_MS; - // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. - // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. - if (_isThrottled) { - result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; - } if (0 != _framerateTarget) { result = MSECS_PER_SECOND / _framerateTarget; + } else if (_isThrottled) { + // This test wouldn't be necessary if we could depend on updateFramerate setting _framerateTarget. + // Alas, that gets complicated: isThrottled() is const and other stuff depends on it. + result = MSECS_PER_SECOND / THROTTLED_FRAMERATE; } qDebug() << "New interval " << result; @@ -135,7 +134,7 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { _framerateTarget = 30; } } else if (_isThrottled) { - _framerateTarget = (float) THROTTLED_FRAMERATE; + _framerateTarget = THROTTLED_FRAMERATE; } int newInterval = getDesiredInterval(); From d09f70239c435fba20eafd61f84b160d856d7afe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 09:03:53 -0800 Subject: [PATCH 52/67] make entity-tree a global. change how network-requests to load model geometry are triggered --- interface/src/Application.cpp | 73 ++++--- interface/src/Application.h | 3 +- .../src/EntityTreeRenderer.h | 2 +- .../src/RenderableModelEntityItem.cpp | 187 ++++++++++-------- .../src/RenderableModelEntityItem.h | 4 +- libraries/entities/src/EntityItem.h | 2 + libraries/entities/src/EntityTree.cpp | 9 + libraries/entities/src/EntityTree.h | 3 + libraries/entities/src/ModelEntityItem.h | 7 +- libraries/entities/src/ZoneEntityItem.h | 2 +- 10 files changed, 170 insertions(+), 122 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..1b94c913db 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -352,6 +352,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(true, qApp, qApp); return true; } @@ -371,7 +372,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _frameCount(0), _fps(60.0f), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), - _entities(true, this, this), _entityClipboardRenderer(false, this, this), _entityClipboard(new EntityTree()), _lastQueriedTime(usecTimestampNow()), @@ -864,7 +864,7 @@ void Application::cleanupBeforeQuit() { } _keyboardFocusHighlight = nullptr; - _entities.clear(); // this will allow entity scripts to properly shutdown + getEntities()->clear(); // this will allow entity scripts to properly shutdown auto nodeList = DependencyManager::get(); @@ -875,7 +875,7 @@ void Application::cleanupBeforeQuit() { // tell the packet receiver we're shutting down, so it can drop packets nodeList->getPacketReceiver().setShouldDropPackets(true); - _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts // first stop all timers directly or by invokeMethod @@ -921,7 +921,7 @@ void Application::emptyLocalCache() { } Application::~Application() { - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); tree->setSimulation(NULL); _octreeProcessor.terminate(); @@ -1995,7 +1995,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); - _entities.mouseMoveEvent(&mappedEvent, deviceID); + getEntities()->mouseMoveEvent(&mappedEvent, deviceID); _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it @@ -2021,7 +2021,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mousePressEvent(&mappedEvent, deviceID); + getEntities()->mousePressEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -2066,7 +2066,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { event->buttons(), event->modifiers()); if (!_aboutToQuit) { - _entities.mouseReleaseEvent(&mappedEvent, deviceID); + getEntities()->mouseReleaseEvent(&mappedEvent, deviceID); } _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts @@ -2389,7 +2389,7 @@ void Application::calibrateEyeTracker5Points() { bool Application::exportEntities(const QString& filename, const QVector& entityIDs) { QVector entities; - auto entityTree = _entities.getTree(); + auto entityTree = getEntities()->getTree(); auto exportTree = std::make_shared(); exportTree->createRootElement(); @@ -2433,7 +2433,7 @@ bool Application::exportEntities(const QString& filename, const QVector entities; - _entities.getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); + getEntities()->getTree()->findEntities(AACube(glm::vec3(x, y, z), scale), entities); if (entities.size() > 0) { glm::vec3 root(x, y, z); @@ -2501,7 +2501,7 @@ bool Application::importEntities(const QString& urlOrFilename) { } QVector Application::pasteEntities(float x, float y, float z) { - return _entityClipboard->sendEntities(&_entityEditSender, _entities.getTree(), x, y, z); + return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z); } void Application::initDisplay() { @@ -2540,13 +2540,13 @@ void Application::init() { // fire off an immediate domain-server check in now that settings are loaded DependencyManager::get()->sendDomainServerCheckIn(); - _entities.init(); - _entities.setViewFrustum(getViewFrustum()); + getEntities()->init(); + getEntities()->setViewFrustum(getViewFrustum()); ObjectMotionState::setShapeManager(&_shapeManager); _physicsEngine->init(); - EntityTreePointer tree = _entities.getTree(); + EntityTreePointer tree = getEntities()->getTree(); _entitySimulation.init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(&_entitySimulation); @@ -2554,11 +2554,11 @@ void Application::init() { // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts connect(&_entitySimulation, &EntitySimulation::entityCollisionWithEntity, - &_entities, &EntityTreeRenderer::entityCollisionWithEntity); + getEntities(), &EntityTreeRenderer::entityCollisionWithEntity); // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities - _entities.connectSignalsToSlots(entityScriptingInterface.data()); + getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); @@ -2907,19 +2907,19 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - if (true || _physicsEnabled) { + if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; _entitySimulation.getObjectsToDelete(motionStates); _physicsEngine->deleteObjects(motionStates); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToAdd(motionStates); _physicsEngine->addObjects(motionStates); }); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.getObjectsToChange(motionStates); VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); _entitySimulation.setObjectsToChange(stillNeedChange); @@ -2937,12 +2937,12 @@ void Application::update(float deltaTime) { myAvatar->prepareForPhysicsSimulation(); - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); if (_physicsEngine->hasOutgoingChanges()) { - _entities.getTree()->withWriteLock([&] { + getEntities()->getTree()->withWriteLock([&] { _entitySimulation.handleOutgoingChanges(_physicsEngine->getOutgoingChanges(), _physicsEngine->getSessionID()); avatarManager->handleOutgoingChanges(_physicsEngine->getOutgoingChanges()); }); @@ -2957,9 +2957,9 @@ void Application::update(float deltaTime) { // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk // deadlock.) _entitySimulation.handleCollisionEvents(collisionEvents); - // NOTE: the _entities.update() call below will wait for lock + // NOTE: the getEntities()->update() call below will wait for lock // and will simulate entity motion (the EntityTree has been given an EntitySimulation). - _entities.update(); // update the models... + getEntities()->update(); // update the models... } myAvatar->harvestResultsFromPhysicsSimulation(); @@ -3781,7 +3781,7 @@ void Application::clearDomainOctreeDetails() { }); // reset the model renderer - _entities.clear(); + getEntities()->clear(); } void Application::domainChanged(const QString& domainHostname) { @@ -3903,7 +3903,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { // Someone logs in close to the table. They receive information about the items on the table before they // receive information about the table. The items are very close to the avatar's capsule, so they become // activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet. - EntityTreePointer entityTree = _entities.getTree(); + EntityTreePointer entityTree = getEntities()->getTree(); if (!entityTree) { return false; } @@ -3916,6 +3916,9 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { foreach (EntityItemPointer entity, entities) { if (!entity->isReadyToComputeShape()) { + static QString repeatedMessage = + LogHandler::getInstance().addRepeatedMessageRegex("Physics disabled until entity loads: .*"); + qCDebug(interfaceapp) << "Physics disabled until entity loads: " << entity->getID() << entity->getName(); return false; } } @@ -3967,11 +3970,21 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer }); }); - if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { - // These stats packets are sent in between full sends of a scene. - // We keep physics disabled until we've recieved a full scene and everything near the avatar in that - // scene is ready to compute its collision shape. - _physicsEnabled = true; + if (!_physicsEnabled) { + if (nearbyEntitiesAreReadyForPhysics()) { + // These stats packets are sent in between full sends of a scene. + // We keep physics disabled until we've recieved a full scene and everything near the avatar in that + // scene is ready to compute its collision shape. + _physicsEnabled = true; + getMyAvatar()->updateMotionBehaviorFromMenu(); + } else { + auto characterController = getMyAvatar()->getCharacterController(); + if (characterController) { + // if we have a character controller, disable it here so the avatar doesn't get stuck due to + // a non-loading collision hull. + characterController->setEnabled(false); + } + } } return statsMessageLength; @@ -4034,7 +4047,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // we can use the same ones from the application. auto entityScriptingInterface = DependencyManager::get(); entityScriptingInterface->setPacketSender(&_entityEditSender); - entityScriptingInterface->setEntityTree(_entities.getTree()); + entityScriptingInterface->setEntityTree(getEntities()->getTree()); // AvatarManager has some custom types AvatarManager::registerMetaTypes(scriptEngine); diff --git a/interface/src/Application.h b/interface/src/Application.h index 27df7835e6..3d033e3b02 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,7 @@ public: const ViewFrustum* getDisplayViewFrustum() const; ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } - EntityTreeRenderer* getEntities() { return &_entities; } + EntityTreeRenderer* getEntities() { return DependencyManager::get().data(); } QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } EntityTreePointer getEntityClipboard() { return _entityClipboard; } @@ -451,7 +451,6 @@ private: PhysicalEntitySimulation _entitySimulation; PhysicsEnginePointer _physicsEngine; - EntityTreeRenderer _entities; EntityTreeRenderer _entityClipboardRenderer; EntityTreePointer _entityClipboard; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 9980b9d8b6..076fe26d6f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -30,7 +30,7 @@ class ZoneEntityItem; // Generic client side Octree renderer class. -class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { +class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency { Q_OBJECT public: EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b0f155decf..8b6f5ab967 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -12,12 +12,14 @@ #include #include +#include #include #include #include #include #include +#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" @@ -44,6 +46,32 @@ RenderableModelEntityItem::~RenderableModelEntityItem() { } } +void RenderableModelEntityItem::setModelURL(const QString& url) { + auto& currentURL = getParsedModelURL(); + ModelEntityItem::setModelURL(url); + + if (currentURL != getParsedModelURL() || !_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } + } +} + +void RenderableModelEntityItem::loader() { + _needsModelReload = true; + EntityTreeRenderer* renderer = DependencyManager::get().data(); + assert(renderer); + if (!_model || _needsModelReload) { + PerformanceTimer perfTimer("getModel"); + getModel(renderer); + } + if (_model) { + _model->setURL(getParsedModelURL()); + _model->setCollisionModelURL(QUrl(getCompoundShapeURL())); + } +} + void RenderableModelEntityItem::setDimensions(const glm::vec3& value) { _dimensionsInitialized = true; ModelEntityItem::setDimensions(value); @@ -253,6 +281,60 @@ void RenderableModelEntityItem::render(RenderArgs* args) { remapTextures(); + { + // float alpha = getLocalRenderAlpha(); + + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + EntityTreeRenderer* renderer = static_cast(args->_renderer); + getModel(renderer); + } + + if (_model) { + // handle animations.. + if (hasAnimation()) { + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + } + + if (jointsMapped()) { + bool newFrame; + QVector frameDataRotations; + QVector frameDataTranslations; + getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); + assert(frameDataRotations.size() == frameDataTranslations.size()); + if (newFrame) { + for (int i = 0; i < frameDataRotations.size(); i++) { + _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); + } + } + } + } + + bool movingOrAnimating = isMoving() || isAnimatingSomething(); + if ((movingOrAnimating || + _needsInitialSimulation || + _model->getTranslation() != getPosition() || + _model->getRotation() != getRotation() || + _model->getRegistrationPoint() != getRegistrationPoint()) + && _model->isActive() && _dimensionsInitialized) { + _model->setScaleToFit(true, getDimensions()); + _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + _model->setRotation(getRotation()); + _model->setTranslation(getPosition()); + + // make sure to simulate so everything gets set up correctly for rendering + { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + + _needsInitialSimulation = false; + } + } + } } else { static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f); gpu::Batch& batch = *args->_batch; @@ -264,7 +346,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { Model* result = NULL; - + if (!renderer) { return result; } @@ -286,7 +368,8 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // if we have a previously allocated model, but its URL doesn't match // then we need to let our renderer update our model for us. - if (_model && QUrl(getModelURL()) != _model->getURL()) { + if (_model && (QUrl(getModelURL()) != _model->getURL() || + QUrl(getCompoundShapeURL()) != _model->getCollisionURL())) { result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL()); _needsInitialSimulation = true; } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one @@ -295,6 +378,12 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } else { // we already have the model we want... result = _model; } + + if (_model && _needsInitialSimulation) { + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + _needsInitialSimulation = false; } else { // if our desired URL is empty, we may need to delete our existing model if (_model) { _myRenderer->releaseModel(_model); @@ -307,35 +396,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } bool RenderableModelEntityItem::needsToCallUpdate() const { - if (!_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate()) { - return true; - } - - if (!_dimensionsInitialized && _model && _model->isActive()) { - return true; - } - - if (_myRenderer && (!_model || _needsModelReload)) { - return true; - } - - if (_model) { - if (hasAnimation() || jointsMapped()) { - return true; - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - return true; - } - } - - return false; + return !_dimensionsInitialized || _needsInitialSimulation || ModelEntityItem::needsToCallUpdate(); } void RenderableModelEntityItem::update(const quint64& now) { @@ -351,56 +412,6 @@ void RenderableModelEntityItem::update(const quint64& now) { Q_ARG(EntityItemProperties, properties)); } - if (_myRenderer && (!_model || _needsModelReload)) { - // TODO: this getModel() appears to be about 3% of model render time. We should optimize - PerformanceTimer perfTimer("getModel"); - getModel(_myRenderer); - } - - if (_model) { - // handle animations.. - if (hasAnimation()) { - if (!jointsMapped()) { - QStringList modelJointNames = _model->getJointNames(); - mapJoints(modelJointNames); - } - - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } - } - } - } - - bool movingOrAnimating = isMoving() || isAnimatingSomething(); - if ((movingOrAnimating || - _needsInitialSimulation || - _model->getTranslation() != getPosition() || - _model->getRotation() != getRotation() || - _model->getRegistrationPoint() != getRegistrationPoint()) - && _model->isActive() && _dimensionsInitialized) { - _model->setScaleToFit(true, getDimensions()); - _model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - - // make sure to simulate so everything gets set up correctly for rendering - { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - - _needsInitialSimulation = false; - } - } - ModelEntityItem::update(now); } @@ -427,17 +438,27 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori } void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { + auto currentCompoundShapeURL = getCompoundShapeURL(); ModelEntityItem::setCompoundShapeURL(url); - if (_model) { - _model->setCollisionModelURL(QUrl(url)); + + if (getCompoundShapeURL() != currentCompoundShapeURL || !_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } } } bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); + if (type == SHAPE_TYPE_COMPOUND) { if (!_model) { + EntityTreePointer tree = getTree(); + if (tree) { + QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); + } return false; // hmm... } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 3f3fe11633..45d5f43683 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -29,7 +29,8 @@ public: virtual ~RenderableModelEntityItem(); virtual void setDimensions(const glm::vec3& value) override; - + virtual void setModelURL(const QString& url); + virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -72,6 +73,7 @@ public: virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; void locationChanged(); + virtual void loader() override; private: void remapTextures(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 69d642fad1..a1fc89c5e0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -382,6 +382,8 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } + virtual void loader() {} // called indirectly when urls for geometry are updated + protected: const QByteArray getActionDataInternal() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index abad1e5cd1..7688d034d0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1266,3 +1266,12 @@ void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytes } } } + + +void EntityTree::callLoader(EntityItemID entityID) { + // this is used to bounce from the networking thread to the main thread + EntityItemPointer entity = findEntityByEntityItemID(entityID); + if (entity) { + entity->loader(); + } +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 064c106b91..e893c69259 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -235,6 +235,9 @@ public: return _deletedEntityItemIDs.contains(id); } +public slots: + void callLoader(EntityItemID entityID); + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index cbd54f7168..310e741fda 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -74,11 +74,10 @@ public: _color[GREEN_INDEX] = value.green; _color[BLUE_INDEX] = value.blue; } - - // model related properties - void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); } - virtual void setCompoundShapeURL(const QString& url); + // model related properties + virtual void setModelURL(const QString& url) { _modelURL = url; _parsedModelURL = QUrl(url); } + virtual void setCompoundShapeURL(const QString& url); // Animation related items... const AnimationPropertyGroup& getAnimationProperties() const { return _animationProperties; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index bf323248c0..19206f8acc 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -57,7 +57,7 @@ public: static bool getDrawZoneBoundaries() { return _drawZoneBoundaries; } static void setDrawZoneBoundaries(bool value) { _drawZoneBoundaries = value; } - virtual bool isReadyToComputeShape() { return false; } + virtual bool isReadyToComputeShape() { return true; } void updateShapeType(ShapeType type) { _shapeType = type; } virtual ShapeType getShapeType() const; From d731875c5b8ac454115255bb266e6cb3ab4e36e2 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 10 Dec 2015 09:58:53 -0800 Subject: [PATCH 53/67] Fix dependencies for Linux builds. --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index af7cc3daa0..101a6c8016 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From dd011e8bc4c72ecb9578666f7d369bba0793cb00 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 10 Dec 2015 10:05:01 -0800 Subject: [PATCH 54/67] Freakin' xcode ^S. --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 101a6c8016..d2cf96c7f8 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers script-engine) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From 5053fcd11320530ce893bc581c96f74ebde90aee Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 10:19:13 -0800 Subject: [PATCH 55/67] Fix unix builds --- libraries/input-plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index af7cc3daa0..d2cf96c7f8 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers) +link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") From b4ef2b4a088ea6e19cd4d3b1e3d8c20b9c00da5f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:27:31 -0800 Subject: [PATCH 56/67] quiet some logging --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 6c450e0735..8fcc50931d 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -95,7 +95,6 @@ int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { result = MSECS_PER_SECOND / _framerateTarget; } - qDebug() << "New interval " << result; return result; } @@ -136,8 +135,6 @@ void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { } } - int newInterval = getDesiredInterval(); - qDebug() << newInterval; _timer.start(getDesiredInterval()); } From d243132b5c9049b196539952ded60bf4a8dd9f4f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:28:24 -0800 Subject: [PATCH 57/67] quiet some logging --- libraries/networking/src/ResourceCache.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 84af87f217..e5771401b9 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -319,10 +319,10 @@ void Resource::attemptRequest() { void Resource::finishedLoading(bool success) { if (success) { - qDebug().noquote() << "Finished loading:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Finished loading:" << _url.toDisplayString(); _loaded = true; } else { - qDebug().noquote() << "Failed to load:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Failed to load:" << _url.toDisplayString(); _failedToLoad = true; } _loadPriorities.clear(); @@ -339,13 +339,13 @@ void Resource::makeRequest() { _request = ResourceManager::createResourceRequest(this, _activeUrl); if (!_request) { - qDebug().noquote() << "Failed to get request for" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); ResourceCache::requestCompleted(this); finishedLoading(false); return; } - qDebug().noquote() << "Starting request for:" << _url.toDisplayString(); + qCDebug(networking).noquote() << "Starting request for:" << _url.toDisplayString(); connect(_request, &ResourceRequest::progress, this, &Resource::handleDownloadProgress); connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished); @@ -369,7 +369,7 @@ void Resource::handleReplyFinished() { if (result == ResourceRequest::Success) { _data = _request->getData(); auto extraInfo = _url == _activeUrl ? "" : QString(", %1").arg(_activeUrl.toDisplayString()); - qDebug().noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); + qCDebug(networking).noquote() << QString("Request finished for %1%2").arg(_url.toDisplayString(), extraInfo); finishedLoading(true); emit loaded(_data); @@ -377,7 +377,7 @@ void Resource::handleReplyFinished() { } else { switch (result) { case ResourceRequest::Result::Timeout: { - qDebug() << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; + qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; // Fall through to other cases } case ResourceRequest::Result::ServerUnavailable: { @@ -386,7 +386,7 @@ void Resource::handleReplyFinished() { const int BASE_DELAY_MS = 1000; if (_attempts++ < MAX_ATTEMPTS) { auto waitTime = BASE_DELAY_MS * (int)pow(2.0, _attempts); - qDebug().nospace() << "Retrying to load the asset in " << waitTime + qCDebug(networking).nospace() << "Retrying to load the asset in " << waitTime << "ms, attempt " << _attempts << " of " << MAX_ATTEMPTS; QTimer::singleShot(waitTime, this, &Resource::attemptRequest); break; @@ -394,7 +394,7 @@ void Resource::handleReplyFinished() { // fall through to final failure } default: { - qDebug() << "Error loading " << _url; + qCDebug(networking) << "Error loading " << _url; auto error = (result == ResourceRequest::Timeout) ? QNetworkReply::TimeoutError : QNetworkReply::UnknownNetworkError; emit failed(error); From 2dd40beed5817358421163cd34c8f50d911299f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:42:25 -0800 Subject: [PATCH 58/67] formatting --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 8b6f5ab967..3709c0b9ad 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -453,7 +453,6 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); if (type == SHAPE_TYPE_COMPOUND) { - if (!_model) { EntityTreePointer tree = getTree(); if (tree) { From 645695d5d546676d8963a9e3aa685c984923afcf Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Nov 2015 15:20:29 -0800 Subject: [PATCH 59/67] Moving sixense to external plugin --- .../ControllerScriptingInterface.cpp | 3 -- interface/src/ui/ApplicationCompositor.cpp | 1 - interface/src/ui/PreferencesDialog.cpp | 1 - libraries/input-plugins/CMakeLists.txt | 1 - .../src/input-plugins/InputPlugin.cpp | 2 - plugins/hifiSixense/CMakeLists.txt | 12 +++++ .../hifiSixense/src}/SixenseManager.cpp | 6 ++- .../hifiSixense/src}/SixenseManager.h | 2 +- plugins/hifiSixense/src/SixenseProvider.cpp | 45 +++++++++++++++++++ .../hifiSixense/src}/SixenseSupportOSX.cpp | 3 +- plugins/hifiSixense/src/plugin.json | 1 + 11 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 plugins/hifiSixense/CMakeLists.txt rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseManager.cpp (99%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseManager.h (99%) create mode 100644 plugins/hifiSixense/src/SixenseProvider.cpp rename {libraries/input-plugins/src/input-plugins => plugins/hifiSixense/src}/SixenseSupportOSX.cpp (99%) create mode 100644 plugins/hifiSixense/src/plugin.json diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 11053154b6..3bcf8bb311 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -20,9 +20,6 @@ #include "Application.h" #include "devices/MotionTracker.h" -// TODO: this needs to be removed, as well as any related controller-specific information -#include - void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { if (event->type() == HFActionEvent::startType()) { emit actionStartEvent(static_cast(*event)); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4cee190a47..f4dbdd3bc0 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -26,7 +26,6 @@ #include "Tooltip.h" #include "Application.h" -#include // TODO: any references to sixense should be removed here #include diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a25f868172..9a995263cd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -16,7 +16,6 @@ #include #include #include -#include // TODO: This should be replaced with InputDevice/InputPlugin, or something similar #include #include "Application.h" diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index d2cf96c7f8..592f1fcc84 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -5,4 +5,3 @@ link_hifi_libraries(shared plugins controllers script-engine) GroupSources("src/input-plugins") target_sdl2() -target_sixense() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 4b79572a07..d226797e95 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -14,14 +14,12 @@ #include "KeyboardMouseDevice.h" #include "SDL2Manager.h" -#include "SixenseManager.h" // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { new KeyboardMouseDevice(), new SDL2Manager(), - new SixenseManager(), nullptr }; diff --git a/plugins/hifiSixense/CMakeLists.txt b/plugins/hifiSixense/CMakeLists.txt new file mode 100644 index 0000000000..c790f6f14d --- /dev/null +++ b/plugins/hifiSixense/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Created by Bradley Austin Davis on 2015/11/18 +# Copyright 2015 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html +# + +set(TARGET_NAME hifiSixense) +setup_hifi_plugin(Script Qml Widgets) +link_hifi_libraries(shared controllers plugins input-plugins) +target_sixense() diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseManager.cpp rename to plugins/hifiSixense/src/SixenseManager.cpp index 3b08c218a2..93329d768e 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -27,9 +27,11 @@ #include #include #include -#include -#include "InputPluginsLogging.h" +#include + +Q_DECLARE_LOGGING_CATEGORY(inputplugins) +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") static const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 static const unsigned int BUTTON_1 = 1U << 5; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseManager.h rename to plugins/hifiSixense/src/SixenseManager.h index b6bf4b24c0..5cd4dc2451 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -17,7 +17,7 @@ #include #include -#include "InputPlugin.h" +#include struct _sixenseControllerData; using SixenseControllerData = _sixenseControllerData; diff --git a/plugins/hifiSixense/src/SixenseProvider.cpp b/plugins/hifiSixense/src/SixenseProvider.cpp new file mode 100644 index 0000000000..2958e47848 --- /dev/null +++ b/plugins/hifiSixense/src/SixenseProvider.cpp @@ -0,0 +1,45 @@ +// +// Created by Bradley Austin Davis on 2015/10/25 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include +#include + +#include +#include + +#include "SixenseManager.h" + +class SixenseProvider : public QObject, public InputProvider +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + SixenseProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SixenseProvider() {} + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new SixenseManager()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + +private: + InputPluginList _inputPlugins; +}; + +#include "SixenseProvider.moc" diff --git a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp b/plugins/hifiSixense/src/SixenseSupportOSX.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp rename to plugins/hifiSixense/src/SixenseSupportOSX.cpp index f6cec5d67f..85e0f3fe48 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseSupportOSX.cpp +++ b/plugins/hifiSixense/src/SixenseSupportOSX.cpp @@ -17,8 +17,7 @@ #include #include - -#include "InputPluginsLogging.h" +#include #ifndef SIXENSE_LIB_FILENAME #define SIXENSE_LIB_FILENAME QCoreApplication::applicationDirPath() + "/../Frameworks/libsixense_x64" diff --git a/plugins/hifiSixense/src/plugin.json b/plugins/hifiSixense/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/hifiSixense/src/plugin.json @@ -0,0 +1 @@ +{} From 6f29d9e7b8ac889fbd47aaba9aa4225a75366a12 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 8 Dec 2015 17:30:26 -0800 Subject: [PATCH 60/67] Use strongly typed enum instead of nested alias --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 6 +++--- libraries/entities/src/EntityTree.cpp | 4 ++-- libraries/shared/src/SpatiallyNestable.cpp | 2 +- libraries/shared/src/SpatiallyNestable.h | 17 +++++++---------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3f2cd92dbc..d241df7e0e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -47,7 +47,7 @@ const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData"; static std::once_flag frameTypeRegistration; AvatarData::AvatarData() : - SpatiallyNestable(NestableTypes::Avatar, QUuid()), + SpatiallyNestable(NestableType::Avatar, QUuid()), _handPosition(0.0f), _targetScale(1.0f), _handState(0), diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d089427abb..f74cdedb9d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -36,7 +36,7 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; EntityItem::EntityItem(const EntityItemID& entityItemID) : - SpatiallyNestable(NestableTypes::Entity, entityItemID), + SpatiallyNestable(NestableType::Entity, entityItemID), _type(EntityTypes::Unknown), _lastSimulated(0), _lastUpdated(0), @@ -1294,7 +1294,7 @@ void EntityItem::updatePosition(const glm::vec3& value) { setLocalPosition(value); _dirtyFlags |= Simulation::DIRTY_POSITION; forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->getNestableType() == NestableTypes::Entity) { + if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); entity->_dirtyFlags |= Simulation::DIRTY_POSITION; } @@ -1317,7 +1317,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) { setLocalOrientation(rotation); _dirtyFlags |= Simulation::DIRTY_ROTATION; forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->getNestableType() == NestableTypes::Entity) { + if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); entity->_dirtyFlags |= Simulation::DIRTY_ROTATION; entity->_dirtyFlags |= Simulation::DIRTY_POSITION; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index abad1e5cd1..8d0962f662 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -219,7 +219,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI // if the entity has children, run UpdateEntityOperator on them. If the children have children, recurse QQueue toProcess; foreach (SpatiallyNestablePointer child, entity->getChildren()) { - if (child && child->getNestableType() == NestableTypes::Entity) { + if (child && child->getNestableType() == NestableType::Entity) { toProcess.enqueue(child); } } @@ -232,7 +232,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI childEntity, newChildBBRelProperties); recurseTreeWithOperator(&theChildOperator); foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) { - if (childChild && childChild->getNestableType() == NestableTypes::Entity) { + if (childChild && childChild->getNestableType() == NestableType::Entity) { toProcess.enqueue(childChild); } } diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index bde788f6ff..98d127cc1e 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -15,7 +15,7 @@ #include "SpatiallyNestable.h" -SpatiallyNestable::SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id) : +SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : _nestableType(nestableType), _id(id), _transform() { diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index e656957912..7a43e2a563 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -25,17 +25,14 @@ using SpatiallyNestableWeakConstPointer = std::weak_ptr using SpatiallyNestablePointer = std::shared_ptr; using SpatiallyNestableConstPointer = std::shared_ptr; -class NestableTypes { -public: - using NestableType = enum NestableType_t { - Entity, - Avatar - }; +enum class NestableType { + Entity, + Avatar }; class SpatiallyNestable : public std::enable_shared_from_this { public: - SpatiallyNestable(NestableTypes::NestableType nestableType, QUuid id); + SpatiallyNestable(NestableType nestableType, QUuid id); virtual ~SpatiallyNestable() { } virtual const QUuid& getID() const { return _id; } @@ -88,17 +85,17 @@ public: virtual void setLocalScale(const glm::vec3& scale); QList getChildren() const; - NestableTypes::NestableType getNestableType() const { return _nestableType; } + NestableType getNestableType() const { return _nestableType; } // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } - + SpatiallyNestablePointer getThisPointer() const; protected: - NestableTypes::NestableType _nestableType; // EntityItem or an AvatarData + const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; QUuid _parentID; // what is this thing's transform relative to? quint16 _parentJointIndex { 0 }; // which joint of the parent is this relative to? From 1467a9d2ebb82485911333c130f9fe94802ef00f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:17:40 -0800 Subject: [PATCH 61/67] handle initial simulation of _model --- .../src/RenderableModelEntityItem.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3709c0b9ad..3dcb86fc50 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -251,7 +251,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { // check if the URL has changed auto& currentURL = getParsedModelURL(); if (currentURL != _model->getURL()) { - qDebug().noquote() << "Updating model URL: " << currentURL.toDisplayString(); + qCDebug(entitiesrenderer).noquote() << "Updating model URL: " << currentURL.toDisplayString(); _model->setURL(currentURL); } @@ -378,12 +378,6 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { } else { // we already have the model we want... result = _model; } - - if (_model && _needsInitialSimulation) { - PerformanceTimer perfTimer("_model->simulate"); - _model->simulate(0.0f); - } - _needsInitialSimulation = false; } else { // if our desired URL is empty, we may need to delete our existing model if (_model) { _myRenderer->releaseModel(_model); @@ -463,7 +457,9 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { if (_needsInitialSimulation) { // the _model's offset will be wrong until _needsInitialSimulation is false - return false; + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + _needsInitialSimulation = false; } assert(!_model->getCollisionURL().isEmpty()); From 739e184b526f9a16a25ea07d243701e8bc4f3399 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 10 Dec 2015 11:19:11 -0800 Subject: [PATCH 62/67] Fix attachments jitter --- interface/src/Application.cpp | 1 + interface/src/avatar/Avatar.cpp | 1 - interface/src/avatar/Avatar.h | 4 +--- interface/src/avatar/MyAvatar.cpp | 5 ----- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..b3385a3744 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2963,6 +2963,7 @@ void Application::update(float deltaTime) { } myAvatar->harvestResultsFromPhysicsSimulation(); + myAvatar->simulateAttachments(deltaTime); } } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e2b92cc06f..218d679898 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -200,7 +200,6 @@ void Avatar::simulate(float deltaTime) { PerformanceTimer perfTimer("skeleton"); _skeletonModel.getRig()->copyJointsFromJointData(_jointData); _skeletonModel.simulate(deltaTime, _hasNewJointRotations || _hasNewJointTranslations); - simulateAttachments(deltaTime); locationChanged(); // joints changed, so if there are any children, update them. _hasNewJointRotations = false; _hasNewJointTranslations = false; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 99a4fc52a9..09685c318e 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -69,6 +69,7 @@ public: void init(); void simulate(float deltaTime); + void simulateAttachments(float deltaTime); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition); @@ -87,7 +88,6 @@ public: bool isInitialized() const { return _initialized; } SkeletonModel& getSkeletonModel() { return _skeletonModel; } const SkeletonModel& getSkeletonModel() const { return _skeletonModel; } - const QVector& getAttachmentModels() const { return _attachmentModels; } glm::vec3 getChestPosition() const; float getAvatarScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } @@ -217,8 +217,6 @@ protected: virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual void fixupModelsInScene(); - void simulateAttachments(float deltaTime); - virtual void updateJointMappings(); render::ItemID _renderItemID; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6637331b64..29f81ae47e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -323,11 +323,6 @@ void MyAvatar::simulate(float deltaTime) { return; } - { - PerformanceTimer perfTimer("attachments"); - simulateAttachments(deltaTime); - } - { PerformanceTimer perfTimer("joints"); // copy out the skeleton joints from the model From 3a35df191a56576c45d23c43efaf1126aa8d3c70 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:19:26 -0800 Subject: [PATCH 63/67] remove an off-brand change --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 -------- .../entities-renderer/src/RenderableModelEntityItem.h | 1 - 2 files changed, 9 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3dcb86fc50..f2826db43f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -624,11 +624,3 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } return glm::vec3(0.0f); } - -void RenderableModelEntityItem::locationChanged() { - EntityItem::locationChanged(); - if (_model && _model->isActive()) { - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); - } -} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 45d5f43683..0aaa7a0977 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -72,7 +72,6 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - void locationChanged(); virtual void loader() override; private: From c5f5e8de60d84f5f8930ac5fc032b88d1e8b8de8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 10 Dec 2015 11:43:18 -0800 Subject: [PATCH 64/67] Trying to fix build problem --- interface/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0baf709082..87cf1a384c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -100,6 +100,15 @@ else() add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM}) endif() +# These are external plugins, but we need to do the 'add dependency' here so that their +# binary directories get added to the fixup path +add_dependency_external_projects(sixense) +add_dependency_external_projects(sdl2) +if (WIN32) + add_dependency_external_projects(OpenVR) +endif() + + # disable /OPT:REF and /OPT:ICF for the Debug builds # This will prevent the following linker warnings # LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification From c463e36ce6978900932b3248a1f264316647c046 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 14:02:52 -0800 Subject: [PATCH 65/67] make particle explorer visible --- examples/particle_explorer/particleExplorer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/particle_explorer/particleExplorer.js b/examples/particle_explorer/particleExplorer.js index 16c75e18c6..0cc51c1a39 100644 --- a/examples/particle_explorer/particleExplorer.js +++ b/examples/particle_explorer/particleExplorer.js @@ -128,7 +128,6 @@ function setUp() { blue: 255 }, lifespan: 5.0, - visible: false, locked: false, isEmitting: true, lifetime: 3600 // 1 hour; just in case From 2fbabf20db0879a404f8dafbbdb79c92706bdcab Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 10 Dec 2015 13:56:37 -0800 Subject: [PATCH 66/67] properly handle repack attempts --- .../src/octree/OctreeSendThread.cpp | 42 +++---------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 9b664572c1..b4eb75ede9 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -416,27 +416,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus return; } - /* TODO: Looking for a way to prevent locking and encoding a tree that is not - // going to result in any packets being sent... - // - // If our node is root, and the root hasn't changed, and our view hasn't changed, - // and we've already seen at least one duplicate packet, then we probably don't need - // to lock the tree and encode, because the result should be that no bytes will be - // encoded, and this will be a duplicate packet from the last one we sent... - OctreeElementPointer root = _myServer->getOctree()->getRoot(); - bool skipEncode = false; - if ( - (subTree == root) - && (nodeData->getLastRootTimestamp() == root->getLastChanged()) - && !viewFrustumChanged - && (nodeData->getDuplicatePacketCount() > 0) - ) { - qDebug() << "is root, root not changed, view not changed, already seen a duplicate!" - << "Can we skip it?"; - skipEncode = true; - } - */ - float octreeSizeScale = nodeData->getOctreeSizeScale(); int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust(); @@ -471,20 +450,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // the packet and send it completedScene = nodeData->elementBag.isEmpty(); - // if we're trying to fill a full size packet, then we use this logic to determine if we have a DIDNT_FIT case. - if (_packetData.getTargetSize() == MAX_OCTREE_PACKET_DATA_SIZE) { - if (_packetData.hasContent() && bytesWritten == 0 && - params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { - lastNodeDidntFit = true; - } - } else { - // in compressed mode and we are trying to pack more... and we don't care if the _packetData has - // content or not... because in this case even if we were unable to pack any data, we want to drop - // below to our sendNow logic, but we do want to track that we attempted to pack extra + if (params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { + lastNodeDidntFit = true; extraPackingAttempts++; - if (bytesWritten == 0 && params.stopReason == EncodeBitstreamParams::DIDNT_FIT) { - lastNodeDidntFit = true; - } } nodeData->stats.encodeStopped(); @@ -517,7 +485,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } nodeData->writeToPacket(_packetData.getFinalizedData(), _packetData.getFinalizedSize()); - extraPackingAttempts = 0; quint64 compressAndWriteEnd = usecTimestampNow(); compressAndWriteElapsedUsec = (float)(compressAndWriteEnd - compressAndWriteStart); } @@ -526,8 +493,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // the packet doesn't have enough space to bother attempting to pack more... bool sendNow = true; - if (nodeData->getAvailable() >= MINIMUM_ATTEMPT_MORE_PACKING && - extraPackingAttempts <= REASONABLE_NUMBER_OF_PACKING_ATTEMPTS) { + if (!completedScene && (nodeData->getAvailable() >= MINIMUM_ATTEMPT_MORE_PACKING && + extraPackingAttempts <= REASONABLE_NUMBER_OF_PACKING_ATTEMPTS)) { sendNow = false; // try to pack more } @@ -539,6 +506,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus packetSendingElapsedUsec = (float)(packetSendingEnd - packetSendingStart); targetSize = nodeData->getAvailable() - sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE); + extraPackingAttempts = 0; } else { // If we're in compressed mode, then we want to see if we have room for more in this wire packet. // but we've finalized the _packetData, so we want to start a new section, we will do that by From 1af780a6645c82bfbb9dda23392a87a96fecb4df Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Dec 2015 15:05:27 -0800 Subject: [PATCH 67/67] Fix for sixense debug draw after move to plugin. static variables used to hold a Singleton cannot be shared across dll boundaries by default. This uses the globalInstance template to store the instance as a property on the QApplication. --- libraries/shared/src/DebugDraw.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/DebugDraw.cpp b/libraries/shared/src/DebugDraw.cpp index 3060e151c8..557889cab0 100644 --- a/libraries/shared/src/DebugDraw.cpp +++ b/libraries/shared/src/DebugDraw.cpp @@ -8,10 +8,11 @@ // #include "DebugDraw.h" +#include "SharedUtil.h" DebugDraw& DebugDraw::getInstance() { - static DebugDraw instance; - return instance; + static DebugDraw* instance = globalInstance("com.highfidelity.DebugDraw"); + return *instance; } DebugDraw::DebugDraw() {