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