From 2a27fc4de2344b877920cbe8dbe3427cfe794073 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 13 Jan 2021 22:31:21 -0800 Subject: [PATCH] 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 -