From 6e0bad814e0e513a4b363059d4cf43e609e2627a Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 3 Jan 2021 20:33:08 -0800 Subject: [PATCH 01/11] working on billboard mode for all entity types --- .../src/RenderableEntityItem.cpp | 40 +++++++++++-------- .../src/RenderableEntityItem.h | 4 +- .../src/RenderableGizmoEntityItem.cpp | 9 +++-- .../src/RenderableGridEntityItem.cpp | 4 +- .../src/RenderableImageEntityItem.cpp | 12 ------ .../src/RenderableImageEntityItem.h | 2 - .../src/RenderableLineEntityItem.cpp | 1 + .../src/RenderableMaterialEntityItem.cpp | 11 ++--- .../RenderableParticleEffectEntityItem.cpp | 2 + .../src/RenderablePolyLineEntityItem.cpp | 4 +- .../src/RenderableShapeEntityItem.cpp | 15 ++++--- .../src/RenderableTextEntityItem.cpp | 37 +++++------------ .../src/RenderableTextEntityItem.h | 2 - .../src/RenderableWebEntityItem.cpp | 16 +------- .../src/RenderableWebEntityItem.h | 2 - libraries/entities/src/EntityItem.cpp | 30 +++++++++++++- libraries/entities/src/EntityItem.h | 7 +++- .../entities/src/EntityItemProperties.cpp | 32 ++++++--------- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- libraries/entities/src/GizmoEntityItem.cpp | 3 ++ libraries/entities/src/ImageEntityItem.cpp | 37 +++-------------- libraries/entities/src/ImageEntityItem.h | 5 --- libraries/entities/src/TextEntityItem.cpp | 37 +++-------------- libraries/entities/src/TextEntityItem.h | 6 --- libraries/entities/src/WebEntityItem.cpp | 35 +++------------- libraries/entities/src/WebEntityItem.h | 5 --- libraries/networking/src/udt/PacketHeaders.h | 1 + 28 files changed, 134 insertions(+), 229 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b116423b75..fdb971e7a3 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -138,7 +138,14 @@ EntityRenderer::~EntityRenderer() {} // Item::Bound EntityRenderer::getBound() { - return _bound; + auto bound = _bound; + if (_billboardMode != BillboardMode::NONE) { + glm::vec3 dimensions = bound.getScale(); + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); + } + return bound; } ShapeKey EntityRenderer::getShapeKey() { @@ -198,12 +205,9 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { } bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { - auto renderWithZones = resultWithReadLock>([&] { - return _renderWithZones; - }); - if (!renderWithZones.isEmpty()) { + if (!_renderWithZones.isEmpty()) { if (!containingZones.empty()) { - for (auto renderWithZone : renderWithZones) { + for (auto renderWithZone : _renderWithZones) { if (containingZones.find(renderWithZone) != containingZones.end()) { return true; } @@ -429,20 +433,24 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _moving = entity->isMovingRelativeToParent(); _visible = entity->getVisible(); - setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); - setRenderLayer(entity->getRenderLayer()); - _primitiveMode = entity->getPrimitiveMode(); - _canCastShadow = entity->getCanCastShadow(); - setCullWithParent(entity->getCullWithParent()); - _cauterized = entity->getCauterized(); - if (entity->needsZoneOcclusionUpdate()) { - entity->resetNeedsZoneOcclusionUpdate(); - _renderWithZones = entity->getRenderWithZones(); - } entity->setNeedsRenderUpdate(false); }); } +void EntityRenderer::doRenderUpdateAsynchronous(const EntityItemPointer& entity) { + setIsVisibleInSecondaryCamera(entity->isVisibleInSecondaryCamera()); + setRenderLayer(entity->getRenderLayer()); + _billboardMode = entity->getBillboardMode(); + _primitiveMode = entity->getPrimitiveMode(); + _canCastShadow = entity->getCanCastShadow(); + setCullWithParent(entity->getCullWithParent()); + _cauterized = entity->getCauterized(); + if (entity->needsZoneOcclusionUpdate()) { + entity->resetNeedsZoneOcclusionUpdate(); + _renderWithZones = entity->getRenderWithZones(); + } +} + void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { QObject::connect(this, &EntityRenderer::requestRenderUpdate, this, [this] { auto renderer = DependencyManager::get(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index ca3e024338..4afcd6e231 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -95,8 +95,7 @@ protected: // 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 // data in this method if using multi-threaded rendering - - virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { } + virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity); // Called by the `render` method after `needsRenderUpdate` virtual void doRender(RenderArgs* args) = 0; @@ -135,6 +134,7 @@ protected: RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; QVector _renderWithZones; + BillboardMode _billboardMode; bool _cauterized { false }; bool _moving { false }; Transform _renderTransform; diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 6928454eb0..caf5bde729 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -242,18 +242,19 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { 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; 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; + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; + geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 35702c63e4..87b916e41b 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -77,17 +77,17 @@ void GridEntityRenderer::doRender(RenderArgs* args) { color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); glm::vec3 dimensions; Transform renderTransform; - bool forward; withReadLock([&] { dimensions = _dimensions; renderTransform = _renderTransform; - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; }); if (!_visible || color.a == 0.0f) { return; } + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; + auto batch = args->_batch; Transform transform; diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index b9b30ea9c7..878fcad6e4 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -58,7 +58,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); - _billboardMode = entity->getBillboardMode(); if (!_textureIsLoaded) { emit requestRenderUpdate(); @@ -66,17 +65,6 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed()); } -Item::Bound ImageEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - ShapeKey ImageEntityRenderer::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (isTransparent()) { diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index 35d60a230f..2359dcc6d1 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -23,7 +23,6 @@ public: ~ImageEntityRenderer(); protected: - Item::Bound getBound() override; ShapeKey getShapeKey() override; bool isTransparent() const override; @@ -44,7 +43,6 @@ private: glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; int _geometryId { 0 }; }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 6e2be1b41e..1964f1bdda 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -48,6 +48,7 @@ void LineEntityRenderer::doRender(RenderArgs* args) { Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); transform.setRotation(modelTransform.getRotation()); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 3d2e59518c..f7631f3e35 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -259,9 +259,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); - Transform renderTransform; + Transform transform; withReadLock([&] { - renderTransform = _renderTransform; + transform = _renderTransform; }); if (!drawMaterial) { @@ -272,7 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - batch.setModelTransform(renderTransform); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + batch.setModelTransform(transform); if (!proceduralRender) { drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); @@ -287,8 +288,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { auto proceduralDrawMaterial = std::static_pointer_cast(drawMaterial); glm::vec4 outColor = glm::vec4(drawMaterial->getAlbedo(), drawMaterial->getOpacity()); outColor = proceduralDrawMaterial->getColor(outColor); - proceduralDrawMaterial->prepare(batch, renderTransform.getTranslation(), renderTransform.getScale(), - renderTransform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); + proceduralDrawMaterial->prepare(batch, transform.getTranslation(), transform.getScale(), + transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f)); if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { DependencyManager::get()->renderWireSphere(batch, outColor); } else { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index e53e52d105..91f922c7c7 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -455,7 +455,9 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created); color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); + batch.setUniformBuffer(0, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle)); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index f98a54d594..47b1186c59 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,8 +325,10 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); + + batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); batch.setResourceTexture(0, texture); batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * _numVertices), 0); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 06ccdef753..87dbbd068b 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -221,14 +221,11 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { graphics::MultiMaterial materials; auto geometryCache = DependencyManager::get(); GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape); - PrimitiveMode primitiveMode; - RenderLayer renderLayer; glm::vec4 outColor; Pipeline pipelineType; + Transform transform; withReadLock([&] { - primitiveMode = _primitiveMode; - renderLayer = _renderLayer; - batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation + transform = _renderTransform; materials = _materials["0"]; pipelineType = getPipelineType(materials); auto& schema = materials.getSchemaBuffer().get(); @@ -241,6 +238,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + if (pipelineType == Pipeline::PROCEDURAL) { auto procedural = std::static_pointer_cast(materials.top().material); outColor = procedural->getColor(outColor); @@ -249,7 +248,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); }); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShape(batch, geometryShape, outColor); } else { geometryCache->renderShape(batch, geometryShape, outColor); @@ -258,8 +257,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, - renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode()); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode()); + if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 04ad86c7e1..acbbb57bd4 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -54,17 +54,6 @@ bool TextEntityRenderer::isTextTransparent() const { }); } -Item::Bound TextEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - ItemKey TextEntityRenderer::getKey() { return ItemKey::Builder(Parent::getKey()).withMetaCullGroup(); } @@ -111,7 +100,6 @@ void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _textAlpha = entity->getTextAlpha(); _backgroundColor = toGlm(entity->getBackgroundColor()); _backgroundAlpha = entity->getBackgroundAlpha(); - _billboardMode = entity->getBillboardMode(); _leftMargin = entity->getLeftMargin(); _rightMargin = entity->getRightMargin(); _topMargin = entity->getTopMargin(); @@ -130,13 +118,9 @@ void TextEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 backgroundColor; - Transform modelTransform; - PrimitiveMode primitiveMode; - RenderLayer renderLayer; + Transform transform; withReadLock([&] { - modelTransform = _renderTransform; - primitiveMode = _primitiveMode; - renderLayer = _renderLayer; + transform = _renderTransform; float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); @@ -147,14 +131,14 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); - batch.setModelTransform(modelTransform); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); // FIXME: we want to use instanced rendering here, but if textAlpha < 1 and backgroundAlpha < 1, the transparency sorting will be wrong //render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(backgroundColor.a < 1.0f, _unlit, - // renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); - //if (render::ShapeKey(args->_globalShapeKey).isWireframe() || primitiveMode == PrimitiveMode::LINES) { + // _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD); + //if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { // geometryCache->renderWireShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); //} else { // geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Quad, backgroundColor, pipeline); @@ -309,21 +293,18 @@ void entities::TextPayload::render(RenderArgs* args) { Transform modelTransform; glm::vec3 dimensions; - BillboardMode billboardMode; glm::vec4 textColor; - bool forward; textRenderable->withReadLock([&] { modelTransform = textRenderable->_renderTransform; dimensions = textRenderable->_dimensions; - billboardMode = textRenderable->_billboardMode; float fadeRatio = textRenderable->_isFading ? Interpolate::calculateFadeRatio(textRenderable->_fadeStartTime) : 1.0f; textColor = glm::vec4(textRenderable->_textColor, fadeRatio * textRenderable->_textAlpha); - - forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; }); + bool forward = textRenderable->_renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; + textColor = EntityRenderer::calculatePulseColor(textColor, textRenderable->_pulseProperties, textRenderable->_created); glm::vec3 effectColor = EntityRenderer::calculatePulseColor(textRenderable->_effectColor, textRenderable->_pulseProperties, textRenderable->_created); @@ -331,7 +312,7 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), billboardMode, args->getViewFrustum().getPosition())); + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 51651d98ba..1564c98644 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -33,7 +33,6 @@ public: protected: bool isTransparent() const override; bool isTextTransparent() const; - Item::Bound getBound() override; ShapeKey getShapeKey() override; ItemKey getKey() override; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; @@ -63,7 +62,6 @@ private: float _topMargin; float _bottomMargin; - BillboardMode _billboardMode; glm::vec3 _dimensions; QString _font { "" }; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8b41a85cf8..93d1b9974e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -167,7 +167,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); - _billboardMode = entity->getBillboardMode(); if (_contentType == ContentType::NoContent) { _tryingToBuildURL = newSourceURL; @@ -257,17 +256,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene }); } -Item::Bound WebEntityRenderer::getBound() { - auto bound = Parent::getBound(); - if (_billboardMode != BillboardMode::NONE) { - glm::vec3 dimensions = bound.getScale(); - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); - } - return bound; -} - void WebEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("WebEntityRenderer::render"); withWriteLock([&] { @@ -297,14 +285,12 @@ void WebEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 color; Transform transform; - bool forward; bool transparent; withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); transform = _renderTransform; - forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; transparent = isTransparent(); }); @@ -312,6 +298,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { return; } + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == render::Args::FORWARD; + batch.setResourceTexture(0, _texture); transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 63ec722811..ee1fa36c02 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -59,7 +59,6 @@ protected: virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; - Item::Bound getBound() override; virtual bool wantsHandControllerPointerEvents() const override { return true; } virtual bool wantsKeyboardFocus() const override { return true; } @@ -90,7 +89,6 @@ private: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _sourceURL; uint16_t _dpi; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d7a5e992e1..657d778090 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -107,6 +107,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; requestedProperties += PROP_RENDER_WITH_ZONES; + requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += _grabProperties.getEntityProperties(params); // Physics @@ -303,6 +304,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection()); APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones()); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -875,6 +877,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); + READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1358,6 +1361,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection); COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1508,6 +1512,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection); SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -1905,6 +1910,16 @@ void EntityItem::setScaledDimensions(const glm::vec3& value) { setUnscaledDimensions(value / parentScale); } +glm::vec3 EntityItem::getRaycastDimensions() const { + glm::vec3 dimensions = getScaledDimensions(); + if (getBillboardMode() != BillboardMode::NONE) { + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + return glm::vec3(SQRT_2 * max); + } + return dimensions; +} + void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(ENTITY_ITEM_MIN_DIMENSION)); const float MIN_SCALE_CHANGE_SQUARED = 1.0e-6f; @@ -3591,4 +3606,17 @@ QVector EntityItem::getRenderWithZones() const { return resultWithReadLock>([&] { return _renderWithZones; }); -} \ No newline at end of file +} + +BillboardMode EntityItem::getBillboardMode() const { + return resultWithReadLock([&] { + return _billboardMode; + }); +} + +void EntityItem::setBillboardMode(BillboardMode value) { + withWriteLock([&] { + _needsRenderUpdate |= _billboardMode != value; + _billboardMode = value; + }); +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2a6952fc0d..69b9abe376 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -203,7 +203,7 @@ public: /// Dimensions in meters (0.0 - TREE_SCALE) virtual glm::vec3 getScaledDimensions() const; virtual void setScaledDimensions(const glm::vec3& value); - virtual glm::vec3 getRaycastDimensions() const { return getScaledDimensions(); } + virtual glm::vec3 getRaycastDimensions() const; glm::vec3 getUnscaledDimensions() const; virtual void setUnscaledDimensions(const glm::vec3& value); @@ -587,6 +587,9 @@ public: bool needsZoneOcclusionUpdate() const { return _needsZoneOcclusionUpdate; } void resetNeedsZoneOcclusionUpdate() { withWriteLock([&] { _needsZoneOcclusionUpdate = false; }); } + void setBillboardMode(BillboardMode value); + BillboardMode getBillboardMode() const; + signals: void spaceUpdate(std::pair data); @@ -778,6 +781,8 @@ protected: QVector _renderWithZones; mutable bool _needsZoneOcclusionUpdate { false }; + BillboardMode _billboardMode { BillboardMode::NONE }; + bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ff55137a03..870ed09515 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -433,6 +433,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones); + CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); changedProperties += _grab.getChangedProperties(); // Physics @@ -493,7 +494,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ALPHA, alpha); changedProperties += _pulse.getChangedProperties(); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); - CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); // Particles CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); @@ -811,6 +811,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within * one of the zones in this list. + * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * * @property {Entities.Grab} grab - The entity's grab-related properties. * @@ -1332,7 +1333,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.TextEffect} textEffect="none" - The effect that is applied to the text. * @property {Color} textEffectColor=255,255,255 - The color of the effect. * @property {number} textEffectThickness=0.2 - The magnitude of the text effect, range 0.00.5. - * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1368,7 +1368,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alpha=1 - The opacity of the web surface. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

- * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1487,7 +1486,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alpha=1 - The opacity of the image. * @property {Entities.Pulse} pulse - Color and alpha pulse. *

Deprecated: This property is deprecated and will be removed.

- * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. * @property {boolean} faceCamera - true if billboardMode is "yaw", false * if it isn't. Setting this property to false sets the billboardMode to "none". *

Deprecated: This property is deprecated and will be removed.

@@ -1611,6 +1609,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -1766,7 +1765,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Text only if (_type == EntityTypes::Text) { _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight); @@ -1816,7 +1814,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DPI, dpi); @@ -1884,7 +1881,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive); @@ -2032,6 +2028,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection); COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2097,7 +2094,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(alpha, float, setAlpha); _pulse.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(textures, QString, setTextures); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); // Particles COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles); @@ -2329,6 +2325,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(primitiveMode); COPY_PROPERTY_IF_CHANGED(ignorePickIntersection); COPY_PROPERTY_IF_CHANGED(renderWithZones); + COPY_PROPERTY_IF_CHANGED(billboardMode); _grab.merge(other._grab); // Physics @@ -2389,7 +2386,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(alpha); _pulse.merge(other._pulse); COPY_PROPERTY_IF_CHANGED(textures); - COPY_PROPERTY_IF_CHANGED(billboardMode); // Particles COPY_PROPERTY_IF_CHANGED(maxParticles); @@ -2625,6 +2621,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool); ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector); + ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); { // Grab ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable); ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic); @@ -2721,7 +2718,6 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_ALPHA_MODE, Pulse, pulse, AlphaMode, alphaMode); } ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); - ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); // Particles ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, @@ -3117,6 +3113,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection()); APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones()); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3249,7 +3246,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); @@ -3321,7 +3317,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); @@ -3384,7 +3379,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, properties.getEmissive()); @@ -3610,6 +3604,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3736,7 +3731,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Text) { properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); @@ -3797,7 +3791,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); @@ -3857,7 +3850,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMISSIVE, bool, setEmissive); @@ -4031,6 +4023,7 @@ void EntityItemProperties::markAllChanged() { _primitiveModeChanged = true; _ignorePickIntersectionChanged = true; _renderWithZonesChanged = true; + _billboardModeChanged = true; _grab.markAllChanged(); // Physics @@ -4084,7 +4077,6 @@ void EntityItemProperties::markAllChanged() { _alphaChanged = true; _pulse.markAllChanged(); _texturesChanged = true; - _billboardModeChanged = true; // Particles _maxParticlesChanged = true; @@ -4439,6 +4431,9 @@ QList EntityItemProperties::listChangedProperties() { if (renderWithZonesChanged()) { out += "renderWithZones"; } + if (billboardModeChanged()) { + out += "billboardMode"; + } getGrab().listChangedProperties(out); // Physics @@ -4574,9 +4569,6 @@ QList EntityItemProperties::listChangedProperties() { if (texturesChanged()) { out += "textures"; } - if (billboardModeChanged()) { - out += "billboardMode"; - } // Particles if (maxParticlesChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index f7fde73430..e431465884 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -197,6 +197,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode, PrimitiveMode::SOLID); DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false); DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector, QVector()); + DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics @@ -257,7 +258,6 @@ public: DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, ENTITY_ITEM_DEFAULT_ALPHA); DEFINE_PROPERTY_GROUP(Pulse, pulse, PulsePropertyGroup); DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, ""); - DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); // Particles DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, particle::DEFAULT_MAX_PARTICLES); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 93bb8a89a7..6029d9f5ec 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -45,6 +45,7 @@ enum EntityPropertyList { PROP_PRIMITIVE_MODE, PROP_IGNORE_PICK_INTERSECTION, PROP_RENDER_WITH_ZONES, + PROP_BILLBOARD_MODE, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, @@ -122,7 +123,6 @@ enum EntityPropertyList { PROP_PULSE_COLOR_MODE, PROP_PULSE_ALPHA_MODE, PROP_TEXTURES, - PROP_BILLBOARD_MODE, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new shared EntityItem properties to the list ABOVE this line diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 47c9afd168..7ca1230fb1 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -111,6 +111,9 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 6a8c457b0a..fb59a85647 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -35,7 +35,6 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive); @@ -55,7 +54,6 @@ bool ImageEntityItem::setSubClassProperties(const EntityItemProperties& properti somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive); @@ -82,7 +80,6 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive); @@ -98,7 +95,6 @@ EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_IMAGE_URL; requestedProperties += PROP_EMISSIVE; @@ -124,7 +120,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive()); @@ -132,16 +127,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage()); } -glm::vec3 ImageEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -150,7 +135,9 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -174,6 +161,9 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -240,21 +230,6 @@ void ImageEntityItem::setKeepAspectRatio(bool keepAspectRatio) { }); } -BillboardMode ImageEntityItem::getBillboardMode() const { - BillboardMode result; - withReadLock([&] { - result = _billboardMode; - }); - return result; -} - -void ImageEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - QRect ImageEntityItem::getSubImage() const { QRect result; withReadLock([&] { diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index bca67dc738..0a90f93f9d 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,7 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -63,9 +62,6 @@ public: void setKeepAspectRatio(bool keepAspectRatio); bool getKeepAspectRatio() const; - void setBillboardMode(BillboardMode value); - BillboardMode getBillboardMode() const; - void setSubImage(const QRect& subImage); QRect getSubImage() const; @@ -81,7 +77,6 @@ protected: glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _imageURL; bool _emissive { false }; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index a996319463..906e28288b 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -53,7 +53,6 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); @@ -81,7 +80,6 @@ bool TextEntityItem::setSubClassProperties(const EntityItemProperties& propertie somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight); @@ -117,7 +115,6 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight); @@ -142,7 +139,6 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_TEXT; requestedProperties += PROP_LINE_HEIGHT; @@ -177,7 +173,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight()); @@ -196,16 +191,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness()); } -glm::vec3 TextEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -214,7 +199,9 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -238,6 +225,9 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -339,21 +329,6 @@ float TextEntityItem::getBackgroundAlpha() const { }); } -BillboardMode TextEntityItem::getBillboardMode() const { - BillboardMode result; - withReadLock([&] { - result = _billboardMode; - }); - return result; -} - -void TextEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - void TextEntityItem::setLeftMargin(float value) { withWriteLock([&] { _needsRenderUpdate |= _leftMargin != value; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 91496708f6..7827ab1b85 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,7 +48,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -82,9 +81,6 @@ public: float getBackgroundAlpha() const; void setBackgroundAlpha(float value); - BillboardMode getBillboardMode() const; - void setBillboardMode(BillboardMode value); - static const float DEFAULT_MARGIN; float getLeftMargin() const; void setLeftMargin(float value); @@ -117,8 +113,6 @@ public: PulsePropertyGroup getPulseProperties() const; private: - BillboardMode _billboardMode; - QString _text; float _lineHeight; glm::u8vec3 _textColor; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 61a1ed18c5..f88b40b2ee 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -54,7 +54,6 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des withReadLock([&] { _pulseProperties.getProperties(properties); }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); @@ -76,7 +75,6 @@ bool WebEntityItem::setSubClassProperties(const EntityItemProperties& properties somethingChanged |= pulsePropertiesChanged; _needsRenderUpdate |= pulsePropertiesChanged; }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(sourceUrl, setSourceUrl); SET_ENTITY_PROPERTY_FROM_PROPERTIES(dpi, setDPI); @@ -106,7 +104,6 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY(PROP_DPI, uint16_t, setDPI); @@ -124,7 +121,6 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_SOURCE_URL; requestedProperties += PROP_DPI; @@ -151,7 +147,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, getDPI()); @@ -162,16 +157,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, getUseBackground()); } -glm::vec3 WebEntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -180,7 +165,9 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -205,6 +192,9 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + withReadLock([&] { + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); + }); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); @@ -259,19 +249,6 @@ float WebEntityItem::getAlpha() const { }); } -BillboardMode WebEntityItem::getBillboardMode() const { - return resultWithReadLock([&] { - return _billboardMode; - }); -} - -void WebEntityItem::setBillboardMode(BillboardMode value) { - withWriteLock([&] { - _needsRenderUpdate |= _billboardMode != value; - _billboardMode = value; - }); -} - void WebEntityItem::setSourceUrl(const QString& value) { withWriteLock([&] { _needsRenderUpdate |= _sourceUrl != value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 4b39261bfb..0a3db2ea78 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,7 +45,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -62,9 +61,6 @@ public: float getAlpha() const; void setAlpha(float alpha); - void setBillboardMode(BillboardMode value); - BillboardMode getBillboardMode() const; - static const QString DEFAULT_SOURCE_URL; void setSourceUrl(const QString& value); QString getSourceUrl() const; @@ -96,7 +92,6 @@ protected: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; QString _sourceUrl; uint16_t _dpi; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fc74f4459c..94fe2ca71f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -283,6 +283,7 @@ enum class EntityVersion : PacketVersion { ZoneOcclusion, ModelBlendshapes, TransparentWeb, + AllBillboardMode, // Add new versions above here NUM_PACKET_TYPE, From bef0c79b677ab4287068465383a7f918873396e1 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 10 Jan 2021 16:03:04 -0800 Subject: [PATCH 02/11] billboard mode working on most entity types --- interface/src/Application.cpp | 15 ++++- .../src/RenderableGizmoEntityItem.cpp | 3 +- .../src/RenderableGridEntityItem.cpp | 2 + .../src/RenderableImageEntityItem.cpp | 3 +- .../src/RenderableLineEntityItem.cpp | 4 +- .../src/RenderableMaterialEntityItem.cpp | 3 +- .../RenderableParticleEffectEntityItem.cpp | 1 - .../src/RenderablePolyLineEntityItem.cpp | 3 +- .../src/RenderablePolyVoxEntityItem.cpp | 64 +++---------------- .../src/RenderablePolyVoxEntityItem.h | 10 +-- .../src/RenderableShapeEntityItem.cpp | 7 +- .../src/RenderableTextEntityItem.cpp | 6 +- .../src/RenderableWebEntityItem.cpp | 3 +- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 6 +- libraries/entities/src/EntityTreeElement.cpp | 30 ++++++--- libraries/entities/src/GizmoEntityItem.cpp | 9 ++- libraries/entities/src/GridEntityItem.cpp | 54 ++++++++++++++++ libraries/entities/src/GridEntityItem.h | 10 +++ libraries/entities/src/ImageEntityItem.cpp | 8 +-- libraries/entities/src/ImageEntityItem.h | 2 +- libraries/entities/src/PolyVoxEntityItem.cpp | 18 ++++-- libraries/entities/src/PolyVoxEntityItem.h | 4 +- libraries/entities/src/ShapeEntityItem.cpp | 30 +++++++-- libraries/entities/src/TextEntityItem.cpp | 8 +-- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 8 +-- libraries/entities/src/WebEntityItem.h | 2 +- 28 files changed, 188 insertions(+), 129 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc46d8591b..c1911151d8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,13 +2455,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { + EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera glm::vec3 dPosition = frustumPos - position; // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + if (rotate90x) { + result *= ROTATE_90X; + } + return result; } else if (billboardMode == BillboardMode::FULL) { // use the referencial from the avatar, y isn't always up glm::vec3 avatarUP = DependencyManager::get()->getMyAvatar()->getWorldOrientation() * Vectors::UP; @@ -2470,7 +2475,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // make sure s is not NaN for any component if (glm::length2(s) > 0.0f) { - return glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + if (rotate90x) { + result *= ROTATE_90X; + } + return result; } } return rotation; diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index caf5bde729..368aa59b5e 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -254,7 +254,8 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 87b916e41b..777ddda934 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -103,6 +103,8 @@ void GridEntityRenderer::doRender(RenderArgs* args) { } else { transform.setTranslation(renderTransform.getTranslation()); } + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); auto minCorner = glm::vec2(-0.5f, -0.5f); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 878fcad6e4..34f48e25f6 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -97,7 +97,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 1964f1bdda..f8a3230f86 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -47,8 +47,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) { const auto& modelTransform = getModelTransform(); Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); - transform.setRotation(modelTransform.getRotation()); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index f7631f3e35..ac28dd517c 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -272,7 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (!proceduralRender) { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 91f922c7c7..4fe6bc8f93 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -455,7 +455,6 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created); color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setUniformBuffer(0, _uniformBuffer); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 47b1186c59..e10e7a845c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,7 +325,8 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f0a6684654..f17f775493 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -238,53 +238,6 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel startUpdates(); } -glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { - glm::vec3 result; - withReadLock([&] { - glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units - if (isEdged(_voxelSurfaceStyle)) { - result = scale / -2.0f; - } - return scale / 2.0f; - }); - return result; -} - -glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { - glm::vec3 voxelVolumeSize; - withReadLock([&] { - voxelVolumeSize = _voxelVolumeSize; - }); - - glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units - bool success; // TODO -- Does this actually have to happen in world space? - glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes - glm::vec3 position = getWorldPosition(success); - glm::vec3 positionToCenter = center - position; - - positionToCenter -= dimensions * Vectors::HALF - getSurfacePositionAdjustment(); - glm::mat4 centerToCorner = glm::translate(glm::mat4(), positionToCenter); - glm::mat4 scaled = glm::scale(centerToCorner, scale); - return scaled; -} - -glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const { - glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix()); - return localToModelMatrix; -} - -glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const { - glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 translation = glm::translate(getWorldPosition()); - return translation * rotation * voxelToLocalMatrix(); -} - -glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const { - glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix()); - return worldToModelMatrix; -} - bool RenderablePolyVoxEntityItem::setVoxel(const ivec3& v, uint8_t toValue) { if (_locked) { return false; @@ -582,7 +535,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return true; } - glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::mat4 wtvMatrix = worldToVoxelMatrix(true); glm::vec3 normDirection = glm::normalize(direction); // the PolyVox ray intersection code requires a near and far point. @@ -623,7 +576,7 @@ bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::ve return true; } - glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::mat4 wtvMatrix = worldToVoxelMatrix(true); glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f); glm::vec4 velocityInVoxel = wtvMatrix * glm::vec4(velocity, 0.0f); glm::vec4 accelerationInVoxel = wtvMatrix * glm::vec4(acceleration, 0.0f); @@ -1803,7 +1756,7 @@ ShapeKey PolyVoxEntityRenderer::getShapeKey() { bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { if (resultWithReadLock([&] { - if (entity->voxelToWorldMatrix() != _lastVoxelToWorldMatrix) { + if (entity->voxelToLocalMatrix() != _lastVoxelToLocalMatrix) { return true; } @@ -1829,7 +1782,9 @@ void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& s } void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - _lastVoxelToWorldMatrix = entity->voxelToWorldMatrix(); + _lastVoxelToLocalMatrix = entity->voxelToLocalMatrix(); + _position = entity->getWorldPosition(); + _orientation = entity->getWorldOrientation(); _lastVoxelVolumeSize = entity->getVoxelVolumeSize(); _params->setSubData(0, vec4(_lastVoxelVolumeSize, 0.0)); graphics::MeshPointer newMesh; @@ -1862,17 +1817,18 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { return; } - PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); gpu::Batch& batch = *args->_batch; - Transform transform(_lastVoxelToWorldMatrix); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(_position, _orientation, _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + Transform transform(glm::translate(_position) * rotation * _lastVoxelToLocalMatrix); batch.setModelTransform(transform); + batch.setInputFormat(_vertexFormat); batch.setInputBuffer(gpu::Stream::POSITION, _mesh->getVertexBuffer()._buffer, 0, sizeof(PolyVox::PositionMaterialNormal)); - // TODO -- should we be setting this? // batch.setInputBuffer(gpu::Stream::NORMAL, mesh->getVertexBuffer()._buffer, // 12, diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 825b4429cd..d4bcc4d19f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -83,12 +83,6 @@ public: virtual void setVoxelVolumeSize(const glm::vec3& voxelVolumeSize) override; virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) override; - glm::vec3 getSurfacePositionAdjustment() const; - glm::mat4 voxelToWorldMatrix() const; - glm::mat4 worldToVoxelMatrix() const; - glm::mat4 voxelToLocalMatrix() const; - glm::mat4 localToVoxelMatrix() const; - virtual ShapeType getShapeType() const override; virtual bool isReadyToComputeShape() const override; virtual void computeShapeInfo(ShapeInfo& info) override; @@ -226,7 +220,9 @@ private: gpu::BufferPointer _params; std::array _xyzTextures; glm::vec3 _lastVoxelVolumeSize; - glm::mat4 _lastVoxelToWorldMatrix; + glm::mat4 _lastVoxelToLocalMatrix; + glm::vec3 _position; + glm::quat _orientation; PolyVoxEntityItem::PolyVoxSurfaceStyle _lastSurfaceStyle { PolyVoxEntityItem::SURFACE_MARCHING_CUBES }; std::array _xyzTextureUrls; }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 87dbbd068b..f1c73dbeed 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -55,6 +55,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void* key = (void*)this; AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] { withWriteLock([&] { + _shape = entity->getShape(); _position = entity->getWorldPosition(); _dimensions = entity->getUnscaledDimensions(); // get unscaled to avoid scaling twice _orientation = entity->getWorldOrientation(); @@ -69,7 +70,6 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - _shape = entity->getShape(); _pulseProperties = entity->getPulseProperties(); bool materialChanged = false; @@ -238,7 +238,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), + _shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron)); + batch.setModelTransform(transform); if (pipelineType == Pipeline::PROCEDURAL) { auto procedural = std::static_pointer_cast(materials.top().material); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index acbbb57bd4..2be84110d6 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -131,7 +131,8 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); @@ -312,7 +313,8 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, args->getViewFrustum().getPosition())); + modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 93d1b9974e..6c6215f69d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -302,7 +302,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { batch.setResourceTexture(0, _texture); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->getViewFrustum().getPosition())); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Turn off jitter for these entities diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 657d778090..f33838d146 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -51,7 +51,7 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; QString EntityItem::_marketplacePublicKey; -std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&) { return rotation; }; +std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; std::function EntityItem::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; EntityItem::EntityItem(const EntityItemID& entityItemID) : diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 69b9abe376..ad3429c0b6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -572,8 +572,8 @@ public: virtual void removeGrab(GrabPointer grab) override; virtual void disableGrab(GrabPointer grab) override; - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos); } + static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } @@ -788,7 +788,7 @@ protected: mutable bool _needsRenderUpdate { false }; private: - static std::function _getBillboardRotationOperator; + static std::function _getBillboardRotationOperator; static std::function _getPrimaryViewFrustumPositionOperator; }; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 9af0bbfdb6..6e446630ee 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -219,8 +219,10 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -368,8 +370,10 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -472,8 +476,10 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -526,8 +532,10 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -585,8 +593,10 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); - glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::vec3 position = entity->getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::quat orientation = entity->getWorldOrientation(); + glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 7ca1230fb1..60ba39b787 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -109,11 +109,9 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); glm::quat rotation = getWorldOrientation(); - rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; + rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), false); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -146,8 +144,9 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); glm::quat rotation = getWorldOrientation(); - rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; + rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), true); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index e635511bfc..499d21a59d 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -125,6 +125,60 @@ void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_MINOR_GRID_EVERY, getMinorGridEvery()); } +bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { + glm::vec3 dimensions = getScaledDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + + if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { + glm::vec3 forward = rotation * Vectors::FRONT; + if (glm::dot(forward, direction) > 0.0f) { + face = MAX_Z_FACE; + surfaceNormal = -forward; + } else { + face = MIN_Z_FACE; + surfaceNormal = forward; + } + return true; + } + return false; +} + +bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, + OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { + glm::vec3 dimensions = getScaledDimensions(); + glm::vec2 xyDimensions(dimensions.x, dimensions.y); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + + glm::quat inverseRot = glm::inverse(rotation); + glm::vec3 localOrigin = inverseRot * (origin - position); + glm::vec3 localVelocity = inverseRot * velocity; + glm::vec3 localAcceleration = inverseRot * acceleration; + + if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { + float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; + glm::vec3 forward = rotation * Vectors::FRONT; + if (localIntersectionVelocityZ > 0.0f) { + face = MIN_Z_FACE; + surfaceNormal = forward; + } else { + face = MAX_Z_FACE; + surfaceNormal = -forward; + } + return true; + } + return false; +} + void GridEntityItem::setColor(const glm::u8vec3& color) { withWriteLock([&] { _needsRenderUpdate |= _color != color; diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h index 7dc7a475b2..fc31c93a5a 100644 --- a/libraries/entities/src/GridEntityItem.h +++ b/libraries/entities/src/GridEntityItem.h @@ -43,6 +43,16 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + OctreeElementPointer& element, float& distance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; + virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, + const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; + static const uint32_t DEFAULT_MAJOR_GRID_EVERY; static const float DEFAULT_MINOR_GRID_EVERY; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index fb59a85647..6cc47cc8f8 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -135,9 +135,7 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -161,9 +159,7 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 0a90f93f9d..a5ed139e6b 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,7 +43,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index dd55ca898b..9c8951514b 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -377,15 +377,21 @@ glm::mat4 PolyVoxEntityItem::localToVoxelMatrix() const { return localToModelMatrix; } -glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix() const { - glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 translation = glm::translate(getWorldPosition()); +glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const { + glm::quat orientation = getWorldOrientation(); + glm::vec3 position = getWorldPosition(); + glm::mat4 translation = glm::translate(position); + glm::mat4 rotation; + if (includeBillboard) { + rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + } else { + rotation = glm::mat4_cast(orientation); + } return translation * rotation * voxelToLocalMatrix(); } -glm::mat4 PolyVoxEntityItem::worldToVoxelMatrix() const { - glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix()); - return worldToModelMatrix; +glm::mat4 PolyVoxEntityItem::worldToVoxelMatrix(bool includeBillboard) const { + return glm::inverse(voxelToWorldMatrix(includeBillboard)); } glm::vec3 PolyVoxEntityItem::voxelCoordsToWorldCoords(const glm::vec3& voxelCoords) const { diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index f994fcd37c..c416353ecf 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -167,8 +167,8 @@ class PolyVoxEntityItem : public EntityItem { bool isEdged() const; - glm::mat4 voxelToWorldMatrix() const; - glm::mat4 worldToVoxelMatrix() const; + glm::mat4 voxelToWorldMatrix(bool includeBillboard = false) const; + glm::mat4 worldToVoxelMatrix(bool includeBillboard = false) const; glm::mat4 voxelToLocalMatrix() const; glm::mat4 localToVoxelMatrix() const; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 3dbb02775a..932dc6b034 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -257,7 +257,8 @@ float ShapeEntityItem::getAlpha() const { void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; - if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { + const auto shape = getShape(); + if ((shape == entity::Shape::Circle || shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y glm::vec3 newDimensions = value; newDimensions.y = MAX_FLAT_DIMENSION; @@ -268,15 +269,24 @@ void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { } bool ShapeEntityItem::supportsDetailedIntersection() const { - return _shape == entity::Sphere; + return getShape() == entity::Sphere || getBillboardMode() != BillboardMode::NONE; } bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + if (getShape() != entity::Sphere) { + return true; + } + + glm::vec3 dimensions = getScaledDimensions(); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + // determine the ray in the frame of the entity transformed from a unit sphere - glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); + glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); @@ -302,8 +312,17 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + if (getShape() != entity::Sphere) { + return true; + } + + glm::vec3 dimensions = getScaledDimensions(); + glm::quat rotation = getWorldOrientation(); + glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + // determine the parabola in the frame of the entity transformed from a unit sphere - glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix(); + glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); @@ -343,8 +362,9 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { // is set. const glm::vec3 entityDimensions = getScaledDimensions(); + const auto shape = getShape(); - switch (_shape){ + switch (shape){ case entity::Shape::Quad: // Quads collide like flat Cubes case entity::Shape::Cube: { diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 906e28288b..bfafae69cf 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -199,9 +199,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -225,9 +223,7 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 7827ab1b85..212f11e768 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,7 +48,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index f88b40b2ee..661c0865ca 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -165,9 +165,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -192,9 +190,7 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - withReadLock([&] { - rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode, EntityItem::getPrimaryViewFrustumPosition()); - }); + rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 0a3db2ea78..e0a66f25b2 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,7 +45,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return true; } + virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, From 6d1667df5a9b48719a96172069b7fd37704f5793 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 10 Jan 2021 16:48:44 -0800 Subject: [PATCH 03/11] better picking against billboarded shapes other than spheres --- libraries/entities/src/ShapeEntityItem.cpp | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 932dc6b034..691990eae1 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -276,10 +276,6 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { - if (getShape() != entity::Sphere) { - return true; - } - glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); @@ -291,18 +287,22 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - // determine where on the unit sphere the hit point occured - glm::vec3 hitAt = origin + (direction * distance); - surfaceNormal = glm::normalize(hitAt - center); - } else { - return false; + if (getShape() == entity::Sphere) { + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + // determine where on the unit sphere the hit point occured + glm::vec3 hitAt = origin + (direction * distance); + surfaceNormal = glm::normalize(hitAt - center); + } else { + return false; + } + return true; } + } else if (findRayAABoxIntersection(entityFrameOrigin, entityFrameDirection, 1.0f / entityFrameDirection, glm::vec3(-0.5f), glm::vec3(1.0f), distance, face, surfaceNormal)) { return true; } return false; @@ -312,10 +312,6 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { - if (getShape() != entity::Sphere) { - return true; - } - glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); @@ -328,16 +324,20 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); glm::vec3 entityFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f)); - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); - } else { - return false; + if (getShape() == entity::Sphere) { + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); + } else { + return false; + } + return true; } + } else if (findParabolaAABoxIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(-0.5f), glm::vec3(1.0f), parabolicDistance, face, surfaceNormal)) { return true; } return false; From 2a27fc4de2344b877920cbe8dbe3427cfe794073 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 13 Jan 2021 22:31:21 -0800 Subject: [PATCH 04/11] billboarding for model entities --- interface/src/Application.cpp | 4 +- interface/src/Menu.cpp | 2 +- .../src/RenderableGizmoEntityItem.cpp | 4 +- .../src/RenderableGridEntityItem.cpp | 4 +- .../src/RenderableImageEntityItem.cpp | 4 +- .../src/RenderableLineEntityItem.cpp | 4 +- .../src/RenderableMaterialEntityItem.cpp | 4 +- .../src/RenderableModelEntityItem.cpp | 2 + .../src/RenderablePolyLineEntityItem.cpp | 4 +- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- .../src/RenderableShapeEntityItem.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 8 +- .../src/RenderableWebEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 3 - libraries/entities/src/EntityItem.h | 9 - libraries/entities/src/EntityTreeElement.cpp | 10 +- libraries/entities/src/GizmoEntityItem.cpp | 4 +- libraries/entities/src/GridEntityItem.cpp | 4 +- libraries/entities/src/ImageEntityItem.cpp | 4 +- libraries/entities/src/PolyVoxEntityItem.cpp | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 4 +- libraries/entities/src/TextEntityItem.cpp | 4 +- libraries/entities/src/WebEntityItem.cpp | 4 +- .../src/CauterizedMeshPartPayload.cpp | 26 +- .../src/CauterizedMeshPartPayload.h | 6 +- .../render-utils/src/CauterizedModel.cpp | 39 +- .../render-utils/src/MeshPartPayload.cpp | 479 ++++++------------ libraries/render-utils/src/MeshPartPayload.h | 157 ++---- libraries/render-utils/src/Model.cpp | 55 +- libraries/render-utils/src/Model.h | 5 + libraries/shared/src/BillboardMode.cpp | 4 +- libraries/shared/src/BillboardMode.h | 15 +- 32 files changed, 328 insertions(+), 558 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1911151d8..e38d156336 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,7 +2455,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera @@ -2484,7 +2484,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } return rotation; }); - EntityItem::setPrimaryViewFrustumPositionOperator([this]() { + BillboardModeHelpers::setPrimaryViewFrustumPositionOperator([this]() { ViewFrustum viewFrustum; copyViewFrustum(viewFrustum); return viewFrustum.getPosition(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 19cc7eacaa..471645e342 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -509,7 +509,7 @@ Menu::Menu() { action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); connect(action, &QAction::triggered, [action] { - MeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); + ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); }); { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 368aa59b5e..3abd120bf9 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -254,8 +254,8 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); batch.setModelTransform(transform); // Background circle diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 777ddda934..a5ae4acbf5 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -103,8 +103,8 @@ void GridEntityRenderer::doRender(RenderArgs* args) { } else { transform.setTranslation(renderTransform.getTranslation()); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); auto minCorner = glm::vec2(-0.5f, -0.5f); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 34f48e25f6..e03655f09c 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -97,8 +97,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index f8a3230f86..a36cdde212 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -47,8 +47,8 @@ void LineEntityRenderer::doRender(RenderArgs* args) { const auto& modelTransform = getModelTransform(); Transform transform = Transform(); transform.setTranslation(modelTransform.getTranslation()); - transform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (_linePoints.size() > 1) { DependencyManager::get()->bindSimpleProgram(batch, false, false, false, false, true, diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index ac28dd517c..74b479affe 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -272,8 +272,8 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { proceduralRender = true; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); if (!proceduralRender) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c694f496d6..c6765f2321 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1254,6 +1254,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint _model->setTagMask(getTagMask(), scene); _model->setHifiRenderLayer(getHifiRenderLayer(), scene); _model->setPrimitiveMode(_primitiveMode, scene); + _model->setBillboardMode(_billboardMode, scene); _model->setCullWithParent(_cullWithParent, scene); _model->setRenderWithZones(_renderWithZones, scene); }); @@ -1332,6 +1333,7 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint model->setTagMask(getTagMask(), scene); model->setHifiRenderLayer(getHifiRenderLayer(), scene); model->setPrimitiveMode(_primitiveMode, scene); + model->setBillboardMode(_billboardMode, scene); model->setCullWithParent(_cullWithParent, scene); model->setRenderWithZones(_renderWithZones, scene); }); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index e10e7a845c..65e9f57b02 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -325,8 +325,8 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { buildPipelines(); } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index f17f775493..5b6c0c8b70 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1820,8 +1820,8 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); gpu::Batch& batch = *args->_batch; - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(_position, _orientation, _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(_position, _orientation, _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); Transform transform(glm::translate(_position) * rotation * _lastVoxelToLocalMatrix); batch.setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index f1c73dbeed..9cc18a8df5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -238,8 +238,8 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), _shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron)); batch.setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 2be84110d6..1724cf69d5 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -131,8 +131,8 @@ void TextEntityRenderer::doRender(RenderArgs* args) { return; } - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); @@ -313,8 +313,8 @@ void entities::TextPayload::render(RenderArgs* args) { return; } - modelTransform.setRotation(EntityItem::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + modelTransform.setRotation(BillboardModeHelpers::getBillboardRotation(modelTransform.getTranslation(), modelTransform.getRotation(), textRenderable->_billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); float scale = textRenderable->_lineHeight / textRenderer->getFontSize(); modelTransform.postTranslate(glm::vec3(-0.5, 0.5, 1.0f + EPSILON / dimensions.z)); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 6c6215f69d..e367b4cc7c 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -302,8 +302,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { batch.setResourceTexture(0, _texture); - transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, - args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? EntityItem::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); batch.setModelTransform(transform); // Turn off jitter for these entities diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f33838d146..68e824f8cc 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -51,9 +51,6 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; QString EntityItem::_marketplacePublicKey; -std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; -std::function EntityItem::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; - EntityItem::EntityItem(const EntityItemID& entityItemID) : SpatiallyNestable(NestableType::Entity, entityItemID) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ad3429c0b6..288f1682c7 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -572,11 +572,6 @@ public: virtual void removeGrab(GrabPointer grab) override; virtual void disableGrab(GrabPointer grab) override; - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } - static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } - static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } - bool stillHasMyGrab() const; bool needsRenderUpdate() const { return _needsRenderUpdate; } @@ -786,10 +781,6 @@ protected: bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; - -private: - static std::function _getBillboardRotationOperator; - static std::function _getPrimaryViewFrustumPositionOperator; }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 6e446630ee..afbb139d5f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -222,7 +222,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -373,7 +373,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -479,7 +479,7 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -535,7 +535,7 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -596,7 +596,7 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, entity->getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 60ba39b787..6586d57fde 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -111,7 +111,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), false); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), false); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -146,7 +146,7 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition(), true); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), true); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index 499d21a59d..c675a11d27 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -133,7 +133,7 @@ bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -157,7 +157,7 @@ bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 6cc47cc8f8..80711e4abc 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -135,7 +135,7 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -159,7 +159,7 @@ bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 9c8951514b..5ed9f69b5a 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -383,7 +383,7 @@ glm::mat4 PolyVoxEntityItem::voxelToWorldMatrix(bool includeBillboard) const { glm::mat4 translation = glm::translate(position); glm::mat4 rotation; if (includeBillboard) { - rotation = glm::mat4_cast(EntityItem::getBillboardRotation(position, orientation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition())); + rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); } else { rotation = glm::mat4_cast(orientation); } diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 691990eae1..943912b934 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -279,7 +279,7 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); // determine the ray in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); @@ -315,7 +315,7 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); // determine the parabola in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index bfafae69cf..7fab5cee53 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -199,7 +199,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -223,7 +223,7 @@ bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 661c0865ca..d9d2425e11 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -165,7 +165,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -190,7 +190,7 @@ bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, co glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = EntityItem::getBillboardRotation(position, rotation, getBillboardMode(), EntityItem::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 9c7a2ee60b..dc1ffb7b67 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -19,8 +19,8 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, - const Transform& transform, const Transform& offsetTransform, const uint64_t& created) - : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform, created) {} + const Transform& transform, const uint64_t& created) + : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, created) {} void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices) { @@ -52,11 +52,26 @@ void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, @@ -23,9 +23,9 @@ public: void updateClusterBuffer(const std::vector& clusterDualQuaternions, const std::vector& cauterizedClusterQuaternions); - void updateTransformForCauterizedMesh(const Transform& renderTransform); + void updateTransformForCauterizedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning); - void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; + void bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const override; void setEnableCauterization(bool enableCauterization) { _enableCauterization = enableCauterization; } diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 94b7661b2f..a5d27dc7d2 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -69,10 +69,6 @@ void CauterizedModel::createRenderItemSet() { transform.setTranslation(_translation); transform.setRotation(_rotation); - Transform offset; - offset.setScale(_scale); - offset.postTranslate(_offset); - // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; uint32_t numMeshes = (uint32_t)meshes.size(); @@ -85,7 +81,7 @@ void CauterizedModel::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); + auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, _created); _modelMeshRenderItems << std::static_pointer_cast(ptr); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); @@ -235,37 +231,8 @@ void CauterizedModel::updateRenderItems() { data.computeAdjustedLocalBound(meshState.clusterMatrices); } - Transform renderTransform = modelTransform; - if (useDualQuaternionSkinning) { - if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { - const auto& dq = meshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(transform); - } - } else { - if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); - } - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - - renderTransform = modelTransform; - if (useDualQuaternionSkinning) { - if (cauterizedMeshState.clusterDualQuaternions.size() == 1 || cauterizedMeshState.clusterDualQuaternions.size() == 2) { - const auto& dq = cauterizedMeshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); - } - } else { - if (cauterizedMeshState.clusterMatrices.size() == 1 || cauterizedMeshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(cauterizedMeshState.clusterMatrices[0])); - } - } - data.updateTransformForCauterizedMesh(renderTransform); + data.updateTransformForSkinnedMesh(modelTransform, meshState, useDualQuaternionSkinning); + data.updateTransformForCauterizedMesh(modelTransform, cauterizedMeshState, useDualQuaternionSkinning); data.setEnableCauterization(enableCauterization); data.updateKey(renderItemKeyGlobalFlags); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 84aed55d72..0e0af6fc71 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -11,8 +11,7 @@ #include "MeshPartPayload.h" -#include - +#include #include #include #include @@ -23,292 +22,33 @@ #include "RenderPipelines.h" -// static const QString ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING { "HIFI_ENABLE_MATERIAL_PROCEDURAL_SHADERS" }; -// static bool ENABLE_MATERIAL_PROCEDURAL_SHADERS = QProcessEnvironment::systemEnvironment().contains(ENABLE_MATERIAL_PROCEDURAL_SHADERS_STRING); - -bool MeshPartPayload::enableMaterialProceduralShaders = false; - using namespace render; -namespace render { -template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - return ItemKey::Builder::opaqueShape(); // for lack of a better idea -} - -template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return Item::Bound(); -} - -template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getShapeKey(); - } - return ShapeKey::Builder::invalid(); -} - -template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); -} - -template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { - if (payload) { - return payload->passesZoneOcclusionTest(containingZones); - } - return false; -} -} - -MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : - _created(created) -{ - updateMeshPart(mesh, partIndex); - addMaterial(graphics::MaterialLayer(material, 0)); -} - -void MeshPartPayload::updateMeshPart(const std::shared_ptr& drawMesh, int partIndex) { - _drawMesh = drawMesh; - if (_drawMesh) { - auto vertexFormat = _drawMesh->getVertexFormat(); - _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); - _drawPart = _drawMesh->getPartBuffer().get(partIndex); - _localBound = _drawMesh->evalPartBound(partIndex); - } -} - -void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) { - _transform = transform; - Transform::mult(_drawTransform, _transform, offsetTransform); - _worldBound = _localBound; - _worldBound.transform(_drawTransform); -} - -void MeshPartPayload::addMaterial(graphics::MaterialLayer material) { - _drawMaterials.push(material); -} - -void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) { - _drawMaterials.remove(material); -} - -void MeshPartPayload::updateKey(const render::ItemKey& key) { - ItemKey::Builder builder(key); - builder.withTypeShape(); - - if (_drawMaterials.shouldUpdate()) { - RenderPipelines::updateMultiMaterial(_drawMaterials); - } - - auto matKey = _drawMaterials.getMaterialKey(); - if (matKey.isTranslucent()) { - builder.withTransparent(); - } - - if (_cullWithParent) { - builder.withSubMetaCulled(); - } - - _itemKey = builder.build(); -} - -ItemKey MeshPartPayload::getKey() const { - return _itemKey; -} - -Item::Bound MeshPartPayload::getBound() const { - graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; - if (material && material->isProcedural() && material->isReady()) { - auto procedural = std::static_pointer_cast(_drawMaterials.top().material); - if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); - } - } - return _worldBound; -} - -ShapeKey MeshPartPayload::getShapeKey() const { - ShapeKey::Builder builder; - graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; - graphics::MaterialKey drawMaterialKey = _drawMaterials.getMaterialKey(); - - if (drawMaterialKey.isTranslucent()) { - builder.withTranslucent(); - } - - if (material && material->isProcedural() && material->isReady()) { - builder.withOwnPipeline(); - } else { - builder.withMaterial(); - - if (drawMaterialKey.isNormalMap()) { - builder.withTangents(); - } - if (drawMaterialKey.isLightMap()) { - builder.withLightMap(); - } - if (drawMaterialKey.isUnlit()) { - builder.withUnlit(); - } - if (material) { - builder.withCullFaceMode(material->getCullFaceMode()); - } - } - - return builder.build(); -} - -void MeshPartPayload::drawCall(gpu::Batch& batch) const { - batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); -} - -void MeshPartPayload::bindMesh(gpu::Batch& batch) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - - batch.setInputFormat((_drawMesh->getVertexFormat())); - - batch.setInputStream(0, _drawMesh->getVertexStream()); -} - -void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { - batch.setModelTransform(_drawTransform); -} - -bool MeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { - if (!_renderWithZones.isEmpty()) { - if (!containingZones.empty()) { - for (auto renderWithZone : _renderWithZones) { - if (containingZones.find(renderWithZone) != containingZones.end()) { - return true; - } - } - } - return false; - } - return true; -} - -void MeshPartPayload::render(RenderArgs* args) { - PerformanceTimer perfTimer("MeshPartPayload::render"); - - if (!args) { - return; - } - - gpu::Batch& batch = *(args->_batch); - - // Bind the model transform and the skinCLusterMatrices if needed - bindTransform(batch, args->_renderMode); - - //Bind the index buffer and vertex buffer and Blend shapes if needed - bindMesh(batch); - - if (!_drawMaterials.empty() && _drawMaterials.top().material && _drawMaterials.top().material->isProcedural() && - _drawMaterials.top().material->isReady()) { - if (!enableMaterialProceduralShaders) { - return; - } - auto procedural = std::static_pointer_cast(_drawMaterials.top().material); - auto& schema = _drawMaterials.getSchemaBuffer().get(); - glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); - outColor = procedural->getColor(outColor); - procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, - ProceduralProgramKey(outColor.a < 1.0f)); - batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); - } else { - // apply material properties - if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; - } - } - - // Draw! - { - PerformanceTimer perfTimer("batch.drawIndexed()"); - drawCall(batch); - } - - const int INDICES_PER_TRIANGLE = 3; - args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; -} - -namespace render { -template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - return ItemKey::Builder::opaqueShape(); // for lack of a better idea -} - -template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return Item::Bound(); -} - -template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getShapeKey(); - } - return ShapeKey::Builder::invalid(); -} - -template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); -} - -template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { - if (payload) { - return payload->passesZoneOcclusionTest(containingZones); - } - return false; -} -} +bool ModelMeshPartPayload::enableMaterialProceduralShaders = false; ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, - const Transform& transform, const Transform& offsetTransform, const uint64_t& created) : + const Transform& transform, const uint64_t& created) : _meshIndex(meshIndex), - _shapeID(shapeIndex) { + _created(created) { assert(model && model->isLoaded()); - bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); - auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); _meshNumVertices = (int)modelMesh->getNumVertices(); const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); + bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); if (useDualQuaternionSkinning) { computeAdjustedLocalBound(state.clusterDualQuaternions); } else { computeAdjustedLocalBound(state.clusterMatrices); } - updateTransform(transform, offsetTransform); - Transform renderTransform = transform; - if (useDualQuaternionSkinning) { - if (state.clusterDualQuaternions.size() == 1) { - const auto& dq = state.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = transform.worldTransform(Transform(transform)); - } - } else { - if (state.clusterMatrices.size() == 1) { - renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); - } - } - updateTransformForSkinnedMesh(renderTransform, transform); + updateTransformForSkinnedMesh(transform, state, useDualQuaternionSkinning); - initCache(model); + initCache(model, shapeIndex); #if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) // On mac AMD, we specifically need to have a _meshBlendshapeBuffer bound when using a deformed mesh pipeline @@ -322,14 +62,11 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in _meshBlendshapeBuffer = std::make_shared(sizeof(BlendshapeOffset), reinterpret_cast(&data), sizeof(BlendshapeOffset)); } #endif - - _created = created; } -void ModelMeshPartPayload::initCache(const ModelPointer& model) { +void ModelMeshPartPayload::initCache(const ModelPointer& model, int shapeID) { if (_drawMesh) { auto vertexFormat = _drawMesh->getVertexFormat(); - _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); _isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX); const HFMModel& hfmModel = model->getHFMModel(); @@ -339,18 +76,22 @@ void ModelMeshPartPayload::initCache(const ModelPointer& model) { _hasTangents = !mesh.tangents.isEmpty(); } - auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID); + auto networkMaterial = model->getGeometry()->getShapeMaterial(shapeID); if (networkMaterial) { addMaterial(graphics::MaterialLayer(networkMaterial, 0)); } } -void ModelMeshPartPayload::notifyLocationChanged() { - +void ModelMeshPartPayload::updateMeshPart(const std::shared_ptr& drawMesh, int partIndex) { + _drawMesh = drawMesh; + if (_drawMesh) { + auto vertexFormat = _drawMesh->getVertexFormat(); + _drawPart = _drawMesh->getPartBuffer().get(partIndex); + _localBound = _drawMesh->evalPartBound(partIndex); + } } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { - // reset cluster buffer if we change the cluster buffer type if (_clusterBufferType != ClusterBufferType::Matrices) { _clusterBuffer.reset(); @@ -370,7 +111,6 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clu } void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterDualQuaternions) { - // reset cluster buffer if we change the cluster buffer type if (_clusterBufferType != ClusterBufferType::DualQuaternions) { _clusterBuffer.reset(); @@ -389,13 +129,78 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { + _adjustedLocalBound = _localBound; + if (clusterMatrices.size() > 0) { + _adjustedLocalBound.transform(clusterMatrices.back()); + + for (int i = 0; i < (int)clusterMatrices.size() - 1; ++i) { + AABox clusterBound = _localBound; + clusterBound.transform(clusterMatrices[i]); + _adjustedLocalBound += clusterBound; + } + } +} + +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions) { + _adjustedLocalBound = _localBound; + if (clusterDualQuaternions.size() > 0) { + Transform rootTransform(clusterDualQuaternions.back().getRotation(), + clusterDualQuaternions.back().getScale(), + clusterDualQuaternions.back().getTranslation()); + _adjustedLocalBound.transform(rootTransform); + + for (int i = 0; i < (int)clusterDualQuaternions.size() - 1; ++i) { + AABox clusterBound = _localBound; + Transform transform(clusterDualQuaternions[i].getRotation(), + clusterDualQuaternions[i].getScale(), + clusterDualQuaternions[i].getTranslation()); + clusterBound.transform(transform); + _adjustedLocalBound += clusterBound; + } + } +} + +void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning) { + _localTransform = Transform(); + if (useDualQuaternionSkinning) { + if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { + const auto& dq = meshState.clusterDualQuaternions[0]; + _localTransform = Transform(dq.getRotation(), + dq.getScale(), + dq.getTranslation()); + } + } else { + if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { + _localTransform = Transform(meshState.clusterMatrices[0]); + } + } + + _parentTransform = modelTransform; + _worldBound = _adjustedLocalBound; + _worldBound.transform(_parentTransform); +} + +void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { + batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); + batch.setInputFormat((_drawMesh->getVertexFormat())); + if (_meshBlendshapeBuffer) { + batch.setResourceBuffer(0, _meshBlendshapeBuffer); + } + batch.setInputStream(0, _drawMesh->getVertexStream()); +} + +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const { + if (_clusterBuffer) { + batch.setUniformBuffer(graphics::slot::buffer::Skinning, _clusterBuffer); + } + batch.setModelTransform(transform); +} + +void ModelMeshPartPayload::drawCall(gpu::Batch& batch) const { + batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); } -// Note that this method is called for models but not for shapes void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { ItemKey::Builder builder(key); builder.withTypeShape(); @@ -480,26 +285,25 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr _shapeKey = builder.build(); } +ItemKey ModelMeshPartPayload::getKey() const { + return _itemKey; +} + +Item::Bound ModelMeshPartPayload::getBound() const { + graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; + if (material && material->isProcedural() && material->isReady()) { + auto procedural = std::static_pointer_cast(_drawMaterials.top().material); + if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { + return procedural->getBound(); + } + } + return _worldBound; +} + ShapeKey ModelMeshPartPayload::getShapeKey() const { return _shapeKey; } -void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { - batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); - batch.setInputFormat((_drawMesh->getVertexFormat())); - if (_meshBlendshapeBuffer) { - batch.setResourceBuffer(0, _meshBlendshapeBuffer); - } - batch.setInputStream(0, _drawMesh->getVertexStream()); -} - -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { - if (_clusterBuffer) { - batch.setUniformBuffer(graphics::slot::buffer::Skinning, _clusterBuffer); - } - batch.setModelTransform(_transform); -} - void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); @@ -509,7 +313,12 @@ void ModelMeshPartPayload::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); - bindTransform(batch, args->_renderMode); + Transform transform = _parentTransform; + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + + Transform modelTransform = transform.worldTransform(_localTransform); + bindTransform(batch, modelTransform, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); @@ -528,7 +337,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { auto& schema = _drawMaterials.getSchemaBuffer().get(); glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); outColor = procedural->getColor(outColor); - procedural->prepare(batch, _drawTransform.getTranslation(), _drawTransform.getScale(), _drawTransform.getRotation(), _created, + procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(outColor.a < 1.0f, _shapeKey.isDeformed(), _shapeKey.isDualQuatSkinned())); batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); } else { @@ -548,36 +357,18 @@ void ModelMeshPartPayload::render(RenderArgs* args) { args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterMatrices) { - _adjustedLocalBound = _localBound; - if (clusterMatrices.size() > 0) { - _adjustedLocalBound.transform(clusterMatrices.back()); - - for (int i = 0; i < (int)clusterMatrices.size() - 1; ++i) { - AABox clusterBound = _localBound; - clusterBound.transform(clusterMatrices[i]); - _adjustedLocalBound += clusterBound; - } - } -} - -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions) { - _adjustedLocalBound = _localBound; - if (clusterDualQuaternions.size() > 0) { - Transform rootTransform(clusterDualQuaternions.back().getRotation(), - clusterDualQuaternions.back().getScale(), - clusterDualQuaternions.back().getTranslation()); - _adjustedLocalBound.transform(rootTransform); - - for (int i = 0; i < (int)clusterDualQuaternions.size() - 1; ++i) { - AABox clusterBound = _localBound; - Transform transform(clusterDualQuaternions[i].getRotation(), - clusterDualQuaternions[i].getScale(), - clusterDualQuaternions[i].getTranslation()); - clusterBound.transform(transform); - _adjustedLocalBound += clusterBound; +bool ModelMeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + if (!_renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : _renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } } + return false; } + return true; } void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes) { @@ -596,3 +387,37 @@ void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_map const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); + } + return ItemKey::Builder::opaqueShape(); // for lack of a better idea +} + +template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); +} + +template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getShapeKey(); + } + return ShapeKey::Builder::invalid(); +} + +template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); +} + +template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} +} diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8ed799bd74..63ccb85470 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -12,147 +12,94 @@ #ifndef hifi_MeshPartPayload_h #define hifi_MeshPartPayload_h -#include - -#include - -#include - -#include - #include "Model.h" -class Model; +#include +#include +#include -class MeshPartPayload { +class ModelMeshPartPayload { public: - MeshPartPayload() = default; - MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created); - virtual ~MeshPartPayload() = default; - - typedef render::Payload Payload; + typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - virtual void updateKey(const render::ItemKey& key); + ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const uint64_t& created); virtual void updateMeshPart(const std::shared_ptr& drawMesh, int partIndex); - virtual void notifyLocationChanged() {} - void updateTransform(const Transform& transform, const Transform& offsetTransform); + void updateClusterBuffer(const std::vector& clusterMatrices); // matrix palette skinning + void updateClusterBuffer(const std::vector& clusterDualQuaternions); // dual quaternion skinning - // Render Item interface - virtual render::ItemKey getKey() const; - virtual render::Item::Bound getBound() const; - virtual render::ShapeKey getShapeKey() const; - virtual void render(RenderArgs* args); + void computeAdjustedLocalBound(const std::vector& clusterMatrices); // matrix palette skinning + void computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); // dual quaternion skinning + + void updateTransformForSkinnedMesh(const Transform& modelTransform, const Model::MeshState& meshState, bool useDualQuaternionSkinning); // ModelMeshPartPayload functions to perform render + void bindMesh(gpu::Batch& batch); + virtual void bindTransform(gpu::Batch& batch, const Transform& transform, RenderArgs::RenderMode renderMode) const; void drawCall(gpu::Batch& batch) const; - virtual void bindMesh(gpu::Batch& batch); - virtual void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const; - // Payload resource cached values - Transform _drawTransform; - Transform _transform; - int _partIndex = 0; - bool _hasColorAttrib { false }; + void updateKey(const render::ItemKey& key); + void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); - graphics::Box _localBound; - graphics::Box _adjustedLocalBound; - mutable graphics::Box _worldBound; - std::shared_ptr _drawMesh; - - graphics::MultiMaterial _drawMaterials; - graphics::Mesh::Part _drawPart; + // Render Item interface + render::ItemKey getKey() const; + render::Item::Bound getBound() const; + render::ShapeKey getShapeKey() const; + void render(RenderArgs* args); size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } size_t getMaterialTextureSize() { return _drawMaterials.getTextureSize(); } int getMaterialTextureCount() { return _drawMaterials.getTextureCount(); } bool hasTextureInfo() const { return _drawMaterials.hasTextureInfo(); } - void addMaterial(graphics::MaterialLayer material); - void removeMaterial(graphics::MaterialPointer material); - + void setCauterized(bool cauterized) { _cauterized = cauterized; } void setCullWithParent(bool value) { _cullWithParent = value; } - void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } + void setBillboardMode(BillboardMode billboardMode) { _billboardMode = billboardMode; } bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; - static bool enableMaterialProceduralShaders; - -protected: - render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; - bool _cullWithParent { false }; - QVector _renderWithZones; - uint64_t _created; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); - template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); - template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); - template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); -} - -class ModelMeshPartPayload : public MeshPartPayload { -public: - ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform, const uint64_t& created); - - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - void notifyLocationChanged() override; - - void updateKey(const render::ItemKey& key) override; - - // matrix palette skinning - void updateClusterBuffer(const std::vector& clusterMatrices); - - // dual quaternion skinning - void updateClusterBuffer(const std::vector& clusterDualQuaternions); - void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); - - // Render Item interface - render::ShapeKey getShapeKey() const override; - void render(RenderArgs* args) override; - - void setShapeKey(bool invalidateShapeKey, PrimitiveMode primitiveMode, bool useDualQuaternionSkinning); - void setCauterized(bool cauterized) { _cauterized = cauterized; } - - // ModelMeshPartPayload functions to perform render - void bindMesh(gpu::Batch& batch) override; - void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; - - // matrix palette skinning - void computeAdjustedLocalBound(const std::vector& clusterMatrices); - - // dual quaternion skinning - void computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); - - gpu::BufferPointer _clusterBuffer; - - enum class ClusterBufferType { Matrices, DualQuaternions }; - ClusterBufferType _clusterBufferType { ClusterBufferType::Matrices }; - - int _meshIndex; - int _shapeID; - - bool _isSkinned{ false }; - bool _isBlendShaped { false }; - bool _hasTangents { false }; + void addMaterial(graphics::MaterialLayer material) { _drawMaterials.push(material); } + void removeMaterial(graphics::MaterialPointer material) { _drawMaterials.remove(material); } void setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes); + static bool enableMaterialProceduralShaders; + private: - void initCache(const ModelPointer& model); + void initCache(const ModelPointer& model, int shapeID); + + int _meshIndex; + std::shared_ptr _drawMesh; + graphics::Mesh::Part _drawPart; + graphics::MultiMaterial _drawMaterials; + + gpu::BufferPointer _clusterBuffer; + enum class ClusterBufferType { Matrices, DualQuaternions }; + ClusterBufferType _clusterBufferType { ClusterBufferType::Matrices }; gpu::BufferPointer _meshBlendshapeBuffer; int _meshNumVertices; + + render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; + + bool _isSkinned { false }; + bool _isBlendShaped { false }; + bool _hasTangents { false }; bool _prevUseDualQuaternionSkinning { false }; bool _cauterized { false }; + bool _cullWithParent { false }; + QVector _renderWithZones; + BillboardMode _billboardMode; + uint64_t _created; + Transform _localTransform; + Transform _parentTransform; + graphics::Box _localBound; + graphics::Box _adjustedLocalBound; + mutable graphics::Box _worldBound; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9ad343639d..9bf1596a04 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -226,6 +226,7 @@ void Model::updateRenderItems() { modelTransform.setScale(glm::vec3(1.0f)); PrimitiveMode primitiveMode = self->getPrimitiveMode(); + BillboardMode billboardMode = self->getBillboardMode(); auto renderWithZones = self->getRenderWithZones(); auto renderItemKeyGlobalFlags = self->getRenderItemKeyGlobalFlags(); bool cauterized = self->isCauterized(); @@ -242,7 +243,7 @@ void Model::updateRenderItems() { bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning(); transaction.updateItem(itemID, [modelTransform, meshState, useDualQuaternionSkinning, - invalidatePayloadShapeKey, primitiveMode, renderItemKeyGlobalFlags, + invalidatePayloadShapeKey, primitiveMode, billboardMode, renderItemKeyGlobalFlags, cauterized, renderWithZones](ModelMeshPartPayload& data) { if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); @@ -252,25 +253,11 @@ void Model::updateRenderItems() { data.computeAdjustedLocalBound(meshState.clusterMatrices); } - Transform renderTransform = modelTransform; - - if (useDualQuaternionSkinning) { - if (meshState.clusterDualQuaternions.size() == 1 || meshState.clusterDualQuaternions.size() == 2) { - const auto& dq = meshState.clusterDualQuaternions[0]; - Transform transform(dq.getRotation(), - dq.getScale(), - dq.getTranslation()); - renderTransform = modelTransform.worldTransform(Transform(transform)); - } - } else { - if (meshState.clusterMatrices.size() == 1 || meshState.clusterMatrices.size() == 2) { - renderTransform = modelTransform.worldTransform(Transform(meshState.clusterMatrices[0])); - } - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform); + data.updateTransformForSkinnedMesh(modelTransform, meshState, useDualQuaternionSkinning); data.setCauterized(cauterized); data.setRenderWithZones(renderWithZones); + data.setBillboardMode(billboardMode); data.updateKey(renderItemKeyGlobalFlags); data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); }); @@ -987,6 +974,31 @@ void Model::setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePoi } } +void Model::setBillboardMode(BillboardMode billboardMode, const render::ScenePointer& scene) { + if (_billboardMode != billboardMode) { + _billboardMode = billboardMode; + if (!scene) { + _needsFixupInScene = true; + return; + } + + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; + std::unordered_map shouldInvalidatePayloadShapeKeyMap; + + for (auto& shape : _modelMeshRenderItemShapes) { + shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex); + } + + render::Transaction transaction; + for (auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [billboardMode](ModelMeshPartPayload& data) { + data.setBillboardMode(billboardMode); + }); + } + scene->enqueueTransaction(transaction); + } +} + void Model::setCullWithParent(bool cullWithParent, const render::ScenePointer& scene) { if (_cullWithParent != cullWithParent) { _cullWithParent = cullWithParent; @@ -1017,9 +1029,8 @@ void Model::setRenderWithZones(const QVector& renderWithZones, const rend } render::Transaction transaction; - auto renderItemsKey = _renderItemKeyGlobalFlags; for (auto item : _modelMeshRenderItemIDs) { - transaction.updateItem(item, [renderWithZones, renderItemsKey](ModelMeshPartPayload& data) { + transaction.updateItem(item, [renderWithZones](ModelMeshPartPayload& data) { data.setRenderWithZones(renderWithZones); }); } @@ -1545,10 +1556,6 @@ void Model::createRenderItemSet() { transform.setTranslation(_translation); transform.setRotation(_rotation); - Transform offset; - offset.setScale(_scale); - offset.postTranslate(_offset); - // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; uint32_t numMeshes = (uint32_t)meshes.size(); @@ -1561,7 +1568,7 @@ void Model::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset, _created); + _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, _created); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1e7ab55d5a..3085dcfc6f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -38,6 +38,7 @@ #include "TextureCache.h" #include "Rig.h" #include "PrimitiveMode.h" +#include "BillboardMode.h" // Use dual quaternion skinning! // Must match define in Skinning.slh @@ -121,6 +122,9 @@ public: void setPrimitiveMode(PrimitiveMode primitiveMode, const render::ScenePointer& scene = nullptr); PrimitiveMode getPrimitiveMode() const { return _primitiveMode; } + void setBillboardMode(BillboardMode billboardMode, const render::ScenePointer& scene = nullptr); + BillboardMode getBillboardMode() const { return _billboardMode; } + void setCullWithParent(bool value, const render::ScenePointer& scene = nullptr); void setRenderWithZones(const QVector& renderWithZones, const render::ScenePointer& scene = nullptr); @@ -447,6 +451,7 @@ protected: virtual void createRenderItemSet(); PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; + BillboardMode _billboardMode { BillboardMode::NONE }; bool _useDualQuaternionSkinning { false }; // debug rendering support diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index 4b6af5db33..8243cf772d 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -15,6 +15,8 @@ const char* billboardModeNames[] = { }; static const size_t BILLBOARD_MODE_NAMES = (sizeof(billboardModeNames) / sizeof(billboardModeNames[0])); +std::function BillboardModeHelpers::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; +std::function BillboardModeHelpers::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)BILLBOARD_MODE_NAMES)) { @@ -22,4 +24,4 @@ QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { } return billboardModeNames[(int)mode]; -} \ No newline at end of file +} diff --git a/libraries/shared/src/BillboardMode.h b/libraries/shared/src/BillboardMode.h index aa00ce34aa..31f11766d8 100644 --- a/libraries/shared/src/BillboardMode.h +++ b/libraries/shared/src/BillboardMode.h @@ -9,8 +9,13 @@ #ifndef hifi_BillboardMode_h #define hifi_BillboardMode_h +#include + #include "QString" +#include "glm/glm.hpp" +#include "glm/gtc/quaternion.hpp" + /**jsdoc *

How an entity is billboarded.

* @@ -37,7 +42,15 @@ enum class BillboardMode { class BillboardModeHelpers { public: static QString getNameForBillboardMode(BillboardMode mode); + + static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } + static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } + static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } + +private: + static std::function _getBillboardRotationOperator; + static std::function _getPrimaryViewFrustumPositionOperator; }; #endif // hifi_BillboardMode_h - From 1f71a23082bbc415a7a12ba9b5a2001a1d5dc4cf Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 13:09:09 -0800 Subject: [PATCH 05/11] optimize picking --- interface/src/avatar/AvatarManager.cpp | 6 +- .../src/RenderableModelEntityItem.cpp | 10 +-- .../src/RenderableModelEntityItem.h | 6 +- .../src/RenderablePolyVoxEntityItem.cpp | 4 +- .../src/RenderablePolyVoxEntityItem.h | 6 +- libraries/entities/src/EntityItem.cpp | 10 --- libraries/entities/src/EntityItem.h | 8 +-- libraries/entities/src/EntityTree.cpp | 18 +++-- libraries/entities/src/EntityTreeElement.cpp | 54 +++++++-------- libraries/entities/src/EntityTreeElement.h | 10 +-- libraries/entities/src/GizmoEntityItem.cpp | 8 +-- libraries/entities/src/GizmoEntityItem.h | 7 +- libraries/entities/src/GridEntityItem.cpp | 54 --------------- libraries/entities/src/GridEntityItem.h | 10 --- libraries/entities/src/ImageEntityItem.cpp | 54 --------------- libraries/entities/src/ImageEntityItem.h | 10 --- libraries/entities/src/LightEntityItem.cpp | 6 +- libraries/entities/src/LightEntityItem.h | 6 +- libraries/entities/src/LineEntityItem.h | 6 +- libraries/entities/src/PolyLineEntityItem.h | 6 +- libraries/entities/src/PolyVoxEntityItem.h | 6 +- libraries/entities/src/ShapeEntityItem.cpp | 67 +++++++++---------- libraries/entities/src/ShapeEntityItem.h | 11 +-- libraries/entities/src/TextEntityItem.cpp | 54 --------------- libraries/entities/src/TextEntityItem.h | 10 --- libraries/entities/src/WebEntityItem.cpp | 56 ---------------- libraries/entities/src/WebEntityItem.h | 10 --- libraries/entities/src/ZoneEntityItem.cpp | 6 +- libraries/entities/src/ZoneEntityItem.h | 6 +- libraries/render-utils/src/Model.cpp | 14 ++-- libraries/render-utils/src/Model.h | 6 +- 31 files changed, 140 insertions(+), 405 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 32e725388c..24d9379ab9 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -767,6 +767,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic glm::vec3 rayDirectionInv = { rayDirection.x != 0.0f ? 1.0f / rayDirection.x : INFINITY, rayDirection.y != 0.0f ? 1.0f / rayDirection.y : INFINITY, rayDirection.z != 0.0f ? 1.0f / rayDirection.z : INFINITY }; + glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition(); for (auto &hit : physicsResults) { auto avatarID = hit._intersectWithAvatar; @@ -842,7 +843,7 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic BoxFace subMeshFace = BoxFace::UNKNOWN_FACE; glm::vec3 subMeshSurfaceNormal; QVariantMap subMeshExtraInfo; - if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { + if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { rayAvatarResult._distance = subMeshDistance; rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection; rayAvatarResult._intersectionNormal = subMeshSurfaceNormal; @@ -932,6 +933,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector std::sort(sortedAvatars.begin(), sortedAvatars.end(), comparator); } + glm::vec3 viewFrustumPos = BillboardModeHelpers::getPrimaryViewFrustumPosition(); for (auto it = sortedAvatars.begin(); it != sortedAvatars.end(); ++it) { const SortedAvatar& sortedAvatar = *it; // We can exit once avatarCapsuleDistance > bestDistance @@ -944,7 +946,7 @@ ParabolaToAvatarIntersectionResult AvatarManager::findParabolaIntersectionVector glm::vec3 surfaceNormal; QVariantMap extraInfo; SkeletonModelPointer avatarModel = sortedAvatar.second->getSkeletonModel(); - if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, parabolicDistance, face, surfaceNormal, extraInfo, true)) { + if (avatarModel->findParabolaIntersectionAgainstSubMeshes(pick.origin, pick.velocity, pick.acceleration, viewFrustumPos, parabolicDistance, face, surfaceNormal, extraInfo, true)) { if (parabolicDistance < result.parabolicDistance) { result.intersects = true; result.avatarID = sortedAvatar.second->getID(); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c6765f2321..c8cfb6491a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -224,26 +224,26 @@ bool RenderableModelEntityItem::supportsDetailedIntersection() const { } bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, BoxFace& face, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { auto model = getModel(); if (!model || !model->isLoaded()) { return false; } - return model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, + return model->findRayIntersectionAgainstSubMeshes(origin, direction, viewFrustumPos, distance, face, surfaceNormal, extraInfo, precisionPicking, false); } bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, - glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { auto model = getModel(); if (!model || !model->isLoaded()) { return false; } - return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, + return model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, viewFrustumPos, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking, false); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 4501f6d88c..29474742c1 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -65,12 +65,12 @@ public: virtual bool supportsDetailedIntersection() const override; virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual void setShapeType(ShapeType type) override; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5b6c0c8b70..e3a29fc99c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -526,7 +526,7 @@ public: #endif bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO -- correctly pick against marching-cube generated meshes @@ -567,7 +567,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } bool RenderablePolyVoxEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO -- correctly pick against marching-cube generated meshes diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index d4bcc4d19f..c1c35a21c8 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -71,12 +71,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const vec3& accleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual void setVoxelData(const QByteArray& voxelData) override; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 68e824f8cc..e5e84abae3 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1907,16 +1907,6 @@ void EntityItem::setScaledDimensions(const glm::vec3& value) { setUnscaledDimensions(value / parentScale); } -glm::vec3 EntityItem::getRaycastDimensions() const { - glm::vec3 dimensions = getScaledDimensions(); - if (getBillboardMode() != BillboardMode::NONE) { - float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); - const float SQRT_2 = 1.41421356237f; - return glm::vec3(SQRT_2 * max); - } - return dimensions; -} - void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(ENTITY_ITEM_MIN_DIMENSION)); const float MIN_SCALE_CHANGE_SQUARED = 1.0e-6f; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 288f1682c7..2acb73abbf 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -175,12 +175,12 @@ public: virtual bool supportsDetailedIntersection() const { return false; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } // attributes applicable to all entity types @@ -203,7 +203,6 @@ public: /// Dimensions in meters (0.0 - TREE_SCALE) virtual glm::vec3 getScaledDimensions() const; virtual void setScaledDimensions(const glm::vec3& value); - virtual glm::vec3 getRaycastDimensions() const; glm::vec3 getUnscaledDimensions() const; virtual void setUnscaledDimensions(const glm::vec3& value); @@ -584,6 +583,7 @@ public: void setBillboardMode(BillboardMode value); BillboardMode getBillboardMode() const; + virtual bool getRotateForPicking() const { return false; } signals: void spaceUpdate(std::pair data); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 24b6f7ccd4..3ed1ad581c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -798,6 +798,7 @@ public: glm::vec3 origin; glm::vec3 direction; glm::vec3 invDirection; + glm::vec3 viewFrustumPos; const QVector& entityIdsToInclude; const QVector& entityIdsToDiscard; PickFilter searchFilter; @@ -815,7 +816,7 @@ bool evalRayIntersectionOp(const OctreeElementPointer& element, void* extraData) RayArgs* args = static_cast(extraData); bool keepSearching = true; EntityTreeElementPointer entityTreeElementPointer = std::static_pointer_cast(element); - EntityItemID entityID = entityTreeElementPointer->evalRayIntersection(args->origin, args->direction, + EntityItemID entityID = entityTreeElementPointer->evalRayIntersection(args->origin, args->direction, args->viewFrustumPos, args->element, args->distance, args->face, args->surfaceNormal, args->entityIdsToInclude, args->entityIdsToDiscard, args->searchFilter, args->extraInfo); if (!entityID.isNull()) { @@ -837,7 +838,8 @@ float evalRayIntersectionSortingOp(const OctreeElementPointer& element, void* ex float boundDistance = FLT_MAX; BoxFace face; glm::vec3 surfaceNormal; - if (entityTreeElementPointer->getAACube().findRayIntersection(args->origin, args->direction, args->invDirection, boundDistance, face, surfaceNormal)) { + if (entityTreeElementPointer->getAACube().findRayIntersection(args->origin, args->direction, args->invDirection, + boundDistance, face, surfaceNormal)) { // Don't add this cell if it's already farther than our best distance so far if (boundDistance < args->distance) { distance = boundDistance; @@ -857,7 +859,7 @@ EntityItemID EntityTree::evalRayIntersection(const glm::vec3& origin, const glm: vec3 dirReciprocal = glm::vec3(direction.x == 0.0f ? 0.0f : 1.0f / direction.x, direction.y == 0.0f ? 0.0f : 1.0f / direction.y, direction.z == 0.0f ? 0.0f : 1.0f / direction.z); - RayArgs args = { origin, direction, dirReciprocal, entityIdsToInclude, entityIdsToDiscard, + RayArgs args = { origin, direction, dirReciprocal, BillboardModeHelpers::getPrimaryViewFrustumPosition(), entityIdsToInclude, entityIdsToDiscard, searchFilter, element, distance, face, surfaceNormal, extraInfo, EntityItemID() }; distance = FLT_MAX; @@ -879,6 +881,7 @@ public: glm::vec3 origin; glm::vec3 velocity; glm::vec3 acceleration; + glm::vec3 viewFrustumPos; const QVector& entityIdsToInclude; const QVector& entityIdsToDiscard; PickFilter searchFilter; @@ -896,7 +899,7 @@ bool evalParabolaIntersectionOp(const OctreeElementPointer& element, void* extra ParabolaArgs* args = static_cast(extraData); bool keepSearching = true; EntityTreeElementPointer entityTreeElementPointer = std::static_pointer_cast(element); - EntityItemID entityID = entityTreeElementPointer->evalParabolaIntersection(args->origin, args->velocity, args->acceleration, + EntityItemID entityID = entityTreeElementPointer->evalParabolaIntersection(args->origin, args->velocity, args->acceleration, args->viewFrustumPos, args->element, args->parabolicDistance, args->face, args->surfaceNormal, args->entityIdsToInclude, args->entityIdsToDiscard, args->searchFilter, args->extraInfo); if (!entityID.isNull()) { @@ -918,7 +921,8 @@ float evalParabolaIntersectionSortingOp(const OctreeElementPointer& element, voi float boundDistance = FLT_MAX; BoxFace face; glm::vec3 surfaceNormal; - if (entityTreeElementPointer->getAACube().findParabolaIntersection(args->origin, args->velocity, args->acceleration, boundDistance, face, surfaceNormal)) { + if (entityTreeElementPointer->getAACube().findParabolaIntersection(args->origin, args->velocity, args->acceleration, + boundDistance, face, surfaceNormal)) { // Don't add this cell if it's already farther than our best distance so far if (boundDistance < args->parabolicDistance) { distance = boundDistance; @@ -934,8 +938,8 @@ EntityItemID EntityTree::evalParabolaIntersection(const PickParabola& parabola, OctreeElementPointer& element, glm::vec3& intersection, float& distance, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, Octree::lockType lockType, bool* accurateResult) { - ParabolaArgs args = { parabola.origin, parabola.velocity, parabola.acceleration, entityIdsToInclude, entityIdsToDiscard, - searchFilter, element, parabolicDistance, face, surfaceNormal, extraInfo, EntityItemID() }; + ParabolaArgs args = { parabola.origin, parabola.velocity, parabola.acceleration, BillboardModeHelpers::getPrimaryViewFrustumPosition(), + entityIdsToInclude, entityIdsToDiscard, searchFilter, element, parabolicDistance, face, surfaceNormal, extraInfo, EntityItemID() }; parabolicDistance = FLT_MAX; distance = FLT_MAX; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index afbb139d5f..4387647383 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -162,7 +162,7 @@ bool EntityTreeElement::checkFilterSettings(const EntityItemPointer& entity, Pic return true; } -EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -177,7 +177,7 @@ EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, con QVariantMap localExtraInfo; float distanceToElementDetails = distance; - EntityItemID entityID = evalDetailedRayIntersection(origin, direction, element, distanceToElementDetails, + EntityItemID entityID = evalDetailedRayIntersection(origin, direction, viewFrustumPos, element, distanceToElementDetails, localFace, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, searchFilter, localExtraInfo); if (!entityID.isNull() && distanceToElementDetails < distance) { distance = distanceToElementDetails; @@ -189,7 +189,7 @@ EntityItemID EntityTreeElement::evalRayIntersection(const glm::vec3& origin, con return result; } -EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, +EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIDsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -222,11 +222,12 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -246,7 +247,7 @@ EntityItemID EntityTreeElement::evalDetailedRayIntersection(const glm::vec3& ori // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; - if (entity->findDetailedRayIntersection(origin, direction, element, localDistance, + if (entity->findDetailedRayIntersection(origin, direction, viewFrustumPos, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < distance) { distance = localDistance; @@ -300,7 +301,7 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad } EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { @@ -323,7 +324,7 @@ EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin } // Get the normal of the plane, the cross product of two vectors on the plane glm::vec3 normal = glm::normalize(glm::cross(vectorOnPlane, acceleration)); - EntityItemID entityID = evalDetailedParabolaIntersection(origin, velocity, acceleration, normal, element, distanceToElementDetails, + EntityItemID entityID = evalDetailedParabolaIntersection(origin, velocity, acceleration, viewFrustumPos, normal, element, distanceToElementDetails, localFace, localSurfaceNormal, entityIdsToInclude, entityIdsToDiscard, searchFilter, localExtraInfo); if (!entityID.isNull() && distanceToElementDetails < parabolicDistance) { parabolicDistance = distanceToElementDetails; @@ -336,9 +337,9 @@ EntityItemID EntityTreeElement::evalParabolaIntersection(const glm::vec3& origin } EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - const glm::vec3& normal, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, - const QVector& entityIdsToInclude, const QVector& entityIDsToDiscard, - PickFilter searchFilter, QVariantMap& extraInfo) { + const glm::vec3& viewFrustumPos,const glm::vec3& normal, OctreeElementPointer& element, float& parabolicDistance, + BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, + const QVector& entityIDsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo) { // only called if we do intersect our bounding cube, but find if we actually intersect with entities... EntityItemID entityID; @@ -373,11 +374,12 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 glm::vec3 position = entity->getWorldPosition(); glm::mat4 translation = glm::translate(position); glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), + viewFrustumPos, entity->getRotateForPicking())); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -398,7 +400,7 @@ EntityItemID EntityTreeElement::evalDetailedParabolaIntersection(const glm::vec3 // now ask the entity if we actually intersect if (entity->supportsDetailedIntersection()) { QVariantMap localExtraInfo; - if (entity->findDetailedParabolaIntersection(origin, velocity, acceleration, element, localDistance, + if (entity->findDetailedParabolaIntersection(origin, velocity, acceleration, viewFrustumPos, element, localDistance, localFace, localSurfaceNormal, localExtraInfo, searchFilter.isPrecise())) { if (localDistance < parabolicDistance) { parabolicDistance = localDistance; @@ -454,7 +456,7 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -476,10 +478,8 @@ void EntityTreeElement::evalEntitiesInSphere(const glm::vec3& position, float ra } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::vec3 position = entity->getWorldPosition(); - glm::mat4 translation = glm::translate(position); - glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -510,7 +510,7 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -532,10 +532,8 @@ void EntityTreeElement::evalEntitiesInSphereWithType(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::vec3 position = entity->getWorldPosition(); - glm::mat4 translation = glm::translate(position); - glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); @@ -571,7 +569,7 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, glm::vec3 penetration; if (success && entityBox.findSpherePenetration(position, radius, penetration)) { - glm::vec3 dimensions = entity->getRaycastDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably do actual hull testing if they wanted to @@ -593,10 +591,8 @@ void EntityTreeElement::evalEntitiesInSphereWithName(const glm::vec3& position, } else { // determine the worldToEntityMatrix that doesn't include scale because // we're going to use the registration aware aa box in the entity frame - glm::vec3 position = entity->getWorldPosition(); - glm::mat4 translation = glm::translate(position); - glm::quat orientation = entity->getWorldOrientation(); - glm::mat4 rotation = glm::mat4_cast(BillboardModeHelpers::getBillboardRotation(position, orientation, entity->getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition())); + glm::mat4 translation = glm::translate(entity->getWorldPosition()); + glm::mat4 rotation = glm::mat4_cast(entity->getWorldOrientation()); glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index f94da44138..dab56132c9 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -136,24 +136,24 @@ public: static bool checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter); virtual bool canPickIntersect() const override { return hasEntities(); } - virtual EntityItemID evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + virtual EntityItemID evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual EntityItemID evalDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration, void** penetratedObject) const override; virtual EntityItemID evalParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); virtual EntityItemID evalDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& normal, const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, + const glm::vec3& normal, const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, PickFilter searchFilter, QVariantMap& extraInfo); template diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index 6586d57fde..694371d739 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -103,7 +103,7 @@ bool GizmoEntityItem::supportsDetailedIntersection() const { } bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); @@ -111,7 +111,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), false); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 hitPosition = origin + (distance * direction); @@ -137,7 +137,7 @@ bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { //// Scale the dimensions by the diameter @@ -146,7 +146,7 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::quat rotation = getWorldOrientation(); rotation *= glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); glm::vec3 position = getWorldPosition(); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition(), true); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); glm::quat inverseRot = glm::inverse(rotation); glm::vec3 localOrigin = inverseRot * (origin - position); diff --git a/libraries/entities/src/GizmoEntityItem.h b/libraries/entities/src/GizmoEntityItem.h index 37a802387d..a05c294523 100644 --- a/libraries/entities/src/GizmoEntityItem.h +++ b/libraries/entities/src/GizmoEntityItem.h @@ -45,13 +45,14 @@ public: bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; + bool getRotateForPicking() const override { return getBillboardMode() != BillboardMode::NONE; } GizmoType getGizmoType() const; void setGizmoType(GizmoType value); diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index c675a11d27..e635511bfc 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -125,60 +125,6 @@ void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_MINOR_GRID_EVERY, getMinorGridEvery()); } -bool GridEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool GridEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - void GridEntityItem::setColor(const glm::u8vec3& color) { withWriteLock([&] { _needsRenderUpdate |= _color != color; diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h index fc31c93a5a..7dc7a475b2 100644 --- a/libraries/entities/src/GridEntityItem.h +++ b/libraries/entities/src/GridEntityItem.h @@ -43,16 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - static const uint32_t DEFAULT_MAJOR_GRID_EVERY; static const float DEFAULT_MINOR_GRID_EVERY; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 80711e4abc..afa6d9ae69 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -127,60 +127,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage()); } -bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool ImageEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - QString ImageEntityItem::getImageURL() const { QString result; withReadLock([&] { diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index a5ed139e6b..4f7aac0c13 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,16 +43,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - void setImageURL(const QString& imageUrl); QString getImageURL() const; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 0dcb5d125a..a3e00cddba 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -254,7 +254,7 @@ float LightEntityItem::getCutoff() const { } bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { @@ -267,8 +267,8 @@ bool LightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } bool LightEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { // TODO: consider if this is really what we want to do. We've made it so that "lights are pickable" is a global state // this is probably reasonable since there's typically only one tree you'd be picking on at a time. Technically we could diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 5245770ec8..0f21c6acd9 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -74,12 +74,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; private: diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 38e526204e..505291cdda 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -52,13 +52,13 @@ class LineEntityItem : public EntityItem { // never have a ray intersection pick a LineEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 8fb7831c6a..23f6e36e73 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -82,12 +82,12 @@ public: // never have a ray intersection pick a PolyLineEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } void computeTightLocalBoundingBox(AABox& box) const; diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index c416353ecf..3e3fe0b18c 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -44,12 +44,12 @@ class PolyVoxEntityItem : public EntityItem { // never have a ray intersection pick a PolyVoxEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } virtual void debugDump() const override; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 943912b934..7858e62f7d 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -269,17 +269,17 @@ void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { } bool ShapeEntityItem::supportsDetailedIntersection() const { - return getShape() == entity::Sphere || getBillboardMode() != BillboardMode::NONE; + return getShape() == entity::Sphere; } bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); // determine the ray in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); @@ -287,35 +287,31 @@ bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 entityFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - if (getShape() == entity::Sphere) { - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - // determine where on the unit sphere the hit point occured - glm::vec3 hitAt = origin + (direction * distance); - surfaceNormal = glm::normalize(hitAt - center); - } else { - return false; - } - return true; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, distance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + // determine where on the unit sphere the hit point occured + glm::vec3 hitAt = origin + (direction * distance); + surfaceNormal = glm::normalize(hitAt - center); + } else { + return false; } - } else if (findRayAABoxIntersection(entityFrameOrigin, entityFrameDirection, 1.0f / entityFrameDirection, glm::vec3(-0.5f), glm::vec3(1.0f), distance, face, surfaceNormal)) { return true; } return false; } bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); + rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), viewFrustumPos); // determine the parabola in the frame of the entity transformed from a unit sphere glm::mat4 entityToWorldMatrix = glm::translate(position) * glm::mat4_cast(rotation) * glm::scale(dimensions); @@ -324,25 +320,26 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, glm::vec3 entityFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); glm::vec3 entityFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f)); - if (getShape() == entity::Sphere) { - // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 - if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { - bool success; - glm::vec3 center = getCenterPosition(success); - if (success) { - // FIXME: this is only correct for uniformly scaled spheres - surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); - } else { - return false; - } - return true; + // NOTE: unit sphere has center of 0,0,0 and radius of 0.5 + if (findParabolaSphereIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(0.0f), 0.5f, parabolicDistance)) { + bool success; + glm::vec3 center = getCenterPosition(success); + if (success) { + // FIXME: this is only correct for uniformly scaled spheres + surfaceNormal = glm::normalize((origin + velocity * parabolicDistance + 0.5f * acceleration * parabolicDistance * parabolicDistance) - center); + } else { + return false; } - } else if (findParabolaAABoxIntersection(entityFrameOrigin, entityFrameVelocity, entityFrameAcceleration, glm::vec3(-0.5f), glm::vec3(1.0f), parabolicDistance, face, surfaceNormal)) { return true; } return false; } +bool ShapeEntityItem::getRotateForPicking() const { + auto shape = getShape(); + return getBillboardMode() != BillboardMode::NONE && (_shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron); +} + void ShapeEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index c0dc9642fe..d5b934153a 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -86,13 +86,14 @@ public: bool supportsDetailedIntersection() const override; bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool precisionPicking) const override; bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; + bool getRotateForPicking() const override; void debugDump() const override; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 7fab5cee53..ebe536cae8 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -191,60 +191,6 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TEXT_EFFECT_THICKNESS, getTextEffectThickness()); } -bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool TextEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - void TextEntityItem::setText(const QString& value) { withWriteLock([&] { _needsRenderUpdate |= _text != value; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 212f11e768..3e58831a72 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -48,16 +48,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - static const QString DEFAULT_TEXT; void setText(const QString& value); QString getText() const; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index d9d2425e11..c0ad9e7094 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -157,62 +157,6 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_WEB_USE_BACKGROUND, getUseBackground()); } -bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } else { - return false; - } -} - -bool WebEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const { - glm::vec3 dimensions = getScaledDimensions(); - glm::vec2 xyDimensions(dimensions.x, dimensions.y); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); - rotation = BillboardModeHelpers::getBillboardRotation(position, rotation, getBillboardMode(), BillboardModeHelpers::getPrimaryViewFrustumPosition()); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } else { - return false; - } -} - void WebEntityItem::setColor(const glm::u8vec3& value) { withWriteLock([&] { _needsRenderUpdate |= _color != value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index e0a66f25b2..8edd20245f 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -45,16 +45,6 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - virtual bool supportsDetailedIntersection() const override { return getBillboardMode() != BillboardMode::NONE; } - virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, - QVariantMap& extraInfo, bool precisionPicking) const override; - glm::u8vec3 getColor() const; void setColor(const glm::u8vec3& value); diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 8b020e92d5..3eabfb4f1e 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -318,15 +318,15 @@ void ZoneEntityItem::setCompoundShapeURL(const QString& url) { } bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return _zonesArePickable; } bool ZoneEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return _zonesArePickable; } diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 9c8e3839b7..2b61bbd346 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -116,12 +116,12 @@ public: virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - OctreeElementPointer& element, float& distance, + const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, - const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override; bool contains(const glm::vec3& point) const override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9bf1596a04..dad2f95420 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -319,8 +319,8 @@ void Model::initJointStates() { _rig.initJointStates(hfmModel, modelOffset); } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles, bool allowBackface) { bool intersectedSomething = false; @@ -330,7 +330,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::quat rotation = BillboardModeHelpers::getBillboardRotation(_translation, _rotation, _billboardMode, viewFrustumPos); + glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(rotation, _translation); glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated @@ -475,8 +476,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, - bool pickAgainstTriangles, bool allowBackface) { + const glm::vec3& viewFrustumPos, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + QVariantMap& extraInfo, bool pickAgainstTriangles, bool allowBackface) { bool intersectedSomething = false; // if we aren't active, we can't pick yet... @@ -485,7 +486,8 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::quat rotation = BillboardModeHelpers::getBillboardRotation(_translation, _rotation, _billboardMode, viewFrustumPos); + glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(rotation, _translation); glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3085dcfc6f..5a8338993a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -198,11 +198,11 @@ public: void setJointRotation(int index, bool valid, const glm::quat& rotation, float priority); void setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority); - bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& viewFrustumPos, + float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false); bool findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + const glm::vec3& viewFrustumPos, float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool pickAgainstTriangles = false, bool allowBackface = false); void setOffset(const glm::vec3& offset); From 92ea14a0591ad70b078eca6e9142deb269e25eb4 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 22:08:06 -0800 Subject: [PATCH 06/11] proper render bounds for models (need to pass RenderArgs to getBound everywhere) --- interface/src/graphics/WorldBox.cpp | 2 +- interface/src/graphics/WorldBox.h | 2 +- interface/src/raypick/ParabolaPointer.cpp | 4 +-- interface/src/raypick/ParabolaPointer.h | 4 +-- interface/src/ui/overlays/Overlay.h | 2 +- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- .../src/workload/GameWorkloadRenderer.cpp | 4 +-- interface/src/workload/GameWorkloadRenderer.h | 4 +-- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/avatars-renderer/Avatar.h | 2 +- .../src/RenderableEntityItem.cpp | 2 +- .../src/RenderableEntityItem.h | 2 +- .../src/RenderableGizmoEntityItem.cpp | 4 +-- .../src/RenderableGizmoEntityItem.h | 2 +- .../src/RenderableGridEntityItem.cpp | 4 +-- .../src/RenderableGridEntityItem.h | 2 +- .../src/RenderableLightEntityItem.cpp | 4 +-- .../src/RenderableLightEntityItem.h | 2 +- .../src/RenderableMaterialEntityItem.cpp | 2 +- .../RenderableParticleEffectEntityItem.cpp | 2 +- .../src/RenderableParticleEffectEntityItem.h | 2 +- .../src/RenderableShapeEntityItem.cpp | 6 ++-- .../src/RenderableShapeEntityItem.h | 2 +- .../src/RenderableTextEntityItem.cpp | 8 ++--- .../src/RenderableTextEntityItem.h | 4 +-- libraries/procedural/CMakeLists.txt | 2 +- .../procedural/src/procedural/Procedural.h | 11 +++--- libraries/render-utils/src/AnimDebugDraw.cpp | 2 +- libraries/render-utils/src/FadeEffectJobs.cpp | 8 ++--- libraries/render-utils/src/FadeEffectJobs.h | 2 +- libraries/render-utils/src/LightPayload.cpp | 4 +-- libraries/render-utils/src/LightPayload.h | 4 +-- .../render-utils/src/MeshPartPayload.cpp | 20 +++++++---- libraries/render-utils/src/MeshPartPayload.h | 5 ++- libraries/render-utils/src/Model.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 34 +++++++++---------- .../render/src/render/DrawSceneOctree.cpp | 2 +- libraries/render/src/render/FilterTask.cpp | 2 +- libraries/render/src/render/Item.cpp | 8 ++--- libraries/render/src/render/Item.h | 20 +++++------ libraries/render/src/render/Scene.cpp | 6 ++-- libraries/render/src/render/SortTask.cpp | 2 +- 42 files changed, 108 insertions(+), 102 deletions(-) diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp index 0e15d9da86..a627cf75e4 100644 --- a/interface/src/graphics/WorldBox.cpp +++ b/interface/src/graphics/WorldBox.cpp @@ -16,7 +16,7 @@ render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; namespace render { template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } - template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { return Item::Bound(); } template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { PerformanceTimer perfTimer("worldBox"); diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h index 4d53652c0e..0d697eb133 100644 --- a/interface/src/graphics/WorldBox.h +++ b/interface/src/graphics/WorldBox.h @@ -32,7 +32,7 @@ public: namespace render { template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff); - template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff); + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args); template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args); } diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 216248f8b5..67f0772228 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -462,9 +462,9 @@ namespace render { template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) { return payload->getKey(); } - template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h index 85d09adbdb..1701e4dcfa 100644 --- a/interface/src/raypick/ParabolaPointer.h +++ b/interface/src/raypick/ParabolaPointer.h @@ -31,7 +31,7 @@ public: void render(RenderArgs* args); render::Item::Bound& editBound() { return _bound; } - const render::Item::Bound& getBound() { return _bound; } + const render::Item::Bound& getBound(RenderArgs* args) { return _bound; } render::ItemKey getKey() const { return _key; } void setVisible(bool visible); @@ -128,7 +128,7 @@ private: namespace render { template <> const ItemKey payloadGetKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); - template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args); template <> void payloadRender(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const ParabolaPointer::RenderState::ParabolaRenderItem::Pointer& payload); } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 72373d2d20..5c92cfce00 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -66,7 +66,7 @@ private: namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay); - template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay); + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args); template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const Overlay::Pointer& overlay); template <> uint32_t metaFetchMetaSubItems(const Overlay::Pointer& overlay, ItemIDs& subItems); diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 0d1bcdd071..fdcd4f7205 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -14,7 +14,7 @@ namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { return overlay->getKey(); } - template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay) { + template <> const Item::Bound payloadGetBound(const Overlay::Pointer& overlay, RenderArgs* args) { return overlay->getBounds(); } template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index f65bf88754..1310baf4b3 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -82,9 +82,9 @@ namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { return payload->getKey(); } - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index a25598821e..ad33425774 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -57,7 +57,7 @@ public: void render(RenderArgs* args); render::Item::Bound& editBound() { return _bound; } - const render::Item::Bound& getBound() { return _bound; } + const render::Item::Bound& getBound(RenderArgs* args) { return _bound; } void setVisible(bool visible); void showProxies(bool show); @@ -96,7 +96,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index d859454a99..f361e15999 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -63,7 +63,7 @@ namespace render { } return keyBuilder.build(); } - template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { + template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args) { auto avatarPtr = static_pointer_cast(avatar); if (avatarPtr) { return avatarPtr->getRenderBounds(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 25dd347484..4fc9c25595 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -39,7 +39,7 @@ namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar); - template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar); + template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar, RenderArgs* args); template <> void payloadRender(const AvatarSharedPointer& avatar, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const AvatarSharedPointer& avatar, ItemIDs& subItems); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index fdb971e7a3..b2670e3bce 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -137,7 +137,7 @@ EntityRenderer::~EntityRenderer() {} // Smart payload proxy members, implementing the payload interface // -Item::Bound EntityRenderer::getBound() { +Item::Bound EntityRenderer::getBound(RenderArgs* args) { auto bound = _bound; if (_billboardMode != BillboardMode::NONE) { glm::vec3 dimensions = bound.getScale(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 4afcd6e231..7f0e1e16ee 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -64,7 +64,7 @@ public: static glm::vec3 calculatePulseColor(const glm::vec3& color, const PulsePropertyGroup& pulseProperties, quint64 start); virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; protected: diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index 3abd120bf9..bf005ae2e5 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -195,8 +195,8 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } } -Item::Bound GizmoEntityRenderer::getBound() { - auto bound = Parent::getBound(); +Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) { + auto bound = Parent::getBound(args); if (_ringProperties.getHasTickMarks()) { glm::vec3 scale = bound.getScale(); for (int i = 0; i < 3; i += 2) { diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h index 8593348bde..6a09d1a047 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h @@ -23,7 +23,7 @@ public: ~GizmoEntityRenderer(); protected: - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; bool isTransparent() const override; diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index a5ae4acbf5..e374fe29c0 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -49,13 +49,13 @@ void GridEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe _minorGridEvery = entity->getMinorGridEvery(); } -Item::Bound GridEntityRenderer::getBound() { +Item::Bound GridEntityRenderer::getBound(RenderArgs* args) { if (_followCamera) { // This is a UI element that should always be in view, lie to the octree to avoid culling const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE); return DOMAIN_BOX; } - return Parent::getBound(); + return Parent::getBound(args); } ShapeKey GridEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.h b/libraries/entities-renderer/src/RenderableGridEntityItem.h index 1958d17136..fd5b397424 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.h @@ -23,7 +23,7 @@ public: ~GridEntityRenderer(); protected: - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; bool isTransparent() const override; diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 9eb2e8428d..2ab2051fcf 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -60,8 +60,8 @@ ItemKey LightEntityRenderer::getKey() { return payloadGetKey(_lightPayload); } -Item::Bound LightEntityRenderer::getBound() { - return payloadGetBound(_lightPayload); +Item::Bound LightEntityRenderer::getBound(RenderArgs* args) { + return payloadGetBound(_lightPayload, args); } void LightEntityRenderer::doRender(RenderArgs* args) { diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 323f280795..bbb5ec346a 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -29,7 +29,7 @@ protected: virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual ItemKey getKey() override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override; private: diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 74b479affe..714defe817 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -376,7 +376,7 @@ void MaterialEntityRenderer::applyMaterial(const TypedEntityPointer& entity) { if (material->isProcedural()) { auto procedural = std::static_pointer_cast(material); - procedural->setBoundOperator([this] { return getBound(); }); + procedural->setBoundOperator([this](RenderArgs* args) { return getBound(args); }); entity->setHasVertexShader(procedural->hasVertexShader()); } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4fe6bc8f93..e2a57840d9 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -161,7 +161,7 @@ ShapeKey ParticleEffectEntityRenderer::getShapeKey() { return builder.build(); } -Item::Bound ParticleEffectEntityRenderer::getBound() { +Item::Bound ParticleEffectEntityRenderer::getBound(RenderArgs* args) { return _bound; } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index ca6bc859fb..547d654486 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -30,7 +30,7 @@ protected: virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; - virtual Item::Bound getBound() override; + virtual Item::Bound getBound(RenderArgs* args) override; virtual void doRender(RenderArgs* args) override; private: diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 9cc18a8df5..674d7c297d 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -200,16 +200,16 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { return builder.build(); } -Item::Bound ShapeEntityRenderer::getBound() { +Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) { auto mat = _materials.find("0"); if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) { auto procedural = std::static_pointer_cast(mat->second.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); + return procedural->getBound(args); } } - return Parent::getBound(); + return Parent::getBound(args); } void ShapeEntityRenderer::doRender(RenderArgs* args) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 9fb2fa8f23..fe62ad48b9 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -26,7 +26,7 @@ public: protected: ShapeKey getShapeKey() override; - Item::Bound getBound() override; + Item::Bound getBound(RenderArgs* args) override; private: virtual bool needsRenderUpdate() const override; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 1724cf69d5..16d9afb913 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -227,12 +227,12 @@ ItemKey entities::TextPayload::getKey() const { return ItemKey::Builder::opaqueShape(); } -Item::Bound entities::TextPayload::getBound() const { +Item::Bound entities::TextPayload::getBound(RenderArgs* args) const { auto entityTreeRenderer = DependencyManager::get(); if (entityTreeRenderer) { auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); if (renderable) { - return std::static_pointer_cast(renderable)->getBound(); + return std::static_pointer_cast(renderable)->getBound(args); } } return Item::Bound(); @@ -335,9 +335,9 @@ template <> const ItemKey payloadGetKey(const TextPayload::Pointer& payload) { return ItemKey::Builder::opaqueShape(); } -template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload) { +template <> const Item::Bound payloadGetBound(const TextPayload::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 1564c98644..0f736d1229 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -88,7 +88,7 @@ public: typedef Payload::DataPointer Pointer; ItemKey getKey() const; - Item::Bound getBound() const; + Item::Bound getBound(RenderArgs* args) const; ShapeKey getShapeKey() const; void render(RenderArgs* args); bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; @@ -104,7 +104,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const entities::TextPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index d737d34e95..a7394a3670 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME procedural) setup_hifi_library() -link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image hfm) +link_hifi_libraries(shared gpu shaders networking render graphics material-networking ktx image hfm) diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 9b3d0a9bd4..7d655b5ef4 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -113,9 +114,9 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } bool hasVertexShader() const; - void setBoundOperator(const std::function& boundOperator) { _boundOperator = boundOperator; } + void setBoundOperator(const std::function& boundOperator) { _boundOperator = boundOperator; } bool hasBoundOperator() const { return (bool)_boundOperator; } - AABox getBound() { return _boundOperator(); } + AABox getBound(RenderArgs* args) { return _boundOperator(args); } gpu::Shader::Source _vertexSource; gpu::Shader::Source _vertexSourceSkinned; @@ -199,7 +200,7 @@ private: bool _doesFade { true }; ProceduralProgramKey _prevKey; - std::function _boundOperator { nullptr }; + std::function _boundOperator { nullptr }; mutable std::mutex _mutex; }; @@ -232,9 +233,9 @@ public: void initializeProcedural(); - void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } + void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } bool hasBoundOperator() const { return _procedural.hasBoundOperator(); } - AABox getBound() { return _procedural.getBound(); } + AABox getBound(RenderArgs* args) { return _procedural.getBound(args); } private: QString _proceduralString; diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c4020cb4c4..770ac0b7dd 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -68,7 +68,7 @@ typedef render::Payload AnimDebugDrawPayload; namespace render { template <> const ItemKey payloadGetKey(const AnimDebugDrawData::Pointer& data) { return (data->_isVisible ? ItemKey::Builder::transparentShape() : ItemKey::Builder::transparentShape().withInvisible()).withTagBits(ItemKey::TAG_BITS_ALL); } - template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data) { return data->_bound; } + template <> const Item::Bound payloadGetBound(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { return data->_bound; } template <> void payloadRender(const AnimDebugDrawData::Pointer& data, RenderArgs* args) { data->render(args); } diff --git a/libraries/render-utils/src/FadeEffectJobs.cpp b/libraries/render-utils/src/FadeEffectJobs.cpp index 43206e77fa..6f6205060a 100644 --- a/libraries/render-utils/src/FadeEffectJobs.cpp +++ b/libraries/render-utils/src/FadeEffectJobs.cpp @@ -575,7 +575,7 @@ void FadeJob::run(const render::RenderContextPointer& renderContext, FadeJob::Ou auto& item = scene->getItem(state.itemId); assert(item.getTransitionId() == transitionId); #endif - if (update(*jobConfig, scene, transaction, state, deltaTime)) { + if (update(renderContext->args, *jobConfig, scene, transaction, state, deltaTime)) { hasTransaction = true; } if (isFirstItem && (state.threshold != jobConfig->threshold)) { @@ -599,7 +599,7 @@ const FadeCategory FadeJob::transitionToCategory[render::Transition::TYPE_COUNT] FADE_AVATAR_CHANGE }; -bool FadeJob::update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const { +bool FadeJob::update(RenderArgs* args, const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const { const auto fadeCategory = transitionToCategory[transition.eventType]; auto& eventConfig = config.events[fadeCategory]; auto item = scene->getItemSafe(transition.itemId); @@ -607,11 +607,11 @@ bool FadeJob::update(const Config& config, const render::ScenePointer& scene, re const FadeConfig::Timing timing = (FadeConfig::Timing) eventConfig.timing; if (item.exist()) { - auto aabb = item.getBound(); + auto aabb = item.getBound(args); if (render::Item::isValidID(transition.boundItemId)) { auto boundItem = scene->getItemSafe(transition.boundItemId); if (boundItem.exist()) { - aabb = boundItem.getBound(); + aabb = boundItem.getBound(args); } } auto& dimensions = aabb.getDimensions(); diff --git a/libraries/render-utils/src/FadeEffectJobs.h b/libraries/render-utils/src/FadeEffectJobs.h index 449995dba5..08b49c8d2d 100644 --- a/libraries/render-utils/src/FadeEffectJobs.h +++ b/libraries/render-utils/src/FadeEffectJobs.h @@ -223,7 +223,7 @@ private: float _thresholdScale[FADE_CATEGORY_COUNT]; uint64_t _previousTime{ 0 }; - bool update(const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const; + bool update(RenderArgs* args, const Config& config, const render::ScenePointer& scene, render::Transaction& transaction, render::Transition& transition, const double deltaTime) const; static float computeElementEnterRatio(double time, const double period, FadeConfig::Timing timing); }; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 79e0c1d94d..d1018982d0 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -28,7 +28,7 @@ namespace render { return builder.build(); } - template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload, RenderArgs* args) { if (payload) { return payload->editBound(); } @@ -98,7 +98,7 @@ namespace render { return builder.build(); } - template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload, RenderArgs* args) { if (payload) { return payload->editBound(); } diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h index 44b79ce10c..4c6695ec58 100644 --- a/libraries/render-utils/src/LightPayload.h +++ b/libraries/render-utils/src/LightPayload.h @@ -43,7 +43,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const LightPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const LightPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const LightPayload::Pointer& payload, RenderArgs* args); } @@ -79,7 +79,7 @@ protected: namespace render { template <> const ItemKey payloadGetKey(const KeyLightPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const KeyLightPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const KeyLightPayload::Pointer& payload, RenderArgs* args); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 0e0af6fc71..2d07fec8bf 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -177,8 +177,6 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& modelT } _parentTransform = modelTransform; - _worldBound = _adjustedLocalBound; - _worldBound.transform(_parentTransform); } void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { @@ -289,15 +287,23 @@ ItemKey ModelMeshPartPayload::getKey() const { return _itemKey; } -Item::Bound ModelMeshPartPayload::getBound() const { +Item::Bound ModelMeshPartPayload::getBound(RenderArgs* args) const { graphics::MaterialPointer material = _drawMaterials.empty() ? nullptr : _drawMaterials.top().material; if (material && material->isProcedural() && material->isReady()) { auto procedural = std::static_pointer_cast(_drawMaterials.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(); + return procedural->getBound(args); } } - return _worldBound; + + auto worldBound = _adjustedLocalBound; + auto parentTransform = _parentTransform; + if (args) { + parentTransform.setRotation(BillboardModeHelpers::getBillboardRotation(parentTransform.getTranslation(), parentTransform.getRotation(), _billboardMode, + args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition())); + } + worldBound.transform(parentTransform); + return worldBound; } ShapeKey ModelMeshPartPayload::getShapeKey() const { @@ -396,9 +402,9 @@ template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& pay return ItemKey::Builder::opaqueShape(); // for lack of a better idea } -template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { +template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { if (payload) { - return payload->getBound(); + return payload->getBound(args); } return Item::Bound(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 63ccb85470..b5cff41bf8 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -45,7 +45,7 @@ public: // Render Item interface render::ItemKey getKey() const; - render::Item::Bound getBound() const; + render::Item::Bound getBound(RenderArgs* args) const; render::ShapeKey getShapeKey() const; void render(RenderArgs* args); @@ -99,12 +99,11 @@ private: Transform _parentTransform; graphics::Box _localBound; graphics::Box _adjustedLocalBound; - mutable graphics::Box _worldBound; }; namespace render { template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload); - template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload); + template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index dad2f95420..f4267fdf39 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1527,7 +1527,7 @@ AABox Model::getRenderableMeshBound() const { // Build a bound using the last known bound from all the renderItems. AABox totalBound; for (auto& renderItem : _modelMeshRenderItems) { - totalBound += renderItem->getBound(); + totalBound += renderItem->getBound(nullptr); } return totalBound; } diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 164d8e9f21..68bb467f66 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -83,7 +83,7 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const for (auto& id : items) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && item.passesZoneOcclusionTest(CullTest::_containingZones)) { - outItems.emplace_back(ItemBound(id, item.getBound())); + outItems.emplace_back(ItemBound(id, item.getBound(renderContext->args))); } } } @@ -188,10 +188,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -203,10 +203,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -218,10 +218,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -233,10 +233,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -250,10 +250,10 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -265,11 +265,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -282,11 +282,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } @@ -299,11 +299,11 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { - ItemBound itemBound(id, item.getBound()); + ItemBound itemBound(id, item.getBound(args)); if (test.frustumTest(itemBound.bound) && test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); + item.fetchMetaSubItemBounds(outItems, (*scene), args); } } } diff --git a/libraries/render/src/render/DrawSceneOctree.cpp b/libraries/render/src/render/DrawSceneOctree.cpp index 493ed01c3f..44d54c3c28 100644 --- a/libraries/render/src/render/DrawSceneOctree.cpp +++ b/libraries/render/src/render/DrawSceneOctree.cpp @@ -194,7 +194,7 @@ void DrawItemSelection::run(const RenderContextPointer& renderContext, const Ite render::ItemBounds itemBounds; for (const auto& itemID : itemIDs) { auto& item = scene->getItem(itemID); - auto itemBound = item.getBound(); + auto itemBound = item.getBound(args); if (!itemBound.isInvalid()) { itemBounds.emplace_back(itemID, itemBound); } diff --git a/libraries/render/src/render/FilterTask.cpp b/libraries/render/src/render/FilterTask.cpp index 20d29f3e5d..b269f44b41 100644 --- a/libraries/render/src/render/FilterTask.cpp +++ b/libraries/render/src/render/FilterTask.cpp @@ -139,7 +139,7 @@ void IDsToBounds::run(const RenderContextPointer& renderContext, const ItemIDs& for (auto id : inItems) { auto& item = scene->getItem(id); if (item.exist()) { - outItems.emplace_back(ItemBound{ id, item.getBound() }); + outItems.emplace_back(ItemBound{ id, item.getBound(renderContext->args) }); } } } else { diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index f21df58368..369f227566 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -97,7 +97,7 @@ const ShapeKey Item::getShapeKey() const { return shapeKey; } -uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const { +uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene, RenderArgs* args) const { ItemIDs subItems; auto numSubs = fetchMetaSubItems(subItems); @@ -107,7 +107,7 @@ uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) c if (scene.isAllocatedID(id)) { auto& item = scene.getItem(id); if (item.exist()) { - subItemBounds.emplace_back(id, item.getBound()); + subItemBounds.emplace_back(id, item.getBound(args)); } else { numSubs--; } @@ -133,11 +133,11 @@ namespace render { return payload->getShapeKey(); } - template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload) { + template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload, RenderArgs* args) { if (!payload) { return render::Item::Bound(); } - return payload->getBound(); + return payload->getBound(args); } template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8a67108d0e..5952be8a84 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -431,7 +431,7 @@ public: class PayloadInterface { public: virtual const ItemKey getKey() const = 0; - virtual const Bound getBound() const = 0; + virtual const Bound getBound(RenderArgs* args) const = 0; virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; @@ -476,7 +476,7 @@ public: // Payload Interface // Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace()) - const Bound getBound() const { return _payload->getBound(); } + const Bound getBound(RenderArgs* args) const { return _payload->getBound(args); } // Get the layer where the item belongs, simply reflecting the key. int getLayer() const { return _key.getLayer(); } @@ -489,7 +489,7 @@ public: // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } - uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; + uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene, RenderArgs* args) const; bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const { return _payload->passesZoneOcclusionTest(containingZones); } @@ -524,13 +524,13 @@ public: inline QDebug operator<<(QDebug debug, const Item& item) { - debug << "[Item: _key:" << item.getKey() << ", bounds:" << item.getBound() << "]"; + debug << "[Item: _key:" << item.getKey() << "]"; return debug; } // Item shared interface supported by the payload template const ItemKey payloadGetKey(const std::shared_ptr& payloadData) { return ItemKey(); } -template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData) { return Item::Bound(); } +template const Item::Bound payloadGetBound(const std::shared_ptr& payloadData, RenderArgs* args) { return Item::Bound(); } template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } // Shape type interface @@ -561,7 +561,7 @@ public: // Payload general interface virtual const ItemKey getKey() const override { return payloadGetKey(_data); } - virtual const Item::Bound getBound() const override { return payloadGetBound(_data); } + virtual const Item::Bound getBound(RenderArgs* args) const override { return payloadGetBound(_data, args); } virtual void render(RenderArgs* args) override { payloadRender(_data, args); } @@ -607,9 +607,9 @@ template <> const ItemKey payloadGetKey(const FooPointer& foo) { foo->makeMyKey(); return foo->_myownKey; } -template <> const Item::Bound payloadGetBound(const FooPointer& foo) { +template <> const Item::Bound payloadGetBound(const FooPointer& foo, RenderArgs* args) { // evaluate Foo's own bound - return foo->evaluateMyBound(); + return foo->evaluateMyBound(args); } // In this example, do not specialize the payloadRender call which means the compiler will use the default version which does nothing @@ -624,7 +624,7 @@ public: virtual ItemKey getKey() = 0; virtual ShapeKey getShapeKey() = 0; - virtual Item::Bound getBound() = 0; + virtual Item::Bound getBound(RenderArgs* args) = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; @@ -635,7 +635,7 @@ public: }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); -template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload); +template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const PayloadProxyInterface::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index bea111edb5..5500183196 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -305,7 +305,7 @@ void Scene::resetItems(const Transaction::Resets& transactions) { // Update the item's container assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), itemId, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), itemId, newKey); item.resetCell(newCell, newKey.isSmall()); } else { _masterNonspatialSet.insert(itemId); @@ -361,14 +361,14 @@ void Scene::updateItems(const Transaction::Updates& transactions) { // Update the item's container if (oldKey.isSpatial() == newKey.isSpatial()) { if (newKey.isSpatial()) { - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } } else { if (newKey.isSpatial()) { _masterNonspatialSet.erase(updateID); - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(nullptr), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } else { _masterSpatialTree.removeItem(oldCell, oldKey, updateID); diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index 5b4061a10f..266c5be41d 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -60,7 +60,7 @@ void render::depthSortItems(const RenderContextPointer& renderContext, bool fron for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); - auto bound = itemDetails.bound; // item.getBound(); + auto bound = itemDetails.bound; // item.getBound(args); float distanceSquared = args->getViewFrustum().distanceToCameraSquared(bound.calcCenter()); itemBoundSorts.emplace_back(ItemBoundSort(distanceSquared, distanceSquared, distanceSquared, itemDetails.id, bound)); From 7030798d41a3afe6af9b0fb0d6ab7ddc20b52c34 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 17 Jan 2021 22:47:26 -0800 Subject: [PATCH 07/11] cleanup --- libraries/render-utils/src/Model.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f4267fdf39..234ae203cb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -984,13 +984,6 @@ void Model::setBillboardMode(BillboardMode billboardMode, const render::ScenePoi return; } - bool useDualQuaternionSkinning = _useDualQuaternionSkinning; - std::unordered_map shouldInvalidatePayloadShapeKeyMap; - - for (auto& shape : _modelMeshRenderItemShapes) { - shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex); - } - render::Transaction transaction; for (auto item : _modelMeshRenderItemIDs) { transaction.updateItem(item, [billboardMode](ModelMeshPartPayload& data) { From 3a821c2b7448175d32d17cfc321fca7f8b9e91f3 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Mon, 18 Jan 2021 11:23:44 -0800 Subject: [PATCH 08/11] update create --- .../create/assets/data/createAppTooltips.json | 15 ++------- .../html/js/entityProperties.js | 31 ++++++------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 478793ab78..edfdad037b 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -38,10 +38,6 @@ "textEffectThickness": { "tooltip": "The magnitude of the text effect." }, - "textBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "topMargin": { "tooltip": "The top margin, in meters." }, @@ -223,10 +219,6 @@ "subImage": { "tooltip": "The area of the image that is displayed." }, - "imageBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "keepAspectRatio": { "tooltip": "If enabled, the image will maintain its original aspect ratio." }, @@ -236,10 +228,6 @@ "dpi": { "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." }, - "webBillboardMode": { - "tooltip": "If enabled, determines how the entity will face the camera.", - "jsPropertyName": "billboardMode" - }, "inputMode": { "tooltip": "The user input mode to use." }, @@ -595,6 +583,9 @@ "primitiveMode": { "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." }, + "billboardMode": { + "tooltip": "Determines if and how the entity will face the camera.", + }, "renderWithZones": { "tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list." }, diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index f3f92a887e..5f39cdfd45 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -116,6 +116,16 @@ const GROUPS = [ }, propertyID: "primitiveMode", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { + none: "None", + yaw: "Yaw", + full: "Full" + }, + propertyID: "billboardMode", + }, { label: "Render With Zones", type: "multipleZonesSelection", @@ -229,13 +239,6 @@ const GROUPS = [ decimals: 2, propertyID: "textEffectThickness", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "textBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Top Margin", type: "number-draggable", @@ -718,13 +721,6 @@ const GROUPS = [ subLabels: [ "x", "y", "w", "h" ], propertyID: "subImage", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "imageBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Keep Aspect Ratio", type: "bool", @@ -774,13 +770,6 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, - { - label: "Billboard Mode", - type: "dropdown", - options: { none: "None", yaw: "Yaw", full: "Full"}, - propertyID: "webBillboardMode", - propertyName: "billboardMode", // actual entity property name - }, { label: "Input Mode", type: "dropdown", From 54d57afdae8f952152c8ca6a667521318a284125 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 21 Jan 2021 19:21:38 -0800 Subject: [PATCH 09/11] use rotation property to determine which axis is facing you --- interface/src/Application.cpp | 4 ++-- libraries/entities/src/EntityItemProperties.cpp | 3 ++- libraries/entities/src/EntityTree.cpp | 7 +++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e38d156336..bad0b6a3aa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2462,7 +2462,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo glm::vec3 dPosition = frustumPos - position; // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + glm::quat result = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)) * rotation; if (rotate90x) { result *= ROTATE_90X; } @@ -2475,7 +2475,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // make sure s is not NaN for any component if (glm::length2(s) > 0.0f) { - glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))); + glm::quat result = glm::conjugate(glm::toQuat(glm::lookAt(frustumPos, position, avatarUP))) * rotation; if (rotate90x) { result *= ROTATE_90X; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 870ed09515..1e771d8e43 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -811,7 +811,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within * one of the zones in this list. - * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. + * @property {BillboardMode} billboardMode="none" - Whether the entity is billboarded to face the camera. Use the rotation + * property to control which axis is facing you. * * @property {Entities.Grab} grab - The entity's grab-related properties. * diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 3ed1ad581c..eeb42626c2 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3141,6 +3141,13 @@ bool EntityTree::readFromMap(QVariantMap& map, const bool isImport) { } } + // Before, billboarded entities ignored rotation. Now, they use it to determine which axis is facing you. + if (contentVersion < (int)EntityVersion::AllBillboardMode) { + if (properties.getBillboardMode() != BillboardMode::NONE) { + properties.setRotation(glm::quat()); + } + } + EntityItemPointer entity = addEntity(entityItemID, properties, isImport); if (!entity) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); From 19cd0fa6ad7cb965ce4930e3b9783fbd7a860a63 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 29 Jan 2021 22:31:17 -0800 Subject: [PATCH 10/11] CR --- interface/src/Application.cpp | 3 ++- interface/src/avatar/AvatarManager.cpp | 3 ++- libraries/entities/src/EntityItem.h | 2 +- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- libraries/shared/src/BillboardMode.cpp | 17 ++++++++++++++++- libraries/shared/src/BillboardMode.h | 8 +++++--- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bad0b6a3aa..79a8714dfe 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,7 +2455,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { + BillboardModeHelpers::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, + BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x) { const glm::quat ROTATE_90X = glm::angleAxis(-(float)M_PI_2, Vectors::RIGHT); if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 24d9379ab9..91d339a38d 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -843,7 +843,8 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersectionVector(const Pic BoxFace subMeshFace = BoxFace::UNKNOWN_FACE; glm::vec3 subMeshSurfaceNormal; QVariantMap subMeshExtraInfo; - if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { + if (avatar->getSkeletonModel()->findRayIntersectionAgainstSubMeshes(defaultFrameRayOrigin, defaultFrameRayDirection, viewFrustumPos, subMeshDistance, + subMeshFace, subMeshSurfaceNormal, subMeshExtraInfo, true, false)) { rayAvatarResult._distance = subMeshDistance; rayAvatarResult._intersectionPoint = ray.origin + subMeshDistance * rayDirection; rayAvatarResult._intersectionNormal = subMeshSurfaceNormal; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 2acb73abbf..60214cdf87 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -180,7 +180,7 @@ public: QVariantMap& extraInfo, bool precisionPicking) const { return true; } virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, + float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { return true; } // attributes applicable to all entity types diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2d07fec8bf..8ba5be54e6 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -292,7 +292,7 @@ Item::Bound ModelMeshPartPayload::getBound(RenderArgs* args) const { if (material && material->isProcedural() && material->isReady()) { auto procedural = std::static_pointer_cast(_drawMaterials.top().material); if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(args); + return procedural->getBound(args); } } diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index 8243cf772d..d8d1b64f65 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -15,9 +15,24 @@ const char* billboardModeNames[] = { }; static const size_t BILLBOARD_MODE_NAMES = (sizeof(billboardModeNames) / sizeof(billboardModeNames[0])); -std::function BillboardModeHelpers::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; +std::function BillboardModeHelpers::_getBillboardRotationOperator = + [](const glm::vec3&, const glm::quat& rotation, BillboardMode, const glm::vec3&, bool) { return rotation; }; std::function BillboardModeHelpers::_getPrimaryViewFrustumPositionOperator = []() { return glm::vec3(0.0f); }; +void BillboardModeHelpers::setBillboardRotationOperator(std::function getBillboardRotationOperator) { + _getBillboardRotationOperator = getBillboardRotationOperator; +} + +glm::quat BillboardModeHelpers::getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, + const glm::vec3& frustumPos, bool rotate90x = false) { + return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); +} + +void BillboardModeHelpers::setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { + _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; +} + QString BillboardModeHelpers::getNameForBillboardMode(BillboardMode mode) { if (((int)mode <= 0) || ((int)mode >= (int)BILLBOARD_MODE_NAMES)) { mode = (BillboardMode)0; diff --git a/libraries/shared/src/BillboardMode.h b/libraries/shared/src/BillboardMode.h index 31f11766d8..4d123c0603 100644 --- a/libraries/shared/src/BillboardMode.h +++ b/libraries/shared/src/BillboardMode.h @@ -43,9 +43,11 @@ class BillboardModeHelpers { public: static QString getNameForBillboardMode(BillboardMode mode); - static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } - static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos, bool rotate90x = false) { return _getBillboardRotationOperator(position, rotation, billboardMode, frustumPos, rotate90x); } - static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator) { _getPrimaryViewFrustumPositionOperator = getPrimaryViewFrustumPositionOperator; } + static void setBillboardRotationOperator(std::function getBillboardRotationOperator); + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, + const glm::vec3& frustumPos, bool rotate90x = false); + static void setPrimaryViewFrustumPositionOperator(std::function getPrimaryViewFrustumPositionOperator); static glm::vec3 getPrimaryViewFrustumPosition() { return _getPrimaryViewFrustumPositionOperator(); } private: From 4554aa338b1a3157711df499cf5c11fcf5eb86d7 Mon Sep 17 00:00:00 2001 From: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com> Date: Sat, 30 Jan 2021 00:28:25 -0800 Subject: [PATCH 11/11] Update BillboardMode.cpp --- libraries/shared/src/BillboardMode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/BillboardMode.cpp b/libraries/shared/src/BillboardMode.cpp index d8d1b64f65..6cc6dca976 100644 --- a/libraries/shared/src/BillboardMode.cpp +++ b/libraries/shared/src/BillboardMode.cpp @@ -25,7 +25,7 @@ void BillboardModeHelpers::setBillboardRotationOperator(std::function