summaryrefslogtreecommitdiffstats
path: root/src/render/jobs/calcboundingvolumejob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/jobs/calcboundingvolumejob.cpp')
-rw-r--r--src/render/jobs/calcboundingvolumejob.cpp96
1 files changed, 66 insertions, 30 deletions
diff --git a/src/render/jobs/calcboundingvolumejob.cpp b/src/render/jobs/calcboundingvolumejob.cpp
index 66d59f812..113dc34ce 100644
--- a/src/render/jobs/calcboundingvolumejob.cpp
+++ b/src/render/jobs/calcboundingvolumejob.cpp
@@ -51,6 +51,7 @@
#include <Qt3DRender/private/buffer_p.h>
#include <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/private/buffervisitor_p.h>
+#include <Qt3DRender/private/entityaccumulator_p.h>
#include <QtCore/qmath.h>
#if QT_CONFIG(concurrent)
@@ -65,23 +66,14 @@ namespace Render {
namespace {
-void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node);
-
-struct UpdateBoundFunctor {
- NodeManagers *manager;
-
- void operator ()(Qt3DRender::Render::Entity *node)
- {
- calculateLocalBoundingVolume(manager, node);
- }
-};
-
class BoundingVolumeCalculator
{
public:
BoundingVolumeCalculator(NodeManagers *manager) : m_manager(manager) { }
const Sphere& result() { return m_volume; }
+ const QVector3D min() const { return m_min; }
+ const QVector3D max() const { return m_max; }
bool apply(Qt3DRender::Render::Attribute *positionAttribute,
Qt3DRender::Render::Attribute *indexAttribute,
@@ -95,6 +87,9 @@ public:
return false;
}
+ m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
+ m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
+
// Calculate squared distance for the pairs of points
const float xDist2 = (findExtremePoints.xMaxPt - findExtremePoints.xMinPt).lengthSquared();
const float yDist2 = (findExtremePoints.yMaxPt - findExtremePoints.yMinPt).lengthSquared();
@@ -127,6 +122,8 @@ public:
private:
Sphere m_volume;
NodeManagers *m_manager;
+ QVector3D m_min;
+ QVector3D m_max;
class FindExtremePoints : public Buffer3fVisitor
{
@@ -191,17 +188,20 @@ private:
};
};
-void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
+QVector<Geometry *> calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
{
// The Bounding volume will only be computed if the position Buffer
// isDirty
+ QVector<Geometry *> updatedGeometries;
+
if (!node->isTreeEnabled())
- return;
+ return updatedGeometries;
GeometryRenderer *gRenderer = node->renderComponent<GeometryRenderer>();
+ GeometryManager *geometryManager = manager->geometryManager();
if (gRenderer && gRenderer->primitiveType() != QGeometryRenderer::Patches) {
- Geometry *geom = manager->lookupResource<Geometry, GeometryManager>(gRenderer->geometryId());
+ Geometry *geom = geometryManager->lookupResource(gRenderer->geometryId());
if (geom) {
int drawVertexCount = gRenderer->vertexCount(); // may be 0, gets changed below if so
@@ -224,14 +224,14 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
|| positionAttribute->vertexBaseType() != QAttribute::Float
|| positionAttribute->vertexSize() < 3) {
qWarning("calculateLocalBoundingVolume: Position attribute not suited for bounding volume computation");
- return;
+ return updatedGeometries;
}
Buffer *buf = manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId());
// No point in continuing if the positionAttribute doesn't have a suitable buffer
if (!buf) {
qWarning("calculateLocalBoundingVolume: Position attribute not referencing a valid buffer");
- return;
+ return updatedGeometries;
}
// Check if there is an index attribute.
@@ -259,7 +259,7 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
std::end(validIndexTypes),
indexAttribute->vertexBaseType()) == std::end(validIndexTypes)) {
qWarning() << "calculateLocalBoundingVolume: Unsupported index attribute type" << indexAttribute->name() << indexAttribute->vertexBaseType();
- return;
+ return updatedGeometries;
}
break;
@@ -287,25 +287,38 @@ void calculateLocalBoundingVolume(NodeManagers *manager, Entity *node)
node->localBoundingVolume()->setCenter(reader.result().center());
node->localBoundingVolume()->setRadius(reader.result().radius());
node->unsetBoundingVolumeDirty();
+
+ // Record min/max vertex in Geometry
+ geom->updateExtent(reader.min(), reader.max());
+ // Mark geometry as requiring a call to update its frontend
+ updatedGeometries.push_back(geom);
}
}
}
}
-#if QT_CONFIG(concurrent)
- const QVector<Qt3DRender::Render::Entity *> children = node->children();
- if (children.size() > 1) {
- UpdateBoundFunctor functor;
- functor.manager = manager;
- QtConcurrent::blockingMap(children, functor);
- } else
-#endif
+ return updatedGeometries;
+}
+
+struct UpdateBoundFunctor
+{
+ NodeManagers *manager;
+
+ // This define is required to work with QtConcurrent
+ typedef QVector<Geometry *> result_type;
+ QVector<Geometry *> operator ()(Qt3DRender::Render::Entity *node)
{
- const auto children = node->children();
- for (Entity *child : children)
- calculateLocalBoundingVolume(manager, child);
+ return calculateLocalBoundingVolume(manager, node);
}
-}
+};
+
+struct ReduceUpdateBoundFunctor
+{
+ void operator ()(QVector<Geometry *> &result, const QVector<Geometry *> &values)
+ {
+ result += values;
+ }
+};
} // anonymous
@@ -318,7 +331,30 @@ CalculateBoundingVolumeJob::CalculateBoundingVolumeJob()
void CalculateBoundingVolumeJob::run()
{
- calculateLocalBoundingVolume(m_manager, m_node);
+ EntityAccumulator accumulator([](Entity *entity) {
+ return !entity->componentUuid<GeometryRenderer>().isNull();
+ }, m_manager);
+ auto entities = accumulator.apply(m_node);
+
+ QVector<Geometry *> updatedGeometries;
+ updatedGeometries.reserve(entities.size());
+
+#if QT_CONFIG(concurrent)
+ if (entities.size() > 1) {
+ UpdateBoundFunctor functor;
+ functor.manager = m_manager;
+ ReduceUpdateBoundFunctor reduceFunctor;
+ updatedGeometries += QtConcurrent::blockingMappedReduced<decltype(updatedGeometries)>(entities, functor, reduceFunctor);
+ } else
+#endif
+ {
+ for (Entity *child : entities)
+ updatedGeometries += calculateLocalBoundingVolume(m_manager, child);
+ }
+
+ // Send extent updates to frontend
+ for (Geometry *geometry : updatedGeometries)
+ geometry->notifyExtentChanged();
}
void CalculateBoundingVolumeJob::setRoot(Entity *node)