Interpolate cut edges after deforming
parent
3af98c5334
commit
eb478d1b54
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue