From 7b70562a1b68ca2fb0d858dc282bdd81f6059145 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Nov 2015 15:51:43 -0800 Subject: [PATCH 01/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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/51] 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 9c5486fb4b407e80a3876422ed04f3c6901f30ad Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 24 Nov 2015 12:58:35 -0800 Subject: [PATCH 29/51] 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 30/51] 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 31/51] 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 32/51] 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 33/51] 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 b24af06589141a194c1c50f64f2752eaee199243 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Dec 2015 18:26:55 -0800 Subject: [PATCH 34/51] Fixing the display of the collision hull mesh --- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++++ libraries/render-utils/src/MeshPartPayload.h | 3 +++ libraries/render-utils/src/Model.cpp | 15 ++++++++++++--- libraries/render-utils/src/ModelRender.cpp | 11 +++++++++++ libraries/render-utils/src/ModelRender.h | 5 +++++ libraries/script-engine/src/ScriptEngine.cpp | 2 +- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index bb37bb4932..456f6eac51 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -71,6 +71,10 @@ void MeshPartPayload::initCache() { } +void MeshPartPayload::updateDrawMaterial(model::MaterialPointer material) { + _drawMaterial = material; +} + void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { _modelPosition = position; _modelOrientation = orientation; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b29d9510d1..5d30eddd20 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -36,6 +36,9 @@ public: glm::vec3 _modelPosition; glm::quat _modelOrientation; + // can replace the material used to draw that item + void updateDrawMaterial(model::MaterialPointer material); + void updateModelLocation(glm::vec3 position, glm::quat orientation); // Render Item interface diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f566d0879d..96fd52edcc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -544,6 +544,7 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin pendingChanges.removeItem(item); } _renderItems.clear(); + _renderItemsSet.clear(); _readyWhenAdded = false; } @@ -1118,8 +1119,10 @@ AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition void Model::segregateMeshGroups() { QSharedPointer networkGeometry; + bool showingCollisionHull = false; if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) { networkGeometry = _collisionGeometry; + showingCollisionHull = true; } else { networkGeometry = _geometry; } @@ -1127,8 +1130,10 @@ void Model::segregateMeshGroups() { const std::vector>& networkMeshes = networkGeometry->getMeshes(); // all of our mesh vectors must match in size - if ((int)networkMeshes.size() != geometry.meshes.size() || - geometry.meshes.size() != _meshStates.size()) { + auto geoMeshesSize = geometry.meshes.size(); + if ((int)networkMeshes.size() != geoMeshesSize || + // geometry.meshes.size() != _meshStates.size()) { + geoMeshesSize > _meshStates.size()) { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } @@ -1146,7 +1151,11 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + auto renderItem = std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + if (showingCollisionHull) { + renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); + } + _renderItemsSet << renderItem; shapeID++; } } diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp index 73f3d715b6..1c4109b185 100644 --- a/libraries/render-utils/src/ModelRender.cpp +++ b/libraries/render-utils/src/ModelRender.cpp @@ -280,3 +280,14 @@ void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, b DependencyManager::get()->getNormalFittingTexture()); } } + +model::MaterialPointer ModelRender::_collisionHullMaterial; + +model::MaterialPointer ModelRender::getCollisionHullMaterial() { + if (!_collisionHullMaterial) { + _collisionHullMaterial = std::make_shared(); + _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + } + return _collisionHullMaterial; +} + diff --git a/libraries/render-utils/src/ModelRender.h b/libraries/render-utils/src/ModelRender.h index 1528dcfc87..39fe05378d 100644 --- a/libraries/render-utils/src/ModelRender.h +++ b/libraries/render-utils/src/ModelRender.h @@ -149,6 +149,11 @@ public: static const RenderPipelineLib& getRenderPipelineLib(); + // Collision hull Material + static model::MaterialPointer _collisionHullMaterial; + + static model::MaterialPointer getCollisionHullMaterial(); + }; #endif // hifi_ModelRender_h \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3306659c80..a075b0a91d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -82,7 +82,7 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) { } Q_DECLARE_METATYPE(controller::InputController*) -static int inputControllerPointerId = qRegisterMetaType(); +//static int inputControllerPointerId = qRegisterMetaType(); QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) { return engine->newQObject(in); From 1adf2cc8ba7b20c9c0e9ab9e30f93622a49a9167 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 Dec 2015 16:45:12 -0800 Subject: [PATCH 35/51] Repesenting the collision meshes of a Model correctly --- libraries/gpu/src/gpu/Stream.h | 1 + .../render-utils/src/MeshPartPayload.cpp | 72 ++++++++++--------- libraries/render-utils/src/MeshPartPayload.h | 4 +- libraries/render-utils/src/Model.cpp | 5 +- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 4fff3b651d..d2fb8a37e9 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -106,6 +106,7 @@ public: bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX); bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX); + bool hasAttribute(Slot slot) const { return (_attributes.find(slot) != _attributes.end()); } protected: AttributeMap _attributes; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 456f6eac51..3aee6cb62c 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -39,30 +39,31 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation) : +MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, + glm::vec3 position, glm::quat orientation, bool applyMeshJoints) : model(model), + _drawMesh(drawMesh), meshIndex(meshIndex), partIndex(partIndex), _shapeID(shapeIndex), _modelPosition(position), - _modelOrientation(orientation) { + _modelOrientation(orientation), + _applyMeshJoints(applyMeshJoints) { initCache(); } void MeshPartPayload::initCache() { - const std::vector>& networkMeshes = model->_geometry->getMeshes(); - const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get()); - _drawMesh = networkMesh._mesh; + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); + _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _hasColorAttrib = !mesh.colors.isEmpty(); - _isBlendShaped = !mesh.blendshapes.isEmpty(); - _isSkinned = !mesh.clusterIndices.isEmpty(); + const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); - - _drawPart = _drawMesh->getPartBuffer().get(partIndex); + _drawPart = _drawMesh->getPartBuffer().get(partIndex); + } auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID); if (networkMaterial) { @@ -219,25 +220,34 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - // Still relying on the raw data from the model - const Model::MeshState& state = model->_meshStates.at(meshIndex); + if (_applyMeshJoints) { + // Still relying on the raw data from the model + const Model::MeshState& state = model->_meshStates.at(meshIndex); - Transform transform; - if (state.clusterBuffer) { - if (model->_cauterizeBones) { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + Transform transform; + if (state.clusterBuffer) { + if (model->_cauterizeBones) { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + } else { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + } } else { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + if (model->_cauterizeBones) { + transform = Transform(state.cauterizedClusterMatrices[0]); + } else { + transform = Transform(state.clusterMatrices[0]); + } } + transform.preTranslate(_modelPosition); + batch.setModelTransform(transform); } else { - if (model->_cauterizeBones) { - transform = Transform(state.cauterizedClusterMatrices[0]); - } else { - transform = Transform(state.clusterMatrices[0]); - } + Transform transform; + transform.setTranslation(_modelPosition); + transform.setRotation(_modelOrientation); + transform.postScale(model->getScale()); + transform.postTranslate(model->getOffset()); + batch.setModelTransform(transform); } - transform.preTranslate(_modelPosition); - batch.setModelTransform(transform); } @@ -280,13 +290,7 @@ void MeshPartPayload::render(RenderArgs* args) const { // sanity check return; // FIXME! } - - - // guard against partially loaded meshes - if (partIndex >= mesh.parts.size()) { - return; - } - + model::MaterialKey drawMaterialKey; if (_drawMaterial) { drawMaterialKey = _drawMaterial->getKey(); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 5d30eddd20..867dd2d264 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -24,7 +24,7 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool applyMeshJoints = true); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -36,6 +36,7 @@ public: glm::vec3 _modelPosition; glm::quat _modelOrientation; + // can replace the material used to draw that item void updateDrawMaterial(model::MaterialPointer material); @@ -62,6 +63,7 @@ public: bool _hasColorAttrib = false; bool _isSkinned = false; bool _isBlendShaped = false; + bool _applyMeshJoints = true; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 96fd52edcc..56c1f642b8 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -90,7 +90,7 @@ void Model::setScale(const glm::vec3& scale) { _scaledToFit = false; } -const float METERS_PER_MILLIMETER = 0.01f; +const float METERS_PER_MILLIMETER = 0.01f; void Model::setScaleInternal(const glm::vec3& scale) { if (glm::distance(_scale, scale) > METERS_PER_MILLIMETER) { @@ -1147,11 +1147,12 @@ void Model::segregateMeshGroups() { int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { const FBXMesh& mesh = geometry.meshes.at(i); + const NetworkMesh& networkMesh = *(networkMeshes.at(i).get()); // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, !showingCollisionHull); if (showingCollisionHull) { renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); } From 9eb40bcd651bcc21a505905aa860827a4689e4bf Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Dec 2015 16:58:14 -0800 Subject: [PATCH 36/51] Trying to redner the collision geometry correctly but still an issue with the bounding box i get --- libraries/model/src/model/Geometry.cpp | 4 +-- libraries/model/src/model/Geometry.h | 4 +-- .../render-utils/src/MeshPartPayload.cpp | 30 ++++++++++++++----- libraries/render-utils/src/MeshPartPayload.h | 5 ++-- libraries/render-utils/src/Model.cpp | 12 +++++--- libraries/render-utils/src/ModelRender.cpp | 2 ++ 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 63adeec0f1..df86ba2a8f 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -92,7 +92,7 @@ void Mesh::setPartBuffer(const BufferView& buffer) { _partBuffer = buffer; } -const Box Mesh::evalPartBound(int partNum) const { +Box Mesh::evalPartBound(int partNum) const { Box box; if (partNum < _partBuffer.getNum()) { const Part& part = _partBuffer.get(partNum); @@ -111,7 +111,7 @@ const Box Mesh::evalPartBound(int partNum) const { return box; } -const Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const { +Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const { Box totalBound; auto part = _partBuffer.cbegin() + partStart; auto partItEnd = _partBuffer.cbegin() + partEnd; diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 8b5f448a64..a35d55d938 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -107,10 +107,10 @@ public: uint getNumParts() const { return _partBuffer.getNumElements(); } // evaluate the bounding box of A part - const Box evalPartBound(int partNum) const; + Box evalPartBound(int partNum) const; // evaluate the bounding boxes of the parts in the range [start, end[ and fill the bounds parameter // the returned box is the bounding box of ALL the evaluated part bounds. - const Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const; + Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const; static gpu::Primitive topologyToPrimitive(Topology topo) { return static_cast(topo); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 3aee6cb62c..b3e27ff558 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -40,7 +40,7 @@ namespace render { using namespace render; MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation, bool applyMeshJoints) : + glm::vec3 position, glm::quat orientation, bool isCollisionGeometry) : model(model), _drawMesh(drawMesh), meshIndex(meshIndex), @@ -48,7 +48,7 @@ MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int _shapeID(shapeIndex), _modelPosition(position), _modelOrientation(orientation), - _applyMeshJoints(applyMeshJoints) { + _isCollisionGeometry(isCollisionGeometry) { initCache(); } @@ -58,9 +58,13 @@ void MeshPartPayload::initCache() { _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _isBlendShaped = !mesh.blendshapes.isEmpty(); + if (!_isCollisionGeometry) { + const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); + } else { + _isBlendShaped = false; + } _drawPart = _drawMesh->getPartBuffer().get(partIndex); } @@ -106,7 +110,19 @@ render::ItemKey MeshPartPayload::getKey() const { render::Item::Bound MeshPartPayload::getBound() const { // NOTE: we can't cache this bounds because we need to handle the case of a moving // entity or mesh part. - return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); + if (_isCollisionGeometry) { + if (_drawMesh && _drawBound.isNull()) { + _drawBound = _drawMesh->evalPartBound(partIndex); + } + // If we not skinned use the bounds of the subMesh for all it's parts + const FBXMesh& mesh = model->_collisionGeometry->getFBXGeometry().meshes.at(meshIndex); + auto otherBound = model->calculateScaledOffsetExtents(mesh.meshExtents, _modelPosition, _modelOrientation); + + return model->getPartBounds(0, 0, _modelPosition, _modelOrientation); + + } else { + return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); + } } void MeshPartPayload::drawCall(gpu::Batch& batch) const { @@ -220,7 +236,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - if (_applyMeshJoints) { + if (!_isCollisionGeometry) { // Still relying on the raw data from the model const Model::MeshState& state = model->_meshStates.at(meshIndex); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 867dd2d264..b810ad8acf 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -24,7 +24,7 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool applyMeshJoints = true); + MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool isCollisionGeometry = false); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -60,10 +60,11 @@ public: model::MeshPointer _drawMesh; model::Mesh::Part _drawPart; model::MaterialPointer _drawMaterial; + mutable model::Box _drawBound; bool _hasColorAttrib = false; bool _isSkinned = false; bool _isBlendShaped = false; - bool _applyMeshJoints = true; + bool _isCollisionGeometry = false; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 56c1f642b8..35d2702cc2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1120,9 +1120,13 @@ AABox Model::getPartBounds(int meshIndex, int partIndex, glm::vec3 modelPosition void Model::segregateMeshGroups() { QSharedPointer networkGeometry; bool showingCollisionHull = false; - if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) { - networkGeometry = _collisionGeometry; - showingCollisionHull = true; + if (_showCollisionHull && _collisionGeometry) { + if (_collisionGeometry->isLoaded()) { + networkGeometry = _collisionGeometry; + showingCollisionHull = true; + } else { + return; + } } else { networkGeometry = _geometry; } @@ -1152,7 +1156,7 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, !showingCollisionHull); + auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, showingCollisionHull); if (showingCollisionHull) { renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); } diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp index 1c4109b185..10c9d738d2 100644 --- a/libraries/render-utils/src/ModelRender.cpp +++ b/libraries/render-utils/src/ModelRender.cpp @@ -287,6 +287,8 @@ model::MaterialPointer ModelRender::getCollisionHullMaterial() { if (!_collisionHullMaterial) { _collisionHullMaterial = std::make_shared(); _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + _collisionHullMaterial->setMetallic(0.02f); + _collisionHullMaterial->setGloss(1.0f); } return _collisionHullMaterial; } From d09f70239c435fba20eafd61f84b160d856d7afe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 09:03:53 -0800 Subject: [PATCH 37/51] 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 b4ef2b4a088ea6e19cd4d3b1e3d8c20b9c00da5f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 10:27:31 -0800 Subject: [PATCH 38/51] 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 39/51] 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 40/51] 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 1467a9d2ebb82485911333c130f9fe94802ef00f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:17:40 -0800 Subject: [PATCH 41/51] 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 3a35df191a56576c45d23c43efaf1126aa8d3c70 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 Dec 2015 11:19:26 -0800 Subject: [PATCH 42/51] 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 c463e36ce6978900932b3248a1f264316647c046 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 10 Dec 2015 14:02:52 -0800 Subject: [PATCH 43/51] 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 98263f0c0d270c35b4d0cf90afecc7099e985ef2 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 18 Nov 2015 15:20:29 -0800 Subject: [PATCH 44/51] Moving sdl2 to external plugin --- cmake/externals/sdl2/CMakeLists.txt | 8 ++++ interface/src/Application.cpp | 10 ----- libraries/input-plugins/CMakeLists.txt | 4 +- .../src/input-plugins/InputPlugin.cpp | 2 - plugins/hifiSdl2/CMakeLists.txt | 12 +++++ .../hifiSdl2/src}/Joystick.cpp | 0 .../hifiSdl2/src}/Joystick.h | 0 .../hifiSdl2/src}/SDL2Manager.cpp | 4 +- .../hifiSdl2/src}/SDL2Manager.h | 3 +- plugins/hifiSdl2/src/SDL2Provider.cpp | 44 +++++++++++++++++++ plugins/hifiSdl2/src/plugin.json | 1 + 11 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 plugins/hifiSdl2/CMakeLists.txt rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/Joystick.cpp (100%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/Joystick.h (100%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/SDL2Manager.cpp (99%) rename {libraries/input-plugins/src/input-plugins => plugins/hifiSdl2/src}/SDL2Manager.h (98%) create mode 100644 plugins/hifiSdl2/src/SDL2Provider.cpp create mode 100644 plugins/hifiSdl2/src/plugin.json diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index ee1d57d2e9..4222cd41f0 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -63,7 +63,11 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") if (APPLE) + +# NOOP + elseif (WIN32) + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE PATH "Location of SDL2 include directory") @@ -75,8 +79,12 @@ elseif (WIN32) set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/lib/x86 CACHE PATH "Location of SDL2 DLL") endif() + add_paths_to_fixup_libs(${${EXTERNAL_NAME_UPPER}_DLL_PATH}) + else () + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory") set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${INSTALL_DIR}/lib/libSDL2.so CACHE FILEPATH "Path to SDL2 library") + endif () diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a79c23712e..a55c4d3617 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -68,7 +68,6 @@ #include #include #include -#include // this should probably be removed #include #include #include @@ -4004,13 +4003,6 @@ void Application::saveScripts() { settings.endArray(); } -QScriptValue joystickToScriptValue(QScriptEngine *engine, Joystick* const &in) { - return engine->newQObject(in); -} - -void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) { - out = qobject_cast(object.toQObject()); -} void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) { // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so @@ -4075,8 +4067,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get().data()); - qScriptRegisterMetaType(scriptEngine, joystickToScriptValue, joystickFromScriptValue); - scriptEngine->registerGlobalObject("UndoStack", &_undoStackScriptingInterface); scriptEngine->registerGlobalObject("LODManager", DependencyManager::get().data()); diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 592f1fcc84..b81554511d 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME input-plugins) setup_hifi_library() -link_hifi_libraries(shared plugins controllers script-engine) +link_hifi_libraries(shared plugins controllers) GroupSources("src/input-plugins") - -target_sdl2() diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index d226797e95..4d59adb602 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -13,13 +13,11 @@ #include #include "KeyboardMouseDevice.h" -#include "SDL2Manager.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(), nullptr }; diff --git a/plugins/hifiSdl2/CMakeLists.txt b/plugins/hifiSdl2/CMakeLists.txt new file mode 100644 index 0000000000..2f106aedce --- /dev/null +++ b/plugins/hifiSdl2/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 hifiSdl2) +setup_hifi_plugin(Script Qml Widgets) +link_hifi_libraries(shared controllers plugins input-plugins script-engine) +target_sdl2() diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp similarity index 100% rename from libraries/input-plugins/src/input-plugins/Joystick.cpp rename to plugins/hifiSdl2/src/Joystick.cpp diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/plugins/hifiSdl2/src/Joystick.h similarity index 100% rename from libraries/input-plugins/src/input-plugins/Joystick.h rename to plugins/hifiSdl2/src/Joystick.h diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp similarity index 99% rename from libraries/input-plugins/src/input-plugins/SDL2Manager.cpp rename to plugins/hifiSdl2/src/SDL2Manager.cpp index c6f5491a5a..7ca49bbd75 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -11,8 +11,6 @@ #include -#include -#include #include #include @@ -163,6 +161,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { joystick->handleButtonEvent(event.cbutton); } +#if 0 if (event.cbutton.button == SDL_CONTROLLER_BUTTON_BACK) { // this will either start or stop a global back event QEvent::Type backType = (event.type == SDL_CONTROLLERBUTTONDOWN) @@ -172,6 +171,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { qApp->sendEvent(qApp, &backEvent); } +#endif } else if (event.type == SDL_CONTROLLERDEVICEADDED) { SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h similarity index 98% rename from libraries/input-plugins/src/input-plugins/SDL2Manager.h rename to plugins/hifiSdl2/src/SDL2Manager.h index d6b6de24b3..61e2d37fd5 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -17,8 +17,7 @@ #endif #include - -#include "InputPlugin.h" +#include #include "Joystick.h" class SDL2Manager : public InputPlugin { diff --git a/plugins/hifiSdl2/src/SDL2Provider.cpp b/plugins/hifiSdl2/src/SDL2Provider.cpp new file mode 100644 index 0000000000..1c387a9886 --- /dev/null +++ b/plugins/hifiSdl2/src/SDL2Provider.cpp @@ -0,0 +1,44 @@ +// +// 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 "SDL2Manager.h" + +class SDL2Provider : public QObject, public InputProvider { + Q_OBJECT + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + SDL2Provider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SDL2Provider() {} + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new SDL2Manager()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + +private: + InputPluginList _inputPlugins; +}; + +#include "SDL2Provider.moc" diff --git a/plugins/hifiSdl2/src/plugin.json b/plugins/hifiSdl2/src/plugin.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/hifiSdl2/src/plugin.json @@ -0,0 +1 @@ +{} From 5805cc8f2b67a723bcf99f17a9abedd28547416b Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 14:59:04 -0800 Subject: [PATCH 45/51] Adding the AABox transform features (from Extents) adn introducing a simple MeshPartPayload to render simple geometry --- .../render-utils/src/MeshPartPayload.cpp | 347 ++++++++++++------ libraries/render-utils/src/MeshPartPayload.h | 82 +++-- libraries/render-utils/src/Model.cpp | 35 +- libraries/render-utils/src/Model.h | 2 +- libraries/shared/src/AABox.cpp | 16 + libraries/shared/src/AABox.h | 16 +- 6 files changed, 347 insertions(+), 151 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b3e27ff558..42924b4a1b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -25,7 +25,7 @@ namespace render { // Return opaque for lack of a better idea return ItemKey::Builder::opaqueShape(); } - + template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { return payload->getBound(); @@ -39,64 +39,38 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation, bool isCollisionGeometry) : - model(model), - _drawMesh(drawMesh), - meshIndex(meshIndex), - partIndex(partIndex), - _shapeID(shapeIndex), - _modelPosition(position), - _modelOrientation(orientation), - _isCollisionGeometry(isCollisionGeometry) { - initCache(); +MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform) { + + updateMeshPart(mesh, partIndex); + updateMaterial(material); + updateTransform(transform); } -void MeshPartPayload::initCache() { +void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) { + _drawMesh = drawMesh; if (_drawMesh) { auto vertexFormat = _drawMesh->getVertexFormat(); _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); - _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); - - if (!_isCollisionGeometry) { - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); - _isBlendShaped = !mesh.blendshapes.isEmpty(); - } else { - _isBlendShaped = false; - } - _drawPart = _drawMesh->getPartBuffer().get(partIndex); + + _localBound = _drawMesh->evalPartBound(partIndex); } - - auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID); - if (networkMaterial) { - _drawMaterial = networkMaterial->_material; - }; - } -void MeshPartPayload::updateDrawMaterial(model::MaterialPointer material) { - _drawMaterial = material; +void MeshPartPayload::updateTransform(const Transform& transform) { + _drawTransform = transform; + _worldBound = _localBound; + _worldBound.transform(_drawTransform); } -void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { - _modelPosition = position; - _modelOrientation = orientation; +void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) { + _drawMaterial = drawMaterial; } render::ItemKey MeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); - if (!model->isVisible()) { - builder.withInvisible(); - } - - if (_isBlendShaped || _isSkinned) { - builder.withDeformed(); - } - if (_drawMaterial) { auto matKey = _drawMaterial->getKey(); if (matKey.isTransparent() || matKey.isTransparentMap()) { @@ -108,21 +82,7 @@ render::ItemKey MeshPartPayload::getKey() const { } render::Item::Bound MeshPartPayload::getBound() const { - // NOTE: we can't cache this bounds because we need to handle the case of a moving - // entity or mesh part. - if (_isCollisionGeometry) { - if (_drawMesh && _drawBound.isNull()) { - _drawBound = _drawMesh->evalPartBound(partIndex); - } - // If we not skinned use the bounds of the subMesh for all it's parts - const FBXMesh& mesh = model->_collisionGeometry->getFBXGeometry().meshes.at(meshIndex); - auto otherBound = model->calculateScaledOffsetExtents(mesh.meshExtents, _modelPosition, _modelOrientation); - - return model->getPartBounds(0, 0, _modelPosition, _modelOrientation); - - } else { - return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation); - } + return _worldBound; } void MeshPartPayload::drawCall(gpu::Batch& batch) const { @@ -130,22 +90,12 @@ void MeshPartPayload::drawCall(gpu::Batch& batch) const { } void MeshPartPayload::bindMesh(gpu::Batch& batch) const { - if (!_isBlendShaped) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - - batch.setInputFormat((_drawMesh->getVertexFormat())); - - batch.setInputStream(0, _drawMesh->getVertexStream()); - } else { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - batch.setInputFormat((_drawMesh->getVertexFormat())); + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputStream(0, _drawMesh->getVertexStream()); - batch.setInputBuffer(0, model->_blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, model->_blendedVertexBuffers[meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); - batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); - } - // TODO: Get rid of that extra call if (!_hasColorAttrib) { batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); @@ -236,40 +186,215 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { - if (!_isCollisionGeometry) { - // Still relying on the raw data from the model - const Model::MeshState& state = model->_meshStates.at(meshIndex); - - Transform transform; - if (state.clusterBuffer) { - if (model->_cauterizeBones) { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); - } else { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); - } - } else { - if (model->_cauterizeBones) { - transform = Transform(state.cauterizedClusterMatrices[0]); - } else { - transform = Transform(state.clusterMatrices[0]); - } - } - transform.preTranslate(_modelPosition); - batch.setModelTransform(transform); - } else { - Transform transform; - transform.setTranslation(_modelPosition); - transform.setRotation(_modelOrientation); - transform.postScale(model->getScale()); - transform.postTranslate(model->getOffset()); - batch.setModelTransform(transform); - } + batch.setModelTransform(_drawTransform); } void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); - if (!model->_readyWhenAdded || !model->_isVisible) { + + + gpu::Batch& batch = *(args->_batch); + auto mode = args->_renderMode; + + auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME + + model::MaterialKey drawMaterialKey; + if (_drawMaterial) { + drawMaterialKey = _drawMaterial->getKey(); + } + bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); + + bool hasTangents = drawMaterialKey.isNormalMap(); + bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isSkinned = false; + bool wireframe = false; + if (wireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + + ModelRender::Locations* locations = nullptr; + ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + args, locations); + + + // Bind the model transform and the skinCLusterMatrices if needed + bindTransform(batch, locations); + + //Bind the index buffer and vertex buffer and Blend shapes if needed + bindMesh(batch); + + // apply material properties + bindMaterial(batch, locations); + + + // TODO: We should be able to do that just in the renderTransparentJob + if (translucentMesh && locations->lightBufferUnit >= 0) { + PerformanceTimer perfTimer("DLE->setupTransparent()"); + + DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); + } + if (args) { + args->_details._materialSwitches++; + } + + // Draw! + { + PerformanceTimer perfTimer("batch.drawIndexed()"); + drawCall(batch); + } + + if (args) { + const int INDICES_PER_TRIANGLE = 3; + args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; + } +} + + + +namespace render { + template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); + } + // Return opaque for lack of a better idea + return ItemKey::Builder::opaqueShape(); + } + + template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return render::Item::Bound(); + } + template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); + } +} + +using namespace render; + +ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, + glm::vec3 position, glm::quat orientation) : + _model(model), + _meshIndex(_meshIndex), + _shapeID(shapeIndex), + _modelPosition(position), + _modelOrientation(orientation) { + auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh; + updateMeshPart(modelMesh, partIndex); + + initCache(); +} + +void ModelMeshPartPayload::initCache() { + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); + _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); + + + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); + const FBXMesh& mesh = geometry.meshes.at(_meshIndex); + _isBlendShaped = !mesh.blendshapes.isEmpty(); + } + + auto networkMaterial = _model->_geometry->getShapeMaterial(_shapeID); + if (networkMaterial) { + _drawMaterial = networkMaterial->_material; + }; + +} + + +void ModelMeshPartPayload::notifyLocationChanged() { + _model->_needsUpdateClusterMatrices = true; +} + +void ModelMeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { + _modelPosition = position; + _modelOrientation = orientation; +} + +render::ItemKey ModelMeshPartPayload::getKey() const { + ItemKey::Builder builder; + builder.withTypeShape(); + + if (!_model->isVisible()) { + builder.withInvisible(); + } + + if (_isBlendShaped || _isSkinned) { + builder.withDeformed(); + } + + if (_drawMaterial) { + auto matKey = _drawMaterial->getKey(); + if (matKey.isTransparent() || matKey.isTransparentMap()) { + builder.withTransparent(); + } + } + + return builder.build(); +} + +render::Item::Bound ModelMeshPartPayload::getBound() const { + // NOTE: we can't cache this bounds because we need to handle the case of a moving + // entity or mesh part. + return _model->getPartBounds(_meshIndex, _partIndex, _modelPosition, _modelOrientation); +} + +void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { + if (!_isBlendShaped) { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputStream(0, _drawMesh->getVertexStream()); + } else { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + + batch.setInputFormat((_drawMesh->getVertexFormat())); + + batch.setInputBuffer(0, _model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); + batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); + } + + // TODO: Get rid of that extra call + if (!_hasColorAttrib) { + batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } +} + +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { + // Still relying on the raw data from the model + const Model::MeshState& state = _model->_meshStates.at(_meshIndex); + + Transform transform; + if (state.clusterBuffer) { + if (_model->_cauterizeBones) { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + } else { + batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + } + } else { + if (_model->_cauterizeBones) { + transform = Transform(state.cauterizedClusterMatrices[0]); + } else { + transform = Transform(state.clusterMatrices[0]); + } + } + // transform.preTranslate(_modelPosition); + transform.preTranslate(_drawTransform.getTranslation()); + batch.setModelTransform(transform); +} + + +void ModelMeshPartPayload::render(RenderArgs* args) const { + PerformanceTimer perfTimer("ModelMeshPartPayload::render"); + if (!_model->_readyWhenAdded || !_model->_isVisible) { return; // bail asap } @@ -278,25 +403,25 @@ void MeshPartPayload::render(RenderArgs* args) const { auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME - const FBXGeometry& geometry = model->_geometry->getFBXGeometry(); - const std::vector>& networkMeshes = model->_geometry->getMeshes(); + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); + const std::vector>& networkMeshes = _model->_geometry->getMeshes(); // guard against partially loaded meshes - if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)model->_meshStates.size() ) { + if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size() ) { return; } // Back to model to update the cluster matrices right now - model->updateClusterMatrices(_modelPosition, _modelOrientation); + _model->updateClusterMatrices(_modelPosition, _modelOrientation); - const FBXMesh& mesh = geometry.meshes.at(meshIndex); + const FBXMesh& mesh = geometry.meshes.at(_meshIndex); // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // to false to rebuild out mesh groups. - if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) { - model->_meshGroupsKnown = false; // regenerate these lists next time around. - model->_readyWhenAdded = false; // in case any of our users are using scenes - model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { + _model->_meshGroupsKnown = false; // regenerate these lists next time around. + _model->_readyWhenAdded = false; // in case any of our users are using scenes + _model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid return; // FIXME! } @@ -317,12 +442,12 @@ void MeshPartPayload::render(RenderArgs* args) const { bool hasSpecular = drawMaterialKey.isGlossMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isSkinned = _isSkinned; - bool wireframe = model->isWireframe(); + bool wireframe = _model->isWireframe(); // render the part bounding box #ifdef DEBUG_BOUNDING_PARTS { - AABox partBounds = getPartBounds(meshIndex, partIndex); + AABox partBounds = getPartBounds(_meshIndex, partIndex); bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; glm::vec4 cubeColor; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b810ad8acf..9cfda4927f 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -1,5 +1,5 @@ // -// MeshPartPayload.h +// ModelMeshPartPayload.h // interface/src/renderer // // Created by Sam Gateau on 10/3/15. @@ -24,47 +24,42 @@ class Model; class MeshPartPayload { public: - MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool isCollisionGeometry = false); - + MeshPartPayload() {} + MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform); + typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - Model* model; - int meshIndex; - int partIndex; - int _shapeID; - glm::vec3 _modelPosition; - glm::quat _modelOrientation; + virtual void updateMeshPart(model::MeshPointer drawMesh, int partIndex); + virtual void notifyLocationChanged() {} + virtual void updateTransform(const Transform& transform); - // can replace the material used to draw that item - void updateDrawMaterial(model::MaterialPointer material); - - void updateModelLocation(glm::vec3 position, glm::quat orientation); + virtual void updateMaterial(model::MaterialPointer drawMaterial); // Render Item interface - render::ItemKey getKey() const; - render::Item::Bound getBound() const; - void render(RenderArgs* args) const; - - // MeshPartPayload functions to perform render + virtual render::ItemKey getKey() const; + virtual render::Item::Bound getBound() const; + virtual void render(RenderArgs* args) const; + + // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; - void bindMesh(gpu::Batch& batch) const; - void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const; - void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; - - - void initCache(); + virtual void bindMesh(gpu::Batch& batch) const; + virtual void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const; + virtual void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; // Payload resource cached values model::MeshPointer _drawMesh; + int _partIndex = 0; model::Mesh::Part _drawPart; + model::MaterialPointer _drawMaterial; - mutable model::Box _drawBound; + + model::Box _localBound; + Transform _drawTransform; + mutable model::Box _worldBound; + bool _hasColorAttrib = false; - bool _isSkinned = false; - bool _isBlendShaped = false; - bool _isCollisionGeometry = false; }; namespace render { @@ -73,4 +68,35 @@ namespace render { template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); } + +class ModelMeshPartPayload : public MeshPartPayload { +public: + ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + virtual void notifyLocationChanged(); + virtual void updateModelLocation(glm::vec3 position, glm::quat orientation); + + // Render Item interface + render::ItemKey getKey() const; + render::Item::Bound getBound() const; + void render(RenderArgs* args) const; + + // ModelMeshPartPayload functions to perform render + void bindMesh(gpu::Batch& batch) const; + void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; + + + void initCache(); + Model* _model; + int _meshIndex; + int _shapeID; + glm::vec3 _modelPosition; + glm::quat _modelOrientation; + bool _isSkinned = false; + bool _isBlendShaped = false; +}; + #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3f88443ade..ce30e99047 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -110,11 +110,15 @@ void Model::setOffset(const glm::vec3& offset) { void Model::enqueueLocationChange() { render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + render::PendingChanges pendingChanges; foreach (auto itemID, _renderItems.keys()) { pendingChanges.updateItem(itemID, [=](MeshPartPayload& data) { - data.updateModelLocation(_translation, _rotation); - data.model->_needsUpdateClusterMatrices = true; + data.updateTransform(transform); + data.notifyLocationChanged(); }); } @@ -495,11 +499,12 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); + // auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderData = renderItem; auto renderPayload = std::make_shared(renderData); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.model->_needsUpdateClusterMatrices = true; + data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -528,7 +533,7 @@ bool Model::addToScene(std::shared_ptr scene, renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.model->_needsUpdateClusterMatrices = true; + data.notifyLocationChanged(); }); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -1155,6 +1160,10 @@ void Model::segregateMeshGroups() { _renderItemsSet.clear(); + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { @@ -1164,11 +1173,13 @@ void Model::segregateMeshGroups() { // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { - auto renderItem = std::make_shared(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, showingCollisionHull); if (showingCollisionHull) { - renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial()); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform); + + } else { + _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); } - _renderItemsSet << renderItem; + shapeID++; } } @@ -1181,6 +1192,10 @@ bool Model::initWhenReady(render::ScenePointer scene) { render::PendingChanges pendingChanges; + Transform transform; + transform.setTranslation(_translation); + transform.setRotation(_rotation); + foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); @@ -1188,8 +1203,8 @@ bool Model::initWhenReady(render::ScenePointer scene) { _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.updateModelLocation(_translation, _rotation); - data.model->_needsUpdateClusterMatrices = true; + data.updateTransform(transform); + data.notifyLocationChanged(); }); } scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index d77cf830bd..08abb74316 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -366,7 +366,7 @@ private: bool _needsUpdateClusterMatrices = true; bool _showCollisionHull = false; - friend class MeshPartPayload; + friend class ModelMeshPartPayload; protected: RigPointer _rig; }; diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index b514e171eb..2e2b69843a 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -12,6 +12,7 @@ #include "AABox.h" #include "AACube.h" +#include "Transform.h" #include "Extents.h" #include "GeometryUtil.h" #include "NumericalConstants.h" @@ -486,3 +487,18 @@ AABox& AABox::operator += (const AABox& box) { } return (*this); } + +void AABox::scale(const glm::vec3& scale) { + _corner *= scale; + _scale *= scale; +} + +void AABox::rotate(const glm::quat& rotation) { + +} + +void AABox::transform(const Transform& transform) { + scale(transform.getScale()); + rotate(transform.getRotation()); + translate(transform.getTranslation()); +} \ No newline at end of file diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 1f5923dbd8..57587d4e71 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -24,6 +24,7 @@ class AACube; class Extents; +class Transform; class AABox { @@ -40,7 +41,6 @@ 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); const glm::vec3& getCorner() const { return _corner; } const glm::vec3& getScale() const { return _scale; } const glm::vec3& getDimensions() const { return _scale; } @@ -80,6 +80,20 @@ public: AABox& operator += (const glm::vec3& point); AABox& operator += (const AABox& box); + // Translate the AABox just moving the corner + void translate(const glm::vec3& translation) { _corner += translation; } + + // Rotate the AABox around its frame origin + // meaning rotating the corners of the AABox around the point {0,0,0} and reevaluating the min max + void rotate(const glm::quat& rotation); + + /// Scale the AABox + void scale(float scale); + void scale(const glm::vec3& scale); + + // Transform the extents with transform + void transform(const Transform& transform); + bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits::infinity()); } private: From 1af780a6645c82bfbb9dda23392a87a96fecb4df Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Dec 2015 15:05:27 -0800 Subject: [PATCH 46/51] 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() { From 4c8b7aa800772d7f1716cf3d3653ebc1b30d2c17 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 10 Dec 2015 16:26:16 -0800 Subject: [PATCH 47/51] Fix EntityErase packets not being handled on agents --- assignment-client/src/Agent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index d744acc42b..46fa8c8181 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -102,8 +102,10 @@ void Agent::handleOctreePacket(QSharedPointer message, SharedNo packetType = message->getType(); } // fall through to piggyback message - if (packetType == PacketType::EntityData || packetType == PacketType::EntityErase) { + if (packetType == PacketType::EntityData) { _entityViewer.processDatagram(*message, senderNode); + } else if (packetType == PacketType::EntityErase) { + _entityViewer.processEraseMessage(*message, senderNode); } } From dffb83a488560235e6ced4ee9a770f4c70cc3230 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 16:31:00 -0800 Subject: [PATCH 48/51] Potentially working correctly --- libraries/render-utils/src/MeshPartPayload.cpp | 16 +++++++++------- libraries/render-utils/src/MeshPartPayload.h | 6 ++++-- libraries/render-utils/src/Model.cpp | 18 +++++++++++++++--- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 42924b4a1b..4c9adb405b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -39,11 +39,11 @@ namespace render { using namespace render; -MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform) { +MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform) { updateMeshPart(mesh, partIndex); updateMaterial(material); - updateTransform(transform); + updateTransform(transform, offsetTransform); } void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) { @@ -57,8 +57,10 @@ void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) } } -void MeshPartPayload::updateTransform(const Transform& transform) { - _drawTransform = transform; +void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) { + _transform = transform; + _offsetTransform = offsetTransform; + Transform::mult(_drawTransform, _transform, _offsetTransform); _worldBound = _localBound; _worldBound.transform(_drawTransform); } @@ -342,7 +344,7 @@ render::ItemKey ModelMeshPartPayload::getKey() const { render::Item::Bound ModelMeshPartPayload::getBound() const { // NOTE: we can't cache this bounds because we need to handle the case of a moving // entity or mesh part. - return _model->getPartBounds(_meshIndex, _partIndex, _modelPosition, _modelOrientation); + return _model->getPartBounds(_meshIndex, _partIndex, _transform.getTranslation(), _transform.getRotation()); } void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { @@ -387,7 +389,7 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::L } } // transform.preTranslate(_modelPosition); - transform.preTranslate(_drawTransform.getTranslation()); + transform.preTranslate(_transform.getTranslation()); batch.setModelTransform(transform); } @@ -412,7 +414,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } // Back to model to update the cluster matrices right now - _model->updateClusterMatrices(_modelPosition, _modelOrientation); + _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); const FBXMesh& mesh = geometry.meshes.at(_meshIndex); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 9cfda4927f..c5b1e492d8 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -25,7 +25,7 @@ class Model; class MeshPartPayload { public: MeshPartPayload() {} - MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform); + MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -33,7 +33,7 @@ public: virtual void updateMeshPart(model::MeshPointer drawMesh, int partIndex); virtual void notifyLocationChanged() {} - virtual void updateTransform(const Transform& transform); + virtual void updateTransform(const Transform& transform, const Transform& offsetTransform); virtual void updateMaterial(model::MaterialPointer drawMaterial); @@ -57,6 +57,8 @@ public: model::Box _localBound; Transform _drawTransform; + Transform _transform; + Transform _offsetTransform; mutable model::Box _worldBound; bool _hasColorAttrib = false; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ce30e99047..545afea681 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -114,10 +114,14 @@ void Model::enqueueLocationChange() { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + render::PendingChanges pendingChanges; foreach (auto itemID, _renderItems.keys()) { pendingChanges.updateItem(itemID, [=](MeshPartPayload& data) { - data.updateTransform(transform); + data.updateTransform(transform, offset); data.notifyLocationChanged(); }); } @@ -1164,6 +1168,10 @@ void Model::segregateMeshGroups() { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; for (int i = 0; i < (int)networkMeshes.size(); i++) { @@ -1174,7 +1182,7 @@ void Model::segregateMeshGroups() { int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { if (showingCollisionHull) { - _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform, offset); } else { _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); @@ -1196,6 +1204,10 @@ bool Model::initWhenReady(render::ScenePointer scene) { transform.setTranslation(_translation); transform.setRotation(_rotation); + Transform offset; + offset.setScale(_scale); + offset.postTranslate(_offset); + foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); @@ -1203,7 +1215,7 @@ bool Model::initWhenReady(render::ScenePointer scene) { _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { - data.updateTransform(transform); + data.updateTransform(transform, offset); data.notifyLocationChanged(); }); } From 20f3d6abe1bc83eae6971a3622aba18439d1ba60 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 16:52:03 -0800 Subject: [PATCH 49/51] REmoving comments --- libraries/render-utils/src/MeshPartPayload.cpp | 13 +++---------- libraries/render-utils/src/MeshPartPayload.h | 17 +++++++---------- libraries/render-utils/src/Model.cpp | 12 ++++-------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4c9adb405b..2d8d7b598b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -277,16 +277,14 @@ namespace render { using namespace render; -ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, - glm::vec3 position, glm::quat orientation) : +ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _model(model), _meshIndex(_meshIndex), - _shapeID(shapeIndex), - _modelPosition(position), - _modelOrientation(orientation) { + _shapeID(shapeIndex) { auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh; updateMeshPart(modelMesh, partIndex); + updateTransform(transform, offsetTransform); initCache(); } @@ -314,11 +312,6 @@ void ModelMeshPartPayload::notifyLocationChanged() { _model->_needsUpdateClusterMatrices = true; } -void ModelMeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) { - _modelPosition = position; - _modelOrientation = orientation; -} - render::ItemKey ModelMeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c5b1e492d8..e03d1c8a68 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -73,30 +73,27 @@ namespace render { class ModelMeshPartPayload : public MeshPartPayload { public: - ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation); + ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void notifyLocationChanged(); - virtual void updateModelLocation(glm::vec3 position, glm::quat orientation); + void notifyLocationChanged() override; // Render Item interface - render::ItemKey getKey() const; - render::Item::Bound getBound() const; - void render(RenderArgs* args) const; + render::ItemKey getKey() const override; + render::Item::Bound getBound() const override; + void render(RenderArgs* args) const override; // ModelMeshPartPayload functions to perform render - void bindMesh(gpu::Batch& batch) const; - void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; + void bindMesh(gpu::Batch& batch) const override; + void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const override; void initCache(); Model* _model; int _meshIndex; int _shapeID; - glm::vec3 _modelPosition; - glm::quat _modelOrientation; bool _isSkinned = false; bool _isBlendShaped = false; }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 545afea681..e7c4442755 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -503,9 +503,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - // auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderData = renderItem; - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { data.notifyLocationChanged(); @@ -532,8 +530,7 @@ bool Model::addToScene(std::shared_ptr scene, foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { @@ -1185,7 +1182,7 @@ void Model::segregateMeshGroups() { _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform, offset); } else { - _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, _translation, _rotation); + _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); } shapeID++; @@ -1210,8 +1207,7 @@ bool Model::initWhenReady(render::ScenePointer scene) { foreach (auto renderItem, _renderItemsSet) { auto item = scene->allocateID(); - auto renderData = MeshPartPayload::Pointer(renderItem); - auto renderPayload = std::make_shared(renderData); + auto renderPayload = std::make_shared(renderItem); _renderItems.insert(item, renderPayload); pendingChanges.resetItem(item, renderPayload); pendingChanges.updateItem(item, [&](MeshPartPayload& data) { From 40bf721ac54ab0b6d6acd459d6e9687bd4cdd081 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Dec 2015 17:16:06 -0800 Subject: [PATCH 50/51] Fixing merging problem --- libraries/shared/src/AABox.cpp | 87 ++++++++++++++++------------------ 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 3dd020fd90..d16bdafcec 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -43,50 +43,6 @@ glm::vec3 AABox::calcCenter() const { return center; } -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 { switch (vertex) { case BOTTOM_LEFT_NEAR: @@ -532,8 +488,49 @@ void AABox::scale(const glm::vec3& scale) { _scale *= scale; } -void AABox::rotate(const glm::quat& rotation) { +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; } void AABox::transform(const Transform& transform) { From e5a5c05e84d049ad72f2dc01e1b48b85f93c6c3a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 10 Dec 2015 17:56:31 -0800 Subject: [PATCH 51/51] switch to july sixense SDK --- cmake/externals/sixense/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index c41694344e..16f2850449 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -8,14 +8,14 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) #set(SIXENSE_URL_MD5 "10cc8dc470d2ac1244a88cf04bc549cc") #set(SIXENSE_NEW_LAYOUT 0) -#set(SIXENSE_URL "http://public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip") -#set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d") -#set(SIXENSE_NEW_LAYOUT 1) - -set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip") -set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1") +set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip") +set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d") set(SIXENSE_NEW_LAYOUT 1) +#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip") +#set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1") +#set(SIXENSE_NEW_LAYOUT 1) + ExternalProject_Add( ${EXTERNAL_NAME} URL ${SIXENSE_URL}