#ifndef INSTANCEDPERMANENTRENDERER_HPP #define INSTANCEDPERMANENTRENDERER_HPP #include "instancedpermanentrenderer.h" template InstancedPermanentRenderer::InstancedPermanentRenderer() : InstancedPermanentRenderer(Chunk::ShaderParamsType::staticGetGLMode()) { } template InstancedPermanentRenderer::InstancedPermanentRenderer(GLenum glMode) : PermanentRenderer< InstancedShapeRendererContext >() { m_glMode = glMode; m_drawMode = DM_VAO; m_mutex = new QMutex(QMutex::Recursive); m_vertexArray = nullptr; m_fastVertexArray = nullptr; m_normalIndicesArray = nullptr; m_fastIndicesArray = nullptr; m_lastCsKeyUsed = std::numeric_limits::max(); } template InstancedPermanentRenderer::~InstancedPermanentRenderer() { clearShapes(); delete m_mutex; } template void InstancedPermanentRenderer::setVertexArray(const std::vector *vertexArray) { m_vertexArray = (std::vector*)vertexArray; } template void InstancedPermanentRenderer::setFastVertexArray(const std::vector *vertexArray) { m_fastVertexArray = (std::vector*)vertexArray; } template void InstancedPermanentRenderer::setCustomVertexAttribute(const QString& name, GLint tupleSize, GLenum type, GLboolean normalized, GLsizei stride, size_t sizeOfOneValueInByte, size_t arraySize, GLvoid* pointer) { VertexAttribute attribute; attribute.name = name.toStdString(); attribute.tupleSize = tupleSize; attribute.type = type; attribute.normalized = normalized; attribute.stride = stride; attribute.sizeOfOneValueInByte = sizeOfOneValueInByte; attribute.arraySize = arraySize; attribute.pointer = pointer; m_customVertexAttributeCollection.insert(name, attribute); } template void InstancedPermanentRenderer::setNormalIndicesArray(const std::vector *normalIndicesArray) { m_normalIndicesArray = (std::vector*)normalIndicesArray; } template void InstancedPermanentRenderer::setFastIndicesArray(const std::vector *fastIndicesArray) { m_fastIndicesArray = (std::vector*)fastIndicesArray; } template void InstancedPermanentRenderer::updateInAllContext() { QMutexLocker locker(m_mutex); typename IContextAccessor< typename Chunk::RendererContextType >::ContextCollectionIterator it(this->getContexts()); while(it.hasNext()) { it.next(); InstancedShapeRendererContext *c = it.value(); c->makeCurrent(); c->getShaders().init(c->getOpenglContext()); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->update(); itC.value()->setCurrentContext(nullptr); } } } template void InstancedPermanentRenderer::updateInfoInAllContext() { QMutexLocker locker(m_mutex); typename IContextAccessor< typename Chunk::RendererContextType >::ContextCollectionIterator it(this->getContexts()); while(it.hasNext()) { it.next(); InstancedShapeRendererContext *c = it.value(); c->makeCurrent(); c->getShaders().init(c->getOpenglContext()); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->updateInfoBO(); itC.value()->setCurrentContext(nullptr); } } } template void InstancedPermanentRenderer::updateColorInAllContext() { QMutexLocker locker(m_mutex); typename IContextAccessor< typename Chunk::RendererContextType >::ContextCollectionIterator it(this->getContexts()); while(it.hasNext()) { it.next(); InstancedShapeRendererContext *c = it.value(); c->makeCurrent(); c->getShaders().init(c->getOpenglContext()); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->updateColorBO(); itC.value()->setCurrentContext(nullptr); } } } template void InstancedPermanentRenderer::updateNormalInAllContext() { // Instanced elements don't have normals ! } template void InstancedPermanentRenderer::updateOnlyVAOInAllContext() { QMutexLocker locker(m_mutex); typename IContextAccessor< typename Chunk::RendererContextType >::ContextCollectionIterator it(this->getContexts()); while(it.hasNext()) { it.next(); InstancedShapeRendererContext *c = it.value(); c->makeCurrent(); c->getShaders().init(c->getOpenglContext()); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->updateOnlyVAO(); itC.value()->setCurrentContext(nullptr); } } } template void InstancedPermanentRenderer::setDrawModeToUse(DrawMode mode) { QMutexLocker locker(m_mutex); if(m_drawMode != mode) { m_drawMode = mode; ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setDrawModeToUse(mode); } } } template void InstancedPermanentRenderer::destroyGL(const QOpenGLContext *context) { QMutexLocker locker(m_mutex); InstancedShapeRendererContext *c = this->getContexts().value(const_cast(context), nullptr); if(c != nullptr) c->destroyGL(); } template const Chunk& InstancedPermanentRenderer::createOrGetChunkForShape(const Eigen::AlignedBox3d &bbox, uint *chunkUniqueKey) { QMutexLocker locker(m_mutex); // TODO : use other information than just the center of the bbox because if the bbox overlap two or more coordinate system it will be a problem Eigen::Vector3d center = bbox.center(); Eigen::Vector3d offset; uint uniqueKey; AMKglEA->getCoordinateSystemManager()->getCoordinateSystemInfosForCoordinates(center[0], center[1], center[2], uniqueKey, offset); if(chunkUniqueKey != nullptr) *chunkUniqueKey = uniqueKey; if(uniqueKey == m_lastCsKeyUsed) { offset = m_lastOffsetUsed; } else { m_lastCsKeyUsed = uniqueKey; m_lastOffsetUsed = offset; } Chunk *ch = m_chunks.value(uniqueKey, nullptr); if(ch == nullptr) { Q_ASSERT(m_vertexArray != nullptr); if (m_vertexArray == nullptr) {qDebug() << "InstancedPermanentRenderer::createOrGetChunkForShape" << ", " << "m_vertexArray == nullptr";} ch = new Chunk(uniqueKey, this->getTypeOfObjectDrawn(), m_glMode, *m_vertexArray, offset, &m_customVertexAttributeCollection, m_fastVertexArray, m_normalIndicesArray, m_fastIndicesArray); ch->setContextAccessor(this); ch->setAttributesAccessor(this->getAttributesAccessor()); ch->setCurrentColor(this->getCurrentColor()); ch->setDrawModeToUse(m_drawMode); m_chunks.insert(uniqueKey, ch); } return *ch; } template void InstancedPermanentRenderer::addShape(const Chunk& chunk, const ShaderParams ¶ms, const ElementInfo &info) { QMutexLocker locker(m_mutex); Chunk& ch = const_cast(chunk); ch.addShape(params, info); } template void InstancedPermanentRenderer::removeShapes(const uint& chunkUniqueKey, const size_t &index, const size_t &count) { QMutexLocker locker(m_mutex); Chunk* c = m_chunks.value(chunkUniqueKey, nullptr); if(c == nullptr) return; c->removeShapes(index, count); } template template void InstancedPermanentRenderer::removeShapes(const uint& chunkUniqueKey, const iterator& begin, const iterator& end) { QMutexLocker locker(m_mutex); if(begin == end) return; Chunk* c = m_chunks.value(chunkUniqueKey, nullptr); if(c == nullptr) return; c->removeShapes(begin, end); } template void InstancedPermanentRenderer::setShapesVisible(const uint& chunkUniqueKey, const size_t &index, const size_t &count, bool visible) { QMutexLocker locker(m_mutex); Chunk* c = m_chunks.value(chunkUniqueKey, nullptr); if(c == nullptr) return; c->setShapesVisible(index, count, visible); } template void InstancedPermanentRenderer::clearShapes() { QMutexLocker locker(m_mutex); qDeleteAll(m_chunks.begin(), m_chunks.end()); m_chunks.clear(); } template size_t InstancedPermanentRenderer::countShapes() const { QMutexLocker locker(m_mutex); size_t count = 0; ChunkCollectionQtIterator it(m_chunks); while(it.hasNext()) count += it.next().value()->countShape(); return count; } template size_t InstancedPermanentRenderer::countShapesInChunk(const uint& chunkUniqueKey) const { QMutexLocker locker(m_mutex); Chunk* c = m_chunks.value(chunkUniqueKey, nullptr); if(c == nullptr) return 0; return c->countShape(); } template void InstancedPermanentRenderer::visitObjects(IObjectsVisitor &visitor) { QMutexLocker locker(m_mutex); ChunkCollectionQtIterator it(m_chunks); while(it.hasNext() && visitor.mustContinueVisit()) visitor.visitChunk(it.next().value()); } template void InstancedPermanentRenderer::draw(DrawInfo &info) { QMutexLocker locker(m_mutex); InstancedShapeRendererContext* c = this->getCurrentContext(); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->draw(info); itC.value()->setCurrentContext(nullptr); } } template void InstancedPermanentRenderer::fastDraw(DrawInfo &info) { QMutexLocker locker(m_mutex); InstancedShapeRendererContext *c = this->getCurrentContext(); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->fastDraw(info); } } template void InstancedPermanentRenderer::postDraw(DrawInfo &info) { QMutexLocker locker(m_mutex); InstancedShapeRendererContext *c = this->getCurrentContext(); ChunkCollectionQtIterator itC(m_chunks); while(itC.hasNext()) { itC.next(); itC.value()->setCurrentContext(c); itC.value()->postDraw(info); itC.value()->setCurrentContext(nullptr); } } template void InstancedPermanentRenderer::currentColorChanged() { QMutexLocker locker(m_mutex); ChunkCollectionQtIterator it(m_chunks); while(it.hasNext()) { it.next().value()->setCurrentColor(this->getCurrentColor()); } } template typename InstancedPermanentRenderer::ChunkCollection& InstancedPermanentRenderer::getChunks() { return m_chunks; } #endif // INSTANCEDPERMANENTRENDERER_HPP