Merge pull request #7319 from samcake/red

Supporting RenderItems being added Outside the RenderSpatialTree volume
This commit is contained in:
Brad Hefta-Gaub 2016-03-11 08:34:50 -08:00
commit d5c8e69c48
3 changed files with 65 additions and 13 deletions

View file

@ -96,6 +96,9 @@ void Scene::processPendingChangesQueue() {
// removes
removeItems(consolidatedPendingChanges._removedItems);
// Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID);
// ready to go back to rendering activities
_itemsMutex.unlock();
}

View file

@ -264,12 +264,33 @@ Octree::Index Octree::accessCellBrick(Index cellID, const CellBrickAccessor& acc
return brickID;
}
Octree::Location ItemSpatialTree::evalLocation(const AABox& bound, Coord3f& minCoordf, Coord3f& maxCoordf) const {
minCoordf = evalCoordf(bound.getMinimumPoint());
maxCoordf = evalCoordf(bound.getMaximumPoint());
// If the bound crosses any of the octree volume limit, then return root cell
if ( (minCoordf.x < 0.0f)
|| (minCoordf.y < 0.0f)
|| (minCoordf.z < 0.0f)
|| (maxCoordf.x >= _size)
|| (maxCoordf.y >= _size)
|| (maxCoordf.z >= _size)) {
return Location();
}
Coord3 minCoord(minCoordf);
Coord3 maxCoord(maxCoordf);
return Location::evalFromRange(minCoord, maxCoord);
}
Octree::Locations ItemSpatialTree::evalLocations(const ItemBounds& bounds) const {
Locations locations;
Coord3f minCoordf, maxCoordf;
locations.reserve(bounds.size());
for (auto& bound : bounds) {
if (!bound.bound.isNull()) {
locations.emplace_back(evalLocation(bound.bound));
locations.emplace_back(evalLocation(bound.bound, minCoordf, maxCoordf));
} else {
locations.emplace_back(Location());
}
@ -344,11 +365,8 @@ bool ItemSpatialTree::removeItem(Index cellIdx, const ItemKey& key, const ItemID
ItemSpatialTree::Index ItemSpatialTree::resetItem(Index oldCell, const ItemKey& oldKey, const AABox& bound, const ItemID& item, ItemKey& newKey) {
auto newCell = INVALID_CELL;
if (!newKey.isViewSpace()) {
auto minCoordf = evalCoordf(bound.getMinimumPoint());
auto maxCoordf = evalCoordf(bound.getMaximumPoint());
Coord3 minCoord(minCoordf);
Coord3 maxCoord(maxCoordf);
auto location = Location::evalFromRange(minCoord, maxCoord);
Coord3f minCoordf, maxCoordf;
auto location = evalLocation(bound, minCoordf, maxCoordf);
// Compare range size vs cell location size and tag itemKey accordingly
// If Item bound fits in sub cell then tag as small
@ -403,7 +421,21 @@ ItemSpatialTree::Index ItemSpatialTree::resetItem(Index oldCell, const ItemKey&
int Octree::select(CellSelection& selection, const FrustumSelector& selector) const {
Index cellID = ROOT_CELL;
return selectTraverse(cellID, selection, selector);
auto cell = getConcreteCell(cellID);
int numSelectedsIn = (int)selection.size();
// Always include the root cell partially containing potentially outer objects
selectCellBrick(cellID, selection, false);
// then traverse deeper
for (int i = 0; i < NUM_OCTANTS; i++) {
Index subCellID = cell.child((Link)i);
if (subCellID != INVALID_CELL) {
selectTraverse(subCellID, selection, selector);
}
}
return (int)selection.size() - numSelectedsIn;
}

View file

@ -117,7 +117,6 @@ namespace render {
return depth;
}
class Location {
void assertValid() {
assert((pos.x >= 0) && (pos.y >= 0) && (pos.z >= 0));
@ -157,6 +156,7 @@ namespace render {
// Eval the location best fitting the specified range
static Location evalFromRange(const Coord3& minCoord, const Coord3& maxCoord, Depth rangeDepth = MAX_DEPTH);
// Eval the intersection test against a frustum
enum Intersection {
Outside = 0,
@ -398,10 +398,26 @@ namespace render {
return getOrigin() + glm::vec3(coord) * cellWidth;
}
// Clamp a 3D relative position to make sure it is in the valid range space of the octree
glm::vec3 clampRelPosToTreeRange(const glm::vec3& pos) const {
const float EPSILON = 0.0001f;
return glm::vec3(
std::min(std::max(pos.x, 0.0f), _size - EPSILON),
std::min(std::max(pos.y, 0.0f), _size - EPSILON),
std::min(std::max(pos.z, 0.0f), _size - EPSILON));
}
// Eval an integer cell coordinate (at the specified deepth) from a given 3d position
// If the 3D position is out of the octree volume, then the position is clamped
// so the integer coordinate is meaningfull
Coord3 evalCoord(const glm::vec3& pos, Depth depth = Octree::METRIC_COORD_DEPTH) const {
auto npos = (pos - getOrigin());
auto npos = clampRelPosToTreeRange((pos - getOrigin()));
return Coord3(npos * getInvCellWidth(depth)); // Truncate fractional part
}
// Eval a real cell coordinate (at the specified deepth) from a given 3d position
// Position is NOT clamped to the boundaries of the octree so beware of conversion to a Coord3!
Coord3f evalCoordf(const glm::vec3& pos, Depth depth = Octree::METRIC_COORD_DEPTH) const {
auto npos = (pos - getOrigin());
return Coord3f(npos * getInvCellWidth(depth));
@ -412,9 +428,10 @@ namespace render {
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()));
}
// Eval the cell location for a given arbitrary Bound,
// if the Bound crosses any of the Octree planes then the root cell is returned
Location evalLocation(const AABox& bound, Coord3f& minCoordf, Coord3f& maxCoordf) const;
Locations evalLocations(const ItemBounds& bounds) const;
// Managing itemsInserting items in cells