Prepare for cut face offset modifier

master
Jeremy Hu 2019-07-07 15:57:58 +09:30
parent 820aa90406
commit eb91a8a16c
16 changed files with 275 additions and 52 deletions

View File

@ -72,7 +72,8 @@ void normalizeCutFacePoints(std::vector<QVector2D> *points)
correctFlippedNormal(points);
}
void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<std::tuple<float, float, float>> &nodes, bool isRing)
void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<std::tuple<float, float, float, QString>> &nodes, bool isRing,
std::vector<QString> *pointsIds)
{
if (isRing) {
if (nodes.size() < 3)
@ -80,6 +81,11 @@ void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<st
for (const auto &it: nodes) {
points.push_back(QVector2D(std::get<1>(it), std::get<2>(it)));
}
if (nullptr != pointsIds) {
for (const auto &it: nodes) {
pointsIds->push_back(std::get<3>(it));
}
}
normalizeCutFacePoints(&points);
return;
}
@ -117,8 +123,18 @@ void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<st
for (const auto &it: cutPoints) {
points.push_back(it.first);
}
if (nullptr != pointsIds) {
for (const auto &it: nodes) {
pointsIds->push_back(std::get<3>(it) + QString("/1"));
}
}
for (auto it = cutPoints.rbegin(); it != cutPoints.rend(); ++it) {
points.push_back(it->second);
}
if (nullptr != pointsIds) {
for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
pointsIds->push_back(std::get<3>(*it) + QString("/2"));
}
}
normalizeCutFacePoints(&points);
}

View File

@ -97,6 +97,7 @@ std::vector<QVector2D> CutFaceToPoints(CutFace cutFace) \
}
void normalizeCutFacePoints(std::vector<QVector2D> *points);
void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<std::tuple<float, float, float>> &nodes, bool isRing=false);
void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<std::tuple<float, float, float, QString>> &nodes, bool isRing=false,
std::vector<QString> *pointsIds=nullptr);
#endif

View File

@ -35,6 +35,8 @@ Document::Document() :
m_isResultMeshObsolete(false),
m_meshGenerator(nullptr),
m_resultMesh(nullptr),
m_resultMeshCutFaceTransforms(nullptr),
m_resultMeshNodesCutFaces(nullptr),
m_isMeshGenerationSucceed(true),
m_batchChangeRefCount(0),
m_currentOutcome(nullptr),
@ -80,6 +82,8 @@ void Document::applyPreferenceFlatShadingChange()
Document::~Document()
{
delete m_resultMesh;
delete m_resultMeshCutFaceTransforms;
delete m_resultMeshNodesCutFaces;
delete m_postProcessedOutcome;
delete textureGuideImage;
delete textureImage;
@ -1516,6 +1520,14 @@ void Document::meshReady()
delete m_resultMesh;
m_resultMesh = resultMesh;
delete m_resultMeshCutFaceTransforms;
m_resultMeshCutFaceTransforms = m_meshGenerator->takeCutFaceTransforms();
delete m_resultMeshNodesCutFaces;
m_resultMeshNodesCutFaces = m_meshGenerator->takeNodesCutFaces();
//addToolToMesh(m_resultMesh);
m_isMeshGenerationSucceed = isSucceed;
delete m_currentOutcome;
@ -1540,6 +1552,36 @@ void Document::meshReady()
}
}
//void Document::addToolToMesh(MeshLoader *mesh)
//{
// if (nullptr == mesh)
// return;
//
// if (nullptr == m_resultMeshCutFaceTransforms ||
// nullptr == m_resultMeshNodesCutFaces ||
// m_resultMeshCutFaceTransforms->empty() ||
// m_resultMeshNodesCutFaces->empty())
// return;
//
// ToolMesh toolMesh;
// for (const auto &transformIt: *m_resultMeshCutFaceTransforms) {
// const auto &nodeId = transformIt.first;
// const auto &transform = transformIt.second;
// qDebug() << "nodeId:" << nodeId;
// for (const auto &cutFaceIt: (*m_resultMeshNodesCutFaces)[nodeId]) {
// const auto &cutFaceId = cutFaceIt.first;
// const auto &cutFace2d = cutFaceIt.second;
// QVector3D position = transform.translation + transform.rotation * (transform.uFactor * cutFace2d.x() + transform.vFactor * cutFace2d.y());
// qDebug() << "cutFaceId:" << cutFaceId;
// toolMesh.addNode(nodeId.toString() + cutFaceId, position);
// }
// }
// toolMesh.generate();
// int shaderVertexCount = 0;
// ShaderVertex *shaderVertices = toolMesh.takeShaderVertices(&shaderVertexCount);
// mesh->updateTool(shaderVertices, shaderVertexCount);
//}
bool Document::isPostProcessResultObsolete() const
{
return m_isPostProcessResultObsolete;
@ -1668,6 +1710,8 @@ void Document::textureReady()
delete m_resultTextureMesh;
m_resultTextureMesh = m_textureGenerator->takeResultMesh();
//addToolToMesh(m_resultTextureMesh);
m_textureImageUpdateVersion++;
delete m_textureGenerator;

View File

@ -651,10 +651,13 @@ private:
void markAllDirty();
void removeRigResults();
void updateLinkedPart(QUuid oldPartId, QUuid newPartId);
//void addToolToMesh(MeshLoader *mesh);
private: // need initialize
bool m_isResultMeshObsolete;
MeshGenerator *m_meshGenerator;
MeshLoader *m_resultMesh;
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *m_resultMeshCutFaceTransforms;
std::map<QUuid, std::map<QString, QVector2D>> *m_resultMeshNodesCutFaces;
bool m_isMeshGenerationSucceed;
int m_batchChangeRefCount;
Outcome *m_currentOutcome;

View File

@ -69,7 +69,7 @@ std::map<QUuid, nodemesh::Builder::CutFaceTransform> *MeshGenerator::takeCutFace
return cutFaceTransforms;
}
std::map<QUuid, std::map<QString, std::tuple<float, float, float>>> *MeshGenerator::takeNodesCutFaces()
std::map<QUuid, std::map<QString, QVector2D>> *MeshGenerator::takeNodesCutFaces()
{
auto nodesCutFaces = m_nodesCutFaces;
m_nodesCutFaces = nullptr;
@ -190,11 +190,12 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
auto target = PartTargetFromString(valueOfKeyInMapOrEmpty(part, "target").toUtf8().constData());
auto base = PartBaseFromString(valueOfKeyInMapOrEmpty(part, "base").toUtf8().constData());
std::map<QString, std::tuple<float, float, float>> cutFaceNodeMap;
std::map<QString, QVector2D> cutTemplateMapByName;
std::vector<QVector2D> cutTemplate;
QString cutFaceString = valueOfKeyInMapOrEmpty(part, "cutFace");
QUuid cutFaceLinkedPartId = QUuid(cutFaceString);
if (!cutFaceLinkedPartId.isNull()) {
std::map<QString, std::tuple<float, float, float>> cutFaceNodeMap;
auto findCutFaceLinkedPart = m_snapshot->parts.find(cutFaceString);
if (findCutFaceLinkedPart == m_snapshot->parts.end()) {
qDebug() << "Find cut face linked part failed:" << cutFaceString;
@ -275,7 +276,7 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
endPointNodeIdString = endpointNodes[0].first;
}
// Loop all linked nodes
std::vector<std::tuple<float, float, float>> cutFaceNodes;
std::vector<std::tuple<float, float, float, QString>> cutFaceNodes;
std::set<QString> cutFaceVisitedNodeIds;
std::function<void (const QString &)> loopNodeLink;
loopNodeLink = [&](const QString &fromNodeIdString) {
@ -285,7 +286,10 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
if (cutFaceVisitedNodeIds.find(fromNodeIdString) != cutFaceVisitedNodeIds.end())
return;
cutFaceVisitedNodeIds.insert(fromNodeIdString);
cutFaceNodes.push_back(findCutFaceNode->second);
cutFaceNodes.push_back({std::get<0>(findCutFaceNode->second),
std::get<1>(findCutFaceNode->second),
std::get<2>(findCutFaceNode->second),
fromNodeIdString});
auto findNeighbor = cutFaceNodeLinkMap.find(fromNodeIdString);
if (findNeighbor == cutFaceNodeLinkMap.end())
return;
@ -300,12 +304,20 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
loopNodeLink(endPointNodeIdString);
}
// Fetch points from linked nodes
cutFacePointsFromNodes(cutTemplate, cutFaceNodes, isRing);
std::vector<QString> cutTemplateNames;
cutFacePointsFromNodes(cutTemplate, cutFaceNodes, isRing, &cutTemplateNames);
for (size_t i = 0; i < cutTemplateNames.size(); ++i) {
cutTemplateMapByName.insert({cutTemplateNames[i], cutTemplate[i]});
}
}
}
if (cutTemplate.size() < 3) {
CutFace cutFace = CutFaceFromString(cutFaceString.toUtf8().constData());
cutTemplate = CutFaceToPoints(cutFace);
cutTemplateMapByName.clear();
for (size_t i = 0; i < cutTemplate.size(); ++i) {
cutTemplateMapByName.insert({cutFaceString + "/" + QString::number(i + 1), cutTemplate[i]});
}
}
if (chamfered)
nodemesh::chamferFace2D(&cutTemplate);
@ -494,10 +506,11 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
continue;
const QString &nodeIdString = nodeIndexToIdStringMap[node.originNodeIndex];
const nodemesh::Builder::CutFaceTransform *cutFaceTransform = builder->nodeAdjustableCutFaceTransform(builderNodeIndices[i]);
if (nullptr != cutFaceTransform) {
if (nullptr != cutFaceTransform &&
PartTarget::Model == target) {
QUuid nodeId = QUuid(nodeIdString);
m_cutFaceTransforms->insert({nodeId, *cutFaceTransform});
m_nodesCutFaces->insert({nodeId, cutFaceNodeMap});
m_nodesCutFaces->insert({nodeId, cutTemplateMapByName});
}
}
@ -993,7 +1006,7 @@ void MeshGenerator::generate()
m_outcome = new Outcome;
m_cutFaceTransforms = new std::map<QUuid, nodemesh::Builder::CutFaceTransform>;
m_nodesCutFaces = new std::map<QUuid, std::map<QString, std::tuple<float, float, float>>>;
m_nodesCutFaces = new std::map<QUuid, std::map<QString, QVector2D>>;
bool needDeleteCacheContext = false;
if (nullptr == m_cacheContext) {

View File

@ -61,7 +61,7 @@ public:
const std::set<QUuid> &generatedPreviewPartIds();
Outcome *takeOutcome();
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *takeCutFaceTransforms();
std::map<QUuid, std::map<QString, std::tuple<float, float, float>>> *takeNodesCutFaces();
std::map<QUuid, std::map<QString, QVector2D>> *takeNodesCutFaces();
void generate();
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
void setSmoothShadingThresholdAngleDegrees(float degrees);
@ -90,7 +90,7 @@ private:
bool m_cacheEnabled = false;
float m_smoothShadingThresholdAngleDegrees = 60;
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *m_cutFaceTransforms = nullptr;
std::map<QUuid, std::map<QString, std::tuple<float, float, float>>> *m_nodesCutFaces = nullptr;
std::map<QUuid, std::map<QString, QVector2D>> *m_nodesCutFaces = nullptr;
void collectParts();
bool checkIsComponentDirty(const QString &componentIdString);

View File

@ -31,6 +31,13 @@ MeshLoader::MeshLoader(const MeshLoader &mesh) :
for (int i = 0; i < mesh.m_edgeVertexCount; i++)
this->m_edgeVertices[i] = mesh.m_edgeVertices[i];
}
if (nullptr != mesh.m_toolVertices &&
mesh.m_toolVertexCount > 0) {
this->m_toolVertices = new ShaderVertex[mesh.m_toolVertexCount];
this->m_toolVertexCount = mesh.m_toolVertexCount;
for (int i = 0; i < mesh.m_toolVertexCount; i++)
this->m_toolVertices[i] = mesh.m_toolVertices[i];
}
if (nullptr != mesh.m_textureImage) {
this->m_textureImage = new QImage(*mesh.m_textureImage);
}
@ -332,3 +339,13 @@ void MeshLoader::exportAsObj(const QString &filename)
exportAsObj(&stream);
}
}
void MeshLoader::updateTool(ShaderVertex *toolVertices, int vertexNum)
{
delete[] m_toolVertices;
m_toolVertices = nullptr;
m_toolVertexCount = 0;
m_toolVertices = toolVertices;
m_toolVertexCount = vertexNum;
}

View File

@ -8,6 +8,7 @@
#include <QTextStream>
#include "outcome.h"
#include "shadervertex.h"
#include "toolmesh.h"
struct TriangulatedFace
{
@ -52,6 +53,7 @@ public:
static float m_defaultRoughness;
void exportAsObj(const QString &filename);
void exportAsObj(QTextStream *textStream);
void updateTool(ShaderVertex *toolVertices, int vertexNum);
private:
ShaderVertex *m_triangleVertices = nullptr;
int m_triangleVertexCount = 0;

View File

@ -8,21 +8,8 @@
#include "modelmeshbinder.h"
#include "ds3file.h"
ModelMeshBinder::ModelMeshBinder() :
m_mesh(nullptr),
m_newMesh(nullptr),
m_renderTriangleVertexCount(0),
m_renderEdgeVertexCount(0),
m_newMeshComing(false),
m_showWireframes(false),
m_hasTexture(false),
m_texture(nullptr),
m_hasNormalMap(false),
m_normalMap(nullptr),
m_hasMetalnessMap(false),
m_hasRoughnessMap(false),
m_hasAmbientOcclusionMap(false),
m_metalnessRoughnessAmbientOcclusionMap(nullptr)
ModelMeshBinder::ModelMeshBinder(bool toolEnabled) :
m_toolEnabled(toolEnabled)
{
}
@ -49,6 +36,8 @@ void ModelMeshBinder::initialize()
{
m_vaoTriangle.create();
m_vaoEdge.create();
if (m_toolEnabled)
m_vaoTool.create();
}
void ModelMeshBinder::paint(ModelShaderProgram *program)
@ -142,9 +131,37 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
m_vboEdge.release();
}
if (m_toolEnabled) {
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTool);
if (m_vboTool.isCreated())
m_vboTool.destroy();
m_vboTool.create();
m_vboTool.bind();
m_vboTool.allocate(m_mesh->toolVertices(), m_mesh->toolVertexCount() * sizeof(ShaderVertex));
m_renderToolVertexCount = m_mesh->toolVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
f->glEnableVertexAttribArray(3);
f->glEnableVertexAttribArray(4);
f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
m_vboTool.release();
} else {
m_renderToolVertexCount = 0;
}
} else {
m_renderTriangleVertexCount = 0;
m_renderEdgeVertexCount = 0;
m_renderToolVertexCount = 0;
}
}
}
@ -190,6 +207,18 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), m_hasAmbientOcclusionMap ? 1 : 0);
f->glDrawArrays(GL_TRIANGLES, 0, m_renderTriangleVertexCount);
}
if (m_toolEnabled) {
if (m_renderToolVertexCount > 0) {
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTool);
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
program->setUniformValue(program->textureEnabledLoc(), 0);
program->setUniformValue(program->normalMapEnabledLoc(), 0);
program->setUniformValue(program->metalnessMapEnabledLoc(), 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), 0);
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), 0);
f->glDrawArrays(GL_TRIANGLES, 0, m_renderToolVertexCount);
}
}
}
void ModelMeshBinder::cleanup()
@ -198,6 +227,10 @@ void ModelMeshBinder::cleanup()
m_vboTriangle.destroy();
if (m_vboEdge.isCreated())
m_vboEdge.destroy();
if (m_toolEnabled) {
if (m_vboTool.isCreated())
m_vboTool.destroy();
}
delete m_texture;
m_texture = nullptr;
delete m_normalMap;

View File

@ -11,7 +11,7 @@
class ModelMeshBinder
{
public:
ModelMeshBinder();
ModelMeshBinder(bool toolEnabled=false);
~ModelMeshBinder();
void updateMesh(MeshLoader *mesh);
void initialize();
@ -21,25 +21,29 @@ public:
void hideWireframes();
bool isWireframesVisible();
private:
MeshLoader *m_mesh;
MeshLoader *m_newMesh;
int m_renderTriangleVertexCount;
int m_renderEdgeVertexCount;
bool m_newMeshComing;
bool m_showWireframes;
bool m_hasTexture;
QOpenGLTexture *m_texture;
bool m_hasNormalMap;
QOpenGLTexture *m_normalMap;
bool m_hasMetalnessMap;
bool m_hasRoughnessMap;
bool m_hasAmbientOcclusionMap;
QOpenGLTexture *m_metalnessRoughnessAmbientOcclusionMap;
MeshLoader *m_mesh = nullptr;
MeshLoader *m_newMesh = nullptr;
int m_renderTriangleVertexCount = 0;
int m_renderEdgeVertexCount = 0;
int m_renderToolVertexCount = 0;
bool m_newMeshComing = false;
bool m_showWireframes = false;
bool m_hasTexture = false;
QOpenGLTexture *m_texture = nullptr;
bool m_hasNormalMap = false;
QOpenGLTexture *m_normalMap = nullptr;
bool m_hasMetalnessMap = false;
bool m_hasRoughnessMap = false;
bool m_hasAmbientOcclusionMap = false;
QOpenGLTexture *m_metalnessRoughnessAmbientOcclusionMap = nullptr;
bool m_toolEnabled = false;
private:
QOpenGLVertexArrayObject m_vaoTriangle;
QOpenGLBuffer m_vboTriangle;
QOpenGLVertexArrayObject m_vaoEdge;
QOpenGLBuffer m_vboEdge;
QOpenGLVertexArrayObject m_vaoTool;
QOpenGLBuffer m_vboTool;
QMutex m_meshMutex;
QMutex m_newMeshMutex;
};

View File

@ -3,6 +3,7 @@
#include <QCoreApplication>
#include <QGuiApplication>
#include <math.h>
#include <QVector4D>
#include "modelwidget.h"
#include "util.h"

View File

@ -7,6 +7,7 @@
#include <QMatrix4x4>
#include <QMutex>
#include <QRubberBand>
#include <QVector2D>
#include "meshloader.h"
#include "modelshaderprogram.h"
#include "modelmeshbinder.h"

View File

@ -1,17 +1,96 @@
#include "toolmesh.h"
#include "theme.h"
void ToolMesh::addNode(const QVector3D &position, float radius, const QMatrix4x4 &transform)
const std::vector<QVector3D> ToolMesh::m_predefinedPoints = {
QVector3D(1.000000, 1.000000, -1.000000),
QVector3D(1.000000, -1.000000, -1.000000),
QVector3D(1.000000, 1.000000, 1.000000),
QVector3D(1.000000, -1.000000, 1.000000),
QVector3D(-1.000000, 1.000000, -1.000000),
QVector3D(-1.000000, -1.000000, -1.000000),
QVector3D(-1.000000, 1.000000, 1.000000),
QVector3D(-1.000000, -1.000000, 1.000000),
};
const std::vector<QVector3D> ToolMesh::m_predefinedNormals = {
QVector3D(0.0000, 1.0000, 0.0000),
QVector3D(0.0000, 0.0000, 1.0000),
QVector3D(-1.0000, 0.0000, 0.0000),
QVector3D(0.0000, -1.0000, 0.0000),
QVector3D(1.0000, 0.0000, 0.0000),
QVector3D(0.0000, 0.0000, -1.0000),
};
ToolMesh::~ToolMesh()
{
m_nodes.push_back({position, radius, transform});
}
void ToolMesh::addNode(const QString &nodeId, const QVector3D &position)
{
m_nodes.insert({nodeId, {position}});
}
void ToolMesh::fillCube(std::vector<ShaderVertex> *vertices, const QVector3D &position)
{
auto addTriangle = [&](const std::vector<size_t> &indices, int normalIndex) {
for (const auto &index: indices) {
ShaderVertex vertex;
memset(&vertex, 0, sizeof(ShaderVertex));
const auto &transformedPosition = position + m_predefinedPoints[index - 1] * 0.003;
const auto &transformedNormal = m_predefinedNormals[normalIndex - 1];
vertex.posX = transformedPosition.x();
vertex.posY = transformedPosition.y();
vertex.posZ = transformedPosition.z();
vertex.normX = transformedNormal.x();
vertex.normY = transformedNormal.y();
vertex.normZ = transformedNormal.z();
vertex.colorR = Theme::green.redF();
vertex.colorG = Theme::green.greenF();
vertex.colorB = Theme::green.blueF();
vertices->push_back(vertex);
}
};
addTriangle({5, 3, 1}, 1);
addTriangle({3, 8, 4}, 2);
addTriangle({7, 6, 8}, 3);
addTriangle({2, 8, 6}, 4);
addTriangle({1, 4, 2}, 5);
addTriangle({5, 2, 6}, 6);
addTriangle({5, 7, 3}, 1);
addTriangle({3, 7, 8}, 2);
addTriangle({7, 5, 6}, 3);
addTriangle({2, 4, 8}, 4);
addTriangle({1, 3, 4}, 5);
addTriangle({5, 1, 2}, 6);
}
void ToolMesh::generate()
{
// TODO:
for (const auto &node: m_nodes) {
fillCube(&m_nodesVertices[node.first], node.second.position);
}
}
ShaderVertex *ToolMesh::takeShaderVertices(int *shaderVertexCount)
{
// TODO:
return nullptr;
int vertexCount = m_nodesVertices.size() * 12 * 3;
ShaderVertex *shaderVertices = new ShaderVertex[vertexCount];
if (nullptr != shaderVertexCount)
*shaderVertexCount = vertexCount;
int vertexIndex = 0;
for (const auto &nodeIt: m_nodesVertices) {
for (const auto &vertexIt: nodeIt.second) {
Q_ASSERT(vertexIndex < vertexCount);
ShaderVertex *dest = &shaderVertices[vertexIndex++];
*dest = vertexIt;
}
}
Q_ASSERT(vertexIndex == vertexCount);
return shaderVertices;
}

View File

@ -3,12 +3,14 @@
#include <QVector3D>
#include <QMatrix4x4>
#include <vector>
#include <map>
#include "shadervertex.h"
class ToolMesh
{
public:
void addNode(const QVector3D &position, float radius, const QMatrix4x4 &transform);
~ToolMesh();
void addNode(const QString &nodeId, const QVector3D &position);
void generate();
ShaderVertex *takeShaderVertices(int *shaderVertexCount);
@ -16,12 +18,15 @@ private:
struct Node
{
QVector3D position;
float radius;
QMatrix4x4 transform;
};
std::vector<Node> m_nodes;
ShaderVertex *m_shaderVertices = nullptr;
std::map<QString, Node> m_nodes;
std::map<QString, std::vector<ShaderVertex>> m_nodesVertices;
static const std::vector<QVector3D> m_predefinedPoints;
static const std::vector<QVector3D> m_predefinedNormals;
void fillCube(std::vector<ShaderVertex> *vertices, const QVector3D &position);
};
#endif

View File

@ -711,6 +711,8 @@ void Builder::makeCut(const QVector3D &position,
auto uFactor = u * radius;
auto vFactor = v * radius;
if (nullptr != cutFaceTransform) {
cutFaceTransform->scale = radius;
cutFaceTransform->translation = position;
cutFaceTransform->uFactor = uFactor;
cutFaceTransform->vFactor = vFactor;
}

View File

@ -15,6 +15,8 @@ class Builder
public:
struct CutFaceTransform
{
QVector3D translation;
float scale;
QMatrix4x4 rotation;
QVector3D uFactor;
QVector3D vFactor;