summaryrefslogtreecommitdiffstats
path: root/src/render/backend/trianglesextractor.cpp
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2015-12-10 15:58:05 +0000
committerMike Krus <mike.krus@kdab.com>2016-01-25 14:13:13 +0000
commit28ec1ca1883e0fe9b8b0e0de4049564ae652bd90 (patch)
tree3722809fc54b75d08b08fb68bd5d9d56fbe24342 /src/render/backend/trianglesextractor.cpp
parent4ad00b344bc79e34f2ba2f8355e65c7948791389 (diff)
Refactor picking to use one thread per entity
Added triangle visitor by refactor the triangle volume extractor Added ability to do a ray intersection with a single volume without using a thread Added entity collector Use one thread for each entity Ignore entities that don’t have a pick object Removed list of triangle volumes stored on each entity Use triangle visitor to test each triangle by creating a single volume on the stack Added triangle and 3 vertex index to the pick event Change-Id: Id3fd53549bf3ea07805426ef868df174f30e176b Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/backend/trianglesextractor.cpp')
-rw-r--r--src/render/backend/trianglesextractor.cpp447
1 files changed, 12 insertions, 435 deletions
diff --git a/src/render/backend/trianglesextractor.cpp b/src/render/backend/trianglesextractor.cpp
index 85eba29df..9e63c1c1e 100644
--- a/src/render/backend/trianglesextractor.cpp
+++ b/src/render/backend/trianglesextractor.cpp
@@ -35,11 +35,13 @@
****************************************************************************/
#include "trianglesextractor_p.h"
+#include <Qt3DCore/qentity.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/geometryrenderer_p.h>
+#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/geometry_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/buffer_p.h>
@@ -51,448 +53,23 @@ namespace Qt3DRender {
namespace Render {
-namespace {
-
-bool isTriangleBased(Qt3DRender::QGeometryRenderer::PrimitiveType type) Q_DECL_NOEXCEPT
-{
- switch (type) {
- case Qt3DRender::QGeometryRenderer::Triangles:
- case Qt3DRender::QGeometryRenderer::TriangleStrip:
- case Qt3DRender::QGeometryRenderer::TriangleFan:
- case Qt3DRender::QGeometryRenderer::TrianglesAdjacency:
- case Qt3DRender::QGeometryRenderer::TriangleStripAdjacency:
- return true;
- default:
- return false;
- }
-}
-
-struct BufferInfo
-{
- BufferInfo()
- : type(QAttribute::DataType::Float)
- , dataSize(0)
- , count(0)
- , byteStride(0)
- , byteOffset(0)
- {}
-
- QByteArray data;
- QAttribute::DataType type;
- uint dataSize;
- uint count;
- uint byteStride;
- uint byteOffset;
-};
-
-// TO DO: Add methods for triangle strip adjacency
-// What about primitive restart ?
-
-// indices, vertices are already offset
-template<typename index, typename vertex>
-QVector<QBoundingVolume *> traverseTrianglesIndexed(index *indices,
- vertex *vertices,
- const BufferInfo &indexInfo,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < indexInfo.count) {
- for (uint u = 0; u < 3; ++u) {
- uint idx = indices[i + u] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 3;
- }
-
- return tris;
-}
-
-// vertices are already offset
-template<typename vertex>
-QVector<QBoundingVolume *> traverseTriangles(vertex *vertices,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
-
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < vertexInfo.count) {
- for (uint u = 0; u < 3; ++u) {
- uint idx = (i + u) * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 3;
- }
- return tris;
-}
-
-// indices, vertices are already offset
-template<typename index, typename vertex>
-QVector<QBoundingVolume *> traverseTriangleStripIndexed(index *indices,
- vertex *vertices,
- const BufferInfo &indexInfo,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < indexInfo.count) {
- for (uint u = 0; u < 3; ++u) {
- uint idx = indices[i + u] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- ++i;
- }
-
- return tris;
-}
-
-// vertices are already offset
-template<typename vertex>
-QVector<QBoundingVolume *> traverseTriangleStrip(vertex *vertices,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
-
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < vertexInfo.count) {
- for (uint u = 0; u < 3; ++u) {
- uint idx = (i + u) * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- ++i;
- }
- return tris;
-}
-
-// indices, vertices are already offset
-template<typename index, typename vertex>
-QVector<QBoundingVolume *> traverseTriangleFanIndexed(index *indices,
- vertex *vertices,
- const BufferInfo &indexInfo,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
-
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[0][j] = vertices[static_cast<int>(indices[0]) * verticesStride + j];
- }
-
- uint i = 1;
- while (i < indexInfo.count) {
- for (uint u = 0; u < 2; ++u) {
- uint idx = indices[i + u] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u + 1][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 2;
- }
-
- return tris;
-}
-
-// vertices are already offset
-template<typename vertex>
-QVector<QBoundingVolume *> traverseTriangleFan(vertex *vertices,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
-
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
-
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[0][j] = vertices[j];
- }
-
- uint i = 1;
- while (i < vertexInfo.count) {
- for (uint u = 0; u < 2; ++u) {
- uint idx = (i + u) * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u + 1][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 2;
- }
- return tris;
-}
-
-// indices, vertices are already offset
-template<typename index, typename vertex>
-QVector<QBoundingVolume *> traverseTriangleAdjacencyIndexed(index *indices,
- vertex *vertices,
- const BufferInfo &indexInfo,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < indexInfo.count) {
- for (uint u = 0; u < 6; u += 2) {
- uint idx = indices[i + u] * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u / 2][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 6;
- }
-
- return tris;
-}
-
-// vertices are already offset
-template<typename vertex>
-QVector<QBoundingVolume *> traverseTriangleAdjacency(vertex *vertices,
- const BufferInfo &vertexInfo,
- const Qt3DCore::QNodeId id)
-{
- QVector<QBoundingVolume *> tris;
- uint i = 0;
-
- const uint verticesStride = vertexInfo.byteStride / sizeof(vertex);
- const uint maxVerticesDataSize = qMin(vertexInfo.dataSize, 3U);
-
- QVector3D abc[3];
- while (i < vertexInfo.count) {
- for (uint u = 0; u < 6; u += 2) {
- uint idx = (i + u) * verticesStride;
- for (uint j = 0; j < maxVerticesDataSize; ++j) {
- abc[u / 2][j] = vertices[idx + j];
- }
- }
- tris.push_back(new TriangleBoundingVolume(id, abc[2], abc[1], abc[0]));
- i += 6;
- }
- return tris;
-}
-
-
-template <QAttribute::DataType> struct EnumToType;
-template <> struct EnumToType<QAttribute::Byte> { typedef const char type; };
-template <> struct EnumToType<QAttribute::UnsignedByte> { typedef const uchar type; };
-template <> struct EnumToType<QAttribute::Short> { typedef const short type; };
-template <> struct EnumToType<QAttribute::UnsignedShort> { typedef const ushort type; };
-template <> struct EnumToType<QAttribute::Int> { typedef const int type; };
-template <> struct EnumToType<QAttribute::UnsignedInt> { typedef const uint type; };
-template <> struct EnumToType<QAttribute::Float> { typedef const float type; };
-template <> struct EnumToType<QAttribute::Double> { typedef const double type; };
-
-template<QAttribute::DataType v>
-typename EnumToType<v>::type *castToType(const QByteArray &u, uint byteOffset)
-{
- return reinterpret_cast< typename EnumToType<v>::type *>(u.constData() + byteOffset);
-}
-
-template<typename ReturnType, typename Func>
-QVector<QBoundingVolume *> processBuffer(const BufferInfo &info, Func &f)
-{
- switch (info.type) {
- case QAttribute::Byte: return f(info, castToType<QAttribute::Byte>(info.data, info.byteOffset));
- case QAttribute::UnsignedByte: return f(info, castToType<QAttribute::UnsignedByte>(info.data, info.byteOffset));
- case QAttribute::Short: return f(info, castToType<QAttribute::Short>(info.data, info.byteOffset));
- case QAttribute::UnsignedShort: return f(info, castToType<QAttribute::UnsignedShort>(info.data, info.byteOffset));
- case QAttribute::Int: return f(info, castToType<QAttribute::Int>(info.data, info.byteOffset));
- case QAttribute::UnsignedInt: return f(info, castToType<QAttribute::UnsignedInt>(info.data, info.byteOffset));
- case QAttribute::Float: return f(info, castToType<QAttribute::Float>(info.data, info.byteOffset));
- case QAttribute::Double: return f(info, castToType<QAttribute::Double>(info.data, info.byteOffset));
- default:
- return ReturnType();
- }
-}
-
-template<typename Index, typename ReturnType>
-struct IndexedVertexExecutor
-{
- template<typename Vertex>
- ReturnType operator ()(const BufferInfo &vertexInfo, Vertex * vertices)
- {
- switch (primitiveType) {
- case Qt3DRender::QGeometryRenderer::Triangles:
- return traverseTrianglesIndexed(indices, vertices, indexBufferInfo, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleStrip:
- return traverseTriangleStripIndexed(indices, vertices, indexBufferInfo, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleFan:
- return traverseTriangleFanIndexed(indices, vertices, indexBufferInfo, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TrianglesAdjacency:
- return traverseTriangleAdjacencyIndexed(indices, vertices, indexBufferInfo, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleStripAdjacency:
- default:
- return ReturnType();
- }
- }
-
- BufferInfo indexBufferInfo;
- Index *indices;
- Qt3DRender::QGeometryRenderer::PrimitiveType primitiveType;
- Qt3DCore::QNodeId id;
-};
-
-template<typename ReturnType>
-struct IndexExecutor
-{
- BufferInfo vertexBufferInfo;
-
- template<typename Index>
- ReturnType operator ()( const BufferInfo &indexInfo, Index *indices)
- {
- IndexedVertexExecutor<Index, ReturnType> exec;
- exec.primitiveType = primitiveType;
- exec.indices = indices;
- exec.indexBufferInfo = indexInfo;
- exec.id = id;
- return processBuffer<ReturnType>(vertexBufferInfo, exec);
- }
-
- Qt3DRender::QGeometryRenderer::PrimitiveType primitiveType;
- Qt3DCore::QNodeId id;
-};
-
-template<typename ReturnType>
-struct VertexExecutor
-{
- template<typename Vertex>
- ReturnType operator ()(const BufferInfo &vertexInfo, Vertex *vertices)
- {
- switch (primitiveType) {
- case Qt3DRender::QGeometryRenderer::Triangles:
- return traverseTriangles(vertices, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleStrip:
- return traverseTriangleStrip(vertices, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleFan:
- return traverseTriangleFan(vertices, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TrianglesAdjacency:
- return traverseTriangleAdjacency(vertices, vertexInfo, id);
- case Qt3DRender::QGeometryRenderer::TriangleStripAdjacency:
- default:
- return ReturnType();
- }
- }
-
- Qt3DRender::QGeometryRenderer::PrimitiveType primitiveType;
- Qt3DCore::QNodeId id;
-};
-
-} // anonymous
-
TrianglesExtractor::TrianglesExtractor(GeometryRenderer *renderer, NodeManagers *manager)
- : m_renderer(renderer)
- , m_manager(manager)
+ : TrianglesVisitor(manager)
+ , m_renderer(renderer)
{
}
QVector<QBoundingVolume *> TrianglesExtractor::extract(const Qt3DCore::QNodeId id)
{
- if (m_renderer && m_renderer->instanceCount() == 1 && isTriangleBased(m_renderer->primitiveType())) {
- Attribute *positionAttribute = Q_NULLPTR;
- Attribute *indexAttribute = Q_NULLPTR;
- Buffer *positionBuffer = Q_NULLPTR;
- Buffer *indexBuffer = Q_NULLPTR;
- Geometry *geom = m_manager->lookupResource<Geometry, GeometryManager>(m_renderer->geometryId());
-
- if (geom) {
- Qt3DRender::Render::Attribute *attribute = Q_NULLPTR;
- Q_FOREACH (const Qt3DCore::QNodeId attrId, geom->attributes()) {
- attribute = m_manager->lookupResource<Attribute, AttributeManager>(attrId);
- if (attribute){
- if (attribute->name() == QAttribute::defaultPositionAttributeName())
- positionAttribute = attribute;
- else if (attribute->attributeType() == QAttribute::IndexAttribute)
- indexAttribute = attribute;
- }
- }
-
- if (positionAttribute)
- positionBuffer = m_manager->lookupResource<Buffer, BufferManager>(positionAttribute->bufferId());
- if (indexAttribute)
- indexBuffer = m_manager->lookupResource<Buffer, BufferManager>(indexAttribute->bufferId());
-
- if (positionBuffer) {
-
- BufferInfo vertexBufferInfo;
- vertexBufferInfo.data = positionBuffer->data();
- vertexBufferInfo.type = positionAttribute->dataType();
- vertexBufferInfo.byteOffset = positionAttribute->byteOffset();
- vertexBufferInfo.byteStride = positionAttribute->byteStride();
- vertexBufferInfo.dataSize = positionAttribute->dataSize();
- vertexBufferInfo.count = positionAttribute->count();
-
- if (indexBuffer) { // Indexed
-
- BufferInfo indexBufferInfo;
- indexBufferInfo.data = indexBuffer->data();
- indexBufferInfo.type = indexAttribute->dataType();
- indexBufferInfo.byteOffset = indexAttribute->byteOffset();
- indexBufferInfo.byteStride = indexAttribute->byteStride();
- indexBufferInfo.count = indexAttribute->count();
-
- IndexExecutor<QVector<QBoundingVolume *> > executor;
- executor.vertexBufferInfo = vertexBufferInfo;
- executor.primitiveType = m_renderer->primitiveType();
- executor.id = id;
-
- return processBuffer<QVector<QBoundingVolume *> >(indexBufferInfo, executor);
-
- } else { // Non Indexed
-
- // Check into which type the buffer needs to be casted
- VertexExecutor<QVector<QBoundingVolume *> > executor;
- executor.primitiveType = m_renderer->primitiveType();
- executor.id = id;
+ qDeleteAll(m_volumes);
+ apply(m_renderer, id);
+ return m_volumes;
+}
- return processBuffer<QVector<QBoundingVolume *> >(vertexBufferInfo, executor);
- }
- }
- }
- }
- return QVector<QBoundingVolume *>();
+void TrianglesExtractor::visit(uint andx, const QVector3D &a, uint bndx, const QVector3D &b, uint cndx, const QVector3D &c)
+{
+ Q_UNUSED(andx); Q_UNUSED(bndx); Q_UNUSED(cndx);
+ m_volumes.push_back(new TriangleBoundingVolume(m_nodeId, a, b, c));
}
} // namespace Render