Dust3D开源项目分析——渲染与材质部分 | 材质预览 Part 2

 2021SC@SDUSC

materialpreviewsgenerator.cpp用于实现具体的材质预览方法。部分简单函数已经在材质预览Part 1中介绍。

#include <QGuiApplication>
#include <QElapsedTimer>
#include "materialpreviewsgenerator.h"
#include "meshgenerator.h"
#include "snapshotxml.h"
#include "ds3file.h"
#include "texturegenerator.h"
#include "imageforever.h"
#include "meshresultpostprocessor.h"

MaterialPreviewsGenerator::MaterialPreviewsGenerator()
{
}

MaterialPreviewsGenerator::~MaterialPreviewsGenerator()
{
    for (auto &item: m_previews) {
        delete item.second;
    }
}

void MaterialPreviewsGenerator::addMaterial(QUuid materialId, const std::vector<MaterialLayer> &layers)
{
    m_materials.push_back({materialId, layers});
}

const std::set<QUuid> &MaterialPreviewsGenerator::generatedPreviewMaterialIds()
{
    return m_generatedMaterialIds;
}

Model *MaterialPreviewsGenerator::takePreview(QUuid materialId)
{
    Model *resultMesh = m_previews[materialId];
    m_previews[materialId] = nullptr;
    return resultMesh;
}

void MaterialPreviewsGenerator::generate()
{
    Snapshot *snapshot = new Snapshot;
    
    std::vector<QUuid> partIds;
    Ds3FileReader ds3Reader(":/resources/material-demo-model.ds3");
    for (int i = 0; i < ds3Reader.items().size(); ++i) {
        Ds3ReaderItem item = ds3Reader.items().at(i);
        if (item.type == "model") {
            QByteArray data;
            ds3Reader.loadItem(item.name, &data);
            QXmlStreamReader stream(data);
            loadSkeletonFromXmlStream(snapshot, stream);
            for (const auto &item: snapshot->parts) {
                partIds.push_back(QUuid(item.first));
            }
        }
    }
    
    GeneratedCacheContext *cacheContext = new GeneratedCacheContext();
    MeshGenerator *meshGenerator = new MeshGenerator(snapshot);
    meshGenerator->setGeneratedCacheContext(cacheContext);
    
    meshGenerator->generate();
    for (const auto &mirror: cacheContext->partMirrorIdMap) {
        partIds.push_back(QUuid(mirror.first));
    }
    
    Object *object = meshGenerator->takeObject();
    if (nullptr != object) {
        MeshResultPostProcessor *poseProcessor = new MeshResultPostProcessor(*object);
        poseProcessor->poseProcess();
        delete object;
        object = poseProcessor->takePostProcessedObject();
        delete poseProcessor;
    }
    
    if (nullptr != object) {
        for (const auto &material: m_materials) {
            TextureGenerator *textureGenerator = new TextureGenerator(*object);
            for (const auto &layer: material.second) {
                for (const auto &mapItem: layer.maps) {
                    const QImage *image = ImageForever::get(mapItem.imageId);
                    if (nullptr == image)
                        continue;
                    for (const auto &partId: partIds) {
                        if (TextureType::BaseColor == mapItem.forWhat)
                            textureGenerator->addPartColorMap(partId, image, layer.tileScale);
                        else if (TextureType::Normal == mapItem.forWhat)
                            textureGenerator->addPartNormalMap(partId, image, layer.tileScale);
                        else if (TextureType::Metallic == mapItem.forWhat)
                            textureGenerator->addPartMetalnessMap(partId, image, layer.tileScale);
                        else if (TextureType::Roughness == mapItem.forWhat)
                            textureGenerator->addPartRoughnessMap(partId, image, layer.tileScale);
                        else if (TextureType::AmbientOcclusion == mapItem.forWhat)
                            textureGenerator->addPartAmbientOcclusionMap(partId, image, layer.tileScale);
                    }
                }
            }
            textureGenerator->generate();
            Model *texturedResultMesh = textureGenerator->takeResultMesh();
            if (nullptr != texturedResultMesh) {
                m_previews[material.first] = new Model(*texturedResultMesh);
                m_generatedMaterialIds.insert(material.first);
                delete texturedResultMesh;
            }
            delete textureGenerator;
        }
    }
    
    delete object;
    
    delete meshGenerator;
    delete cacheContext;
}

void MaterialPreviewsGenerator::process()
{
    QElapsedTimer countTimeConsumed;
    countTimeConsumed.start();

    generate();

    qDebug() << "The material previews generation took" << countTimeConsumed.elapsed() << "milliseconds";

    emit finished();
}

generate()函数主要负责生成预览材质:

……
    
    std::vector<QUuid> partIds;
    Ds3FileReader ds3Reader(":/resources/material-demo-model.ds3");
    for (int i = 0; i < ds3Reader.items().size(); ++i) {
        Ds3ReaderItem item = ds3Reader.items().at(i);
        if (item.type == "model") {
            QByteArray data;
            ds3Reader.loadItem(item.name, &data);
            QXmlStreamReader stream(data);
            loadSkeletonFromXmlStream(snapshot, stream);
            for (const auto &item: snapshot->parts) {
                partIds.push_back(QUuid(item.first));
            }
        }
    }

……

从.ds3文件中提取partId。遍历.ds3文件中的item,如果item类型判定为“model”的话,将item的关键字添加到partId尾部。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值