Interpolate cut edges after deforming

master
huxingyi 2020-10-19 00:04:43 +09:30
parent 3af98c5334
commit eb478d1b54
5 changed files with 67 additions and 11 deletions

View File

@ -19,6 +19,7 @@
#include "scriptrunner.h" #include "scriptrunner.h"
#include "imageforever.h" #include "imageforever.h"
#include "contourtopartconverter.h" #include "contourtopartconverter.h"
#include "meshgenerator.h"
unsigned long Document::m_maxSnapshot = 1000; unsigned long Document::m_maxSnapshot = 1000;
const float Component::defaultClothStiffness = 0.5f; const float Component::defaultClothStiffness = 0.5f;
@ -46,7 +47,7 @@ Document::Document() :
m_meshGenerator(nullptr), m_meshGenerator(nullptr),
m_resultMesh(nullptr), m_resultMesh(nullptr),
m_paintedMesh(nullptr), m_paintedMesh(nullptr),
m_resultMeshCutFaceTransforms(nullptr), //m_resultMeshCutFaceTransforms(nullptr),
m_resultMeshNodesCutFaces(nullptr), m_resultMeshNodesCutFaces(nullptr),
m_isMeshGenerationSucceed(true), m_isMeshGenerationSucceed(true),
m_batchChangeRefCount(0), m_batchChangeRefCount(0),
@ -79,7 +80,8 @@ Document::Document() :
m_paintMode(PaintMode::None), m_paintMode(PaintMode::None),
m_mousePickRadius(0.05), m_mousePickRadius(0.05),
m_saveNextPaintSnapshot(false), m_saveNextPaintSnapshot(false),
m_vertexColorVoxelGrid(nullptr) m_vertexColorVoxelGrid(nullptr),
m_generatedCacheContext(nullptr)
{ {
connect(&Preferences::instance(), &Preferences::partColorChanged, this, &Document::applyPreferencePartColorChange); connect(&Preferences::instance(), &Preferences::partColorChanged, this, &Document::applyPreferencePartColorChange);
connect(&Preferences::instance(), &Preferences::flatShadingChanged, this, &Document::applyPreferenceFlatShadingChange); connect(&Preferences::instance(), &Preferences::flatShadingChanged, this, &Document::applyPreferenceFlatShadingChange);
@ -106,7 +108,7 @@ Document::~Document()
{ {
delete m_resultMesh; delete m_resultMesh;
delete m_paintedMesh; delete m_paintedMesh;
delete m_resultMeshCutFaceTransforms; //delete m_resultMeshCutFaceTransforms;
delete m_resultMeshNodesCutFaces; delete m_resultMeshNodesCutFaces;
delete m_postProcessedOutcome; delete m_postProcessedOutcome;
delete textureGuideImage; delete textureGuideImage;
@ -1970,8 +1972,8 @@ void Document::meshReady()
delete m_resultMesh; delete m_resultMesh;
m_resultMesh = resultMesh; m_resultMesh = resultMesh;
delete m_resultMeshCutFaceTransforms; //delete m_resultMeshCutFaceTransforms;
m_resultMeshCutFaceTransforms = m_meshGenerator->takeCutFaceTransforms(); //m_resultMeshCutFaceTransforms = m_meshGenerator->takeCutFaceTransforms();
delete m_resultMeshNodesCutFaces; delete m_resultMeshNodesCutFaces;
m_resultMeshNodesCutFaces = m_meshGenerator->takeNodesCutFaces(); m_resultMeshNodesCutFaces = m_meshGenerator->takeNodesCutFaces();
@ -2093,7 +2095,9 @@ void Document::generateMesh()
m_meshGenerator = new MeshGenerator(snapshot); m_meshGenerator = new MeshGenerator(snapshot);
m_meshGenerator->setId(m_nextMeshGenerationId++); m_meshGenerator->setId(m_nextMeshGenerationId++);
m_meshGenerator->setDefaultPartColor(Preferences::instance().partColor()); m_meshGenerator->setDefaultPartColor(Preferences::instance().partColor());
m_meshGenerator->setGeneratedCacheContext(&m_generatedCacheContext); if (nullptr == m_generatedCacheContext)
m_generatedCacheContext = new GeneratedCacheContext;
m_meshGenerator->setGeneratedCacheContext(m_generatedCacheContext);
if (!m_smoothNormal) { if (!m_smoothNormal) {
m_meshGenerator->setSmoothShadingThresholdAngleDegrees(0); m_meshGenerator->setSmoothShadingThresholdAngleDegrees(0);
} }

View File

@ -12,7 +12,6 @@
#include <QPolygon> #include <QPolygon>
#include "snapshot.h" #include "snapshot.h"
#include "model.h" #include "model.h"
#include "meshgenerator.h"
#include "theme.h" #include "theme.h"
#include "texturegenerator.h" #include "texturegenerator.h"
#include "meshresultpostprocessor.h" #include "meshresultpostprocessor.h"
@ -37,6 +36,8 @@
class MaterialPreviewsGenerator; class MaterialPreviewsGenerator;
class MotionsGenerator; class MotionsGenerator;
class ScriptRunner; class ScriptRunner;
class MeshGenerator;
class GeneratedCacheContext;
class HistoryItem class HistoryItem
{ {
@ -787,7 +788,7 @@ private: // need initialize
MeshGenerator *m_meshGenerator; MeshGenerator *m_meshGenerator;
Model *m_resultMesh; Model *m_resultMesh;
Model *m_paintedMesh; Model *m_paintedMesh;
std::map<QUuid, StrokeMeshBuilder::CutFaceTransform> *m_resultMeshCutFaceTransforms; //std::map<QUuid, StrokeMeshBuilder::CutFaceTransform> *m_resultMeshCutFaceTransforms;
std::map<QUuid, std::map<QString, QVector2D>> *m_resultMeshNodesCutFaces; std::map<QUuid, std::map<QString, QVector2D>> *m_resultMeshNodesCutFaces;
bool m_isMeshGenerationSucceed; bool m_isMeshGenerationSucceed;
int m_batchChangeRefCount; int m_batchChangeRefCount;
@ -824,11 +825,11 @@ private: // need initialize
float m_mousePickRadius; float m_mousePickRadius;
bool m_saveNextPaintSnapshot; bool m_saveNextPaintSnapshot;
VoxelGrid<PaintColor> *m_vertexColorVoxelGrid; VoxelGrid<PaintColor> *m_vertexColorVoxelGrid;
GeneratedCacheContext *m_generatedCacheContext;
private: private:
static unsigned long m_maxSnapshot; static unsigned long m_maxSnapshot;
std::deque<HistoryItem> m_undoItems; std::deque<HistoryItem> m_undoItems;
std::deque<HistoryItem> m_redoItems; std::deque<HistoryItem> m_redoItems;
GeneratedCacheContext m_generatedCacheContext;
std::vector<std::pair<QtMsgType, QString>> m_resultRigMessages; std::vector<std::pair<QtMsgType, QString>> m_resultRigMessages;
QVector3D m_mouseRayNear; QVector3D m_mouseRayNear;
QVector3D m_mouseRayFar; QVector3D m_mouseRayFar;

View File

@ -39,10 +39,12 @@ void remeshHole(std::vector<QVector3D> &vertices,
Mesh mesh; Mesh mesh;
double targetEdgeLength = 0; double targetEdgeLength = 0;
for (size_t i = 1; i < hole.size(); ++i) { for (size_t i = 0; i < hole.size(); ++i) {
targetEdgeLength += (vertices[hole[i - 1]] - vertices[hole[i]]).length(); size_t j = (i + 1) % hole.size();
targetEdgeLength += (vertices[hole[i]] - vertices[hole[j]]).length();
} }
targetEdgeLength /= hole.size(); targetEdgeLength /= hole.size();
targetEdgeLength *= 1.2;
std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> meshFace; std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> meshFace;
std::vector<size_t> originalIndices; std::vector<size_t> originalIndices;

View File

@ -247,6 +247,53 @@ void StrokeMeshBuilder::buildMesh()
} }
} }
void StrokeMeshBuilder::interpolateCutEdges()
{
std::vector<std::vector<size_t>> interpolatedCuts;
for (const auto &cut: m_cuts) {
double sumOfLegnth = 0;
std::vector<double> edgeLengths;
edgeLengths.reserve(cut.size());
for (size_t i = 0; i < cut.size(); ++i) {
size_t j = (i + 1) % cut.size();
double length = (m_generatedVertices[cut[i]] - m_generatedVertices[cut[j]]).length();
edgeLengths.push_back(length);
sumOfLegnth += length;
}
double targetLength = 1.2 * sumOfLegnth / cut.size();
std::vector<size_t> newCut;
for (size_t index = 0; index < cut.size(); ++index) {
size_t nextIndex = (index + 1) % cut.size();
newCut.push_back(cut[index]);
const auto &oldEdgeLength = edgeLengths[index];
if (targetLength >= oldEdgeLength)
continue;
size_t newInsertNum = oldEdgeLength / targetLength;
qDebug() << "oldEdgeLength:" << oldEdgeLength << "targetLength:" << targetLength << "newInsertNum:" << newInsertNum;
if (newInsertNum < 1)
newInsertNum = 1;
if (newInsertNum > 100)
continue;
float stepFactor = 1.0 / (newInsertNum + 1);
float factor = stepFactor;
for (size_t i = 0; i < newInsertNum && factor < 1.0; factor += stepFactor, ++i) {
float firstFactor = 1.0 - factor;
auto newPosition = m_generatedVertices[cut[index]] * firstFactor + m_generatedVertices[cut[nextIndex]] * factor;
newCut.push_back(m_generatedVertices.size());
m_generatedVertices.push_back(newPosition);
const auto &oldIndex = cut[index];
m_generatedVerticesCutDirects.push_back(m_generatedVerticesCutDirects[oldIndex]);
m_generatedVerticesSourceNodeIndices.push_back(m_generatedVerticesSourceNodeIndices[oldIndex]);
m_generatedVerticesInfos.push_back(m_generatedVerticesInfos[oldIndex]);
}
}
interpolatedCuts.push_back(newCut);
}
m_cuts = interpolatedCuts;
}
void StrokeMeshBuilder::stitchCuts() void StrokeMeshBuilder::stitchCuts()
{ {
for (size_t i = m_isRing ? 0 : 1; i < m_nodeIndices.size(); ++i) { for (size_t i = m_isRing ? 0 : 1; i < m_nodeIndices.size(); ++i) {
@ -744,6 +791,7 @@ bool StrokeMeshBuilder::build()
buildMesh(); buildMesh();
applyDeform(); applyDeform();
interpolateCutEdges();
stitchCuts(); stitchCuts();
return true; return true;
} }

View File

@ -118,6 +118,7 @@ private:
std::vector<size_t> edgeloopFlipped(const std::vector<size_t> &edgeLoop); std::vector<size_t> edgeloopFlipped(const std::vector<size_t> &edgeLoop);
void reviseNodeBaseNormal(Node &node); void reviseNodeBaseNormal(Node &node);
void applyDeform(); void applyDeform();
void interpolateCutEdges();
void stitchCuts(); void stitchCuts();
}; };