aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick3d/bakedlightmap/Box.qml2
-rw-r--r--examples/quick3d/bakedlightmap/main.qml1
-rw-r--r--src/plugins/assetimporters/assimp/assimpimporter_rt.cpp11
-rw-r--r--src/plugins/assetimporters/assimp/assimputils.cpp6
-rw-r--r--src/plugins/assetimporters/assimp/assimputils.h3
-rw-r--r--src/plugins/assetimporters/assimp/options.json26
-rw-r--r--src/quick3d/qquick3dlightmapper.cpp28
-rw-r--r--src/quick3d/qquick3dlightmapper_p.h5
-rw-r--r--src/quick3d/qquick3dmodel.cpp59
-rw-r--r--src/quick3d/qquick3dmodel_p.h7
-rw-r--r--src/quick3d/qquick3dscenerenderer.cpp1
-rw-r--r--src/runtimerender/graphobjects/qssgrendermodel_p.h2
-rw-r--r--src/runtimerender/rendererimpl/qssglightmapper.cpp33
-rw-r--r--src/runtimerender/rendererimpl/qssglightmapper.h1
-rw-r--r--src/utils/qssglightmapuvgenerator.cpp5
-rw-r--r--src/utils/qssglightmapuvgenerator_p.h8
-rw-r--r--src/utils/qssgmesh.cpp18
-rw-r--r--src/utils/qssgmesh_p.h2
18 files changed, 120 insertions, 98 deletions
diff --git a/examples/quick3d/bakedlightmap/Box.qml b/examples/quick3d/bakedlightmap/Box.qml
index 0cabcf93..eb885b10 100644
--- a/examples/quick3d/bakedlightmap/Box.qml
+++ b/examples/quick3d/bakedlightmap/Box.qml
@@ -6,8 +6,8 @@ import QtQuick3D
Node {
property alias usedInBakedLighting: cornellBox_Original.usedInBakedLighting
- property alias lightmapBaseResolution: cornellBox_Original.lightmapBaseResolution
property alias bakedLightmap: cornellBox_Original.bakedLightmap
+ property alias texelsPerUnit: cornellBox_Original.texelsPerUnit
// Materials
PrincipledMaterial {
diff --git a/examples/quick3d/bakedlightmap/main.qml b/examples/quick3d/bakedlightmap/main.qml
index 5c02288b..7ff1ccf7 100644
--- a/examples/quick3d/bakedlightmap/main.qml
+++ b/examples/quick3d/bakedlightmap/main.qml
@@ -45,7 +45,6 @@ Window {
//! [model]
Box {
usedInBakedLighting: true
- lightmapBaseResolution: 256
bakedLightmap: BakedLightmap {
enabled: root.lmEnabled
key: "box"
diff --git a/src/plugins/assetimporters/assimp/assimpimporter_rt.cpp b/src/plugins/assetimporters/assimp/assimpimporter_rt.cpp
index 39bb27a5..6cee41b5 100644
--- a/src/plugins/assetimporters/assimp/assimpimporter_rt.cpp
+++ b/src/plugins/assetimporters/assimp/assimpimporter_rt.cpp
@@ -129,10 +129,8 @@ struct SceneInfo
bool binaryKeyframes = false;
bool forceMipMapGeneration = false;
bool useFloatJointIndices = false;
- bool generateLightmapUV = false;
bool designStudioWorkarounds = false;
- int lightmapBaseResolution = 1024;
float globalScaleValue = 1.0;
bool generateMeshLODs = false;
@@ -1300,8 +1298,6 @@ static void setModelProperties(QSSGSceneDesc::Model &target, const aiNode &sourc
sceneInfo.opt.generateMeshLODs,
sceneInfo.opt.lodNormalMergeAngle,
sceneInfo.opt.lodNormalSplitAngle,
- sceneInfo.opt.generateLightmapUV,
- sceneInfo.opt.lightmapBaseResolution,
errorString);
meshStorage.push_back(std::move(meshData));
@@ -1658,13 +1654,6 @@ static SceneInfo::Options processSceneOptions(const QJsonObject &optionsObject)
sceneOptions.useFloatJointIndices = checkBooleanOption(QStringLiteral("useFloatJointIndices"), options);
sceneOptions.forceMipMapGeneration = checkBooleanOption(QStringLiteral("generateMipMaps"), options);
sceneOptions.binaryKeyframes = checkBooleanOption(QStringLiteral("useBinaryKeyframes"), options);
-
- sceneOptions.generateLightmapUV = checkBooleanOption(QStringLiteral("generateLightmapUV"), options);
- if (sceneOptions.generateLightmapUV) {
- qreal v = getRealOption(QStringLiteral("lightmapBaseResolution"), options);
- sceneOptions.lightmapBaseResolution = v == 0.0 ? 1024 : int(v);
- }
-
sceneOptions.generateMeshLODs = checkBooleanOption(QStringLiteral("generateMeshLevelsOfDetail"), options);
if (sceneOptions.generateMeshLODs) {
bool recalculateLODNormals = checkBooleanOption(QStringLiteral("recalculateLodNormals"), options);
diff --git a/src/plugins/assetimporters/assimp/assimputils.cpp b/src/plugins/assetimporters/assimp/assimputils.cpp
index 9ad9509b..c5418f31 100644
--- a/src/plugins/assetimporters/assimp/assimputils.cpp
+++ b/src/plugins/assetimporters/assimp/assimputils.cpp
@@ -667,8 +667,6 @@ QSSGMesh::Mesh AssimpUtils::generateMeshData(const aiScene &scene,
bool generateLevelsOfDetail,
float normalMergeAngle,
float normalSplitAngle,
- bool generateLightmapUV,
- int lightmapBaseResolution,
QString &errorString)
{
Q_UNUSED(errorString);
@@ -819,10 +817,6 @@ QSSGMesh::Mesh AssimpUtils::generateMeshData(const aiScene &scene,
subsets,
requirments.numMorphTargets,
numTargetComponents(requirments));
-
- if (generateLightmapUV && mesh.isValid())
- mesh.createLightmapUVChannel(lightmapBaseResolution);
-
return mesh;
}
diff --git a/src/plugins/assetimporters/assimp/assimputils.h b/src/plugins/assetimporters/assimp/assimputils.h
index 89086183..db857306 100644
--- a/src/plugins/assetimporters/assimp/assimputils.h
+++ b/src/plugins/assetimporters/assimp/assimputils.h
@@ -26,10 +26,7 @@ QSSGMesh::Mesh generateMeshData(const aiScene &scene,
bool generateLevelsOfDetail,
float normalMergeAngle,
float normalSplitAngle,
- bool generateLightmapUV,
- int lightmapBaseResolution,
QString &errorString);
-
}
inline size_t qHash(const QVector3D &vector, size_t seed = 0) {
diff --git a/src/plugins/assetimporters/assimp/options.json b/src/plugins/assetimporters/assimp/options.json
index 54e19d44..fa487a07 100644
--- a/src/plugins/assetimporters/assimp/options.json
+++ b/src/plugins/assetimporters/assimp/options.json
@@ -199,25 +199,6 @@
"value": false,
"type": "Boolean"
},
- "generateLightmapUV": {
- "name": "Generate Lightmap UVs",
- "description": "Unwrap mesh to generate lightmap UV channel",
- "value": false,
- "type": "Boolean"
- },
- "lightmapBaseResolution": {
- "name": "Lightmap Base Resolution",
- "description": "Approx. size (width and height) which lightmap images should target.",
- "value": 1024,
- "type": "Real",
- "conditions": [
- {
- "mode": "Equals",
- "property": "generateLightmapUV",
- "value": true
- }
- ]
- },
"generateMeshLevelsOfDetail": {
"name": "Generate Mesh Levels of Detail",
"description": "When possible, create mesh Levels of Detail by automatically simplifying the source mesh",
@@ -272,13 +253,6 @@
"globalScaleValue"
]
},
- "generateLightmapUV": {
- "name": "Lightmap",
- "items": [
- "generateLightmapUV",
- "lightmapBaseResolution"
- ]
- },
"generateMeshLevelsOfDetail": {
"name": "Level of Detail",
"items": [
diff --git a/src/quick3d/qquick3dlightmapper.cpp b/src/quick3d/qquick3dlightmapper.cpp
index 4fb375a6..5b1c362d 100644
--- a/src/quick3d/qquick3dlightmapper.cpp
+++ b/src/quick3d/qquick3dlightmapper.cpp
@@ -34,7 +34,7 @@ QT_BEGIN_NAMESPACE
\list
\li \l Model::bakedLightmap and the associated \l BakedLightmap,
- \li \l Model::usedInBakedLighting and \l Model::lightmapBaseResolution,
+ \li \l Model::usedInBakedLighting and \l Model::texelsPerUnit,
\li \l Light::bakeMode,
\li the engine's built-in lightmap baker.
\endlist
@@ -190,6 +190,18 @@ QT_BEGIN_NAMESPACE
while still removing the noise.
*/
+/*!
+ \qmlproperty real Lightmapper::texelsPerUnit
+ \since 6.10
+ \default 1
+
+ This property defines the unit to texel scale, meaning a \c{1x1} quad with
+ texelsPerUnit of \c{32} will take up approximately \c{32x32} texels in the
+ lightmap.
+
+ \sa Model::texelsPerUnit
+*/
+
float QQuick3DLightmapper::opacityThreshold() const
{
return m_opacityThreshold;
@@ -339,4 +351,18 @@ void QQuick3DLightmapper::setDenoiseSigma(float newDenoiseSigma)
emit changed();
}
+float QQuick3DLightmapper::texelsPerUnit() const
+{
+ return m_texelsPerUnit;
+}
+
+void QQuick3DLightmapper::setTexelsPerUnit(float newTexelsPerUnit)
+{
+ if (qFuzzyCompare(m_texelsPerUnit, newTexelsPerUnit))
+ return;
+ m_texelsPerUnit = newTexelsPerUnit;
+ emit texelsPerUnitChanged();
+ emit changed();
+}
+
QT_END_NAMESPACE
diff --git a/src/quick3d/qquick3dlightmapper_p.h b/src/quick3d/qquick3dlightmapper_p.h
index 0ae204ef..9b0dccce 100644
--- a/src/quick3d/qquick3dlightmapper_p.h
+++ b/src/quick3d/qquick3dlightmapper_p.h
@@ -32,6 +32,7 @@ class Q_QUICK3D_EXPORT QQuick3DLightmapper : public QObject
Q_PROPERTY(float indirectLightFactor READ indirectLightFactor WRITE setIndirectLightFactor NOTIFY indirectLightFactorChanged)
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged FINAL REVISION(6, 10))
Q_PROPERTY(float denoiseSigma READ denoiseSigma WRITE setDenoiseSigma NOTIFY denoiseSigmaChanged FINAL REVISION(6, 10))
+ Q_PROPERTY(float texelsPerUnit READ texelsPerUnit WRITE setTexelsPerUnit NOTIFY texelsPerUnitChanged FINAL REVISION(6, 10))
QML_NAMED_ELEMENT(Lightmapper)
@@ -46,6 +47,7 @@ public:
float indirectLightFactor() const;
Q_REVISION(6, 10) QString source() const;
Q_REVISION(6, 10) float denoiseSigma() const;
+ Q_REVISION(6, 10) float texelsPerUnit() const;
public Q_SLOTS:
void setOpacityThreshold(float opacity);
@@ -58,6 +60,7 @@ public Q_SLOTS:
void setIndirectLightFactor(float factor);
Q_REVISION(6, 10) void setSource(const QString &source);
Q_REVISION(6, 10) void setDenoiseSigma(float newDenoiseSigma);
+ Q_REVISION(6, 10) void setTexelsPerUnit(float newTexelsPerUnit);
Q_SIGNALS:
void changed();
@@ -71,6 +74,7 @@ Q_SIGNALS:
void indirectLightFactorChanged();
Q_REVISION(6, 10) void sourceChanged();
Q_REVISION(6, 10) void denoiseSigmaChanged();
+ Q_REVISION(6, 10) void texelsPerUnitChanged();
private:
// keep the defaults in sync with the default values in QSSGLightmapperOptions
@@ -84,6 +88,7 @@ private:
float m_indirectFactor = 1.0f;
QString m_source = QStringLiteral("lightmaps.bin");
float m_denoiseSigma = 8.f;
+ float m_texelsPerUnit = 1.f;
};
QT_END_NAMESPACE
diff --git a/src/quick3d/qquick3dmodel.cpp b/src/quick3d/qquick3dmodel.cpp
index 99048635..f72586ae 100644
--- a/src/quick3d/qquick3dmodel.cpp
+++ b/src/quick3d/qquick3dmodel.cpp
@@ -472,34 +472,7 @@ bool QQuick3DModel::isUsedInBakedLighting() const
/*!
\qmlproperty int Model::lightmapBaseResolution
- Defines the approximate size of the lightmap for this model. The default
- value is 1024, indicating 1024x1024 as the base size. The actual size of
- the lightmap texture is likely to be different, often bigger, depending on
- the mesh.
-
- For simpler, smaller meshes, or when it is known that using a bigger
- lightmap is unnecessary, the value can be set to something smaller, for
- example, 512 or 256.
-
- The minimum value is 128.
-
- This setting applies both to persistently stored and for intermediate,
- partial lightmaps. When baking lightmaps, all models that have \l
- usedInBakedLighting enabled are part of the path-traced scene. Thus all of
- them need to have lightmap UV unwrapping performed and the rasterization
- steps necessary to compute direct lighting which then can be taken into
- account for indirect light bounces in the scene. However, for models that
- just contribute to, but do not store a lightmap the default value is often
- sufficient. Fine-tuning is more relevant for models that store and then use
- the generated lightmaps.
-
- This property is relevant only when baking lightmaps. It has no effect
- afterwards, when using the generated lightmaps during rendering.
-
- Models that have lightmap UV data pre-generated during asset import time
- (e.g. via the balsam tool) will ignore this property because the lightmap
- UV unwrapping and the lightmap size hint evaluation have already been done,
- and will not be performed again during lightmap baking.
+ \deprecated [6.10] This has no effect. Use Model::texelsPerUnit instead.
*/
int QQuick3DModel::lightmapBaseResolution() const
{
@@ -748,6 +721,8 @@ void QQuick3DModel::setLightmapBaseResolution(int resolution)
if (m_lightmapBaseResolution == resolution)
return;
+ qWarning() << "Model::lightmapBaseResolution is deprecated and will have no effect.";
+
m_lightmapBaseResolution = resolution;
emit lightmapBaseResolutionChanged();
markDirty(PropertyDirty);
@@ -927,7 +902,7 @@ QSSGRenderGraphObject *QQuick3DModel::updateSpatialNode(QSSGRenderGraphObject *n
if (m_dirtyAttributes & PropertyDirty) {
modelNode->m_depthBiasSq = QSSGRenderModel::signedSquared(m_depthBias);
modelNode->usedInBakedLighting = m_usedInBakedLighting;
- modelNode->lightmapBaseResolution = uint(m_lightmapBaseResolution);
+ modelNode->texelsPerUnit = m_texelsPerUnit;
if (m_bakedLightmap && m_bakedLightmap->isEnabled()) {
modelNode->lightmapKey = m_bakedLightmap->key();
} else {
@@ -1198,4 +1173,30 @@ void QQuick3DModel::setLevelOfDetailBias(float newLevelOfDetailBias)
markDirty(QQuick3DModel::PropertyDirty);
}
+/*!
+ \qmlproperty real Model::texelsPerUnit
+ \since 6.10
+ \default 0.0
+
+ A value greater than zero means this value will override the
+ SceneEnvironment::texelsPerUnit value for this specific model during
+ lightmap baking.
+
+ \sa SceneEnvironment::texelsPerUnit
+*/
+
+float QQuick3DModel::texelsPerUnit() const
+{
+ return m_texelsPerUnit;
+}
+
+void QQuick3DModel::setTexelsPerUnit(float newTexelsPerUnit)
+{
+ if (qFuzzyCompare(m_texelsPerUnit, newTexelsPerUnit))
+ return;
+ m_texelsPerUnit = newTexelsPerUnit;
+ emit texelsPerUnitChanged();
+ markDirty(PropertyDirty);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick3d/qquick3dmodel_p.h b/src/quick3d/qquick3dmodel_p.h
index c884d4ff..643cb077 100644
--- a/src/quick3d/qquick3dmodel_p.h
+++ b/src/quick3d/qquick3dmodel_p.h
@@ -82,6 +82,7 @@ class Q_QUICK3D_EXPORT QQuick3DModel : public QQuick3DNode
Q_PROPERTY(float instancingLodMin READ instancingLodMin WRITE setInstancingLodMin NOTIFY instancingLodMinChanged REVISION(6, 5))
Q_PROPERTY(float instancingLodMax READ instancingLodMax WRITE setInstancingLodMax NOTIFY instancingLodMaxChanged REVISION(6, 5))
Q_PROPERTY(float levelOfDetailBias READ levelOfDetailBias WRITE setLevelOfDetailBias NOTIFY levelOfDetailBiasChanged REVISION(6, 5))
+ Q_PROPERTY(float texelsPerUnit READ texelsPerUnit WRITE setTexelsPerUnit NOTIFY texelsPerUnitChanged FINAL REVISION(6, 10))
QML_NAMED_ELEMENT(Model)
@@ -119,6 +120,9 @@ public:
Q_REVISION(6, 5) float instancingLodMax() const;
Q_REVISION(6, 5) float levelOfDetailBias() const;
+ Q_REVISION(6, 10) float texelsPerUnit() const;
+ Q_REVISION(6, 10) void setTexelsPerUnit(float newTexelsPerUnit);
+
public Q_SLOTS:
void setSource(const QUrl &source);
void setCastsShadows(bool castsShadows);
@@ -166,6 +170,8 @@ Q_SIGNALS:
Q_REVISION(6, 5) void instancingLodMaxChanged();
Q_REVISION(6, 5) void levelOfDetailBiasChanged();
+ Q_REVISION(6, 10) void texelsPerUnitChanged();
+
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void markAllDirty() override;
@@ -238,6 +244,7 @@ private:
float m_instancingLodMin = -1;
float m_instancingLodMax = -1;
float m_levelOfDetailBias = 1.0f;
+ float m_texelsPerUnit = 0.0f;
};
QT_END_NAMESPACE
diff --git a/src/quick3d/qquick3dscenerenderer.cpp b/src/quick3d/qquick3dscenerenderer.cpp
index 95cf6859..8321b766 100644
--- a/src/quick3d/qquick3dscenerenderer.cpp
+++ b/src/quick3d/qquick3dscenerenderer.cpp
@@ -1270,6 +1270,7 @@ void QQuick3DSceneRenderer::updateLayerNode(QSSGRenderLayer &layerNode,
layerNode.lmOptions.indirectLightFactor = lightmapper->indirectLightFactor();
layerNode.lmOptions.source = lightmapper->source();
layerNode.lmOptions.sigma = lightmapper->denoiseSigma();
+ layerNode.lmOptions.texelsPerUnit = lightmapper->texelsPerUnit();
} else {
layerNode.lmOptions = {};
}
diff --git a/src/runtimerender/graphobjects/qssgrendermodel_p.h b/src/runtimerender/graphobjects/qssgrendermodel_p.h
index 3b92b4c6..8abeb77a 100644
--- a/src/runtimerender/graphobjects/qssgrendermodel_p.h
+++ b/src/runtimerender/graphobjects/qssgrendermodel_p.h
@@ -63,7 +63,7 @@ struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderModel : public QSSGRenderNode
bool castsReflections = true;
bool usedInBakedLighting = false;
QString lightmapKey;
- uint lightmapBaseResolution = 0;
+ float texelsPerUnit = 0.0f;
bool hasLightmap() const { return !lightmapKey.isEmpty(); }
bool usesBoneTexture() const { return ((skin != nullptr) || (skeleton != nullptr)); }
diff --git a/src/runtimerender/rendererimpl/qssglightmapper.cpp b/src/runtimerender/rendererimpl/qssglightmapper.cpp
index eff166c0..1882d289 100644
--- a/src/runtimerender/rendererimpl/qssglightmapper.cpp
+++ b/src/runtimerender/rendererimpl/qssglightmapper.cpp
@@ -431,6 +431,28 @@ static QByteArray meshToByteArray(const QSSGMesh::Mesh &mesh)
return meshData;
}
+// Function to extract a scale-only matrix from a transform matrix
+static QMatrix4x4 extractScaleMatrix(const QMatrix4x4 &transform)
+{
+ Q_ASSERT(transform.isAffine());
+
+ // Extract scale factors by computing the length of the basis vectors (columns)
+ const QVector4D col0 = transform.column(0);
+ const QVector4D col1 = transform.column(1);
+ const QVector4D col2 = transform.column(2);
+
+ const float scaleX = QVector3D(col0[0], col0[1], col0[2]).length(); // X column
+ const float scaleY = QVector3D(col1[0], col1[1], col1[2]).length(); // Y column
+ const float scaleZ = QVector3D(col2[0], col2[1], col2[2]).length(); // Z column
+
+ // Construct a scale-only matrix
+ QMatrix4x4 scaleMatrix;
+ scaleMatrix.data()[0 * 4 + 0] = scaleX;
+ scaleMatrix.data()[1 * 4 + 1] = scaleY;
+ scaleMatrix.data()[2 * 4 + 2] = scaleZ;
+ return scaleMatrix;
+}
+
bool QSSGLightmapperPrivate::commitGeometry(const StageProgressReporter &reporter)
{
if (bakedLightingModels.isEmpty()) {
@@ -502,6 +524,7 @@ bool QSSGLightmapperPrivate::commitGeometry(const StageProgressReporter &reporte
QSSGSubsetRenderable *renderableObj = static_cast<QSSGSubsetRenderable *>(lm.renderables.first().obj);
worldTransform = renderableObj->globalTransform;
normalMatrix = renderableObj->modelContext.normalMatrix;
+ const QMatrix4x4 scaleTransform = extractScaleMatrix(worldTransform);
DrawInfo &drawInfo(drawInfos[lmIdx]);
QSSGMesh::Mesh mesh;
@@ -519,7 +542,9 @@ bool QSSGLightmapperPrivate::commitGeometry(const StageProgressReporter &reporte
QElapsedTimer unwrapTimer;
unwrapTimer.start();
- if (!mesh.createLightmapUVChannel(lm.model->lightmapBaseResolution)) {
+ // Use scene texelsPerUnit if the model's texelsPerUnit is unset (< 0)
+ const float texelsPerUnit = lm.model->texelsPerUnit <= 0.0f ? options.texelsPerUnit : lm.model->texelsPerUnit;
+ if (!mesh.createLightmapUVChannel(texelsPerUnit, scaleTransform)) {
sendOutputInfo(QSSGLightmapper::BakingStatus::Warning, QStringLiteral("Failed to do lightmap UV unwrapping for model %1").
arg(lm.model->lightmapKey));
return false;
@@ -548,12 +573,6 @@ bool QSSGLightmapperPrivate::commitGeometry(const StageProgressReporter &reporte
}
drawInfo.lightmapSize = mesh.subsets().first().lightmapSizeHint;
- if (drawInfo.lightmapSize.isEmpty()) {
- sendOutputInfo(QSSGLightmapper::BakingStatus::Warning, QStringLiteral("No lightmap size hint found for model %1, defaulting to 1024x1024").
- arg(lm.model->lightmapKey));
- drawInfo.lightmapSize = QSize(1024, 1024);
- }
-
drawInfo.vertexData = mesh.vertexBuffer().data;
drawInfo.vertexStride = mesh.vertexBuffer().stride;
drawInfo.indexData = mesh.indexBuffer().data;
diff --git a/src/runtimerender/rendererimpl/qssglightmapper.h b/src/runtimerender/rendererimpl/qssglightmapper.h
index 4f75900d..749992af 100644
--- a/src/runtimerender/rendererimpl/qssglightmapper.h
+++ b/src/runtimerender/rendererimpl/qssglightmapper.h
@@ -30,6 +30,7 @@ struct QSSGLightmapperOptions
float indirectLightFactor = 1.0f;
QString source = QStringLiteral("lightmaps.bin");
float sigma = 8.f;
+ float texelsPerUnit = 1.f;
};
QT_END_NAMESPACE
diff --git a/src/utils/qssglightmapuvgenerator.cpp b/src/utils/qssglightmapuvgenerator.cpp
index c2a475e3..94b16ddb 100644
--- a/src/utils/qssglightmapuvgenerator.cpp
+++ b/src/utils/qssglightmapuvgenerator.cpp
@@ -11,7 +11,7 @@ QSSGLightmapUVGeneratorResult QSSGLightmapUVGenerator::run(const QByteArray &pos
const QByteArray &uv0,
const QByteArray &index,
QSSGMesh::Mesh::ComponentType indexComponentType,
- uint baseResolution)
+ float texelsPerUnit)
{
QSSGLightmapUVGeneratorResult result;
@@ -60,7 +60,8 @@ QSSGLightmapUVGeneratorResult QSSGLightmapUVGenerator::run(const QByteArray &pos
xatlas::PackOptions packOptions;
packOptions.maxChartSize = 4096;
packOptions.padding = 1;
- packOptions.resolution = baseResolution;
+ packOptions.resolution = 0;
+ packOptions.texelsPerUnit = texelsPerUnit;
packOptions.blockAlign = true;
xatlas::ChartOptions chartOptions;
diff --git a/src/utils/qssglightmapuvgenerator_p.h b/src/utils/qssglightmapuvgenerator_p.h
index d5f35ebf..f103285f 100644
--- a/src/utils/qssglightmapuvgenerator_p.h
+++ b/src/utils/qssglightmapuvgenerator_p.h
@@ -57,16 +57,16 @@ public:
// data (position, normals, UVs, etc.) so that the count of their elements
// matches the lightmap UV channel.
//
- // baseResolution sepecifies the approx. size on which the lightmap size
- // calculation is based; the returned width and height are in the same
- // ballpark as much as possible (but may be bigger, depending on the mesh).
+ // texelsPerUnit
+ // Unit to texel scale. e.g. a 1x1 quad with texelsPerUnit of 32 will take
+ // up approximately 32x32 texels in the atlas.
//
QSSGLightmapUVGeneratorResult run(const QByteArray &positions,
const QByteArray &normals,
const QByteArray &uv0,
const QByteArray &index,
QSSGMesh::Mesh::ComponentType indexComponentType,
- uint baseResolution);
+ float texelsPerUnit);
// source is of N elements of componentCount * sizeof(T) bytes each. The
// returned data is M elements of componentCount * sizeof(T) bytes each, where
diff --git a/src/utils/qssgmesh.cpp b/src/utils/qssgmesh.cpp
index 3f017a75..1be22b1d 100644
--- a/src/utils/qssgmesh.cpp
+++ b/src/utils/qssgmesh.cpp
@@ -1019,7 +1019,7 @@ bool Mesh::hasLightmapUVChannel() const
return false;
}
-bool Mesh::createLightmapUVChannel(uint lightmapBaseResolution)
+bool Mesh::createLightmapUVChannel(float texelsPerUnit, const QMatrix4x4 &scale)
{
const char *posAttrName = MeshInternal::getPositionAttrName();
const char *normalAttrName = MeshInternal::getNormalAttrName();
@@ -1079,9 +1079,17 @@ bool Mesh::createLightmapUVChannel(uint lightmapBaseResolution)
for (qsizetype i = 0; i < vertexCount; ++i) {
const char *vertexBasePtr = srcVertexData + i * srcVertexStride;
const float *srcPos = reinterpret_cast<const float *>(vertexBasePtr + positionOffset);
- *posPtr++ = *srcPos++;
- *posPtr++ = *srcPos++;
- *posPtr++ = *srcPos++;
+ QVector3D srcV;
+ srcV.setX(*srcPos++);
+ srcV.setY(*srcPos++);
+ srcV.setZ(*srcPos++);
+ // We scale the positions here, but not on the source mesh, so that the uv unwrapper works on
+ // the positions that the model will have in the scene after its scaling has been applied. This
+ // way the texels-per-unit will be correct.
+ srcV = scale.map(srcV);
+ *posPtr++ = srcV.x();
+ *posPtr++ = srcV.y();
+ *posPtr++ = srcV.z();
}
QByteArray normalData;
@@ -1112,7 +1120,7 @@ bool Mesh::createLightmapUVChannel(uint lightmapBaseResolution)
QSSGLightmapUVGenerator uvGen;
QSSGLightmapUVGeneratorResult r = uvGen.run(positionData, normalData, uvData,
m_indexBuffer.data, m_indexBuffer.componentType,
- lightmapBaseResolution);
+ texelsPerUnit);
if (!r.isValid())
return false;
diff --git a/src/utils/qssgmesh_p.h b/src/utils/qssgmesh_p.h
index c9ab14da..8628be7d 100644
--- a/src/utils/qssgmesh_p.h
+++ b/src/utils/qssgmesh_p.h
@@ -165,7 +165,7 @@ public:
quint32 save(QIODevice *device, quint32 id = 0) const;
bool hasLightmapUVChannel() const;
- bool createLightmapUVChannel(uint lightmapBaseResolution);
+ bool createLightmapUVChannel(float texelsPerUnit, const QMatrix4x4 &scale);
private:
DrawMode m_drawMode = DrawMode::Triangles;