Merge pull request #13429 from danteruiz/fix-entity-lag-2

Fix entities rendering a frame ahead or behind when parented to my avatar.
This commit is contained in:
John Conklin II 2018-06-26 13:57:19 -07:00 committed by GitHub
commit 4948ad425e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 88 additions and 40 deletions

View file

@ -363,6 +363,14 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
return false; return false;
} }
void EntityRenderer::updateModelTransform() {
bool success = false;
auto newModelTransform = _entity->getTransformToCenter(success);
if (success) {
_modelTransform = newModelTransform;
}
}
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
withWriteLock([&] { withWriteLock([&] {
@ -419,4 +427,4 @@ void EntityRenderer::addMaterial(graphics::MaterialLayer material, const std::st
void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock); std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].remove(material); _materials[parentMaterialName].remove(material);
} }

View file

@ -97,6 +97,7 @@ protected:
virtual void doRender(RenderArgs* args) = 0; virtual void doRender(RenderArgs* args) = 0;
bool isFading() const { return _isFading; } bool isFading() const { return _isFading; }
void updateModelTransform();
virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; } virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; } inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
@ -140,6 +141,7 @@ protected:
bool _needsRenderUpdate { false }; bool _needsRenderUpdate { false };
// Only touched on the rendering thread // Only touched on the rendering thread
bool _renderUpdateQueued{ false }; bool _renderUpdateQueued{ false };
Transform _renderTransform;
std::unordered_map<std::string, graphics::MultiMaterial> _materials; std::unordered_map<std::string, graphics::MultiMaterial> _materials;
std::mutex _materialsLock; std::mutex _materialsLock;

View file

@ -35,7 +35,6 @@ private:
glm::vec2 _materialMappingPos; glm::vec2 _materialMappingPos;
glm::vec2 _materialMappingScale; glm::vec2 _materialMappingScale;
float _materialMappingRot; float _materialMappingRot;
Transform _renderTransform;
std::shared_ptr<NetworkMaterial> _drawMaterial; std::shared_ptr<NetworkMaterial> _drawMaterial;
}; };

View file

@ -122,6 +122,14 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi
}); });
} }
} }
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
withWriteLock([&] {
updateModelTransform();
_renderTransform = getModelTransform();
});
});
} }
void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
@ -319,7 +327,10 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
// In trail mode, the particles are created in world space. // In trail mode, the particles are created in world space.
// so we only set a transform if they're not in trail mode // so we only set a transform if they're not in trail mode
if (!_particleProperties.emission.shouldTrail) { if (!_particleProperties.emission.shouldTrail) {
transform = getModelTransform();
withReadLock([&] {
transform = _renderTransform;
});
transform.setScale(vec3(1)); transform.setScale(vec3(1));
} }
batch.setModelTransform(transform); batch.setModelTransform(transform);

View file

@ -97,16 +97,25 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
addMaterial(graphics::MaterialLayer(_material, 0), "0"); addMaterial(graphics::MaterialLayer(_material, 0), "0");
_shape = entity->getShape(); _shape = entity->getShape();
_position = entity->getWorldPosition(); });
_dimensions = entity->getScaledDimensions();
_orientation = entity->getWorldOrientation();
_renderTransform = getModelTransform();
if (_shape == entity::Sphere) { void* key = (void*)this;
_renderTransform.postScale(SPHERE_ENTITY_SCALE); AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this] () {
} withWriteLock([&] {
auto entity = getEntity();
_position = entity->getWorldPosition();
_dimensions = entity->getScaledDimensions();
_orientation = entity->getWorldOrientation();
bool success = false;
auto newModelTransform = entity->getTransformToCenter(success);
_renderTransform = success ? newModelTransform : getModelTransform();
_renderTransform.postScale(_dimensions); if (_shape == entity::Sphere) {
_renderTransform.postScale(SPHERE_ENTITY_SCALE);
}
_renderTransform.postScale(_dimensions);
});;
}); });
} }

View file

@ -40,7 +40,6 @@ private:
Procedural _procedural; Procedural _procedural;
QString _lastUserData; QString _lastUserData;
Transform _renderTransform;
entity::Shape _shape { entity::Sphere }; entity::Shape _shape { entity::Sphere };
std::shared_ptr<graphics::Material> _material; std::shared_ptr<graphics::Material> _material;
glm::vec3 _position; glm::vec3 _position;

View file

@ -20,6 +20,7 @@
#include "GLMHelpers.h" #include "GLMHelpers.h"
using namespace render;
using namespace render::entities; using namespace render::entities;
static const int FIXED_FONT_POINT_SIZE = 40; static const int FIXED_FONT_POINT_SIZE = 40;
@ -64,10 +65,20 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
return false; return false;
} }
void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
withWriteLock([&] {
_dimensions = entity->getScaledDimensions();
updateModelTransform();
_renderTransform = getModelTransform();
});
});
}
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
_textColor = toGlm(entity->getTextColorX()); _textColor = toGlm(entity->getTextColorX());
_backgroundColor = toGlm(entity->getBackgroundColorX()); _backgroundColor = toGlm(entity->getBackgroundColorX());
_dimensions = entity->getScaledDimensions();
_faceCamera = entity->getFaceCamera(); _faceCamera = entity->getFaceCamera();
_lineHeight = entity->getLineHeight(); _lineHeight = entity->getLineHeight();
_text = entity->getText(); _text = entity->getText();
@ -76,24 +87,28 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
void TextEntityRenderer::doRender(RenderArgs* args) { void TextEntityRenderer::doRender(RenderArgs* args) {
PerformanceTimer perfTimer("RenderableTextEntityItem::render"); PerformanceTimer perfTimer("RenderableTextEntityItem::render");
Transform modelTransform;
glm::vec3 dimensions;
withReadLock([&] {
modelTransform = _renderTransform;
dimensions = _dimensions;
});
static const float SLIGHTLY_BEHIND = -0.005f; static const float SLIGHTLY_BEHIND = -0.005f;
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
bool transparent = fadeRatio < 1.0f; bool transparent = fadeRatio < 1.0f;
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio); glm::vec4 textColor = glm::vec4(_textColor, fadeRatio);
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio); glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio);
const glm::vec3& dimensions = _dimensions;
// Render background // Render background
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND); glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND); glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
// Batch render calls // Batch render calls
Q_ASSERT(args->_batch); Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch; gpu::Batch& batch = *args->_batch;
const auto& modelTransform = getModelTransform();
auto transformToTopLeft = modelTransform; auto transformToTopLeft = modelTransform;
if (_faceCamera) { if (_faceCamera) {
//rotate about vertical to face the camera //rotate about vertical to face the camera
@ -105,7 +120,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
} }
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed
batch.setModelTransform(transformToTopLeft); batch.setModelTransform(transformToTopLeft);
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
if (!_geometryID) { if (!_geometryID) {
@ -113,11 +128,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
} }
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false); geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false);
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
float scale = _lineHeight / _textRenderer->getFontSize(); float scale = _lineHeight / _textRenderer->getFontSize();
transformToTopLeft.setScale(scale); // Scale to have the correct line height transformToTopLeft.setScale(scale); // Scale to have the correct line height
batch.setModelTransform(transformToTopLeft); batch.setModelTransform(transformToTopLeft);
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight; float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin, glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
dimensions.y - 2.0f * topMargin); dimensions.y - 2.0f * topMargin);

View file

@ -27,6 +27,7 @@ public:
~TextEntityRenderer(); ~TextEntityRenderer();
private: private:
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;
int _geometryID{ 0 }; int _geometryID{ 0 };
@ -39,6 +40,6 @@ private:
float _lineHeight; float _lineHeight;
}; };
} } } }
#endif // hifi_RenderableTextEntityItem_h #endif // hifi_RenderableTextEntityItem_h

View file

@ -149,8 +149,8 @@ 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) {
// If the content type has changed, or the old content type was QML, we need to // If the content type has changed, or the old content type was QML, we need to
// destroy the existing surface (because surfaces don't support changing the root // destroy the existing surface (because surfaces don't support changing the root
// object, so subsequent loads of content just overlap the existing content // object, so subsequent loads of content just overlap the existing content
bool urlChanged = false; bool urlChanged = false;
{ {
@ -187,24 +187,30 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
if (!hasWebSurface() && !buildWebSurface(entity)) { if (!hasWebSurface() && !buildWebSurface(entity)) {
return; return;
} }
if (urlChanged && _contentType == ContentType::HtmlContent) { if (urlChanged && _contentType == ContentType::HtmlContent) {
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl); _webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl);
} }
if (_contextPosition != entity->getWorldPosition()) { void* key = (void*)this;
// update globalPosition AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
_contextPosition = entity->getWorldPosition(); withWriteLock([&] {
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); if (_contextPosition != entity->getWorldPosition()) {
} // update globalPosition
_contextPosition = entity->getWorldPosition();
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
}
_lastDPI = entity->getDPI(); _lastDPI = entity->getDPI();
_lastLocked = entity->getLocked(); _lastLocked = entity->getLocked();
glm::vec2 windowSize = getWindowSize(entity); glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y)); _webSurface->resize(QSize(windowSize.x, windowSize.y));
_renderTransform = getModelTransform(); updateModelTransform();
_renderTransform.postScale(entity->getScaledDimensions()); _renderTransform = getModelTransform();
_renderTransform.postScale(entity->getScaledDimensions());
});
});
}); });
} }
@ -297,7 +303,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
if (_contentType == ContentType::HtmlContent) { if (_contentType == ContentType::HtmlContent) {
// 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.
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the // FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
// web entity // web entity
if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) { if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
_webSurface->setMaxFps(YOUTUBE_MAX_FPS); _webSurface->setMaxFps(YOUTUBE_MAX_FPS);

View file

@ -68,7 +68,6 @@ private:
bool _lastLocked; bool _lastLocked;
QTimer _timer; QTimer _timer;
uint64_t _lastRenderTime { 0 }; uint64_t _lastRenderTime { 0 };
Transform _renderTransform;
}; };
} } // namespace } } // namespace

View file

@ -123,7 +123,6 @@ private:
bool _pendingSkyboxTexture{ false }; bool _pendingSkyboxTexture{ false };
QString _proceduralUserData; QString _proceduralUserData;
Transform _renderTransform;
}; };
} } // namespace } } // namespace