diff options
-rw-r--r-- | examples/quick3d/bakedlightmap/Box.qml | 2 | ||||
-rw-r--r-- | examples/quick3d/bakedlightmap/main.qml | 1 | ||||
-rw-r--r-- | src/plugins/assetimporters/assimp/assimpimporter_rt.cpp | 11 | ||||
-rw-r--r-- | src/plugins/assetimporters/assimp/assimputils.cpp | 6 | ||||
-rw-r--r-- | src/plugins/assetimporters/assimp/assimputils.h | 3 | ||||
-rw-r--r-- | src/plugins/assetimporters/assimp/options.json | 26 | ||||
-rw-r--r-- | src/quick3d/qquick3dlightmapper.cpp | 28 | ||||
-rw-r--r-- | src/quick3d/qquick3dlightmapper_p.h | 5 | ||||
-rw-r--r-- | src/quick3d/qquick3dmodel.cpp | 59 | ||||
-rw-r--r-- | src/quick3d/qquick3dmodel_p.h | 7 | ||||
-rw-r--r-- | src/quick3d/qquick3dscenerenderer.cpp | 1 | ||||
-rw-r--r-- | src/runtimerender/graphobjects/qssgrendermodel_p.h | 2 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssglightmapper.cpp | 33 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssglightmapper.h | 1 | ||||
-rw-r--r-- | src/utils/qssglightmapuvgenerator.cpp | 5 | ||||
-rw-r--r-- | src/utils/qssglightmapuvgenerator_p.h | 8 | ||||
-rw-r--r-- | src/utils/qssgmesh.cpp | 18 | ||||
-rw-r--r-- | src/utils/qssgmesh_p.h | 2 |
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; |