/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.io ** ** This file is part of the Qt Data Visualization module. ** ** Licensees holding valid commercial license for Qt may use this file in ** accordance with the Qt License Agreement provided with the Software ** or, alternatively, in accordance with the terms contained in a written ** agreement between you and Digia. ** ** If you have questions regarding the use of this file, please use ** contact form at http://qt.io ** ****************************************************************************/ #include "meshloader_p.h" #include "vertexindexer_p.h" #include "objecthelper_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION ObjectHelper::ObjectHelper(const QString &objectFile) : m_objectFile(objectFile) { load(); } struct ObjectHelperRef { int refCount; ObjectHelper *obj; }; // The "Abstract3DRenderer *" key identifies the renderer static QHash *> cacheTable; ObjectHelper::~ObjectHelper() { } void ObjectHelper::resetObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj, const QString &meshFile) { Q_ASSERT(cacheId); if (obj) { const QString &oldFile = obj->objectFile(); if (meshFile == oldFile) return; // same file, do nothing releaseObjectHelper(cacheId, obj); } obj = getObjectHelper(cacheId, meshFile); } void ObjectHelper::releaseObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj) { Q_ASSERT(cacheId); if (obj) { QHash *objectTable = cacheTable.value(cacheId, 0); if (objectTable) { // Delete object if last reference is released ObjectHelperRef *objRef = objectTable->value(obj->m_objectFile, 0); if (objRef) { objRef->refCount--; if (objRef->refCount <= 0) { objectTable->remove(obj->m_objectFile); delete objRef->obj; delete objRef; } } if (objectTable->isEmpty()) { // Remove the entire cache if last object was removed cacheTable.remove(cacheId); delete objectTable; } } else { // Just delete the object if unknown cache delete obj; } obj = 0; } } ObjectHelper *ObjectHelper::getObjectHelper(const Abstract3DRenderer *cacheId, const QString &objectFile) { if (objectFile.isEmpty()) return 0; QHash *objectTable = cacheTable.value(cacheId, 0); if (!objectTable) { objectTable = new QHash; cacheTable.insert(cacheId, objectTable); } // Check if object helper for this mesh already exists ObjectHelperRef *objRef = objectTable->value(objectFile, 0); if (!objRef) { objRef = new ObjectHelperRef; objRef->refCount = 0; objRef->obj = new ObjectHelper(objectFile); objectTable->insert(objectFile, objRef); } objRef->refCount++; return objRef->obj; } void ObjectHelper::load() { if (m_meshDataLoaded) { // Delete old data glDeleteBuffers(1, &m_vertexbuffer); glDeleteBuffers(1, &m_uvbuffer); glDeleteBuffers(1, &m_normalbuffer); glDeleteBuffers(1, &m_elementbuffer); m_indices.clear(); m_indexedVertices.clear(); m_indexedUVs.clear(); m_indexedNormals.clear(); m_vertexbuffer = 0; m_uvbuffer = 0; m_normalbuffer = 0; m_elementbuffer = 0; } QVector vertices; QVector uvs; QVector normals; bool loadOk = MeshLoader::loadOBJ(m_objectFile, vertices, uvs, normals); if (!loadOk) qFatal("loading failed"); // Index vertices VertexIndexer::indexVBO(vertices, uvs, normals, m_indices, m_indexedVertices, m_indexedUVs, m_indexedNormals); m_indexCount = m_indices.size(); glGenBuffers(1, &m_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); glBufferData(GL_ARRAY_BUFFER, m_indexedVertices.size() * sizeof(QVector3D), &m_indexedVertices.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_normalbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); glBufferData(GL_ARRAY_BUFFER, m_indexedNormals.size() * sizeof(QVector3D), &m_indexedNormals.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_uvbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); glBufferData(GL_ARRAY_BUFFER, m_indexedUVs.size() * sizeof(QVector2D), &m_indexedUVs.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_elementbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(GLuint), &m_indices.at(0), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); m_meshDataLoaded = true; } QT_END_NAMESPACE_DATAVISUALIZATION