| 1 | // Copyright (C) 2019 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 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 | // Target Buffer |
| 90 | if (header.hasSeparateTargetBuffer()) { |
| 91 | const Mesh::TargetBuffer tb = mesh.targetBuffer(); |
| 92 | qDebug() << "\t\t -- Morph Target Buffers --" ; |
| 93 | qDebug() << "\t\tentry count:" << tb.entries.count(); |
| 94 | for (quint32 idx = 0, end = tb.entries.count(); idx < end; ++idx) { |
| 95 | qDebug() << "\t\t\t -- Target Buffer Entry" << idx << "--" ; |
| 96 | const Mesh::VertexBufferEntry &entry(vb.entries[idx]); |
| 97 | qDebug() << "\t\t\tname:" << entry.name; |
| 98 | qDebug() << "\t\t\ttype:" << QSSGBaseTypeHelpers::toString(value: QSSGRenderComponentType(entry.componentType)); |
| 99 | qDebug() << "\t\t\tcomponentCount:" << entry.componentCount; |
| 100 | qDebug() << "\t\t\tstart offset:" << entry.offset; |
| 101 | } |
| 102 | qDebug() << "\t\tnumber of targets:" << tb.numTargets; |
| 103 | qDebug() << "\t\tdata size in bytes:" << tb.data.size(); |
| 104 | } |
| 105 | |
| 106 | // Index Buffer |
| 107 | const Mesh::IndexBuffer ib = mesh.indexBuffer(); |
| 108 | qDebug() << "\t\t -- Index Buffer --" ; |
| 109 | qDebug() << "\t\tcomponentType:" << QSSGBaseTypeHelpers::toString(value: QSSGRenderComponentType(ib.componentType)); |
| 110 | qDebug() << "\t\tdata size in bytes:" << ib.data.size(); |
| 111 | |
| 112 | // Subsets |
| 113 | const QVector<Mesh::Subset> subsets = mesh.subsets(); |
| 114 | qDebug() << "\t\t -- Subsets --" ; |
| 115 | qDebug() << "\t\tsubset count:" << subsets.size(); |
| 116 | for (quint32 idx = 0, end = subsets.size(); idx < end; ++idx) { |
| 117 | qDebug() << "\t\t -- Subset" << idx << "--" ; |
| 118 | const Mesh::Subset &subset(subsets[idx]); |
| 119 | qDebug() << "\t\tindex count:" << subset.count; |
| 120 | qDebug() << "\t\tstart offset in indices:" << subset.offset; |
| 121 | qDebug() << "\t\tbounds: (" << |
| 122 | subset.bounds.min.x() << "," << |
| 123 | subset.bounds.min.y() << "," << |
| 124 | subset.bounds.min.z() << ") (" << |
| 125 | subset.bounds.max.x() << "," << |
| 126 | subset.bounds.max.y() << "," << |
| 127 | subset.bounds.max.z() << ")" ; |
| 128 | qDebug() << "\t\tname:" << subset.name; |
| 129 | if (header.hasLightmapSizeHint()) |
| 130 | qDebug() << "\t\tlightmap size hint:" << subset.lightmapSizeHint; |
| 131 | if (header.hasLodDataHint()) { |
| 132 | qDebug() << "\t\tlods: " ; |
| 133 | for (auto lod : subset.lods) { |
| 134 | qDebug() << "\t\t\tcount: " << lod.count << "offset: " << lod.offset << "distance: " << lod.distance; |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | } |
| 141 | |
| 142 | meshFile.close(); |
| 143 | qDebug() << "closed meshFile" ; |
| 144 | } |
| 145 | |
| 146 | return 0; |
| 147 | } |
| 148 | |