Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssglightmapuvgenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5#include "xatlas.h"
6
8
9QSSGLightmapUVGeneratorResult QSSGLightmapUVGenerator::run(const QByteArray &positions,
10 const QByteArray &normals,
11 const QByteArray &uv0,
12 const QByteArray &index,
13 QSSGMesh::Mesh::ComponentType indexComponentType,
14 float texelsPerUnit)
15{
16 QSSGLightmapUVGeneratorResult result;
17
18 xatlas::MeshDecl meshInfo;
19
20 if (indexComponentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16) {
21 meshInfo.indexFormat = xatlas::IndexFormat::UInt16;
22 } else if (indexComponentType == QSSGMesh::Mesh::ComponentType::UnsignedInt32) {
23 meshInfo.indexFormat = xatlas::IndexFormat::UInt32;
24 } else {
25 qWarning("Lightmap UV generator: Unknown index type %d; cannot generate",
26 int(indexComponentType));
27 return result;
28 }
29
30 const quint32 indexComponentByteSize = QSSGMesh::MeshInternal::byteSizeForComponentType(indexComponentType);
31 const quint32 indexCount = index.size() / indexComponentByteSize;
32
33 meshInfo.indexCount = indexCount;
34 meshInfo.indexData = index.constData();
35
36 const quint32 positionStride = 3 * sizeof(float);
37 const quint32 normalStride = 3 * sizeof(float);
38 const quint32 uvStride = 2 * sizeof(float);
39
40 meshInfo.vertexCount = positions.size() / positionStride;
41 meshInfo.vertexPositionData = positions.data();
42 meshInfo.vertexPositionStride = positionStride;
43
44 if (!normals.isEmpty()) {
45 meshInfo.vertexNormalData = normals.constData();
46 meshInfo.vertexNormalStride = normalStride;
47 } else {
48 meshInfo.vertexNormalData = nullptr;
49 meshInfo.vertexNormalStride = 0;
50 }
51
52 if (!uv0.isEmpty()) {
53 meshInfo.vertexUvData = uv0.constData();
54 meshInfo.vertexUvStride = uvStride;
55 } else {
56 meshInfo.vertexUvData = nullptr;
57 meshInfo.vertexUvStride = 0;
58 }
59
60 xatlas::PackOptions packOptions;
61 packOptions.maxChartSize = 4096;
62 packOptions.padding = 1;
63 packOptions.resolution = 0;
64 packOptions.texelsPerUnit = texelsPerUnit;
65 packOptions.blockAlign = true;
66
67 xatlas::ChartOptions chartOptions;
68
69 xatlas::Atlas *atlas = xatlas::Create();
70 xatlas::AddMeshError err = xatlas::AddMesh(atlas, meshInfo, 1);
71 if (err != xatlas::AddMeshError::Success) {
72 qWarning("Failed to register mesh for UV unwrapping (error %d)", int(err));
73 xatlas::Destroy(atlas);
74 return result;
75 }
76 xatlas::Generate(atlas, chartOptions, packOptions);
77
78 const uint32_t textureWidth = atlas->width;
79 const uint32_t textureHeight = atlas->height;
80 if (textureWidth == 0 || textureHeight == 0) {
81 qWarning("Texture size is empty, UV unwrapping failed");
82 xatlas::Destroy(atlas);
83 return result;
84 }
85 result.lightmapWidth = textureWidth;
86 result.lightmapHeight = textureHeight;
87
88 const xatlas::Mesh &output = atlas->meshes[0];
89 result.lightmapUVChannel.resize(output.vertexCount * uvStride);
90 result.vertexMap.resize(output.vertexCount);
91
92 float *uvPtr = reinterpret_cast<float *>(result.lightmapUVChannel.data());
93 for (uint32_t i = 0; i < output.vertexCount; ++i) {
94 const float u = output.vertexArray[i].uv[0] / float(textureWidth);
95 const float v = output.vertexArray[i].uv[1] / float(textureHeight);
96 *uvPtr++ = u;
97 *uvPtr++ = v;
98 result.vertexMap[i] = output.vertexArray[i].xref;
99 }
100
101 result.indexData.resize(output.indexCount * sizeof(quint32));
102 quint32 *indexPtr = reinterpret_cast<quint32 *>(result.indexData.data());
103 for (uint32_t i = 0; i < output.indexCount; ++i)
104 *indexPtr++ = output.indexArray[i];
105
106 xatlas::Destroy(atlas);
107
108 return result;
109}
110
111QT_END_NAMESPACE