Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcacheutils.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qcacheutils_p.h"
5
6#include <QFile>
7#include <QFileInfo>
8#include <QtQml/QQmlFile>
9#include <extensions/PxExtensionsAPI.h>
10#include "qphysicsworld_p.h"
11
13namespace QCacheUtils {
14
16
17static QString MESH_CACHE_PATH = qEnvironmentVariable("QT_PHYSICS_CACHE_PATH");
18
19static QString getCachedFilename(const QString &filePath, CacheGeometry geom)
20{
21 const char *extension = "unknown_physx";
22 switch (geom) {
24 extension = "triangle_physx";
25 break;
27 extension = "convex_physx";
28 break;
30 extension = "heightfield_physx";
31 break;
32 }
33
34 return QString::fromUtf8("%1/%2.%3")
36}
37
38static void readCachedMesh(const QString &meshFilename, physx::PxPhysics &physics,
39 physx::PxTriangleMesh *&triangleMesh, physx::PxConvexMesh *&convexMesh,
40 physx::PxHeightField *&heightField, CacheGeometry geom)
41{
42 if (MESH_CACHE_PATH.isEmpty())
43 return;
44
45 QString cacheFilename = getCachedFilename(meshFilename, geom);
46 QFile cacheFile(cacheFilename);
47 QFile meshFile(meshFilename);
48 uchar *cacheData = nullptr;
49 uchar *meshData = nullptr;
50
51 auto cleanup = qScopeGuard([&] {
52 if (cacheData)
53 cacheFile.unmap(cacheData);
54 if (meshData)
55 meshFile.unmap(meshData);
56 if (cacheFile.isOpen())
57 cacheFile.close();
58 if (meshFile.isOpen())
59 meshFile.close();
60 });
61
62 if (!cacheFile.open(QIODevice::ReadOnly)) {
63 return;
64 }
65 if (!meshFile.open(QIODevice::ReadOnly)) {
66 qWarning() << "Could not open" << meshFilename;
67 return;
68 }
69
70 // first uint64 (8 bytes) is hash of input file
71 if (cacheFile.size() <= qint64(sizeof(uint64_t))) {
72 qWarning() << "Invalid convex mesh from file" << cacheFilename;
73 return;
74 }
75
76 cacheData = cacheFile.map(0, cacheFile.size());
77 if (!cacheData) {
78 qWarning() << "Could not map" << cacheFilename;
79 return;
80 }
81 uint64_t cacheHash = *reinterpret_cast<uint64_t *>(cacheData);
82
83 meshData = meshFile.map(0, meshFile.size());
84 if (!meshData) {
85 qWarning() << "Could not map" << meshFilename;
86 return;
87 }
88 uint64_t meshHash = qHash(QByteArrayView(meshData, meshFile.size()));
89
90 if (cacheHash != meshHash)
91 return; // hash is different, need to re-cook
92
93 physx::PxDefaultMemoryInputData input(cacheData + sizeof(uint64_t),
94 physx::PxU32(cacheFile.size() - sizeof(uint64_t)));
95
96 switch (geom) {
98 triangleMesh = physics.createTriangleMesh(input);
99 qCDebug(lcQuick3dPhysics) << "Read triangle mesh" << triangleMesh << "from file"
100 << cacheFilename;
101 break;
102 }
104 convexMesh = physics.createConvexMesh(input);
105 qCDebug(lcQuick3dPhysics) << "Read convex mesh" << convexMesh << "from file"
106 << cacheFilename;
107 break;
108 }
110 heightField = physics.createHeightField(input);
111 qCDebug(lcQuick3dPhysics) << "Read height field" << heightField << "from file"
112 << cacheFilename;
113 break;
114 }
115}
116
117static void writeCachedMesh(const QString &meshFilename, physx::PxDefaultMemoryOutputStream &buf,
118 CacheGeometry geom)
119{
120 if (MESH_CACHE_PATH.isEmpty())
121 return;
122
123 QString cacheFilename = getCachedFilename(meshFilename, geom);
124 QFile cacheFile(cacheFilename);
125 QFile meshFile(meshFilename);
126 uchar *cacheData = nullptr;
127 uchar *meshData = nullptr;
128
129 auto cleanup = qScopeGuard([&] {
130 if (cacheData)
131 cacheFile.unmap(cacheData);
132 if (meshData)
133 meshFile.unmap(meshData);
134 if (cacheFile.isOpen())
135 cacheFile.close();
136 if (meshFile.isOpen())
137 meshFile.close();
138 });
139
140 if (!cacheFile.open(QIODevice::WriteOnly)) {
141 qCWarning(lcQuick3dPhysics) << "Could not open" << cacheFile.fileName() << "for writing.";
142 return;
143 }
144 if (!meshFile.open(QIODevice::ReadOnly)) {
145 qWarning() << "Could not open" << meshFilename;
146 return;
147 }
148
149 meshData = meshFile.map(0, meshFile.size());
150 if (!meshData) {
151 qWarning() << "Could not map" << meshFilename;
152 return;
153 }
154 uint64_t meshHash = qHash(QByteArrayView(meshData, meshFile.size()));
155
156 cacheFile.write(reinterpret_cast<char *>(&meshHash), sizeof(uint64_t));
157 cacheFile.write(reinterpret_cast<char *>(buf.getData()), buf.getSize());
158 cacheFile.close();
159
160 qCDebug(lcQuick3dPhysics) << "Wrote" << cacheFile.size() << "bytes to" << cacheFile.fileName();
161}
162
163void writeCachedTriangleMesh(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
164{
166}
167
168void writeCachedConvexMesh(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
169{
171}
172
173void writeCachedHeightField(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
174{
176}
177
178static void readCookedMesh(const QString &meshFilename, physx::PxPhysics &physics,
179 physx::PxTriangleMesh *&triangleMesh, physx::PxConvexMesh *&convexMesh,
180 physx::PxHeightField *&heightField, CacheGeometry geom)
181{
182 QFile file(meshFilename);
183 uchar *data = nullptr;
184
185 auto cleanup = qScopeGuard([&] {
186 if (data)
187 file.unmap(data);
188 if (file.isOpen())
189 file.close();
190 });
191
193 qWarning() << "Could not open" << meshFilename;
194 return;
195 }
196
197 data = file.map(0, file.size());
198 if (!data) {
199 qWarning() << "Could not map" << meshFilename;
200 return;
201 }
202
203 physx::PxDefaultMemoryInputData input(data, physx::PxU32(file.size()));
204
205 switch (geom) {
207 triangleMesh = physics.createTriangleMesh(input);
208 break;
209 }
211 convexMesh = physics.createConvexMesh(input);
212 break;
213 }
215 heightField = physics.createHeightField(input);
216 break;
217 }
218}
219
220physx::PxTriangleMesh *readCachedTriangleMesh(const QString &filePath, physx::PxPhysics &physics)
221{
222 physx::PxTriangleMesh *triangleMesh = nullptr;
223 physx::PxConvexMesh *convexMesh = nullptr;
224 physx::PxHeightField *heightField = nullptr;
225 readCachedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
227 return triangleMesh;
228}
229
230physx::PxConvexMesh *readCachedConvexMesh(const QString &filePath, physx::PxPhysics &physics)
231{
232 physx::PxTriangleMesh *triangleMesh = nullptr;
233 physx::PxConvexMesh *convexMesh = nullptr;
234 physx::PxHeightField *heightField = nullptr;
235 readCachedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
237 return convexMesh;
238}
239
240physx::PxHeightField *readCachedHeightField(const QString &filePath, physx::PxPhysics &physics)
241{
242 physx::PxTriangleMesh *triangleMesh = nullptr;
243 physx::PxConvexMesh *convexMesh = nullptr;
244 physx::PxHeightField *heightField = nullptr;
245 readCachedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
247 return heightField;
248}
249
250physx::PxTriangleMesh *readCookedTriangleMesh(const QString &filePath, physx::PxPhysics &physics)
251{
252 physx::PxTriangleMesh *triangleMesh = nullptr;
253 physx::PxConvexMesh *convexMesh = nullptr;
254 physx::PxHeightField *heightField = nullptr;
255 readCookedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
257 return triangleMesh;
258}
259
260physx::PxConvexMesh *readCookedConvexMesh(const QString &filePath, physx::PxPhysics &physics)
261{
262 physx::PxTriangleMesh *triangleMesh = nullptr;
263 physx::PxConvexMesh *convexMesh = nullptr;
264 physx::PxHeightField *heightField = nullptr;
265 readCookedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
267 return convexMesh;
268}
269
270physx::PxHeightField *readCookedHeightField(const QString &filePath, physx::PxPhysics &physics)
271{
272 physx::PxTriangleMesh *triangleMesh = nullptr;
273 physx::PxConvexMesh *convexMesh = nullptr;
274 physx::PxHeightField *heightField = nullptr;
275 readCookedMesh(filePath, physics, triangleMesh, convexMesh, heightField,
277 return heightField;
278}
279
280}
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
bool unmap(uchar *address)
Unmaps the memory address.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
qint64 size() const override
\reimp
Definition qfile.cpp:1179
bool isOpen() const
Returns true if the device is open; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
void extension()
[6]
Definition dialogs.cpp:230
static void readCookedMesh(const QString &meshFilename, physx::PxPhysics &physics, physx::PxTriangleMesh *&triangleMesh, physx::PxConvexMesh *&convexMesh, physx::PxHeightField *&heightField, CacheGeometry geom)
void writeCachedConvexMesh(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
void writeCachedTriangleMesh(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
static void readCachedMesh(const QString &meshFilename, physx::PxPhysics &physics, physx::PxTriangleMesh *&triangleMesh, physx::PxConvexMesh *&convexMesh, physx::PxHeightField *&heightField, CacheGeometry geom)
physx::PxTriangleMesh * readCachedTriangleMesh(const QString &filePath, physx::PxPhysics &physics)
void writeCachedHeightField(const QString &filePath, physx::PxDefaultMemoryOutputStream &buf)
physx::PxConvexMesh * readCookedConvexMesh(const QString &filePath, physx::PxPhysics &physics)
physx::PxTriangleMesh * readCookedTriangleMesh(const QString &filePath, physx::PxPhysics &physics)
physx::PxHeightField * readCookedHeightField(const QString &filePath, physx::PxPhysics &physics)
static QString MESH_CACHE_PATH
static void writeCachedMesh(const QString &meshFilename, physx::PxDefaultMemoryOutputStream &buf, CacheGeometry geom)
static QString getCachedFilename(const QString &filePath, CacheGeometry geom)
physx::PxConvexMesh * readCachedConvexMesh(const QString &filePath, physx::PxPhysics &physics)
physx::PxHeightField * readCachedHeightField(const QString &filePath, physx::PxPhysics &physics)
Combined button and popup list for selecting options.
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
#define qWarning
Definition qlogging.h:166
#define qCWarning(category,...)
#define qCDebug(category,...)
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLenum GLenum input
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
unsigned char uchar
Definition qtypes.h:32
long long qint64
Definition qtypes.h:60
QFile file
[0]