summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Korpipaa <tomi.korpipaa@qt.io>2022-08-25 09:07:45 +0300
committerTomi Korpipaa <tomi.korpipaa@qt.io>2022-08-26 11:03:04 +0300
commit449f644df503dc409514cafd7b46ee8664e4d451 (patch)
tree3b5fdba3a3ffb6a3ae317f30ec5bacdadf083810
parenteae43d7f21b29a8d40e2f12f418efd7f9a35a43c (diff)
Do not crash if custom object load fails
There was no check for the existence of UVs or normals in an OBJ file. A check for those was added. Additionally a debug message was added in case model loading fails due to missing UVs or normals. Furthermore, we no more qFatal out when custom object loading fails. Pick-to: 6.2 6.4 Fixes: QTBUG-105398 Change-Id: Ie2742fb4307fe117e313cedf8111bc8f460f9c7b Reviewed-by: Sami Varanka <sami.varanka@qt.io> Reviewed-by: Kwanghyo Park <kwanghyo.park@qt.io> Reviewed-by: Dilek Akcay Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--src/datavisualization/data/customrenderitem.cpp3
-rw-r--r--src/datavisualization/data/customrenderitem_p.h2
-rw-r--r--src/datavisualization/data/qcustom3ditem.cpp7
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp11
-rw-r--r--src/datavisualization/utils/meshloader.cpp4
-rw-r--r--src/datavisualization/utils/objecthelper.cpp86
6 files changed, 70 insertions, 43 deletions
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp
index fccf6b9a..9873bcf5 100644
--- a/src/datavisualization/data/customrenderitem.cpp
+++ b/src/datavisualization/data/customrenderitem.cpp
@@ -42,9 +42,10 @@ CustomRenderItem::~CustomRenderItem()
ObjectHelper::releaseObjectHelper(m_renderer, m_object);
}
-void CustomRenderItem::setMesh(const QString &meshFile)
+bool CustomRenderItem::setMesh(const QString &meshFile)
{
ObjectHelper::resetObjectHelper(m_renderer, m_object, meshFile);
+ return m_object ? true : false;
}
void CustomRenderItem::setColorTable(const QList<QRgb> &colors)
diff --git a/src/datavisualization/data/customrenderitem_p.h b/src/datavisualization/data/customrenderitem_p.h
index ff9b06bf..abc62247 100644
--- a/src/datavisualization/data/customrenderitem_p.h
+++ b/src/datavisualization/data/customrenderitem_p.h
@@ -33,7 +33,7 @@ public:
inline void setTexture(GLuint texture) { m_texture = texture; }
inline GLuint texture() const { return m_texture; }
- void setMesh(const QString &meshFile);
+ bool setMesh(const QString &meshFile);
inline ObjectHelper *mesh() const { return m_object; }
inline void setScaling(const QVector3D &scaling) { m_scaling = scaling; }
inline const QVector3D &scaling() const { return m_scaling; }
diff --git a/src/datavisualization/data/qcustom3ditem.cpp b/src/datavisualization/data/qcustom3ditem.cpp
index a9cfd5de..a657823c 100644
--- a/src/datavisualization/data/qcustom3ditem.cpp
+++ b/src/datavisualization/data/qcustom3ditem.cpp
@@ -32,7 +32,9 @@ QT_BEGIN_NAMESPACE
/*! \qmlproperty string Custom3DItem::meshFile
*
* The item mesh file name. The item in the file must be in Wavefront OBJ format and include
- * vertices, normals, and UVs. It also needs to be in triangles.
+ * vertices, normals, and UVs. It also needs to be in triangles. If the file is missing either
+ * normals or UVs, loading will fail with an error message to the console output and the item will
+ * not be rendered.
*/
/*! \qmlproperty string Custom3DItem::textureFile
@@ -177,6 +179,9 @@ QCustom3DItem::~QCustom3DItem()
*
* The item in the file must be in Wavefront OBJ format and include
* vertices, normals, and UVs. It also needs to be in triangles.
+ * If the file is missing either normals or UVs, loading will fail
+ * with an error message to the console output and the item will
+ * not be rendered.
*/
void QCustom3DItem::setMeshFile(const QString &meshFile)
{
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 4ddd19e8..b7a37a20 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -723,8 +723,10 @@ void Abstract3DRenderer::updateCustomData(const QList<QCustom3DItem *> &customIt
CustomRenderItem *renderItem = m_customRenderCache.value(item);
if (!renderItem)
renderItem = addCustomItem(item);
- renderItem->setValid(true);
- renderItem->setIndex(i); // always update index, as it must match the custom item index
+ if (renderItem) {
+ renderItem->setValid(true);
+ renderItem->setIndex(i); // always update index, as it must match the custom item index
+ }
}
// Check render item cache and remove items that are not in customItems list anymore
@@ -1127,7 +1129,10 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
CustomRenderItem *newItem = new CustomRenderItem();
newItem->setRenderer(this);
newItem->setItemPointer(item); // Store pointer for render item updates
- newItem->setMesh(item->meshFile());
+ if (!newItem->setMesh(item->meshFile())) {
+ delete newItem;
+ return nullptr;
+ }
newItem->setOrigPosition(item->position());
newItem->setOrigScaling(item->scaling());
newItem->setScalingAbsolute(item->isScalingAbsolute());
diff --git a/src/datavisualization/utils/meshloader.cpp b/src/datavisualization/utils/meshloader.cpp
index 8b3b0725..baa719bc 100644
--- a/src/datavisualization/utils/meshloader.cpp
+++ b/src/datavisualization/utils/meshloader.cpp
@@ -55,6 +55,10 @@ bool MeshLoader::loadOBJ(const QString &path, QList<QVector3D> &out_vertices,
QStringList set1 = lineContents.at(1).split(slashTag);
QStringList set2 = lineContents.at(2).split(slashTag);
QStringList set3 = lineContents.at(3).split(slashTag);
+ if (set1.length() < 3 || set2.length() < 3 || set3.length() < 3) {
+ qWarning("The file being loaded is missing UVs and/or normals");
+ return false;
+ }
vertexIndex[0] = set1.at(0).toUInt();
vertexIndex[1] = set2.at(0).toUInt();
vertexIndex[2] = set3.at(0).toUInt();
diff --git a/src/datavisualization/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp
index 893e65c0..6053b255 100644
--- a/src/datavisualization/utils/objecthelper.cpp
+++ b/src/datavisualization/utils/objecthelper.cpp
@@ -87,10 +87,19 @@ ObjectHelper *ObjectHelper::getObjectHelper(const Abstract3DRenderer *cacheId,
objRef = new ObjectHelperRef;
objRef->refCount = 0;
objRef->obj = new ObjectHelper(objectFile);
- objectTable->insert(objectFile, objRef);
+ if (objRef->obj->m_meshDataLoaded) {
+ objectTable->insert(objectFile, objRef);
+ } else {
+ delete objRef->obj;
+ delete objRef;
+ objRef = nullptr;
+ }
+ }
+ if (objRef) {
+ objRef->refCount++;
+ return objRef->obj;
}
- objRef->refCount++;
- return objRef->obj;
+ return nullptr;
}
void ObjectHelper::load()
@@ -114,41 +123,44 @@ void ObjectHelper::load()
QList<QVector2D> uvs;
QList<QVector3D> 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;
+ if (!loadOk) {
+ qCritical() << "Loading" << m_objectFile << "failed";
+ m_meshDataLoaded = false;
+ } else {
+ // 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