mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:37:17 +02:00
starting improve entity updates pt 2
This commit is contained in:
parent
89c006d190
commit
5a8c1a0374
16 changed files with 433 additions and 624 deletions
|
@ -431,13 +431,13 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
||||||
_visible = entity->getVisible();
|
_visible = entity->getVisible();
|
||||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||||
setRenderLayer(entity->getRenderLayer());
|
setRenderLayer(entity->getRenderLayer());
|
||||||
setPrimitiveMode(entity->getPrimitiveMode());
|
_primitiveMode = entity->getPrimitiveMode();
|
||||||
_canCastShadow = entity->getCanCastShadow();
|
_canCastShadow = entity->getCanCastShadow();
|
||||||
setCullWithParent(entity->getCullWithParent());
|
setCullWithParent(entity->getCullWithParent());
|
||||||
_cauterized = entity->getCauterized();
|
_cauterized = entity->getCauterized();
|
||||||
if (entity->needsZoneOcclusionUpdate()) {
|
if (entity->needsZoneOcclusionUpdate()) {
|
||||||
entity->resetNeedsZoneOcclusionUpdate();
|
entity->resetNeedsZoneOcclusionUpdate();
|
||||||
setRenderWithZones(entity->getRenderWithZones());
|
_renderWithZones = entity->getRenderWithZones();
|
||||||
}
|
}
|
||||||
entity->setNeedsRenderUpdate(false);
|
entity->setNeedsRenderUpdate(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -108,18 +108,7 @@ protected:
|
||||||
|
|
||||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||||
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; }
|
|
||||||
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
|
virtual void setCullWithParent(bool value) { _cullWithParent = value; }
|
||||||
virtual void setRenderWithZones(const QVector<QUuid>& renderWithZones) { _renderWithZones = renderWithZones; }
|
|
||||||
|
|
||||||
template <typename F, typename T>
|
|
||||||
T withReadLockResult(const std::function<T()>& f) {
|
|
||||||
T result;
|
|
||||||
withReadLock([&] {
|
|
||||||
result = f();
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestRenderUpdate();
|
void requestRenderUpdate();
|
||||||
|
|
|
@ -52,14 +52,11 @@ void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
RingGizmoPropertyGroup ringProperties = entity->getRingProperties();
|
RingGizmoPropertyGroup ringProperties = entity->getRingProperties();
|
||||||
withWriteLock([&] {
|
_gizmoType = entity->getGizmoType();
|
||||||
_gizmoType = entity->getGizmoType();
|
if (_ringProperties != ringProperties) {
|
||||||
if (_ringProperties != ringProperties) {
|
_ringProperties = ringProperties;
|
||||||
_ringProperties = ringProperties;
|
dirty = true;
|
||||||
dirty = true;
|
}
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dirty || _prevPrimitiveMode != _primitiveMode || !_ringGeometryID || !_majorTicksGeometryID || !_minorTicksGeometryID) {
|
if (dirty || _prevPrimitiveMode != _primitiveMode || !_ringGeometryID || !_majorTicksGeometryID || !_minorTicksGeometryID) {
|
||||||
_prevPrimitiveMode = _primitiveMode;
|
_prevPrimitiveMode = _primitiveMode;
|
||||||
|
@ -242,19 +239,20 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
||||||
|
|
||||||
if (_gizmoType == GizmoType::RING) {
|
if (_gizmoType == GizmoType::RING) {
|
||||||
Transform transform;
|
Transform transform;
|
||||||
bool hasTickMarks;
|
bool hasTickMarks = _ringProperties.getHasTickMarks();
|
||||||
glm::vec4 tickProperties;
|
glm::vec4 tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||||
|
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||||
bool forward;
|
bool forward;
|
||||||
|
bool wireframe;
|
||||||
|
bool transparent;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
transform = _renderTransform;
|
transform = _renderTransform;
|
||||||
hasTickMarks = _ringProperties.getHasTickMarks();
|
transparent = isTransparent();
|
||||||
tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
|
||||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||||
});
|
});
|
||||||
|
|
||||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,6 @@ bool GridEntityRenderer::isTransparent() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
withWriteLock([&] {
|
|
||||||
_color = entity->getColor();
|
|
||||||
_alpha = entity->getAlpha();
|
|
||||||
_pulseProperties = entity->getPulseProperties();
|
|
||||||
|
|
||||||
_followCamera = entity->getFollowCamera();
|
|
||||||
_majorGridEvery = entity->getMajorGridEvery();
|
|
||||||
_minorGridEvery = entity->getMinorGridEvery();
|
|
||||||
});
|
|
||||||
|
|
||||||
void* key = (void*)this;
|
void* key = (void*)this;
|
||||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
|
@ -49,6 +39,16 @@ void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GridEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
|
_color = entity->getColor();
|
||||||
|
_alpha = entity->getAlpha();
|
||||||
|
_pulseProperties = entity->getPulseProperties();
|
||||||
|
|
||||||
|
_followCamera = entity->getFollowCamera();
|
||||||
|
_majorGridEvery = entity->getMajorGridEvery();
|
||||||
|
_minorGridEvery = entity->getMinorGridEvery();
|
||||||
|
}
|
||||||
|
|
||||||
Item::Bound GridEntityRenderer::getBound() {
|
Item::Bound GridEntityRenderer::getBound() {
|
||||||
if (_followCamera) {
|
if (_followCamera) {
|
||||||
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
||||||
|
@ -73,13 +73,12 @@ ShapeKey GridEntityRenderer::getShapeKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridEntityRenderer::doRender(RenderArgs* args) {
|
void GridEntityRenderer::doRender(RenderArgs* args) {
|
||||||
glm::vec4 color;
|
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||||
|
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||||
glm::vec3 dimensions;
|
glm::vec3 dimensions;
|
||||||
Transform renderTransform;
|
Transform renderTransform;
|
||||||
bool forward;
|
bool forward;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
color = glm::vec4(toGlm(_color), _alpha);
|
|
||||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
|
||||||
dimensions = _dimensions;
|
dimensions = _dimensions;
|
||||||
renderTransform = _renderTransform;
|
renderTransform = _renderTransform;
|
||||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||||
|
|
|
@ -30,10 +30,11 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) 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;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
|
|
||||||
glm::u8vec3 _color;
|
glm::u8vec3 _color { NAN };
|
||||||
float _alpha;
|
float _alpha { NAN };
|
||||||
PulsePropertyGroup _pulseProperties;
|
PulsePropertyGroup _pulseProperties;
|
||||||
|
|
||||||
bool _followCamera;
|
bool _followCamera;
|
||||||
|
|
|
@ -29,44 +29,7 @@ bool ImageEntityRenderer::isTransparent() const {
|
||||||
return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageEntityRenderer::needsRenderUpdate() const {
|
|
||||||
if (resultWithReadLock<bool>([&] {
|
|
||||||
return !_textureIsLoaded;
|
|
||||||
})) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parent::needsRenderUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
withWriteLock([&] {
|
|
||||||
auto imageURL = entity->getImageURL();
|
|
||||||
if (_imageURL != imageURL) {
|
|
||||||
_imageURL = imageURL;
|
|
||||||
if (imageURL.isEmpty()) {
|
|
||||||
_texture.reset();
|
|
||||||
} else {
|
|
||||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
|
|
||||||
}
|
|
||||||
_textureIsLoaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_emissive = entity->getEmissive();
|
|
||||||
_keepAspectRatio = entity->getKeepAspectRatio();
|
|
||||||
_subImage = entity->getSubImage();
|
|
||||||
|
|
||||||
_color = entity->getColor();
|
|
||||||
_alpha = entity->getAlpha();
|
|
||||||
_pulseProperties = entity->getPulseProperties();
|
|
||||||
_billboardMode = entity->getBillboardMode();
|
|
||||||
|
|
||||||
if (!_textureIsLoaded) {
|
|
||||||
emit requestRenderUpdate();
|
|
||||||
}
|
|
||||||
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
|
||||||
});
|
|
||||||
|
|
||||||
void* key = (void*)this;
|
void* key = (void*)this;
|
||||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
|
@ -76,6 +39,33 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
|
auto imageURL = entity->getImageURL();
|
||||||
|
if (_imageURL != imageURL) {
|
||||||
|
_imageURL = imageURL;
|
||||||
|
if (imageURL.isEmpty()) {
|
||||||
|
_texture.reset();
|
||||||
|
} else {
|
||||||
|
_texture = DependencyManager::get<TextureCache>()->getTexture(_imageURL);
|
||||||
|
}
|
||||||
|
_textureIsLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_emissive = entity->getEmissive();
|
||||||
|
_keepAspectRatio = entity->getKeepAspectRatio();
|
||||||
|
_subImage = entity->getSubImage();
|
||||||
|
|
||||||
|
_color = entity->getColor();
|
||||||
|
_alpha = entity->getAlpha();
|
||||||
|
_pulseProperties = entity->getPulseProperties();
|
||||||
|
_billboardMode = entity->getBillboardMode();
|
||||||
|
|
||||||
|
if (!_textureIsLoaded) {
|
||||||
|
emit requestRenderUpdate();
|
||||||
|
}
|
||||||
|
_textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed());
|
||||||
|
}
|
||||||
|
|
||||||
Item::Bound ImageEntityRenderer::getBound() {
|
Item::Bound ImageEntityRenderer::getBound() {
|
||||||
auto bound = Parent::getBound();
|
auto bound = Parent::getBound();
|
||||||
if (_billboardMode != BillboardMode::NONE) {
|
if (_billboardMode != BillboardMode::NONE) {
|
||||||
|
@ -93,33 +83,26 @@ ShapeKey ImageEntityRenderer::getShapeKey() {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
|
|
||||||
withReadLock([&] {
|
if (_emissive) {
|
||||||
if (_emissive) {
|
builder.withUnlit();
|
||||||
builder.withUnlit();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||||
builder.withWireframe();
|
builder.withWireframe();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageEntityRenderer::doRender(RenderArgs* args) {
|
void ImageEntityRenderer::doRender(RenderArgs* args) {
|
||||||
NetworkTexturePointer texture;
|
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||||
QRect subImage;
|
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||||
glm::vec4 color;
|
|
||||||
Transform transform;
|
Transform transform;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
texture = _texture;
|
|
||||||
subImage = _subImage;
|
|
||||||
color = glm::vec4(toGlm(_color), _alpha);
|
|
||||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
|
||||||
transform = _renderTransform;
|
transform = _renderTransform;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_visible || !texture || !texture->isLoaded() || color.a == 0.0f) {
|
if (!_visible || !_texture || !_texture->isLoaded() || color.a == 0.0f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,28 +112,28 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
||||||
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||||
|
|
||||||
batch->setModelTransform(transform);
|
batch->setModelTransform(transform);
|
||||||
batch->setResourceTexture(0, texture->getGPUTexture());
|
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||||
|
|
||||||
float imageWidth = texture->getWidth();
|
float imageWidth = _texture->getWidth();
|
||||||
float imageHeight = texture->getHeight();
|
float imageHeight = _texture->getHeight();
|
||||||
|
|
||||||
QRect fromImage;
|
QRect fromImage;
|
||||||
if (subImage.width() <= 0) {
|
if (_subImage.width() <= 0) {
|
||||||
fromImage.setX(0);
|
fromImage.setX(0);
|
||||||
fromImage.setWidth(imageWidth);
|
fromImage.setWidth(imageWidth);
|
||||||
} else {
|
} else {
|
||||||
float scaleX = imageWidth / texture->getOriginalWidth();
|
float scaleX = imageWidth / _texture->getOriginalWidth();
|
||||||
fromImage.setX(scaleX * subImage.x());
|
fromImage.setX(scaleX * _subImage.x());
|
||||||
fromImage.setWidth(scaleX * subImage.width());
|
fromImage.setWidth(scaleX * _subImage.width());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subImage.height() <= 0) {
|
if (_subImage.height() <= 0) {
|
||||||
fromImage.setY(0);
|
fromImage.setY(0);
|
||||||
fromImage.setHeight(imageHeight);
|
fromImage.setHeight(imageHeight);
|
||||||
} else {
|
} else {
|
||||||
float scaleY = imageHeight / texture->getOriginalHeight();
|
float scaleY = imageHeight / _texture->getOriginalHeight();
|
||||||
fromImage.setY(scaleY * subImage.y());
|
fromImage.setY(scaleY * _subImage.y());
|
||||||
fromImage.setHeight(scaleY * subImage.height());
|
fromImage.setHeight(scaleY * _subImage.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
float maxSize = glm::max(fromImage.width(), fromImage.height());
|
float maxSize = glm::max(fromImage.width(), fromImage.height());
|
||||||
|
|
|
@ -29,8 +29,8 @@ protected:
|
||||||
bool isTransparent() const override;
|
bool isTransparent() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdate() const override;
|
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) 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;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
|
|
||||||
QString _imageURL;
|
QString _imageURL;
|
||||||
|
|
|
@ -16,199 +16,186 @@
|
||||||
using namespace render;
|
using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
bool MaterialEntityRenderer::needsRenderUpdate() const {
|
|
||||||
if (_retryApply) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!_texturesLoaded) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return Parent::needsRenderUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||||
if (resultWithReadLock<bool>([&] {
|
if (resultWithReadLock<bool>([&] {
|
||||||
if (entity->getTransform() != _transform) {
|
return entity->getParentID() != _parentID;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (entity->getUnscaledDimensions() != _dimensions) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (entity->getParentID() != _parentID) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
})) {
|
})) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
withWriteLock([&] {
|
void* key = (void*)this;
|
||||||
bool deleteNeeded = false;
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||||
bool addNeeded = _retryApply;
|
withWriteLock([&] {
|
||||||
bool transformChanged = false;
|
_renderTransform = getModelTransform();
|
||||||
{
|
const float MATERIAL_ENTITY_SCALE = 0.5f;
|
||||||
MaterialMappingMode mode = entity->getMaterialMappingMode();
|
_renderTransform.postScale(MATERIAL_ENTITY_SCALE);
|
||||||
if (mode != _materialMappingMode) {
|
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||||
_materialMappingMode = mode;
|
});
|
||||||
transformChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
} else if (_materialURL.contains("?")) {
|
|
||||||
qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL;
|
|
||||||
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 = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
|
||||||
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
|
||||||
if (success) {
|
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
|
||||||
_texturesLoaded = false;
|
|
||||||
_parsedMaterials = _networkMaterial->parsedMaterials;
|
|
||||||
setCurrentMaterialName(newCurrentMaterialName);
|
|
||||||
applyMaterial(entity);
|
|
||||||
} else {
|
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
|
||||||
_retryApply = false;
|
|
||||||
_texturesLoaded = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (_networkMaterial) {
|
|
||||||
if (_networkMaterial->isLoaded()) {
|
|
||||||
onMaterialRequestFinished(!_networkMaterial->isFailed());
|
|
||||||
} else {
|
|
||||||
connect(_networkMaterial.data(), &Resource::finished, this, [this, onMaterialRequestFinished](bool success) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
onMaterialRequestFinished(success);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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(entity);
|
|
||||||
} else {
|
|
||||||
if (deleteNeeded) {
|
|
||||||
deleteMaterial(oldParentID, oldParentMaterialName);
|
|
||||||
}
|
|
||||||
if (addNeeded) {
|
|
||||||
applyMaterial(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
|
bool deleteNeeded = false;
|
||||||
|
bool addNeeded = _retryApply;
|
||||||
|
bool transformChanged = false;
|
||||||
|
{
|
||||||
|
MaterialMappingMode mode = entity->getMaterialMappingMode();
|
||||||
|
if (mode != _materialMappingMode) {
|
||||||
|
_materialMappingMode = mode;
|
||||||
|
transformChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
} else if (_materialURL.contains("?")) {
|
||||||
|
qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL;
|
||||||
|
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 = DependencyManager::get<MaterialCache>()->getMaterial(_materialURL);
|
||||||
|
auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) {
|
||||||
|
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||||
|
if (success) {
|
||||||
|
_texturesLoaded = false;
|
||||||
|
_parsedMaterials = _networkMaterial->parsedMaterials;
|
||||||
|
setCurrentMaterialName(newCurrentMaterialName);
|
||||||
|
applyMaterial(entity);
|
||||||
|
emit requestRenderUpdate();
|
||||||
|
} else {
|
||||||
|
_retryApply = false;
|
||||||
|
_texturesLoaded = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_networkMaterial) {
|
||||||
|
if (_networkMaterial->isLoaded()) {
|
||||||
|
onMaterialRequestFinished(!_networkMaterial->isFailed());
|
||||||
|
} else {
|
||||||
|
connect(_networkMaterial.data(), &Resource::finished, this, [this, onMaterialRequestFinished](bool success) {
|
||||||
|
onMaterialRequestFinished(success);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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(entity);
|
||||||
|
} else {
|
||||||
|
if (deleteNeeded) {
|
||||||
|
deleteMaterial(oldParentID, oldParentMaterialName);
|
||||||
|
}
|
||||||
|
if (addNeeded) {
|
||||||
|
applyMaterial(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto material = getMaterial();
|
||||||
|
bool newTexturesLoaded = material ? !material->isMissingTexture() : false;
|
||||||
|
if (!_texturesLoaded && newTexturesLoaded) {
|
||||||
|
material->checkResetOpacityMap();
|
||||||
|
}
|
||||||
|
_texturesLoaded = newTexturesLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_texturesLoaded || _retryApply) {
|
||||||
|
emit requestRenderUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ItemKey MaterialEntityRenderer::getKey() {
|
ItemKey MaterialEntityRenderer::getKey() {
|
||||||
auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
|
|
||||||
|
@ -276,25 +263,26 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform renderTransform;
|
graphics::MaterialPointer drawMaterial = getMaterial();
|
||||||
graphics::MaterialPointer drawMaterial;
|
|
||||||
bool proceduralRender = false;
|
bool proceduralRender = false;
|
||||||
Transform textureTransform;
|
Transform textureTransform;
|
||||||
|
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
|
||||||
|
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
|
||||||
|
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
|
||||||
|
|
||||||
|
Transform renderTransform;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
renderTransform = _renderTransform;
|
renderTransform = _renderTransform;
|
||||||
drawMaterial = getMaterial();
|
|
||||||
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
|
|
||||||
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
|
|
||||||
textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
|
|
||||||
|
|
||||||
if (drawMaterial && drawMaterial->isProcedural() && drawMaterial->isReady()) {
|
|
||||||
proceduralRender = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!drawMaterial) {
|
if (!drawMaterial) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drawMaterial->isProcedural() && drawMaterial->isReady()) {
|
||||||
|
proceduralRender = true;
|
||||||
|
}
|
||||||
|
|
||||||
batch.setModelTransform(renderTransform);
|
batch.setModelTransform(renderTransform);
|
||||||
|
|
||||||
if (!proceduralRender) {
|
if (!proceduralRender) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ public:
|
||||||
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
|
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool needsRenderUpdate() const override;
|
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) 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 doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual void doRender(RenderArgs* args) override;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ ModelPointer ModelEntityWrapper::getModel() const {
|
||||||
|
|
||||||
bool ModelEntityWrapper::isModelLoaded() const {
|
bool ModelEntityWrapper::isModelLoaded() const {
|
||||||
return resultWithReadLock<bool>([&] {
|
return resultWithReadLock<bool>([&] {
|
||||||
return _model.operator bool() && _model->isLoaded();
|
return _model && _model->isLoaded();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,8 +69,7 @@ EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityI
|
||||||
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) :
|
RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized) :
|
||||||
ModelEntityWrapper(entityItemID),
|
ModelEntityWrapper(entityItemID),
|
||||||
_dimensionsInitialized(dimensionsInitialized) {
|
_dimensionsInitialized(dimensionsInitialized) {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderableModelEntityItem::~RenderableModelEntityItem() { }
|
RenderableModelEntityItem::~RenderableModelEntityItem() { }
|
||||||
|
@ -182,20 +181,24 @@ void RenderableModelEntityItem::updateModelBounds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overridingModelTransform = model->isOverridingModelTransformAndOffset();
|
bool overridingModelTransform = model->isOverridingModelTransformAndOffset();
|
||||||
|
glm::vec3 scaledDimensions = getScaledDimensions();
|
||||||
|
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||||
|
QString modelURL = getModelURL();
|
||||||
if (!overridingModelTransform &&
|
if (!overridingModelTransform &&
|
||||||
(model->getScaleToFitDimensions() != getScaledDimensions() ||
|
(model->getScaleToFitDimensions() != scaledDimensions ||
|
||||||
model->getRegistrationPoint() != getRegistrationPoint() ||
|
model->getRegistrationPoint() != registrationPoint ||
|
||||||
|
model->getURL() != modelURL ||
|
||||||
!model->getIsScaledToFit())) {
|
!model->getIsScaledToFit())) {
|
||||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
||||||
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
||||||
// This doesn't cause the entity values to change -- it just allows the model to match once it comes in.
|
// This doesn't cause the entity values to change -- it just allows the model to match once it comes in.
|
||||||
model->setScaleToFit(false, getScaledDimensions());
|
model->setScaleToFit(false, scaledDimensions);
|
||||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
model->setSnapModelToRegistrationPoint(false, registrationPoint);
|
||||||
|
|
||||||
// now recalculate the bounds and registration
|
// now recalculate the bounds and registration
|
||||||
model->setScaleToFit(true, getScaledDimensions());
|
model->setScaleToFit(true, scaledDimensions);
|
||||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
model->setSnapModelToRegistrationPoint(true, registrationPoint);
|
||||||
updateRenderItems = true;
|
updateRenderItems = true;
|
||||||
model->scaleToFit();
|
model->scaleToFit();
|
||||||
}
|
}
|
||||||
|
@ -248,8 +251,6 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,13 +961,13 @@ QStringList RenderableModelEntityItem::getJointNames() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
||||||
auto model = resultWithReadLock<ModelPointer>([this]{ return _model; });
|
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||||
|
|
||||||
if (!model || !model->isLoaded()) {
|
if (!model || !model->isLoaded()) {
|
||||||
return scriptable::ScriptableModelBase();
|
return scriptable::ScriptableModelBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = _model->getScriptableModel();
|
auto result = model->getScriptableModel();
|
||||||
result.objectID = getEntity()->getID();
|
result.objectID = getEntity()->getID();
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_materialsLock);
|
std::lock_guard<std::mutex> lock(_materialsLock);
|
||||||
|
@ -1054,10 +1055,10 @@ ModelEntityRenderer::ModelEntityRenderer(const EntityItemPointer& entity) : Pare
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed) {
|
void ModelEntityRenderer::setKey(bool didVisualGeometryRequestSucceed, const ModelPointer& model) {
|
||||||
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
auto builder = ItemKey::Builder().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||||
|
|
||||||
if (!_cullWithParent && _model && _model->isGroupCulled()) {
|
if (!_cullWithParent && model && model->isGroupCulled()) {
|
||||||
builder.withMetaCullGroup();
|
builder.withMetaCullGroup();
|
||||||
} else if (_cullWithParent) {
|
} else if (_cullWithParent) {
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
|
@ -1075,8 +1076,9 @@ ItemKey ModelEntityRenderer::getKey() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
||||||
if (_model) {
|
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||||
auto metaSubItems = _model->fetchRenderItemIDs();
|
if (model) {
|
||||||
|
auto metaSubItems = model->fetchRenderItemIDs();
|
||||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||||
return (uint32_t)metaSubItems.size();
|
return (uint32_t)metaSubItems.size();
|
||||||
}
|
}
|
||||||
|
@ -1089,8 +1091,9 @@ void ModelEntityRenderer::handleBlendedVertices(int blendshapeNumber, const QVec
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& transaction) {
|
void ModelEntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& transaction) {
|
||||||
if (_model) {
|
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||||
_model->removeFromScene(scene, transaction);
|
if (model) {
|
||||||
|
model->removeFromScene(scene, transaction);
|
||||||
}
|
}
|
||||||
Parent::removeFromScene(scene, transaction);
|
Parent::removeFromScene(scene, transaction);
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +1102,7 @@ void ModelEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entit
|
||||||
entity->setModel({});
|
entity->setModel({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
void ModelEntityRenderer::animate(const TypedEntityPointer& entity, const ModelPointer& model) {
|
||||||
if (!_animation || !_animation->isLoaded()) {
|
if (!_animation || !_animation->isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1124,17 +1127,17 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
_lastKnownCurrentFrame = currentIntegerFrame;
|
_lastKnownCurrentFrame = currentIntegerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jointMapping.size() != _model->getJointStateCount()) {
|
if (_jointMapping.size() != model->getJointStateCount()) {
|
||||||
qCWarning(entitiesrenderer) << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
qCWarning(entitiesrenderer) << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
||||||
<< _jointMapping.size() << _model->getJointStateCount();
|
<< _jointMapping.size() << model->getJointStateCount();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
||||||
auto& hfmJoints = _animation->getHFMModel().joints;
|
auto& hfmJoints = _animation->getHFMModel().joints;
|
||||||
|
|
||||||
auto& originalHFMJoints = _model->getHFMModel().joints;
|
auto& originalHFMJoints = model->getHFMModel().joints;
|
||||||
auto& originalHFMIndices = _model->getHFMModel().jointIndices;
|
auto& originalHFMIndices = model->getHFMModel().jointIndices;
|
||||||
|
|
||||||
bool allowTranslation = entity->getAnimationAllowTranslation();
|
bool allowTranslation = entity->getAnimationAllowTranslation();
|
||||||
|
|
||||||
|
@ -1183,90 +1186,39 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelEntityRenderer::needsRenderUpdate() const {
|
bool ModelEntityRenderer::needsRenderUpdate() const {
|
||||||
if (resultWithReadLock<bool>([&] {
|
//ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||||
if (_moving || _animating) {
|
// return _model;
|
||||||
return true;
|
//});
|
||||||
}
|
|
||||||
|
|
||||||
if (!_texturesLoaded) {
|
//if (model) {
|
||||||
return true;
|
// // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||||
}
|
// // we will watch for that and ask the model to update it's render items
|
||||||
|
// if (model->needsReload()) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
if (!_prevModelLoaded) {
|
// if (model->needsFixupInScene()) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
return false;
|
|
||||||
})) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelPointer model;
|
|
||||||
QUrl parsedModelURL;
|
|
||||||
withReadLock([&] {
|
|
||||||
model = _model;
|
|
||||||
parsedModelURL = _parsedModelURL;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (model) {
|
|
||||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
|
||||||
// we will watch for that and ask the model to update it's render items
|
|
||||||
if (parsedModelURL != model->getURL()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model->needsReload()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model->needsFixupInScene()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model->getRenderItemsNeedUpdate()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Parent::needsRenderUpdate();
|
return Parent::needsRenderUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||||
if (resultWithReadLock<bool>([&] {
|
if (entity->blendshapesChanged()) {
|
||||||
if (entity->hasModel() != _hasModel) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// No model to render, early exit
|
// Check to see if we need to update the model bounds
|
||||||
if (!_hasModel) {
|
if (entity->needsUpdateModelBounds()) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_animating != entity->isAnimatingSomething()) {
|
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||||
return true;
|
return _model;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
})) { return true; }
|
|
||||||
|
|
||||||
ModelPointer model;
|
|
||||||
withReadLock([&] {
|
|
||||||
model = _model;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (model && model->isLoaded()) {
|
if (model && model->isLoaded()) {
|
||||||
if (!entity->_dimensionsInitialized || entity->_needsInitialSimulation || !entity->_originalTexturesRead) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->blendshapesChanged()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if we need to update the model bounds
|
|
||||||
if (entity->needsUpdateModelBounds()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if we need to update the model bounds
|
// Check to see if we need to update the model bounds
|
||||||
auto transform = entity->getTransform();
|
auto transform = entity->getTransform();
|
||||||
if (model->getTranslation() != transform.getTranslation() ||
|
if (model->getTranslation() != transform.getTranslation() ||
|
||||||
|
@ -1280,48 +1232,38 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return Parent::needsRenderUpdateFromTypedEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||||
if (_hasModel != entity->hasModel()) {
|
|
||||||
withWriteLock([&] {
|
_hasModel = entity->hasModel();
|
||||||
_hasModel = entity->hasModel();
|
if (_parsedModelURL != entity->getModelURL()) {
|
||||||
});
|
_parsedModelURL = QUrl(entity->getModelURL());
|
||||||
}
|
}
|
||||||
|
|
||||||
withWriteLock([&] {
|
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||||
_animating = entity->isAnimatingSomething();
|
return _model;
|
||||||
if (_parsedModelURL != entity->getModelURL()) {
|
|
||||||
_parsedModelURL = QUrl(entity->getModelURL());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ModelPointer model;
|
bool visuallyReady = model && model->isLoaded() && _didLastVisualGeometryRequestSucceed && _texturesLoaded;
|
||||||
withReadLock([&] { model = _model; });
|
entity->setVisuallyReady(visuallyReady);
|
||||||
|
|
||||||
withWriteLock([&] {
|
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
bool visuallyReady = true;
|
render::Transaction transaction;
|
||||||
if (_hasModel) {
|
|
||||||
if (model && _didLastVisualGeometryRequestSucceed) {
|
|
||||||
visuallyReady = (_prevModelLoaded && _texturesLoaded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entity->setVisuallyReady(visuallyReady);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check for removal
|
// Check for removal
|
||||||
if (!_hasModel) {
|
if (!_hasModel) {
|
||||||
if (model) {
|
if (model) {
|
||||||
model->removeFromScene(scene, transaction);
|
model->removeFromScene(scene, transaction);
|
||||||
entity->bumpAncestorChainRenderableVersion();
|
entity->bumpAncestorChainRenderableVersion();
|
||||||
withWriteLock([&] { _model.reset(); });
|
|
||||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||||
|
withWriteLock([&] { model.reset(); });
|
||||||
}
|
}
|
||||||
setKey(false);
|
|
||||||
_didLastVisualGeometryRequestSucceed = false;
|
_didLastVisualGeometryRequestSucceed = false;
|
||||||
|
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,18 +1272,28 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
model = std::make_shared<Model>(nullptr, entity.get(), _created);
|
model = std::make_shared<Model>(nullptr, entity.get(), _created);
|
||||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||||
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
|
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
|
||||||
setKey(didVisualGeometryRequestSucceed);
|
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
_model->setTagMask(getTagMask());
|
withWriteLock([&] {
|
||||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
setKey(didVisualGeometryRequestSucceed, _model);
|
||||||
_model->setPrimitiveMode(_primitiveMode);
|
_model->setVisibleInScene(_visible, scene);
|
||||||
_model->setCullWithParent(_cullWithParent);
|
_model->setCauterized(_cauterized, scene);
|
||||||
_model->setRenderWithZones(_renderWithZones);
|
_model->setCanCastShadow(_canCastShadow, scene);
|
||||||
emit requestRenderUpdate();
|
_model->setGroupCulled(entity->getGroupCulled(), scene);
|
||||||
|
_model->setTagMask(getTagMask(), scene);
|
||||||
|
_model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||||
|
_model->setPrimitiveMode(_primitiveMode, scene);
|
||||||
|
_model->setCullWithParent(_cullWithParent, scene);
|
||||||
|
_model->setRenderWithZones(_renderWithZones, scene);
|
||||||
|
});
|
||||||
if (didVisualGeometryRequestSucceed) {
|
if (didVisualGeometryRequestSucceed) {
|
||||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||||
}
|
}
|
||||||
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
||||||
|
entity->_dimensionsInitialized = false;
|
||||||
|
entity->_originalTexturesRead = false;
|
||||||
|
entity->_needsJointSimulation = true;
|
||||||
|
emit requestRenderUpdate();
|
||||||
});
|
});
|
||||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||||
entity->setModel(model);
|
entity->setModel(model);
|
||||||
|
@ -1350,24 +1302,15 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
|
|
||||||
// From here on, we are guaranteed a populated model
|
// From here on, we are guaranteed a populated model
|
||||||
if (_parsedModelURL != model->getURL()) {
|
if (_parsedModelURL != model->getURL()) {
|
||||||
withWriteLock([&] {
|
_texturesLoaded = false;
|
||||||
_texturesLoaded = false;
|
_jointMappingCompleted = false;
|
||||||
_jointMappingCompleted = false;
|
model->setURL(_parsedModelURL);
|
||||||
model->setURL(_parsedModelURL);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing else to do unless the model is loaded
|
// Nothing else to do unless the model is loaded
|
||||||
if (!model->isLoaded()) {
|
if (!model->isLoaded()) {
|
||||||
withWriteLock([&] {
|
|
||||||
_prevModelLoaded = false;
|
|
||||||
});
|
|
||||||
emit requestRenderUpdate();
|
emit requestRenderUpdate();
|
||||||
return;
|
return;
|
||||||
} else if (!_prevModelLoaded) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_prevModelLoaded = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for initializing the model
|
// Check for initializing the model
|
||||||
|
@ -1383,6 +1326,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
|
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<EntityScriptingInterface>().data(), "editEntity",
|
QMetaObject::invokeMethod(DependencyManager::get<EntityScriptingInterface>().data(), "editEntity",
|
||||||
Qt::QueuedConnection, Q_ARG(QUuid, entity->getEntityItemID()), Q_ARG(EntityItemProperties, properties));
|
Qt::QueuedConnection, Q_ARG(QUuid, entity->getEntityItemID()), Q_ARG(EntityItemProperties, properties));
|
||||||
|
entity->_dimensionsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity->_originalTexturesRead) {
|
if (!entity->_originalTexturesRead) {
|
||||||
|
@ -1393,51 +1337,34 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
|
|
||||||
if (_textures != entity->getTextures()) {
|
if (_textures != entity->getTextures()) {
|
||||||
QVariantMap newTextures;
|
QVariantMap newTextures;
|
||||||
withWriteLock([&] {
|
_texturesLoaded = false;
|
||||||
_texturesLoaded = false;
|
_textures = entity->getTextures();
|
||||||
_textures = entity->getTextures();
|
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
||||||
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
|
||||||
});
|
|
||||||
model->setTextures(newTextures);
|
model->setTextures(newTextures);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity->_needsJointSimulation) {
|
if (entity->_needsJointSimulation) {
|
||||||
entity->copyAnimationJointDataToModel();
|
entity->copyAnimationJointDataToModel();
|
||||||
}
|
}
|
||||||
entity->updateModelBounds();
|
entity->updateModelBounds();
|
||||||
entity->stopModelOverrideIfNoParent();
|
entity->stopModelOverrideIfNoParent();
|
||||||
|
|
||||||
if (model->isVisible() != _visible) {
|
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||||
model->setVisibleInScene(_visible, scene);
|
model->setVisibleInScene(_visible, scene);
|
||||||
}
|
model->setCauterized(_cauterized, scene);
|
||||||
|
model->setCanCastShadow(_canCastShadow, scene);
|
||||||
if (model->isCauterized() != _cauterized) {
|
model->setGroupCulled(entity->getGroupCulled(), scene);
|
||||||
model->setCauterized(_cauterized, scene);
|
model->setTagMask(getTagMask(), scene);
|
||||||
}
|
model->setHifiRenderLayer(getHifiRenderLayer(), scene);
|
||||||
|
model->setPrimitiveMode(_primitiveMode, scene);
|
||||||
render::hifi::Tag tagMask = getTagMask();
|
model->setCullWithParent(_cullWithParent, scene);
|
||||||
if (model->getTagMask() != tagMask) {
|
model->setRenderWithZones(_renderWithZones, scene);
|
||||||
model->setTagMask(tagMask, scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->blendshapesChanged()) {
|
if (entity->blendshapesChanged()) {
|
||||||
model->setBlendshapeCoefficients(entity->getBlendshapeCoefficientVector());
|
model->setBlendshapeCoefficients(entity->getBlendshapeCoefficientVector());
|
||||||
model->updateBlendshapes();
|
model->updateBlendshapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO? early exit here when not visible?
|
|
||||||
|
|
||||||
if (model->canCastShadow() != _canCastShadow) {
|
|
||||||
model->setCanCastShadow(_canCastShadow, scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
bool groupCulled = entity->getGroupCulled();
|
|
||||||
if (model->isGroupCulled() != groupCulled) {
|
|
||||||
model->setGroupCulled(groupCulled);
|
|
||||||
setKey(_didLastVisualGeometryRequestSucceed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||||
if (model->needsFixupInScene()) {
|
if (model->needsFixupInScene()) {
|
||||||
|
@ -1452,9 +1379,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
||||||
withWriteLock([&] {
|
_texturesLoaded = true;
|
||||||
_texturesLoaded = true;
|
|
||||||
});
|
|
||||||
model->updateRenderItems();
|
model->updateRenderItems();
|
||||||
} else if (!_texturesLoaded) {
|
} else if (!_texturesLoaded) {
|
||||||
emit requestRenderUpdate();
|
emit requestRenderUpdate();
|
||||||
|
@ -1491,9 +1416,13 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
model->updateRenderItems();
|
model->updateRenderItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
// The code to deal with the change of properties is now in ModelEntityItem.cpp
|
// The code to deal with the change of properties is now in ModelEntityItem.cpp
|
||||||
// That is where _currentFrame and _lastAnimated were updated.
|
// That is where _currentFrame and _lastAnimated were updated.
|
||||||
if (_animating) {
|
if (entity->isAnimatingSomething()) {
|
||||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||||
|
|
||||||
auto animationURL = entity->getAnimationURL();
|
auto animationURL = entity->getAnimationURL();
|
||||||
|
@ -1502,18 +1431,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
_animationURL = animationURL;
|
_animationURL = animationURL;
|
||||||
|
|
||||||
if (_animation) {
|
if (_animation) {
|
||||||
//(_animation->getURL().toString() != entity->getAnimationURL())) { // bad check
|
|
||||||
// the joints have been mapped before but we have a new animation to load
|
// the joints have been mapped before but we have a new animation to load
|
||||||
_animation.reset();
|
_animation.reset();
|
||||||
_jointMappingCompleted = false;
|
_jointMappingCompleted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||||
|
return _model;
|
||||||
|
});
|
||||||
if (!_jointMappingCompleted) {
|
if (!_jointMappingCompleted) {
|
||||||
mapJoints(entity, model);
|
mapJoints(entity, model);
|
||||||
}
|
}
|
||||||
if (entity->readyToAnimate()) {
|
if (entity->readyToAnimate() && model && model->isLoaded()) {
|
||||||
animate(entity);
|
animate(entity, model);
|
||||||
}
|
}
|
||||||
emit requestRenderUpdate();
|
emit requestRenderUpdate();
|
||||||
}
|
}
|
||||||
|
@ -1521,40 +1452,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
|
|
||||||
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
|
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
|
||||||
Parent::setIsVisibleInSecondaryCamera(value);
|
Parent::setIsVisibleInSecondaryCamera(value);
|
||||||
setKey(_didLastVisualGeometryRequestSucceed);
|
// called within a lock so no need to lock for _model
|
||||||
if (_model) {
|
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||||
_model->setTagMask(getTagMask());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::setRenderLayer(RenderLayer value) {
|
void ModelEntityRenderer::setRenderLayer(RenderLayer value) {
|
||||||
Parent::setRenderLayer(value);
|
Parent::setRenderLayer(value);
|
||||||
setKey(_didLastVisualGeometryRequestSucceed);
|
// called within a lock so no need to lock for _model
|
||||||
if (_model) {
|
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) {
|
|
||||||
Parent::setPrimitiveMode(value);
|
|
||||||
if (_model) {
|
|
||||||
_model->setPrimitiveMode(_primitiveMode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityRenderer::setCullWithParent(bool value) {
|
void ModelEntityRenderer::setCullWithParent(bool value) {
|
||||||
Parent::setCullWithParent(value);
|
Parent::setCullWithParent(value);
|
||||||
setKey(_didLastVisualGeometryRequestSucceed);
|
// called within a lock so no need to lock for _model
|
||||||
if (_model) {
|
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||||
_model->setCullWithParent(_cullWithParent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelEntityRenderer::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
|
|
||||||
Parent::setRenderWithZones(renderWithZones);
|
|
||||||
if (_model) {
|
|
||||||
_model->setRenderWithZones(renderWithZones);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||||
|
@ -1570,9 +1481,8 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||||
geometryCache->renderWireCubeInstance(args, batch, greenColor, geometryCache->getShapePipelinePointer(false, false, args->_renderMethod == Args::RenderMethod::FORWARD));
|
geometryCache->renderWireCubeInstance(args, batch, greenColor, geometryCache->getShapePipelinePointer(false, false, args->_renderMethod == Args::RenderMethod::FORWARD));
|
||||||
|
|
||||||
#if WANT_EXTRA_DEBUGGING
|
#if WANT_EXTRA_DEBUGGING
|
||||||
ModelPointer model;
|
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||||
withReadLock([&] {
|
return _model;
|
||||||
model = _model;
|
|
||||||
});
|
});
|
||||||
if (model) {
|
if (model) {
|
||||||
model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
|
model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||||
|
|
|
@ -153,25 +153,24 @@ protected:
|
||||||
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override;
|
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override;
|
||||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||||
|
|
||||||
void setKey(bool didVisualGeometryRequestSucceed);
|
void setKey(bool didVisualGeometryRequestSucceed, const ModelPointer& model);
|
||||||
virtual ItemKey getKey() override;
|
virtual ItemKey getKey() override;
|
||||||
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
|
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
|
||||||
virtual void handleBlendedVertices(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets,
|
virtual void handleBlendedVertices(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets,
|
||||||
const QVector<int>& blendedMeshSizes, const render::ItemIDs& subItemIDs) override;
|
const QVector<int>& blendedMeshSizes, const render::ItemIDs& subItemIDs) override;
|
||||||
|
|
||||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
|
||||||
virtual bool needsRenderUpdate() const override;
|
virtual bool needsRenderUpdate() const override;
|
||||||
virtual void doRender(RenderArgs* args) override;
|
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) 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;
|
||||||
|
|
||||||
void setIsVisibleInSecondaryCamera(bool value) override;
|
void setIsVisibleInSecondaryCamera(bool value) override;
|
||||||
void setRenderLayer(RenderLayer value) override;
|
void setRenderLayer(RenderLayer value) override;
|
||||||
void setPrimitiveMode(PrimitiveMode value) override;
|
|
||||||
void setCullWithParent(bool value) override;
|
void setCullWithParent(bool value) override;
|
||||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void animate(const TypedEntityPointer& entity);
|
void animate(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||||
void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
|
void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||||
|
|
||||||
// Transparency is handled in ModelMeshPartPayload
|
// Transparency is handled in ModelMeshPartPayload
|
||||||
|
@ -192,14 +191,12 @@ private:
|
||||||
bool _jointMappingCompleted { false };
|
bool _jointMappingCompleted { false };
|
||||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||||
AnimationPointer _animation;
|
AnimationPointer _animation;
|
||||||
bool _animating { false };
|
|
||||||
QString _animationURL;
|
QString _animationURL;
|
||||||
uint64_t _lastAnimated { 0 };
|
uint64_t _lastAnimated { 0 };
|
||||||
|
|
||||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||||
|
|
||||||
bool _didLastVisualGeometryRequestSucceed { true };
|
bool _didLastVisualGeometryRequestSucceed { true };
|
||||||
bool _prevModelLoaded { false };
|
|
||||||
|
|
||||||
void processMaterials();
|
void processMaterials();
|
||||||
bool _allProceduralMaterialsLoaded { false };
|
bool _allProceduralMaterialsLoaded { false };
|
||||||
|
|
|
@ -78,7 +78,14 @@ void LightEntityItem::setFalloffRadius(float value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEntityItem::setIsSpotlight(bool value) {
|
void LightEntityItem::setIsSpotlight(bool value) {
|
||||||
if (value == getIsSpotlight()) {
|
bool needsRenderUpdate;
|
||||||
|
withWriteLock([&] {
|
||||||
|
needsRenderUpdate = value != _isSpotlight;
|
||||||
|
_needsRenderUpdate |= needsRenderUpdate;
|
||||||
|
_isSpotlight = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!needsRenderUpdate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,25 +99,25 @@ void LightEntityItem::setIsSpotlight(bool value) {
|
||||||
newDimensions = glm::vec3(glm::compMax(dimensions));
|
newDimensions = glm::vec3(glm::compMax(dimensions));
|
||||||
}
|
}
|
||||||
|
|
||||||
withWriteLock([&] {
|
|
||||||
_needsRenderUpdate = true;
|
|
||||||
_isSpotlight = value;
|
|
||||||
});
|
|
||||||
setScaledDimensions(newDimensions);
|
setScaledDimensions(newDimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightEntityItem::setCutoff(float value) {
|
void LightEntityItem::setCutoff(float value) {
|
||||||
value = glm::clamp(value, MIN_CUTOFF, MAX_CUTOFF);
|
value = glm::clamp(value, MIN_CUTOFF, MAX_CUTOFF);
|
||||||
if (value == getCutoff()) {
|
bool needsRenderUpdate;
|
||||||
|
bool spotlight;
|
||||||
|
withWriteLock([&] {
|
||||||
|
needsRenderUpdate = value != _cutoff;
|
||||||
|
_needsRenderUpdate |= needsRenderUpdate;
|
||||||
|
_cutoff = value;
|
||||||
|
spotlight = _isSpotlight;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!needsRenderUpdate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
withWriteLock([&] {
|
if (spotlight) {
|
||||||
_needsRenderUpdate = true;
|
|
||||||
_cutoff = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (getIsSpotlight()) {
|
|
||||||
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
|
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
|
||||||
// so update the dimensions to reflect this.
|
// so update the dimensions to reflect this.
|
||||||
const float length = getScaledDimensions().z;
|
const float length = getScaledDimensions().z;
|
||||||
|
|
|
@ -330,13 +330,6 @@ void ModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationURL(const QString& url) {
|
|
||||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setURL(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationSettings(const QString& value) {
|
void ModelEntityItem::setAnimationSettings(const QString& value) {
|
||||||
// NOTE: this method only called for old bitstream format
|
// NOTE: this method only called for old bitstream format
|
||||||
|
|
||||||
|
@ -399,20 +392,6 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationIsPlaying(bool value) {
|
|
||||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setRunning(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationFPS(float value) {
|
|
||||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setFPS(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelEntityItem::resizeJointArrays(int newSize) {
|
void ModelEntityItem::resizeJointArrays(int newSize) {
|
||||||
if (newSize < 0) {
|
if (newSize < 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -629,61 +608,18 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationAllowTranslation(bool value) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setAllowTranslation(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::getAnimationAllowTranslation() const {
|
bool ModelEntityItem::getAnimationAllowTranslation() const {
|
||||||
return resultWithReadLock<bool>([&] {
|
return resultWithReadLock<bool>([&] {
|
||||||
return _animationProperties.getAllowTranslation();
|
return _animationProperties.getAllowTranslation();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationLoop(bool loop) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setLoop(loop);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::getAnimationLoop() const {
|
|
||||||
return resultWithReadLock<bool>([&] {
|
|
||||||
return _animationProperties.getLoop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationHold(bool hold) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_animationProperties.setHold(hold);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::getAnimationHold() const {
|
|
||||||
return resultWithReadLock<bool>([&] {
|
|
||||||
return _animationProperties.getHold();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::getAnimationIsPlaying() const {
|
|
||||||
return resultWithReadLock<bool>([&] {
|
|
||||||
return _animationProperties.getRunning();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
float ModelEntityItem::getAnimationCurrentFrame() const {
|
float ModelEntityItem::getAnimationCurrentFrame() const {
|
||||||
return resultWithReadLock<float>([&] {
|
return resultWithReadLock<float>([&] {
|
||||||
return _animationProperties.getCurrentFrame();
|
return _animationProperties.getCurrentFrame();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
float ModelEntityItem::getAnimationFPS() const {
|
|
||||||
return resultWithReadLock<float>([&] {
|
|
||||||
return _animationProperties.getFPS();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::isAnimatingSomething() const {
|
bool ModelEntityItem::isAnimatingSomething() const {
|
||||||
return resultWithReadLock<bool>([&] {
|
return resultWithReadLock<bool>([&] {
|
||||||
return _animationProperties.isValidAndRunning();
|
return _animationProperties.isValidAndRunning();
|
||||||
|
@ -722,6 +658,7 @@ bool ModelEntityItem::applyNewAnimationProperties(AnimationPropertyGroup newProp
|
||||||
bool somethingChanged = newProperties != _animationProperties;
|
bool somethingChanged = newProperties != _animationProperties;
|
||||||
if (somethingChanged) {
|
if (somethingChanged) {
|
||||||
_animationProperties = newProperties;
|
_animationProperties = newProperties;
|
||||||
|
_needsRenderUpdate = true;
|
||||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||||
}
|
}
|
||||||
return somethingChanged;
|
return somethingChanged;
|
||||||
|
|
|
@ -85,24 +85,12 @@ public:
|
||||||
|
|
||||||
// Animation related items...
|
// Animation related items...
|
||||||
AnimationPropertyGroup getAnimationProperties() const;
|
AnimationPropertyGroup getAnimationProperties() const;
|
||||||
|
|
||||||
// TODO: audit and remove unused Animation accessors
|
|
||||||
bool hasAnimation() const;
|
bool hasAnimation() const;
|
||||||
QString getAnimationURL() const;
|
QString getAnimationURL() const;
|
||||||
virtual void setAnimationURL(const QString& url);
|
|
||||||
|
|
||||||
void setAnimationCurrentFrame(float value);
|
void setAnimationCurrentFrame(float value);
|
||||||
void setAnimationIsPlaying(bool value);
|
float getAnimationCurrentFrame() const;
|
||||||
void setAnimationFPS(float value);
|
|
||||||
|
|
||||||
void setAnimationAllowTranslation(bool value);
|
|
||||||
bool getAnimationAllowTranslation() const;
|
bool getAnimationAllowTranslation() const;
|
||||||
|
bool isAnimatingSomething() const;
|
||||||
void setAnimationLoop(bool loop);
|
|
||||||
bool getAnimationLoop() const;
|
|
||||||
|
|
||||||
void setAnimationHold(bool hold);
|
|
||||||
bool getAnimationHold() const;
|
|
||||||
|
|
||||||
void setRelayParentJoints(bool relayJoints);
|
void setRelayParentJoints(bool relayJoints);
|
||||||
bool getRelayParentJoints() const;
|
bool getRelayParentJoints() const;
|
||||||
|
@ -110,11 +98,6 @@ public:
|
||||||
void setGroupCulled(bool value);
|
void setGroupCulled(bool value);
|
||||||
bool getGroupCulled() const;
|
bool getGroupCulled() const;
|
||||||
|
|
||||||
bool getAnimationIsPlaying() const;
|
|
||||||
float getAnimationCurrentFrame() const;
|
|
||||||
float getAnimationFPS() const;
|
|
||||||
bool isAnimatingSomething() const;
|
|
||||||
|
|
||||||
static const QString DEFAULT_TEXTURES;
|
static const QString DEFAULT_TEXTURES;
|
||||||
const QString getTextures() const;
|
const QString getTextures() const;
|
||||||
void setTextures(const QString& textures);
|
void setTextures(const QString& textures);
|
||||||
|
|
|
@ -958,16 +958,20 @@ void Model::setCauterized(bool cauterized, const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::setPrimitiveMode(PrimitiveMode primitiveMode) {
|
void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene) {
|
||||||
if (_primitiveMode != primitiveMode) {
|
if (_primitiveMode != primitiveMode) {
|
||||||
_primitiveMode = primitiveMode;
|
_primitiveMode = primitiveMode;
|
||||||
updateRenderItemsKey(nullptr);
|
updateRenderItemsKey(scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::setCullWithParent(bool cullWithParent) {
|
void Model::setCullWithParent(bool cullWithParent, const render::ScenePointer& scene) {
|
||||||
if (_cullWithParent != cullWithParent) {
|
if (_cullWithParent != cullWithParent) {
|
||||||
_cullWithParent = cullWithParent;
|
_cullWithParent = cullWithParent;
|
||||||
|
if (!scene) {
|
||||||
|
_needsFixupInScene = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
|
@ -977,14 +981,27 @@ void Model::setCullWithParent(bool cullWithParent) {
|
||||||
data.updateKey(renderItemsKey);
|
data.updateKey(renderItemsKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
|
void Model::setRenderWithZones(const QVector<QUuid>& renderWithZones, const render::ScenePointer& scene) {
|
||||||
if (_renderWithZones != renderWithZones) {
|
if (_renderWithZones != renderWithZones) {
|
||||||
_renderWithZones = renderWithZones;
|
_renderWithZones = renderWithZones;
|
||||||
setRenderItemsNeedUpdate();
|
|
||||||
|
if (!scene) {
|
||||||
|
_needsFixupInScene = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
render::Transaction transaction;
|
||||||
|
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||||
|
for (auto item : _modelMeshRenderItemIDs) {
|
||||||
|
transaction.updateItem<ModelMeshPartPayload>(item, [renderWithZones, renderItemsKey](ModelMeshPartPayload& data) {
|
||||||
|
data.setRenderWithZones(renderWithZones);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,14 +116,14 @@ public:
|
||||||
void setHifiRenderLayer(render::hifi::Layer layer, const render::ScenePointer& scene = nullptr);
|
void setHifiRenderLayer(render::hifi::Layer layer, const render::ScenePointer& scene = nullptr);
|
||||||
|
|
||||||
bool isCauterized() const { return _cauterized; }
|
bool isCauterized() const { return _cauterized; }
|
||||||
void setCauterized(bool value, const render::ScenePointer& scene);
|
void setCauterized(bool value, const render::ScenePointer& scene = nullptr);
|
||||||
|
|
||||||
void setPrimitiveMode(PrimitiveMode primitiveMode);
|
void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr);
|
||||||
PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
|
PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
|
||||||
|
|
||||||
void setCullWithParent(bool value);
|
void setCullWithParent(bool value, const render::ScenePointer& scene = nullptr);
|
||||||
|
|
||||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones);
|
void setRenderWithZones(const QVector<QUuid>& renderWithZones, const render::ScenePointer& scene = nullptr);
|
||||||
const QVector<QUuid>& getRenderWithZones() const { return _renderWithZones; }
|
const QVector<QUuid>& getRenderWithZones() const { return _renderWithZones; }
|
||||||
|
|
||||||
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
|
// Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model.
|
||||||
|
|
Loading…
Reference in a new issue