From 59434e1ea9f53a62d9b3ad49ec41e2b7aba59878 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 29 Jan 2016 18:16:45 -0800 Subject: [PATCH] DDisplay of the octree cells is working, added the Brick empty / full per cell --- .../render/src/render/DrawSceneOctree.cpp | 12 ++-- libraries/render/src/render/DrawStatus.cpp | 20 +++++++ libraries/render/src/render/DrawStatus.h | 6 +- libraries/render/src/render/Octree.cpp | 55 ++++++++++--------- libraries/render/src/render/Octree.h | 23 ++++++-- libraries/render/src/render/Scene.cpp | 35 ++++++++++-- .../render/src/render/drawCellBounds.slv | 7 ++- .../render/src/render/drawItemBounds.slf | 5 +- .../render/src/render/drawItemBounds.slv | 26 ++++++--- 9 files changed, 132 insertions(+), 57 deletions(-) diff --git a/libraries/render/src/render/DrawSceneOctree.cpp b/libraries/render/src/render/DrawSceneOctree.cpp index 1a89aa3275..55e0506a1d 100644 --- a/libraries/render/src/render/DrawSceneOctree.cpp +++ b/libraries/render/src/render/DrawSceneOctree.cpp @@ -42,9 +42,7 @@ const gpu::PipelinePointer DrawSceneOctree::getDrawCellBoundsPipeline() { state->setDepthTest(true, false, gpu::LESS_EQUAL); // Blend on transparent - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); // Good to go add the brand new pipeline _drawCellBoundsPipeline = gpu::Pipeline::create(program, state); @@ -99,9 +97,13 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext, const auto& inCells = scene->getSpatialTree()._cells; - for (int i = 0; i < nbCells; i++) { - auto& cellLoc = inCells[i].getlocation(); + for (const auto& cell: inCells ) { + auto cellLoc = cell.getlocation(); + glm::ivec4 cellLocation(cellLoc.pos.x, cellLoc.pos.y, cellLoc.pos.z, cellLoc.depth); + if (cell.isBrickEmpty() || !cell.hasBrick()) { + cellLocation.w *= -1; + } batch._glUniform4iv(_drawCellLocationLoc, 1, ((const int*)(&cellLocation))); diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 9ffb444e8e..584f41499a 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -43,6 +43,7 @@ const gpu::PipelinePointer DrawStatus::getDrawItemBoundsPipeline() { _drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); _drawItemBoundDimLoc = program->getUniforms().findLocation("inBoundDim"); + _drawItemCellLocLoc = program->getUniforms().findLocation("inCellLocation"); auto state = std::make_shared(); @@ -121,11 +122,17 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, if (!_itemStatus) { _itemStatus = std::make_shared();; } + if (!_itemCells) { + _itemCells = std::make_shared();; + } _itemBounds->resize((inItems.size() * sizeof(AABox))); _itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4))); + _itemCells->resize((inItems.size() * sizeof(Octree::Location))); + AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); for (auto& item : inItems) { if (!item.bound.isInvalid()) { if (!item.bound.isNull()) { @@ -133,8 +140,12 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, } else { (*itemAABox).setBox(item.bound.getCorner(), 0.1f); } + + auto& itemScene = scene->getItem(item.id); + (*itemCell) = scene->getSpatialTree().getCellLocation(itemScene.getCell()); + auto itemStatusPointer = itemScene.getStatus(); if (itemStatusPointer) { // Query the current status values, this is where the statusGetter lambda get called @@ -159,6 +170,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, nbItems++; itemAABox++; + itemCell++; } } } @@ -184,6 +196,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + Octree::Location* itemCell = reinterpret_cast (_itemCells->editData()); const unsigned int VEC3_ADRESS_OFFSET = 3; @@ -191,8 +204,15 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); + + + glm::ivec4 cellLocation(itemCell->pos.x, itemCell->pos.y, itemCell->pos.z, itemCell->depth); + + batch._glUniform4iv(_drawItemCellLocLoc, 1, ((const int*)(&cellLocation))); + batch.draw(gpu::LINES, 24, 0); + itemCell++; } } diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index f33193c808..263ebc2548 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -21,11 +21,11 @@ namespace render { Q_PROPERTY(bool showDisplay MEMBER showDisplay WRITE setShowDisplay) Q_PROPERTY(bool showNetwork MEMBER showNetwork WRITE setShowNetwork) public: - DrawStatusConfig() : Job::Config(false) {} + DrawStatusConfig() : Job::Config(true) {} // FIXME FOR debug void dirtyHelper(); - bool showDisplay{ false }; + bool showDisplay{ true }; // FIXME FOR debug bool showNetwork{ false }; public slots: @@ -59,6 +59,7 @@ namespace render { int _drawItemBoundPosLoc = -1; int _drawItemBoundDimLoc = -1; + int _drawItemCellLocLoc = -1; int _drawItemStatusPosLoc = -1; int _drawItemStatusDimLoc = -1; int _drawItemStatusValue0Loc = -1; @@ -68,6 +69,7 @@ namespace render { gpu::PipelinePointer _drawItemBoundsPipeline; gpu::PipelinePointer _drawItemStatusPipeline; gpu::BufferPointer _itemBounds; + gpu::BufferPointer _itemCells; gpu::BufferPointer _itemStatus; gpu::TexturePointer _statusIconMap; }; diff --git a/libraries/render/src/render/Octree.cpp b/libraries/render/src/render/Octree.cpp index 0b638db3ae..65187f1e4a 100644 --- a/libraries/render/src/render/Octree.cpp +++ b/libraries/render/src/render/Octree.cpp @@ -73,7 +73,7 @@ Octree::Indices Octree::indexConcreteCellPath(const Locations& path) const { for (int l = 1; l < path.size(); l++) { auto& location = path[l]; - auto nextIndex = getCell(currentIndex).child(location.octant()); + auto nextIndex = getConcreteCell(currentIndex).child(location.octant()); if (nextIndex == INVALID) { break; } @@ -133,8 +133,8 @@ Octree::Index Octree::allocateBrick() { Octree::Index Octree::accessCellBrick(Index cellID, const CellBrickAccessor& accessor, bool createBrick) { assert(cellID != INVALID); - auto cell = editCell(cellID); - if (!cell.asBrick()) { + auto& cell = editCell(cellID); + if (!cell.hasBrick()) { if (!createBrick) { return INVALID; } @@ -146,7 +146,7 @@ Octree::Index Octree::accessCellBrick(Index cellID, const CellBrickAccessor& acc auto& brick = _bricks[brickID]; // execute the accessor - accessor(brick, brickID); + accessor(cell, brick, brickID); return brickID; } @@ -164,13 +164,11 @@ Octree::Locations ItemSpatialTree::evalLocations(const ItemBounds& bounds) const return locations; } -ItemSpatialTree::Index ItemSpatialTree::insertItem(const Location& location, const ItemID& item) { - // Go to the cell - auto cellIdx = indexCell(location); - +ItemSpatialTree::Index ItemSpatialTree::insertItem(Index cellIdx, const ItemID& item) { // Add the item to the brick (and a brick if needed) - accessCellBrick(cellIdx, [&](Brick& brick, Octree::Index cellID) { + auto brickID = accessCellBrick(cellIdx, [&](Cell& cell, Brick& brick, Octree::Index cellID) { brick.items.push_back(item); + cell.signalBrickFilled(); }, true); return cellIdx; @@ -180,9 +178,12 @@ bool ItemSpatialTree::removeItem(Index cellIdx, const ItemID& item) { auto success = false; // Access the brick at the cell (without createing new ones) - auto brickIdx = accessCellBrick(cellIdx, [&](Brick& brick, Octree::Index brickID) { + accessCellBrick(cellIdx, [&](Cell& cell, Brick& brick, Octree::Index brickID) { // remove the item from the list brick.items.erase(std::find(brick.items.begin(), brick.items.end(), item)); + if (brick.items.empty()) { + cell.signalBrickEmpty(); + } success = true; }, false); // do not create brick! @@ -190,25 +191,27 @@ bool ItemSpatialTree::removeItem(Index cellIdx, const ItemID& item) { } ItemSpatialTree::Index ItemSpatialTree::resetItem(Index oldCell, const Location& location, const ItemID& item) { - // do we know about this item ? - if (oldCell == Item::INVALID_CELL) { - auto newCell = insertItem(location, item); - return newCell; - } else { - auto newCell = indexCell(location); + auto newCell = indexCell(location); - accessCellBrick(newCell, [&](Brick& brick, Octree::Index brickID) { - // insert the item only if the new cell is different from the previous one - if (newCell != oldCell) { - brick.items.push_back(item); - } + // Early exit if nothing changed + if (newCell == oldCell) { + return newCell; + } + // do we know about this item ? + else if (oldCell == Item::INVALID_CELL) { + insertItem(newCell, item); + return newCell; + } + // A true update of cell is required + else { + // Add the item to the brick (and a brick if needed) + accessCellBrick(newCell, [&](Cell& cell, Brick& brick, Octree::Index cellID) { + brick.items.push_back(item); + cell.signalBrickFilled(); }, true); - // now we know where the cell has been added and where it was, - // if different then go clean the previous cell - if (newCell != oldCell) { - removeItem(oldCell, item); - } + // And remove it from the previous one + removeItem(oldCell, item); return newCell; } diff --git a/libraries/render/src/render/Octree.h b/libraries/render/src/render/Octree.h index 7d3cce9267..bd54a297b0 100644 --- a/libraries/render/src/render/Octree.h +++ b/libraries/render/src/render/Octree.h @@ -162,8 +162,11 @@ namespace render { void setChild(Link octant, Index child) { _links[octant] = child; } Index brick() const { return _links[BrickLink]; } - bool asBrick() const { return _links[BrickLink] != INVALID; } + bool hasBrick() const { return _links[BrickLink] != INVALID; } void setBrick(Index brick) { _links[BrickLink] = brick; } + void signalBrickFilled() { _location.spare = 1; } + void signalBrickEmpty() { _location.spare = 0; } + bool isBrickEmpty() const { return _location.spare == 0; } Cell() : _links({ { INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID } }) @@ -198,8 +201,16 @@ namespace render { // the returned indices stops at the last existing cell on the requested path. Indices indexConcreteCellPath(const Locations& path) const; + // Get the cell location from the CellID + Location getCellLocation(Index cellID) const { + if ((cellID >= 0) && (cellID < _cells.size())) { + return getConcreteCell(cellID).getlocation(); + } + return Location(); + } + // Reach a concrete cell - const Cell& getCell(Index index) const { + const Cell& getConcreteCell(Index index) const { assert(index < _cells.size()); return _cells[index]; } @@ -207,14 +218,14 @@ namespace render { // Let s talk about the Cell Bricks now - using CellBrickAccessor = std::function; + using CellBrickAccessor = std::function; // acces a cell (must be concrete), then call the brick accessor if the brick exists ( or is just created if authorized to) // This returns the Brick index Index accessCellBrick(Index cellID, const CellBrickAccessor& accessor, bool createBrick = true); - const Brick& getBrick(Index index) const { + const Brick& getConcreteBrick(Index index) const { assert(index < _bricks.size()); return _bricks[index]; } @@ -272,8 +283,10 @@ namespace render { Locations evalLocations(const ItemBounds& bounds) const; // Managing itemsInserting items in cells - Index insertItem(const Location& location, const ItemID& item); + // Cells need to have been allocated first calling indexCell + Index insertItem(Index cellIdx, const ItemID& item); bool removeItem(Index cellIdx, const ItemID& item); + Index resetItem(Index oldCell, const Location& location, const ItemID& item); ItemSpatialTree() {} diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 241f23e290..78defa4c81 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -155,15 +155,38 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { void Scene::removeItems(const ItemIDs& ids) { for (auto removedID :ids) { - _masterBucketMap.erase(removedID, _items[removedID].getKey()); - _items[removedID].kill(); + // Access the true item + auto& item = _items[removedID]; + + // Remove from Bucket map + _masterBucketMap.erase(removedID, item.getKey()); + + // Remove from spatial tree + _masterSpatialTree.removeItem(item.getCell(), removedID); + + // Kill it + item.kill(); } } void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { - auto updateID = ids.begin(); - auto updateFunctor = functors.begin(); - for (;updateID != ids.end(); updateID++, updateFunctor++) { - _items[(*updateID)].update((*updateFunctor)); + + auto& updateFunctor = functors.begin(); + for (auto updateID : ids) { + // Access the true item + auto& item = _items[updateID]; + auto oldCell = item.getCell(); + + // Update it + _items[updateID].update((*updateFunctor)); + + // Update the citem in the spatial tree if needed + // THis could be avoided if we + auto newCellLocation = _masterSpatialTree.evalLocation(item.getBound()); + auto newCell = _masterSpatialTree.resetItem(oldCell, newCellLocation, updateID); + item.resetCell(newCell); + + // next loop + updateFunctor++; } } diff --git a/libraries/render/src/render/drawCellBounds.slv b/libraries/render/src/render/drawCellBounds.slv index 13b0c465d5..628d44c0b2 100644 --- a/libraries/render/src/render/drawCellBounds.slv +++ b/libraries/render/src/render/drawCellBounds.slv @@ -18,7 +18,6 @@ <@include gpu/Color.slh@> <$declareColorWheel()$> - <@include SceneOctree.slh@> uniform ivec4 inCellLocation; @@ -53,7 +52,9 @@ void main(void) { ); vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - vec4 cellBound = evalBound(inCellLocation); + int cellIsEmpty = sign(inCellLocation.w); + ivec4 cellLocation = ivec4(inCellLocation.xyz, (inCellLocation.w < 0 ? -inCellLocation.w : inCellLocation.w)); + vec4 cellBound = evalBound(cellLocation); pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz; @@ -62,5 +63,5 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(inCellLocation.w) / 5.0)), 1.0); + varColor = vec4(colorWheel(fract(float(inCellLocation.w) / 5.0)), 0.5 + 0.4 * cellIsEmpty); } \ No newline at end of file diff --git a/libraries/render/src/render/drawItemBounds.slf b/libraries/render/src/render/drawItemBounds.slf index 16a8fd6165..6f5db0a6c2 100644 --- a/libraries/render/src/render/drawItemBounds.slf +++ b/libraries/render/src/render/drawItemBounds.slf @@ -12,9 +12,12 @@ // in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; void main(void) { - outFragColor = vec4(1.0, 0.5, 0.0, 1.0); + float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); + + outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); } diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv index 7b69370f13..08c5fc7ed4 100644 --- a/libraries/render/src/render/drawItemBounds.slv +++ b/libraries/render/src/render/drawItemBounds.slv @@ -13,22 +13,28 @@ // <@include gpu/Transform.slh@> - <$declareStandardTransform()$> +<@include gpu/Color.slh@> +<$declareColorWheel()$> + uniform vec3 inBoundPos; uniform vec3 inBoundDim; +uniform ivec4 inCellLocation; + +out vec4 varColor; +out vec2 varTexcoord; void main(void) { const vec4 UNIT_BOX[8] = vec4[8]( - vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 2.0), vec4(0.0, 0.0, 1.0, 1.0), - vec4(1.0, 0.0, 1.0, 1.0), - vec4(0.0, 1.0, 1.0, 1.0), - vec4(1.0, 1.0, 1.0, 1.0) + vec4(1.0, 0.0, 1.0, 2.0), + vec4(0.0, 1.0, 1.0, 2.0), + vec4(1.0, 1.0, 1.0, 3.0) ); const int UNIT_BOX_LINE_INDICES[24] = int[24]( 0, 1, @@ -44,14 +50,16 @@ void main(void) { 0, 4, 1, 5 ); - vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; + vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; - pos.xyz = inBoundPos + inBoundDim * pos.xyz; + vec4 pos = vec4(inBoundPos + inBoundDim * cubeVec.xyz, 1.0); // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - // varTexcoord = (pos.xy + 1) * 0.5; + varColor = vec4(colorWheel(fract(float(inCellLocation.w) / 5.0)), 1.0); + varTexcoord = vec2(cubeVec.w, length(inBoundDim)); + } \ No newline at end of file