ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
162 lines
4.5 KiB
C++
162 lines
4.5 KiB
C++
// Copyright (C) 2025 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include "lightmapmesh.h"
|
|
|
|
#include <QBuffer>
|
|
|
|
#include <private/qssgmesh_p.h>
|
|
#include <private/qssglightmapio_p.h>
|
|
|
|
LightmapMesh::LightmapMesh(QQuick3DObject *parent) : QQuick3DGeometry(parent) { }
|
|
LightmapMesh::~LightmapMesh() = default;
|
|
|
|
void LightmapMesh::updateData()
|
|
{
|
|
if (!m_source.isValid() || m_key.isEmpty())
|
|
return;
|
|
|
|
if (m_currentlyLoadedSource == m_source && m_currentlyLoadedKey == m_key)
|
|
return;
|
|
|
|
auto loader = QSSGLightmapLoader::open(m_source.toLocalFile());
|
|
if (!loader) {
|
|
qWarning("Failed to open lightmap source file");
|
|
return;
|
|
}
|
|
|
|
const auto keys = loader->getKeys();
|
|
const bool isMeshKey = keys.contains(std::make_pair(m_key, QSSGLightmapIODataTag::Mesh));
|
|
|
|
if (!isMeshKey) {
|
|
return;
|
|
}
|
|
|
|
QByteArray meshData = loader->readData(m_key, QSSGLightmapIODataTag::Mesh);
|
|
if (meshData.isEmpty())
|
|
return;
|
|
|
|
QBuffer buffer(&meshData);
|
|
buffer.open(QIODevice::ReadOnly);
|
|
const QSSGMesh::Mesh mesh = QSSGMesh::Mesh::loadMesh(&buffer, 1);
|
|
if (!mesh.isValid()) {
|
|
qWarning("Mesh load failed");
|
|
return;
|
|
}
|
|
if (!mesh.hasLightmapUVChannel()) {
|
|
qWarning("Mesh does not have lightmap UVs");
|
|
return;
|
|
}
|
|
|
|
clear();
|
|
|
|
const auto &vb = mesh.vertexBuffer();
|
|
const auto &ib = mesh.indexBuffer();
|
|
|
|
setVertexData(vb.data);
|
|
setIndexData(ib.data);
|
|
setStride(vb.stride);
|
|
setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles);
|
|
|
|
auto findEntry = [&](const QByteArray &name) -> const QSSGMesh::Mesh::VertexBufferEntry * {
|
|
for (const auto &e : vb.entries)
|
|
if (e.name == name)
|
|
return &e;
|
|
return nullptr;
|
|
};
|
|
|
|
const QByteArray posName = QSSGMesh::MeshInternal::getPositionAttrName();
|
|
const QByteArray lmuvName = QSSGMesh::MeshInternal::getLightmapUVAttrName();
|
|
|
|
const auto *pos = findEntry(posName);
|
|
const auto *lmuv = findEntry(lmuvName);
|
|
|
|
if (!pos) {
|
|
qWarning("Position attribute not found");
|
|
return;
|
|
}
|
|
if (!lmuv) {
|
|
qWarning("Lightmap UV attribute not found");
|
|
return;
|
|
}
|
|
|
|
addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, pos->offset, Attribute::ComponentType::F32Type);
|
|
|
|
addAttribute(QQuick3DGeometry::Attribute::TexCoord0Semantic, lmuv->offset, Attribute::ComponentType::F32Type);
|
|
|
|
Attribute::ComponentType ibCompType;
|
|
switch (ib.componentType) {
|
|
case QSSGRenderComponentType::UnsignedInt16:
|
|
ibCompType = Attribute::ComponentType::U16Type;
|
|
break;
|
|
case QSSGRenderComponentType::UnsignedInt32:
|
|
ibCompType = Attribute::ComponentType::U32Type;
|
|
break;
|
|
case QSSGRenderComponentType::Int32:
|
|
ibCompType = Attribute::ComponentType::I32Type;
|
|
break;
|
|
case QSSGRenderComponentType::Float32:
|
|
ibCompType = Attribute::ComponentType::F32Type;
|
|
break;
|
|
default:
|
|
ibCompType = Attribute::ComponentType::U32Type;
|
|
}
|
|
|
|
addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0, ibCompType);
|
|
|
|
m_bounds.bounds.minimum = QVector3D(std::numeric_limits<float>::max(),
|
|
std::numeric_limits<float>::max(),
|
|
std::numeric_limits<float>::max());
|
|
m_bounds.bounds.maximum = QVector3D(-std::numeric_limits<float>::max(),
|
|
-std::numeric_limits<float>::max(),
|
|
-std::numeric_limits<float>::max());
|
|
|
|
for (const auto &subset : mesh.subsets()) {
|
|
m_bounds.bounds.minimum = QSSGUtils::vec3::minimum(m_bounds.bounds.minimum, subset.bounds.min);
|
|
m_bounds.bounds.maximum = QSSGUtils::vec3::maximum(m_bounds.bounds.maximum, subset.bounds.max);
|
|
}
|
|
|
|
setBounds(m_bounds.bounds.minimum, m_bounds.bounds.maximum);
|
|
|
|
m_currentlyLoadedSource = m_source;
|
|
m_currentlyLoadedKey = m_key;
|
|
|
|
update();
|
|
emit boundsChanged();
|
|
}
|
|
|
|
QUrl LightmapMesh::source() const
|
|
{
|
|
return m_source;
|
|
}
|
|
|
|
void LightmapMesh::setSource(const QUrl &newSource)
|
|
{
|
|
if (m_source == newSource)
|
|
return;
|
|
|
|
m_source = newSource;
|
|
updateData();
|
|
emit sourceChanged();
|
|
}
|
|
|
|
QString LightmapMesh::key() const
|
|
{
|
|
return m_key;
|
|
}
|
|
|
|
void LightmapMesh::setKey(const QString &newKey)
|
|
{
|
|
if (m_key == newKey)
|
|
return;
|
|
|
|
m_key = newKey;
|
|
updateData();
|
|
emit keyChanged();
|
|
}
|
|
|
|
const QQuick3DBounds3 &LightmapMesh::bounds() const
|
|
{
|
|
return m_bounds;
|
|
}
|