1 | // Copyright (C) 2017 The Qt Company Ltd and/or its subsidiary(-ies). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "stlgeometryloader.h" |
5 | |
6 | #include <QtCore/QDataStream> |
7 | #include <QtCore/QLoggingCategory> |
8 | #include <QtCore/QIODevice> |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | namespace Qt3DRender { |
13 | |
14 | Q_LOGGING_CATEGORY(StlGeometryLoaderLog, "Qt3D.StlGeometryLoader" , QtWarningMsg) |
15 | |
16 | bool StlGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh) |
17 | { |
18 | Q_UNUSED(subMesh); |
19 | |
20 | if (loadBinary(ioDev)) |
21 | return true; |
22 | |
23 | return loadAscii(ioDev); |
24 | } |
25 | |
26 | bool StlGeometryLoader::loadAscii(QIODevice *ioDev) |
27 | { |
28 | // TODO stricter syntax checking |
29 | |
30 | ioDev->setTextModeEnabled(true); |
31 | if (!ioDev->seek(pos: 0)) |
32 | return false; |
33 | |
34 | char signature[5]; |
35 | if (ioDev->peek(data: signature, maxlen: sizeof(signature)) != sizeof(signature)) |
36 | return false; |
37 | |
38 | if (qstrncmp(str1: signature, str2: "solid" , len: 5) != 0) |
39 | return false; |
40 | |
41 | while (!ioDev->atEnd()) { |
42 | QByteArray lineBuffer = ioDev->readLine(); |
43 | |
44 | const char *begin = lineBuffer.constData(); |
45 | const char *end = begin + lineBuffer.size(); |
46 | |
47 | const ByteArraySplitter tokens(begin, end, ' ', Qt::SkipEmptyParts); |
48 | |
49 | if (qstrncmp(str1: tokens.charPtrAt(index: 0), str2: "vertex " , len: 7) == 0) { |
50 | if (tokens.size() < 4) { |
51 | qCWarning(StlGeometryLoaderLog) << "Unsupported number of components in vertex" ; |
52 | } else { |
53 | const float x = tokens.floatAt(index: 1); |
54 | const float y = tokens.floatAt(index: 2); |
55 | const float z = tokens.floatAt(index: 3); |
56 | m_points.push_back(x: QVector3D(x, y, z)); |
57 | m_indices.push_back(x: uint(m_indices.size())); |
58 | } |
59 | } |
60 | } |
61 | |
62 | return true; |
63 | } |
64 | |
65 | bool StlGeometryLoader::loadBinary(QIODevice *ioDev) |
66 | { |
67 | static const int = 80; |
68 | |
69 | if (ioDev->read(maxlen: headerSize).size() != headerSize) |
70 | return false; |
71 | |
72 | ioDev->setTextModeEnabled(false); |
73 | |
74 | QDataStream stream(ioDev); |
75 | stream.setByteOrder(QDataStream::LittleEndian); |
76 | stream.setFloatingPointPrecision(QDataStream::SinglePrecision); |
77 | |
78 | quint32 triangleCount; |
79 | stream >> triangleCount; |
80 | |
81 | if (quint64(ioDev->size()) != headerSize + sizeof(quint32) + (triangleCount * 50)) |
82 | return false; |
83 | |
84 | m_points.reserve(n: triangleCount * 3); |
85 | m_indices.reserve(n: triangleCount * 3); |
86 | |
87 | for (unsigned i = 0; i < triangleCount; ++i) { |
88 | QVector3D normal; |
89 | stream >> normal; |
90 | |
91 | for (int j = 0; j < 3; ++j) { |
92 | QVector3D point; |
93 | stream >> point; |
94 | m_points.push_back(x: point); |
95 | m_indices.push_back(x: (i * 3) + j); |
96 | } |
97 | |
98 | quint16 attributeCount; |
99 | stream >> attributeCount; |
100 | } |
101 | |
102 | return true; |
103 | } |
104 | |
105 | } // namespace Qt3DRender |
106 | |
107 | QT_END_NAMESPACE |
108 | |