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