diff --git a/interface/src/Application.h b/interface/src/Application.h index 79a75eef43..fb262ad2aa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -348,6 +348,9 @@ public: void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond(); + + render::ScenePointer getMain3DScene() { return _main3DScene; } + render::EnginePointer getRenderEngine() { return _renderEngine; } signals: diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 6c7fa04a21..6a45b85271 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -12,4 +12,4 @@ find_package(Bullet REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) -link_hifi_libraries(shared gpu script-engine render-utils) +link_hifi_libraries(shared gpu script-engine render render-utils) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 0a16cedb70..b59ea7e7af 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -29,8 +29,11 @@ #include #include + #include "EntityTreeRenderer.h" +#include "RenderableEntityItem.h" + #include "RenderableBoxEntityItem.h" #include "RenderableLightEntityItem.h" #include "RenderableModelEntityItem.h" @@ -92,6 +95,10 @@ void EntityTreeRenderer::clear() { } OctreeRenderer::clear(); _entityScripts.clear(); + + // TODO/FIXME - this needs to be fixed... we need to clear all items out of the scene in this case. + qDebug() << "EntityTreeRenderer::clear() need to clear the scene... "; + } void EntityTreeRenderer::init() { @@ -474,6 +481,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptr_renderSide); @@ -509,7 +517,9 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { glPushMatrix(); renderArgs->_context->enqueueBatch(batch); glPopMatrix(); - + + renderArgs->_batch = nullptr; + // stats... _meshesConsidered = renderArgs->_meshesConsidered; _meshesRendered = renderArgs->_meshesRendered; @@ -693,35 +703,38 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) } } } + + // hack for models. :( + if (entityItem->getType() == EntityTypes::Model) { + // render entityItem + AABox entityBox = entityItem->getAABox(); - // render entityItem - AABox entityBox = entityItem->getAABox(); + // TODO: some entity types (like lights) might want to be rendered even + // when they are outside of the view frustum... + float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter()); - - bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; - if (!outOfView) { - bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); + bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE; + if (!outOfView) { + bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance); - if (bigEnoughToRender) { - renderProxies(entityItem, args); + if (bigEnoughToRender) { + renderProxies(entityItem, args); - Glower* glower = NULL; - if (entityItem->getGlowLevel() > 0.0f) { - glower = new Glower(args, entityItem->getGlowLevel()); - } - entityItem->render(args); - args->_itemsRendered++; - if (glower) { - delete glower; + Glower* glower = NULL; + if (entityItem->getGlowLevel() > 0.0f) { + glower = new Glower(args, entityItem->getGlowLevel()); + } + entityItem->render(args); + args->_itemsRendered++; + if (glower) { + delete glower; + } + } else { + args->_itemsTooSmall++; } } else { - args->_itemsTooSmall++; + args->_itemsOutOfView++; } - } else { - args->_itemsOutOfView++; } } } @@ -1048,10 +1061,34 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { checkAndCallUnload(entityID); } _entityScripts.remove(entityID); + + // here's where we remove the entity payload from the scene + + render::Scene::PendingChanges pendingChanges; + if (_entityToSceneItems.contains(entityID)) { + render::ItemID renderItem = _entityToSceneItems[entityID]; + pendingChanges.removeItem(renderItem); + _viewState->getMain3DScene()->enqueuePendingChanges(pendingChanges); + } } void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { checkAndCallPreload(entityID); + + // here's where we add the entity payload to the scene + + render::Scene::PendingChanges pendingChanges; + render::ItemID renderItem = _viewState->getMain3DScene()->allocateID(); + _entityToSceneItems[entityID] = renderItem; + EntityItemPointer entity = static_cast(_tree)->findEntityByID(entityID); + + auto renderData = RenderableEntityItem::Pointer(new RenderableEntityItem(entity)); + auto renderPayload = render::PayloadPointer(new RenderableEntityItem::Payload(renderData)); + + pendingChanges.resetItem(renderItem, renderPayload); + + _viewState->getMain3DScene()->enqueuePendingChanges(pendingChanges); + _viewState->getMain3DScene()->processPendingChangesQueue(); } void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) { @@ -1181,4 +1218,3 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons entityScriptB.property("collisionWithEntity").call(entityScriptA, args); } } - diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 888e8c1681..22d6703069 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -19,6 +19,7 @@ #include // for RayToEntityIntersectionResult #include #include +#include #include #include @@ -186,6 +187,8 @@ private: float _previousStageHour; int _previousStageDay; + QHash _entityToSceneItems; }; + #endif // hifi_EntityTreeRenderer_h diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp new file mode 100644 index 0000000000..355a004594 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -0,0 +1,38 @@ +// +// RenderableEntityItem.cpp +// interface/src +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#include "RenderableEntityItem.h" + +namespace render { + template <> const ItemKey payloadGetKey(const RenderableEntityItem::Pointer& payload) { + return ItemKey::Builder::opaqueShape(); + } + + template <> const Item::Bound payloadGetBound(const RenderableEntityItem::Pointer& payload) { + if (payload && payload->entity) { + return payload->entity->getAABox(); + } + return render::Item::Bound(); + } + template <> void payloadRender(const RenderableEntityItem::Pointer& payload, RenderArgs* args) { + if (args) { + args->_elementsTouched++; + if (payload && payload->entity) { + if (payload->entity->getType() != EntityTypes::Model) { + payload->entity->render(args); + } + } + } + } +} + + diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h new file mode 100644 index 0000000000..028bc5efa5 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -0,0 +1,33 @@ +// +// RenderableEntityItem.h +// interface/src +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderableEntityItem_h +#define hifi_RenderableEntityItem_h + +#include +#include + +class RenderableEntityItem { +public: + RenderableEntityItem(EntityItemPointer entity) : entity(entity) { } + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + EntityItemPointer entity; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const RenderableEntityItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const RenderableEntityItem::Pointer& payload); + template <> void payloadRender(const RenderableEntityItem::Pointer& payload, RenderArgs* args); +} + +#endif // hifi_RenderableEntityItem_h diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index a1447293b7..ff417da85e 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -15,6 +15,9 @@ #include #include +#include +#include + #include class Transform; @@ -60,6 +63,10 @@ public: virtual void postLambdaEvent(std::function f) = 0; virtual qreal getDevicePixelRatio() = 0; + virtual render::ScenePointer getMain3DScene() = 0; + virtual render::EnginePointer getRenderEngine() = 0; + + // FIXME - we shouldn't assume that there's a single instance of an AbstractViewStateInterface static AbstractViewStateInterface* instance(); static void setInstance(AbstractViewStateInterface* instance); }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 688fa31fe1..2c30d0e2f8 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -11,6 +11,12 @@ #include "DrawTask.h" +#include + +#include "gpu/Batch.h" +#include "gpu/Context.h" + + using namespace render; @@ -28,13 +34,20 @@ void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderCon auto& itemBucketMap = scene->getMasterBucket(); RenderArgs* args = renderContext->args; + gpu::Batch theBatch; + + args->_batch = &theBatch; + // render opaques auto filter = ItemFilter::Builder::opaqueShape(); auto& opaqueShapeItems = itemBucketMap.at(filter); - + for (auto id : opaqueShapeItems) { auto item = scene->getItem(id); item.render(args); } + + args->_context->enqueueBatch((*args->_batch)); + args->_batch = nullptr; }; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 5d4444c333..c7d112e74b 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -12,16 +12,17 @@ #ifndef hifi_render_Scene_h #define hifi_render_Scene_h -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include #include #include +#include +#include + +#include +#include namespace render { @@ -93,6 +94,13 @@ public: bool isPickable() const { return _flags[PICKABLE]; } }; +inline QDebug operator<<(QDebug debug, const ItemKey& itemKey) { + debug << "[ItemKey: isOpaque:" << itemKey.isOpaque() + << ", isStatic:" << itemKey.isStatic() + << ", isWorldSpace:" << itemKey.isWorldSpace() + << "]"; + return debug; +} class ItemFilter { public: @@ -153,6 +161,12 @@ public: }; }; +inline QDebug operator<<(QDebug debug, const ItemFilter& me) { + debug << "[ItemFilter: opaqueShape:" << me.test(ItemKey::Builder::opaqueShape()) + << "]"; + return debug; +} + class Item { public: typedef std::vector Vector; @@ -202,6 +216,12 @@ protected: friend class Scene; }; +inline QDebug operator<<(QDebug debug, const Item& item) { + debug << "[Item: _key:" << item.getKey() << ", bounds:" << item.getBound() << "]"; + return debug; +} + + // THe Payload class is the real Payload to be used // THis allow anything to be turned into a Payload as long as the required interface functions are available // When creating a new kind of payload from a new "stuff" class then you need to create specialized version for "stuff"