clening up the BRick insert item interface and the shaders

This commit is contained in:
samcake 2016-01-29 14:30:53 -08:00
parent 2a5aab6dc8
commit 7b50a4d05f
8 changed files with 192 additions and 104 deletions

View file

@ -34,9 +34,7 @@ const gpu::PipelinePointer DrawSceneOctree::getDrawCellBoundsPipeline() {
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
_drawBoundPosLoc = program->getUniforms().findLocation("inBoundPos");
_drawBoundDimLoc = program->getUniforms().findLocation("inBoundDim");
_drawCellLocationLoc = program->getUniforms().findLocation("inCellLocation");
auto state = std::make_shared<gpu::State>();
@ -69,10 +67,7 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
if (!_cells) {
_cells = std::make_shared<gpu::Buffer>();
}
/* if (!_octreeInfo) {
_octreeInfo = std::make_shared<gpu::Buffer>();;
}*/
const auto& inCells = scene->getSpatialTree()._cells;
_cells->resize(inCells.size() * sizeof(AABox));
AABox* cellAABox = reinterpret_cast<AABox*> (_cells->editData());
@ -102,15 +97,9 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
// bind the one gpu::Pipeline we need
batch.setPipeline(getDrawCellBoundsPipeline());
AABox* cellAABox = reinterpret_cast<AABox*> (_cells->editData());
const unsigned int VEC3_ADRESS_OFFSET = 3;
const auto& inCells = scene->getSpatialTree()._cells;
for (int i = 0; i < nbCells; i++) {
batch._glUniform3fv(_drawBoundPosLoc, 1, (const float*) (cellAABox + i));
batch._glUniform3fv(_drawBoundDimLoc, 1, ((const float*)(cellAABox + i)) + VEC3_ADRESS_OFFSET);
auto& cellLoc = inCells[i].getlocation();
glm::ivec4 cellLocation(cellLoc.pos.x, cellLoc.pos.y, cellLoc.pos.z, cellLoc.depth);

View file

@ -18,8 +18,6 @@
namespace render {
class DrawSceneOctree {
int _drawBoundPosLoc;
int _drawBoundDimLoc;
int _drawCellLocationLoc;
gpu::PipelinePointer _drawCellBoundsPipeline;
gpu::BufferPointer _cells;

View file

@ -191,6 +191,7 @@ inline QDebug operator<<(QDebug debug, const ItemFilter& me) {
}
using ItemID = uint32_t;
using ItemCell = int32_t;
class Item {
public:
@ -198,6 +199,7 @@ public:
typedef ItemID ID;
static const ID INVALID_ITEM_ID = 0;
static const ItemCell INVALID_CELL = -1;
// Bound is the AABBox fully containing this item
typedef AABox Bound;
@ -292,12 +294,16 @@ public:
// Main scene / item managment interface Reset/Update/Kill
void resetPayload(const PayloadPointer& payload);
void resetCell(ItemCell cell) { _cell = cell; }
void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Communicate update to the payload
void kill() { _payload.reset(); _key._flags.reset(); } // Kill means forget the payload and key
void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Kill means forget the payload and key and cell
// Check heuristic key
const ItemKey& getKey() const { return _key; }
// Check spatial cell
const ItemCell& getCell() const { return _cell; }
// Payload Interface
// Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace())
@ -318,6 +324,7 @@ public:
protected:
PayloadPointer _payload;
ItemKey _key;
ItemCell _cell{ INVALID_CELL };
friend class Scene;
};

View file

@ -67,7 +67,7 @@ Octree::Location Octree::Location::evalFromRange(const Coord3& minCoord, const C
}
}
Octree::Indices Octree::indexAllocatedCellPath(const Locations& path) const {
Octree::Indices Octree::indexConcreteCellPath(const Locations& path) const {
Index currentIndex = ROOT;
Indices cellPath(1, currentIndex);
@ -105,7 +105,7 @@ Octree::Index Octree::allocateCell(Index parent, const Location& location) {
Octree::Indices Octree::indexCellPath(const Locations& path) {
// First through the aallocated cells
Indices cellPath = indexAllocatedCellPath(path);
Indices cellPath = indexConcreteCellPath(path);
// Catch up from the last allocated cell on the path
auto currentIndex = cellPath.back();
@ -131,34 +131,86 @@ Octree::Index Octree::allocateBrick() {
return brickIdx;
}
Octree::Index Octree::accessCellBrick(const Location& loc, const CellBrickAccessor& accessor) {
auto cellId = indexCell(loc);
auto cell = editCell(cellId);
Octree::Index Octree::accessCellBrick(Index cellID, const CellBrickAccessor& accessor, bool createBrick) {
assert(cellID != INVALID);
auto cell = editCell(cellID);
if (!cell.asBrick()) {
if (!createBrick) {
return INVALID;
}
cell.setBrick(allocateBrick());
}
// access the brick
auto& brick = _bricks[cell.brick()];
auto brickID = cell.brick();
auto& brick = _bricks[brickID];
// execute the accessor
accessor(brick, cell.brick());
accessor(brick, brickID);
return cell.brick();
return brickID;
}
void ItemSpatialTree::insert(const ItemBounds& items) {
for (auto& item : items) {
if (!item.bound.isNull()) {
auto cellIdx = indexCell(evalLocation(item.bound));
accessCellBrick(evalLocation(item.bound), [&] (Brick& brick, Octree::Index cellID) {
brick.items.push_back(item.id);
});
Octree::Locations ItemSpatialTree::evalLocations(const ItemBounds& bounds) const {
Locations locations;
locations.reserve(bounds.size());
for (auto& bound : bounds) {
if (!bound.bound.isNull()) {
locations.emplace_back(evalLocation(bound.bound));
} else {
locations.emplace_back(Location());
}
}
return locations;
}
ItemSpatialTree::Index ItemSpatialTree::insertItem(const Location& location, const ItemID& item) {
// Go to the cell
auto cellIdx = indexCell(location);
// Add the item to the brick (and a brick if needed)
accessCellBrick(cellIdx, [&](Brick& brick, Octree::Index cellID) {
brick.items.push_back(item);
}, true);
return cellIdx;
}
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) {
// remove the item from the list
brick.items.erase(std::find(brick.items.begin(), brick.items.end(), item));
success = true;
}, false); // do not create brick!
return success;
}
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);
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);
}
}, 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);
}
return newCell;
}
}
void ItemSpatialTree::erase(const ItemBounds& items) {
}

View file

@ -144,7 +144,7 @@ namespace render {
using Locations = Location::vector;
// Cell or Brick Indexing
using Index = int32_t;
using Index = ItemCell; // int32_t
static const Index INVALID = -1;
static const Index ROOT = 0;
using Indices = std::vector<Index>;
@ -194,9 +194,9 @@ namespace render {
Indices indexCellPath(const Locations& path);
Index indexCell(const Location& loc) { return indexCellPath(Location::pathTo(loc)).back(); }
// Same as indexCellPath except that NO cells are allocated,
// Same as indexCellPath except that NO cells are allocated, only the COncrete cells previously allocated
// the returned indices stops at the last existing cell on the requested path.
Indices indexAllocatedCellPath(const Locations& path) const;
Indices indexConcreteCellPath(const Locations& path) const;
// Reach a concrete cell
const Cell& getCell(Index index) const {
@ -209,7 +209,10 @@ namespace render {
// Let s talk about the Cell Bricks now
using CellBrickAccessor = std::function<void(Brick& brick, Index brickIdx)>;
Index accessCellBrick(const Location& loc, const CellBrickAccessor& accessor);
// 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 {
assert(index < _bricks.size());
@ -258,19 +261,22 @@ namespace render {
}
// Bound to Location
AABox evalBound(const Location& loc) const {
float cellWidth = getCellWidth(loc.depth);
return AABox(evalPos(loc.pos, cellWidth), cellWidth);
}
Location evalLocation(const AABox& bound) const {
return Location::evalFromRange(evalCoord(bound.getMinimumPoint()), evalCoord(bound.getMaximumPoint()));
}
Locations evalLocations(const ItemBounds& bounds) const;
// Managing itemsInserting items in cells
Index insertItem(const Location& location, const ItemID& item);
bool removeItem(Index cellIdx, const ItemID& item);
Index resetItem(Index oldCell, const Location& location, const ItemID& item);
ItemSpatialTree() {}
void insert(const ItemBounds& items);
void erase(const ItemBounds& items);
};
}

View file

@ -129,22 +129,28 @@ void Scene::processPendingChangesQueue() {
}
void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) {
auto resetID = ids.begin();
auto resetPayload = payloads.begin();
ItemBounds itemBounds;
itemBounds.reserve(ids.size());
for (;resetID != ids.end(); resetID++, resetPayload++) {
auto& item = _items[(*resetID)];
auto& resetPayload = payloads.begin();
for (auto resetID : ids) {
// Access the true item
auto& item = _items[resetID];
auto oldKey = item.getKey();
auto oldCell = item.getCell();
// Reset the item with a new payload
item.resetPayload(*resetPayload);
_masterBucketMap.reset((*resetID), oldKey, item.getKey());
// Reset the item in the Bucket map
_masterBucketMap.reset(resetID, oldKey, item.getKey());
itemBounds.emplace_back(ItemBound((*resetID), item.getBound()));
// Reset the item in the spatial tree
auto newCellLocation = _masterSpatialTree.evalLocation(item.getBound());
auto newCell = _masterSpatialTree.resetItem(oldCell, newCellLocation, resetID);
item.resetCell(newCell);
// next loop
resetPayload++;
}
_masterSpatialTree.insert(itemBounds);
}
void Scene::removeItems(const ItemIDs& ids) {

View file

@ -0,0 +1,76 @@
<!
// render/SceneOctree.slh
//
// Created by Sam Gateau on 1/29/16.
// Copyright 2016 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
!>
<@if not RENDER_OCTREE_SLH@>
<@def RENDER_OCTREE_SLH@>
const float _size = 32768.0;
const float _invSize = 1.0 / _size;
const vec3 _origin = vec3(-16384.0);
float getSize() { return _size; }
vec3 getOrigin() { return _origin; }
const int MAX_DEPTH = 15;
const float DEPTH_DIM[16] = float[16](
1.0,
2.0,
4.0,
8.0,
16.0,
32.0,
64.0,
128.0,
256.0,
512.0,
1024.0,
2048.0,
4096.0,
8192.0,
16384.0,
32768.0 );
const float INV_DEPTH_DIM[16] = float[16](
1.0,
1.0 / 2.0,
1.0 / 4.0,
1.0 / 8.0,
1.0 / 16.0,
1.0 / 32.0,
1.0 / 64.0,
1.0 / 128.0,
1.0 / 256.0,
1.0 / 512.0,
1.0 / 1024.0,
1.0 / 2048.0,
1.0 / 4096.0,
1.0 / 8192.0,
1.0 / 16384.0,
1.0 / 32768.0 );
int getDepthDimension(int depth) { return 1 << depth; }
float getDepthDimensionf(int depth) { return DEPTH_DIM[depth]; }
float getInvDepthDimension(int depth) { return INV_DEPTH_DIM[depth]; }
float getCellWidth(int depth) { return _size * getInvDepthDimension(depth); }
float getInvCellWidth(int depth) { return getDepthDimensionf(depth) * _invSize; }
vec3 evalPos(ivec3 coord, int depth = MAX_DEPTH) {
return getOrigin() + vec3(coord) * getCellWidth(depth);
}
vec3 evalPosDepthWidth(ivec3 coord, float cellWidth) {
return getOrigin() + vec3(coord) * cellWidth;
}
vec4 evalBound(ivec4 loc) {
float cellWidth = getCellWidth(loc.w);
return vec4(evalPosDepthWidth(loc.xyz, cellWidth), cellWidth);
}
<@endif@>

View file

@ -19,56 +19,8 @@
<@include gpu/Color.slh@>
<$declareColorWheel()$>
<!
uniform ivec4 inCellLocation;
<@include SceneOctree.slh@>
const float _size = 32768.0;
const float _invSize = 1.0 / _size;
const vec3 _origin = vec3(-16384.0);
float getSize() { return _size; }
vec3 getOrigin() { return _origin; }
const int MAX_DEPTH = 15;
const float INV_DEPTH_DIM[16] = float[16](
1.0,
1.0 / 2.0,
1.0 / 4.0,
1.0 / 8.0,
1.0 / 16.0,
1.0 / 32.0,
1.0 / 64.0,
1.0 / 128.0,
1.0 / 256.0,
1.0 / 512.0,
1.0 / 1024.0,
1.0 / 2048.0,
1.0 / 4096.0,
1.0 / 8192.0,
1.0 / 16384.0,
1.0 / 32768.0 );
int getDepthDimension(int depth) { return 1 << depth; }
float getInvDepthDimension(int depth) { return INV_DEPTH_DIM[depth]; }
float getCellWidth(int depth) { return _size * getInvDepthDimension(depth); }
float getInvCellWidth(int depth) { return float(getDepthDimension(depth)) * _invSize; }
vec3 evalPos(ivec3 coord, int depth = MAX_DEPTH) {
return getOrigin() + vec3(coord) * getCellWidth(depth);
}
vec3 evalPos(ivec3 coord, float cellWidth) {
return getOrigin() + vec3(coord) * cellWidth;
}
vec4 evalBound(ivec4 loc) {
float cellWidth = getCellWidth(loc.w);
return vec4(evalPos(loc.xyz, cellWidth), cellWidth);
}
!>
uniform vec3 inBoundPos;
uniform vec3 inBoundDim;
uniform ivec4 inCellLocation;
out vec4 varColor;
@ -101,7 +53,9 @@ void main(void) {
);
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
pos.xyz = inBoundPos + inBoundDim * pos.xyz;
vec4 cellBound = evalBound(inCellLocation);
pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz;
// standard transform
TransformCamera cam = getTransformCamera();