1 | // Copyright (C) 2019 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include <QtCore/QCoreApplication> |
5 | #include <QtCore/QCommandLineParser> |
6 | #include <QtCore/QFile> |
7 | #include <QtCore/QDebug> |
8 | |
9 | #include <QtQuick3DUtils/private/qssgmesh_p.h> |
10 | |
11 | using Qt::hex; |
12 | |
13 | using namespace QSSGMesh; |
14 | |
15 | int main(int argc, char *argv[]) |
16 | { |
17 | QCoreApplication app(argc, argv); |
18 | |
19 | // Setup command line arguments |
20 | QCommandLineParser cmdLineParser; |
21 | cmdLineParser.setApplicationDescription( |
22 | "Allows to debug the high level structure of .mesh files for use with Qt Quick 3D" ); |
23 | cmdLineParser.addHelpOption(); |
24 | cmdLineParser.process(app); |
25 | QStringList meshFileNames = cmdLineParser.positionalArguments(); |
26 | |
27 | // if there is nothing to do return early |
28 | if (meshFileNames.isEmpty()) |
29 | return -1; |
30 | |
31 | // Process Mesh files |
32 | for (const auto &meshFileName : meshFileNames) { |
33 | QFile meshFile(meshFileName); |
34 | if (!meshFile.open(flags: QIODevice::ReadOnly)) { |
35 | qWarning() << "could not open" << meshFileName; |
36 | continue; |
37 | } |
38 | |
39 | MeshInternal::MultiMeshInfo = MeshInternal::readFileHeader(device: &meshFile); |
40 | if (multiHeader.isValid()) { |
41 | // Print Multiheader information |
42 | qDebug() << " -- Multiheader --" ; |
43 | qDebug() << "fileId:" << multiHeader.fileId; |
44 | qDebug() << "version:" << multiHeader.fileVersion; |
45 | qDebug() << "mesh entries:" << multiHeader.meshEntries.size(); |
46 | |
47 | for (auto it = multiHeader.meshEntries.cbegin(), end = multiHeader.meshEntries.cend(); it != end; ++it) { |
48 | const quint32 meshId = it.key(); |
49 | const quint64 meshOffset = it.value(); |
50 | qDebug() << "\t -- mesh entry --" ; |
51 | qDebug() << "\tid:" << meshId; |
52 | qDebug() << "\toffset:" << Qt::hex << meshOffset; |
53 | |
54 | MeshInternal::MeshDataHeader ; |
55 | Mesh mesh; |
56 | if (!MeshInternal::readMeshData(device: &meshFile, offset: meshOffset, mesh: &mesh, header: &header)) { |
57 | qWarning(msg: "Failed to load mesh body" ); |
58 | continue; |
59 | } |
60 | |
61 | // Header |
62 | qDebug() << "\t -- MeshDataHeader --" ; |
63 | qDebug() << "\tfileId:" << header.fileId; |
64 | qDebug() << "\tfileVersion:" << header.fileVersion; |
65 | qDebug() << "\tflags:" << header.flags; |
66 | qDebug() << "\tsize in bytes:" << header.sizeInBytes; |
67 | |
68 | // Draw Mode |
69 | qDebug() << "\t\tdraw mode:" << static_cast<int>(mesh.drawMode()); |
70 | |
71 | // Winding |
72 | qDebug() << "\t\twinding:" << QSSGBaseTypeHelpers::toString(value: QSSGRenderWinding(mesh.winding())); |
73 | |
74 | // Vertex Buffer |
75 | const Mesh::VertexBuffer vb = mesh.vertexBuffer(); |
76 | qDebug() << "\t\t -- Vertex Buffer --" ; |
77 | qDebug() << "\t\tentry count:" << vb.entries.size(); |
78 | for (quint32 idx = 0, end = vb.entries.size(); idx < end; ++idx) { |
79 | qDebug() << "\t\t\t -- Vertex Buffer Entry" << idx << "--" ; |
80 | const Mesh::VertexBufferEntry &entry(vb.entries[idx]); |
81 | qDebug() << "\t\t\tname:" << entry.name; |
82 | qDebug() << "\t\t\ttype:" << QSSGBaseTypeHelpers::toString(value: QSSGRenderComponentType(entry.componentType)); |
83 | qDebug() << "\t\t\tcomponentCount:" << entry.componentCount; |
84 | qDebug() << "\t\t\tstart offset:" << entry.offset; |
85 | } |
86 | qDebug() << "\t\tstride:" << vb.stride; |
87 | qDebug() << "\t\tdata size in bytes:" << vb.data.size(); |
88 | |
89 | // Index Buffer |
90 | const Mesh::IndexBuffer ib = mesh.indexBuffer(); |
91 | qDebug() << "\t\t -- Index Buffer --" ; |
92 | qDebug() << "\t\tcomponentType:" << QSSGBaseTypeHelpers::toString(value: QSSGRenderComponentType(ib.componentType)); |
93 | qDebug() << "\t\tdata size in bytes:" << ib.data.size(); |
94 | |
95 | // Subsets |
96 | const QVector<Mesh::Subset> subsets = mesh.subsets(); |
97 | qDebug() << "\t\t -- Subsets --" ; |
98 | qDebug() << "\t\tsubset count:" << subsets.size(); |
99 | for (quint32 idx = 0, end = subsets.size(); idx < end; ++idx) { |
100 | qDebug() << "\t\t -- Subset" << idx << "--" ; |
101 | const Mesh::Subset &subset(subsets[idx]); |
102 | qDebug() << "\t\tindex count:" << subset.count; |
103 | qDebug() << "\t\tstart offset in indices:" << subset.offset; |
104 | qDebug() << "\t\tbounds: (" << |
105 | subset.bounds.min.x() << "," << |
106 | subset.bounds.min.y() << "," << |
107 | subset.bounds.min.z() << ") (" << |
108 | subset.bounds.max.x() << "," << |
109 | subset.bounds.max.y() << "," << |
110 | subset.bounds.max.z() << ")" ; |
111 | qDebug() << "\t\tname:" << subset.name; |
112 | if (header.hasLightmapSizeHint()) |
113 | qDebug() << "\t\tlightmap size hint:" << subset.lightmapSizeHint; |
114 | if (header.hasLodDataHint()) { |
115 | qDebug() << "\t\tlods: " ; |
116 | for (auto lod : subset.lods) { |
117 | qDebug() << "\t\t\tcount: " << lod.count << "offset: " << lod.offset << "distance: " << lod.distance; |
118 | } |
119 | } |
120 | } |
121 | } |
122 | |
123 | } |
124 | |
125 | meshFile.close(); |
126 | qDebug() << "closed meshFile" ; |
127 | } |
128 | |
129 | return 0; |
130 | } |
131 | |