Implement bone preview images generator
parent
ef0fe2dcfe
commit
03f1440e7d
|
@ -2,6 +2,11 @@
|
|||
#include <dust3d/mesh/smooth_normal.h>
|
||||
#include <dust3d/mesh/trim_vertices.h>
|
||||
|
||||
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>* BoneGenerator::takeBonePreviewMeshes()
|
||||
{
|
||||
return m_bonePreviewMeshes.release();
|
||||
}
|
||||
|
||||
void BoneGenerator::process()
|
||||
{
|
||||
generate();
|
||||
|
|
|
@ -4,10 +4,13 @@
|
|||
#include "model_mesh.h"
|
||||
#include <QObject>
|
||||
#include <dust3d/rig/bone_generator.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class BoneGenerator : public QObject, public dust3d::BoneGenerator {
|
||||
Q_OBJECT
|
||||
public:
|
||||
std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>* takeBonePreviewMeshes();
|
||||
public slots:
|
||||
void process();
|
||||
signals:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "document.h"
|
||||
#include "bone_generator.h"
|
||||
#include "image_forever.h"
|
||||
#include "mesh_generator.h"
|
||||
#include "mesh_result_post_processor.h"
|
||||
|
@ -2795,6 +2796,11 @@ bool Document::isTextureGenerating() const
|
|||
return nullptr != m_textureGenerator;
|
||||
}
|
||||
|
||||
bool Document::isBoneGenerating() const
|
||||
{
|
||||
return nullptr != m_boneGenerator;
|
||||
}
|
||||
|
||||
void Document::copyNodes(std::set<dust3d::Uuid> nodeIdSet) const
|
||||
{
|
||||
dust3d::Snapshot snapshot;
|
||||
|
@ -2865,7 +2871,7 @@ void Document::addBone(const dust3d::Uuid& boneId)
|
|||
return;
|
||||
|
||||
Bone bone(boneId);
|
||||
boneMap.emplace(boneId, bone);
|
||||
boneMap.emplace(boneId, std::move(bone));
|
||||
boneIdList.push_back(boneId);
|
||||
emit boneAdded(boneId);
|
||||
emit boneIdListChanged();
|
||||
|
@ -3018,3 +3024,66 @@ void Document::pickBoneNode(const dust3d::Uuid& nodeId)
|
|||
|
||||
stopBoneJointsPicking();
|
||||
}
|
||||
|
||||
void Document::generateBone()
|
||||
{
|
||||
if (nullptr != m_boneGenerator) {
|
||||
m_isResultBoneObsolete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_isResultBoneObsolete = false;
|
||||
|
||||
emit boneGenerating();
|
||||
|
||||
// TODO:
|
||||
|
||||
QThread* thread = new QThread;
|
||||
m_boneGenerator = std::make_unique<BoneGenerator>();
|
||||
m_boneGenerator->moveToThread(thread);
|
||||
connect(thread, &QThread::started, m_boneGenerator.get(), &BoneGenerator::process);
|
||||
connect(m_boneGenerator.get(), &BoneGenerator::finished, this, &Document::boneReady);
|
||||
connect(m_boneGenerator.get(), &BoneGenerator::finished, thread, &QThread::quit);
|
||||
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void Document::boneReady()
|
||||
{
|
||||
std::unique_ptr<std::map<dust3d::Uuid, std::unique_ptr<ModelMesh>>> bonePreviewMeshes;
|
||||
bonePreviewMeshes.reset(m_boneGenerator->takeBonePreviewMeshes());
|
||||
bool bonePreviewsChanged = bonePreviewMeshes && !bonePreviewMeshes->empty();
|
||||
if (bonePreviewsChanged) {
|
||||
for (auto& it : *bonePreviewMeshes) {
|
||||
setBonePreviewMesh(it.first, std::move(it.second));
|
||||
}
|
||||
emit resultBonePreviewMeshesChanged();
|
||||
}
|
||||
|
||||
// TODO:
|
||||
|
||||
m_boneGenerator.reset();
|
||||
|
||||
emit resultBoneChanged();
|
||||
|
||||
if (m_isResultBoneObsolete)
|
||||
generateBone();
|
||||
}
|
||||
|
||||
void Document::setBonePreviewMesh(const dust3d::Uuid& boneId, std::unique_ptr<ModelMesh> mesh)
|
||||
{
|
||||
Document::Bone* bone = (Document::Bone*)findBone(boneId);
|
||||
if (nullptr == bone)
|
||||
return;
|
||||
bone->updatePreviewMesh(std::move(mesh));
|
||||
emit bonePreviewMeshChanged(boneId);
|
||||
}
|
||||
|
||||
void Document::setBonePreviewPixmap(const dust3d::Uuid& boneId, const QPixmap& pixmap)
|
||||
{
|
||||
Document::Bone* bone = (Document::Bone*)findBone(boneId);
|
||||
if (nullptr == bone)
|
||||
return;
|
||||
bone->previewPixmap = pixmap;
|
||||
emit bonePreviewPixmapChanged(boneId);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
class UvMapGenerator;
|
||||
class MeshGenerator;
|
||||
class MeshResultPostProcessor;
|
||||
class BoneGenerator;
|
||||
|
||||
class Document : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -208,8 +209,14 @@ public:
|
|||
std::vector<dust3d::Uuid> joints;
|
||||
QString name;
|
||||
QPixmap previewPixmap;
|
||||
bool isPreviewMeshObsolete = false;
|
||||
void updatePreviewMesh(std::unique_ptr<ModelMesh> mesh);
|
||||
ModelMesh* takePreviewMesh() const;
|
||||
|
||||
Bone(const dust3d::Uuid& withId = dust3d::Uuid());
|
||||
|
||||
private:
|
||||
std::unique_ptr<ModelMesh> m_previewMesh;
|
||||
};
|
||||
|
||||
signals:
|
||||
|
@ -218,6 +225,7 @@ signals:
|
|||
void partPreviewChanged(dust3d::Uuid partId);
|
||||
void resultMeshChanged();
|
||||
void resultComponentPreviewMeshesChanged();
|
||||
void resultBonePreviewMeshesChanged();
|
||||
void turnaroundChanged();
|
||||
void editModeChanged();
|
||||
void resultTextureChanged();
|
||||
|
@ -288,9 +296,12 @@ signals:
|
|||
void boneNodesChanged(const dust3d::Uuid& boneId);
|
||||
void boneJointsChanged(const dust3d::Uuid& boneId);
|
||||
void boneNameChanged(const dust3d::Uuid& boneId);
|
||||
void bonePreviewMeshChanged(const dust3d::Uuid& boneId);
|
||||
void bonePreviewPixmapChanged(const dust3d::Uuid& boneId);
|
||||
void boneIdListChanged();
|
||||
void rigChanged();
|
||||
void boneGenerating();
|
||||
void resultBoneChanged();
|
||||
|
||||
public: // need initialize
|
||||
QImage* textureImage = nullptr;
|
||||
|
@ -359,6 +370,7 @@ public:
|
|||
bool isMeshGenerating() const;
|
||||
bool isPostProcessing() const;
|
||||
bool isTextureGenerating() const;
|
||||
bool isBoneGenerating() const;
|
||||
void collectCutFaceList(std::vector<QString>& cutFaces) const;
|
||||
float getOriginX(bool rotated = false) const
|
||||
{
|
||||
|
@ -417,6 +429,8 @@ public:
|
|||
void resetDirtyFlags();
|
||||
void markAllDirty();
|
||||
const Bone* findBone(const dust3d::Uuid& boneId) const;
|
||||
void setBonePreviewMesh(const dust3d::Uuid& boneId, std::unique_ptr<ModelMesh> mesh);
|
||||
void setBonePreviewPixmap(const dust3d::Uuid& boneId, const QPixmap& pixmap);
|
||||
|
||||
public slots:
|
||||
void undo();
|
||||
|
@ -435,6 +449,8 @@ public slots:
|
|||
void textureReady();
|
||||
void postProcess();
|
||||
void postProcessedMeshResultReady();
|
||||
void generateBone();
|
||||
void boneReady();
|
||||
void setPartSubdivState(dust3d::Uuid partId, bool subdived);
|
||||
void setPartXmirrorState(dust3d::Uuid partId, bool mirrored);
|
||||
void setPartDeformThickness(dust3d::Uuid partId, float thickness);
|
||||
|
@ -565,10 +581,14 @@ private:
|
|||
float m_originZ = 0;
|
||||
dust3d::Uuid m_currentCanvasComponentId;
|
||||
bool m_allPositionRelatedLocksEnabled = true;
|
||||
|
||||
dust3d::Uuid m_currentBondId;
|
||||
size_t m_currentBoneJoints = 0;
|
||||
std::vector<dust3d::Uuid> m_currentBoneJointNodes;
|
||||
|
||||
std::unique_ptr<BoneGenerator> m_boneGenerator;
|
||||
bool m_isResultBoneObsolete = false;
|
||||
|
||||
private:
|
||||
static unsigned long m_maxSnapshot;
|
||||
std::deque<HistoryItem> m_undoItems;
|
||||
|
|
|
@ -4,3 +4,16 @@ Document::Bone::Bone(const dust3d::Uuid& withId)
|
|||
{
|
||||
id = withId.isNull() ? dust3d::Uuid::createUuid() : withId;
|
||||
}
|
||||
|
||||
void Document::Bone::updatePreviewMesh(std::unique_ptr<ModelMesh> mesh)
|
||||
{
|
||||
m_previewMesh = std::move(mesh);
|
||||
isPreviewMeshObsolete = true;
|
||||
}
|
||||
|
||||
ModelMesh* Document::Bone::takePreviewMesh() const
|
||||
{
|
||||
if (nullptr == m_previewMesh)
|
||||
return nullptr;
|
||||
return new ModelMesh(*m_previewMesh);
|
||||
}
|
||||
|
|
|
@ -208,6 +208,9 @@ DocumentWindow::DocumentWindow()
|
|||
connect(m_document, &Document::textureGenerating, this, &DocumentWindow::updateInprogressIndicator);
|
||||
connect(m_document, &Document::resultTextureChanged, this, &DocumentWindow::updateInprogressIndicator);
|
||||
connect(m_document, &Document::postProcessedResultChanged, this, &DocumentWindow::updateInprogressIndicator);
|
||||
connect(m_document, &Document::boneGenerating, this, &DocumentWindow::updateInprogressIndicator);
|
||||
connect(m_document, &Document::resultBoneChanged, this, &DocumentWindow::updateInprogressIndicator);
|
||||
connect(m_document, &Document::resultBonePreviewMeshesChanged, this, &DocumentWindow::generateBonePreviewImages);
|
||||
|
||||
toolButtonLayout->addWidget(addButton);
|
||||
toolButtonLayout->addWidget(selectButton);
|
||||
|
@ -616,6 +619,8 @@ DocumentWindow::DocumentWindow()
|
|||
connect(m_document, &Document::textureChanged, m_document, &Document::generateTexture);
|
||||
connect(m_document, &Document::resultMeshChanged, m_document, &Document::postProcess);
|
||||
connect(m_document, &Document::postProcessedResultChanged, m_document, &Document::generateTexture);
|
||||
connect(m_document, &Document::rigChanged, m_document, &Document::generateBone);
|
||||
connect(m_document, &Document::postProcessedResultChanged, m_document, &Document::generateBone);
|
||||
connect(m_document, &Document::resultTextureChanged, [=]() {
|
||||
if (m_document->isMeshGenerating())
|
||||
return;
|
||||
|
@ -677,7 +682,7 @@ DocumentWindow::DocumentWindow()
|
|||
|
||||
void DocumentWindow::updateInprogressIndicator()
|
||||
{
|
||||
bool inprogress = m_document->isMeshGenerating() || m_document->isPostProcessing() || m_document->isTextureGenerating() || nullptr != m_componentPreviewImagesGenerator || nullptr != m_componentPreviewImagesDecorator;
|
||||
bool inprogress = m_document->isMeshGenerating() || m_document->isPostProcessing() || m_document->isTextureGenerating() || m_document->isBoneGenerating() || nullptr != m_componentPreviewImagesGenerator || nullptr != m_componentPreviewImagesDecorator;
|
||||
if (inprogress == m_inprogressIndicator->isSpinning())
|
||||
return;
|
||||
m_inprogressIndicator->showSpinner(inprogress);
|
||||
|
@ -1403,3 +1408,52 @@ void DocumentWindow::toggleRenderColor()
|
|||
mesh->removeColor();
|
||||
m_modelRenderWidget->updateMesh(mesh);
|
||||
}
|
||||
|
||||
void DocumentWindow::generateBonePreviewImages()
|
||||
{
|
||||
if (nullptr != m_bonePreviewImagesGenerator) {
|
||||
m_isBonePreviewImagesObsolete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_isBonePreviewImagesObsolete = false;
|
||||
|
||||
QThread* thread = new QThread;
|
||||
|
||||
m_bonePreviewImagesGenerator = new MeshPreviewImagesGenerator(new ModelOffscreenRender(m_modelRenderWidget->format()));
|
||||
for (auto& bone : m_document->boneMap) {
|
||||
if (!bone.second.isPreviewMeshObsolete)
|
||||
continue;
|
||||
bone.second.isPreviewMeshObsolete = false;
|
||||
auto previewMesh = std::unique_ptr<ModelMesh>(bone.second.takePreviewMesh());
|
||||
const bool useFrontView = false;
|
||||
m_bonePreviewImagesGenerator->addInput(bone.first, std::move(previewMesh), useFrontView);
|
||||
}
|
||||
m_bonePreviewImagesGenerator->moveToThread(thread);
|
||||
connect(thread, &QThread::started, m_bonePreviewImagesGenerator, &MeshPreviewImagesGenerator::process);
|
||||
connect(m_bonePreviewImagesGenerator, &MeshPreviewImagesGenerator::finished, this, &DocumentWindow::bonePreviewImagesReady);
|
||||
connect(m_bonePreviewImagesGenerator, &MeshPreviewImagesGenerator::finished, thread, &QThread::quit);
|
||||
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||
thread->start();
|
||||
|
||||
updateInprogressIndicator();
|
||||
}
|
||||
|
||||
void DocumentWindow::bonePreviewImagesReady()
|
||||
{
|
||||
std::unique_ptr<std::map<dust3d::Uuid, QImage>> boneImages;
|
||||
boneImages.reset(m_bonePreviewImagesGenerator->takeImages());
|
||||
if (nullptr != boneImages) {
|
||||
for (const auto& it : *boneImages) {
|
||||
m_document->setBonePreviewPixmap(it.first, QPixmap::fromImage(it.second));
|
||||
}
|
||||
}
|
||||
|
||||
delete m_bonePreviewImagesGenerator;
|
||||
m_bonePreviewImagesGenerator = nullptr;
|
||||
|
||||
if (m_isBonePreviewImagesObsolete)
|
||||
generateBonePreviewImages();
|
||||
else
|
||||
updateInprogressIndicator();
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ public slots:
|
|||
void componentPreviewImagesReady();
|
||||
void decorateComponentPreviewImages();
|
||||
void componentPreviewImageDecorationsReady();
|
||||
void generateBonePreviewImages();
|
||||
void bonePreviewImagesReady();
|
||||
void updateInprogressIndicator();
|
||||
void openRecentFile();
|
||||
void updateRecentFileActions();
|
||||
|
@ -170,6 +172,9 @@ private:
|
|||
std::unique_ptr<ComponentPreviewImagesDecorator> m_componentPreviewImagesDecorator;
|
||||
bool m_isComponentPreviewImageDecorationsObsolete = false;
|
||||
|
||||
MeshPreviewImagesGenerator* m_bonePreviewImagesGenerator = nullptr;
|
||||
bool m_isBonePreviewImagesObsolete = false;
|
||||
|
||||
PartManageWidget* m_partManageWidget = nullptr;
|
||||
BoneManageWidget* m_boneManageWidget = nullptr;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <dust3d/mesh/mesh_combiner.h>
|
||||
#include <dust3d/mesh/solid_mesh_boolean_operation.h>
|
||||
#include <dust3d/mesh/triangulate.h>
|
||||
#include <dust3d/util/obj.h>
|
||||
|
||||
namespace dust3d {
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <dust3d/base/position_key.h>
|
||||
#include <dust3d/mesh/re_triangulator.h>
|
||||
#include <dust3d/mesh/solid_mesh_boolean_operation.h>
|
||||
#include <dust3d/util/obj.h>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stdio.h>
|
||||
|
|
Loading…
Reference in New Issue