Save cut face transforms

master
Jeremy Hu 2019-07-03 07:19:18 +09:30
parent 969a25b697
commit 713935adb5
6 changed files with 66 additions and 7 deletions

View File

@ -27,6 +27,7 @@ MeshGenerator::~MeshGenerator()
delete m_resultMesh;
delete m_snapshot;
delete m_outcome;
delete m_cutFaceTransforms;
}
bool MeshGenerator::isSucceed()
@ -60,6 +61,13 @@ Outcome *MeshGenerator::takeOutcome()
return outcome;
}
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *MeshGenerator::takeCutFaceTransforms()
{
auto cutFaceTransforms = m_cutFaceTransforms;
m_cutFaceTransforms = nullptr;
return cutFaceTransforms;
}
void MeshGenerator::collectParts()
{
for (const auto &node: m_snapshot->nodes) {
@ -465,12 +473,23 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
builder->enableBaseNormalOnY(false);
}
std::vector<size_t> builderNodeIndices;
for (const auto &node: modifier->nodes())
builder->addNode(node.position, node.radius, node.cutTemplate);
builderNodeIndices.push_back(builder->addNode(node.position, node.radius, node.cutTemplate));
for (const auto &edge: modifier->edges())
builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex);
bool buildSucceed = builder->build();
for (size_t i = 0; i < modifier->nodes().size(); ++i) {
const auto &node = modifier->nodes()[i];
if (!node.isOriginal)
continue;
const QString &nodeIdString = nodeIndexToIdStringMap[node.originNodeIndex];
const nodemesh::Builder::CutFaceTransform *cutFaceTransform = builder->nodeAdjustableCutFaceTransform(builderNodeIndices[i]);
if (nullptr != cutFaceTransform)
m_cutFaceTransforms->insert({QUuid(nodeIdString), *cutFaceTransform});
}
partCache.vertices = builder->generatedVertices();
partCache.faces = builder->generatedFaces();
for (size_t i = 0; i < partCache.vertices.size(); ++i) {
@ -962,6 +981,7 @@ void MeshGenerator::generate()
countTimeConsumed.start();
m_outcome = new Outcome;
m_cutFaceTransforms = new std::map<QUuid, nodemesh::Builder::CutFaceTransform>;
bool needDeleteCacheContext = false;
if (nullptr == m_cacheContext) {

View File

@ -5,6 +5,7 @@
#include <QColor>
#include <nodemesh/combiner.h>
#include <nodemesh/positionkey.h>
#include <nodemesh/builder.h>
#include "outcome.h"
#include "snapshot.h"
#include "combinemode.h"
@ -59,6 +60,7 @@ public:
MeshLoader *takePartPreviewMesh(const QUuid &partId);
const std::set<QUuid> &generatedPreviewPartIds();
Outcome *takeOutcome();
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *takeCutFaceTransforms();
void generate();
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
void setSmoothShadingThresholdAngleDegrees(float degrees);
@ -86,6 +88,7 @@ private:
bool m_isSucceed = false;
bool m_cacheEnabled = false;
float m_smoothShadingThresholdAngleDegrees = 60;
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *m_cutFaceTransforms = nullptr;
void collectParts();
bool checkIsComponentDirty(const QString &componentIdString);

View File

@ -417,6 +417,16 @@ void Builder::insertCutVertices(const std::vector<QVector3D> &cut, std::vector<s
}
}
const Builder::CutFaceTransform *Builder::nodeAdjustableCutFaceTransform(size_t nodeIndex)
{
if (nodeIndex >= m_nodes.size())
return nullptr;
const auto &node = m_nodes[nodeIndex];
if (!node.hasAdjustableCutFace)
return nullptr;
return &node.cutFaceTransform;
}
bool Builder::generateCutsForNode(size_t nodeIndex)
{
if (m_swallowedNodes.find(nodeIndex) != m_swallowedNodes.end()) {
@ -430,7 +440,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex)
if (1 == neighborsCount) {
const QVector3D &cutNormal = node.raysToNeibors[0];
std::vector<QVector3D> cut;
makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut);
makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform);
node.hasAdjustableCutFace = true;
std::vector<size_t> vertices;
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
m_generatedFaces.push_back(vertices);
@ -438,7 +449,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex)
} else if (2 == neighborsCount) {
const QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2;
std::vector<QVector3D> cut;
makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut);
makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform);
node.hasAdjustableCutFace = true;
std::vector<size_t> vertices;
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
std::vector<size_t> verticesReversed;
@ -678,7 +690,8 @@ void Builder::makeCut(const QVector3D &position,
QVector3D &baseNormal,
const QVector3D &cutNormal,
const QVector3D &traverseDirection,
std::vector<QVector3D> &resultCut)
std::vector<QVector3D> &resultCut,
CutFaceTransform *cutFaceTransform)
{
auto finalCutTemplate = cutTemplate;
auto finalCutNormal = cutNormal;
@ -690,11 +703,17 @@ void Builder::makeCut(const QVector3D &position,
finalCutNormal = -finalCutNormal;
std::reverse(finalCutTemplate.begin(), finalCutTemplate.end());
std::rotate(finalCutTemplate.begin(), finalCutTemplate.begin() + finalCutTemplate.size() - 1, finalCutTemplate.end());
if (nullptr != cutFaceTransform)
cutFaceTransform->reverse = true;
}
QVector3D u = QVector3D::crossProduct(finalCutNormal, baseNormal).normalized();
QVector3D v = QVector3D::crossProduct(u, finalCutNormal).normalized();
auto uFactor = u * radius;
auto vFactor = v * radius;
if (nullptr != cutFaceTransform) {
cutFaceTransform->uFactor = uFactor;
cutFaceTransform->vFactor = vFactor;
}
for (const auto &t: finalCutTemplate) {
resultCut.push_back(uFactor * t.x() + vFactor * t.y());
}
@ -705,6 +724,8 @@ void Builder::makeCut(const QVector3D &position,
for (auto &positionOnCut: resultCut) {
positionOnCut = rotation * positionOnCut;
}
if (nullptr != cutFaceTransform)
cutFaceTransform->rotation = rotation;
}
for (auto &positionOnCut: resultCut) {
positionOnCut += position;

View File

@ -5,6 +5,7 @@
#include <vector>
#include <map>
#include <set>
#include <QMatrix4x4>
namespace nodemesh
{
@ -12,6 +13,14 @@ namespace nodemesh
class Builder
{
public:
struct CutFaceTransform
{
QMatrix4x4 rotation;
QVector3D uFactor;
QVector3D vFactor;
bool reverse = false;
};
size_t addNode(const QVector3D &position, float radius, const std::vector<QVector2D> &cutTemplate);
size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex);
void setDeformThickness(float thickness);
@ -26,6 +35,7 @@ public:
const std::vector<size_t> &generatedVerticesSourceNodeIndices();
void exportAsObj(const QString &filename);
bool build();
const CutFaceTransform *nodeAdjustableCutFaceTransform(size_t nodeIndex);
private:
@ -38,6 +48,7 @@ private:
std::vector<size_t> edges;
std::vector<QVector2D> cutTemplate;
std::vector<QVector3D> raysToNeibors;
CutFaceTransform cutFaceTransform;
QVector3D initialTraverseDirection;
QVector3D traverseDirection;
QVector3D growthDirection;
@ -48,6 +59,7 @@ private:
bool baseNormalResolved = false;
bool baseNormalSearched = false;
bool hasInitialTraverseDirection = false;
bool hasAdjustableCutFace = false;
size_t anotherEdge(size_t edgeIndex) const
{
@ -122,7 +134,8 @@ private:
QVector3D &baseNormal,
const QVector3D &cutNormal,
const QVector3D &traverseDirection,
std::vector<QVector3D> &resultCut);
std::vector<QVector3D> &resultCut,
CutFaceTransform *cutFaceTransform=nullptr);
void insertCutVertices(const std::vector<QVector3D> &cut, std::vector<size_t> &vertices, size_t nodeIndex, const QVector3D &cutDirect);
void stitchEdgeCuts();
void applyWeld();

View File

@ -11,6 +11,7 @@ size_t Modifier::addNode(const QVector3D &position, float radius, const std::vec
size_t nodeIndex = m_nodes.size();
Node node;
node.isOriginal = true;
node.position = position;
node.radius = radius;
node.cutTemplate = cutTemplate;

View File

@ -11,10 +11,11 @@ class Modifier
public:
struct Node
{
bool isOriginal = false;
QVector3D position;
float radius;
float radius = 0.0;
std::vector<QVector2D> cutTemplate;
size_t originNodeIndex;
size_t originNodeIndex = 0;
};
struct Edge