#ifndef DUST3D_MESH_GENERATOR_H #define DUST3D_MESH_GENERATOR_H #include #include #include #include #include "meshcombiner.h" #include "positionkey.h" #include "strokemeshbuilder.h" #include "outcome.h" #include "snapshot.h" #include "combinemode.h" #include "model.h" #include "componentlayer.h" #include "clothforce.h" #include "strokemodifier.h" class GeneratedPart { public: ~GeneratedPart() { releaseMeshes(); }; void releaseMeshes() { delete mesh; mesh = nullptr; } MeshCombiner::Mesh *mesh = nullptr; std::vector vertices; std::vector> faces; std::vector outcomeNodes; std::vector, std::pair>> outcomeEdges; std::vector>> outcomeNodeVertices; std::vector previewVertices; std::vector> previewTriangles; OutcomePaintMap outcomePaintMap; bool isSuccessful = false; bool joined = true; }; class GeneratedComponent { public: ~GeneratedComponent() { releaseMeshes(); }; void releaseMeshes() { delete mesh; mesh = nullptr; for (auto &it: incombinableMeshes) delete it; incombinableMeshes.clear(); } MeshCombiner::Mesh *mesh = nullptr; std::vector incombinableMeshes; std::set> sharedQuadEdges; std::set noneSeamVertices; std::vector outcomeNodes; std::vector, std::pair>> outcomeEdges; std::vector>> outcomeNodeVertices; std::vector outcomePaintMaps; }; class GeneratedCacheContext { public: ~GeneratedCacheContext() { for (auto &it: cachedCombination) delete it.second; for (auto &it: parts) it.second.releaseMeshes(); for (auto &it: components) it.second.releaseMeshes(); } std::map components; std::map parts; std::map partMirrorIdMap; std::map cachedCombination; }; class MeshGenerator : public QObject { Q_OBJECT public: MeshGenerator(Snapshot *snapshot); ~MeshGenerator(); bool isSuccessful(); Model *takeResultMesh(); Model *takePartPreviewMesh(const QUuid &partId); const std::set &generatedPreviewPartIds(); Outcome *takeOutcome(); std::map *takeCutFaceTransforms(); std::map> *takeNodesCutFaces(); void generate(); void setGeneratedCacheContext(GeneratedCacheContext *cacheContext); void setSmoothShadingThresholdAngleDegrees(float degrees); void setDefaultPartColor(const QColor &color); void setId(quint64 id); void setWeldEnabled(bool enabled); quint64 id(); signals: void finished(); public slots: void process(); private: QColor m_defaultPartColor = Qt::white; Snapshot *m_snapshot = nullptr; GeneratedCacheContext *m_cacheContext = nullptr; std::set m_dirtyComponentIds; std::set m_dirtyPartIds; float m_mainProfileMiddleX = 0; float m_sideProfileMiddleX = 0; float m_mainProfileMiddleY = 0; Outcome *m_outcome = nullptr; std::map> m_partNodeIds; std::map> m_partEdgeIds; std::set m_generatedPreviewPartIds; Model *m_resultMesh = nullptr; std::map m_partPreviewMeshes; bool m_isSuccessful = false; bool m_cacheEnabled = false; float m_smoothShadingThresholdAngleDegrees = 60; std::map *m_cutFaceTransforms = nullptr; std::map> *m_nodesCutFaces = nullptr; quint64 m_id = 0; std::vector m_clothCollisionVertices; std::vector> m_clothCollisionTriangles; bool m_weldEnabled = true; void collectParts(); void collectIncombinableComponentMeshes(const QString &componentIdString); void collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache); bool checkIsComponentDirty(const QString &componentIdString); bool checkIsPartDirty(const QString &partIdString); bool checkIsPartDependencyDirty(const QString &partIdString); void checkDirtyFlags(); bool fillPartWithMesh(GeneratedPart &partCache, const QUuid &fillMeshFileId, float deformThickness, float deformWidth, float cutRotation, const StrokeMeshBuilder *strokeMeshBuilder); MeshCombiner::Mesh *combinePartMesh(const QString &partIdString, bool *hasError, bool *retryable, bool addIntermediateNodes=true); MeshCombiner::Mesh *combineComponentMesh(const QString &componentIdString, CombineMode *combineMode); void makeXmirror(const std::vector &sourceVertices, const std::vector> &sourceFaces, std::vector *destVertices, std::vector> *destFaces); void collectSharedQuadEdges(const std::vector &vertices, const std::vector> &faces, std::set> *sharedQuadEdges); MeshCombiner::Mesh *combineTwoMeshes(const MeshCombiner::Mesh &first, const MeshCombiner::Mesh &second, MeshCombiner::Method method, bool recombine=true); void generateSmoothTriangleVertexNormals(const std::vector &vertices, const std::vector> &triangles, const std::vector &triangleNormals, std::vector> *triangleVertexNormals); const std::map *findComponent(const QString &componentIdString); CombineMode componentCombineMode(const std::map *component); bool componentRemeshed(const std::map *component, float *polyCountValue=nullptr); MeshCombiner::Mesh *combineComponentChildGroupMesh(const std::vector &componentIdStrings, GeneratedComponent &componentCache); MeshCombiner::Mesh *combineMultipleMeshes(const std::vector> &multipleMeshes, bool recombine=true); QString componentColorName(const std::map *component); ComponentLayer componentLayer(const std::map *component); float componentClothStiffness(const std::map *component); size_t componentClothIteration(const std::map *component); ClothForce componentClothForce(const std::map *component); float componentClothOffset(const std::map *component); void collectUncombinedComponent(const QString &componentIdString); void collectClothComponent(const QString &componentIdString); void collectClothComponentIdStrings(const QString &componentIdString, std::vector *componentIdStrings); void cutFaceStringToCutTemplate(const QString &cutFaceString, std::vector &cutTemplate); void remesh(const std::vector &inputNodes, const std::vector> &interpolatedNodes, const std::vector &inputVertices, const std::vector> &inputFaces, float targetVertexMultiplyFactor, std::vector *outputVertices, std::vector> *outputQuads, std::vector> *outputTriangles, std::vector>> *outputNodeVertices); void postprocessOutcome(Outcome *outcome); void collectErroredParts(); }; #endif