mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01: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();
|
||||
setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera());
|
||||
setRenderLayer(entity->getRenderLayer());
|
||||
setPrimitiveMode(entity->getPrimitiveMode());
|
||||
_primitiveMode = entity->getPrimitiveMode();
|
||||
_canCastShadow = entity->getCanCastShadow();
|
||||
setCullWithParent(entity->getCullWithParent());
|
||||
_cauterized = entity->getCauterized();
|
||||
if (entity->needsZoneOcclusionUpdate()) {
|
||||
entity->resetNeedsZoneOcclusionUpdate();
|
||||
setRenderWithZones(entity->getRenderWithZones());
|
||||
_renderWithZones = entity->getRenderWithZones();
|
||||
}
|
||||
entity->setNeedsRenderUpdate(false);
|
||||
});
|
||||
|
|
|
@ -108,18 +108,7 @@ protected:
|
|||
|
||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||
virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; }
|
||||
virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = 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:
|
||||
void requestRenderUpdate();
|
||||
|
|
|
@ -52,14 +52,11 @@ void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
bool dirty = false;
|
||||
RingGizmoPropertyGroup ringProperties = entity->getRingProperties();
|
||||
withWriteLock([&] {
|
||||
_gizmoType = entity->getGizmoType();
|
||||
if (_ringProperties != ringProperties) {
|
||||
_ringProperties = ringProperties;
|
||||
dirty = true;
|
||||
|
||||
}
|
||||
});
|
||||
_gizmoType = entity->getGizmoType();
|
||||
if (_ringProperties != ringProperties) {
|
||||
_ringProperties = ringProperties;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty || _prevPrimitiveMode != _primitiveMode || !_ringGeometryID || !_majorTicksGeometryID || !_minorTicksGeometryID) {
|
||||
_prevPrimitiveMode = _primitiveMode;
|
||||
|
@ -242,19 +239,20 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
if (_gizmoType == GizmoType::RING) {
|
||||
Transform transform;
|
||||
bool hasTickMarks;
|
||||
glm::vec4 tickProperties;
|
||||
bool hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
glm::vec4 tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
bool forward;
|
||||
bool wireframe;
|
||||
bool transparent;
|
||||
withReadLock([&] {
|
||||
transform = _renderTransform;
|
||||
hasTickMarks = _ringProperties.getHasTickMarks();
|
||||
tickProperties = glm::vec4(_ringProperties.getMajorTickMarksAngle(), _ringProperties.getMajorTickMarksLength(),
|
||||
_ringProperties.getMinorTickMarksAngle(), _ringProperties.getMinorTickMarksLength());
|
||||
transparent = isTransparent();
|
||||
wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
});
|
||||
|
||||
bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES;
|
||||
geometryCache->bindSimpleProgram(batch, false, isTransparent(), wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE);
|
||||
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
|
|
|
@ -30,16 +30,6 @@ bool GridEntityRenderer::isTransparent() const {
|
|||
}
|
||||
|
||||
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;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
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() {
|
||||
if (_followCamera) {
|
||||
// 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) {
|
||||
glm::vec4 color;
|
||||
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
glm::vec3 dimensions;
|
||||
Transform renderTransform;
|
||||
bool forward;
|
||||
withReadLock([&] {
|
||||
color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
dimensions = _dimensions;
|
||||
renderTransform = _renderTransform;
|
||||
forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD;
|
||||
|
|
|
@ -30,10 +30,11 @@ protected:
|
|||
|
||||
private:
|
||||
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;
|
||||
|
||||
glm::u8vec3 _color;
|
||||
float _alpha;
|
||||
glm::u8vec3 _color { NAN };
|
||||
float _alpha { NAN };
|
||||
PulsePropertyGroup _pulseProperties;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
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() {
|
||||
auto bound = Parent::getBound();
|
||||
if (_billboardMode != BillboardMode::NONE) {
|
||||
|
@ -93,33 +83,26 @@ ShapeKey ImageEntityRenderer::getShapeKey() {
|
|||
builder.withTranslucent();
|
||||
}
|
||||
|
||||
withReadLock([&] {
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
});
|
||||
if (_primitiveMode == PrimitiveMode::LINES) {
|
||||
builder.withWireframe();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void ImageEntityRenderer::doRender(RenderArgs* args) {
|
||||
NetworkTexturePointer texture;
|
||||
QRect subImage;
|
||||
glm::vec4 color;
|
||||
glm::vec4 color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
Transform transform;
|
||||
withReadLock([&] {
|
||||
texture = _texture;
|
||||
subImage = _subImage;
|
||||
color = glm::vec4(toGlm(_color), _alpha);
|
||||
color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created);
|
||||
transform = _renderTransform;
|
||||
});
|
||||
|
||||
if (!_visible || !texture || !texture->isLoaded() || color.a == 0.0f) {
|
||||
if (!_visible || !_texture || !_texture->isLoaded() || color.a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,28 +112,28 @@ void ImageEntityRenderer::doRender(RenderArgs* args) {
|
|||
transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
batch->setResourceTexture(0, texture->getGPUTexture());
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
|
||||
float imageWidth = texture->getWidth();
|
||||
float imageHeight = texture->getHeight();
|
||||
float imageWidth = _texture->getWidth();
|
||||
float imageHeight = _texture->getHeight();
|
||||
|
||||
QRect fromImage;
|
||||
if (subImage.width() <= 0) {
|
||||
if (_subImage.width() <= 0) {
|
||||
fromImage.setX(0);
|
||||
fromImage.setWidth(imageWidth);
|
||||
} else {
|
||||
float scaleX = imageWidth / texture->getOriginalWidth();
|
||||
fromImage.setX(scaleX * subImage.x());
|
||||
fromImage.setWidth(scaleX * subImage.width());
|
||||
float scaleX = imageWidth / _texture->getOriginalWidth();
|
||||
fromImage.setX(scaleX * _subImage.x());
|
||||
fromImage.setWidth(scaleX * _subImage.width());
|
||||
}
|
||||
|
||||
if (subImage.height() <= 0) {
|
||||
if (_subImage.height() <= 0) {
|
||||
fromImage.setY(0);
|
||||
fromImage.setHeight(imageHeight);
|
||||
} else {
|
||||
float scaleY = imageHeight / texture->getOriginalHeight();
|
||||
fromImage.setY(scaleY * subImage.y());
|
||||
fromImage.setHeight(scaleY * subImage.height());
|
||||
float scaleY = imageHeight / _texture->getOriginalHeight();
|
||||
fromImage.setY(scaleY * _subImage.y());
|
||||
fromImage.setHeight(scaleY * _subImage.height());
|
||||
}
|
||||
|
||||
float maxSize = glm::max(fromImage.width(), fromImage.height());
|
||||
|
|
|
@ -29,8 +29,8 @@ protected:
|
|||
bool isTransparent() const override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdate() 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;
|
||||
|
||||
QString _imageURL;
|
||||
|
|
|
@ -16,199 +16,186 @@
|
|||
using namespace render;
|
||||
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 {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->getTransform() != _transform) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getUnscaledDimensions() != _dimensions) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getParentID() != _parentID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return entity->getParentID() != _parentID;
|
||||
})) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
withWriteLock([&] {
|
||||
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) {
|
||||
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::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
void* key = (void*)this;
|
||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] {
|
||||
withWriteLock([&] {
|
||||
_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() {
|
||||
auto builder = ItemKey::Builder().withTypeShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
|
||||
|
||||
|
@ -276,25 +263,26 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
return;
|
||||
}
|
||||
|
||||
Transform renderTransform;
|
||||
graphics::MaterialPointer drawMaterial;
|
||||
graphics::MaterialPointer drawMaterial = getMaterial();
|
||||
bool proceduralRender = false;
|
||||
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([&] {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawMaterial->isProcedural() && drawMaterial->isReady()) {
|
||||
proceduralRender = true;
|
||||
}
|
||||
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
if (!proceduralRender) {
|
||||
|
|
|
@ -27,8 +27,8 @@ public:
|
|||
~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;
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ ModelPointer ModelEntityWrapper::getModel() const {
|
|||
|
||||
bool ModelEntityWrapper::isModelLoaded() const {
|
||||
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) :
|
||||
ModelEntityWrapper(entityItemID),
|
||||
_dimensionsInitialized(dimensionsInitialized) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
RenderableModelEntityItem::~RenderableModelEntityItem() { }
|
||||
|
@ -182,20 +181,24 @@ void RenderableModelEntityItem::updateModelBounds() {
|
|||
}
|
||||
|
||||
bool overridingModelTransform = model->isOverridingModelTransformAndOffset();
|
||||
glm::vec3 scaledDimensions = getScaledDimensions();
|
||||
glm::vec3 registrationPoint = getRegistrationPoint();
|
||||
QString modelURL = getModelURL();
|
||||
if (!overridingModelTransform &&
|
||||
(model->getScaleToFitDimensions() != getScaledDimensions() ||
|
||||
model->getRegistrationPoint() != getRegistrationPoint() ||
|
||||
(model->getScaleToFitDimensions() != scaledDimensions ||
|
||||
model->getRegistrationPoint() != registrationPoint ||
|
||||
model->getURL() != modelURL ||
|
||||
!model->getIsScaledToFit())) {
|
||||
// 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
|
||||
// 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.
|
||||
model->setScaleToFit(false, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
||||
model->setScaleToFit(false, scaledDimensions);
|
||||
model->setSnapModelToRegistrationPoint(false, registrationPoint);
|
||||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, getScaledDimensions());
|
||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
model->setScaleToFit(true, scaledDimensions);
|
||||
model->setSnapModelToRegistrationPoint(true, registrationPoint);
|
||||
updateRenderItems = true;
|
||||
model->scaleToFit();
|
||||
}
|
||||
|
@ -248,8 +251,6 @@ EntityItemProperties RenderableModelEntityItem::getProperties(const EntityProper
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -960,13 +961,13 @@ QStringList RenderableModelEntityItem::getJointNames() const {
|
|||
}
|
||||
|
||||
scriptable::ScriptableModelBase render::entities::ModelEntityRenderer::getScriptableModel() {
|
||||
auto model = resultWithReadLock<ModelPointer>([this]{ return _model; });
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
|
||||
if (!model || !model->isLoaded()) {
|
||||
return scriptable::ScriptableModelBase();
|
||||
}
|
||||
|
||||
auto result = _model->getScriptableModel();
|
||||
auto result = model->getScriptableModel();
|
||||
result.objectID = getEntity()->getID();
|
||||
{
|
||||
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());
|
||||
|
||||
if (!_cullWithParent && _model && _model->isGroupCulled()) {
|
||||
if (!_cullWithParent && model && model->isGroupCulled()) {
|
||||
builder.withMetaCullGroup();
|
||||
} else if (_cullWithParent) {
|
||||
builder.withSubMetaCulled();
|
||||
|
@ -1075,8 +1076,9 @@ ItemKey ModelEntityRenderer::getKey() {
|
|||
}
|
||||
|
||||
uint32_t ModelEntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const {
|
||||
if (_model) {
|
||||
auto metaSubItems = _model->fetchRenderItemIDs();
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
if (model) {
|
||||
auto metaSubItems = model->fetchRenderItemIDs();
|
||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
return (uint32_t)metaSubItems.size();
|
||||
}
|
||||
|
@ -1089,8 +1091,9 @@ void ModelEntityRenderer::handleBlendedVertices(int blendshapeNumber, const QVec
|
|||
}
|
||||
|
||||
void ModelEntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& transaction) {
|
||||
if (_model) {
|
||||
_model->removeFromScene(scene, transaction);
|
||||
auto model = resultWithReadLock<ModelPointer>([&] { return _model; });
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
}
|
||||
Parent::removeFromScene(scene, transaction);
|
||||
}
|
||||
|
@ -1099,7 +1102,7 @@ void ModelEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entit
|
|||
entity->setModel({});
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||
void ModelEntityRenderer::animate(const TypedEntityPointer& entity, const ModelPointer& model) {
|
||||
if (!_animation || !_animation->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1124,17 +1127,17 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
|||
_lastKnownCurrentFrame = currentIntegerFrame;
|
||||
}
|
||||
|
||||
if (_jointMapping.size() != _model->getJointStateCount()) {
|
||||
if (_jointMapping.size() != model->getJointStateCount()) {
|
||||
qCWarning(entitiesrenderer) << "RenderableModelEntityItem::getAnimationFrame -- joint count mismatch"
|
||||
<< _jointMapping.size() << _model->getJointStateCount();
|
||||
<< _jointMapping.size() << model->getJointStateCount();
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
||||
auto& hfmJoints = _animation->getHFMModel().joints;
|
||||
|
||||
auto& originalHFMJoints = _model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = _model->getHFMModel().jointIndices;
|
||||
auto& originalHFMJoints = model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = model->getHFMModel().jointIndices;
|
||||
|
||||
bool allowTranslation = entity->getAnimationAllowTranslation();
|
||||
|
||||
|
@ -1183,90 +1186,39 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
|||
}
|
||||
|
||||
bool ModelEntityRenderer::needsRenderUpdate() const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (_moving || _animating) {
|
||||
return true;
|
||||
}
|
||||
//ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
// return _model;
|
||||
//});
|
||||
|
||||
if (!_texturesLoaded) {
|
||||
return true;
|
||||
}
|
||||
//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 (model->needsReload()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (!_prevModelLoaded) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
// if (model->needsFixupInScene()) {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
return Parent::needsRenderUpdate();
|
||||
}
|
||||
|
||||
bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (resultWithReadLock<bool>([&] {
|
||||
if (entity->hasModel() != _hasModel) {
|
||||
return true;
|
||||
}
|
||||
if (entity->blendshapesChanged()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No model to render, early exit
|
||||
if (!_hasModel) {
|
||||
return false;
|
||||
}
|
||||
// Check to see if we need to update the model bounds
|
||||
if (entity->needsUpdateModelBounds()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_animating != entity->isAnimatingSomething()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})) { return true; }
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
|
||||
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
|
||||
auto transform = entity->getTransform();
|
||||
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__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
withWriteLock([&] {
|
||||
_hasModel = entity->hasModel();
|
||||
});
|
||||
|
||||
_hasModel = entity->hasModel();
|
||||
if (_parsedModelURL != entity->getModelURL()) {
|
||||
_parsedModelURL = QUrl(entity->getModelURL());
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_animating = entity->isAnimatingSomething();
|
||||
if (_parsedModelURL != entity->getModelURL()) {
|
||||
_parsedModelURL = QUrl(entity->getModelURL());
|
||||
}
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&] { model = _model; });
|
||||
bool visuallyReady = model && model->isLoaded() && _didLastVisualGeometryRequestSucceed && _texturesLoaded;
|
||||
entity->setVisuallyReady(visuallyReady);
|
||||
|
||||
withWriteLock([&] {
|
||||
bool visuallyReady = true;
|
||||
if (_hasModel) {
|
||||
if (model && _didLastVisualGeometryRequestSucceed) {
|
||||
visuallyReady = (_prevModelLoaded && _texturesLoaded);
|
||||
}
|
||||
}
|
||||
entity->setVisuallyReady(visuallyReady);
|
||||
});
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
|
||||
// Check for removal
|
||||
if (!_hasModel) {
|
||||
if (model) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
entity->bumpAncestorChainRenderableVersion();
|
||||
withWriteLock([&] { _model.reset(); });
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||
withWriteLock([&] { model.reset(); });
|
||||
}
|
||||
setKey(false);
|
||||
_didLastVisualGeometryRequestSucceed = false;
|
||||
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1330,18 +1272,28 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model = std::make_shared<Model>(nullptr, entity.get(), _created);
|
||||
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
|
||||
connect(model.get(), &Model::setURLFinished, this, [&](bool didVisualGeometryRequestSucceed) {
|
||||
setKey(didVisualGeometryRequestSucceed);
|
||||
_model->setTagMask(getTagMask());
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
||||
_model->setPrimitiveMode(_primitiveMode);
|
||||
_model->setCullWithParent(_cullWithParent);
|
||||
_model->setRenderWithZones(_renderWithZones);
|
||||
emit requestRenderUpdate();
|
||||
const render::ScenePointer& scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
withWriteLock([&] {
|
||||
setKey(didVisualGeometryRequestSucceed, _model);
|
||||
_model->setVisibleInScene(_visible, scene);
|
||||
_model->setCauterized(_cauterized, scene);
|
||||
_model->setCanCastShadow(_canCastShadow, scene);
|
||||
_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) {
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, _model);
|
||||
modelAddedToScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||
}
|
||||
_didLastVisualGeometryRequestSucceed = didVisualGeometryRequestSucceed;
|
||||
entity->_dimensionsInitialized = false;
|
||||
entity->_originalTexturesRead = false;
|
||||
entity->_needsJointSimulation = true;
|
||||
emit requestRenderUpdate();
|
||||
});
|
||||
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
|
||||
entity->setModel(model);
|
||||
|
@ -1350,24 +1302,15 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
// From here on, we are guaranteed a populated model
|
||||
if (_parsedModelURL != model->getURL()) {
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
_jointMappingCompleted = false;
|
||||
model->setURL(_parsedModelURL);
|
||||
});
|
||||
_texturesLoaded = false;
|
||||
_jointMappingCompleted = false;
|
||||
model->setURL(_parsedModelURL);
|
||||
}
|
||||
|
||||
// Nothing else to do unless the model is loaded
|
||||
if (!model->isLoaded()) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = false;
|
||||
});
|
||||
emit requestRenderUpdate();
|
||||
return;
|
||||
} else if (!_prevModelLoaded) {
|
||||
withWriteLock([&] {
|
||||
_prevModelLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Check for initializing the model
|
||||
|
@ -1383,6 +1326,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
QMetaObject::invokeMethod(DependencyManager::get<EntityScriptingInterface>().data(), "editEntity",
|
||||
Qt::QueuedConnection, Q_ARG(QUuid, entity->getEntityItemID()), Q_ARG(EntityItemProperties, properties));
|
||||
entity->_dimensionsInitialized = true;
|
||||
}
|
||||
|
||||
if (!entity->_originalTexturesRead) {
|
||||
|
@ -1393,51 +1337,34 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
if (_textures != entity->getTextures()) {
|
||||
QVariantMap newTextures;
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = false;
|
||||
_textures = entity->getTextures();
|
||||
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
||||
});
|
||||
_texturesLoaded = false;
|
||||
_textures = entity->getTextures();
|
||||
newTextures = parseTexturesToMap(_textures, entity->_originalTextures);
|
||||
model->setTextures(newTextures);
|
||||
}
|
||||
|
||||
if (entity->_needsJointSimulation) {
|
||||
entity->copyAnimationJointDataToModel();
|
||||
}
|
||||
entity->updateModelBounds();
|
||||
entity->stopModelOverrideIfNoParent();
|
||||
|
||||
if (model->isVisible() != _visible) {
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
}
|
||||
|
||||
if (model->isCauterized() != _cauterized) {
|
||||
model->setCauterized(_cauterized, scene);
|
||||
}
|
||||
|
||||
render::hifi::Tag tagMask = getTagMask();
|
||||
if (model->getTagMask() != tagMask) {
|
||||
model->setTagMask(tagMask, scene);
|
||||
}
|
||||
setKey(_didLastVisualGeometryRequestSucceed, model);
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
model->setCauterized(_cauterized, scene);
|
||||
model->setCanCastShadow(_canCastShadow, scene);
|
||||
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 (entity->blendshapesChanged()) {
|
||||
model->setBlendshapeCoefficients(entity->getBlendshapeCoefficientVector());
|
||||
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");
|
||||
if (model->needsFixupInScene()) {
|
||||
|
@ -1452,9 +1379,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
|
||||
if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
||||
withWriteLock([&] {
|
||||
_texturesLoaded = true;
|
||||
});
|
||||
_texturesLoaded = true;
|
||||
model->updateRenderItems();
|
||||
} else if (!_texturesLoaded) {
|
||||
emit requestRenderUpdate();
|
||||
|
@ -1491,9 +1416,13 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
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
|
||||
// That is where _currentFrame and _lastAnimated were updated.
|
||||
if (_animating) {
|
||||
if (entity->isAnimatingSomething()) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||
|
||||
auto animationURL = entity->getAnimationURL();
|
||||
|
@ -1502,18 +1431,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
_animationURL = animationURL;
|
||||
|
||||
if (_animation) {
|
||||
//(_animation->getURL().toString() != entity->getAnimationURL())) { // bad check
|
||||
// the joints have been mapped before but we have a new animation to load
|
||||
_animation.reset();
|
||||
_jointMappingCompleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
if (!_jointMappingCompleted) {
|
||||
mapJoints(entity, model);
|
||||
}
|
||||
if (entity->readyToAnimate()) {
|
||||
animate(entity);
|
||||
if (entity->readyToAnimate() && model && model->isLoaded()) {
|
||||
animate(entity, model);
|
||||
}
|
||||
emit requestRenderUpdate();
|
||||
}
|
||||
|
@ -1521,40 +1452,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
void ModelEntityRenderer::setIsVisibleInSecondaryCamera(bool value) {
|
||||
Parent::setIsVisibleInSecondaryCamera(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setTagMask(getTagMask());
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setRenderLayer(RenderLayer value) {
|
||||
Parent::setRenderLayer(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setHifiRenderLayer(getHifiRenderLayer());
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setPrimitiveMode(PrimitiveMode value) {
|
||||
Parent::setPrimitiveMode(value);
|
||||
if (_model) {
|
||||
_model->setPrimitiveMode(_primitiveMode);
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setCullWithParent(bool value) {
|
||||
Parent::setCullWithParent(value);
|
||||
setKey(_didLastVisualGeometryRequestSucceed);
|
||||
if (_model) {
|
||||
_model->setCullWithParent(_cullWithParent);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityRenderer::setRenderWithZones(const QVector<QUuid>& renderWithZones) {
|
||||
Parent::setRenderWithZones(renderWithZones);
|
||||
if (_model) {
|
||||
_model->setRenderWithZones(renderWithZones);
|
||||
}
|
||||
// called within a lock so no need to lock for _model
|
||||
setKey(_didLastVisualGeometryRequestSucceed, _model);
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
#if WANT_EXTRA_DEBUGGING
|
||||
ModelPointer model;
|
||||
withReadLock([&] {
|
||||
model = _model;
|
||||
ModelPointer model = resultWithReadLock<ModelPointer>([&] {
|
||||
return _model;
|
||||
});
|
||||
if (model) {
|
||||
model->renderDebugMeshBoxes(batch, args->_renderMethod == Args::RenderMethod::FORWARD);
|
||||
|
|
|
@ -153,25 +153,24 @@ protected:
|
|||
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override;
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
void setKey(bool didVisualGeometryRequestSucceed);
|
||||
void setKey(bool didVisualGeometryRequestSucceed, const ModelPointer& model);
|
||||
virtual ItemKey getKey() override;
|
||||
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override;
|
||||
virtual void handleBlendedVertices(int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets,
|
||||
const QVector<int>& blendedMeshSizes, const render::ItemIDs& subItemIDs) override;
|
||||
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) 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 doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
void setIsVisibleInSecondaryCamera(bool value) override;
|
||||
void setRenderLayer(RenderLayer value) override;
|
||||
void setPrimitiveMode(PrimitiveMode value) override;
|
||||
void setCullWithParent(bool value) override;
|
||||
void setRenderWithZones(const QVector<QUuid>& renderWithZones) override;
|
||||
|
||||
private:
|
||||
void animate(const TypedEntityPointer& entity);
|
||||
void animate(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||
void mapJoints(const TypedEntityPointer& entity, const ModelPointer& model);
|
||||
|
||||
// Transparency is handled in ModelMeshPartPayload
|
||||
|
@ -192,14 +191,12 @@ private:
|
|||
bool _jointMappingCompleted { false };
|
||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||
AnimationPointer _animation;
|
||||
bool _animating { false };
|
||||
QString _animationURL;
|
||||
uint64_t _lastAnimated { 0 };
|
||||
|
||||
render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() };
|
||||
|
||||
bool _didLastVisualGeometryRequestSucceed { true };
|
||||
bool _prevModelLoaded { false };
|
||||
|
||||
void processMaterials();
|
||||
bool _allProceduralMaterialsLoaded { false };
|
||||
|
|
|
@ -78,7 +78,14 @@ void LightEntityItem::setFalloffRadius(float value) {
|
|||
}
|
||||
|
||||
void LightEntityItem::setIsSpotlight(bool value) {
|
||||
if (value == getIsSpotlight()) {
|
||||
bool needsRenderUpdate;
|
||||
withWriteLock([&] {
|
||||
needsRenderUpdate = value != _isSpotlight;
|
||||
_needsRenderUpdate |= needsRenderUpdate;
|
||||
_isSpotlight = value;
|
||||
});
|
||||
|
||||
if (!needsRenderUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,25 +99,25 @@ void LightEntityItem::setIsSpotlight(bool value) {
|
|||
newDimensions = glm::vec3(glm::compMax(dimensions));
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = true;
|
||||
_isSpotlight = value;
|
||||
});
|
||||
setScaledDimensions(newDimensions);
|
||||
}
|
||||
|
||||
void LightEntityItem::setCutoff(float value) {
|
||||
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;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_needsRenderUpdate = true;
|
||||
_cutoff = value;
|
||||
});
|
||||
|
||||
if (getIsSpotlight()) {
|
||||
if (spotlight) {
|
||||
// If we are a spotlight, adjusting the cutoff will affect the area we encapsulate,
|
||||
// so update the dimensions to reflect this.
|
||||
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) {
|
||||
// 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) {
|
||||
if (newSize < 0) {
|
||||
return;
|
||||
|
@ -629,61 +608,18 @@ void ModelEntityItem::setAnimationCurrentFrame(float value) {
|
|||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationAllowTranslation(bool value) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setAllowTranslation(value);
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationAllowTranslation() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
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 {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getCurrentFrame();
|
||||
});
|
||||
}
|
||||
|
||||
float ModelEntityItem::getAnimationFPS() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getFPS();
|
||||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::isAnimatingSomething() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.isValidAndRunning();
|
||||
|
@ -722,6 +658,7 @@ bool ModelEntityItem::applyNewAnimationProperties(AnimationPropertyGroup newProp
|
|||
bool somethingChanged = newProperties != _animationProperties;
|
||||
if (somethingChanged) {
|
||||
_animationProperties = newProperties;
|
||||
_needsRenderUpdate = true;
|
||||
_flags |= Simulation::DIRTY_UPDATEABLE;
|
||||
}
|
||||
return somethingChanged;
|
||||
|
|
|
@ -85,24 +85,12 @@ public:
|
|||
|
||||
// Animation related items...
|
||||
AnimationPropertyGroup getAnimationProperties() const;
|
||||
|
||||
// TODO: audit and remove unused Animation accessors
|
||||
bool hasAnimation() const;
|
||||
QString getAnimationURL() const;
|
||||
virtual void setAnimationURL(const QString& url);
|
||||
|
||||
void setAnimationCurrentFrame(float value);
|
||||
void setAnimationIsPlaying(bool value);
|
||||
void setAnimationFPS(float value);
|
||||
|
||||
void setAnimationAllowTranslation(bool value);
|
||||
float getAnimationCurrentFrame() const;
|
||||
bool getAnimationAllowTranslation() const;
|
||||
|
||||
void setAnimationLoop(bool loop);
|
||||
bool getAnimationLoop() const;
|
||||
|
||||
void setAnimationHold(bool hold);
|
||||
bool getAnimationHold() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
void setRelayParentJoints(bool relayJoints);
|
||||
bool getRelayParentJoints() const;
|
||||
|
@ -110,11 +98,6 @@ public:
|
|||
void setGroupCulled(bool value);
|
||||
bool getGroupCulled() const;
|
||||
|
||||
bool getAnimationIsPlaying() const;
|
||||
float getAnimationCurrentFrame() const;
|
||||
float getAnimationFPS() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
static const QString DEFAULT_TEXTURES;
|
||||
const QString getTextures() const;
|
||||
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) {
|
||||
_primitiveMode = primitiveMode;
|
||||
updateRenderItemsKey(nullptr);
|
||||
updateRenderItemsKey(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::setCullWithParent(bool cullWithParent) {
|
||||
void Model::setCullWithParent(bool cullWithParent, const render::ScenePointer& scene) {
|
||||
if (_cullWithParent != cullWithParent) {
|
||||
_cullWithParent = cullWithParent;
|
||||
if (!scene) {
|
||||
_needsFixupInScene = true;
|
||||
return;
|
||||
}
|
||||
|
||||
render::Transaction transaction;
|
||||
auto renderItemsKey = _renderItemKeyGlobalFlags;
|
||||
|
@ -977,14 +981,27 @@ void Model::setCullWithParent(bool cullWithParent) {
|
|||
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) {
|
||||
_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);
|
||||
|
||||
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; }
|
||||
|
||||
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; }
|
||||
|
||||
// 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