From 950a62f3f8a88d7a3f0b9e1d05b62c49207990d8 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 8 Feb 2018 15:52:20 -0800 Subject: [PATCH 01/61] Global graphics flag default to on. Added cast shadows flag to zone/keylight. Exit the RenderShadowMap job if current keylight doesn't cast shadows. --- .../src/RenderableZoneEntityItem.cpp | 1 + .../entities/src/EntityItemProperties.cpp | 2 ++ libraries/entities/src/EntityPropertyFlags.h | 9 ++--- .../entities/src/KeyLightPropertyGroup.cpp | 35 +++++++++++++++---- .../entities/src/KeyLightPropertyGroup.h | 2 ++ libraries/graphics/src/graphics/Light.cpp | 9 ++++- libraries/graphics/src/graphics/Light.h | 5 +++ .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../src/DeferredLightingEffect.cpp | 16 ++++++--- .../render-utils/src/DeferredLightingEffect.h | 2 +- .../render-utils/src/RenderShadowTask.cpp | 15 ++++++++ libraries/render-utils/src/RenderShadowTask.h | 2 +- scripts/system/html/entityProperties.html | 4 +++ scripts/system/html/js/entityProperties.js | 7 ++++ 15 files changed, 94 insertions(+), 20 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 04f07c5bd3..c46409c4ee 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -330,6 +330,7 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity sunLight->setColor(ColorUtils::toVec3(_keyLightProperties.getColor())); sunLight->setIntensity(_keyLightProperties.getIntensity()); sunLight->setDirection(_keyLightProperties.getDirection()); + sunLight->setCastShadows(_keyLightProperties.getCastShadows()); } void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index e2a5ddf8b5..cca4e858fa 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1128,6 +1128,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOWS, KeyLightCastShadows, keyLightCastShadows, bool); + ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 90438ab01c..ffcd4f64cb 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -205,6 +205,11 @@ enum EntityPropertyList { PROP_HAZE_MODE, + PROP_KEYLIGHT_COLOR, + PROP_KEYLIGHT_INTENSITY, + PROP_KEYLIGHT_DIRECTION, + PROP_KEYLIGHT_CAST_SHADOWS, + PROP_HAZE_RANGE, PROP_HAZE_COLOR, PROP_HAZE_GLARE_COLOR, @@ -246,10 +251,6 @@ enum EntityPropertyList { // Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for // other properties which will never overlap with each other. We do this so that we don't have to expand // the size of the properties bitflags mask - PROP_KEYLIGHT_COLOR = PROP_COLOR, - PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY, - PROP_KEYLIGHT_DIRECTION = PROP_EXPONENT, - PROP_SKYBOX_COLOR = PROP_ANIMATION_URL, PROP_SKYBOX_URL = PROP_ANIMATION_FPS, diff --git a/libraries/entities/src/KeyLightPropertyGroup.cpp b/libraries/entities/src/KeyLightPropertyGroup.cpp index c476b4c23c..70b9a5395a 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.cpp +++ b/libraries/entities/src/KeyLightPropertyGroup.cpp @@ -21,6 +21,7 @@ const xColor KeyLightPropertyGroup::DEFAULT_KEYLIGHT_COLOR = { 255, 255, 255 }; const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f; const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f; const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f }; +const bool KeyLightPropertyGroup::DEFAULT_KEYLIGHT_CAST_SHADOWS { false }; void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { @@ -28,23 +29,27 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOWS, KeyLight, keyLight, CastShadows, castShadows); } void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, color, xColor, setColor); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, glmVec3, setDirection); - + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows); + // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, xColor, setColor, getColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightIntensity, float, setIntensity, getIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightDirection, glmVec3, setDirection, getDirection); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightCastShadows, bool, setCastShadows, getCastShadows); } void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) { COPY_PROPERTY_IF_CHANGED(color); COPY_PROPERTY_IF_CHANGED(intensity); COPY_PROPERTY_IF_CHANGED(direction); + COPY_PROPERTY_IF_CHANGED(castShadows); } void KeyLightPropertyGroup::debugDump() const { @@ -52,6 +57,7 @@ void KeyLightPropertyGroup::debugDump() const { qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2]; qCDebug(entities) << " intensity:" << getIntensity(); qCDebug(entities) << " direction:" << getDirection(); + qCDebug(entities) << " castShadows:" << getCastShadows(); } void KeyLightPropertyGroup::listChangedProperties(QList& out) { @@ -64,6 +70,9 @@ void KeyLightPropertyGroup::listChangedProperties(QList& out) { if (directionChanged()) { out << "keyLight-direction"; } + if (castShadowsChanged()) { + out << "keyLight-castShadows"; + } } bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData, @@ -71,19 +80,22 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, int& propertyCount, - OctreeElement::AppendState& appendState) const { + OctreeElement::AppendState& appendState) const +{ bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); - + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, getCastShadows()); + return true; } bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt, - int& processedBytes) { + int& processedBytes) +{ int bytesRead = 0; bool overwriteLocalData = true; @@ -92,11 +104,13 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); - + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, bool, setCastShadows); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction); - + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOWS, CastShadows); + processedBytes += bytesRead; Q_UNUSED(somethingChanged); @@ -108,6 +122,7 @@ void KeyLightPropertyGroup::markAllChanged() { _colorChanged = true; _intensityChanged = true; _directionChanged = true; + _castShadowsChanged = true; } EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const { @@ -116,7 +131,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction); - + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOWS, castShadows); + return changedProperties; } @@ -124,6 +140,7 @@ void KeyLightPropertyGroup::getProperties(EntityItemProperties& properties) cons COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Color, getColor); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, CastShadows, getCastShadows); } bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) { @@ -132,6 +149,7 @@ bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Color, color, setColor); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, CastShadows, castShadows, setCastShadows); return somethingChanged; } @@ -142,6 +160,7 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa requestedProperties += PROP_KEYLIGHT_COLOR; requestedProperties += PROP_KEYLIGHT_INTENSITY; requestedProperties += PROP_KEYLIGHT_DIRECTION; + requestedProperties += PROP_KEYLIGHT_CAST_SHADOWS; return requestedProperties; } @@ -159,6 +178,7 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, getCastShadows()); } int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -172,6 +192,7 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, bool, setCastShadows); return bytesRead; } diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index f33ebb282d..d3c8597f95 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -78,10 +78,12 @@ public: static const float DEFAULT_KEYLIGHT_INTENSITY; static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY; static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION; + static const bool DEFAULT_KEYLIGHT_CAST_SHADOWS; DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, xColor, DEFAULT_KEYLIGHT_COLOR); DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION); + DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS); }; #endif // hifi_KeyLightPropertyGroup_h diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp index cb5209d4cf..94ec3a376a 100755 --- a/libraries/graphics/src/graphics/Light.cpp +++ b/libraries/graphics/src/graphics/Light.cpp @@ -65,6 +65,14 @@ const Vec3& Light::getDirection() const { return _lightSchemaBuffer->volume.direction; } +void Light::setCastShadows(const bool castShadows) { + _castShadows = castShadows; +} + +const bool Light::getCastShadows() const { + return _castShadows; +} + void Light::setColor(const Color& color) { _lightSchemaBuffer.edit().irradiance.color = color; updateLightRadius(); @@ -132,7 +140,6 @@ void Light::setSpotExponent(float exponent) { _lightSchemaBuffer.edit().irradiance.falloffSpot = exponent; } - void Light::setAmbientIntensity(float intensity) { _ambientSchemaBuffer.edit().intensity = intensity; } diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index 360e3f224e..7497691185 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -103,6 +103,9 @@ public: void setDirection(const Vec3& direction); const Vec3& getDirection() const; + void setCastShadows(const bool castShadows); + const bool getCastShadows() const; + void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } @@ -187,6 +190,8 @@ protected: void updateLightRadius(); + bool _castShadows{ false }; + }; typedef std::shared_ptr< Light > LightPointer; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c48c6bfc0b..5cafb4caa2 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::SoftEntities); + return static_cast(EntityVersion::ShadowControl); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::RemovedJurisdictions); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index d186ed41c3..d996c2826f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -206,7 +206,8 @@ enum class EntityVersion : PacketVersion { OwnershipChallengeFix, ZoneLightInheritModes = 82, ZoneStageRemoved, - SoftEntities + SoftEntities, + ShadowControl }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index d0d9708c04..c7e6ff1dcf 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -541,15 +541,23 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto keyLight = lightAndShadow.first; - graphics::LightPointer keyAmbientLight; + graphics::LightPointer ambientLight; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { - keyAmbientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front()); + ambientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front()); } - bool hasAmbientMap = (keyAmbientLight != nullptr); + bool hasAmbientMap = (ambientLight != nullptr); // Setup the global directional pass pipeline { - if (deferredLightingEffect->_shadowMapEnabled) { + // Check if keylight casts shadows + bool keyLightCastShadows { false }; + + if (lightStage && lightStage->_currentFrame._sunLights.size()) { + graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); + keyLightCastShadows = keyLight->getCastShadows(); + } + + if (deferredLightingEffect->_shadowMapEnabled && keyLightCastShadows) { // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 1b776e6409..ce7ecacbbe 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -61,7 +61,7 @@ public: private: DeferredLightingEffect() = default; - bool _shadowMapEnabled{ false }; + bool _shadowMapEnabled{ true }; // note that this value is overwritten in the ::configure method bool _ambientOcclusionEnabled{ false }; graphics::MeshPointer _pointLightMesh; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index e8963c2e4e..c5bdcf03dd 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -120,6 +120,12 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con auto lightStage = renderContext->_scene->getStage(); assert(lightStage); + // Exit if current keylight does not cast shadows + bool castShadows = lightStage->getCurrentKeyLight()->getCastShadows(); + if (!castShadows) { + return; + } + auto shadow = lightStage->getCurrentKeyShadow(); if (!shadow || _cascadeIndex >= shadow->getCascadeCount()) { return; @@ -378,6 +384,15 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) { auto lightStage = renderContext->_scene->getStage(); assert(lightStage); + + // Exit if current keylight does not cast shadows + bool castShadows = lightStage->getCurrentKeyLight()->getCastShadows(); + if (!castShadows) { + output.edit0() = ItemFilter::Builder::nothing(); + output.edit1() = ViewFrustumPointer(); + return; + } + // Cache old render args RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 7f127a558c..98b70c0c9f 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -38,7 +38,7 @@ class RenderShadowTaskConfig : public render::Task::Config::Persistent { Q_OBJECT Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) public: - RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", false) {} + RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {} signals: void dirty(); diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index b93974ee77..856ca3c6e1 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -532,6 +532,10 @@
+
+ + +
Skybox diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7008d0df66..7e8827a9b5 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -652,6 +652,8 @@ function loaded() { var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x"); var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); + var elZoneKeyLightCastShadows = document.getElementById("property-zone-key-light-cast-shadows"); + // Skybox var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); @@ -1026,6 +1028,8 @@ function loaded() { elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2); elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); + elZoneKeyLightCastShadows.checked = properties.keyLight.castShadows; + // Skybox elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); @@ -1463,6 +1467,9 @@ function loaded() { elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction); elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction); + elZoneKeyLightCastShadows.addEventListener('change', + createEmitGroupCheckedPropertyUpdateFunction('keyLight', 'castShadows')); + // Skybox var skyboxModeChanged = createZoneComponentModeChangedFunction('skyboxMode', elZoneSkyboxModeInherit, elZoneSkyboxModeDisabled, elZoneSkyboxModeEnabled); From 7ee5245aebeb645c03e2849cd57a235aebb1d96c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 9 Feb 2018 10:45:29 -0800 Subject: [PATCH 02/61] Added shadow caster flag to filter. --- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index c5bdcf03dd..e34f550def 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -224,7 +224,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto setupOutput = task.addJob("ShadowSetup"); const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); + static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); @@ -398,7 +398,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); + output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster(); // Set the keylight render args auto& cascade = globalShadow->getCascade(_cascadeIndex); From 4acd0a34f50ec1219a40ca82cea17df24acf0435 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 12 Feb 2018 12:55:14 -0800 Subject: [PATCH 03/61] Seems OK. Before adding flag to entity. --- libraries/render-utils/src/RenderShadowTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index e34f550def..53c109dc9f 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -224,7 +224,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto setupOutput = task.addJob("ShadowSetup"); const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); + static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); From cf5452313a01c8eab3404a4fccc9f2145d56fae7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 12 Feb 2018 18:44:24 -0800 Subject: [PATCH 04/61] WIP check in of making the use of dq or mat dynamic per model --- .../src/CauterizedMeshPartPayload.cpp | 30 ++++- .../src/CauterizedMeshPartPayload.h | 12 +- .../render-utils/src/CauterizedModel.cpp | 123 +++++++++++------- .../render-utils/src/MeshPartPayload.cpp | 99 ++++++++------ libraries/render-utils/src/MeshPartPayload.h | 20 +-- libraries/render-utils/src/Model.cpp | 65 +++++---- libraries/render-utils/src/Model.h | 11 +- .../render-utils/src/SoftAttachmentModel.cpp | 36 ++--- 8 files changed, 238 insertions(+), 158 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 3d213840dd..e7ea902adb 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -20,16 +20,32 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} -void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms) { - ModelMeshPartPayload::updateClusterBuffer(clusterTransforms); +void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, + const std::vector& cauterizedClusterMatrices) { + ModelMeshPartPayload::updateClusterBuffer(clusterMatrices); - if (cauterizedClusterTransforms.size() > 1) { + if (cauterizedClusterMatrices.size() > 1) { if (!_cauterizedClusterBuffer) { - _cauterizedClusterBuffer = std::make_shared(cauterizedClusterTransforms.size() * sizeof(TransformType), - (const gpu::Byte*) cauterizedClusterTransforms.data()); + _cauterizedClusterBuffer = std::make_shared(cauterizedClusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterMatrices.data()); } else { - _cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(TransformType), - (const gpu::Byte*) cauterizedClusterTransforms.data()); + _cauterizedClusterBuffer->setSubData(0, cauterizedClusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterMatrices.data()); + } + } +} + +void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterDualQuaternions, + const std::vector& cauterizedClusterDualQuaternions) { + ModelMeshPartPayload::updateClusterBuffer(clusterDualQuaternions); + + if (cauterizedClusterDualQuaternions.size() > 1) { + if (!_cauterizedClusterBuffer) { + _cauterizedClusterBuffer = std::make_shared(cauterizedClusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), + (const gpu::Byte*) cauterizedClusterDualQuaternions.data()); + } else { + _cauterizedClusterBuffer->setSubData(0, cauterizedClusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), + (const gpu::Byte*) cauterizedClusterDualQuaternions.data()); } } } diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 2337632047..3783bd1bf8 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -15,13 +15,13 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); -#if defined(SKIN_DQ) - using TransformType = Model::TransformDualQuaternion; -#else - using TransformType = glm::mat4; -#endif + // matrix palette skinning + void updateClusterBuffer(const std::vector& clusterMatrices, + const std::vector& cauterizedClusterMatrices); - void updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms); + // dual quaternion skinning + void updateClusterBuffer(const std::vector& clusterDualQuaternions, + const std::vector& cauterizedClusterQuaternions); void updateTransformForCauterizedMesh(const Transform& renderTransform); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 54dfd96a00..f4a745278e 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -35,8 +35,13 @@ bool CauterizedModel::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { Model::MeshState state; - state.clusterTransforms.resize(mesh.clusters.size()); - _cauterizeMeshStates.append(state); + if (_useDualQuaternionSkinning) { + state.clusterDualQuaternions.resize(mesh.clusters.size()); + _cauterizeMeshStates.append(state); + } else { + state.clusterMatrices.resize(mesh.clusters.size()); + _cauterizeMeshStates.append(state); + } } } return needsFullUpdate; @@ -109,33 +114,33 @@ void CauterizedModel::updateClusterMatrices() { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); -#if defined(SKIN_DQ) - auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); - Transform clusterTransform; - Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); - state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform); - state.clusterTransforms[j].setCauterizationParameters(0.0f, jointPose.trans()); -#else - auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); -#endif + if (_useDualQuaternionSkinning) { + auto jointPose = _rig.getJointPose(cluster.jointIndex); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); + Transform clusterTransform; + Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); + state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); + state.clusterDualQuaternions[j].setCauterizationParameters(0.0f, jointPose.trans()); + } else { + auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); + } } } // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. if (!_cauterizeBoneSet.empty()) { -#if defined(SKIN_DQ) + AnimPose cauterizePose = _rig.getJointPose(geometry.neckJointIndex); cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f); -#else + static const glm::mat4 zeroScale( glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0001f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0001f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); auto cauterizeMatrix = _rig.getJointTransform(geometry.neckJointIndex) * zeroScale; -#endif + for (int i = 0; i < _cauterizeMeshStates.size(); i++) { Model::MeshState& state = _cauterizeMeshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); @@ -143,19 +148,24 @@ void CauterizedModel::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) { - // not cauterized so just copy the value from the non-cauterized version. - state.clusterTransforms[j] = _meshStates[i].clusterTransforms[j]; + if (_useDualQuaternionSkinning) { + if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) { + // not cauterized so just copy the value from the non-cauterized version. + state.clusterDualQuaternions[j] = _meshStates[i].clusterDualQuaternions[j]; + } else { + Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans()); + Transform clusterTransform; + Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); + state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); + state.clusterDualQuaternions[j].setCauterizationParameters(1.0f, cauterizePose.trans()); + } } else { -#if defined(SKIN_DQ) - Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans()); - Transform clusterTransform; - Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); - state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform); - state.clusterTransforms[j].setCauterizationParameters(1.0f, cauterizePose.trans()); -#else - glm_mat4u_mul(cauterizeMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); -#endif + if (_cauterizeBoneSet.find(cluster.jointIndex) == _cauterizeBoneSet.end()) { + // not cauterized so just copy the value from the non-cauterized version. + state.clusterMatrices[j] = _meshStates[i].clusterMatrices[j]; + } else { + glm_mat4u_mul(cauterizeMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); + } } } } @@ -213,38 +223,51 @@ void CauterizedModel::updateRenderItems() { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; - auto clusterTransforms(self->getMeshState(meshIndex).clusterTransforms); - auto clusterTransformsCauterized(self->getCauterizeMeshState(meshIndex).clusterTransforms); + + const auto& meshState = self->getMeshState(meshIndex); + const auto& cauterizedMeshState = self->getCauterizeMeshState(meshIndex); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [modelTransform, clusterTransforms, clusterTransformsCauterized, invalidatePayloadShapeKey, + transaction.updateItem(itemID, [modelTransform, meshState, cauterizedMeshState, invalidatePayloadShapeKey, isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) { - data.updateClusterBuffer(clusterTransforms, clusterTransformsCauterized); + if (_useDualQuaternionSkinning) { + data.updateClusterBuffer(meshState.clusterDualQuaternions, + cauterizedMeshState.clusterDualQuaternions); + } else { + data.updateClusterBuffer(meshState.clusterMatrices, + cauterizedMeshState.clusterMatrices); + } Transform renderTransform = modelTransform; - if (clusterTransforms.size() == 1) { -#if defined(SKIN_DQ) - Transform transform(clusterTransforms[0].getRotation(), - clusterTransforms[0].getScale(), - clusterTransforms[0].getTranslation()); - renderTransform = modelTransform.worldTransform(transform); -#else - renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); -#endif + if (_useDualQuaternionSkinning) { + if (meshState.clusterDualQuaternions.size() == 1) { + const auto& dq = meshState.clusterDualQuaternions[0]; + Transform transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + renderTransform = modelTransform.worldTransform(transform); + } + } else { + if (meshState.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); + } } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); renderTransform = modelTransform; - if (clusterTransformsCauterized.size() == 1) { -#if defined(SKIN_DQ) - Transform transform(clusterTransformsCauterized[0].getRotation(), - clusterTransformsCauterized[0].getScale(), - clusterTransformsCauterized[0].getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); -#else - renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0])); -#endif + if (_useDualQuaternionSkinning) { + if (cauterizedMeshState.clusterDualQuaternions.size() == 1) { + const auto& dq = cauterizedMeshState.clusterDualQuaternions[0]; + Transform transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + renderTransform = modelTransform.worldTransform(Transform(transform)); + } + } else { + if (cauterizedMeshState.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(cauterizedMeshState.clusterMatrices[0])); + } } data.updateTransformForCauterizedMesh(renderTransform); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 9655b60a78..595a4013f1 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -340,20 +340,27 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); - computeAdjustedLocalBound(state.clusterTransforms); + + if (_useDualQuaternionSkinning) { + computeAdjustedLocalBound(state.clusterDualQuaternions); + } else { + computeAdjustedLocalBound(state.clusterMatrices); + } updateTransform(transform, offsetTransform); Transform renderTransform = transform; - if (state.clusterTransforms.size() == 1) { -#if defined(SKIN_DQ) - Transform transform(state.clusterTransforms[0].getRotation(), - state.clusterTransforms[0].getScale(), - state.clusterTransforms[0].getTranslation()); - renderTransform = transform.worldTransform(Transform(transform)); -#else - renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0])); -#endif - + if (_useDualQuaternionSkinning) { + if (state.clusterDualQuaternions.size() == 1) { + const auto& dq = state.clusterDualQuaternions[0]; + Transform transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + renderTransform = transform.worldTransform(Transform(transform)); + } + } else { + if (state.clusterMatrices.size() == 1) { + renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); + } } updateTransformForSkinnedMesh(renderTransform, transform); @@ -383,16 +390,30 @@ void ModelMeshPartPayload::notifyLocationChanged() { } -void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms) { +void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { // Once computed the cluster matrices, update the buffer(s) - if (clusterTransforms.size() > 1) { + if (clusterMatrices.size() > 1) { if (!_clusterBuffer) { - _clusterBuffer = std::make_shared(clusterTransforms.size() * sizeof(TransformType), - (const gpu::Byte*) clusterTransforms.data()); + _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.data()); } else { - _clusterBuffer->setSubData(0, clusterTransforms.size() * sizeof(TransformType), - (const gpu::Byte*) clusterTransforms.data()); + _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterMatrices.data()); + } + } +} + +void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterDualQuaternions) { + // Once computed the cluster matrices, update the buffer(s) + if (clusterDualQuaternions.size() > 1) { + if (!_clusterBuffer) { + _clusterBuffer = std::make_shared(clusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), + (const gpu::Byte*) clusterDualQuaternions.data()); + } + else { + _clusterBuffer->setSubData(0, clusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), + (const gpu::Byte*) clusterDualQuaternions.data()); } } } @@ -550,29 +571,33 @@ void ModelMeshPartPayload::render(RenderArgs* args) { args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } - -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterTransforms) { +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterMatrices) { _adjustedLocalBound = _localBound; - if (clusterTransforms.size() > 0) { -#if defined(SKIN_DQ) - Transform rootTransform(clusterTransforms[0].getRotation(), - clusterTransforms[0].getScale(), - clusterTransforms[0].getTranslation()); - _adjustedLocalBound.transform(rootTransform); -#else - _adjustedLocalBound.transform(clusterTransforms[0]); -#endif + if (clusterMatrices.size() > 0) { + _adjustedLocalBound.transform(clusterMatrices[0]); - for (int i = 1; i < (int)clusterTransforms.size(); ++i) { + for (int i = 1; i < (int)clusterMatrices.size(); ++i) { AABox clusterBound = _localBound; -#if defined(SKIN_DQ) - Transform transform(clusterTransforms[i].getRotation(), - clusterTransforms[i].getScale(), - clusterTransforms[i].getTranslation()); - clusterBound.transform(transform); -#else - clusterBound.transform(clusterTransforms[i]); -#endif + clusterBound.transform(clusterMatrices[i]); + _adjustedLocalBound += clusterBound; + } + } +} + +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions) { + _adjustedLocalBound = _localBound; + if (clusterDualQuaternions.size() > 0) { + Transform rootTransform(clusterDualQuaternions[0].getRotation(), + clusterDualQuaternions[0].getScale(), + clusterDualQuaternions[0].getTranslation()); + _adjustedLocalBound.transform(rootTransform); + + for (int i = 1; i < (int)clusterDualQuaternions.size(); ++i) { + AABox clusterBound = _localBound; + Transform transform(clusterDualQuaternions[i].getRotation(), + clusterDualQuaternions[i].getScale(), + clusterDualQuaternions[i].getTranslation()); + clusterBound.transform(transform); _adjustedLocalBound += clusterBound; } } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 21f9dc2e68..7791390203 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -93,14 +93,14 @@ public: void notifyLocationChanged() override; -#if defined(SKIN_DQ) - using TransformType = Model::TransformDualQuaternion; -#else - using TransformType = glm::mat4; -#endif - void updateKey(bool isVisible, bool isLayered, uint8_t tagBits) override; - void updateClusterBuffer(const std::vector& clusterTransforms); + + // matrix palette skinning + void updateClusterBuffer(const std::vector& clusterMatrices); + + // dual quaternion skinning + void updateClusterBuffer(const std::vector& clusterDualQuaternions); + void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); // Render Item interface @@ -115,7 +115,11 @@ public: void bindMesh(gpu::Batch& batch) override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; - void computeAdjustedLocalBound(const std::vector& clusterTransforms); + // matrix palette skinning + void computeAdjustedLocalBound(const std::vector& clusterMatrices); + + // dual quaternion skinning + void computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); gpu::BufferPointer _clusterBuffer; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b9ccc28c01..92abac3520 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -277,26 +277,35 @@ void Model::updateRenderItems() { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; - auto clusterTransforms(self->getMeshState(meshIndex).clusterTransforms); + + const auto& meshState = self->getMeshState(meshIndex); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [modelTransform, clusterTransforms, + transaction.updateItem(itemID, [modelTransform, meshState, invalidatePayloadShapeKey, isWireframe, isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.updateClusterBuffer(clusterTransforms); + if (_useDualQuaternions) { + data.updateClusterBuffer(meshState.clusterDualQuaternions); + } else { + data.updateClusterBuffer(meshState.clusterMatrices); + } Transform renderTransform = modelTransform; - if (clusterTransforms.size() == 1) { -#if defined(SKIN_DQ) - Transform transform(clusterTransforms[0].getRotation(), - clusterTransforms[0].getScale(), - clusterTransforms[0].getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); -#else - renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); -#endif + + if (_useDualQuaternions) { + if (meshState.clusterDualQuaternions.size() == 1) { + const auto& dq = meshState.clusterDualQuaternions[0]; + Transform transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + renderTransform = modelTransform.worldTransform(Transform(transform)); + } + } else { + if (meshState.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); + } } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); @@ -377,7 +386,11 @@ bool Model::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; - state.clusterTransforms.resize(mesh.clusters.size()); + if (_useDualQuaternions) { + state.clusterDualQuaternions.resize(mesh.clusters.size()); + } else { + state.clusterMatrices.resize(mesh.clusters.size()); + } _meshStates.push_back(state); // Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index @@ -1262,7 +1275,11 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) { void Model::computeMeshPartLocalBounds() { for (auto& part : _modelMeshRenderItems) { const Model::MeshState& state = _meshStates.at(part->_meshIndex); - part->computeAdjustedLocalBound(state.clusterTransforms); + if (_useDualQuaternions) { + part->computeAdjustedLocalBound(state.clusterDualQuaternions); + } else { + part->computeAdjustedLocalBound(state.clusterMatrices); + } } } @@ -1281,16 +1298,16 @@ void Model::updateClusterMatrices() { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); -#if defined(SKIN_DQ) - auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); - Transform clusterTransform; - Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); - state.clusterTransforms[j] = Model::TransformDualQuaternion(clusterTransform); -#else - auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); -#endif + if (_useDualQuaternionSkinning) { + auto jointPose = _rig.getJointPose(cluster.jointIndex); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); + Transform clusterTransform; + Transform::mult(clusterTransform, jointTransform, cluster.inverseBindTransform); + state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); + } else { + auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); + } } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index ca0904f334..84d7dcb7cc 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -254,8 +254,6 @@ public: int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; } bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; } - -#if defined(SKIN_DQ) class TransformDualQuaternion { public: TransformDualQuaternion() {} @@ -293,15 +291,11 @@ public: DualQuaternion _dq; glm::vec4 _cauterizedPosition { 0.0f, 0.0f, 0.0f, 1.0f }; }; -#endif class MeshState { public: -#if defined(SKIN_DQ) - std::vector clusterTransforms; -#else - std::vector clusterTransforms; -#endif + std::vector clusterDualQuaternions; + std::vector clusterMatrices; }; const MeshState& getMeshState(int index) { return _meshStates.at(index); } @@ -420,6 +414,7 @@ protected: virtual void createCollisionRenderItemSet(); bool _isWireframe; + bool _useDualQuaternionSkinning { false }; // debug rendering support int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 0d0db7cbe3..079e6f75ef 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -52,27 +52,27 @@ void SoftAttachmentModel::updateClusterMatrices() { // TODO: cache these look-ups as an optimization int jointIndexOverride = getJointIndexOverride(cluster.jointIndex); -#if defined(SKIN_DQ) - glm::mat4 jointMatrix; - if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { - jointMatrix = _rigOverride.getJointTransform(jointIndexOverride); - } else { - jointMatrix = _rig.getJointTransform(cluster.jointIndex); - } + if (_useDualQuaternionSkinning) { + glm::mat4 jointMatrix; + if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { + jointMatrix = _rigOverride.getJointTransform(jointIndexOverride); + } else { + jointMatrix = _rig.getJointTransform(cluster.jointIndex); + } - glm::mat4 m; - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); - state.clusterTransforms[j] = Model::TransformDualQuaternion(m); -#else - glm::mat4 jointMatrix; - if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { - jointMatrix = _rigOverride.getJointTransform(jointIndexOverride); + glm::mat4 m; + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); + state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(m); } else { - jointMatrix = _rig.getJointTransform(cluster.jointIndex); - } + glm::mat4 jointMatrix; + if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { + jointMatrix = _rigOverride.getJointTransform(jointIndexOverride); + } else { + jointMatrix = _rig.getJointTransform(cluster.jointIndex); + } - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); -#endif + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); + } } } From 7f5f48bca9ad7a3a9f85934888da314d5f91720a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 13 Feb 2018 11:37:14 -0800 Subject: [PATCH 05/61] Models can now switch between dual quats and matrix palette skinning. but not dynamically, because we still only compile one version of the shader. --- libraries/render-utils/src/CauterizedModel.cpp | 9 +++++---- libraries/render-utils/src/MeshPartPayload.cpp | 3 +++ libraries/render-utils/src/MeshPartPayload.h | 1 + libraries/render-utils/src/Model.cpp | 11 ++++++----- libraries/render-utils/src/Model.h | 3 ++- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index f4a745278e..fb1d31d273 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -228,10 +228,11 @@ void CauterizedModel::updateRenderItems() { const auto& cauterizedMeshState = self->getCauterizeMeshState(meshIndex); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); - transaction.updateItem(itemID, [modelTransform, meshState, cauterizedMeshState, invalidatePayloadShapeKey, + transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey, isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) { - if (_useDualQuaternionSkinning) { + if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions, cauterizedMeshState.clusterDualQuaternions); } else { @@ -240,7 +241,7 @@ void CauterizedModel::updateRenderItems() { } Transform renderTransform = modelTransform; - if (_useDualQuaternionSkinning) { + if (useDualQuaternionSkinning) { if (meshState.clusterDualQuaternions.size() == 1) { const auto& dq = meshState.clusterDualQuaternions[0]; Transform transform(dq.getRotation(), @@ -256,7 +257,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForSkinnedMesh(renderTransform, modelTransform); renderTransform = modelTransform; - if (_useDualQuaternionSkinning) { + if (useDualQuaternionSkinning) { if (cauterizedMeshState.clusterDualQuaternions.size() == 1) { const auto& dq = cauterizedMeshState.clusterDualQuaternions[0]; Transform transform(dq.getRotation(), diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 595a4013f1..1585a075f5 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -335,6 +335,9 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in _shapeID(shapeIndex) { assert(model && model->isLoaded()); + + _useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); + _blendedVertexBuffer = model->_blendedVertexBuffers[_meshIndex]; auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); const Model::MeshState& state = model->getMeshState(_meshIndex); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 7791390203..220a0bc48c 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -136,6 +136,7 @@ private: gpu::BufferPointer _blendedVertexBuffer; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; int _layer { render::Item::LAYER_3D }; + bool _useDualQuaternionSkinning { false }; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 92abac3520..1318299f43 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -281,12 +281,13 @@ void Model::updateRenderItems() { const auto& meshState = self->getMeshState(meshIndex); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); - transaction.updateItem(itemID, [modelTransform, meshState, + transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, invalidatePayloadShapeKey, isWireframe, isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - if (_useDualQuaternions) { + if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); } else { data.updateClusterBuffer(meshState.clusterMatrices); @@ -294,7 +295,7 @@ void Model::updateRenderItems() { Transform renderTransform = modelTransform; - if (_useDualQuaternions) { + if (useDualQuaternionSkinning) { if (meshState.clusterDualQuaternions.size() == 1) { const auto& dq = meshState.clusterDualQuaternions[0]; Transform transform(dq.getRotation(), @@ -386,7 +387,7 @@ bool Model::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; - if (_useDualQuaternions) { + if (_useDualQuaternionSkinning) { state.clusterDualQuaternions.resize(mesh.clusters.size()); } else { state.clusterMatrices.resize(mesh.clusters.size()); @@ -1275,7 +1276,7 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) { void Model::computeMeshPartLocalBounds() { for (auto& part : _modelMeshRenderItems) { const Model::MeshState& state = _meshStates.at(part->_meshIndex); - if (_useDualQuaternions) { + if (_useDualQuaternionSkinning) { part->computeAdjustedLocalBound(state.clusterDualQuaternions); } else { part->computeAdjustedLocalBound(state.clusterMatrices); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 84d7dcb7cc..46dbc90324 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -311,6 +311,7 @@ public: Q_INVOKABLE MeshProxyList getMeshes() const; void scaleToFit(); + bool getUseDualQuaternionSkinning() const { return _useDualQuaternionSkinning; } public slots: void loadURLFinished(bool success); @@ -414,7 +415,7 @@ protected: virtual void createCollisionRenderItemSet(); bool _isWireframe; - bool _useDualQuaternionSkinning { false }; + bool _useDualQuaternionSkinning { true }; // debug rendering support int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; From 23a29b8d4b18b07f44a667542f20c210131be1d8 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 13 Feb 2018 16:16:04 -0800 Subject: [PATCH 06/61] Added don't castr shadow flag to entity and shape classes. --- libraries/entities/src/EntityItemProperties.h | 1 + .../src/EntityItemPropertiesDefaults.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 1 + libraries/entities/src/ModelEntityItem.cpp | 35 +++++++++++++++++-- libraries/entities/src/ModelEntityItem.h | 5 +++ libraries/entities/src/ShapeEntityItem.cpp | 29 +++++++++++++++ libraries/entities/src/ShapeEntityItem.h | 5 +++ .../render-utils/src/RenderShadowTask.cpp | 4 +-- libraries/render/src/render/Item.h | 4 +++ 9 files changed, 80 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 3e0770f386..731bb9390e 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -128,6 +128,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT); DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP); DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL); + DEFINE_PROPERTY(PROP_DONT_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR); DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD); DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index eb09a64628..181ba9bbf2 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -46,6 +46,7 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0; const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; +const bool ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW { false }; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index ffcd4f64cb..fbc4199097 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -31,6 +31,7 @@ enum EntityPropertyList { PROP_SCRIPT, // these properties are supported by some derived classes + PROP_DONT_CAST_SHADOW, PROP_COLOR, // these are used by models only diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 5d33e4c047..73cf29bce1 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -53,6 +53,8 @@ void ModelEntityItem::setTextures(const QString& textures) { EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + + COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); @@ -64,6 +66,7 @@ EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredP COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslations, getJointTranslations); COPY_ENTITY_PROPERTY_TO_PROPERTIES(relayParentJoints, getRelayParentJoints); _animationProperties.getProperties(properties); + return properties; } @@ -71,6 +74,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); @@ -112,6 +116,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, const unsigned char* dataAt = data; bool animationPropertiesChanged = false; + READ_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); @@ -148,6 +153,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + requestedProperties += PROP_DONT_CAST_SHADOW; requestedProperties += PROP_MODEL_URL; requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_TEXTURES; @@ -172,6 +178,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; + APPEND_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); @@ -191,8 +198,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); } - - // added update function back for property fix void ModelEntityItem::update(const quint64& now) { @@ -290,6 +295,7 @@ void ModelEntityItem::updateFrameCount() { } void ModelEntityItem::debugDump() const { + qCDebug(entities) << " can cast shadow" << getCanCastShadow(); qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); qCDebug(entities) << " position:" << getWorldPosition(); @@ -571,15 +577,16 @@ QVector ModelEntityItem::getJointTranslationsSet() const { return result; } - xColor ModelEntityItem::getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + bool ModelEntityItem::hasModel() const { return resultWithReadLock([&] { return !_modelURL.isEmpty(); }); } + bool ModelEntityItem::hasCompoundShapeURL() const { return !_compoundShapeURL.get().isEmpty(); } @@ -722,3 +729,25 @@ bool ModelEntityItem::isAnimatingSomething() const { (_animationProperties.getFPS() != 0.0f); }); } + +bool ModelEntityItem::getCanCastShadow() const { + bool result; + withReadLock([&] { + result = _canCastShadow; + }); + return result; +} + +void ModelEntityItem::setCanCastShadow(bool value) { + bool changed = false; + withWriteLock([&] { + if (_canCastShadow != value) { + changed = true; + _canCastShadow = value; + } + }); + + if (changed) { + emit requestRenderUpdate(); + } +} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index c2109ba51f..ec65876d84 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -131,6 +131,9 @@ public: QVector getJointTranslations() const; QVector getJointTranslationsSet() const; + bool getCanCastShadow() const; + void setCanCastShadow(bool value); + private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; @@ -171,6 +174,8 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; + bool _canCastShadow{ ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW }; + private: uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index cbcfcaaa1d..2fbb6702f2 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -91,6 +91,8 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class properties.setColor(getXColor()); properties.setShape(entity::stringFromShape(getShape())); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); + return properties; } @@ -129,6 +131,7 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); if (somethingChanged) { bool wantDebug = false; @@ -154,6 +157,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + READ_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, bool, setCanCastShadow); return bytesRead; } @@ -165,6 +169,8 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_SHAPE; requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += PROP_DONT_CAST_SHADOW; + return requestedProperties; } @@ -180,6 +186,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + APPEND_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, getCanCastShadow()); } void ShapeEntityItem::setColor(const rgbColor& value) { @@ -259,6 +266,7 @@ void ShapeEntityItem::debugDump() const { qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; + qCDebug(entities) << " can cast shadow" << getCanCastShadow(); } void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { @@ -362,3 +370,24 @@ ShapeType ShapeEntityItem::getShapeType() const { return _collisionShapeType; } +bool ShapeEntityItem::getCanCastShadow() const { + bool result; + withReadLock([&] { + result = _canCastShadow; + }); + return result; +} + +void ShapeEntityItem::setCanCastShadow(bool value) { + bool changed = false; + withWriteLock([&] { + if (_canCastShadow != value) { + changed = true; + _canCastShadow = value; + } + }); + + if (changed) { + emit requestRenderUpdate(); + } +} diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 84ce1ce57e..63c4eb58c5 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -101,6 +101,9 @@ public: virtual void computeShapeInfo(ShapeInfo& info) override; virtual ShapeType getShapeType() const override; + bool getCanCastShadow() const; + void setCanCastShadow(bool value); + protected: float _alpha { 1 }; @@ -111,6 +114,8 @@ protected: //! prior functionality where new or unsupported shapes are treated as //! ellipsoids. ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID }; + + bool _canCastShadow { ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW }; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 53c109dc9f..eef641e369 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -224,7 +224,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto setupOutput = task.addJob("ShadowSetup"); const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); + static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withNoShadowCaster(); const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); @@ -398,7 +398,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster(); + output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withNoShadowCaster(); // Set the keylight render args auto& cascade = globalShadow->getCascade(_cascadeIndex); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index ff4b3a0458..7713c1ea7e 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -120,7 +120,10 @@ public: Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } + + Builder& withNoShadowCaster() { _flags.reset(SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } + Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } @@ -155,6 +158,7 @@ public: bool isInvisible() const { return _flags[INVISIBLE]; } bool isShadowCaster() const { return _flags[SHADOW_CASTER]; } + bool isNotShadowCaster() const { return !_flags[SHADOW_CASTER]; } bool isLayered() const { return _flags[LAYERED]; } bool isSpatial() const { return !isLayered(); } From d2c199104e715b33b4ef59922c1e52a010e425b7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 13 Feb 2018 17:47:49 -0800 Subject: [PATCH 07/61] Avatars use Dual Quaternion Skinning and Model Entities do not. --- .../src/avatars-renderer/SkeletonModel.cpp | 2 + .../render-utils/src/MeshPartPayload.cpp | 4 + libraries/render-utils/src/MeshPartPayload.h | 2 +- libraries/render-utils/src/Model.h | 2 +- .../render-utils/src/RenderPipelines.cpp | 79 ++++++++++++++++++- libraries/render-utils/src/Skinning.slh | 14 ++-- libraries/render-utils/src/skin_model.slv | 1 + libraries/render-utils/src/skin_model_dq.slv | 52 ++++++++++++ .../render-utils/src/skin_model_fade.slv | 1 + .../render-utils/src/skin_model_fade_dq.slv | 54 +++++++++++++ .../src/skin_model_normal_map.slv | 1 + .../src/skin_model_normal_map_dq.slv | 61 ++++++++++++++ .../src/skin_model_normal_map_fade.slv | 1 + .../src/skin_model_normal_map_fade_dq.slv | 61 ++++++++++++++ .../render-utils/src/skin_model_shadow.slv | 1 + .../render-utils/src/skin_model_shadow_dq.slv | 30 +++++++ .../src/skin_model_shadow_fade.slv | 1 + .../src/skin_model_shadow_fade_dq.slv | 33 ++++++++ libraries/render/src/render/ShapePipeline.h | 5 ++ 19 files changed, 392 insertions(+), 13 deletions(-) create mode 100644 libraries/render-utils/src/skin_model_dq.slv create mode 100644 libraries/render-utils/src/skin_model_fade_dq.slv create mode 100644 libraries/render-utils/src/skin_model_normal_map_dq.slv create mode 100644 libraries/render-utils/src/skin_model_normal_map_fade_dq.slv create mode 100644 libraries/render-utils/src/skin_model_shadow_dq.slv create mode 100644 libraries/render-utils/src/skin_model_shadow_fade_dq.slv diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 1112ccde60..b2a494230b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -31,6 +31,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)), _headClipDistance(DEFAULT_NEAR_CLIP) { + // SkeletonModels, and by extention Avatars, use Dual Quaternion skinning. + _useDualQuaternionSkinning = true; assert(_owningAvatar); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 1585a075f5..da3a6d80dd 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -516,6 +516,10 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe if (isWireframe) { builder.withWireframe(); } + if (_useDualQuaternionSkinning) { + builder.withDualQuatSkinned(); + } + _shapeKey = builder.build(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 220a0bc48c..cd4d390b1e 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -129,6 +129,7 @@ public: bool _isSkinned{ false }; bool _isBlendShaped { false }; bool _hasTangents { false }; + bool _useDualQuaternionSkinning { false }; private: void initCache(const ModelPointer& model); @@ -136,7 +137,6 @@ private: gpu::BufferPointer _blendedVertexBuffer; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; int _layer { render::Item::LAYER_3D }; - bool _useDualQuaternionSkinning { false }; }; namespace render { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 46dbc90324..9aa4aa6b97 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -415,7 +415,7 @@ protected: virtual void createCollisionRenderItemSet(); bool _isWireframe; - bool _useDualQuaternionSkinning { true }; + bool _useDualQuaternionSkinning { false }; // debug rendering support int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ad7409b731..68c1918044 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -26,6 +26,8 @@ #include "model_lightmap_normal_map_vert.h" #include "skin_model_vert.h" #include "skin_model_normal_map_vert.h" +#include "skin_model_dq_vert.h" +#include "skin_model_normal_map_dq_vert.h" #include "model_lightmap_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h" @@ -33,6 +35,8 @@ #include "model_translucent_normal_map_vert.h" #include "skin_model_fade_vert.h" #include "skin_model_normal_map_fade_vert.h" +#include "skin_model_fade_dq_vert.h" +#include "skin_model_normal_map_fade_dq_vert.h" #include "simple_vert.h" #include "simple_textured_frag.h" @@ -95,6 +99,7 @@ #include "model_shadow_vert.h" #include "skin_model_shadow_vert.h" +#include "skin_model_shadow_dq_vert.h" #include "model_shadow_frag.h" #include "skin_model_shadow_frag.h" @@ -195,16 +200,28 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip auto modelTranslucentVertex = model_translucent_vert::getShader(); auto modelTranslucentNormalMapVertex = model_translucent_normal_map_vert::getShader(); auto modelShadowVertex = model_shadow_vert::getShader(); + + auto modelLightmapFadeVertex = model_lightmap_fade_vert::getShader(); + auto modelLightmapNormalMapFadeVertex = model_lightmap_normal_map_fade_vert::getShader(); + + // matrix palette skinned auto skinModelVertex = skin_model_vert::getShader(); auto skinModelNormalMapVertex = skin_model_normal_map_vert::getShader(); auto skinModelShadowVertex = skin_model_shadow_vert::getShader(); - auto modelLightmapFadeVertex = model_lightmap_fade_vert::getShader(); - auto modelLightmapNormalMapFadeVertex = model_lightmap_normal_map_fade_vert::getShader(); auto skinModelFadeVertex = skin_model_fade_vert::getShader(); auto skinModelNormalMapFadeVertex = skin_model_normal_map_fade_vert::getShader(); auto skinModelTranslucentVertex = skinModelFadeVertex; // We use the same because it ouputs world position per vertex auto skinModelNormalMapTranslucentVertex = skinModelNormalMapFadeVertex; // We use the same because it ouputs world position per vertex + // dual quaternion skinned + auto skinModelDualQuatVertex = skin_model_dq_vert::getShader(); + auto skinModelNormalMapDualQuatVertex = skin_model_normal_map_dq_vert::getShader(); + auto skinModelShadowDualQuatVertex = skin_model_shadow_dq_vert::getShader(); + auto skinModelFadeDualQuatVertex = skin_model_fade_dq_vert::getShader(); + auto skinModelNormalMapFadeDualQuatVertex = skin_model_normal_map_fade_dq_vert::getShader(); + auto skinModelTranslucentDualQuatVertex = skinModelFadeDualQuatVertex; // We use the same because it ouputs world position per vertex + auto skinModelNormalMapTranslucentDualQuatVertex = skinModelNormalMapFadeDualQuatVertex; // We use the same because it ouputs world position per vertex + auto modelFadeVertex = model_fade_vert::getShader(); auto modelNormalMapFadeVertex = model_normal_map_fade_vert::getShader(); auto simpleFadeVertex = simple_fade_vert::getShader(); @@ -376,7 +393,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip Key::Builder().withMaterial().withLightmap().withTangents().withSpecular().withFade(), modelLightmapNormalMapFadeVertex, modelLightmapNormalSpecularMapFadePixel, batchSetter, itemSetter); - // Skinned + // matrix palette skinned addPipeline( Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel, nullptr, nullptr); @@ -403,7 +420,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip Key::Builder().withMaterial().withSkinned().withTangents().withSpecular().withFade(), skinModelNormalMapFadeVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); - // Skinned and Translucent + // matrix palette skinned and translucent addPipeline( Key::Builder().withMaterial().withSkinned().withTranslucent(), skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr); @@ -430,6 +447,60 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + // dual quatenion skinned + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(), + skinModelDualQuatVertex, modelPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents(), + skinModelNormalMapDualQuatVertex, modelNormalMapPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular(), + skinModelDualQuatVertex, modelSpecularMapPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular(), + skinModelNormalMapDualQuatVertex, modelNormalSpecularMapPixel, nullptr, nullptr); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withFade(), + skinModelFadeDualQuatVertex, modelFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withFade(), + skinModelNormalMapFadeDualQuatVertex, modelNormalMapFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withSpecular().withFade(), + skinModelFadeDualQuatVertex, modelSpecularMapFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withSpecular().withFade(), + skinModelNormalMapFadeDualQuatVertex, modelNormalSpecularMapFadePixel, batchSetter, itemSetter); + + // dual quaternion skinned and translucent + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent(), + skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents(), + skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular(), + skinModelTranslucentDualQuatVertex, modelTranslucentPixel, nullptr, nullptr); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular(), + skinModelNormalMapTranslucentDualQuatVertex, modelTranslucentNormalMapPixel, nullptr, nullptr); + // Same thing but with Fade on + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withFade(), + skinModelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withFade(), + skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withSpecular().withFade(), + skinModelFadeDualQuatVertex, modelTranslucentFadePixel, batchSetter, itemSetter); + addPipeline( + Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withSpecular().withFade(), + skinModelNormalMapFadeDualQuatVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); + // Depth-only addPipeline( Key::Builder().withDepthOnly(), diff --git a/libraries/render-utils/src/Skinning.slh b/libraries/render-utils/src/Skinning.slh index 6048ba4ade..fbfe6b7185 100644 --- a/libraries/render-utils/src/Skinning.slh +++ b/libraries/render-utils/src/Skinning.slh @@ -11,18 +11,16 @@ <@if not SKINNING_SLH@> <@def SKINNING_SLH@> -// Use dual quaternion skinning -// Must match #define SKIN_DQ in Model.h -<@def SKIN_DQ@> - const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; +<@func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING)@> + layout(std140) uniform skinClusterBuffer { mat4 clusterMatrices[MAX_CLUSTERS]; }; -<@if SKIN_DQ@> +<@if USE_DUAL_QUATERNION_SKINNING@> mat4 dualQuatToMat4(vec4 real, vec4 dual) { float twoRealXSq = 2.0 * real.x * real.x; @@ -211,7 +209,7 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v skinnedTangent = vec3(m * vec4(inTangent, 0)); } -<@else@> // SKIN_DQ +<@else@> // USE_DUAL_QUATERNION_SKINNING void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0); @@ -260,6 +258,8 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v skinnedTangent = newTangent.xyz; } -<@endif@> // if SKIN_DQ +<@endif@> // if USE_DUAL_QUATERNION_SKINNING + +<@endfunc@> // func declareUseDualQuaternionSkinning(USE_DUAL_QUATERNION_SKINNING) <@endif@> // if not SKINNING_SLH diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index 4236508edb..bd1655fc40 100644 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -18,6 +18,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> diff --git a/libraries/render-utils/src/skin_model_dq.slv b/libraries/render-utils/src/skin_model_dq.slv new file mode 100644 index 0000000000..96f9b4a713 --- /dev/null +++ b/libraries/render-utils/src/skin_model_dq.slv @@ -0,0 +1,52 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model.vert +// vertex shader +// +// Created by Andrzej Kapolka on 10/14/13. +// Copyright 2013 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _color; +out float _alpha; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0); + + skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$> +} diff --git a/libraries/render-utils/src/skin_model_fade.slv b/libraries/render-utils/src/skin_model_fade.slv index fa8e1f8991..b14bf1532e 100644 --- a/libraries/render-utils/src/skin_model_fade.slv +++ b/libraries/render-utils/src/skin_model_fade.slv @@ -18,6 +18,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> diff --git a/libraries/render-utils/src/skin_model_fade_dq.slv b/libraries/render-utils/src/skin_model_fade_dq.slv new file mode 100644 index 0000000000..4f8a923a03 --- /dev/null +++ b/libraries/render-utils/src/skin_model_fade_dq.slv @@ -0,0 +1,54 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// Copyright 2017 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _color; +out float _alpha; +out vec4 _worldPosition; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec3 interpolatedNormal = vec3(0.0, 0.0, 0.0); + + skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToWorldPos(obj, position, _worldPosition)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, _normal.xyz)$> +} diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 9f1087f87a..666bdf865f 100644 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -18,6 +18,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> diff --git a/libraries/render-utils/src/skin_model_normal_map_dq.slv b/libraries/render-utils/src/skin_model_normal_map_dq.slv new file mode 100644 index 0000000000..02b3742f6f --- /dev/null +++ b/libraries/render-utils/src/skin_model_normal_map_dq.slv @@ -0,0 +1,61 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_normal_map.vert +// vertex shader +// +// Created by Andrzej Kapolka on 10/29/13. +// Copyright 2013 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out float _alpha; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); + + skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> + + _normal = interpolatedNormal.xyz; + _tangent = interpolatedTangent.xyz; +} diff --git a/libraries/render-utils/src/skin_model_normal_map_fade.slv b/libraries/render-utils/src/skin_model_normal_map_fade.slv index 4e638866fc..d72e47702d 100644 --- a/libraries/render-utils/src/skin_model_normal_map_fade.slv +++ b/libraries/render-utils/src/skin_model_normal_map_fade.slv @@ -18,6 +18,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> <@include MaterialTextures.slh@> <$declareMaterialTexMapArrayBuffer()$> diff --git a/libraries/render-utils/src/skin_model_normal_map_fade_dq.slv b/libraries/render-utils/src/skin_model_normal_map_fade_dq.slv new file mode 100644 index 0000000000..02b3742f6f --- /dev/null +++ b/libraries/render-utils/src/skin_model_normal_map_fade_dq.slv @@ -0,0 +1,61 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_normal_map.vert +// vertex shader +// +// Created by Andrzej Kapolka on 10/29/13. +// Copyright 2013 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 gpu/Inputs.slh@> +<@include gpu/Color.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +<@include MaterialTextures.slh@> +<$declareMaterialTexMapArrayBuffer()$> + +out vec4 _position; +out vec2 _texCoord0; +out vec2 _texCoord1; +out vec3 _normal; +out vec3 _tangent; +out vec3 _color; +out float _alpha; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); + vec4 interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); + + skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz); + + // pass along the color + _color = colorToLinearRGB(inColor.rgb); + _alpha = inColor.a; + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToEyeAndClipPos(cam, obj, position, _position, gl_Position)$> + <$transformModelToWorldDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToWorldDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> + + _normal = interpolatedNormal.xyz; + _tangent = interpolatedTangent.xyz; +} diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv index 6684cfea80..03da2e074e 100644 --- a/libraries/render-utils/src/skin_model_shadow.slv +++ b/libraries/render-utils/src/skin_model_shadow.slv @@ -17,6 +17,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); diff --git a/libraries/render-utils/src/skin_model_shadow_dq.slv b/libraries/render-utils/src/skin_model_shadow_dq.slv new file mode 100644 index 0000000000..74cd4076bc --- /dev/null +++ b/libraries/render-utils/src/skin_model_shadow_dq.slv @@ -0,0 +1,30 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_shadow.vert +// vertex shader +// +// Created by Andrzej Kapolka on 3/24/14. +// Copyright 2014 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 gpu/Inputs.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, position, gl_Position)$> +} diff --git a/libraries/render-utils/src/skin_model_shadow_fade.slv b/libraries/render-utils/src/skin_model_shadow_fade.slv index 7b27263569..d2e79f9d74 100644 --- a/libraries/render-utils/src/skin_model_shadow_fade.slv +++ b/libraries/render-utils/src/skin_model_shadow_fade.slv @@ -17,6 +17,7 @@ <$declareStandardTransform()$> <@include Skinning.slh@> +<$declareUseDualQuaternionSkinning()$> out vec4 _worldPosition; diff --git a/libraries/render-utils/src/skin_model_shadow_fade_dq.slv b/libraries/render-utils/src/skin_model_shadow_fade_dq.slv new file mode 100644 index 0000000000..fb9c60eefd --- /dev/null +++ b/libraries/render-utils/src/skin_model_shadow_fade_dq.slv @@ -0,0 +1,33 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// skin_model_shadow_fade.vert +// vertex shader +// +// Created by Olivier Prat on 06/045/17. +// Copyright 2017 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 gpu/Inputs.slh@> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include Skinning.slh@> +<$declareUseDualQuaternionSkinning(1)$> + +out vec4 _worldPosition; + +void main(void) { + vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + skinPosition(inSkinClusterIndex, inSkinClusterWeight, inPosition, position); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, position, gl_Position)$> + <$transformModelToWorldPos(obj, position, _worldPosition)$> +} diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 1dd9f5da49..f175bab99a 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -32,6 +32,7 @@ public: SPECULAR, UNLIT, SKINNED, + DUAL_QUAT_SKINNED, DEPTH_ONLY, DEPTH_BIAS, WIREFRAME, @@ -80,6 +81,7 @@ public: Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } + Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } @@ -133,6 +135,9 @@ public: Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withDualQuatSkinned() { _flags.set(DUAL_QUAT_SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withoutDualQuatSkinned() { _flags.reset(DUAL_QUAT_SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } From 1632ab9782cd4ed566ca3b9e417994ec657e6a7a Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 13 Feb 2018 18:27:36 -0800 Subject: [PATCH 08/61] Changed flag to "cast shadow" instead of "don't cast shadow". --- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityItemPropertiesDefaults.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 6 +++--- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 6 +++--- libraries/entities/src/ShapeEntityItem.h | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++-- libraries/render/src/render/Item.h | 4 ---- 9 files changed, 13 insertions(+), 17 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 731bb9390e..8feebd3979 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -128,7 +128,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT); DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP); DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL); - DEFINE_PROPERTY(PROP_DONT_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW); + DEFINE_PROPERTY(PROP_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAST_SHADOW); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR); DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD); DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 181ba9bbf2..f85d55dc3a 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -46,7 +46,7 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0; const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; -const bool ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW { false }; +const bool ENTITY_ITEM_DEFAULT_CAST_SHADOW { true }; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index fbc4199097..d2de67735c 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -31,7 +31,7 @@ enum EntityPropertyList { PROP_SCRIPT, // these properties are supported by some derived classes - PROP_DONT_CAST_SHADOW, + PROP_CAST_SHADOW, PROP_COLOR, // these are used by models only diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 73cf29bce1..6d15fded31 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -116,7 +116,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, const unsigned char* dataAt = data; bool animationPropertiesChanged = false; - READ_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, bool, setCanCastShadow); + READ_ENTITY_PROPERTY(PROP_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); @@ -153,7 +153,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - requestedProperties += PROP_DONT_CAST_SHADOW; + requestedProperties += PROP_CAST_SHADOW; requestedProperties += PROP_MODEL_URL; requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_TEXTURES; @@ -178,7 +178,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, getCanCastShadow()); + APPEND_ENTITY_PROPERTY(PROP_CAST_SHADOW, getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index ec65876d84..49f20c48e2 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -174,7 +174,7 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; - bool _canCastShadow{ ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW }; + bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAST_SHADOW }; private: uint64_t _lastAnimated{ 0 }; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 2fbb6702f2..22c3bab4f3 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -157,7 +157,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); - READ_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, bool, setCanCastShadow); + READ_ENTITY_PROPERTY(PROP_CAST_SHADOW, bool, setCanCastShadow); return bytesRead; } @@ -169,7 +169,7 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_SHAPE; requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; - requestedProperties += PROP_DONT_CAST_SHADOW; + requestedProperties += PROP_CAST_SHADOW; return requestedProperties; } @@ -186,7 +186,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); - APPEND_ENTITY_PROPERTY(PROP_DONT_CAST_SHADOW, getCanCastShadow()); + APPEND_ENTITY_PROPERTY(PROP_CAST_SHADOW, getCanCastShadow()); } void ShapeEntityItem::setColor(const rgbColor& value) { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 63c4eb58c5..4a08936bce 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -115,7 +115,7 @@ protected: //! ellipsoids. ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID }; - bool _canCastShadow { ENTITY_ITEM_DEFAULT_DONT_CAST_SHADOW }; + bool _canCastShadow { ENTITY_ITEM_DEFAULT_CAST_SHADOW }; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index eef641e369..e34f550def 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -224,7 +224,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto setupOutput = task.addJob("ShadowSetup"); const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene - static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withNoShadowCaster(); + static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); @@ -398,7 +398,7 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow && _cascadeIndexgetCascadeCount()) { - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withNoShadowCaster(); + output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster(); // Set the keylight render args auto& cascade = globalShadow->getCascade(_cascadeIndex); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 7713c1ea7e..ff4b3a0458 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -120,10 +120,7 @@ public: Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } - - Builder& withNoShadowCaster() { _flags.reset(SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } - Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } @@ -158,7 +155,6 @@ public: bool isInvisible() const { return _flags[INVISIBLE]; } bool isShadowCaster() const { return _flags[SHADOW_CASTER]; } - bool isNotShadowCaster() const { return !_flags[SHADOW_CASTER]; } bool isLayered() const { return _flags[LAYERED]; } bool isSpatial() const { return !isLayered(); } From a92765a83a3578572c1ce9951c807d417b6744f5 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 12:01:30 -0800 Subject: [PATCH 09/61] Adding can cast shadow property. --- .../entities/src/EntityItemProperties.cpp | 9 +++++ libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 8 ++-- libraries/entities/src/ShapeEntityItem.cpp | 6 +-- scripts/system/html/entityProperties.html | 38 +++++++++---------- scripts/system/html/js/entityProperties.js | 29 ++++++++++++-- 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index cca4e858fa..79c36180d6 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -290,6 +290,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL); CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL); CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible); + CHECK_PROPERTY_CHANGE(PROP_CAN_CAST_SHADOW, canCastShadow); CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint); CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity); CHECK_PROPERTY_CHANGE(PROP_ANGULAR_DAMPING, angularDamping); @@ -625,6 +626,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); } + // Models and Shapes + if (_type == EntityTypes::Model || _type == EntityTypes::Shape || _type == EntityTypes::Box || _type == EntityTypes::Sphere) { + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); + } + if (!skipDefaults && !strictSemantics) { AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); @@ -707,6 +713,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping); COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible); + COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow); COPY_PROPERTY_FROM_QSCRIPTVALUE(color, xColor, setColor); COPY_PROPERTY_FROM_QSCRIPTVALUE(colorSpread, xColor, setColorSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(colorStart, xColor, setColorStart); @@ -1851,6 +1858,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int properties.getType() == EntityTypes::Box || properties.getType() == EntityTypes::Sphere) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); } READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); @@ -1974,6 +1982,7 @@ void EntityItemProperties::markAllChanged() { _angularDampingChanged = true; _nameChanged = true; _visibleChanged = true; + _canCastShadowChanged = true; _colorChanged = true; _alphaChanged = true; _modelURLChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 8feebd3979..ec10910092 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -128,7 +128,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT); DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP); DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL); - DEFINE_PROPERTY(PROP_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAST_SHADOW); + DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAST_SHADOW); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR); DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD); DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d2de67735c..ab17f2a873 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -31,7 +31,7 @@ enum EntityPropertyList { PROP_SCRIPT, // these properties are supported by some derived classes - PROP_CAST_SHADOW, + PROP_CAN_CAST_SHADOW, PROP_COLOR, // these are used by models only diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 6d15fded31..7c14d8a4a0 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -116,7 +116,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, const unsigned char* dataAt = data; bool animationPropertiesChanged = false; - READ_ENTITY_PROPERTY(PROP_CAST_SHADOW, bool, setCanCastShadow); + READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); @@ -153,7 +153,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - requestedProperties += PROP_CAST_SHADOW; + requestedProperties += PROP_CAN_CAST_SHADOW; requestedProperties += PROP_MODEL_URL; requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_TEXTURES; @@ -178,7 +178,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_CAST_SHADOW, getCanCastShadow()); + APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); @@ -619,6 +619,7 @@ void ModelEntityItem::setColor(const rgbColor& value) { }); } +#pragma optimize("", off) void ModelEntityItem::setColor(const xColor& value) { withWriteLock([&] { _color[RED_INDEX] = value.red; @@ -666,7 +667,6 @@ bool ModelEntityItem::getAnimationLoop() const { }); } - void ModelEntityItem::setAnimationHold(bool hold) { withWriteLock([&] { _animationProperties.setHold(hold); diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 22c3bab4f3..9d81e850df 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -157,7 +157,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); - READ_ENTITY_PROPERTY(PROP_CAST_SHADOW, bool, setCanCastShadow); + READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); return bytesRead; } @@ -169,7 +169,7 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_SHAPE; requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; - requestedProperties += PROP_CAST_SHADOW; + requestedProperties += PROP_CAN_CAST_SHADOW; return requestedProperties; } @@ -186,7 +186,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); - APPEND_ENTITY_PROPERTY(PROP_CAST_SHADOW, getCanCastShadow()); + APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); } void ShapeEntityItem::setColor(const rgbColor& value) { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 856ca3c6e1..1420e85b11 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -42,25 +42,28 @@
-
+
+ +
@@ -293,7 +296,6 @@
-
BehaviorM @@ -365,8 +367,6 @@
- -
LightM @@ -400,7 +400,6 @@
-
ModelM @@ -484,7 +483,6 @@
-
ZoneM diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7e8827a9b5..846a1da21a 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -595,6 +595,8 @@ function loaded() { var elShape = document.getElementById("property-shape"); + var elCanCastShadow = document.getElementById("property-can-cast-shadow"); + var elLightSpotLight = document.getElementById("property-light-spot-light"); var elLightColor = document.getElementById("property-light-color"); var elLightColorRed = document.getElementById("property-light-color-red"); @@ -799,7 +801,6 @@ function loaded() { elLocked.checked = properties.locked; - elName.value = properties.name; elVisible.checked = properties.visible; @@ -966,6 +967,12 @@ function loaded() { properties.color.green + "," + properties.color.blue + ")"; } + if (properties.type === "Model" || + properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { + + elCanCastShadow = properties.canCastShadow; + } + if (properties.type === "Model") { elModelURL.value = properties.modelURL; elShapeType.value = properties.shapeType; @@ -1012,7 +1019,6 @@ function loaded() { elLightFalloffRadius.value = properties.falloffRadius.toFixed(1); elLightExponent.value = properties.exponent.toFixed(2); elLightCutoff.value = properties.cutoff.toFixed(2); - } else if (properties.type === "Zone") { // Key light elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); @@ -1093,13 +1099,15 @@ function loaded() { // Show/hide sections as required showElements(document.getElementsByClassName('skybox-section'), elZoneSkyboxModeEnabled.checked); + showElements(document.getElementsByClassName('keylight-section'), elZoneKeyLightModeEnabled.checked); + showElements(document.getElementsByClassName('ambient-section'), elZoneAmbientLightModeEnabled.checked); + showElements(document.getElementsByClassName('haze-section'), elZoneHazeModeEnabled.checked); - } else if (properties.type === "PolyVox") { elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); @@ -1111,6 +1119,15 @@ function loaded() { elZTextureURL.value = properties.zTextureURL; } + // Only these types can cast a shadow + if (properties.type === "Model" || + properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { + + showElements(document.getElementsByClassName('can-cast-shadow-section'), true); + } else { + showElements(document.getElementsByClassName('can-cast-shadow-section'), false); + } + if (properties.locked) { disableProperties(); elLocked.removeAttribute('disabled'); @@ -1356,6 +1373,12 @@ function loaded() { elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); + if (properties.type === "Model" || + properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { + + elCanCastShadow.addEventListener('change', createEmitTextPropertyUpdateFunction('canCastShadow')); + } + elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); elWebDPI.addEventListener('change', createEmitNumberPropertyUpdateFunction('dpi', 0)); From a679b6f82841b701c06c313b57d18de1c3d1c672 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 18:55:04 -0800 Subject: [PATCH 10/61] Fixed possible crash. --- libraries/render-utils/src/DeferredLightingEffect.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 2e77d702c6..665e767c7c 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -550,7 +550,9 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, if (lightStage && lightStage->_currentFrame._sunLights.size()) { graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); - keyLightCastShadows = keyLight->getCastShadows(); + if (keyLight) { + keyLightCastShadows = keyLight->getCastShadows(); + } } if (deferredLightingEffect->_shadowMapEnabled && keyLightCastShadows) { From ef771b6db49ff48655fe772d01b9f6683e1e3234 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 19:11:13 -0800 Subject: [PATCH 11/61] Minor indentation correction. --- scripts/system/html/entityProperties.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 1cfa5c3899..7dbeae067c 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -678,7 +678,7 @@ min="-1000" max="50000" step="10"> -
+
From 12f4b8dbb19321c74c7b967b569627b87b8c23aa Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 19:12:24 -0800 Subject: [PATCH 12/61] Corrected event listener for canCastShadow - still bad. --- scripts/system/html/js/entityProperties.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 9502e9f4d4..8868159848 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1392,12 +1392,8 @@ function loaded() { elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); - if (properties.type === "Model" || - properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { - - elCanCastShadow.addEventListener('change', createEmitTextPropertyUpdateFunction('canCastShadow')); - } - + elCanCastShadow.addEventListener('change', createEmitCheckedPropertyUpdateFunction('canCastShadow')); + elImageURL.addEventListener('change', createImageURLUpdateFunction('textures')); elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); From 26e7a85a955db374b526f8a117585ff6c47ccbd2 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 21:15:29 -0800 Subject: [PATCH 13/61] Fixed possible crash. --- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index e34f550def..24a14a697c 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -386,6 +386,10 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon assert(lightStage); // Exit if current keylight does not cast shadows + if (!lightStage->getCurrentKeyLight()) { + return; + } + bool castShadows = lightStage->getCurrentKeyLight()->getCastShadows(); if (!castShadows) { output.edit0() = ItemFilter::Builder::nothing(); From adb02d69f9c50721d9e186870ae8ca6cf201a413 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 14 Feb 2018 21:45:56 -0800 Subject: [PATCH 14/61] WIP -adding canCastShadow flag. --- libraries/entities/src/EntityItemProperties.cpp | 5 +++++ libraries/entities/src/EntityItemProperties.h | 3 ++- .../entities/src/EntityItemPropertiesDefaults.h | 3 ++- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/ShapeEntityItem.h | 2 +- scripts/system/html/js/entityProperties.js | 16 ++++++++-------- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 79c36180d6..3c3c0742da 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -878,6 +878,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(angularVelocity); COPY_PROPERTY_IF_CHANGED(angularDamping); COPY_PROPERTY_IF_CHANGED(visible); + COPY_PROPERTY_IF_CHANGED(canCastShadow); COPY_PROPERTY_IF_CHANGED(color); COPY_PROPERTY_IF_CHANGED(colorSpread); COPY_PROPERTY_IF_CHANGED(colorStart); @@ -1050,6 +1051,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue std::call_once(initMap, [](){ ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool); + ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool); ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat); @@ -2172,6 +2174,9 @@ QList EntityItemProperties::listChangedProperties() { if (visibleChanged()) { out += "visible"; } + if (canCastShadowChanged()) { + out += "canCastShadow"; + } if (rotationChanged()) { out += "rotation"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index ec10910092..dcec1a1f81 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -128,7 +128,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT); DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP); DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL); - DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAST_SHADOW); + DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR); DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD); DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR); @@ -415,6 +415,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters"); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Name, name, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, CanCastShadow, canCastShadow, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, ""); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index f85d55dc3a..efbf45ce8d 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -46,7 +46,8 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0; const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; -const bool ENTITY_ITEM_DEFAULT_CAST_SHADOW { true }; +const bool ENTITY_ITEM_DEFAULT_CAST_SHADOWS { true }; +const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { false }; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 49f20c48e2..791eebb7d9 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -174,7 +174,7 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; - bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAST_SHADOW }; + bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; private: uint64_t _lastAnimated{ 0 }; diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 4a08936bce..4bc008f761 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -115,7 +115,7 @@ protected: //! ellipsoids. ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID }; - bool _canCastShadow { ENTITY_ITEM_DEFAULT_CAST_SHADOW }; + bool _canCastShadow { ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; }; #endif // hifi_ShapeEntityItem_h diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 8868159848..fca43c4665 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -802,11 +802,11 @@ function loaded() { // HTML workaround since image is not yet a separate entity type var IMAGE_MODEL_NAME = 'default-image-model.fbx'; - var urlParts = properties.modelURL.split('/') - var propsFilename = urlParts[urlParts.length - 1]; - if (properties.type === "Model" && propsFilename === IMAGE_MODEL_NAME) { - properties.type = "Image"; - } +//// var urlParts = properties.modelURL.split('/') +//// var propsFilename = urlParts[urlParts.length - 1]; +//// if (properties.type === "Model" && propsFilename === IMAGE_MODEL_NAME) { +//// properties.type = "Image"; +//// } // Create class name for css ruleset filtering elPropertiesList.className = properties.type + 'Menu'; @@ -983,11 +983,11 @@ function loaded() { properties.color.green + "," + properties.color.blue + ")"; } - if (properties.type === "Model" || - properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { + //if (properties.type === "Model" || + // properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { elCanCastShadow = properties.canCastShadow; - } + //} if (properties.type === "Model") { elModelURL.value = properties.modelURL; From 7e99570824418cc1a57b72cad44ddd8c386a1bff Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 15 Feb 2018 07:54:55 -0800 Subject: [PATCH 15/61] Fixed Ubuntu warnings. --- libraries/entities/src/ModelEntityItem.cpp | 1 - libraries/graphics/src/graphics/Light.cpp | 2 +- libraries/graphics/src/graphics/Light.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 7c14d8a4a0..b1edd47a67 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -619,7 +619,6 @@ void ModelEntityItem::setColor(const rgbColor& value) { }); } -#pragma optimize("", off) void ModelEntityItem::setColor(const xColor& value) { withWriteLock([&] { _color[RED_INDEX] = value.red; diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp index 50601299dd..76d8a6030a 100755 --- a/libraries/graphics/src/graphics/Light.cpp +++ b/libraries/graphics/src/graphics/Light.cpp @@ -69,7 +69,7 @@ void Light::setCastShadows(const bool castShadows) { _castShadows = castShadows; } -const bool Light::getCastShadows() const { +bool Light::getCastShadows() const { return _castShadows; } diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h index ebe22d5593..bb9fb3e5b9 100755 --- a/libraries/graphics/src/graphics/Light.h +++ b/libraries/graphics/src/graphics/Light.h @@ -104,7 +104,7 @@ public: const Vec3& getDirection() const; void setCastShadows(const bool castShadows); - const bool getCastShadows() const; + bool getCastShadows() const; void setOrientation(const Quat& orientation); const glm::quat& getOrientation() const { return _transform.getRotation(); } From 777862f253c32afcfa1bd0988a986da0d5b7c7da Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 15 Feb 2018 11:50:38 -0800 Subject: [PATCH 16/61] can cast shadow flag now works correctly (UI/JS aspects). --- libraries/entities/src/EntityItemProperties.cpp | 9 +++++++++ libraries/entities/src/EntityItemProperties.h | 2 +- scripts/system/html/js/entityProperties.js | 8 ++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 3c3c0742da..86404c6504 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1506,6 +1506,15 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape()); } + // Only models and shapes (including cubes and spheres) can cast shadows + if (properties.getType() == EntityTypes::Model || + properties.getType() == EntityTypes::Shape || + properties.getType() == EntityTypes::Box || + properties.getType() == EntityTypes::Sphere) { + + APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); + } + APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL()); APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData()); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index dcec1a1f81..349d32f806 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -113,6 +113,7 @@ public: // bool _fooChanged { false }; DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool, ENTITY_ITEM_DEFAULT_VISIBLE); + DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW); DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3, ENTITY_ITEM_DEFAULT_DIMENSIONS); DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat, ENTITY_ITEM_DEFAULT_ROTATION); @@ -128,7 +129,6 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT); DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP); DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL); - DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor, particle::DEFAULT_COLOR); DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, xColor, particle::DEFAULT_COLOR_SPREAD); DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, xColor, particle::DEFAULT_COLOR); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index fca43c4665..1b4df84f40 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -983,11 +983,11 @@ function loaded() { properties.color.green + "," + properties.color.blue + ")"; } - //if (properties.type === "Model" || - // properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { + if (properties.type === "Model" || + properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") { - elCanCastShadow = properties.canCastShadow; - //} + elCanCastShadow.checked = properties.canCastShadow; + } if (properties.type === "Model") { elModelURL.value = properties.modelURL; From df7a8389b3102c9c4dc4b0bb74168f97a16343ab Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 15 Feb 2018 11:51:06 -0800 Subject: [PATCH 17/61] Fixed possible crash. --- libraries/render-utils/src/RenderShadowTask.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 24a14a697c..7806c95330 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -121,8 +121,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con assert(lightStage); // Exit if current keylight does not cast shadows - bool castShadows = lightStage->getCurrentKeyLight()->getCastShadows(); - if (!castShadows) { + if (!lightStage->getCurrentKeyLight() || !lightStage->getCurrentKeyLight()->getCastShadows()) { return; } From 72e89851f3c2936bbf3da1f065fb3bc4fb4b919e Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 15 Feb 2018 14:16:56 -0800 Subject: [PATCH 18/61] Added READ_ENTITY_PROPERTY_TO_PROPERTIES --- libraries/entities/src/EntityItemProperties.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 86404c6504..78c6c6a6b3 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1869,6 +1869,14 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int properties.getType() == EntityTypes::Box || properties.getType() == EntityTypes::Sphere) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); + } + + // Can cast shadow flag + if (properties.getType() == EntityTypes::Model || + properties.getType() == EntityTypes::Shape || + properties.getType() == EntityTypes::Box || + properties.getType() == EntityTypes::Sphere) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); } From 194c7f41015575a91b4aa64f1775cc533689b5ec Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 16 Feb 2018 09:28:15 -0800 Subject: [PATCH 19/61] WIP - for review. --- interface/src/avatar/MyAvatar.cpp | 8 +-- interface/src/avatar/MyAvatar.h | 2 - .../src/RenderableEntityItem.h | 1 + .../src/RenderableModelEntityItem.cpp | 4 ++ .../render-utils/src/CauterizedModel.cpp | 5 +- .../render-utils/src/MeshPartPayload.cpp | 10 +++- libraries/render-utils/src/MeshPartPayload.h | 4 +- libraries/render-utils/src/Model.cpp | 55 ++++++++++++++----- libraries/render-utils/src/Model.h | 6 ++ 9 files changed, 67 insertions(+), 28 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c25aaeeecd..97b8c71a32 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1112,6 +1112,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { void MyAvatar::setEnableMeshVisible(bool isEnabled) { _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); + _skeletonModel->setCanCastShadow(true, qApp->getMain3DScene()); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -1464,6 +1465,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); + _skeletonModel->setCanCastShadow(true, qApp->getMain3DScene()); _headBoneSet.clear(); _cauterizationNeedsUpdate = true; @@ -1819,12 +1821,6 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved); } -void MyAvatar::setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visible) { - if (model->isActive() && model->isRenderable()) { - model->setVisibleInScene(visible, scene, render::ItemKey::TAG_BITS_NONE, true); - } -} - void MyAvatar::initHeadBones() { int neckJointIndex = -1; if (_skeletonModel->isLoaded()) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 28af8b62fd..a62bc1a109 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -677,8 +677,6 @@ private: // These are made private for MyAvatar so that you will use the "use" methods instead virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; - void setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visiblity); - virtual void updatePalms() override {} void lateUpdatePalms(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index f8685df5da..a9bb12d087 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -124,6 +124,7 @@ protected: bool _isFading{ _entitiesShouldFadeFunction() }; bool _prevIsTransparent { false }; bool _visible { false }; + bool _canCastShadow { false }; bool _cauterized { false }; bool _moving { false }; bool _needsRenderUpdate { false }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 56e3f96014..d3e1b62f5a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1356,6 +1356,10 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } // TODO? early exit here when not visible? + if (model->canCastShadow() != _canCastShadow) { + model->setCanCastShadow(_canCastShadow, scene); + } + if (_needsCollisionGeometryUpdate) { setCollisionMeshKey(entity->getCollisionMeshKey()); _needsCollisionGeometryUpdate = false; diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 54dfd96a00..74b278c2c1 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -204,6 +204,7 @@ void CauterizedModel::updateRenderItems() { bool isWireframe = self->isWireframe(); bool isVisible = self->isVisible(); + bool canCastShadow = self->canCastShadow(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); bool enableCauterization = self->getEnableCauterization(); @@ -219,7 +220,7 @@ void CauterizedModel::updateRenderItems() { bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); transaction.updateItem(itemID, [modelTransform, clusterTransforms, clusterTransformsCauterized, invalidatePayloadShapeKey, - isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) { + isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, canCastShadow, enableCauterization](CauterizedMeshPartPayload& data) { data.updateClusterBuffer(clusterTransforms, clusterTransformsCauterized); Transform renderTransform = modelTransform; @@ -249,7 +250,7 @@ void CauterizedModel::updateRenderItems() { data.updateTransformForCauterizedMesh(renderTransform); data.setEnableCauterization(enableCauterization); - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, render::ItemKey::TAG_BITS_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index da11535396..84f6c6aca3 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -71,7 +71,7 @@ void MeshPartPayload::updateMaterial(graphics::MaterialPointer drawMaterial) { _drawMaterial = drawMaterial; } -void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled) { +void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); @@ -85,6 +85,10 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, builder.withLayered(); } + if (canCastShadow) { + builder.withShadowCaster(); + } + if (isGroupCulled) { builder.withSubMetaCulled(); } @@ -421,6 +425,10 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tag builder.withLayered(); } + if (canCastShadow) { + builder.withShadowCaster(); + } + if (isGroupCulled) { builder.withSubMetaCulled(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 40efc67572..e7996e94dc 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -33,7 +33,7 @@ public: typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled = false); + virtual void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false); virtual void updateMeshPart(const std::shared_ptr& drawMesh, int partIndex); @@ -99,7 +99,7 @@ public: using TransformType = glm::mat4; #endif - void updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled = false) override; + void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false) override; void updateClusterBuffer(const std::vector& clusterTransforms); void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index bb8353c746..197008fc94 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -102,6 +102,7 @@ Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) : _snappedToRegistrationPoint(false), _url(HTTP_INVALID_COM), _isVisible(true), + _canCastShadow(false), _blendNumber(0), _appliedBlendNumber(0), _isWireframe(false) @@ -268,6 +269,7 @@ void Model::updateRenderItems() { bool isWireframe = self->isWireframe(); bool isVisible = self->isVisible(); + bool canCastShadow = self->canCastShadow(); uint8_t viewTagBits = self->getViewTagBits(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); @@ -284,7 +286,7 @@ void Model::updateRenderItems() { transaction.updateItem(itemID, [modelTransform, clusterTransforms, invalidatePayloadShapeKey, isWireframe, isVisible, - viewTagBits, isLayeredInFront, + canCastShadow, viewTagBits, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { data.updateClusterBuffer(clusterTransforms); @@ -301,7 +303,7 @@ void Model::updateRenderItems() { } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); @@ -693,46 +695,68 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, bool isLayeredInFront = _isLayeredInFront; bool isLayeredInHUD = _isLayeredInHUD; - + bool canCastShadow = _canCastShadow; render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); }); } scene->enqueueTransaction(transaction); } } +void Model::setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene) { + if (_canCastShadow != canCastShadow) { + _canCastShadow = canCastShadow; + + bool isVisible = _isVisible; + bool viewTagBits = _viewTagBits; + bool isLayeredInFront = _isLayeredInFront; + bool isLayeredInHUD = _isLayeredInHUD; + bool isGroupCulled = _isGroupCulled; + + render::Transaction transaction; + foreach (auto item, _modelMeshRenderItemsMap.keys()) { + transaction.updateItem(item, + [isVisible, viewTagBits, canCastShadow, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { + data.updateKey(isVisible, viewTagBits, canCastShadow, isLayeredInFront || isLayeredInHUD, isGroupCulled); + }); + } + + scene->enqueueTransaction(transaction); + } +} void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene) { if (_isLayeredInFront != isLayeredInFront) { _isLayeredInFront = isLayeredInFront; bool isVisible = _isVisible; + bool canCastShadow = _canCastShadow; uint8_t viewTagBits = _viewTagBits; bool isLayeredInHUD = _isLayeredInHUD; bool isGroupCulled = _isGroupCulled; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } @@ -745,22 +769,23 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce _isLayeredInHUD = isLayeredInHUD; bool isVisible = _isVisible; + bool canCastShadow = _canCastShadow; uint8_t viewTagBits = _viewTagBits; bool isLayeredInFront = _isLayeredInFront; bool isGroupCulled = _isGroupCulled; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, + transaction.updateItem(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); + data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 57d2798a66..c0d2c32f8f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -87,6 +87,10 @@ public: // new Scene/Engine rendering support void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled); + + bool canCastShadow() const { return _canCastShadow; } + void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene); + void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); bool needsFixupInScene() const; @@ -401,6 +405,8 @@ protected: bool _isVisible; uint8_t _viewTagBits{ render::ItemKey::TAG_BITS_ALL }; + bool _canCastShadow; + gpu::Buffers _blendedVertexBuffers; QVector > > _dilatedTextures; From 47924a58f9732e62ef79efa065bd944781193ebd Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 16 Feb 2018 10:14:46 -0800 Subject: [PATCH 20/61] WIP - for review. --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 84f6c6aca3..178f5782dd 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -411,7 +411,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled) { +void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); From 4c1f22f84e62213b3de4e7cb658a0473809a37d3 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 16 Feb 2018 14:01:33 -0800 Subject: [PATCH 21/61] Models and Avatar cast shadows (box doesn't, yet). --- interface/src/avatar/MyAvatar.cpp | 5 +++- .../src/RenderableEntityItem.cpp | 1 + libraries/entities/src/EntityItem.cpp | 28 +++++++++++++++++++ libraries/entities/src/EntityItem.h | 5 ++++ libraries/entities/src/ModelEntityItem.cpp | 28 ------------------- libraries/entities/src/ModelEntityItem.h | 5 ---- .../render-utils/src/MeshPartPayload.cpp | 2 +- 7 files changed, 39 insertions(+), 35 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 97b8c71a32..c70dc9df98 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1112,7 +1112,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { void MyAvatar::setEnableMeshVisible(bool isEnabled) { _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); - _skeletonModel->setCanCastShadow(true, qApp->getMain3DScene()); + _skeletonModel->setCanCastShadow(isEnabled, qApp->getMain3DScene()); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -2010,8 +2010,11 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 || _attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) { + _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); + + _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene()); } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index aca2f4d35b..7f2f57d1ac 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -371,6 +371,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); + _canCastShadow = entity->getCanCastShadow(); _cauterized = entity->getCauterized(); _needsRenderUpdate = false; }); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ed13a46414..e14d0b6757 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -99,6 +99,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_REGISTRATION_POINT; requestedProperties += PROP_ANGULAR_DAMPING; requestedProperties += PROP_VISIBLE; + requestedProperties += PROP_CAN_CAST_SHADOW; requestedProperties += PROP_COLLISIONLESS; requestedProperties += PROP_COLLISION_MASK; requestedProperties += PROP_DYNAMIC; @@ -257,6 +258,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible()); + APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, getCollisionless()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, getCollisionMask()); APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, getDynamic()); @@ -807,6 +809,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, setAngularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); + READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless); READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask); READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic); @@ -900,6 +903,7 @@ void EntityItem::debugDump() const { qCDebug(entities, " edited ago:%f", (double)getEditedAgo()); qCDebug(entities, " position:%f,%f,%f", (double)position.x, (double)position.y, (double)position.z); qCDebug(entities) << " dimensions:" << getScaledDimensions(); + qCDebug(entities) << " can cast shadow" << getCanCastShadow(); } // adjust any internal timestamps to fix clock skew for this server @@ -1242,6 +1246,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping); COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionless, getCollisionless); COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionMask, getCollisionMask); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dynamic, getDynamic); @@ -1354,6 +1359,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); // Certifiable Properties @@ -2731,6 +2737,28 @@ void EntityItem::setVisible(bool value) { } } +bool EntityItem::getCanCastShadow() const { + bool result; + withReadLock([&] { + result = _canCastShadow; + }); + return result; +} + +void EntityItem::setCanCastShadow(bool value) { + bool changed = false; + withWriteLock([&] { + if (_canCastShadow != value) { + changed = true; + _canCastShadow = value; + } + }); + + if (changed) { + emit requestRenderUpdate(); + } +} + bool EntityItem::isChildOfMyAvatar() const { QUuid ancestorID = findAncestorOfType(NestableType::Avatar); return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f84bcc311..19a1a9c88e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -273,6 +273,10 @@ public: bool getVisible() const; void setVisible(bool value); + + bool getCanCastShadow() const; + void setCanCastShadow(bool value); + inline bool isVisible() const { return getVisible(); } inline bool isInvisible() const { return !getVisible(); } @@ -543,6 +547,7 @@ protected: glm::vec3 _registrationPoint { ENTITY_ITEM_DEFAULT_REGISTRATION_POINT }; float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING }; bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE }; + bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS }; uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; bool _dynamic { ENTITY_ITEM_DEFAULT_DYNAMIC }; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b1edd47a67..a4fe8e6b1e 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -54,7 +54,6 @@ void ModelEntityItem::setTextures(const QString& textures) { EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); @@ -74,7 +73,6 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); @@ -116,7 +114,6 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, const unsigned char* dataAt = data; bool animationPropertiesChanged = false; - READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); @@ -153,7 +150,6 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - requestedProperties += PROP_CAN_CAST_SHADOW; requestedProperties += PROP_MODEL_URL; requestedProperties += PROP_COMPOUND_SHAPE_URL; requestedProperties += PROP_TEXTURES; @@ -178,7 +174,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); @@ -295,7 +290,6 @@ void ModelEntityItem::updateFrameCount() { } void ModelEntityItem::debugDump() const { - qCDebug(entities) << " can cast shadow" << getCanCastShadow(); qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); qCDebug(entities) << " position:" << getWorldPosition(); @@ -728,25 +722,3 @@ bool ModelEntityItem::isAnimatingSomething() const { (_animationProperties.getFPS() != 0.0f); }); } - -bool ModelEntityItem::getCanCastShadow() const { - bool result; - withReadLock([&] { - result = _canCastShadow; - }); - return result; -} - -void ModelEntityItem::setCanCastShadow(bool value) { - bool changed = false; - withWriteLock([&] { - if (_canCastShadow != value) { - changed = true; - _canCastShadow = value; - } - }); - - if (changed) { - emit requestRenderUpdate(); - } -} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 791eebb7d9..c2109ba51f 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -131,9 +131,6 @@ public: QVector getJointTranslations() const; QVector getJointTranslationsSet() const; - bool getCanCastShadow() const; - void setCanCastShadow(bool value); - private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; @@ -174,8 +171,6 @@ protected: ShapeType _shapeType = SHAPE_TYPE_NONE; - bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; - private: uint64_t _lastAnimated{ 0 }; AnimationPropertyGroup _previousAnimationProperties; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 84f6c6aca3..178f5782dd 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -411,7 +411,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled) { +void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); From dc3b03c9bcbd3df163cacfabdb6701a2dad3055b Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 16 Feb 2018 18:37:47 -0800 Subject: [PATCH 22/61] Added shadows to shapes - still sucks... --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 4 ++-- libraries/render/src/render/Item.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 7f2f57d1ac..1318f221c9 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -159,10 +159,10 @@ Item::Bound EntityRenderer::getBound() { ItemKey EntityRenderer::getKey() { if (isTransparent()) { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withNoShadowCaster(); } - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster(); } uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index e4dcc7ee03..bd7daa228e 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -123,6 +123,7 @@ public: Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } + Builder& withNoShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } Builder& withSubMetaCulled() { _flags.set(SUB_META_CULLED); return (*this); } From 7ba8a9935a5d18c2448e203c3556f1bd59ddbab2 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Fri, 16 Feb 2018 19:23:31 -0800 Subject: [PATCH 23/61] No extraneous shadows. --- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 178f5782dd..293150d552 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -87,6 +87,8 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShad if (canCastShadow) { builder.withShadowCaster(); + } else { + builder.withNoShadowCaster(); } if (isGroupCulled) { @@ -427,6 +429,8 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCas if (canCastShadow) { builder.withShadowCaster(); + } else { + builder.withNoShadowCaster(); } if (isGroupCulled) { From a69816f885146389750438f8a69caad5c62d297e Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Sat, 17 Feb 2018 15:21:57 -0800 Subject: [PATCH 24/61] WIP. --- libraries/entities/src/EntityItem.cpp | 1 - .../entities/src/EntityItemProperties.cpp | 36 ++++++++----------- .../src/EntityItemPropertiesDefaults.h | 4 +-- libraries/entities/src/EntityPropertyFlags.h | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 27 -------------- libraries/entities/src/ShapeEntityItem.h | 3 -- 6 files changed, 18 insertions(+), 55 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e14d0b6757..3b118a1376 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -903,7 +903,6 @@ void EntityItem::debugDump() const { qCDebug(entities, " edited ago:%f", (double)getEditedAgo()); qCDebug(entities, " position:%f,%f,%f", (double)position.x, (double)position.y, (double)position.z); qCDebug(entities) << " dimensions:" << getScaledDimensions(); - qCDebug(entities) << " can cast shadow" << getCanCastShadow(); } // adjust any internal timestamps to fix clock skew for this server diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 78c6c6a6b3..60f0034d81 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -458,6 +458,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_VELOCITY, angularVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISIONLESS, collisionless); COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_COLLISIONLESS, collisionless, ignoreForCollisions, getCollisionless()); // legacy support COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_MASK, collisionMask); @@ -626,10 +627,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); } - // Models and Shapes - if (_type == EntityTypes::Model || _type == EntityTypes::Shape || _type == EntityTypes::Box || _type == EntityTypes::Sphere) { - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); - } + ////// Models and Shapes + ////if (_type == EntityTypes::Model || _type == EntityTypes::Shape || _type == EntityTypes::Box || _type == EntityTypes::Sphere) { + //// COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow); + ////} if (!skipDefaults && !strictSemantics) { AABox aaBox = getAABox(); @@ -1364,6 +1365,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, properties.getAngularDamping()); APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible()); + APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, properties.getCollisionless()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, properties.getCollisionMask()); APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, properties.getDynamic()); @@ -1506,14 +1508,14 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape()); } - // Only models and shapes (including cubes and spheres) can cast shadows - if (properties.getType() == EntityTypes::Model || - properties.getType() == EntityTypes::Shape || - properties.getType() == EntityTypes::Box || - properties.getType() == EntityTypes::Sphere) { - - APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); - } + ////// Only models and shapes (including cubes and spheres) can cast shadows + ////if (properties.getType() == EntityTypes::Model || + //// properties.getType() == EntityTypes::Shape || + //// properties.getType() == EntityTypes::Box || + //// properties.getType() == EntityTypes::Sphere) { + //// + //// APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); + ////} APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL()); @@ -1734,6 +1736,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic); @@ -1871,15 +1874,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); } - // Can cast shadow flag - if (properties.getType() == EntityTypes::Model || - properties.getType() == EntityTypes::Shape || - properties.getType() == EntityTypes::Box || - properties.getType() == EntityTypes::Sphere) { - - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); - } - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACTION_DATA, QByteArray, setActionData); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index efbf45ce8d..7a8db2591f 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -46,8 +46,8 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0; const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; -const bool ENTITY_ITEM_DEFAULT_CAST_SHADOWS { true }; -const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { false }; +const bool ENTITY_ITEM_DEFAULT_CAST_SHADOWS { false }; +const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true }; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index ab17f2a873..3f542adfc2 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -20,6 +20,7 @@ enum EntityPropertyList { // these properties are supported by the EntityItem base class PROP_VISIBLE, + PROP_CAN_CAST_SHADOW, PROP_POSITION, PROP_DIMENSIONS, PROP_ROTATION, @@ -31,7 +32,6 @@ enum EntityPropertyList { PROP_SCRIPT, // these properties are supported by some derived classes - PROP_CAN_CAST_SHADOW, PROP_COLOR, // these are used by models only diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 9d81e850df..10588aa643 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -91,7 +91,6 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class properties.setColor(getXColor()); properties.setShape(entity::stringFromShape(getShape())); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); return properties; } @@ -131,7 +130,6 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow); if (somethingChanged) { bool wantDebug = false; @@ -157,7 +155,6 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape); READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); - READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); return bytesRead; } @@ -169,7 +166,6 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_SHAPE; requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; - requestedProperties += PROP_CAN_CAST_SHADOW; return requestedProperties; } @@ -186,7 +182,6 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); - APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); } void ShapeEntityItem::setColor(const rgbColor& value) { @@ -369,25 +364,3 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType ShapeEntityItem::getShapeType() const { return _collisionShapeType; } - -bool ShapeEntityItem::getCanCastShadow() const { - bool result; - withReadLock([&] { - result = _canCastShadow; - }); - return result; -} - -void ShapeEntityItem::setCanCastShadow(bool value) { - bool changed = false; - withWriteLock([&] { - if (_canCastShadow != value) { - changed = true; - _canCastShadow = value; - } - }); - - if (changed) { - emit requestRenderUpdate(); - } -} diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 4bc008f761..f5677830c7 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -101,9 +101,6 @@ public: virtual void computeShapeInfo(ShapeInfo& info) override; virtual ShapeType getShapeType() const override; - bool getCanCastShadow() const; - void setCanCastShadow(bool value); - protected: float _alpha { 1 }; From 3027d3461e446eca1901527206cdc064dd8efca8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 17 Feb 2018 15:24:50 -0800 Subject: [PATCH 25/61] Qt 5.10 seems to indicate pendingDatagramSizes of 0. Reading from these would block and causes an QAbstractSocket::TemporaryError to be thrown --- libraries/networking/src/udt/Socket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 55643985c8..f705854bda 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -328,14 +328,14 @@ void Socket::checkForReadyReadBackup() { void Socket::readPendingDatagrams() { int packetSizeWithHeader = -1; - while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) != -1) { + while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) > 0) { // we're reading a packet so re-start the readyRead backup timer _readyReadBackupTimer->start(); // grab a time point we can mark as the receive time of this packet auto receiveTime = p_high_resolution_clock::now(); - + // setup a HifiSockAddr to read into HifiSockAddr senderSockAddr; From 0a92596452250881bec62a2faf9785603db6bf89 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 18 Feb 2018 10:04:22 -0800 Subject: [PATCH 26/61] don't rely on return value of pendingDatagramSize() when hasPendingDatagrams() is false --- libraries/networking/src/udt/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index f705854bda..af9ff76eb3 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -328,7 +328,7 @@ void Socket::checkForReadyReadBackup() { void Socket::readPendingDatagrams() { int packetSizeWithHeader = -1; - while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) > 0) { + while (_udpSocket.hasPendingDatagrams() && (packetSizeWithHeader = _udpSocket.pendingDatagramSize()) != -1) { // we're reading a packet so re-start the readyRead backup timer _readyReadBackupTimer->start(); From 81c9e449e69248b7e6369d7681a41778774c8fa1 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Sun, 18 Feb 2018 10:19:17 -0800 Subject: [PATCH 27/61] Models casting shadows (again). (Something stupid happened...) --- libraries/entities/src/ShapeEntityItem.cpp | 1 - libraries/render/src/render/Item.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 10588aa643..c9ba96d06d 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -261,7 +261,6 @@ void ShapeEntityItem::debugDump() const { qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; - qCDebug(entities) << " can cast shadow" << getCanCastShadow(); } void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index bd7daa228e..25c1244990 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -123,7 +123,7 @@ public: Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } - Builder& withNoShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } + Builder& withNoShadowCaster() { _flags.reset(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } Builder& withSubMetaCulled() { _flags.set(SUB_META_CULLED); return (*this); } From 6a9bbaf0a55175d3886d4a73c1f210c4909f613e Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 19 Feb 2018 12:00:30 -0800 Subject: [PATCH 28/61] WIP - clean-up. --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.cpp | 5 +---- libraries/render-utils/src/RenderShadowTask.cpp | 3 +++ libraries/render/src/render/Item.h | 2 -- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 1318f221c9..b1251a2530 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -159,7 +159,7 @@ Item::Bound EntityRenderer::getBound() { ItemKey EntityRenderer::getKey() { if (isTransparent()) { - return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withNoShadowCaster(); + return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster(); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 293150d552..16eca007af 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -87,8 +87,6 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShad if (canCastShadow) { builder.withShadowCaster(); - } else { - builder.withNoShadowCaster(); } if (isGroupCulled) { @@ -413,6 +411,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } +// Note that this method is called for models but not for shapes void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) { ItemKey::Builder builder; builder.withTypeShape(); @@ -429,8 +428,6 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCas if (canCastShadow) { builder.withShadowCaster(); - } else { - builder.withNoShadowCaster(); } if (isGroupCulled) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 7806c95330..be84482c63 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -223,7 +223,10 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto setupOutput = task.addJob("ShadowSetup"); const auto queryResolution = setupOutput.getN(2); // Fetch and cull the items from the scene + + // Enable models to not cast shadows (otherwise, models will always cast shadows) static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster(); + const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying(); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 25c1244990..f6cd6a19e1 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -123,7 +123,6 @@ public: Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } - Builder& withNoShadowCaster() { _flags.reset(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } Builder& withSubMetaCulled() { _flags.set(SUB_META_CULLED); return (*this); } @@ -227,7 +226,6 @@ public: Builder& withVisible() { _value.reset(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } Builder& withInvisible() { _value.set(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); } - Builder& withNoShadowCaster() { _value.reset(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); } Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } From 992121780703dd586bf97ee74ffaf01f086a2aa1 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Mon, 19 Feb 2018 12:32:11 -0800 Subject: [PATCH 29/61] Shapes casting shadows OK. --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b1251a2530..6483a7e891 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -162,7 +162,12 @@ ItemKey EntityRenderer::getKey() { return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster(); + // This allows shapes to cast shadows + if (_canCastShadow) { + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster(); + } else { + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + } } uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) { From 5cd184ddc3d5403eca4bea7a70f830c2f7ef381e Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Tue, 20 Feb 2018 17:55:30 -0800 Subject: [PATCH 30/61] change default add to world shape for asset browser --- interface/resources/qml/hifi/AssetServer.qml | 2 +- interface/resources/qml/hifi/dialogs/TabletAssetServer.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index dd0aba9ec5..fea275999e 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -206,7 +206,7 @@ Windows.ScrollingWindow { SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; - var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; + var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_SIMPLE_COMPOUND; var DYNAMIC_DEFAULT = false; var prompt = desktop.customInputDialog({ textInput: { diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index 049a7faad8..c5f85e885c 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -207,7 +207,7 @@ Rectangle { SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; - var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; + var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_SIMPLE_COMPOUND; var DYNAMIC_DEFAULT = false; var prompt = tabletRoot.customInputDialog({ textInput: { From 6f84e4c9772627dbb1c511896f571977c8886d6f Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Tue, 20 Feb 2018 23:45:07 -0800 Subject: [PATCH 31/61] Moved shadows and ambient occlusion to menu checkboxes. --- .../dialogs/GraphicsPreferencesDialog.qml | 19 ---------- .../hifi/tablet/TabletGraphicsPreferences.qml | 37 ------------------- interface/src/Menu.cpp | 14 +++++-- interface/src/Menu.h | 2 + .../src/DeferredLightingEffect.cpp | 2 +- 5 files changed, 13 insertions(+), 61 deletions(-) delete mode 100644 interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml delete mode 100644 interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml diff --git a/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml deleted file mode 100644 index d95bafd0a9..0000000000 --- a/interface/resources/qml/hifi/dialogs/GraphicsPreferencesDialog.qml +++ /dev/null @@ -1,19 +0,0 @@ -import QtQuick 2.5 -import Qt.labs.settings 1.0 - -import "../../dialogs" - -PreferencesDialog { - id: root - objectName: "GraphicsPreferencesDialog" - title: "Graphics Settings" - showCategories: ["Graphics"] - property var settings: Settings { - category: root.objectName - property alias x: root.x - property alias y: root.y - property alias width: root.width - property alias height: root.height - } -} - diff --git a/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml deleted file mode 100644 index 25b5be05f2..0000000000 --- a/interface/resources/qml/hifi/tablet/TabletGraphicsPreferences.qml +++ /dev/null @@ -1,37 +0,0 @@ -// -// TabletGraphicsPreferences.qml -// -// Created by Vlad Stelmahovsky on 12 Mar 2017. -// Copyright 2017 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 -// - -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import "tabletWindows" -import "../../dialogs" - -StackView { - id: profileRoot - initialItem: root - objectName: "stack" - property string title: "Graphics Settings" - - signal sendToScript(var message); - - function pushSource(path) { - profileRoot.push(Qt.resolvedUrl(path)); - } - - function popSource() { - profileRoot.pop(); - } - - TabletPreferencesDialog { - id: root - objectName: "TabletGraphicsPreferences" - showCategories: ["Graphics"] - } -} diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f3d8ea2344..051d5ce8ec 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -44,6 +44,7 @@ #include "ui/StandAloneJSConsole.h" #include "InterfaceLogging.h" #include "LocationBookmarks.h" +#include "DeferredLightingEffect.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" @@ -365,10 +366,15 @@ Menu::Menu() { MenuWrapper* developerMenu = addMenu("Developer", "Developer"); // Developer > Graphics... - action = addActionToQMenuAndActionHash(developerMenu, "Graphics..."); - connect(action, &QAction::triggered, [] { - qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"), - QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog"); + MenuWrapper* graphicsOptionsMenu = developerMenu->addMenu("Render"); + action = addCheckableActionToQMenuAndActionHash(graphicsOptionsMenu, MenuOption::Shadows, 0, true); + connect(action, &QAction::triggered, [action] { + DependencyManager::get()->setShadowMapEnabled(action->isChecked()); + }); + + action = addCheckableActionToQMenuAndActionHash(graphicsOptionsMenu, MenuOption::AmbientOcclusion, 0, false); + connect(action, &QAction::triggered, [action] { + DependencyManager::get()->setAmbientOcclusionEnabled(action->isChecked()); }); // Developer > UI >>> diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8cb1804fd4..ec6fa42818 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -204,6 +204,8 @@ namespace MenuOption { const QString WorldAxes = "World Axes"; const QString DesktopTabletToToolbar = "Desktop Tablet Becomes Toolbar"; const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar"; + const QString Shadows = "Shadows"; + const QString AmbientOcclusion = "AmbientOcclusion"; } #endif // hifi_Menu_h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 665e767c7c..78bc3ba195 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -492,7 +492,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture()); // FIXME: Different render modes should have different tasks - if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled()) { + if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled() && ambientOcclusionFramebuffer) { batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, ambientOcclusionFramebuffer->getOcclusionTexture()); } else { // need to assign the white texture if ao is off From 47a98d9d0f49dd2621102c34475bae4112d50419 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 21 Feb 2018 10:12:04 -0800 Subject: [PATCH 32/61] relax the deadlock time to 2 minutes --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3aa0f3d889..2b87456459 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -392,7 +392,7 @@ const QHash Application::_acceptedExtensi class DeadlockWatchdogThread : public QThread { public: static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1; - static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND; + static const unsigned long MAX_HEARTBEAT_AGE_USECS = 120 * USECS_PER_SECOND; // 2 mins with no checkin probably a deadlock static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples From bf4ba07b722fb4e2f1990e7a445794f828037d97 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 21 Feb 2018 12:36:34 -0800 Subject: [PATCH 33/61] Added parameters to canCastShadow - still sucks. --- interface/src/avatar/MyAvatar.cpp | 6 +++--- .../entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- libraries/render-utils/src/Model.cpp | 4 +--- libraries/render-utils/src/Model.h | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c70dc9df98..2a2e4a1199 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1112,7 +1112,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) { void MyAvatar::setEnableMeshVisible(bool isEnabled) { _skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); - _skeletonModel->setCanCastShadow(isEnabled, qApp->getMain3DScene()); + _skeletonModel->setCanCastShadow(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); } void MyAvatar::setEnableInverseKinematics(bool isEnabled) { @@ -1465,7 +1465,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); - _skeletonModel->setCanCastShadow(true, qApp->getMain3DScene()); + _skeletonModel->setCanCastShadow(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); _headBoneSet.clear(); _cauterizationNeedsUpdate = true; @@ -2014,7 +2014,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { _attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); - _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene()); + _attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true); } } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 9dfa7d4796..1a7af15374 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1357,7 +1357,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // TODO? early exit here when not visible? if (model->canCastShadow() != _canCastShadow) { - model->setCanCastShadow(_canCastShadow, scene); + model->setCanCastShadow(_canCastShadow, scene, viewTaskBits, false); } if (_needsCollisionGeometryUpdate) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 11955c4be5..386f890153 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -713,15 +713,13 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene, } } -void Model::setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene) { +void Model::setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled) { if (_canCastShadow != canCastShadow) { _canCastShadow = canCastShadow; bool isVisible = _isVisible; - bool viewTagBits = _viewTagBits; bool isLayeredInFront = _isLayeredInFront; bool isLayeredInHUD = _isLayeredInHUD; - bool isGroupCulled = _isGroupCulled; render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b7015b8732..f301dd8031 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -89,7 +89,7 @@ public: void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled); bool canCastShadow() const { return _canCastShadow; } - void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene); + void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled); void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); From 049beba1572638b2b45695dfee3a3e5c5f2b8c86 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 21 Feb 2018 14:15:41 -0800 Subject: [PATCH 34/61] Corrected edge case of creating a snapshot with "" as the filename. --- interface/src/Application.h | 3 +-- interface/src/scripting/WindowScriptingInterface.h | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index d4041aa3be..784b509c1a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -266,9 +266,8 @@ public: float getGameLoopRate() const { return _gameLoopCounter.rate(); } - // Note that takeSnapshot has a default value, as this method is used internally. void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString()); - void takeSecondaryCameraSnapshot(const QString& filename); + void takeSecondaryCameraSnapshot(const QString& filename = QString()); void shareSnapshot(const QString& filename, const QUrl& href = QUrl("")); diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 76decf4362..196863e362 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -334,8 +334,8 @@ public slots: * @param {number} aspectRatio=0 - The width/height ratio of the snapshot required. If the value is 0 the * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. - * @param {string} filename=QString() - If this value is not null then the image will be saved to this filename, with an appended ",jpg". - * otherwise, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS' + * @param {string} filename="" - If this value is not given, or is "" then the image will be saved to this filename, with an appended ",jpg". + * otherwise, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. * @example Using the snapshot function and signals. * function onStillSnapshotTaken(path, notify) { * print("Still snapshot taken: " + path); @@ -357,7 +357,7 @@ public slots: * var notify = true; * var animated = true; * var aspect = 1920 / 1080; - * var filename = QString(); + * var filename = ""; * Window.takeSnapshot(notify, animated, aspect, filename); */ void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString()); @@ -365,7 +365,7 @@ public slots: /**jsdoc * Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API. * @function Window.takeSecondaryCameraSnapshot - * @param {string} filename=QString() - If this value is not null then the image will be saved to this filename, with an appended ".jpg" + * @param {string} filename="" - If this value is not given, or is "" then the image will be saved to this filename, with an appended ".jpg". * * var filename = QString(); */ From 4b1217f1f6b4768386b8b9f7ab09a2efb31b5d8a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 21 Feb 2018 15:25:18 -0800 Subject: [PATCH 35/61] move all entity items to main thread --- interface/src/octree/OctreePacketProcessor.cpp | 2 ++ libraries/entities/src/EntityTypes.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index c792834d9c..122b58c057 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -17,6 +17,8 @@ #include "SceneScriptingInterface.h" OctreePacketProcessor::OctreePacketProcessor() { + setObjectName("Octree Packet Processor"); + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerDirectListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 307371c649..694542b04e 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -97,6 +97,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const auto mutableProperties = properties; mutableProperties.markAllChanged(); newEntityItem = factory(entityID, mutableProperties); + newEntityItem->moveToThread(qApp->thread()); } return newEntityItem; } From a843a534277cdc3d2885bb5531d93a8e93bb3143 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 22 Feb 2018 10:17:20 -0800 Subject: [PATCH 36/61] Improved JSDoc comments. --- interface/src/scripting/WindowScriptingInterface.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 196863e362..9d773b8a2f 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -325,6 +325,7 @@ public slots: * {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured, * {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted} * are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings > + * NOTE: to provide a non-default value - all previous parameters must be provided. * General > Snapshots. * @function Window.takeSnapshot * @param {boolean} notify=true - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} @@ -334,8 +335,10 @@ public slots: * @param {number} aspectRatio=0 - The width/height ratio of the snapshot required. If the value is 0 the * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. - * @param {string} filename="" - If this value is not given, or is "" then the image will be saved to this filename, with an appended ",jpg". - * otherwise, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. + * @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. + * If this parameter is "" then the image will be saved as ".jpg". + * Otherwise, the image will be saved to this filename, with an appended ".jpg". + * * @example Using the snapshot function and signals. * function onStillSnapshotTaken(path, notify) { * print("Still snapshot taken: " + path); @@ -364,8 +367,11 @@ public slots: /**jsdoc * Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API. + * NOTE: to provide a non-default value - all previous parameters must be provided. * @function Window.takeSecondaryCameraSnapshot - * @param {string} filename="" - If this value is not given, or is "" then the image will be saved to this filename, with an appended ".jpg". + * @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by--YYYY-MM-DD_HH-MM-SS'. + * If this parameter is "" then the image will be saved as ".jpg". + * Otherwise, the image will be saved to this filename, with an appended ".jpg". * * var filename = QString(); */ From c15cf33ca1f9a5ec776838dd1c19c976a57319c0 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Fri, 23 Feb 2018 00:36:00 +0300 Subject: [PATCH 37/61] 12518 - Help icon in toolbar does not highlight when help window is open --- scripts/system/help.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/help.js b/scripts/system/help.js index 494b0a2cdb..cae5a11d79 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -15,6 +15,7 @@ (function() { // BEGIN LOCAL_SCOPE var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; + var HELP_URL = Script.resourcesPath() + "html/tabletHelp.html"; var buttonName = "HELP"; var onHelpScreen = false; var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); @@ -40,7 +41,7 @@ } function onScreenChanged(type, url) { - onHelpScreen = type === "Web" && url.startsWith("../../../html/tabletHelp.html"); + onHelpScreen = type === "Web" && url.startsWith(HELP_URL); button.editProperties({ isActive: onHelpScreen }); } From 4d2d7fa51f5d8cd37d43ff5f245cf03cb41af110 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 13:56:46 -0800 Subject: [PATCH 38/61] lots of fun initial progress! --- interface/resources/fonts/hifi-glyphs.ttf | Bin 32536 -> 32544 bytes .../qml/hifi/commerce/checkout/Checkout.qml | 8 +- .../hifi/commerce/purchases/PurchasedItem.qml | 3 + interface/src/commerce/QmlCommerce.cpp | 99 ++++++++++++++++++ interface/src/commerce/QmlCommerce.h | 8 +- scripts/system/marketplaces/marketplaces.js | 10 +- 6 files changed, 120 insertions(+), 8 deletions(-) diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index 8db0377f88864810e7f893132449ad8e258e68cd..7f7393da1811f3933a2d9c0deabfdbc245a25b47 100644 GIT binary patch delta 216 zcmbR7k8#02Mhyl=1_lORh6V;^h5$FW5Z}t>Df<{0>RA{V7-ZaCT-_M6H9y?UR&-AV_+!z!N9<{xgfu| zq-^uwW(J0eH4F@F`e2I~85p9{zJ$f|+k9ob(8U_Y7h((MH4DuVzTjTj{zA|t#F@V6e#qS@(=uM1=N;&5$a&vHUo3S!) qK3!(X$ZW`9FqyqVkIB$rvw6i-HV*d8yyB9?oSeyb>MXgD^a23O9zII| diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index ab47bb28ad..98f26887ae 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -146,7 +146,8 @@ Rectangle { } onItemTypeChanged: { - if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "avatar") { + if (root.itemType === "entity" || root.itemType === "wearable" || + root.itemType === "contentSet" || root.itemType === "avatar" || root.itemType === "app") { root.isCertified = true; } else { root.isCertified = false; @@ -679,7 +680,7 @@ Rectangle { id: rezNowButton; enabled: (root.itemType === "entity" && root.canRezCertifiedItems) || (root.itemType === "contentSet" && Entities.canReplaceContent()) || - root.itemType === "wearable" || root.itemType === "avatar"; + root.itemType === "wearable" || root.itemType === "avatar" || root.itemType === "app"; buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; color: hifi.buttons.red; colorScheme: hifi.colorSchemes.light; @@ -712,6 +713,9 @@ Rectangle { lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; + } else if (root.itemType === "app") { + // "Run" button is separate. + Commerce.installApp(root.itemHref); } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); rezzedNotifContainer.visible = true; diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index cc2bcd69aa..c96fc15f5c 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -506,6 +506,9 @@ Item { sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref}); } else if (root.itemType === "avatar") { sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref}); + } else if (root.itemType === "app") { + // "Run" and "Uninstall" buttons are separate. + Commerce.installApp(root.itemHref); } else { sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); root.showConfirmation = true; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 36c1e422c5..0b583e6153 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -10,6 +10,7 @@ // #include "QmlCommerce.h" +#include "CommerceLogging.h" #include "Application.h" #include "DependencyManager.h" #include "Ledger.h" @@ -17,6 +18,7 @@ #include #include #include +#include QmlCommerce::QmlCommerce() { auto ledger = DependencyManager::get(); @@ -183,3 +185,100 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) { auto ledger = DependencyManager::get(); ledger->alreadyOwned(marketplaceId); } + +static QString APP_PATH = PathUtils::getAppDataPath() + "apps"; +bool QmlCommerce::isAppInstalled(const QString& itemHref) { + QUrl appHref(itemHref); + + QFileInfo appFile(APP_PATH + "/" + appHref.fileName()); + if (appFile.exists() && appFile.isFile()) { + return true; + } else { + return false; + } +} + +bool QmlCommerce::installApp(const QString& itemHref) { + if (!QDir(APP_PATH).exists()) { + if (!QDir().mkdir(APP_PATH)) { + qCDebug(commerce) << "Couldn't make APP_PATH directory."; + return false; + } + } + + QUrl appHref(itemHref); + + auto request = + std::unique_ptr(DependencyManager::get()->createResourceRequest(this, appHref)); + + if (!request) { + qCDebug(commerce) << "Couldn't create resource request for app."; + return false; + } + + QEventLoop loop; + connect(request.get(), &ResourceRequest::finished, &loop, &QEventLoop::quit); + request->send(); + loop.exec(); + + if (request->getResult() != ResourceRequest::Success) { + qCDebug(commerce) << "Failed to get .app.json file from remote."; + return false; + } + + // Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface + auto requestData = request->getData(); + QFile appFile(APP_PATH + "/" + appHref.fileName()); + if (!appFile.open(QIODevice::WriteOnly)) { + qCDebug(commerce) << "Couldn't open local .app.json file for creation."; + return false; + } + if (appFile.write(requestData) == -1) { + qCDebug(commerce) << "Couldn't write to local .app.json file."; + return false; + } + // Close the file + appFile.close(); + + // Read from the returned datastream to know what .js to add to Running Scripts + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(requestData); + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString scriptUrl = appFileJsonObject["scriptURL"].toString(); + + if ((DependencyManager::get()->loadScript(scriptUrl.trimmed())).isNull()) { + qCDebug(commerce) << "Couldn't load script."; + return false; + } + + emit appInstalled(appHref.fileName()); + return true; +} + +bool QmlCommerce::uninstallApp(const QString& itemHref) { + QUrl appHref(itemHref); + + // Read from the file to know what .js script to stop + QFile appFile(APP_PATH + "/" + appHref.fileName()); + if (!appFile.open(QIODevice::ReadOnly)) { + qCDebug(commerce) << "Couldn't open local .app.json file for deletion."; + return false; + } + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString scriptUrl = appFileJsonObject["scriptURL"].toString(); + + if (!DependencyManager::get()->stopScript(scriptUrl.trimmed(), false)) { + qCDebug(commerce) << "Couldn't stop script."; + return false; + } + + // Delete the .app.json from the filesystem + // remove() closes the file first. + if (!appFile.remove()) { + qCDebug(commerce) << "Couldn't delete local .app.json file."; + return false; + } + + emit appUninstalled(appHref.fileName()); + return true; +} diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index b621608190..60e52a441b 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -51,6 +51,9 @@ signals: void contentSetChanged(const QString& contentSetHref); + void appInstalled(const QString& appFileName); + void appUninstalled(const QString& appFileName); + protected: Q_INVOKABLE void getWalletStatus(); @@ -76,8 +79,11 @@ protected: Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage); - Q_INVOKABLE void replaceContentSet(const QString& itemHref); + + Q_INVOKABLE bool isAppInstalled(const QString& itemHref); + Q_INVOKABLE bool installApp(const QString& itemHref); + Q_INVOKABLE bool uninstallApp(const QString& itemHref); }; #endif // hifi_QmlCommerce_h diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 631b5e97ac..ecd1bf2a6e 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -551,11 +551,11 @@ var selectionDisplay = null; // for gridTool.js to ignore break; case 'checkout_rezClicked': case 'purchases_rezClicked': - if (message.itemType === "app") { - console.log("How did you get here? You can't buy apps yet!"); - } else { - rezEntity(message.itemHref, message.itemType); - } + rezEntity(message.itemHref, message.itemType); + break; + case 'checkout_installClicked': + case 'purchases_installClicked': + break; case 'header_marketplaceImageClicked': case 'purchases_backClicked': From bb04f3f53328906baa542c16f8f6f9d1a22f249a Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 22 Feb 2018 13:57:46 -0800 Subject: [PATCH 39/61] CR corrections. --- .../entities/src/EntityItemProperties.cpp | 2 +- .../src/EntityItemPropertiesDefaults.h | 1 - libraries/entities/src/EntityPropertyFlags.h | 2 +- .../entities/src/KeyLightPropertyGroup.cpp | 19 +++++++++---------- .../entities/src/KeyLightPropertyGroup.h | 2 +- scripts/system/html/entityProperties.html | 8 ++++---- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0612810e1e..2eca612fc2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1192,7 +1192,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float); ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3); - ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOWS, KeyLightCastShadows, keyLightCastShadows, bool); + ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLightCastShadows, keyLightCastShadows, bool); ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 7a8db2591f..0e0c2994cd 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -46,7 +46,6 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0; const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const bool ENTITY_ITEM_DEFAULT_VISIBLE = true; -const bool ENTITY_ITEM_DEFAULT_CAST_SHADOWS { false }; const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true }; const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString(""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index b787b16fb9..07908fe6cf 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -209,7 +209,7 @@ enum EntityPropertyList { PROP_KEYLIGHT_COLOR, PROP_KEYLIGHT_INTENSITY, PROP_KEYLIGHT_DIRECTION, - PROP_KEYLIGHT_CAST_SHADOWS, + PROP_KEYLIGHT_CAST_SHADOW, PROP_HAZE_RANGE, PROP_HAZE_COLOR, diff --git a/libraries/entities/src/KeyLightPropertyGroup.cpp b/libraries/entities/src/KeyLightPropertyGroup.cpp index 70b9a5395a..b2c65c6f9d 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.cpp +++ b/libraries/entities/src/KeyLightPropertyGroup.cpp @@ -29,7 +29,7 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction); - COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOWS, KeyLight, keyLight, CastShadows, castShadows); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows); } void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { @@ -88,14 +88,13 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); - APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, getCastShadows()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows()); return true; } bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt, - int& processedBytes) -{ + int& processedBytes) { int bytesRead = 0; bool overwriteLocalData = true; @@ -104,12 +103,12 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); - READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, bool, setCastShadows); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOWS, CastShadows); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOW, CastShadows); processedBytes += bytesRead; @@ -131,7 +130,7 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction); - CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOWS, castShadows); + CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOW, castShadows); return changedProperties; } @@ -160,7 +159,7 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa requestedProperties += PROP_KEYLIGHT_COLOR; requestedProperties += PROP_KEYLIGHT_INTENSITY; requestedProperties += PROP_KEYLIGHT_DIRECTION; - requestedProperties += PROP_KEYLIGHT_CAST_SHADOWS; + requestedProperties += PROP_KEYLIGHT_CAST_SHADOW; return requestedProperties; } @@ -178,7 +177,7 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection()); - APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, getCastShadows()); + APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows()); } int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -192,7 +191,7 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection); - READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, bool, setCastShadows); + READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows); return bytesRead; } diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index d3c8597f95..5e13a6afa6 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -83,7 +83,7 @@ public: DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, xColor, DEFAULT_KEYLIGHT_COLOR); DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION); - DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOWS, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS); + DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS); }; #endif // hifi_KeyLightPropertyGroup_h diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 8c34d01358..d6710238fb 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -530,10 +530,10 @@
-
- - -
+
+ + +
Skybox From e9cad947d7f429be3a50e98c0acf5e0feeafd496 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 Feb 2018 14:01:56 -0800 Subject: [PATCH 40/61] add the deadlock watchdog stats to the stats metaverse checkin data --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2878515240..8c3e6f130d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1719,6 +1719,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection(); properties["hardware_stats"] = displayPlugin->getHardwareStats(); + // deadlock watchdog related stats + properties["deadlock_watchdog_maxElapsed"] = (int)DeadlockWatchdogThread::_maxElapsed; + properties["deadlock_watchdog_maxElapsedAverage"] = (int)DeadlockWatchdogThread::_maxElapsedAverage; + auto bandwidthRecorder = DependencyManager::get(); properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond(); properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond(); From de0eee52d6ccaa96d8db21f189d2f0028dd8d33d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 14:45:32 -0800 Subject: [PATCH 41/61] cool --- .../hifi/commerce/purchases/PurchasedItem.qml | 45 +++++++++++++ interface/src/commerce/QmlCommerce.cpp | 67 +++++++++++++++---- interface/src/commerce/QmlCommerce.h | 10 ++- 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index c96fc15f5c..76e2afd308 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -47,6 +47,7 @@ Item { property bool showConfirmation: false; property bool hasPermissionToRezThis; property bool permissionExplanationCardVisible; + property bool isInstalled: false; property string originalStatusText; property string originalStatusColor; @@ -62,6 +63,12 @@ Item { showConfirmation = true; } } + + onAppInstalled: { + if (appHref === root.itemHref) { + root.isInstalled = true; + } + } } Connections { @@ -81,6 +88,10 @@ Item { } else { root.hasPermissionToRezThis = true; } + + if (itemType === "app") { + root.isInstalled = Commerce.isAppInstalled(root.itemHref); + } } onPurchaseStatusChangedChanged: { @@ -472,6 +483,40 @@ Item { } } + Rectangle { + id: appButtonContainer; + color: hifi.colors.white; + z: 994; + visible: root.isInstalled; + anchors.fill: buttonContainer; + + HifiControlsUit.Button { + id: openAppButton; + color: hifi.buttons.blue; + colorScheme: hifi.colorSchemes.light; + anchors.top: parent.top; + anchors.right: parent.right; + height: 44; + text: "OPEN" + onClicked: { + Commerce.openApp(root.itemHref); + } + } + + HifiControlsUit.Button { + id: uninstallAppButton; + color: hifi.buttons.noneBorderless; + colorScheme: hifi.colorSchemes.light; + anchors.bottom: parent.bottom; + anchors.right: parent.right; + height: 44; + text: "UNINSTALL" + onClicked: { + Commerce.uninstallApp(root.itemHref); + } + } + } + Button { id: buttonContainer; property int color: hifi.buttons.blue; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 0b583e6153..f9bb0d2003 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include "scripting/HMDScriptingInterface.h" QmlCommerce::QmlCommerce() { auto ledger = DependencyManager::get(); @@ -42,6 +44,8 @@ QmlCommerce::QmlCommerce() { connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); }); + + _appsPath = PathUtils::getAppDataPath() + "Apps"; } void QmlCommerce::getWalletStatus() { @@ -186,22 +190,32 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) { ledger->alreadyOwned(marketplaceId); } -static QString APP_PATH = PathUtils::getAppDataPath() + "apps"; bool QmlCommerce::isAppInstalled(const QString& itemHref) { QUrl appHref(itemHref); - QFileInfo appFile(APP_PATH + "/" + appHref.fileName()); - if (appFile.exists() && appFile.isFile()) { - return true; - } else { + // First check if .app.json exists + QFileInfo appFile(_appsPath + "/" + appHref.fileName()); + if (!(appFile.exists() && appFile.isFile())) { return false; } + + // Then check to see if script is running + auto runningScripts = DependencyManager::get()->getRunningScripts(); + foreach(const QString& runningScript, runningScripts) { + QUrl runningScriptURL = QUrl(runningScript); + qCDebug(commerce) << "ZRF FIXME" << runningScriptURL; + if (runningScriptURL == appHref) { + return true; + } + } + + return false; } bool QmlCommerce::installApp(const QString& itemHref) { - if (!QDir(APP_PATH).exists()) { - if (!QDir().mkdir(APP_PATH)) { - qCDebug(commerce) << "Couldn't make APP_PATH directory."; + if (!QDir(_appsPath).exists()) { + if (!QDir().mkdir(_appsPath)) { + qCDebug(commerce) << "Couldn't make _appsPath directory."; return false; } } @@ -228,7 +242,7 @@ bool QmlCommerce::installApp(const QString& itemHref) { // Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface auto requestData = request->getData(); - QFile appFile(APP_PATH + "/" + appHref.fileName()); + QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::WriteOnly)) { qCDebug(commerce) << "Couldn't open local .app.json file for creation."; return false; @@ -250,7 +264,7 @@ bool QmlCommerce::installApp(const QString& itemHref) { return false; } - emit appInstalled(appHref.fileName()); + emit appInstalled(itemHref); return true; } @@ -258,7 +272,7 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { QUrl appHref(itemHref); // Read from the file to know what .js script to stop - QFile appFile(APP_PATH + "/" + appHref.fileName()); + QFile appFile(_appsPath + "/" + appHref.fileName()); if (!appFile.open(QIODevice::ReadOnly)) { qCDebug(commerce) << "Couldn't open local .app.json file for deletion."; return false; @@ -279,6 +293,35 @@ bool QmlCommerce::uninstallApp(const QString& itemHref) { return false; } - emit appUninstalled(appHref.fileName()); + emit appUninstalled(itemHref); + return true; +} + +bool QmlCommerce::openApp(const QString& itemHref) { + QUrl appHref(itemHref); + + // Read from the file to know what .html or .qml document to open + QFile appFile(_appsPath + "/" + appHref.fileName()); + if (!appFile.open(QIODevice::ReadOnly)) { + qCDebug(commerce) << "Couldn't open local .app.json file."; + return false; + } + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString homeUrl = appFileJsonObject["homeURL"].toString(); + + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + if (homeUrl.contains(".qml", Qt::CaseInsensitive)) { + tablet->loadQMLSource(homeUrl); + } else if (homeUrl.contains(".html", Qt::CaseInsensitive)) { + tablet->gotoWebScreen(homeUrl); + } else { + qCDebug(commerce) << "Attempted to open unknown type of homeURL!"; + return false; + } + + DependencyManager::get()->openTablet(); + return true; } diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 60e52a441b..e0c018878d 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -81,9 +81,13 @@ protected: Q_INVOKABLE void replaceContentSet(const QString& itemHref); - Q_INVOKABLE bool isAppInstalled(const QString& itemHref); - Q_INVOKABLE bool installApp(const QString& itemHref); - Q_INVOKABLE bool uninstallApp(const QString& itemHref); + Q_INVOKABLE bool isAppInstalled(const QString& appHref); + Q_INVOKABLE bool installApp(const QString& appHref); + Q_INVOKABLE bool uninstallApp(const QString& appHref); + Q_INVOKABLE bool openApp(const QString& appHref); + +private: + QString _appsPath; }; #endif // hifi_QmlCommerce_h From 10fa3fa346a2d8a54b650497f421200cdc4ada17 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 16:09:01 -0800 Subject: [PATCH 42/61] It's working! --- .../hifi/commerce/purchases/PurchasedItem.qml | 15 ++++--- .../qml/hifi/commerce/purchases/Purchases.qml | 12 +++++ interface/src/commerce/QmlCommerce.cpp | 44 ++++++++++++------- interface/src/commerce/QmlCommerce.h | 6 +-- scripts/system/commerce/wallet.js | 2 +- 5 files changed, 54 insertions(+), 25 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 76e2afd308..fb8e509cde 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -47,7 +47,7 @@ Item { property bool showConfirmation: false; property bool hasPermissionToRezThis; property bool permissionExplanationCardVisible; - property bool isInstalled: false; + property bool isInstalled; property string originalStatusText; property string originalStatusColor; @@ -69,6 +69,12 @@ Item { root.isInstalled = true; } } + + onAppUninstalled: { + if (appHref === root.itemHref) { + root.isInstalled = false; + } + } } Connections { @@ -88,10 +94,6 @@ Item { } else { root.hasPermissionToRezThis = true; } - - if (itemType === "app") { - root.isInstalled = Commerce.isAppInstalled(root.itemHref); - } } onPurchaseStatusChangedChanged: { @@ -496,6 +498,8 @@ Item { colorScheme: hifi.colorSchemes.light; anchors.top: parent.top; anchors.right: parent.right; + anchors.left: parent.left; + width: 92; height: 44; text: "OPEN" onClicked: { @@ -509,6 +513,7 @@ Item { colorScheme: hifi.colorSchemes.light; anchors.bottom: parent.bottom; anchors.right: parent.right; + anchors.left: parent.left; height: 44; text: "UNINSTALL" onClicked: { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 9b333a60cd..896200a8e6 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -36,6 +36,7 @@ Rectangle { property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; property int pendingItemCount: 0; + property var installedApps; // Style color: hifi.colors.white; Connections { @@ -61,6 +62,8 @@ Rectangle { root.activeView = "firstUseTutorial"; } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { root.activeView = "purchasesMain"; + root.installedApps = Commerce.getInstalledApps(); + console.log("ZRF! " + root.installedApps); Commerce.inventory(); } } else { @@ -269,6 +272,7 @@ Rectangle { case 'tutorial_finished': Settings.setValue("isFirstUseOfPurchases", false); root.activeView = "purchasesMain"; + root.installedApps = Commerce.getInstalledApps(); Commerce.inventory(); break; } @@ -394,6 +398,7 @@ Rectangle { limitedRun: model.limited_run; displayedItemCount: model.displayedItemCount; permissionExplanationCardVisible: model.permissionExplanationCardVisible; + isInstalled: model.isInstalled; itemType: { if (model.root_file_url.indexOf(".fst") > -1) { "avatar"; @@ -680,9 +685,16 @@ Rectangle { if (sameItemCount !== tempPurchasesModel.count || filterBar.text !== filterBar.previousText) { filteredPurchasesModel.clear(); + var currentId; for (var i = 0; i < tempPurchasesModel.count; i++) { + currentId = tempPurchasesModel.get(i).id; + console.log("ZRF HERE 2 " + root.installedApps); + console.log("ZRF HERE 3 " + currentId); + console.log("ZRF HERE 4 " + ((root.installedApps).indexOf(currentId) > -1)); + filteredPurchasesModel.append(tempPurchasesModel.get(i)); filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false); + filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1)); } populateDisplayedItemCounts(); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index f9bb0d2003..f80e88d175 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -45,7 +45,7 @@ QmlCommerce::QmlCommerce() { setPassphrase(""); }); - _appsPath = PathUtils::getAppDataPath() + "Apps"; + _appsPath = PathUtils::getAppDataPath() + "Apps/"; } void QmlCommerce::getWalletStatus() { @@ -190,26 +190,38 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) { ledger->alreadyOwned(marketplaceId); } -bool QmlCommerce::isAppInstalled(const QString& itemHref) { - QUrl appHref(itemHref); +QStringList QmlCommerce::getInstalledApps() { + QStringList installedAppsFromMarketplace; + QStringList runningScripts = DependencyManager::get()->getRunningScripts(); - // First check if .app.json exists - QFileInfo appFile(_appsPath + "/" + appHref.fileName()); - if (!(appFile.exists() && appFile.isFile())) { - return false; - } + QDir directory(_appsPath); + qCDebug(commerce) << "ZRF FIXME" << _appsPath; + QStringList apps = directory.entryList(QStringList("*.app.json")); + foreach(QString appFileName, apps) { + installedAppsFromMarketplace.append(appFileName); + qCDebug(commerce) << "ZRF FIXME" << appFileName; + QFile appFile(_appsPath + appFileName); + if (appFile.open(QIODevice::ReadOnly)) { + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); - // Then check to see if script is running - auto runningScripts = DependencyManager::get()->getRunningScripts(); - foreach(const QString& runningScript, runningScripts) { - QUrl runningScriptURL = QUrl(runningScript); - qCDebug(commerce) << "ZRF FIXME" << runningScriptURL; - if (runningScriptURL == appHref) { - return true; + appFile.close(); + + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString scriptURL = appFileJsonObject["scriptURL"].toString(); + + // If the script .app.json is on the user's local disk but the associated script isn't running + // for some reason, start that script again. + if (!runningScripts.contains(scriptURL)) { + if ((DependencyManager::get()->loadScript(scriptURL.trimmed())).isNull()) { + qCDebug(commerce) << "Couldn't start script while checking installed apps."; + } + } + } else { + qCDebug(commerce) << "Couldn't open local .app.json file for reading."; } } - return false; + return installedAppsFromMarketplace; } bool QmlCommerce::installApp(const QString& itemHref) { diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index e0c018878d..2bf4959177 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -51,8 +51,8 @@ signals: void contentSetChanged(const QString& contentSetHref); - void appInstalled(const QString& appFileName); - void appUninstalled(const QString& appFileName); + void appInstalled(const QString& appHref); + void appUninstalled(const QString& appHref); protected: Q_INVOKABLE void getWalletStatus(); @@ -81,7 +81,7 @@ protected: Q_INVOKABLE void replaceContentSet(const QString& itemHref); - Q_INVOKABLE bool isAppInstalled(const QString& appHref); + Q_INVOKABLE QStringList getInstalledApps(); Q_INVOKABLE bool installApp(const QString& appHref); Q_INVOKABLE bool uninstallApp(const QString& appHref); Q_INVOKABLE bool openApp(const QString& appHref); diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 8cf5b72b9a..9ff7038c09 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -39,7 +39,7 @@ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - tablet.loadQMLSource(WALLET_QML_SOURCE); + tablet.loadQMLSource(MARKETPLACE_PURCHASES_QML_PATH); } } From 33f73fef0df20528ca3867a41d4a1257fc4791f9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 16:26:35 -0800 Subject: [PATCH 43/61] YAY! --- .../resources/qml/hifi/commerce/purchases/Purchases.qml | 6 +----- interface/src/commerce/QmlCommerce.cpp | 9 ++++----- interface/src/commerce/QmlCommerce.h | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 896200a8e6..3612de7323 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -36,7 +36,7 @@ Rectangle { property bool isShowingMyItems: false; property bool isDebuggingFirstUseTutorial: false; property int pendingItemCount: 0; - property var installedApps; + property string installedApps; // Style color: hifi.colors.white; Connections { @@ -63,7 +63,6 @@ Rectangle { } else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") { root.activeView = "purchasesMain"; root.installedApps = Commerce.getInstalledApps(); - console.log("ZRF! " + root.installedApps); Commerce.inventory(); } } else { @@ -688,9 +687,6 @@ Rectangle { var currentId; for (var i = 0; i < tempPurchasesModel.count; i++) { currentId = tempPurchasesModel.get(i).id; - console.log("ZRF HERE 2 " + root.installedApps); - console.log("ZRF HERE 3 " + currentId); - console.log("ZRF HERE 4 " + ((root.installedApps).indexOf(currentId) > -1)); filteredPurchasesModel.append(tempPurchasesModel.get(i)); filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index f80e88d175..6de5de1a9d 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -190,16 +190,15 @@ void QmlCommerce::alreadyOwned(const QString& marketplaceId) { ledger->alreadyOwned(marketplaceId); } -QStringList QmlCommerce::getInstalledApps() { - QStringList installedAppsFromMarketplace; +QString QmlCommerce::getInstalledApps() { + QString installedAppsFromMarketplace; QStringList runningScripts = DependencyManager::get()->getRunningScripts(); QDir directory(_appsPath); - qCDebug(commerce) << "ZRF FIXME" << _appsPath; QStringList apps = directory.entryList(QStringList("*.app.json")); foreach(QString appFileName, apps) { - installedAppsFromMarketplace.append(appFileName); - qCDebug(commerce) << "ZRF FIXME" << appFileName; + installedAppsFromMarketplace += appFileName; + installedAppsFromMarketplace += ","; QFile appFile(_appsPath + appFileName); if (appFile.open(QIODevice::ReadOnly)) { QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll()); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 2bf4959177..09eb7137af 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -81,7 +81,7 @@ protected: Q_INVOKABLE void replaceContentSet(const QString& itemHref); - Q_INVOKABLE QStringList getInstalledApps(); + Q_INVOKABLE QString getInstalledApps(); Q_INVOKABLE bool installApp(const QString& appHref); Q_INVOKABLE bool uninstallApp(const QString& appHref); Q_INVOKABLE bool openApp(const QString& appHref); From 3150b963c0106f163ea5aec03a34a23c5220dda3 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 22 Feb 2018 16:29:58 -0800 Subject: [PATCH 44/61] Implemented call to abortTask(). --- .../render-utils/src/RenderShadowTask.cpp | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index be84482c63..ce4bf01dcf 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -120,11 +120,6 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con auto lightStage = renderContext->_scene->getStage(); assert(lightStage); - // Exit if current keylight does not cast shadows - if (!lightStage->getCurrentKeyLight() || !lightStage->getCurrentKeyLight()->getCastShadows()) { - return; - } - auto shadow = lightStage->getCurrentKeyShadow(); if (!shadow || _cascadeIndex >= shadow->getCascadeCount()) { return; @@ -305,8 +300,14 @@ void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) { } void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) { + // Abort all jobs if not casting shadows auto lightStage = renderContext->_scene->getStage(); assert(lightStage); + if (!lightStage->getCurrentKeyLight() || !lightStage->getCurrentKeyLight()->getCastShadows()) { + renderContext->taskFlow.abortTask(); + return; + } + // Cache old render args RenderArgs* args = renderContext->args; @@ -387,18 +388,6 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon auto lightStage = renderContext->_scene->getStage(); assert(lightStage); - // Exit if current keylight does not cast shadows - if (!lightStage->getCurrentKeyLight()) { - return; - } - - bool castShadows = lightStage->getCurrentKeyLight()->getCastShadows(); - if (!castShadows) { - output.edit0() = ItemFilter::Builder::nothing(); - output.edit1() = ViewFrustumPointer(); - return; - } - // Cache old render args RenderArgs* args = renderContext->args; From f14673bc5079622d019919f004bb54e4539768d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 16:37:12 -0800 Subject: [PATCH 45/61] Fixup Checkout for apps --- .../qml/hifi/commerce/checkout/Checkout.qml | 16 +++++++++++++--- scripts/system/commerce/wallet.js | 2 +- scripts/system/marketplaces/marketplaces.js | 4 ---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 98f26887ae..10894109ef 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -48,6 +48,7 @@ Rectangle { property bool debugCheckoutSuccess: false; property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); property string referrer; + property bool isInstalled; // Style color: hifi.colors.white; Connections { @@ -122,6 +123,12 @@ Rectangle { root.refreshBuyUI(); } } + + onAppInstalled: { + if (appHref === root.itemHref) { + root.isInstalled = true; + } + } } onItemIdChanged: { @@ -689,7 +696,7 @@ Rectangle { height: 50; anchors.left: parent.left; anchors.right: parent.right; - text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; + text: root.itemType === "app" && root.isInstalled ? "OPEN APP" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; onClicked: { if (root.itemType === "contentSet") { lightboxPopup.titleText = "Replace Content"; @@ -714,8 +721,11 @@ Rectangle { lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;"; lightboxPopup.visible = true; } else if (root.itemType === "app") { - // "Run" button is separate. - Commerce.installApp(root.itemHref); + if (root.isInstalled) { + Commerce.openApp(root.itemHref); + } else { + Commerce.installApp(root.itemHref); + } } else { sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType}); rezzedNotifContainer.visible = true; diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 9ff7038c09..8cf5b72b9a 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -39,7 +39,7 @@ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - tablet.loadQMLSource(MARKETPLACE_PURCHASES_QML_PATH); + tablet.loadQMLSource(WALLET_QML_SOURCE); } } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index ecd1bf2a6e..8f51d88f2d 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -552,10 +552,6 @@ var selectionDisplay = null; // for gridTool.js to ignore case 'checkout_rezClicked': case 'purchases_rezClicked': rezEntity(message.itemHref, message.itemType); - break; - case 'checkout_installClicked': - case 'purchases_installClicked': - break; case 'header_marketplaceImageClicked': case 'purchases_backClicked': From 249f0568a14157e8a48f0071b65283127e9f93d1 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 22 Feb 2018 17:14:23 -0800 Subject: [PATCH 46/61] New loader --- .../qml/hifi/commerce/checkout/Checkout.qml | 7 ++++--- .../hifi/commerce/common/images/loader-blue.gif | Bin 0 -> 59768 bytes 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/images/loader-blue.gif diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 10894109ef..d88ded6a15 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -319,7 +319,7 @@ Rectangle { z: 997; visible: !root.ownershipStatusReceived || !root.balanceReceived; anchors.fill: parent; - color: Qt.rgba(0.0, 0.0, 0.0, 0.7); + color: hifi.colors.white; // This object is always used in a popup. // This MouseArea is used to prevent a user from being @@ -331,8 +331,9 @@ Rectangle { } AnimatedImage { - source: "../common/images/loader.gif" - width: 96; + id: loadingImage; + source: "../common/images/loader-blue.gif" + width: 74; height: width; anchors.verticalCenter: parent.verticalCenter; anchors.horizontalCenter: parent.horizontalCenter; diff --git a/interface/resources/qml/hifi/commerce/common/images/loader-blue.gif b/interface/resources/qml/hifi/commerce/common/images/loader-blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..8b9e17053b2420e2ea3dcf68e3677d172858a9b5 GIT binary patch literal 59768 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 Date: Thu, 22 Feb 2018 17:20:36 -0800 Subject: [PATCH 47/61] add dynamic mode for scripted avatar motor --- interface/src/avatar/MyAvatar.cpp | 92 +++++++++++++++++++++++-------- interface/src/avatar/MyAvatar.h | 5 ++ libraries/gl/src/gl/Context.cpp | 2 +- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c25aaeeecd..445b176c15 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -79,6 +79,8 @@ float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f; const int SCRIPTED_MOTOR_CAMERA_FRAME = 0; const int SCRIPTED_MOTOR_AVATAR_FRAME = 1; const int SCRIPTED_MOTOR_WORLD_FRAME = 2; +const int SCRIPTED_MOTOR_SIMPLE_MODE = 0; +const int SCRIPTED_MOTOR_DYNAMIC_MODE = 1; const QString& DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; const float MyAvatar::ZOOM_MIN = 0.5f; @@ -92,6 +94,7 @@ MyAvatar::MyAvatar(QThread* thread) : _pitchSpeed(PITCH_SPEED_DEFAULT), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), + _scriptedMotorMode(SCRIPTED_MOTOR_SIMPLE_MODE), _motionBehaviors(AVATAR_MOTION_DEFAULTS), _characterController(this), _eyeContactTarget(LEFT_EYE), @@ -1623,32 +1626,38 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; + glm::quat avatarOrientation = getWorldOrientation(); + + const float FLYING_MOTOR_TIMESCALE = 0.05f; + const float WALKING_MOTOR_TIMESCALE = 0.2f; + const float INVALID_MOTOR_TIMESCALE = 1.0e6f; + + float horizontalMotorTimescale; + float verticalMotorTimescale; + + if (_characterController.getState() == CharacterController::State::Hover || + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; + verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; + } + else { + horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; + verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; + } + if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { - - const float FLYING_MOTOR_TIMESCALE = 0.05f; - const float WALKING_MOTOR_TIMESCALE = 0.2f; - const float INVALID_MOTOR_TIMESCALE = 1.0e6f; - - float horizontalMotorTimescale; - float verticalMotorTimescale; - if (_characterController.getState() == CharacterController::State::Hover || _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { motorRotation = getMyHead()->getHeadOrientation(); - horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; - verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; } else { // non-hovering = walking: follow camera twist about vertical but not lift // we decompose camera's rotation and store the twist part in motorRotation // however, we need to perform the decomposition in the avatar-frame // using the local UP axis and then transform back into world-frame - glm::quat orientation = getWorldOrientation(); - glm::quat headOrientation = glm::inverse(orientation) * getMyHead()->getHeadOrientation(); // avatar-frame + glm::quat headOrientation = glm::inverse(avatarOrientation) * getMyHead()->getHeadOrientation(); // avatar-frame glm::quat liftRotation; swingTwistDecomposition(headOrientation, Vectors::UNIT_Y, liftRotation, motorRotation); - motorRotation = orientation * motorRotation; - horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; - verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; + motorRotation = avatarOrientation * motorRotation; } if (_isPushing || _isBraking || !_isBeingPushed) { @@ -1660,15 +1669,36 @@ void MyAvatar::updateMotors() { } } if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { - motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } else { - // world-frame - motorRotation = glm::quat(); + if (_scriptedMotorMode == SCRIPTED_MOTOR_SIMPLE_MODE) { + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else { + // world-frame + motorRotation = glm::quat(); + } + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); + } else { + // dynamic mode + glm::vec3 avatarFrameVelocity; + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + // convert camera frame velocity to avatar frame + glm::quat cameraOrientation = qApp->getCamera().getOrientation(); + avatarFrameVelocity = glm::inverse(avatarOrientation) * cameraOrientation * _scriptedMotorVelocity; + } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_WORLD_FRAME) { + // convert world frame velocity to avatar frame + avatarFrameVelocity = glm::inverse(avatarOrientation) * _scriptedMotorVelocity; + } else { + // avatar frame + avatarFrameVelocity = _scriptedMotorVelocity; + } + // dynamic mode for scripted motor uses avatar frame and piggybacks off of the default action motor's timescales + motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); + _characterController.addMotor(avatarFrameVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); } - _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); } // legacy support for 'MyAvatar::applyThrust()', which has always been implemented as a @@ -1752,6 +1782,14 @@ QString MyAvatar::getScriptedMotorFrame() const { return frame; } +QString MyAvatar::getScriptedMotorMode() const { + QString mode = "simple"; + if (_scriptedMotorMode == SCRIPTED_MOTOR_DYNAMIC_MODE) { + mode = "dynamic"; + } + return mode; +} + void MyAvatar::setScriptedMotorVelocity(const glm::vec3& velocity) { float MAX_SCRIPTED_MOTOR_SPEED = 500.0f; _scriptedMotorVelocity = velocity; @@ -1778,6 +1816,14 @@ void MyAvatar::setScriptedMotorFrame(QString frame) { } } +void MyAvatar::setScriptedMotorMode(QString frame) { + if (frame.toLower() == "simple") { + _scriptedMotorMode = SCRIPTED_MOTOR_SIMPLE_MODE; + } else if (frame.toLower() == "dynamic") { + _scriptedMotorMode = SCRIPTED_MOTOR_DYNAMIC_MODE; + } +} + void MyAvatar::clearScriptableSettings() { _scriptedMotorVelocity = Vectors::ZERO; _scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 28af8b62fd..464d94bce7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,6 +69,7 @@ class MyAvatar : public Avatar { * @property motorTimescale {float} Specifies how quickly the avatar should accelerate to meet the motorVelocity, * smaller values will result in higher acceleration. * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", "camera", "world" + * @property motorMode {string} Type of scripted motor behavior, "simple" = unmodified legacy behavior and "dynamic" = same as default motor * @property collisionSoundURL {string} Specifies the sound to play when the avatar experiences a collision. * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. @@ -124,6 +125,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(glm::vec3 motorVelocity READ getScriptedMotorVelocity WRITE setScriptedMotorVelocity) Q_PROPERTY(float motorTimescale READ getScriptedMotorTimescale WRITE setScriptedMotorTimescale) Q_PROPERTY(QString motorReferenceFrame READ getScriptedMotorFrame WRITE setScriptedMotorFrame) + Q_PROPERTY(QString motorMode READ getScriptedMotorMode WRITE setScriptedMotorMode) Q_PROPERTY(QString collisionSoundURL READ getCollisionSoundURL WRITE setCollisionSoundURL) Q_PROPERTY(AudioListenerMode audioListenerMode READ getAudioListenerMode WRITE setAudioListenerMode) Q_PROPERTY(glm::vec3 customListenPosition READ getCustomListenPosition WRITE setCustomListenPosition) @@ -662,9 +664,11 @@ private: glm::vec3 getScriptedMotorVelocity() const { return _scriptedMotorVelocity; } float getScriptedMotorTimescale() const { return _scriptedMotorTimescale; } QString getScriptedMotorFrame() const; + QString getScriptedMotorMode() const; void setScriptedMotorVelocity(const glm::vec3& velocity); void setScriptedMotorTimescale(float timescale); void setScriptedMotorFrame(QString frame); + void setScriptedMotorMode(QString frame); virtual void attach(const QString& modelURL, const QString& jointName = QString(), const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f, bool isSoft = false, @@ -706,6 +710,7 @@ private: glm::vec3 _scriptedMotorVelocity; // target local-frame velocity of avatar (analog script) float _scriptedMotorTimescale; // timescale for avatar to achieve its target velocity int _scriptedMotorFrame; + int _scriptedMotorMode; quint32 _motionBehaviors; QString _collisionSoundURL; diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index 309839808e..155849bffa 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -147,7 +147,7 @@ static void debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum s } // FIXME For high severity errors, force a sync to the log, since we might crash // before the log file was flushed otherwise. Performance hit here - qCDebug(glLogging) << "OpenGL: " << message; + //qCDebug(glLogging) << "OpenGL: " << message; } static void setupPixelFormatSimple(HDC hdc) { From 9f68accb302e6ea59120a9bb5717df00e2788fc7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 Feb 2018 17:34:00 -0800 Subject: [PATCH 48/61] add menu for testing unresponsive interface --- interface/src/Application.cpp | 12 ++++++++++++ interface/src/Application.h | 1 + interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + 4 files changed, 15 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8c3e6f130d..e8264a398a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7542,6 +7542,18 @@ void Application::deadlockApplication() { } } +// cause main thread to be unresponsive for 35 seconds +void Application::unresponsiveApplication() { + // to avoid compiler warnings about a loop that will never exit + uint64_t start = usecTimestampNow(); + uint64_t UNRESPONSIVE_FOR_SECONDS = 35; + uint64_t UNRESPONSIVE_FOR_USECS = UNRESPONSIVE_FOR_SECONDS * USECS_PER_SECOND; + qCDebug(interfaceapp) << "Intentionally cause Interface to be unresponsive for " << UNRESPONSIVE_FOR_SECONDS << " seconds"; + while (usecTimestampNow() - start < UNRESPONSIVE_FOR_USECS) { + QThread::sleep(1); + } +} + void Application::setActiveDisplayPlugin(const QString& pluginName) { auto menu = Menu::getInstance(); foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index d4041aa3be..5ce9a1619a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -367,6 +367,7 @@ public slots: void updateHeartbeat() const; static void deadlockApplication(); + static void unresponsiveApplication(); // cause main thread to be unresponsive for 35 seconds void rotationModeChanged() const; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 464de87fdb..5abc59356e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -713,6 +713,7 @@ Menu::Menu() { MenuWrapper* crashMenu = developerMenu->addMenu("Crash"); addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication())); + addActionToQMenuAndActionHash(crashMenu, MenuOption::UnresponsiveInterface, 0, qApp, SLOT(unresponsiveApplication())); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction); connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); }); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8cb1804fd4..9c4efd6ac7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -77,6 +77,7 @@ namespace MenuOption { const QString CrashNewFault = "New Fault"; const QString CrashNewFaultThreaded = "New Fault (threaded)"; const QString DeadlockInterface = "Deadlock Interface"; + const QString UnresponsiveInterface = "Unresponsive Interface"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DefaultSkybox = "Default Skybox"; const QString DeleteAvatarBookmark = "Delete Avatar Bookmark..."; From ba0ba96d81a096100948d11730b3ff2d7b3825a3 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 22 Feb 2018 17:54:03 -0800 Subject: [PATCH 49/61] undo --- libraries/gl/src/gl/Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index 155849bffa..309839808e 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -147,7 +147,7 @@ static void debugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum s } // FIXME For high severity errors, force a sync to the log, since we might crash // before the log file was flushed otherwise. Performance hit here - //qCDebug(glLogging) << "OpenGL: " << message; + qCDebug(glLogging) << "OpenGL: " << message; } static void setupPixelFormatSimple(HDC hdc) { From 0469eafbe46bf2df42f9f0ea6104d1ad9d98273a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 22 Feb 2018 18:35:16 -0800 Subject: [PATCH 50/61] Switch between dualQuats and matrix skinning based on model entity scale factor. --- .../src/RenderableModelEntityItem.cpp | 7 ++++++- .../render-utils/src/MeshPartPayload.cpp | 9 ++++++++- libraries/render-utils/src/MeshPartPayload.h | 2 ++ libraries/render-utils/src/Model.cpp | 20 ++++++++++++------- libraries/render-utils/src/Model.h | 1 + .../render-utils/src/RenderPipelines.cpp | 2 +- libraries/shared/src/DualQuaternion.h | 2 +- libraries/shared/src/GLMHelpers.cpp | 3 +++ libraries/shared/src/GLMHelpers.h | 2 ++ 9 files changed, 37 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 83ec675adf..d295e9e1fa 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -133,6 +133,9 @@ void RenderableModelEntityItem::doInitialModelSimulation() { model->setRotation(getWorldOrientation()); model->setTranslation(getWorldPosition()); + glm::vec3 scale = model->getScale(); + model->setUseDualQuaternionSkinning(!isNonUniformScale(scale)); + if (_needsInitialSimulation) { model->simulate(0.0f); _needsInitialSimulation = false; @@ -243,6 +246,8 @@ void RenderableModelEntityItem::updateModelBounds() { } if (updateRenderItems) { + glm::vec3 scale = model->getScale(); + model->setUseDualQuaternionSkinning(!isNonUniformScale(scale)); model->updateRenderItems(); } } @@ -1500,4 +1505,4 @@ void ModelEntityRenderer::processMaterials() { material.pop(); } } -} \ No newline at end of file +} diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4a0ea40f55..99048fe324 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -407,7 +407,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe if (isWireframe) { builder.withWireframe(); } - if (_useDualQuaternionSkinning) { + if (_useDualQuaternionSkinning && isSkinned) { builder.withDualQuatSkinned(); } @@ -497,3 +497,10 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); + void setUseDualQuaternionSkinning(bool value); + gpu::BufferPointer _clusterBuffer; int _meshIndex; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index da43e4fd8f..8318715732 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -288,6 +288,7 @@ void Model::updateRenderItems() { invalidatePayloadShapeKey, isWireframe, isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); } else { @@ -388,11 +389,8 @@ bool Model::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; - if (_useDualQuaternionSkinning) { - state.clusterDualQuaternions.resize(mesh.clusters.size()); - } else { - state.clusterMatrices.resize(mesh.clusters.size()); - } + state.clusterDualQuaternions.resize(mesh.clusters.size()); + state.clusterMatrices.resize(mesh.clusters.size()); _meshStates.push_back(state); // Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index @@ -1248,6 +1246,10 @@ void Model::snapToRegistrationPoint() { _snappedToRegistrationPoint = true; } +void Model::setUseDualQuaternionSkinning(bool value) { + _useDualQuaternionSkinning = value; +} + void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) @@ -1583,11 +1585,13 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); data.setShapeKey(invalidatePayloadShapeKey, wireframe); }); } @@ -1608,11 +1612,13 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.removeMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); data.setShapeKey(invalidatePayloadShapeKey, wireframe); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 61e699f30a..aef6a84a24 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -314,6 +314,7 @@ public: void scaleToFit(); bool getUseDualQuaternionSkinning() const { return _useDualQuaternionSkinning; } + void setUseDualQuaternionSkinning(bool value); void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index cccc128b64..3fedae1778 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -447,7 +447,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); - // dual quatenion skinned + // dual quaternion skinned addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(), skinModelDualQuatVertex, modelPixel, nullptr, nullptr); diff --git a/libraries/shared/src/DualQuaternion.h b/libraries/shared/src/DualQuaternion.h index 709c089fdc..af1011a6d8 100644 --- a/libraries/shared/src/DualQuaternion.h +++ b/libraries/shared/src/DualQuaternion.h @@ -55,7 +55,7 @@ protected: inline QDebug operator<<(QDebug debug, const DualQuaternion& dq) { - debug << "AnimPose, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")"; + debug << "DualQuaternion, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")"; return debug; } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index ff1d29eed1..46e484cf2b 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -601,3 +601,6 @@ glm::vec3 randVector() { return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f; } +bool isNonUniformScale(const glm::vec3& scale) { + return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON; +} diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 4f761a4aac..5c9a8b5ca1 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -260,6 +260,8 @@ glm::mat4 orthoInverse(const glm::mat4& m); // Return a random vector of average length 1 glm::vec3 randVector(); +bool isNonUniformScale(const glm::vec3& scale); + // // Safe replacement of glm_mat4_mul() for unaligned arguments instead of __m128 // From b8102cfbd72e3323d35351670c8e5f901cb11c42 Mon Sep 17 00:00:00 2001 From: vladest Date: Fri, 23 Feb 2018 10:06:16 +0100 Subject: [PATCH 51/61] Make sure sort indicator is attached to the right of title --- .../resources/qml/controls-uit/Table.qml | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index a3e4113d08..c5a605c69e 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -22,6 +22,7 @@ TableView { readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light property bool expandSelectedRow: false property bool centerHeaderText: false + readonly property real headerSpacing: 3 //spacing between sort indicator and table header title model: ListModel { } @@ -69,20 +70,18 @@ TableView { height: hifi.dimensions.tableHeaderHeight color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark + RalewayRegular { id: titleText + x: centerHeaderText ? parent.width/2 - + (paintedWidth/2 + (sortIndicatorVisible ? titleSort.paintedWidth/12 : 0)) : + hifi.dimensions.tablePadding text: styleData.value size: hifi.fontSizes.tableHeading font.capitalization: Font.AllUppercase color: hifi.colors.baseGrayHighlight horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft) - anchors { - left: parent.left - leftMargin: hifi.dimensions.tablePadding - right: parent.right - rightMargin: hifi.dimensions.tablePadding - verticalCenter: parent.verticalCenter - } + anchors.verticalCenter: parent.verticalCenter } HiFiGlyphs { @@ -91,13 +90,9 @@ TableView { color: hifi.colors.darkGray opacity: 0.6; size: hifi.fontSizes.tableHeadingIcon - anchors { - left: titleText.right - leftMargin: -hifi.fontSizes.tableHeadingIcon / 3 - (centerHeaderText ? 15 : 10) - right: parent.right - rightMargin: hifi.dimensions.tablePadding - verticalCenter: titleText.verticalCenter - } + anchors.verticalCenter: titleText.verticalCenter + anchors.left: titleText.right + anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 3 + tableView.headerSpacing) visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column } @@ -152,7 +147,7 @@ TableView { color: styleData.selected ? hifi.colors.primaryHighlight : tableView.isLightColorScheme - ? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd) - : (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd) + ? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd) + : (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd) } } From 59bd05aa554ad6d433d50edae5b223a400a0765f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 23 Feb 2018 09:21:13 -0800 Subject: [PATCH 52/61] make shadow-related shader compile on osx --- libraries/render-utils/src/Shadow.slh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index abb04a4498..36eb35c757 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -89,7 +89,9 @@ float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) { ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition); - vec4 cascadeShadowCoords[2] = { vec4(0), vec4(0) }; + vec4 cascadeShadowCoords[2]; + cascadeShadowCoords[0] = vec4(0); + cascadeShadowCoords[1] = vec4(0); ivec2 cascadeIndices; float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices); From 5ee28297f33693ce5c90e9fc1745cbdd7f461110 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 23 Feb 2018 10:19:00 -0800 Subject: [PATCH 53/61] Don't use eventLoop, since that will block the UI --- interface/src/commerce/QmlCommerce.cpp | 70 +++++++++++++------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 6de5de1a9d..e7d62930cf 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -233,49 +233,47 @@ bool QmlCommerce::installApp(const QString& itemHref) { QUrl appHref(itemHref); - auto request = - std::unique_ptr(DependencyManager::get()->createResourceRequest(this, appHref)); + auto request = DependencyManager::get()->createResourceRequest(this, appHref); if (!request) { qCDebug(commerce) << "Couldn't create resource request for app."; return false; } - QEventLoop loop; - connect(request.get(), &ResourceRequest::finished, &loop, &QEventLoop::quit); + connect(request, &ResourceRequest::finished, this, [=]() { + if (request->getResult() != ResourceRequest::Success) { + qCDebug(commerce) << "Failed to get .app.json file from remote."; + return false; + } + + // Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface + auto requestData = request->getData(); + QFile appFile(_appsPath + "/" + appHref.fileName()); + if (!appFile.open(QIODevice::WriteOnly)) { + qCDebug(commerce) << "Couldn't open local .app.json file for creation."; + return false; + } + if (appFile.write(requestData) == -1) { + qCDebug(commerce) << "Couldn't write to local .app.json file."; + return false; + } + // Close the file + appFile.close(); + + // Read from the returned datastream to know what .js to add to Running Scripts + QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(requestData); + QJsonObject appFileJsonObject = appFileJsonDocument.object(); + QString scriptUrl = appFileJsonObject["scriptURL"].toString(); + + if ((DependencyManager::get()->loadScript(scriptUrl.trimmed())).isNull()) { + qCDebug(commerce) << "Couldn't load script."; + return false; + } + + emit appInstalled(itemHref); + return true; + }); request->send(); - loop.exec(); - - if (request->getResult() != ResourceRequest::Success) { - qCDebug(commerce) << "Failed to get .app.json file from remote."; - return false; - } - - // Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface - auto requestData = request->getData(); - QFile appFile(_appsPath + "/" + appHref.fileName()); - if (!appFile.open(QIODevice::WriteOnly)) { - qCDebug(commerce) << "Couldn't open local .app.json file for creation."; - return false; - } - if (appFile.write(requestData) == -1) { - qCDebug(commerce) << "Couldn't write to local .app.json file."; - return false; - } - // Close the file - appFile.close(); - - // Read from the returned datastream to know what .js to add to Running Scripts - QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(requestData); - QJsonObject appFileJsonObject = appFileJsonDocument.object(); - QString scriptUrl = appFileJsonObject["scriptURL"].toString(); - - if ((DependencyManager::get()->loadScript(scriptUrl.trimmed())).isNull()) { - qCDebug(commerce) << "Couldn't load script."; - return false; - } - - emit appInstalled(itemHref); return true; } From d0ec84b6c8739ad6eab55eefe7bc6efd71038eb2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 23 Feb 2018 10:45:59 -0800 Subject: [PATCH 54/61] remove menu option for booking marking avatar entities --- interface/src/Application.cpp | 4 - interface/src/AvatarBookmarks.cpp | 96 +++++++++++-- interface/src/AvatarBookmarks.h | 1 + interface/src/AvatarEntitiesBookmarks.cpp | 168 ---------------------- interface/src/AvatarEntitiesBookmarks.h | 45 ------ interface/src/Menu.cpp | 5 - interface/src/Menu.h | 1 - 7 files changed, 82 insertions(+), 238 deletions(-) delete mode 100644 interface/src/AvatarEntitiesBookmarks.cpp delete mode 100644 interface/src/AvatarEntitiesBookmarks.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 60e4c7c948..ffd2bbef97 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -68,7 +68,6 @@ #include #include #include -#include #include #include #include @@ -785,7 +784,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); - DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -2606,7 +2604,6 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance()); surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); - surfaceContext->setContextProperty("AvatarEntitiesBookmarks", DependencyManager::get().data()); surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get().data()); // Caches @@ -5987,7 +5984,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get()->getStats().data()); scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get().data()); scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("AvatarEntitiesBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get().data()); scriptEngine->registerGlobalObject("RayPick", DependencyManager::get().data()); diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 0f177e3d15..7845158a80 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -19,6 +19,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "MainWindow.h" #include "Menu.h" @@ -29,6 +34,62 @@ #include + +void addAvatarEntities(const QVariantList& avatarEntities) { + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + EntityTreePointer entityTree = DependencyManager::get()->getTree(); + if (!entityTree) { + return; + } + EntitySimulationPointer entitySimulation = entityTree->getSimulation(); + PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast(entitySimulation); + EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender(); + QScriptEngine scriptEngine; + for (int index = 0; index < avatarEntities.count(); index++) { + const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap(); + QVariant variantProperties = avatarEntityProperties["properties"]; + QVariantMap asMap = variantProperties.toMap(); + QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); + EntityItemProperties entityProperties; + EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties); + + entityProperties.setParentID(myNodeID); + entityProperties.setClientOnly(true); + entityProperties.setOwningAvatarID(myNodeID); + entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY); + entityProperties.markAllChanged(); + + EntityItemID id = EntityItemID(QUuid::createUuid()); + bool success = true; + entityTree->withWriteLock([&] { + EntityItemPointer entity = entityTree->addEntity(id, entityProperties); + if (entity) { + if (entityProperties.queryAACubeRelatedPropertyChanged()) { + // due to parenting, the server may not know where something is in world-space, so include the bounding cube. + bool success; + AACube queryAACube = entity->getQueryAACube(success); + if (success) { + entityProperties.setQueryAACube(queryAACube); + } + } + + entity->setLastBroadcast(usecTimestampNow()); + // since we're creating this object we will immediately volunteer to own its simulation + entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); + entityProperties.setLastEdited(entity->getLastEdited()); + } else { + qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree"; + success = false; + } + }); + + if (success) { + entityPacketSender->queueEditEntityMessage(PacketType::EntityAdd, entityTree, id, entityProperties); + } + } +} + AvatarBookmarks::AvatarBookmarks() { _bookmarksFilename = PathUtils::getAppDataPath() + "/" + AVATARBOOKMARKS_FILENAME; readFromFile(); @@ -38,7 +99,7 @@ void AvatarBookmarks::readFromFile() { // migrate old avatarbookmarks.json, used to be in 'local' folder on windows QString oldConfigPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME; QFile oldConfig(oldConfigPath); - + // I imagine that in a year from now, this code for migrating (as well as the two lines above) // may be removed since all bookmarks should have been migrated by then // - Robbie Uvanni (6.8.2017) @@ -48,9 +109,9 @@ void AvatarBookmarks::readFromFile() { } else { qCDebug(interfaceapp) << "Failed to migrate" << AVATARBOOKMARKS_FILENAME; } - } - - Bookmarks::readFromFile(); + } + + Bookmarks::readFromFile(); } void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { @@ -81,23 +142,27 @@ void AvatarBookmarks::changeToBookmarkedAvatar() { myAvatar->useFullAvatarURL(action->data().toString()); qCDebug(interfaceapp) << " Using Legacy V1 Avatar Bookmark "; } else { - + const QMap bookmark = action->data().toMap(); - // Not magic value. This is the current made version, and if it changes this interpreter should be updated to + // Not magic value. This is the current made version, and if it changes this interpreter should be updated to // handle the new one separately. // This is where the avatar bookmark entry is parsed. If adding new Value, make sure to have backward compatability with previous if (bookmark.value(ENTRY_VERSION) == 3) { - const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString(); - myAvatar->useFullAvatarURL(avatarUrl); - qCDebug(interfaceapp) << "Avatar On " << avatarUrl; - const QList& attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList()).toList(); + myAvatar->removeAvatarEntities(); + const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString(); + myAvatar->useFullAvatarURL(avatarUrl); + qCDebug(interfaceapp) << "Avatar On " << avatarUrl; + const QList& attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList()).toList(); - qCDebug(interfaceapp) << "Attach " << attachments; - myAvatar->setAttachmentsVariant(attachments); + qCDebug(interfaceapp) << "Attach " << attachments; + myAvatar->setAttachmentsVariant(attachments); + + const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat(); + myAvatar->setAvatarScale(qScale); + + const QVariantList& avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList(); + addAvatarEntities(avatarEntities); - const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat(); - myAvatar->setAvatarScale(qScale); - } else { qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarBookmark"; } @@ -126,6 +191,7 @@ void AvatarBookmarks::addBookmark() { bookmark.insert(ENTRY_AVATAR_URL, avatarUrl); bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale); bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant()); + bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant()); Bookmarks::addBookmarkToFile(bookmarkName, bookmark); }); diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 0529eeb516..7e2f64379e 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -34,6 +34,7 @@ private: const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json"; const QString ENTRY_AVATAR_URL = "avatarUrl"; const QString ENTRY_AVATAR_ATTACHMENTS = "attachments"; + const QString ENTRY_AVATAR_ENTITIES = "avatarEntites"; const QString ENTRY_AVATAR_SCALE = "avatarScale"; const QString ENTRY_VERSION = "version"; diff --git a/interface/src/AvatarEntitiesBookmarks.cpp b/interface/src/AvatarEntitiesBookmarks.cpp deleted file mode 100644 index 21d3657346..0000000000 --- a/interface/src/AvatarEntitiesBookmarks.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// -// AvatarEntitiesBookmarks.cpp -// interface/src -// -// Created by Dante Ruiz on 15/01/18. -// Copyright 2018 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MainWindow.h" -#include "Menu.h" -#include "AvatarEntitiesBookmarks.h" -#include "InterfaceLogging.h" - -#include "QVariantGLM.h" - -#include - -void addAvatarEntities(const QVariantList& avatarEntities) { - auto nodeList = DependencyManager::get(); - const QUuid myNodeID = nodeList->getSessionUUID(); - EntityTreePointer entityTree = DependencyManager::get()->getTree(); - if (!entityTree) { - return; - } - EntitySimulationPointer entitySimulation = entityTree->getSimulation(); - PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast(entitySimulation); - EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender(); - QScriptEngine scriptEngine; - for (int index = 0; index < avatarEntities.count(); index++) { - const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap(); - QVariant variantProperties = avatarEntityProperties["properties"]; - QVariantMap asMap = variantProperties.toMap(); - QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); - EntityItemProperties entityProperties; - EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties); - - entityProperties.setParentID(myNodeID); - entityProperties.setClientOnly(true); - entityProperties.setOwningAvatarID(myNodeID); - entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY); - entityProperties.markAllChanged(); - - EntityItemID id = EntityItemID(QUuid::createUuid()); - bool success = true; - entityTree->withWriteLock([&] { - EntityItemPointer entity = entityTree->addEntity(id, entityProperties); - if (entity) { - if (entityProperties.queryAACubeRelatedPropertyChanged()) { - // due to parenting, the server may not know where something is in world-space, so include the bounding cube. - bool success; - AACube queryAACube = entity->getQueryAACube(success); - if (success) { - entityProperties.setQueryAACube(queryAACube); - } - } - - entity->setLastBroadcast(usecTimestampNow()); - // since we're creating this object we will immediately volunteer to own its simulation - entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); - entityProperties.setLastEdited(entity->getLastEdited()); - } else { - qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree"; - success = false; - } - }); - - if (success) { - entityPacketSender->queueEditEntityMessage(PacketType::EntityAdd, entityTree, id, entityProperties); - } - } -} - -AvatarEntitiesBookmarks::AvatarEntitiesBookmarks() { - _bookmarksFilename = PathUtils::getAppDataPath() + "/" + AVATAR_ENTITIES_BOOKMARKS_FILENAME; - Bookmarks::readFromFile(); -} - -void AvatarEntitiesBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { - auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkAvatarEntities); - QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection); - _bookmarksMenu = menu->addMenu(MenuOption::AvatarEntitiesBookmarks); - _deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarEntitiesBookmark); - QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection); - - for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) { - addBookmarkToMenu(menubar, it.key(), it.value()); - } - - Bookmarks::sortActions(menubar, _bookmarksMenu); -} - -void AvatarEntitiesBookmarks::applyBookmarkedAvatarEntities() { - QAction* action = qobject_cast(sender()); - auto myAvatar = DependencyManager::get()->getMyAvatar(); - - const QMap bookmark = action->data().toMap(); - - if (bookmark.value(ENTRY_VERSION) == AVATAR_ENTITIES_BOOKMARK_VERSION) { - myAvatar->removeAvatarEntities(); - const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString(); - myAvatar->useFullAvatarURL(avatarUrl); - const QVariantList& avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList(); - addAvatarEntities(avatarEntities); - const float& avatarScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat(); - myAvatar->setAvatarScale(avatarScale); - } else { - qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarEntitiesBookmark"; - } -} - -void AvatarEntitiesBookmarks::addBookmark() { - ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar Entities", "Name", QString()); - connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) { - disconnect(dlg, &ModalDialogListener::response, this, nullptr); - auto bookmarkName = response.toString(); - bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); - if (bookmarkName.length() == 0) { - return; - } - - auto myAvatar = DependencyManager::get()->getMyAvatar(); - - const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString(); - const QVariant& avatarScale = myAvatar->getAvatarScale(); - - QVariantMap bookmark; - bookmark.insert(ENTRY_VERSION, AVATAR_ENTITIES_BOOKMARK_VERSION); - bookmark.insert(ENTRY_AVATAR_URL, avatarUrl); - bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale); - bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant()); - - Bookmarks::addBookmarkToFile(bookmarkName, bookmark); - }); -} - -void AvatarEntitiesBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) { - QAction* changeAction = _bookmarksMenu->newAction(); - changeAction->setData(bookmark); - connect(changeAction, SIGNAL(triggered()), this, SLOT(applyBookmarkedAvatarEntities())); - if (!_isMenuSorted) { - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); - } else { - // TODO: this is aggressive but other alternatives have proved less fruitful so far. - menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole); - Bookmarks::sortActions(menubar, _bookmarksMenu); - } -} diff --git a/interface/src/AvatarEntitiesBookmarks.h b/interface/src/AvatarEntitiesBookmarks.h deleted file mode 100644 index 0c70e4dbc0..0000000000 --- a/interface/src/AvatarEntitiesBookmarks.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// AvatarEntitiesBookmarks.h -// interface/src -// -// Created by Dante Ruiz on 15/01/18. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AvatarEntitiesBookmarks_h -#define hifi_AvatarEntitiesBookmarks_h - -#include -#include "Bookmarks.h" - -class AvatarEntitiesBookmarks: public Bookmarks, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: - AvatarEntitiesBookmarks(); - void setupMenus(Menu* menubar, MenuWrapper* menu) override; - -public slots: - void addBookmark(); - -protected: - void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) override; - -private: - const QString AVATAR_ENTITIES_BOOKMARKS_FILENAME = "AvatarEntitiesBookmarks.json"; - const QString ENTRY_AVATAR_URL = "AvatarUrl"; - const QString ENTRY_AVATAR_SCALE = "AvatarScale"; - const QString ENTRY_AVATAR_ENTITIES = "AvatarEntities"; - const QString ENTRY_VERSION = "version"; - - const int AVATAR_ENTITIES_BOOKMARK_VERSION = 1; - -private slots: - void applyBookmarkedAvatarEntities(); -}; - -#endif diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 464de87fdb..40f7ad09ed 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -34,7 +34,6 @@ #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" #include "AvatarBookmarks.h" -#include "AvatarEntitiesBookmarks.h" #include "devices/DdeFaceTracker.h" #include "MainWindow.h" #include "render/DrawStatus.h" @@ -207,10 +206,6 @@ Menu::Menu() { auto avatarBookmarks = DependencyManager::get(); avatarBookmarks->setupMenus(this, avatarMenu); - auto avatarEntitiesBookmarks = DependencyManager::get(); - avatarEntitiesBookmarks->setupMenus(this, avatarMenu); - - // Display menu ---------------------------------- // FIXME - this is not yet matching Alan's spec because it doesn't have // menus for "2D"/"3D" - we need to add support for detecting the appropriate diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8cb1804fd4..24a4af9506 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -46,7 +46,6 @@ namespace MenuOption { const QString AutoMuteAudio = "Auto Mute Microphone"; const QString AvatarReceiveStats = "Show Receive Stats"; const QString AvatarBookmarks = "Avatar Bookmarks"; - const QString AvatarEntitiesBookmarks = "Avatar Entities Bookmarks"; const QString Back = "Back"; const QString BinaryEyelidControl = "Binary Eyelid Control"; const QString BookmarkAvatar = "Bookmark Avatar"; From a418129bea79b5f7cb2e0724305377d7db067258 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:00:23 -0800 Subject: [PATCH 55/61] simplify to just changing timescales --- interface/src/avatar/MyAvatar.cpp | 44 +++++++++++-------------------- interface/src/avatar/MyAvatar.h | 4 +-- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d5d85b3365..4a58af9378 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1626,7 +1626,6 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; - glm::quat avatarOrientation = getWorldOrientation(); const float FLYING_MOTOR_TIMESCALE = 0.05f; const float WALKING_MOTOR_TIMESCALE = 0.2f; @@ -1654,10 +1653,11 @@ void MyAvatar::updateMotors() { // we decompose camera's rotation and store the twist part in motorRotation // however, we need to perform the decomposition in the avatar-frame // using the local UP axis and then transform back into world-frame - glm::quat headOrientation = glm::inverse(avatarOrientation) * getMyHead()->getHeadOrientation(); // avatar-frame + glm::quat orientation = getWorldOrientation(); + glm::quat headOrientation = glm::inverse(orientation) * getMyHead()->getHeadOrientation(); // avatar-frame glm::quat liftRotation; swingTwistDecomposition(headOrientation, Vectors::UNIT_Y, liftRotation, motorRotation); - motorRotation = avatarOrientation * motorRotation; + motorRotation = orientation * motorRotation; } if (_isPushing || _isBraking || !_isBeingPushed) { @@ -1669,35 +1669,21 @@ void MyAvatar::updateMotors() { } } if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { + if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { + motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + } + else { + // world-frame + motorRotation = glm::quat(); + } if (_scriptedMotorMode == SCRIPTED_MOTOR_SIMPLE_MODE) { - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { - motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else { - // world-frame - motorRotation = glm::quat(); - } _characterController.addMotor(_scriptedMotorVelocity, motorRotation, _scriptedMotorTimescale); - } else { + } else { // dynamic mode - glm::vec3 avatarFrameVelocity; - if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - // convert camera frame velocity to avatar frame - glm::quat cameraOrientation = qApp->getCamera().getOrientation(); - avatarFrameVelocity = glm::inverse(avatarOrientation) * cameraOrientation * _scriptedMotorVelocity; - } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_WORLD_FRAME) { - // convert world frame velocity to avatar frame - avatarFrameVelocity = glm::inverse(avatarOrientation) * _scriptedMotorVelocity; - } else { - // avatar frame - avatarFrameVelocity = _scriptedMotorVelocity; - } - // dynamic mode for scripted motor uses avatar frame and piggybacks off of the default action motor's timescales - motorRotation = avatarOrientation * glm::angleAxis(PI, Vectors::UNIT_Y); - _characterController.addMotor(avatarFrameVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); + _characterController.addMotor(_scriptedMotorVelocity, motorRotation, horizontalMotorTimescale, verticalMotorTimescale); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 464d94bce7..fa5206e128 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,7 +69,7 @@ class MyAvatar : public Avatar { * @property motorTimescale {float} Specifies how quickly the avatar should accelerate to meet the motorVelocity, * smaller values will result in higher acceleration. * @property motorReferenceFrame {string} Reference frame of the motorVelocity, must be one of the following: "avatar", "camera", "world" - * @property motorMode {string} Type of scripted motor behavior, "simple" = unmodified legacy behavior and "dynamic" = same as default motor + * @property motorMode {string} Type of scripted motor behavior, "simple" = use motorTimescale property (default mode) and "dynamic" = use action motor's timescales * @property collisionSoundURL {string} Specifies the sound to play when the avatar experiences a collision. * You can provide a mono or stereo 16-bit WAV file running at either 24 Khz or 48 Khz. * The latter is downsampled by the audio mixer, so all audio effectively plays back at a 24 Khz sample rate. @@ -668,7 +668,7 @@ private: void setScriptedMotorVelocity(const glm::vec3& velocity); void setScriptedMotorTimescale(float timescale); void setScriptedMotorFrame(QString frame); - void setScriptedMotorMode(QString frame); + void setScriptedMotorMode(QString mode); virtual void attach(const QString& modelURL, const QString& jointName = QString(), const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f, bool isSoft = false, From da391564a8577676875c34335f5f31fcc742a1e9 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:01:29 -0800 Subject: [PATCH 56/61] CR changes --- interface/src/avatar/MyAvatar.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4a58af9378..28cfb3e8f4 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1638,8 +1638,7 @@ void MyAvatar::updateMotors() { _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; - } - else { + } else { horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE; verticalMotorTimescale = INVALID_MOTOR_TIMESCALE; } @@ -1671,11 +1670,9 @@ void MyAvatar::updateMotors() { if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { + } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { motorRotation = getWorldOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); - } - else { + } else { // world-frame motorRotation = glm::quat(); } From 283b5724ba42b69edec649ed15a0a60335c29e1d Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 23 Feb 2018 15:02:51 -0800 Subject: [PATCH 57/61] CR changes --- interface/src/avatar/MyAvatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 28cfb3e8f4..b6fa3fde96 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1799,10 +1799,10 @@ void MyAvatar::setScriptedMotorFrame(QString frame) { } } -void MyAvatar::setScriptedMotorMode(QString frame) { - if (frame.toLower() == "simple") { +void MyAvatar::setScriptedMotorMode(QString mode) { + if (mode.toLower() == "simple") { _scriptedMotorMode = SCRIPTED_MOTOR_SIMPLE_MODE; - } else if (frame.toLower() == "dynamic") { + } else if (mode.toLower() == "dynamic") { _scriptedMotorMode = SCRIPTED_MOTOR_DYNAMIC_MODE; } } From 62f2ba0dadb6acf852966af445a1bd0f2ba04b2c Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 24 Feb 2018 09:32:08 +0100 Subject: [PATCH 58/61] More intellectual calculation of title positions taking in account actual sort indicator glyph size --- interface/resources/qml/controls-uit/Table.qml | 18 +++++++++++++++--- interface/resources/qml/hifi/Pal.qml | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/controls-uit/Table.qml b/interface/resources/qml/controls-uit/Table.qml index c5a605c69e..3c1d0fcd3c 100644 --- a/interface/resources/qml/controls-uit/Table.qml +++ b/interface/resources/qml/controls-uit/Table.qml @@ -23,6 +23,9 @@ TableView { property bool expandSelectedRow: false property bool centerHeaderText: false readonly property real headerSpacing: 3 //spacing between sort indicator and table header title + property var titlePaintedPos: [] // storing extra data position behind painted + // title text and sort indicatorin table's header + signal titlePaintedPosSignal(int column) //signal that extradata position gets changed model: ListModel { } @@ -73,8 +76,10 @@ TableView { RalewayRegular { id: titleText - x: centerHeaderText ? parent.width/2 - - (paintedWidth/2 + (sortIndicatorVisible ? titleSort.paintedWidth/12 : 0)) : + x: centerHeaderText ? (parent.width - paintedWidth - + ((sortIndicatorVisible && + sortIndicatorColumn === styleData.column) ? + (titleSort.paintedWidth / 5 + tableView.headerSpacing) : 0)) / 2 : hifi.dimensions.tablePadding text: styleData.value size: hifi.fontSizes.tableHeading @@ -84,6 +89,8 @@ TableView { anchors.verticalCenter: parent.verticalCenter } + //actual image of sort indicator in glyph font only 20% of real font size + //i.e. if the charachter size set to 60 pixels, actual image is 12 pixels HiFiGlyphs { id: titleSort text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn @@ -92,8 +99,13 @@ TableView { size: hifi.fontSizes.tableHeadingIcon anchors.verticalCenter: titleText.verticalCenter anchors.left: titleText.right - anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 3 + tableView.headerSpacing) + anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 2.5) + tableView.headerSpacing visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column + onXChanged: { + titlePaintedPos[styleData.column] = titleText.x + titleText.paintedWidth + + paintedWidth / 5 + tableView.headerSpacing*2 + titlePaintedPosSignal(styleData.column) + } } Rectangle { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index bb54ba9e57..8fb27714ee 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -30,7 +30,7 @@ Rectangle { property int myCardWidth: width - upperRightInfoContainer.width; property int myCardHeight: 100; property int rowHeight: 60; - property int actionButtonWidth: 55; + property int actionButtonWidth: 65; property int locationColumnWidth: 170; property int nearbyNameCardWidth: nearbyTable.width - (iAmAdmin ? (actionButtonWidth * 4) : (actionButtonWidth * 2)) - 4 - hifi.dimensions.scrollbarBackgroundWidth; property int connectionsNameCardWidth: connectionsTable.width - locationColumnWidth - actionButtonWidth - 4 - hifi.dimensions.scrollbarBackgroundWidth; @@ -415,6 +415,7 @@ Rectangle { movable: false; resizable: false; } + TableViewColumn { role: "ignore"; title: "IGNORE"; @@ -599,13 +600,23 @@ Rectangle { } // This Rectangle refers to the [?] popup button next to "NAMES" Rectangle { + id: questionRect color: hifi.colors.tableBackgroundLight; width: 20; height: hifi.dimensions.tableHeaderHeight - 2; anchors.left: nearbyTable.left; anchors.top: nearbyTable.top; anchors.topMargin: 1; - anchors.leftMargin: actionButtonWidth + nearbyNameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6; + + Connections { + target: nearbyTable + onTitlePaintedPosSignal: { + if (column === 1) { // name column + questionRect.anchors.leftMargin = actionButtonWidth + nearbyTable.titlePaintedPos[column] + } + } + } + RalewayRegular { id: helpText; text: "[?]"; From 77ef0e05a1c3662cbd431b50b6b26bb22483a81f Mon Sep 17 00:00:00 2001 From: vladest Date: Mon, 26 Feb 2018 13:43:50 +0100 Subject: [PATCH 59/61] Search main window by checking object name --- libraries/ui/src/OffscreenUi.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 4309789b03..7a938f39c8 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -625,8 +625,7 @@ private: auto windows = qApp->topLevelWindows(); QWindow* result = nullptr; for (auto window : windows) { - QVariant isMainWindow = window->property("MainWindow"); - if (!qobject_cast(window)) { + if (window->objectName().contains("MainWindow")) { result = window; break; } From 0404b722e4c9766f8f7b6f7ca2e50cb03e40c83d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Feb 2018 10:00:32 -0800 Subject: [PATCH 60/61] Code review feedback --- .../render-utils/src/CauterizedModel.cpp | 2 +- .../render-utils/src/MeshPartPayload.cpp | 31 ++++++++++++------- libraries/render-utils/src/MeshPartPayload.h | 8 ++--- libraries/render-utils/src/Model.cpp | 9 ++---- libraries/shared/src/GLMHelpers.cpp | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index fb1d31d273..6806b41647 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -275,7 +275,7 @@ void CauterizedModel::updateRenderItems() { data.setEnableCauterization(enableCauterization); data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL); data.setLayer(isLayeredInFront, isLayeredInHUD); - data.setShapeKey(invalidatePayloadShapeKey, isWireframe); + data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning); }); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 99048fe324..2637d24d67 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -223,7 +223,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in assert(model && model->isLoaded()); - _useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); + bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); _blendedVertexBuffer = model->_blendedVertexBuffers[_meshIndex]; auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); @@ -231,7 +231,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in updateMeshPart(modelMesh, partIndex); - if (_useDualQuaternionSkinning) { + if (useDualQuaternionSkinning) { computeAdjustedLocalBound(state.clusterDualQuaternions); } else { computeAdjustedLocalBound(state.clusterMatrices); @@ -239,7 +239,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in updateTransform(transform, offsetTransform); Transform renderTransform = transform; - if (_useDualQuaternionSkinning) { + if (useDualQuaternionSkinning) { if (state.clusterDualQuaternions.size() == 1) { const auto& dq = state.clusterDualQuaternions[0]; Transform transform(dq.getRotation(), @@ -281,6 +281,13 @@ void ModelMeshPartPayload::notifyLocationChanged() { } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { + + // reset cluster buffer if we change the cluster buffer type + if (_clusterBufferType != ClusterBufferType::Matrices) { + _clusterBuffer.reset(); + } + _clusterBufferType = ClusterBufferType::Matrices; + // Once computed the cluster matrices, update the buffer(s) if (clusterMatrices.size() > 1) { if (!_clusterBuffer) { @@ -295,6 +302,13 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clu } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterDualQuaternions) { + + // reset cluster buffer if we change the cluster buffer type + if (_clusterBufferType != ClusterBufferType::DualQuaternions) { + _clusterBuffer.reset(); + } + _clusterBufferType = ClusterBufferType::DualQuaternions; + // Once computed the cluster matrices, update the buffer(s) if (clusterDualQuaternions.size() > 1) { if (!_clusterBuffer) { @@ -360,7 +374,7 @@ int ModelMeshPartPayload::getLayer() const { return _layer; } -void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe) { +void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe, bool useDualQuaternionSkinning) { if (invalidateShapeKey) { _shapeKey = ShapeKey::Builder::invalid(); return; @@ -407,7 +421,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe if (isWireframe) { builder.withWireframe(); } - if (_useDualQuaternionSkinning && isSkinned) { + if (isSkinned && useDualQuaternionSkinning) { builder.withDualQuatSkinned(); } @@ -497,10 +511,3 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); - void setUseDualQuaternionSkinning(bool value); - gpu::BufferPointer _clusterBuffer; + enum class ClusterBufferType { Matrices, DualQuaternions }; + ClusterBufferType _clusterBufferType { ClusterBufferType::Matrices }; + int _meshIndex; int _shapeID; bool _isSkinned{ false }; bool _isBlendShaped { false }; bool _hasTangents { false }; - bool _useDualQuaternionSkinning { false }; private: void initCache(const ModelPointer& model); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8318715732..4198193fc9 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -288,7 +288,6 @@ void Model::updateRenderItems() { invalidatePayloadShapeKey, isWireframe, isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { - data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); } else { @@ -314,7 +313,7 @@ void Model::updateRenderItems() { data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled); data.setLayer(isLayeredInFront, isLayeredInHUD); - data.setShapeKey(invalidatePayloadShapeKey, isWireframe); + data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning); }); } @@ -1591,8 +1590,7 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par data.addMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); - data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); - data.setShapeKey(invalidatePayloadShapeKey, wireframe); + data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); }); } } @@ -1618,8 +1616,7 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string data.removeMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); - data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); - data.setShapeKey(invalidatePayloadShapeKey, wireframe); + data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning); }); } } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 46e484cf2b..ad2c991c49 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -602,5 +602,5 @@ glm::vec3 randVector() { } bool isNonUniformScale(const glm::vec3& scale) { - return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON; + return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON || fabsf(scale.z - scale.x); } From c8af9c6f04c85e2e29334b6f1ef92854e6466e6f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Feb 2018 10:05:15 -0800 Subject: [PATCH 61/61] Missing EPSILON --- libraries/shared/src/GLMHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index ad2c991c49..72710a6a7d 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -602,5 +602,5 @@ glm::vec3 randVector() { } bool isNonUniformScale(const glm::vec3& scale) { - return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON || fabsf(scale.z - scale.x); + return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON || fabsf(scale.z - scale.x) > EPSILON; }