diff options
author | Mike Krus <mike.krus@kdab.com> | 2015-12-10 15:58:05 +0000 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2016-01-25 14:13:13 +0000 |
commit | 28ec1ca1883e0fe9b8b0e0de4049564ae652bd90 (patch) | |
tree | 3722809fc54b75d08b08fb68bd5d9d56fbe24342 /src/render/backend/trianglesextractor.cpp | |
parent | 4ad00b344bc79e34f2ba2f8355e65c7948791389 (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.cpp | 447 |
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 |