mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
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:
commit
4948ad425e
11 changed files with 88 additions and 40 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
});;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -123,7 +123,6 @@ private:
|
||||||
bool _pendingSkyboxTexture{ false };
|
bool _pendingSkyboxTexture{ false };
|
||||||
|
|
||||||
QString _proceduralUserData;
|
QString _proceduralUserData;
|
||||||
Transform _renderTransform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace
|
} } // namespace
|
||||||
|
|
Loading…
Reference in a new issue