6#include <QtCore/QVector>
7#include <QtQuick3DUtils/private/qssgdataref_p.h>
8#include <QtQuick3DUtils/private/qssglightmapuvgenerator_p.h>
10#include "meshoptimizer.h"
47 device->seek(multiHeaderStartOffset);
62 inputStream >> multiEntriesOffset >> meshCount;
65 device->seek(multiHeaderStartOffset
88 outputStream <<
offset <<
id << padding;
92 outputStream << meshFileInfo.
fileId << meshFileInfo.
fileVersion << multiEntriesOffset << meshCount;
97 static char alignPadding[4] = {};
121 quint32 targetBufferEntriesCount;
122 quint32 vertexBufferEntriesCount;
125 inputStream >> targetBufferEntriesCount
126 >> vertexBufferEntriesCount
127 >> mesh->m_vertexBuffer.
stride
128 >> targetBufferDataSize
129 >> vertexBufferDataSize;
131 if (!
header->hasSeparateTargetBuffer()) {
132 targetBufferEntriesCount = 0;
133 targetBufferDataSize = 0;
136 quint32 indexBufferComponentType;
139 inputStream >> indexBufferComponentType
140 >> indexBufferDataOffset
141 >> indexBufferDataSize;
146 inputStream >> targetCount >> subsetsCount;
147 mesh->m_targetBuffer.
numTargets = targetCount;
151 inputStream >> jointsOffsets >> jointsCount;
154 inputStream >> drawMode >> winding;
161 for (
quint32 i = 0;
i < vertexBufferEntriesCount; ++
i) {
165 inputStream >> nameOffset
168 >> vertexBufferEntry.
offset;
170 mesh->m_vertexBuffer.
entries.append(vertexBufferEntry);
175 device->read(alignPadding, alignAmount);
184 inputStream >> nameLength;
190 device->read(alignPadding, alignAmount);
197 if (
entry.name.sliced(6).startsWith(
"pos")) {
202 numTargets =
qMax(numTargets, targetId + 1);
205 targetBufferEntriesCount++;
206 }
else if (
entry.name.sliced(6).startsWith(
"norm")) {
210 numTargets =
qMax(numTargets, targetId + 1);
213 targetBufferEntriesCount++;
214 }
else if (
entry.name.sliced(6).startsWith(
"tan")) {
218 numTargets =
qMax(numTargets, targetId + 1);
221 targetBufferEntriesCount++;
222 }
else if (
entry.name.sliced(6).startsWith(
"binorm")) {
226 numTargets =
qMax(numTargets, targetId + 1);
229 targetBufferEntriesCount++;
230 }
else if (
entry.name.startsWith(
"attr_unsupported")) {
232 entry.name = attrNames[targetBufferEntriesCount % attrNames.
size()];
234 targetBufferEntriesCount++;
239 mesh->m_vertexBuffer.
data =
device->read(vertexBufferDataSize);
242 device->read(alignPadding, alignAmount);
244 mesh->m_indexBuffer.
data =
device->read(indexBufferDataSize);
247 device->read(alignPadding, alignAmount);
260 inputStream >> subset.
count
272 if (
header->hasLightmapSizeHint()) {
277 if (
header->hasLodDataHint()) {
279 inputStream >> lodCount;
289 internalSubsets.
append(subset);
294 device->read(alignPadding, alignAmount);
297 internalSubset.rawNameUtf16 =
device->read(internalSubset.nameLength * 2);
298 alignAmount = offsetTracker.
alignedAdvance(internalSubset.nameLength * 2);
300 device->read(alignPadding, alignAmount);
305 auto meshSubset = internalSubset.toMeshSubset();
307 for (
auto &
lod : meshSubset.lods) {
318 mesh->m_subsets.append(meshSubset);
322 device->read(alignPadding, alignAmount);
326 if (targetBufferEntriesCount > 0) {
327 if (
header->hasSeparateTargetBuffer()) {
329 for (
quint32 i = 0;
i < targetBufferEntriesCount; ++
i) {
333 inputStream >> nameOffset
336 >> targetBufferEntry.
offset;
338 mesh->m_targetBuffer.
entries.append(targetBufferEntry);
343 device->read(alignPadding, alignAmount);
347 inputStream >> nameLength;
353 device->read(alignPadding, alignAmount);
356 mesh->m_targetBuffer.
data =
device->read(targetBufferDataSize);
359 mesh->m_vertexBuffer.
entries.remove(vertexBufferEntriesCount - targetBufferEntriesCount,
360 targetBufferEntriesCount);
361 const quint32 vertexCount = vertexBufferDataSize / mesh->m_vertexBuffer.
stride;
363 const quint32 targetCompStride = targetEntryTexWidth * targetEntryTexWidth * 4 *
sizeof(float);
364 mesh->m_targetBuffer.
data.
resize(targetCompStride * targetBufferEntriesCount);
365 const quint32 numComps = targetBufferEntriesCount / numTargets;
366 for (
quint32 i = 0;
i < targetBufferEntriesCount; ++
i) {
368 char *dstBuf = mesh->m_targetBuffer.
data.
data()
369 + (
i / numComps) * targetCompStride
370 + (
i % numComps) * (targetCompStride * numTargets);
374 memcpy(dstBuf +
j * 4 *
sizeof(
float),
375 srcBuf +
j * mesh->m_vertexBuffer.
stride,
378 entry.offset =
i * targetCompStride;
381 mesh->m_targetBuffer.
entries.remove(numComps, targetBufferEntriesCount - numComps);
386 return header->sizeInBytes;
409 static const char alignPadding[4] = {};
419 const quint32 vertexBufferEntriesCount = mesh.m_vertexBuffer.
entries.size();
421 const quint32 vertexBufferStride = mesh.m_vertexBuffer.
stride;
422 const quint32 targetBufferEntriesCount = mesh.m_targetBuffer.
entries.count();
424 outputStream << targetBufferEntriesCount
425 << vertexBufferEntriesCount
426 << vertexBufferStride;
427 outputStream << targetBufferDataSize
428 << vertexBufferDataSize;
432 outputStream << indexComponentType;
434 << indexBufferDataSize;
437 const quint32 subsetsCount = mesh.m_subsets.size();
438 outputStream << targetCount
446 outputStream << drawMode
452 for (
quint32 i = 0;
i < vertexBufferEntriesCount; ++
i) {
465 device->write(alignPadding, alignAmount);
467 for (
quint32 i = 0;
i < vertexBufferEntriesCount; ++
i) {
470 outputStream << nameLength;
474 device->write(alignPadding, alignAmount);
480 device->write(alignPadding, alignAmount);
485 device->write(alignPadding, alignAmount);
502 outputStream << subsetCount
512 outputStream << lightmapSizeHintWidth
513 << lightmapSizeHintHeight;
514 outputStream << lodCount;
519 device->write(alignPadding, alignAmount);
523 const char *utf16Name =
reinterpret_cast<const char *
>(subset.
name.
utf16());
525 device->write(utf16Name, nameByteSize);
528 device->write(alignPadding, alignAmount);
545 device->write(alignPadding, alignAmount);
548 for (
quint32 i = 0;
i < targetBufferEntriesCount; ++
i) {
561 device->write(alignPadding, alignAmount);
563 for (
quint32 i = 0;
i < targetBufferEntriesCount; ++
i) {
566 outputStream << nameLength;
570 device->write(alignPadding, alignAmount);
576 const quint32 sizeInBytes = endPos - startPos;
611 qWarning(
"Failed to find mesh #%u",
it.key());
621 return offset + (align - leftover);
645 if (
entry.data.isEmpty())
653 if (
entry.morphTargetId < 0) {
664 numItems = localNumItems;
665 }
else if (numItems != localNumItems) {
668 numItems =
qMin(numItems, localNumItems);
672 meshEntry.
offset = currentOffset;
674 mesh.m_vertexBuffer.
entries.append(meshEntry);
675 currentOffset += byteSize;
679 if (!targetCompStride) {
682 targetCompStride = targetEntryTexWidth * targetEntryTexWidth * 4 *
sizeof(float);
683 mesh.m_targetBuffer.
data.
resize(targetCompStride * numTargets * numTargetComps);
688 meshEntry.
offset = (targetCurrentComp * numTargets +
entry.morphTargetId)
695 if (
entry.morphTargetId == 0)
696 mesh.m_targetBuffer.
entries.append(meshEntry);
698 targetCurrentComp = (targetCurrentComp + 1 < numTargetComps) ? targetCurrentComp + 1 : 0;
708 for (
quint32 idx = 0; idx < numItems; ++idx) {
711 if (
entry.data.isEmpty())
718 if (newOffset != dataOffset) {
719 QByteArray filler(newOffset - dataOffset,
'\0');
724 dataOffset = newOffset + byteSize;
730 mesh.m_indexBuffer.
data = indexBufferData;
734 meshSubset.
name = subset.name;
735 meshSubset.
count = subset.count;
736 meshSubset.
offset = subset.offset;
739 if (subset.boundsPositionEntryIndex != std::numeric_limits<quint32>::max()) {
741 mesh.m_vertexBuffer.
entries[subset.boundsPositionEntryIndex],
742 mesh.m_vertexBuffer.
data,
743 mesh.m_vertexBuffer.
stride,
744 mesh.m_indexBuffer.
data,
753 meshSubset.
lods = subset.lods;
755 mesh.m_subsets.append(meshSubset);
758 mesh.m_drawMode = DrawMode::Triangles;
759 mesh.m_winding = Winding::CounterClockwise;
766 if (
data.m_vertexBuffer.size() == 0) {
767 *
error = QObject::tr(
"Vertex buffer empty");
770 if (
data.m_attributeCount == 0) {
771 *
error = QObject::tr(
"No attributes defined");
776 mesh.m_drawMode =
data.m_primitiveType;
777 mesh.m_winding = Winding::CounterClockwise;
779 for (
int i = 0;
i <
data.m_attributeCount; ++
i) {
784 const char *
name =
nullptr;
814 *
error = QObject::tr(
"Warning: Invalid attribute semantic: %1")
828 mesh.m_vertexBuffer.
data =
data.m_vertexBuffer;
832 mesh.m_subsets =
data.m_subsets;
833 mesh.m_indexBuffer.
data =
data.m_indexBuffer;
835 if (!
data.m_targetBuffer.isEmpty()) {
838 const quint32 targetCompStride = targetEntryTexWidth * targetEntryTexWidth * 4 *
sizeof(float);
839 mesh.m_targetBuffer.
data.
resize(targetCompStride *
data.m_targetAttributeCount);
842 data.m_targetAttributes,
843 data.m_targetAttributes +
data.m_targetAttributeCount);
844 std::sort(sortedAttribs.
begin(), sortedAttribs.
end(),
846 return (a.targetId == b.targetId) ? a.attr.semantic < b.attr.semantic :
847 a.targetId < b.targetId; });
848 for (
int i = 0;
i <
data.m_targetAttributeCount; ++
i) {
851 : sortedAttribs[
i].stride;
852 const char *
name =
nullptr;
875 *
error = QObject::tr(
"Warning: Invalid target attribute semantic: %1")
882 *
error = QObject::tr(
"Warning: Invalid target attribute semantic: %1")
886 char *dstBuf = mesh.m_targetBuffer.
data.
data() +
i * targetCompStride;
887 const char *srcBuf =
data.m_targetBuffer.constData() + att.
offset;
889 if (
stride == 4 *
sizeof(
float)) {
890 memcpy(dstBuf, srcBuf, vertexCount *
stride);
893 memcpy(dstBuf +
j * 4 *
sizeof(
float),
899 if (sortedAttribs[
i].targetId == 0) {
903 entry.offset =
i * targetCompStride;
915 qint64 newMeshStartPosFromEnd = 0;
922 qWarning(
"There is existing data, but mesh file header is invalid; cannot save");
930 newId =
qMax(newId,
it.key() + 1);
966 if (
entry.componentType != Mesh::ComponentType::Float32 ||
entry.componentCount != 3) {
972 if (indexComponentByteSize != 2 && indexComponentByteSize != 4) {
977 const quint32 indexBufferCount = indexBufferData.
size() / indexComponentByteSize;
978 const quint32 vertexBufferByteSize = vertexBufferData.
size();
979 const char *vertexSrcPtr = vertexBufferData.
constData();
980 const char *indexSrcPtr = indexBufferData.
constData();
982 for (
quint32 idx = 0, numItems = subsetCount; idx < numItems; ++idx) {
983 if (idx + subsetOffset >= indexBufferCount)
987 switch (indexComponentByteSize) {
989 vertexIdx =
reinterpret_cast<const quint16 *
>(indexSrcPtr)[idx + subsetOffset];
992 vertexIdx =
reinterpret_cast<const quint32 *
>(indexSrcPtr)[idx + subsetOffset];
999 const quint32 finalOffset =
entry.offset + (vertexIdx * vertexBufferStride);
1001 if (finalOffset +
sizeof(
v) <= vertexBufferByteSize) {
1002 memcpy(
v, vertexSrcPtr + finalOffset,
sizeof(
v));
1016 if (vbe.name == lightmapAttrName)
1033 const char *srcVertexData = m_vertexBuffer.
data.
constData();
1035 if (!srcVertexStride) {
1036 qWarning(
"Lightmap UV unwrapping encountered a Mesh with 0 vertex stride, this cannot happen");
1040 qWarning(
"Lightmap UV unwrapping encountered a Mesh without index data, this cannot happen");
1044 quint32 positionOffset = UINT32_MAX;
1045 quint32 normalOffset = UINT32_MAX;
1046 quint32 uvOffset = UINT32_MAX;
1049 if (vbe.name == posAttrName) {
1050 if (vbe.componentCount != 3) {
1051 qWarning(
"Lightmap UV unwrapping encountered a Mesh non-float3 position data, this cannot happen");
1054 positionOffset = vbe.offset;
1055 }
else if (vbe.name == normalAttrName) {
1056 if (vbe.componentCount != 3) {
1057 qWarning(
"Lightmap UV unwrapping encountered a Mesh non-float3 normal data, this cannot happen");
1060 normalOffset = vbe.offset;
1061 }
else if (vbe.name == uvAttrName) {
1062 if (vbe.componentCount != 2) {
1063 qWarning(
"Lightmap UV unwrapping encountered a Mesh non-float2 UV0 data, this cannot happen");
1066 uvOffset = vbe.offset;
1070 if (positionOffset == UINT32_MAX) {
1071 qWarning(
"Lightmap UV unwrapping encountered a Mesh without vertex positions, this cannot happen");
1078 float *posPtr =
reinterpret_cast<float *
>(positionData.
data());
1080 const char *vertexBasePtr = srcVertexData +
i * srcVertexStride;
1081 const float *srcPos =
reinterpret_cast<const float *
>(vertexBasePtr + positionOffset);
1082 *posPtr++ = *srcPos++;
1083 *posPtr++ = *srcPos++;
1084 *posPtr++ = *srcPos++;
1088 if (normalOffset != UINT32_MAX) {
1089 normalData.
resize(vertexCount * 3 *
sizeof(
float));
1090 float *normPtr =
reinterpret_cast<float *
>(normalData.
data());
1092 const char *vertexBasePtr = srcVertexData +
i * srcVertexStride;
1093 const float *srcNormal =
reinterpret_cast<const float *
>(vertexBasePtr + normalOffset);
1094 *normPtr++ = *srcNormal++;
1095 *normPtr++ = *srcNormal++;
1096 *normPtr++ = *srcNormal++;
1101 if (uvOffset != UINT32_MAX) {
1102 uvData.
resize(vertexCount * 2 *
sizeof(
float));
1103 float *uvPtr =
reinterpret_cast<float *
>(uvData.
data());
1105 const char *vertexBasePtr = srcVertexData +
i * srcVertexStride;
1106 const float *srcUv =
reinterpret_cast<const float *
>(vertexBasePtr + uvOffset);
1107 *uvPtr++ = *srcUv++;
1108 *uvPtr++ = *srcUv++;
1115 lightmapBaseResolution);
1120 const int newVertexCount =
r.
vertexMap.size();
1123 const quint32 *newIndex =
reinterpret_cast<const quint32 *
>(
r.indexData.constData());
1124 if (m_indexBuffer.
componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt32) {
1125 if (
r.indexData.size() != m_indexBuffer.
data.
size()) {
1126 qWarning(
"Index buffer size mismatch after lightmap UV unwrapping");
1130 memcpy(indexDst, newIndex, m_indexBuffer.
data.
size());
1132 if (
r.indexData.size() != m_indexBuffer.
data.
size() * 2) {
1133 qWarning(
"Index buffer size mismatch after lightmap UV unwrapping");
1138 *indexDst++ = *newIndex++;
1149 memcpy(
dst, srcVertexData +
i * srcVertexStride + vbe.offset, byteSize);
1152 switch (vbe.componentType) {
1153 case ComponentType::UnsignedInt8:
1154 newData.
append(QSSGLightmapUVGenerator::remap<quint8>(
data,
r.vertexMap, vbe.componentCount));
1156 case ComponentType::Int8:
1157 newData.
append(QSSGLightmapUVGenerator::remap<qint8>(
data,
r.vertexMap, vbe.componentCount));
1159 case ComponentType::UnsignedInt16:
1160 newData.
append(QSSGLightmapUVGenerator::remap<quint16>(
data,
r.vertexMap, vbe.componentCount));
1162 case ComponentType::Int16:
1163 newData.
append(QSSGLightmapUVGenerator::remap<qint16>(
data,
r.vertexMap, vbe.componentCount));
1165 case ComponentType::UnsignedInt32:
1166 newData.
append(QSSGLightmapUVGenerator::remap<quint32>(
data,
r.vertexMap, vbe.componentCount));
1168 case ComponentType::Int32:
1169 newData.
append(QSSGLightmapUVGenerator::remap<qint32>(
data,
r.vertexMap, vbe.componentCount));
1171 case ComponentType::UnsignedInt64:
1172 newData.
append(QSSGLightmapUVGenerator::remap<quint64>(
data,
r.vertexMap, vbe.componentCount));
1174 case ComponentType::Int64:
1175 newData.
append(QSSGLightmapUVGenerator::remap<qint64>(
data,
r.vertexMap, vbe.componentCount));
1177 case ComponentType::Float16:
1178 newData.
append(QSSGLightmapUVGenerator::remap<qfloat16>(
data,
r.vertexMap, vbe.componentCount));
1180 case ComponentType::Float32:
1181 newData.
append(QSSGLightmapUVGenerator::remap<float>(
data,
r.vertexMap, vbe.componentCount));
1183 case ComponentType::Float64:
1184 newData.
append(QSSGLightmapUVGenerator::remap<double>(
data,
r.vertexMap, vbe.componentCount));
1192 lightmapUVEntry.
offset = 0;
1193 lightmapUVEntry.
name = lightmapAttrName;
1196 newVertexBuffer.
reserve(newVertexCount * (srcVertexStride + 8));
1199 for (
int vertexIdx = 0; vertexIdx < newVertexCount; ++vertexIdx) {
1201 for (
int vbIdx = 0,
end = m_vertexBuffer.
entries.size(); vbIdx !=
end; ++vbIdx) {
1209 if (newOffset != dataOffset) {
1210 QByteArray filler(newOffset - dataOffset,
'\0');
1211 newVertexBuffer.
append(filler);
1217 newVertexBuffer.
append(newData[vbIdx].constData() + byteSize * vertexIdx, byteSize);
1218 dataOffset = newOffset + byteSize;
1221 const quint32 byteSize = 2 *
sizeof(float);
1223 if (newOffset != dataOffset) {
1224 QByteArray filler(newOffset - dataOffset,
'\0');
1225 newVertexBuffer.
append(filler);
1229 lightmapUVEntry.
offset = newVertexBuffer.
size();
1231 newVertexBuffer.
append(
r.lightmapUVChannel.constData() + byteSize * vertexIdx, byteSize);
1232 dataOffset = newOffset + byteSize;
1238 m_vertexBuffer.
entries.append(lightmapUVEntry);
1240 m_vertexBuffer.
data = newVertexBuffer;
1242 const QSize lightmapSizeHint(
r.lightmapWidth,
r.lightmapHeight);
1243 for (
Subset &subset : m_subsets)
1244 subset.lightmapSizeHint = lightmapSizeHint;
1249size_t simplifyMesh(
unsigned int *
destination,
const unsigned int *
indices,
size_t indexCount,
const float *vertexPositions,
size_t vertexCount,
size_t vertexPositionsStride,
size_t targetIndexCount,
float targetError,
unsigned int options,
float *resultError)
1251 return meshopt_simplify(
destination,
indices, indexCount, vertexPositions, vertexCount, vertexPositionsStride, targetIndexCount, targetError, options, resultError);
1254float simplifyScale(
const float *vertexPositions,
size_t vertexCount,
size_t vertexPositionsStride)
1256 return meshopt_simplifyScale(vertexPositions, vertexCount, vertexPositionsStride);
IOBluetoothDevice * device
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore\reentrant
void setFloatingPointPrecision(FloatingPointPrecision precision)
Sets the floating point precision of the data stream to precision.
void setByteOrder(ByteOrder)
Sets the serialization byte order to bo.
\inmodule QtCore \reentrant
qsizetype size() const noexcept
void append(parameter_type t)
iterator insert(const Key &key, const T &value)
const_iterator cend() const
const_iterator cbegin() const
const_iterator constFind(const Key &key) const
const_iterator constEnd() const
Class representing 3D range or axis aligned bounding box.
QSSGLightmapUVGeneratorResult run(const QByteArray &positions, const QByteArray &normals, const QByteArray &uv0, const QByteArray &index, QSSGMesh::Mesh::ComponentType indexComponentType, uint baseResolution)
static Mesh fromAssetData(const QVector< AssetVertexEntry > &vbufEntries, const QByteArray &indexBufferData, ComponentType indexComponentType, const QVector< AssetMeshSubset > &subsets, quint32 numTargets=0, quint32 numTargetComps=0)
bool createLightmapUVChannel(uint lightmapBaseResolution)
QSSGRenderWinding Winding
static Mesh fromRuntimeData(const RuntimeMeshData &data, QString *error)
static QMap< quint32, Mesh > loadAll(QIODevice *device)
QSSGRenderComponentType ComponentType
static Mesh loadMesh(QIODevice *device, quint32 id=0)
bool hasLightmapUVChannel() const
QSSGRenderDrawMode DrawMode
QVector< Subset > subsets() const
quint32 save(QIODevice *device, quint32 id=0) const
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
const_iterator cbegin() const
qsizetype size() const
Returns the number of characters in this string.
const_iterator cend() const
QString & insert(qsizetype i, QChar c)
void reserve(qsizetype sz)
iterator begin() noexcept
The QVector3D class represents a vector or vertex in 3D space.
constexpr float y() const noexcept
Returns the y coordinate of this point.
constexpr float x() const noexcept
Returns the x coordinate of this point.
constexpr float z() const noexcept
Returns the z coordinate of this point.
QSet< QString >::iterator it
static const size_t LOD_STRUCT_SIZE
float simplifyScale(const float *vertexPositions, size_t vertexCount, size_t vertexPositionsStride)
static const size_t SUBSET_STRUCT_SIZE_V5
static const size_t MESH_HEADER_STRUCT_SIZE
void optimizeVertexCache(unsigned int *destination, const unsigned int *indices, size_t indexCount, size_t vertexCount)
static const size_t MESH_STRUCT_SIZE
static const size_t VERTEX_BUFFER_ENTRY_STRUCT_SIZE
size_t simplifyMesh(unsigned int *destination, const unsigned int *indices, size_t indexCount, const float *vertexPositions, size_t vertexCount, size_t vertexPositionsStride, size_t targetIndexCount, float targetError, unsigned int options, float *resultError)
static quint32 getAlignedOffset(quint32 offset, quint32 align)
static const size_t MULTI_HEADER_STRUCT_SIZE
static const size_t SUBSET_STRUCT_SIZE_V3_V4
static const size_t MULTI_ENTRY_STRUCT_SIZE
static const size_t SUBSET_STRUCT_SIZE_V6
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char * destination
DBusConnection const char DBusError * error
static QString header(const QString &name)
qfloat16 qSqrt(qfloat16 f)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLsizei GLsizei height
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
const void GLsizei GLsizei stride
GLsizei GLsizei GLfloat distance
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat maxZ
GLsizei GLenum const void * indices
GLfloat GLfloat GLfloat GLfloat maxX
unsigned long long quint64
QVector< quint32 > vertexMap
void advance(int advanceAmount)
quint32 alignedAdvance(int advanceAmount)
static MultiMeshInfo withDefaults()
QMap< quint32, quint64 > meshEntries
Mesh::SubsetBounds bounds
static quint32 byteSizeForComponentType(Mesh::ComponentType componentType)
static const char * getLightmapUVAttrName()
static const char * getNormalAttrName()
static quint64 writeMeshData(QIODevice *device, const Mesh &mesh)
static const char * getUV1AttrName()
static const char * getTexBinormalAttrName()
static MultiMeshInfo readFileHeader(QIODevice *device)
static const char * getPositionAttrName()
static quint64 readMeshData(QIODevice *device, quint64 offset, Mesh *mesh, MeshDataHeader *header)
static const char * getTexTanAttrName()
static QSSGBounds3 calculateSubsetBounds(const Mesh::VertexBufferEntry &entry, const QByteArray &vertexBufferData, quint32 vertexBufferStride, const QByteArray &indexBufferData, Mesh::ComponentType indexComponentType, quint32 subsetCount, quint32 subsetOffset)
static const char * getColorAttrName()
static void writeFileHeader(QIODevice *device, const MultiMeshInfo &meshFileInfo)
static void writeMeshHeader(QIODevice *device, const MeshDataHeader &header)
static const char * getJointAttrName()
static const char * getUV0AttrName()
static const char * getWeightAttrName()
ComponentType componentType
QVector< VertexBufferEntry > entries
ComponentType componentType
QVector< VertexBufferEntry > entries
int componentCount() const
Mesh::ComponentType componentType