Merge pull request #14935 from SamGondelman/matEntity

Case 20920: Move Material Entity logic to render thread
This commit is contained in:
John Conklin II 2019-02-19 10:59:51 -08:00 committed by GitHub
commit 1348baecc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 445 additions and 356 deletions

View file

@ -1911,46 +1911,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
}, Qt::QueuedConnection);
EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
EntityTreeRenderer::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
if (_aboutToQuit) {
return false;
}
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) {
renderable->addMaterial(material, parentMaterialName);
}
// even if we don't find it, try to find the entity
auto entity = getEntities()->getEntity(entityID);
if (entity) {
entity->addMaterial(material, parentMaterialName);
return true;
}
return false;
});
EntityTree::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
EntityTreeRenderer::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
if (_aboutToQuit) {
return false;
}
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) {
renderable->removeMaterial(material, parentMaterialName);
}
// even if we don't find it, try to find the entity
auto entity = getEntities()->getEntity(entityID);
if (entity) {
entity->removeMaterial(material, parentMaterialName);
return true;
}
return false;
});
EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
if (avatar) {
@ -1959,7 +1947,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
return false;
});
EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID);
if (avatar) {

View file

@ -1360,3 +1360,36 @@ EntityEditPacketSender* EntityTreeRenderer::getPacketSender() {
EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr;
return packetSender;
}
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTreeRenderer::_addMaterialToEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTreeRenderer::_removeMaterialFromEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTreeRenderer::_addMaterialToAvatarOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTreeRenderer::_removeMaterialFromAvatarOperator = nullptr;
bool EntityTreeRenderer::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
if (_addMaterialToEntityOperator) {
return _addMaterialToEntityOperator(entityID, material, parentMaterialName);
}
return false;
}
bool EntityTreeRenderer::removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
if (_removeMaterialFromEntityOperator) {
return _removeMaterialFromEntityOperator(entityID, material, parentMaterialName);
}
return false;
}
bool EntityTreeRenderer::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
if (_addMaterialToAvatarOperator) {
return _addMaterialToAvatarOperator(avatarID, material, parentMaterialName);
}
return false;
}
bool EntityTreeRenderer::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
if (_removeMaterialFromAvatarOperator) {
return _removeMaterialFromAvatarOperator(avatarID, material, parentMaterialName);
}
return false;
}

View file

@ -120,6 +120,16 @@ public:
EntityEditPacketSender* getPacketSender();
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; }
static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName);
static bool removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName);
static void setAddMaterialToAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; }
static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName);
static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName);
signals:
void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID);
@ -255,6 +265,11 @@ private:
workload::SpacePointer _space{ new workload::Space() };
workload::Transaction::Updates _spaceUpdates;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToAvatarOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
};

View file

@ -146,7 +146,6 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entit
_needsRenderUpdate = true;
emit requestRenderUpdate();
});
_materials = entity->getMaterials();
}
EntityRenderer::~EntityRenderer() { }

View file

@ -14,42 +14,210 @@
using namespace render;
using namespace render::entities;
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
if (entity->getMaterial() != _drawMaterial) {
return true;
}
if (entity->getParentID() != _parentID) {
return true;
}
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
bool MaterialEntityRenderer::needsRenderUpdate() const {
if (_retryApply) {
return true;
}
if (!_texturesLoaded) {
return true;
}
return Parent::needsRenderUpdate();
}
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
if (resultWithReadLock<bool>([&] {
if (entity->getMaterialMappingMode() != _materialMappingMode) {
return true;
}
if (entity->getMaterialRepeat() != _materialRepeat) {
return true;
}
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
return true;
}
if (entity->getTransform() != _transform) {
return true;
}
if (entity->getUnscaledDimensions() != _dimensions) {
return true;
}
if (entity->getMaterialURL() != _materialURL) {
return true;
}
if (entity->getMaterialData() != _materialData) {
return true;
}
if (entity->getParentMaterialName() != _parentMaterialName) {
return true;
}
if (entity->getParentID() != _parentID) {
return true;
}
if (entity->getPriority() != _priority) {
return true;
}
return false;
})) {
return true;
}
return false;
}
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
withWriteLock([&] {
if (_drawMaterial != entity->getMaterial()) {
_texturesLoaded = false;
_drawMaterial = entity->getMaterial();
bool deleteNeeded = false;
bool addNeeded = _retryApply;
bool transformChanged = false;
{
MaterialMappingMode mode = entity->getMaterialMappingMode();
if (mode != _materialMappingMode) {
_materialMappingMode = mode;
transformChanged = true;
}
}
_parentID = entity->getParentID();
_materialMappingPos = entity->getMaterialMappingPos();
_materialMappingScale = entity->getMaterialMappingScale();
_materialMappingRot = entity->getMaterialMappingRot();
{
bool repeat = entity->getMaterialRepeat();
if (repeat != _materialRepeat) {
_materialRepeat = repeat;
transformChanged = true;
}
}
{
glm::vec2 mappingPos = entity->getMaterialMappingPos();
glm::vec2 mappingScale = entity->getMaterialMappingScale();
float mappingRot = entity->getMaterialMappingRot();
if (mappingPos != _materialMappingPos || mappingScale != _materialMappingScale || mappingRot != _materialMappingRot) {
_materialMappingPos = mappingPos;
_materialMappingScale = mappingScale;
_materialMappingRot = mappingRot;
transformChanged |= _materialMappingMode == MaterialMappingMode::UV;
}
}
{
Transform transform = entity->getTransform();
glm::vec3 dimensions = entity->getUnscaledDimensions();
if (transform != _transform || dimensions != _dimensions) {
_transform = transform;
_dimensions = dimensions;
transformChanged |= _materialMappingMode == MaterialMappingMode::PROJECTED;
}
}
{
auto material = getMaterial();
// Update the old material regardless of if it's going to change
if (transformChanged && material && !_parentID.isNull()) {
deleteNeeded = true;
addNeeded = true;
applyTextureTransform(material);
}
}
bool urlChanged = false;
std::string newCurrentMaterialName = _currentMaterialName;
{
QString materialURL = entity->getMaterialURL();
if (materialURL != _materialURL) {
_materialURL = materialURL;
if (_materialURL.contains("?")) {
auto split = _materialURL.split("?");
newCurrentMaterialName = split.last().toStdString();
}
urlChanged = true;
}
}
bool usingMaterialData = _materialURL.startsWith("materialData");
bool materialDataChanged = false;
QUuid oldParentID = _parentID;
QString oldParentMaterialName = _parentMaterialName;
{
QString materialData = entity->getMaterialData();
if (materialData != _materialData) {
_materialData = materialData;
if (usingMaterialData) {
materialDataChanged = true;
}
}
}
{
QString parentMaterialName = entity->getParentMaterialName();
if (parentMaterialName != _parentMaterialName) {
_parentMaterialName = parentMaterialName;
deleteNeeded = true;
addNeeded = true;
}
}
{
QUuid parentID = entity->getParentID();
if (parentID != _parentID) {
_parentID = parentID;
deleteNeeded = true;
addNeeded = true;
}
}
{
quint16 priority = entity->getPriority();
if (priority != _priority) {
_priority = priority;
deleteNeeded = true;
addNeeded = true;
}
}
if (urlChanged && !usingMaterialData) {
_networkMaterial = MaterialCache::instance().getMaterial(_materialURL);
auto onMaterialRequestFinished = [&, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
if (success) {
deleteMaterial(oldParentID, oldParentMaterialName);
_texturesLoaded = false;
_parsedMaterials = _networkMaterial->parsedMaterials;
setCurrentMaterialName(newCurrentMaterialName);
applyMaterial();
} else {
deleteMaterial(oldParentID, oldParentMaterialName);
_retryApply = false;
_texturesLoaded = true;
}
};
if (_networkMaterial) {
if (_networkMaterial->isLoaded()) {
onMaterialRequestFinished(!_networkMaterial->isFailed());
} else {
connect(_networkMaterial.data(), &Resource::finished, this, onMaterialRequestFinished);
}
}
} else if (materialDataChanged && usingMaterialData) {
deleteMaterial(oldParentID, oldParentMaterialName);
_texturesLoaded = false;
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL);
// Since our material changed, the current name might not be valid anymore, so we need to update
setCurrentMaterialName(newCurrentMaterialName);
applyMaterial();
} else {
if (deleteNeeded) {
deleteMaterial(oldParentID, oldParentMaterialName);
}
if (addNeeded) {
applyMaterial();
}
}
{
auto material = getMaterial();
bool newTexturesLoaded = material ? !material->isMissingTexture() : false;
if (!_texturesLoaded && newTexturesLoaded) {
material->checkResetOpacityMap();
}
_texturesLoaded = newTexturesLoaded;
}
_renderTransform = getModelTransform();
const float MATERIAL_ENTITY_SCALE = 0.5f;
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
bool newTexturesLoaded = _drawMaterial ? !_drawMaterial->isMissingTexture() : false;
if (!_texturesLoaded && newTexturesLoaded) {
_drawMaterial->checkResetOpacityMap();
}
_texturesLoaded = newTexturesLoaded;
});
}
@ -61,8 +229,9 @@ ItemKey MaterialEntityRenderer::getKey() {
builder.withInvisible();
}
if (_drawMaterial) {
auto matKey = _drawMaterial->getKey();
const auto drawMaterial = getMaterial();
if (drawMaterial) {
auto matKey = drawMaterial->getKey();
if (matKey.isTranslucent()) {
builder.withTransparent();
}
@ -73,8 +242,9 @@ ItemKey MaterialEntityRenderer::getKey() {
ShapeKey MaterialEntityRenderer::getShapeKey() {
graphics::MaterialKey drawMaterialKey;
if (_drawMaterial) {
drawMaterialKey = _drawMaterial->getKey();
const auto drawMaterial = getMaterial();
if (drawMaterial) {
drawMaterialKey = drawMaterial->getKey();
}
bool isTranslucent = drawMaterialKey.isTranslucent();
@ -112,18 +282,24 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
// Don't render if our parent is set or our material is null
QUuid parentID;
withReadLock([&] {
parentID = _parentID;
});
if (!parentID.isNull()) {
return;
}
Transform renderTransform;
graphics::MaterialPointer drawMaterial;
Transform textureTransform;
withReadLock([&] {
parentID = _parentID;
renderTransform = _renderTransform;
drawMaterial = _drawMaterial;
drawMaterial = getMaterial();
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
});
if (!parentID.isNull() || !drawMaterial) {
if (!drawMaterial) {
return;
}
@ -142,3 +318,86 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
}
void MaterialEntityRenderer::setCurrentMaterialName(const std::string& currentMaterialName) {
if (_parsedMaterials.networkMaterials.find(currentMaterialName) != _parsedMaterials.networkMaterials.end()) {
_currentMaterialName = currentMaterialName;
} else if (_parsedMaterials.names.size() > 0) {
_currentMaterialName = _parsedMaterials.names[0];
}
}
std::shared_ptr<NetworkMaterial> MaterialEntityRenderer::getMaterial() const {
auto material = _parsedMaterials.networkMaterials.find(_currentMaterialName);
if (material != _parsedMaterials.networkMaterials.end()) {
return material->second;
} else {
return nullptr;
}
}
void MaterialEntityRenderer::deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName) {
std::shared_ptr<NetworkMaterial> material = _appliedMaterial;
if (!material || oldParentID.isNull()) {
return;
}
// Our parent could be an entity or an avatar
std::string oldParentMaterialNameStd = oldParentMaterialName.toStdString();
if (EntityTreeRenderer::removeMaterialFromEntity(oldParentID, material, oldParentMaterialNameStd)) {
_appliedMaterial = nullptr;
return;
}
if (EntityTreeRenderer::removeMaterialFromAvatar(oldParentID, material, oldParentMaterialNameStd)) {
_appliedMaterial = nullptr;
return;
}
// if a remove fails, our parent is gone, so we don't need to retry
}
void MaterialEntityRenderer::applyTextureTransform(std::shared_ptr<NetworkMaterial>& material) {
Transform textureTransform;
if (_materialMappingMode == MaterialMappingMode::UV) {
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f));
textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot)));
textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f));
} else if (_materialMappingMode == MaterialMappingMode::PROJECTED) {
textureTransform = _transform;
textureTransform.postScale(_dimensions);
// Pass the inverse transform here so we don't need to compute it in the shaders
textureTransform.evalFromRawMatrix(textureTransform.getInverseMatrix());
}
material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat);
}
void MaterialEntityRenderer::applyMaterial() {
_retryApply = false;
std::shared_ptr<NetworkMaterial> material = getMaterial();
QUuid parentID = _parentID;
if (!material || parentID.isNull()) {
_appliedMaterial = nullptr;
return;
}
applyTextureTransform(material);
graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority);
// Our parent could be an entity or an avatar
std::string parentMaterialName = _parentMaterialName.toStdString();
if (EntityTreeRenderer::addMaterialToEntity(parentID, materialLayer, parentMaterialName)) {
_appliedMaterial = material;
return;
}
if (EntityTreeRenderer::addMaterialToAvatar(parentID, materialLayer, parentMaterialName)) {
_appliedMaterial = material;
return;
}
// if we've reached this point, we couldn't find our parent, so we need to try again later
_retryApply = true;
}

View file

@ -13,6 +13,8 @@
#include <MaterialEntityItem.h>
#include <material-networking/MaterialCache.h>
class NetworkMaterial;
namespace render { namespace entities {
@ -22,22 +24,46 @@ class MaterialEntityRenderer : public TypedEntityRenderer<MaterialEntityItem> {
using Pointer = std::shared_ptr<MaterialEntityRenderer>;
public:
MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {}
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
private:
virtual bool needsRenderUpdate() const override;
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
virtual void doRender(RenderArgs* args) override;
ItemKey getKey() override;
ShapeKey getShapeKey() override;
QString _materialURL;
QString _materialData;
QString _parentMaterialName;
quint16 _priority;
QUuid _parentID;
MaterialMappingMode _materialMappingMode;
bool _materialRepeat;
glm::vec2 _materialMappingPos;
glm::vec2 _materialMappingScale;
float _materialMappingRot;
bool _texturesLoaded { false };
Transform _transform;
glm::vec3 _dimensions;
bool _texturesLoaded { false };
bool _retryApply { false };
std::shared_ptr<NetworkMaterial> getMaterial() const;
void setCurrentMaterialName(const std::string& currentMaterialName);
void applyTextureTransform(std::shared_ptr<NetworkMaterial>& material);
void applyMaterial();
void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName);
NetworkMaterialResourcePointer _networkMaterial;
NetworkMaterialResource::ParsedMaterials _parsedMaterials;
std::shared_ptr<NetworkMaterial> _appliedMaterial;
std::string _currentMaterialName;
std::shared_ptr<NetworkMaterial> _drawMaterial;
};
} }

View file

@ -3250,25 +3250,6 @@ void EntityItem::setSpaceIndex(int32_t index) {
void EntityItem::preDelete() {
}
void EntityItem::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].push(material);
}
void EntityItem::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].remove(material);
}
std::unordered_map<std::string, graphics::MultiMaterial> EntityItem::getMaterials() {
std::unordered_map<std::string, graphics::MultiMaterial> toReturn;
{
std::lock_guard<std::mutex> lock(_materialsLock);
toReturn = _materials;
}
return toReturn;
}
bool EntityItem::getCloneable() const {
bool result;
withReadLock([&] {

View file

@ -37,8 +37,6 @@
#include "EntityDynamicInterface.h"
#include "GrabPropertyGroup.h"
#include "graphics/Material.h"
class EntitySimulation;
class EntityTreeElement;
class EntityTreeElementExtraEncodeData;
@ -542,10 +540,6 @@ public:
virtual void preDelete();
virtual void postParentFixup() {}
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
std::unordered_map<std::string, graphics::MultiMaterial> getMaterials();
void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; }
uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; }
@ -754,11 +748,7 @@ protected:
QHash<QUuid, EntityDynamicPointer> _grabActions;
private:
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
std::mutex _materialsLock;
static std::function<glm::quat(const glm::vec3&, const glm::quat&, BillboardMode)> _getBillboardRotationOperator;
};
#endif // hifi_EntityItem_h

View file

@ -2953,41 +2953,9 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
return entity->getJointNames();
}
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTree::_addMaterialToEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTree::_removeMaterialFromEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTree::_addMaterialToAvatarOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTree::_removeMaterialFromAvatarOperator = nullptr;
std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr;
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr;
bool EntityTree::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
if (_addMaterialToEntityOperator) {
return _addMaterialToEntityOperator(entityID, material, parentMaterialName);
}
return false;
}
bool EntityTree::removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
if (_removeMaterialFromEntityOperator) {
return _removeMaterialFromEntityOperator(entityID, material, parentMaterialName);
}
return false;
}
bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
if (_addMaterialToAvatarOperator) {
return _addMaterialToAvatarOperator(avatarID, material, parentMaterialName);
}
return false;
}
bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
if (_removeMaterialFromAvatarOperator) {
return _removeMaterialFromAvatarOperator(avatarID, material, parentMaterialName);
}
return false;
}
QObject* EntityTree::getEntityObject(const QUuid& id) {
if (_getEntityObjectOperator) {
return _getEntityObjectOperator(id);

View file

@ -262,16 +262,6 @@ public:
void setIsServerlessMode(bool value) { _serverlessDomain = value; }
bool isServerlessMode() const { return _serverlessDomain; }
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; }
static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName);
static bool removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName);
static void setAddMaterialToAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; }
static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName);
static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName);
static void setGetEntityObjectOperator(std::function<QObject*(const QUuid&)> getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; }
static QObject* getEntityObject(const QUuid& id);
@ -386,10 +376,6 @@ private:
std::shared_ptr<AvatarData> _myAvatar{ nullptr };
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToAvatarOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;

View file

@ -16,9 +16,6 @@
EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
entity->setProperties(properties);
// When you reload content, setProperties doesn't have any of the propertiesChanged flags set, so it won't trigger a material add
entity->removeMaterial();
entity->applyMaterial();
return entity;
}
@ -27,10 +24,6 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit
_type = EntityTypes::Material;
}
MaterialEntityItem::~MaterialEntityItem() {
removeMaterial();
}
EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL);
@ -131,7 +124,6 @@ void MaterialEntityItem::debugDump() const {
qCDebug(entities) << " MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------";
qCDebug(entities) << " name:" << _name;
qCDebug(entities) << " material url:" << _materialURL;
qCDebug(entities) << " current material name:" << _currentMaterialName.c_str();
qCDebug(entities) << " material mapping mode:" << _materialMappingMode;
qCDebug(entities) << " material repeat:" << _materialRepeat;
qCDebug(entities) << " priority:" << _priority;
@ -154,208 +146,101 @@ void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) {
}
}
std::shared_ptr<NetworkMaterial> MaterialEntityItem::getMaterial() const {
auto material = _parsedMaterials.networkMaterials.find(_currentMaterialName);
if (material != _parsedMaterials.networkMaterials.end()) {
return material->second;
} else {
return nullptr;
}
QString MaterialEntityItem::getMaterialURL() const {
return resultWithReadLock<QString>([&] {
return _materialURL;
});
}
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) {
bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData");
if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) {
removeMaterial();
_materialURL = materialURLString;
if (materialURLString.contains("?")) {
auto split = materialURLString.split("?");
_currentMaterialName = split.last().toStdString();
}
if (usingMaterialData) {
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getMaterialData().toUtf8()), materialURLString);
// Since our material changed, the current name might not be valid anymore, so we need to update
setCurrentMaterialName(_currentMaterialName);
applyMaterial();
} else {
_networkMaterial = MaterialCache::instance().getMaterial(materialURLString);
auto onMaterialRequestFinished = [&](bool success) {
if (success) {
_parsedMaterials = _networkMaterial->parsedMaterials;
setCurrentMaterialName(_currentMaterialName);
applyMaterial();
}
};
if (_networkMaterial) {
if (_networkMaterial->isLoaded()) {
onMaterialRequestFinished(!_networkMaterial->isFailed());
} else {
connect(_networkMaterial.data(), &Resource::finished, this, onMaterialRequestFinished);
}
}
}
}
void MaterialEntityItem::setMaterialURL(const QString& materialURL) {
withWriteLock([&] {
_materialURL = materialURL;
});
}
void MaterialEntityItem::setCurrentMaterialName(const std::string& currentMaterialName) {
if (_parsedMaterials.networkMaterials.find(currentMaterialName) != _parsedMaterials.networkMaterials.end()) {
_currentMaterialName = currentMaterialName;
} else if (_parsedMaterials.names.size() > 0) {
_currentMaterialName = _parsedMaterials.names[0];
}
QString MaterialEntityItem::getMaterialData() const {
return resultWithReadLock<QString>([&] {
return _materialData;
});
}
void MaterialEntityItem::setMaterialData(const QString& materialData) {
if (_materialData != materialData) {
withWriteLock([&] {
_materialData = materialData;
if (_materialURL.startsWith("materialData")) {
// Trigger material update when material data changes
setMaterialURL(_materialURL, true);
}
}
});
}
MaterialMappingMode MaterialEntityItem::getMaterialMappingMode() const {
return resultWithReadLock<MaterialMappingMode>([&] {
return _materialMappingMode;
});
}
void MaterialEntityItem::setMaterialMappingMode(MaterialMappingMode mode) {
if (_materialMappingMode != mode) {
removeMaterial();
withWriteLock([&] {
_materialMappingMode = mode;
setUnscaledDimensions(_desiredDimensions);
applyMaterial();
}
});
setUnscaledDimensions(_desiredDimensions);
}
void MaterialEntityItem::setMaterialRepeat(bool repeat) {
if (_materialRepeat != repeat) {
removeMaterial();
_materialRepeat = repeat;
applyMaterial();
}
}
void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) {
if (_materialMappingPos != materialMappingPos) {
removeMaterial();
_materialMappingPos = materialMappingPos;
applyMaterial();
}
}
void MaterialEntityItem::setMaterialMappingScale(const glm::vec2& materialMappingScale) {
if (_materialMappingScale != materialMappingScale) {
removeMaterial();
_materialMappingScale = materialMappingScale;
applyMaterial();
}
}
void MaterialEntityItem::setMaterialMappingRot(const float& materialMappingRot) {
if (_materialMappingRot != materialMappingRot) {
removeMaterial();
_materialMappingRot = materialMappingRot;
applyMaterial();
}
quint16 MaterialEntityItem::getPriority() const {
return resultWithReadLock<quint16>([&] {
return _priority;
});
}
void MaterialEntityItem::setPriority(quint16 priority) {
if (_priority != priority) {
removeMaterial();
withWriteLock([&] {
_priority = priority;
applyMaterial();
}
});
}
QString MaterialEntityItem::getParentMaterialName() const {
return resultWithReadLock<QString>([&] {
return _parentMaterialName;
});
}
void MaterialEntityItem::setParentMaterialName(const QString& parentMaterialName) {
if (_parentMaterialName != parentMaterialName) {
removeMaterial();
withWriteLock([&] {
_parentMaterialName = parentMaterialName;
applyMaterial();
}
});
}
void MaterialEntityItem::setParentID(const QUuid& parentID) {
if (getParentID() != parentID) {
removeMaterial();
EntityItem::setParentID(parentID);
applyMaterial();
}
glm::vec2 MaterialEntityItem::getMaterialMappingPos() const {
return resultWithReadLock<glm::vec2>([&] {
return _materialMappingPos;
});
}
void MaterialEntityItem::locationChanged(bool tellPhysics) {
EntityItem::locationChanged();
if (_materialMappingMode == MaterialMappingMode::PROJECTED) {
removeMaterial();
applyMaterial();
}
void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) {
withWriteLock([&] {
_materialMappingPos = materialMappingPos;
});
}
void MaterialEntityItem::dimensionsChanged() {
EntityItem::dimensionsChanged();
if (_materialMappingMode == MaterialMappingMode::PROJECTED) {
removeMaterial();
applyMaterial();
}
glm::vec2 MaterialEntityItem::getMaterialMappingScale() const {
return resultWithReadLock<glm::vec2>([&] {
return _materialMappingScale;
});
}
void MaterialEntityItem::removeMaterial() {
graphics::MaterialPointer material = getMaterial();
if (!material) {
return;
}
QUuid parentID = getParentID();
if (parentID.isNull()) {
return;
}
// Our parent could be an entity or an avatar
if (EntityTree::removeMaterialFromEntity(parentID, material, getParentMaterialName().toStdString())) {
return;
}
if (EntityTree::removeMaterialFromAvatar(parentID, material, getParentMaterialName().toStdString())) {
return;
}
// if a remove fails, our parent is gone, so we don't need to retry
void MaterialEntityItem::setMaterialMappingScale(const glm::vec2& materialMappingScale) {
withWriteLock([&] {
_materialMappingScale = materialMappingScale;
});
}
void MaterialEntityItem::applyMaterial() {
_retryApply = false;
graphics::MaterialPointer material = getMaterial();
QUuid parentID = getParentID();
if (!material || parentID.isNull()) {
return;
}
float MaterialEntityItem::getMaterialMappingRot() const {
return resultWithReadLock<float>([&] {
return _materialMappingRot;
});
}
Transform textureTransform;
if (_materialMappingMode == MaterialMappingMode::UV) {
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f));
textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot)));
textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f));
} else if (_materialMappingMode == MaterialMappingMode::PROJECTED) {
textureTransform = getTransform();
textureTransform.postScale(getUnscaledDimensions());
// Pass the inverse transform here so we don't need to compute it in the shaders
textureTransform.evalFromRawMatrix(textureTransform.getInverseMatrix());
}
material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat);
graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, getPriority());
// Our parent could be an entity or an avatar
if (EntityTree::addMaterialToEntity(parentID, materialLayer, getParentMaterialName().toStdString())) {
return;
}
if (EntityTree::addMaterialToAvatar(parentID, materialLayer, getParentMaterialName().toStdString())) {
return;
}
// if we've reached this point, we couldn't find our parent, so we need to try again later
_retryApply = true;
void MaterialEntityItem::setMaterialMappingRot(float materialMappingRot) {
withWriteLock([&] {
_materialMappingRot = materialMappingRot;
});
}
AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
@ -372,18 +257,3 @@ AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
}
return aaCube;
}
void MaterialEntityItem::postParentFixup() {
removeMaterial();
_queryAACubeSet = false; // force an update so we contain our parent
updateQueryAACube();
applyMaterial();
}
void MaterialEntityItem::update(const quint64& now) {
if (_retryApply) {
applyMaterial();
}
EntityItem::update(now);
}

View file

@ -12,8 +12,6 @@
#include "EntityItem.h"
#include "MaterialMappingMode.h"
#include <model-networking/ModelCache.h>
#include <material-networking/MaterialCache.h>
class MaterialEntityItem : public EntityItem {
using Pointer = std::shared_ptr<MaterialEntityItem>;
@ -21,13 +19,9 @@ public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
MaterialEntityItem(const EntityItemID& entityItemID);
~MaterialEntityItem();
ALLOW_INSTANTIATION // This class can be instantiated
void update(const quint64& now) override;
bool needsToCallUpdate() const override { return true; }
// methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
@ -52,44 +46,30 @@ public:
virtual void setUnscaledDimensions(const glm::vec3& value) override;
QString getMaterialURL() const { return _materialURL; }
void setMaterialURL(const QString& materialURLString, bool materialDataChanged = false);
QString getMaterialURL() const;
void setMaterialURL(const QString& materialURL);
void setCurrentMaterialName(const std::string& currentMaterialName);
QString getMaterialData() const;
void setMaterialData(const QString& materialData);
MaterialMappingMode getMaterialMappingMode() const { return _materialMappingMode; }
MaterialMappingMode getMaterialMappingMode() const;
void setMaterialMappingMode(MaterialMappingMode mode);
bool getMaterialRepeat() const { return _materialRepeat; }
void setMaterialRepeat(bool repeat);
void setMaterialRepeat(bool repeat) { _materialRepeat = repeat; }
quint16 getPriority() const { return _priority; }
quint16 getPriority() const;
void setPriority(quint16 priority);
QString getParentMaterialName() const { return _parentMaterialName; }
QString getParentMaterialName() const;
void setParentMaterialName(const QString& parentMaterialName);
glm::vec2 getMaterialMappingPos() const { return _materialMappingPos; }
glm::vec2 getMaterialMappingPos() const;
void setMaterialMappingPos(const glm::vec2& materialMappingPos);
glm::vec2 getMaterialMappingScale() const { return _materialMappingScale; }
glm::vec2 getMaterialMappingScale() const;
void setMaterialMappingScale(const glm::vec2& materialMappingScale);
float getMaterialMappingRot() const { return _materialMappingRot; }
void setMaterialMappingRot(const float& materialMappingRot);
QString getMaterialData() const { return _materialData; }
void setMaterialData(const QString& materialData);
std::shared_ptr<NetworkMaterial> getMaterial() const;
void setParentID(const QUuid& parentID) override;
void locationChanged(bool tellPhysics) override;
void dimensionsChanged() override;
void applyMaterial();
void removeMaterial();
void postParentFixup() override;
float getMaterialMappingRot() const;
void setMaterialMappingRot(float materialMappingRot);
AACube calculateInitialQueryAACube(bool& success) override;
@ -128,12 +108,6 @@ private:
float _materialMappingRot { 0 };
QString _materialData;
NetworkMaterialResourcePointer _networkMaterial;
NetworkMaterialResource::ParsedMaterials _parsedMaterials;
std::string _currentMaterialName;
bool _retryApply { false };
};
#endif // hifi_MaterialEntityItem_h