Merge pull request #11533 from SamGondelman/modelMaster

Fix model loading for real this time
This commit is contained in:
Bradley Austin Davis 2017-10-08 10:23:13 -07:00 committed by GitHub
commit c92588685b
10 changed files with 112 additions and 172 deletions

View file

@ -222,16 +222,6 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
_renderablesToUpdate.insert({ entityId, renderable }); _renderablesToUpdate.insert({ entityId, renderable });
} }
// NOTE: Looping over all the entity renderers is likely to be a bottleneck in the future
// Currently, this is necessary because the model entity loading logic requires constant polling
// This was working fine because the entity server used to send repeated updates as your view changed,
// but with the improved entity server logic (PR 11141), updateInScene (below) would not be triggered enough
for (const auto& entry : _entitiesInScene) {
const auto& renderable = entry.second;
if (renderable) {
renderable->update(scene, transaction);
}
}
if (!_renderablesToUpdate.empty()) { if (!_renderablesToUpdate.empty()) {
for (const auto& entry : _renderablesToUpdate) { for (const auto& entry : _renderablesToUpdate) {
const auto& renderable = entry.second; const auto& renderable = entry.second;

View file

@ -291,18 +291,6 @@ void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& trans
}); });
} }
void EntityRenderer::update(const ScenePointer& scene, Transaction& transaction) {
if (!isValidRenderItem()) {
return;
}
if (!needsUpdate()) {
return;
}
doUpdate(scene, transaction, _entity);
}
// //
// Internal methods // Internal methods
// //
@ -316,11 +304,6 @@ bool EntityRenderer::needsRenderUpdate() const {
return needsRenderUpdateFromEntity(_entity); return needsRenderUpdateFromEntity(_entity);
} }
// Returns true if the item needs to have update called
bool EntityRenderer::needsUpdate() const {
return needsUpdateFromEntity(_entity);
}
// Returns true if the item in question needs to have updateInScene called because of changes in the entity // Returns true if the item in question needs to have updateInScene called because of changes in the entity
bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity) const { bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity) const {
bool success = false; bool success = false;
@ -346,25 +329,27 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
return false; return false;
} }
void EntityRenderer::doRenderUpdateAsynchronous(const EntityItemPointer& entity) { void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
auto transparent = isTransparent(); withWriteLock([&] {
if (_prevIsTransparent && !transparent) { auto transparent = isTransparent();
_isFading = false; if (_prevIsTransparent && !transparent) {
} _isFading = false;
_prevIsTransparent = transparent; }
_prevIsTransparent = transparent;
bool success = false; bool success = false;
auto bound = entity->getAABox(success); auto bound = entity->getAABox(success);
if (success) { if (success) {
_bound = bound; _bound = bound;
} }
auto newModelTransform = entity->getTransformToCenter(success); auto newModelTransform = entity->getTransformToCenter(success);
if (success) { if (success) {
_modelTransform = newModelTransform; _modelTransform = newModelTransform;
} }
_moving = entity->isMovingRelativeToParent(); _moving = entity->isMovingRelativeToParent();
_visible = entity->getVisible(); _visible = entity->getVisible();
});
} }
void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { void EntityRenderer::onAddToScene(const EntityItemPointer& entity) {

View file

@ -49,8 +49,6 @@ public:
virtual bool addToScene(const ScenePointer& scene, Transaction& transaction) final; virtual bool addToScene(const ScenePointer& scene, Transaction& transaction) final;
virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction); virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction);
virtual void update(const ScenePointer& scene, Transaction& transaction);
protected: protected:
virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); }
virtual void onAddToScene(const EntityItemPointer& entity); virtual void onAddToScene(const EntityItemPointer& entity);
@ -73,22 +71,14 @@ protected:
// Returns true if the item in question needs to have updateInScene called because of changes in the entity // Returns true if the item in question needs to have updateInScene called because of changes in the entity
virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const; virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const;
// Returns true if the item in question needs to have update called
virtual bool needsUpdate() const;
// Returns true if the item in question needs to have update called because of changes in the entity
virtual bool needsUpdateFromEntity(const EntityItemPointer& entity) const { return false; }
// Will be called on the main thread from updateInScene. This can be used to fetch things like // Will be called on the main thread from updateInScene. This can be used to fetch things like
// network textures or model geometry from resource caches // network textures or model geometry from resource caches
virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { } virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity);
// Will be called by the lambda posted to the scene in updateInScene. // Will be called by the lambda posted to the scene in updateInScene.
// This function will execute on the rendering thread, so you cannot use network caches to fetch // This function will execute on the rendering thread, so you cannot use network caches to fetch
// data in this method if using multi-threaded rendering // data in this method if using multi-threaded rendering
virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity); virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { }
virtual void doUpdate(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { }
// Called by the `render` method after `needsRenderUpdate` // Called by the `render` method after `needsRenderUpdate`
virtual void doRender(RenderArgs* args) = 0; virtual void doRender(RenderArgs* args) = 0;
@ -158,15 +148,6 @@ protected:
onRemoveFromSceneTyped(_typedEntity); onRemoveFromSceneTyped(_typedEntity);
} }
using Parent::needsUpdateFromEntity;
// Returns true if the item in question needs to have update called because of changes in the entity
virtual bool needsUpdateFromEntity(const EntityItemPointer& entity) const override final {
if (Parent::needsUpdateFromEntity(entity)) {
return true;
}
return needsUpdateFromTypedEntity(_typedEntity);
}
using Parent::needsRenderUpdateFromEntity; using Parent::needsRenderUpdateFromEntity;
// Returns true if the item in question needs to have updateInScene called because of changes in the entity // Returns true if the item in question needs to have updateInScene called because of changes in the entity
virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const override final { virtual bool needsRenderUpdateFromEntity(const EntityItemPointer& entity) const override final {
@ -181,11 +162,6 @@ protected:
doRenderUpdateSynchronousTyped(scene, transaction, _typedEntity); doRenderUpdateSynchronousTyped(scene, transaction, _typedEntity);
} }
virtual void doUpdate(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) override final {
Parent::doUpdate(scene, transaction, entity);
doUpdateTyped(scene, transaction, _typedEntity);
}
virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) override final { virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) override final {
Parent::doRenderUpdateAsynchronous(entity); Parent::doRenderUpdateAsynchronous(entity);
doRenderUpdateAsynchronousTyped(_typedEntity); doRenderUpdateAsynchronousTyped(_typedEntity);
@ -194,8 +170,6 @@ protected:
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { return false; } virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { return false; }
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { } virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { }
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { } virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { }
virtual bool needsUpdateFromTypedEntity(const TypedEntityPointer& entity) const { return false; }
virtual void doUpdateTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { }
virtual void onAddToSceneTyped(const TypedEntityPointer& entity) { } virtual void onAddToSceneTyped(const TypedEntityPointer& entity) { }
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) { } virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) { }

View file

@ -1026,16 +1026,12 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
entity->copyAnimationJointDataToModel(); entity->copyAnimationJointDataToModel();
} }
bool ModelEntityRenderer::needsUpdate() const { bool ModelEntityRenderer::needsRenderUpdate() const {
ModelPointer model; ModelPointer model;
withReadLock([&] { withReadLock([&] {
model = _model; model = _model;
}); });
if (_modelJustLoaded) {
return true;
}
if (model) { if (model) {
if (_needsJointSimulation || _moving || _animating) { if (_needsJointSimulation || _moving || _animating) {
return true; return true;
@ -1061,10 +1057,10 @@ bool ModelEntityRenderer::needsUpdate() const {
return true; return true;
} }
} }
return Parent::needsUpdate(); return Parent::needsRenderUpdate();
} }
bool ModelEntityRenderer::needsUpdateFromTypedEntity(const TypedEntityPointer& entity) const { bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
if (resultWithReadLock<bool>([&] { if (resultWithReadLock<bool>([&] {
if (entity->hasModel() != _hasModel) { if (entity->hasModel() != _hasModel) {
return true; return true;
@ -1126,7 +1122,7 @@ bool ModelEntityRenderer::needsUpdateFromTypedEntity(const TypedEntityPointer& e
return false; return false;
} }
void ModelEntityRenderer::doUpdateTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
if (_hasModel != entity->hasModel()) { if (_hasModel != entity->hasModel()) {
_hasModel = entity->hasModel(); _hasModel = entity->hasModel();
} }
@ -1152,11 +1148,11 @@ void ModelEntityRenderer::doUpdateTyped(const ScenePointer& scene, Transaction&
return; return;
} }
_modelJustLoaded = false;
// Check for addition // Check for addition
if (_hasModel && !(bool)_model) { if (_hasModel && !(bool)_model) {
model = std::make_shared<Model>(nullptr, entity.get()); model = std::make_shared<Model>(nullptr, entity.get());
connect(model.get(), &Model::setURLFinished, this, &ModelEntityRenderer::handleModelLoaded); connect(model.get(), &Model::setURLFinished, this, &ModelEntityRenderer::requestRenderUpdate);
connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate);
model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity)); model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity));
model->init(); model->init();
entity->setModel(model); entity->setModel(model);
@ -1247,12 +1243,6 @@ void ModelEntityRenderer::doUpdateTyped(const ScenePointer& scene, Transaction&
} }
} }
void ModelEntityRenderer::handleModelLoaded(bool success) {
if (success) {
_modelJustLoaded = true;
}
}
// 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
void ModelEntityRenderer::doRender(RenderArgs* args) { void ModelEntityRenderer::doRender(RenderArgs* args) {
PROFILE_RANGE(render_detail, "MetaModelRender"); PROFILE_RANGE(render_detail, "MetaModelRender");

View file

@ -138,10 +138,10 @@ protected:
virtual ItemKey getKey() override; virtual ItemKey getKey() override;
virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) override;
virtual bool needsUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
virtual bool needsUpdate() const override; virtual bool needsRenderUpdate() const override;
virtual void doRender(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override;
virtual void doUpdateTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
private: private:
void animate(const TypedEntityPointer& entity); void animate(const TypedEntityPointer& entity);
@ -151,7 +151,6 @@ private:
// Transparency is handled in ModelMeshPartPayload // Transparency is handled in ModelMeshPartPayload
virtual bool isTransparent() const override { return false; } virtual bool isTransparent() const override { return false; }
bool _modelJustLoaded { false };
bool _hasModel { false }; bool _hasModel { false };
::ModelPointer _model; ::ModelPointer _model;
GeometryResource::Pointer _compoundShapeResource; GeometryResource::Pointer _compoundShapeResource;
@ -180,8 +179,6 @@ private:
uint64_t _lastAnimated { 0 }; uint64_t _lastAnimated { 0 };
float _currentFrame { 0 }; float _currentFrame { 0 };
private slots:
void handleModelLoaded(bool success);
}; };
} } // namespace } } // namespace

View file

@ -88,31 +88,33 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
} }
_color = vec4(toGlm(entity->getXColor()), entity->getLocalRenderAlpha()); _color = vec4(toGlm(entity->getXColor()), entity->getLocalRenderAlpha());
_shape = entity->getShape();
_position = entity->getPosition();
_dimensions = entity->getDimensions();
_orientation = entity->getOrientation();
if (_shape == entity::Sphere) {
_modelTransform.postScale(SPHERE_ENTITY_SCALE);
}
_modelTransform.postScale(_dimensions);
}); });
} }
void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
if (_procedural.isEnabled() && _procedural.isFading()) { withReadLock([&] {
float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; if (_procedural.isEnabled() && _procedural.isFading()) {
_procedural.setIsFading(isFading); float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f;
} _procedural.setIsFading(isFading);
}
_shape = entity->getShape(); });
_position = entity->getPosition();
_dimensions = entity->getDimensions();
_orientation = entity->getOrientation();
if (_shape == entity::Sphere) {
_modelTransform.postScale(SPHERE_ENTITY_SCALE);
}
_modelTransform.postScale(_dimensions);
} }
bool ShapeEntityRenderer::isTransparent() const { bool ShapeEntityRenderer::isTransparent() const {
if (_procedural.isEnabled() && _procedural.isFading()) { if (_procedural.isEnabled() && _procedural.isFading()) {
return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f;
} }
// return _entity->getLocalRenderAlpha() < 1.0f || Parent::isTransparent(); // return _entity->getLocalRenderAlpha() < 1.0f || Parent::isTransparent();
return Parent::isTransparent(); return Parent::isTransparent();
@ -126,15 +128,16 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
auto geometryShape = MAPPING[_shape]; GeometryCache::Shape geometryShape;
batch.setModelTransform(_modelTransform); // use a transform with scale, rotation, registration point and translation
bool proceduralRender = false; bool proceduralRender = false;
glm::vec4 outColor = _color; glm::vec4 outColor;
withReadLock([&] { withReadLock([&] {
geometryShape = MAPPING[_shape];
batch.setModelTransform(_modelTransform); // use a transform with scale, rotation, registration point and translation
outColor = _color;
if (_procedural.isReady()) { if (_procedural.isReady()) {
_procedural.prepare(batch, _position, _dimensions, _orientation); _procedural.prepare(batch, _position, _dimensions, _orientation);
auto outColor = _procedural.getColor(_color); outColor = _procedural.getColor(_color);
outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f;
proceduralRender = true; proceduralRender = true;
} }
@ -149,13 +152,13 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
} }
} else { } else {
// FIXME, support instanced multi-shape rendering using multidraw indirect // FIXME, support instanced multi-shape rendering using multidraw indirect
_color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto pipeline = _color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) {
geometryCache->renderWireShapeInstance(args, batch, geometryShape, _color, pipeline); geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
} else { } else {
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, _color, pipeline); geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
} }
} }

View file

@ -118,31 +118,30 @@ void WebEntityRenderer::onTimeout() {
} }
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
// This work must be done on the main thread withWriteLock([&] {
if (!hasWebSurface()) { // This work must be done on the main thread
buildWebSurface(entity); if (!hasWebSurface()) {
} buildWebSurface(entity);
}
if (_contextPosition != entity->getPosition()) { if (_contextPosition != entity->getPosition()) {
// update globalPosition // update globalPosition
_contextPosition = entity->getPosition(); _contextPosition = entity->getPosition();
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
} }
if (_lastSourceUrl != entity->getSourceUrl()) { if (_lastSourceUrl != entity->getSourceUrl()) {
_lastSourceUrl = entity->getSourceUrl(); _lastSourceUrl = entity->getSourceUrl();
loadSourceURL(); loadSourceURL();
} }
_lastDPI = entity->getDPI(); _lastDPI = entity->getDPI();
glm::vec2 windowSize = getWindowSize(entity); glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y)); _webSurface->resize(QSize(windowSize.x, windowSize.y));
}
void WebEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { _modelTransform.postScale(entity->getDimensions());
Parent::doRenderUpdateAsynchronousTyped(entity); });
_modelTransform.postScale(entity->getDimensions());
} }
void WebEntityRenderer::doRender(RenderArgs* args) { void WebEntityRenderer::doRender(RenderArgs* args) {
@ -180,7 +179,9 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
batch.setModelTransform(_modelTransform); withReadLock([&] {
batch.setModelTransform(_modelTransform);
});
batch.setResourceTexture(0, _texture); batch.setResourceTexture(0, _texture);
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio);
@ -190,7 +191,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
} }
bool WebEntityRenderer::hasWebSurface() { bool WebEntityRenderer::hasWebSurface() {
return resultWithReadLock<bool>([&] { return (bool)_webSurface; }); return (bool)_webSurface;
} }
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
@ -213,11 +214,8 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
}; };
{ {
QSharedPointer<OffscreenQmlSurface> webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter); _webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
webSurface->create(); _webSurface->create();
withWriteLock([&] {
_webSurface = webSurface;
});
} }
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
@ -322,33 +320,31 @@ glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) con
} }
void WebEntityRenderer::loadSourceURL() { void WebEntityRenderer::loadSourceURL() {
withWriteLock([&] { const QUrl sourceUrl(_lastSourceUrl);
const QUrl sourceUrl(_lastSourceUrl); if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || _lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) {
_lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) { _contentType = htmlContent;
_contentType = htmlContent; _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/"));
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/"));
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) { if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) {
_webSurface->setMaxFps(YOUTUBE_MAX_FPS); _webSurface->setMaxFps(YOUTUBE_MAX_FPS);
} else {
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
}
_webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
item->setProperty("url", _lastSourceUrl);
});
} else { } else {
_contentType = qmlContent; _webSurface->setMaxFps(DEFAULT_MAX_FPS);
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
_webSurface->load(_lastSourceUrl);
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
}
} }
});
_webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
item->setProperty("url", _lastSourceUrl);
});
} else {
_contentType = qmlContent;
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
_webSurface->load(_lastSourceUrl);
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
}
}
} }
void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) { void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) {

View file

@ -29,7 +29,6 @@ protected:
virtual bool needsRenderUpdate() const override; 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 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;
virtual bool isTransparent() const override; virtual bool isTransparent() const override;

View file

@ -267,6 +267,11 @@ void Model::updateRenderItems() {
}); });
} }
void Model::setRenderItemsNeedUpdate() {
_renderItemsNeedUpdate = true;
emit requestRenderUpdate();
}
void Model::initJointTransforms() { void Model::initJointTransforms() {
if (isLoaded()) { if (isLoaded()) {
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset); glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);

View file

@ -103,7 +103,7 @@ public:
bool isLayeredInFront() const { return _isLayeredInFront; } bool isLayeredInFront() const { return _isLayeredInFront; }
virtual void updateRenderItems(); virtual void updateRenderItems();
void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; } void setRenderItemsNeedUpdate();
bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; } bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; }
AABox getRenderableMeshBound() const; AABox getRenderableMeshBound() const;
const render::ItemIDs& fetchRenderItemIDs() const; const render::ItemIDs& fetchRenderItemIDs() const;
@ -265,6 +265,7 @@ public slots:
signals: signals:
void setURLFinished(bool success); void setURLFinished(bool success);
void setCollisionModelURLFinished(bool success); void setCollisionModelURLFinished(bool success);
void requestRenderUpdate();
protected: protected: