Save cut face transforms
parent
969a25b697
commit
713935adb5
|
@ -27,6 +27,7 @@ MeshGenerator::~MeshGenerator()
|
||||||
delete m_resultMesh;
|
delete m_resultMesh;
|
||||||
delete m_snapshot;
|
delete m_snapshot;
|
||||||
delete m_outcome;
|
delete m_outcome;
|
||||||
|
delete m_cutFaceTransforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeshGenerator::isSucceed()
|
bool MeshGenerator::isSucceed()
|
||||||
|
@ -60,6 +61,13 @@ Outcome *MeshGenerator::takeOutcome()
|
||||||
return outcome;
|
return outcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *MeshGenerator::takeCutFaceTransforms()
|
||||||
|
{
|
||||||
|
auto cutFaceTransforms = m_cutFaceTransforms;
|
||||||
|
m_cutFaceTransforms = nullptr;
|
||||||
|
return cutFaceTransforms;
|
||||||
|
}
|
||||||
|
|
||||||
void MeshGenerator::collectParts()
|
void MeshGenerator::collectParts()
|
||||||
{
|
{
|
||||||
for (const auto &node: m_snapshot->nodes) {
|
for (const auto &node: m_snapshot->nodes) {
|
||||||
|
@ -465,12 +473,23 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
|
||||||
builder->enableBaseNormalOnY(false);
|
builder->enableBaseNormalOnY(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<size_t> builderNodeIndices;
|
||||||
for (const auto &node: modifier->nodes())
|
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())
|
for (const auto &edge: modifier->edges())
|
||||||
builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex);
|
builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex);
|
||||||
bool buildSucceed = builder->build();
|
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.vertices = builder->generatedVertices();
|
||||||
partCache.faces = builder->generatedFaces();
|
partCache.faces = builder->generatedFaces();
|
||||||
for (size_t i = 0; i < partCache.vertices.size(); ++i) {
|
for (size_t i = 0; i < partCache.vertices.size(); ++i) {
|
||||||
|
@ -962,6 +981,7 @@ void MeshGenerator::generate()
|
||||||
countTimeConsumed.start();
|
countTimeConsumed.start();
|
||||||
|
|
||||||
m_outcome = new Outcome;
|
m_outcome = new Outcome;
|
||||||
|
m_cutFaceTransforms = new std::map<QUuid, nodemesh::Builder::CutFaceTransform>;
|
||||||
|
|
||||||
bool needDeleteCacheContext = false;
|
bool needDeleteCacheContext = false;
|
||||||
if (nullptr == m_cacheContext) {
|
if (nullptr == m_cacheContext) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <nodemesh/combiner.h>
|
#include <nodemesh/combiner.h>
|
||||||
#include <nodemesh/positionkey.h>
|
#include <nodemesh/positionkey.h>
|
||||||
|
#include <nodemesh/builder.h>
|
||||||
#include "outcome.h"
|
#include "outcome.h"
|
||||||
#include "snapshot.h"
|
#include "snapshot.h"
|
||||||
#include "combinemode.h"
|
#include "combinemode.h"
|
||||||
|
@ -59,6 +60,7 @@ public:
|
||||||
MeshLoader *takePartPreviewMesh(const QUuid &partId);
|
MeshLoader *takePartPreviewMesh(const QUuid &partId);
|
||||||
const std::set<QUuid> &generatedPreviewPartIds();
|
const std::set<QUuid> &generatedPreviewPartIds();
|
||||||
Outcome *takeOutcome();
|
Outcome *takeOutcome();
|
||||||
|
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *takeCutFaceTransforms();
|
||||||
void generate();
|
void generate();
|
||||||
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
|
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
|
||||||
void setSmoothShadingThresholdAngleDegrees(float degrees);
|
void setSmoothShadingThresholdAngleDegrees(float degrees);
|
||||||
|
@ -86,6 +88,7 @@ private:
|
||||||
bool m_isSucceed = false;
|
bool m_isSucceed = false;
|
||||||
bool m_cacheEnabled = false;
|
bool m_cacheEnabled = false;
|
||||||
float m_smoothShadingThresholdAngleDegrees = 60;
|
float m_smoothShadingThresholdAngleDegrees = 60;
|
||||||
|
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *m_cutFaceTransforms = nullptr;
|
||||||
|
|
||||||
void collectParts();
|
void collectParts();
|
||||||
bool checkIsComponentDirty(const QString &componentIdString);
|
bool checkIsComponentDirty(const QString &componentIdString);
|
||||||
|
|
|
@ -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)
|
bool Builder::generateCutsForNode(size_t nodeIndex)
|
||||||
{
|
{
|
||||||
if (m_swallowedNodes.find(nodeIndex) != m_swallowedNodes.end()) {
|
if (m_swallowedNodes.find(nodeIndex) != m_swallowedNodes.end()) {
|
||||||
|
@ -430,7 +440,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex)
|
||||||
if (1 == neighborsCount) {
|
if (1 == neighborsCount) {
|
||||||
const QVector3D &cutNormal = node.raysToNeibors[0];
|
const QVector3D &cutNormal = node.raysToNeibors[0];
|
||||||
std::vector<QVector3D> cut;
|
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;
|
std::vector<size_t> vertices;
|
||||||
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
|
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
|
||||||
m_generatedFaces.push_back(vertices);
|
m_generatedFaces.push_back(vertices);
|
||||||
|
@ -438,7 +449,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex)
|
||||||
} else if (2 == neighborsCount) {
|
} else if (2 == neighborsCount) {
|
||||||
const QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2;
|
const QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2;
|
||||||
std::vector<QVector3D> cut;
|
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;
|
std::vector<size_t> vertices;
|
||||||
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
|
insertCutVertices(cut, vertices, nodeIndex, cutNormal);
|
||||||
std::vector<size_t> verticesReversed;
|
std::vector<size_t> verticesReversed;
|
||||||
|
@ -678,7 +690,8 @@ void Builder::makeCut(const QVector3D &position,
|
||||||
QVector3D &baseNormal,
|
QVector3D &baseNormal,
|
||||||
const QVector3D &cutNormal,
|
const QVector3D &cutNormal,
|
||||||
const QVector3D &traverseDirection,
|
const QVector3D &traverseDirection,
|
||||||
std::vector<QVector3D> &resultCut)
|
std::vector<QVector3D> &resultCut,
|
||||||
|
CutFaceTransform *cutFaceTransform)
|
||||||
{
|
{
|
||||||
auto finalCutTemplate = cutTemplate;
|
auto finalCutTemplate = cutTemplate;
|
||||||
auto finalCutNormal = cutNormal;
|
auto finalCutNormal = cutNormal;
|
||||||
|
@ -690,11 +703,17 @@ void Builder::makeCut(const QVector3D &position,
|
||||||
finalCutNormal = -finalCutNormal;
|
finalCutNormal = -finalCutNormal;
|
||||||
std::reverse(finalCutTemplate.begin(), finalCutTemplate.end());
|
std::reverse(finalCutTemplate.begin(), finalCutTemplate.end());
|
||||||
std::rotate(finalCutTemplate.begin(), finalCutTemplate.begin() + finalCutTemplate.size() - 1, 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 u = QVector3D::crossProduct(finalCutNormal, baseNormal).normalized();
|
||||||
QVector3D v = QVector3D::crossProduct(u, finalCutNormal).normalized();
|
QVector3D v = QVector3D::crossProduct(u, finalCutNormal).normalized();
|
||||||
auto uFactor = u * radius;
|
auto uFactor = u * radius;
|
||||||
auto vFactor = v * radius;
|
auto vFactor = v * radius;
|
||||||
|
if (nullptr != cutFaceTransform) {
|
||||||
|
cutFaceTransform->uFactor = uFactor;
|
||||||
|
cutFaceTransform->vFactor = vFactor;
|
||||||
|
}
|
||||||
for (const auto &t: finalCutTemplate) {
|
for (const auto &t: finalCutTemplate) {
|
||||||
resultCut.push_back(uFactor * t.x() + vFactor * t.y());
|
resultCut.push_back(uFactor * t.x() + vFactor * t.y());
|
||||||
}
|
}
|
||||||
|
@ -705,6 +724,8 @@ void Builder::makeCut(const QVector3D &position,
|
||||||
for (auto &positionOnCut: resultCut) {
|
for (auto &positionOnCut: resultCut) {
|
||||||
positionOnCut = rotation * positionOnCut;
|
positionOnCut = rotation * positionOnCut;
|
||||||
}
|
}
|
||||||
|
if (nullptr != cutFaceTransform)
|
||||||
|
cutFaceTransform->rotation = rotation;
|
||||||
}
|
}
|
||||||
for (auto &positionOnCut: resultCut) {
|
for (auto &positionOnCut: resultCut) {
|
||||||
positionOnCut += position;
|
positionOnCut += position;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <QMatrix4x4>
|
||||||
|
|
||||||
namespace nodemesh
|
namespace nodemesh
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,14 @@ namespace nodemesh
|
||||||
class Builder
|
class Builder
|
||||||
{
|
{
|
||||||
public:
|
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 addNode(const QVector3D &position, float radius, const std::vector<QVector2D> &cutTemplate);
|
||||||
size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex);
|
size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex);
|
||||||
void setDeformThickness(float thickness);
|
void setDeformThickness(float thickness);
|
||||||
|
@ -26,6 +35,7 @@ public:
|
||||||
const std::vector<size_t> &generatedVerticesSourceNodeIndices();
|
const std::vector<size_t> &generatedVerticesSourceNodeIndices();
|
||||||
void exportAsObj(const QString &filename);
|
void exportAsObj(const QString &filename);
|
||||||
bool build();
|
bool build();
|
||||||
|
const CutFaceTransform *nodeAdjustableCutFaceTransform(size_t nodeIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -38,6 +48,7 @@ private:
|
||||||
std::vector<size_t> edges;
|
std::vector<size_t> edges;
|
||||||
std::vector<QVector2D> cutTemplate;
|
std::vector<QVector2D> cutTemplate;
|
||||||
std::vector<QVector3D> raysToNeibors;
|
std::vector<QVector3D> raysToNeibors;
|
||||||
|
CutFaceTransform cutFaceTransform;
|
||||||
QVector3D initialTraverseDirection;
|
QVector3D initialTraverseDirection;
|
||||||
QVector3D traverseDirection;
|
QVector3D traverseDirection;
|
||||||
QVector3D growthDirection;
|
QVector3D growthDirection;
|
||||||
|
@ -48,6 +59,7 @@ private:
|
||||||
bool baseNormalResolved = false;
|
bool baseNormalResolved = false;
|
||||||
bool baseNormalSearched = false;
|
bool baseNormalSearched = false;
|
||||||
bool hasInitialTraverseDirection = false;
|
bool hasInitialTraverseDirection = false;
|
||||||
|
bool hasAdjustableCutFace = false;
|
||||||
|
|
||||||
size_t anotherEdge(size_t edgeIndex) const
|
size_t anotherEdge(size_t edgeIndex) const
|
||||||
{
|
{
|
||||||
|
@ -122,7 +134,8 @@ private:
|
||||||
QVector3D &baseNormal,
|
QVector3D &baseNormal,
|
||||||
const QVector3D &cutNormal,
|
const QVector3D &cutNormal,
|
||||||
const QVector3D &traverseDirection,
|
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 insertCutVertices(const std::vector<QVector3D> &cut, std::vector<size_t> &vertices, size_t nodeIndex, const QVector3D &cutDirect);
|
||||||
void stitchEdgeCuts();
|
void stitchEdgeCuts();
|
||||||
void applyWeld();
|
void applyWeld();
|
||||||
|
|
|
@ -11,6 +11,7 @@ size_t Modifier::addNode(const QVector3D &position, float radius, const std::vec
|
||||||
size_t nodeIndex = m_nodes.size();
|
size_t nodeIndex = m_nodes.size();
|
||||||
|
|
||||||
Node node;
|
Node node;
|
||||||
|
node.isOriginal = true;
|
||||||
node.position = position;
|
node.position = position;
|
||||||
node.radius = radius;
|
node.radius = radius;
|
||||||
node.cutTemplate = cutTemplate;
|
node.cutTemplate = cutTemplate;
|
||||||
|
|
|
@ -11,10 +11,11 @@ class Modifier
|
||||||
public:
|
public:
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
|
bool isOriginal = false;
|
||||||
QVector3D position;
|
QVector3D position;
|
||||||
float radius;
|
float radius = 0.0;
|
||||||
std::vector<QVector2D> cutTemplate;
|
std::vector<QVector2D> cutTemplate;
|
||||||
size_t originNodeIndex;
|
size_t originNodeIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Edge
|
struct Edge
|
||||||
|
|
Loading…
Reference in New Issue