1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "meshloader_p.h"
5#include "vertexindexer_p.h"
6#include "objecthelper_p.h"
7
8QT_BEGIN_NAMESPACE
9
10ObjectHelper::ObjectHelper(const QString &objectFile)
11 : m_objectFile(objectFile)
12{
13 load();
14}
15
16struct ObjectHelperRef {
17 int refCount;
18 ObjectHelper *obj;
19};
20
21// The "Abstract3DRenderer *" key identifies the renderer
22static QHash<const Abstract3DRenderer *, QHash<QString, ObjectHelperRef *> *> cacheTable;
23
24ObjectHelper::~ObjectHelper()
25{
26}
27
28void ObjectHelper::resetObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj,
29 const QString &meshFile)
30{
31 Q_ASSERT(cacheId);
32
33 if (obj) {
34 const QString &oldFile = obj->objectFile();
35 if (meshFile == oldFile)
36 return; // same file, do nothing
37 releaseObjectHelper(cacheId, obj);
38 }
39 obj = getObjectHelper(cacheId, objectFile: meshFile);
40}
41
42void ObjectHelper::releaseObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj)
43{
44 Q_ASSERT(cacheId);
45
46 if (obj) {
47 QHash<QString, ObjectHelperRef *> *objectTable = cacheTable.value(key: cacheId, defaultValue: 0);
48 if (objectTable) {
49 // Delete object if last reference is released
50 ObjectHelperRef *objRef = objectTable->value(key: obj->m_objectFile, defaultValue: 0);
51 if (objRef) {
52 objRef->refCount--;
53 if (objRef->refCount <= 0) {
54 objectTable->remove(key: obj->m_objectFile);
55 delete objRef->obj;
56 delete objRef;
57 }
58 }
59 if (objectTable->isEmpty()) {
60 // Remove the entire cache if last object was removed
61 cacheTable.remove(key: cacheId);
62 delete objectTable;
63 }
64 } else {
65 // Just delete the object if unknown cache
66 delete obj;
67 }
68 obj = 0;
69 }
70}
71
72ObjectHelper *ObjectHelper::getObjectHelper(const Abstract3DRenderer *cacheId,
73 const QString &objectFile)
74{
75 if (objectFile.isEmpty())
76 return 0;
77
78 QHash<QString, ObjectHelperRef *> *objectTable = cacheTable.value(key: cacheId, defaultValue: 0);
79 if (!objectTable) {
80 objectTable = new QHash<QString, ObjectHelperRef *>;
81 cacheTable.insert(key: cacheId, value: objectTable);
82 }
83
84 // Check if object helper for this mesh already exists
85 ObjectHelperRef *objRef = objectTable->value(key: objectFile, defaultValue: 0);
86 if (!objRef) {
87 objRef = new ObjectHelperRef;
88 objRef->refCount = 0;
89 objRef->obj = new ObjectHelper(objectFile);
90 if (objRef->obj->m_meshDataLoaded) {
91 objectTable->insert(key: objectFile, value: objRef);
92 } else {
93 delete objRef->obj;
94 delete objRef;
95 objRef = nullptr;
96 }
97 }
98 if (objRef) {
99 objRef->refCount++;
100 return objRef->obj;
101 }
102 return nullptr;
103}
104
105void ObjectHelper::load()
106{
107 if (m_meshDataLoaded) {
108 // Delete old data
109 glDeleteBuffers(n: 1, buffers: &m_vertexbuffer);
110 glDeleteBuffers(n: 1, buffers: &m_uvbuffer);
111 glDeleteBuffers(n: 1, buffers: &m_normalbuffer);
112 glDeleteBuffers(n: 1, buffers: &m_elementbuffer);
113 m_indices.clear();
114 m_indexedVertices.clear();
115 m_indexedUVs.clear();
116 m_indexedNormals.clear();
117 m_vertexbuffer = 0;
118 m_uvbuffer = 0;
119 m_normalbuffer = 0;
120 m_elementbuffer = 0;
121 }
122 QList<QVector3D> vertices;
123 QList<QVector2D> uvs;
124 QList<QVector3D> normals;
125 bool loadOk = MeshLoader::loadOBJ(path: m_objectFile, out_vertices&: vertices, out_uvs&: uvs, out_normals&: normals);
126
127 if (!loadOk) {
128 qCritical() << "Loading" << m_objectFile << "failed";
129 m_meshDataLoaded = false;
130 } else {
131 // Index vertices
132 VertexIndexer::indexVBO(in_vertices: vertices, in_uvs: uvs, in_normals: normals, out_indices&: m_indices, out_vertices&: m_indexedVertices, out_uvs&: m_indexedUVs,
133 out_normals&: m_indexedNormals);
134
135 m_indexCount = m_indices.size();
136
137 glGenBuffers(n: 1, buffers: &m_vertexbuffer);
138 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_vertexbuffer);
139 glBufferData(GL_ARRAY_BUFFER, size: m_indexedVertices.size() * sizeof(QVector3D),
140 data: &m_indexedVertices.at(i: 0),
141 GL_STATIC_DRAW);
142
143 glGenBuffers(n: 1, buffers: &m_normalbuffer);
144 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_normalbuffer);
145 glBufferData(GL_ARRAY_BUFFER, size: m_indexedNormals.size() * sizeof(QVector3D),
146 data: &m_indexedNormals.at(i: 0),
147 GL_STATIC_DRAW);
148
149 glGenBuffers(n: 1, buffers: &m_uvbuffer);
150 glBindBuffer(GL_ARRAY_BUFFER, buffer: m_uvbuffer);
151 glBufferData(GL_ARRAY_BUFFER, size: m_indexedUVs.size() * sizeof(QVector2D),
152 data: &m_indexedUVs.at(i: 0), GL_STATIC_DRAW);
153
154 glGenBuffers(n: 1, buffers: &m_elementbuffer);
155 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: m_elementbuffer);
156 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size: m_indices.size() * sizeof(GLuint),
157 data: &m_indices.at(i: 0), GL_STATIC_DRAW);
158
159 glBindBuffer(GL_ARRAY_BUFFER, buffer: 0);
160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer: 0);
161
162 m_meshDataLoaded = true;
163 }
164}
165
166QT_END_NAMESPACE
167

source code of qtdatavis3d/src/datavisualization/utils/objecthelper.cpp