Save cut face transforms
parent
969a25b697
commit
713935adb5
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue