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); 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 (isRing) {
if (nodes.size() < 3) if (nodes.size() < 3)
@ -80,6 +81,11 @@ void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<st
for (const auto &it: nodes) { for (const auto &it: nodes) {
points.push_back(QVector2D(std::get<1>(it), std::get<2>(it))); 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); normalizeCutFacePoints(&points);
return; return;
} }
@ -117,8 +123,18 @@ void cutFacePointsFromNodes(std::vector<QVector2D> &points, const std::vector<st
for (const auto &it: cutPoints) { for (const auto &it: cutPoints) {
points.push_back(it.first); 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) { for (auto it = cutPoints.rbegin(); it != cutPoints.rend(); ++it) {
points.push_back(it->second); 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); normalizeCutFacePoints(&points);
} }

View File

@ -97,6 +97,7 @@ std::vector<QVector2D> CutFaceToPoints(CutFace cutFace) \
} }
void normalizeCutFacePoints(std::vector<QVector2D> *points); 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 #endif

View File

@ -35,6 +35,8 @@ Document::Document() :
m_isResultMeshObsolete(false), m_isResultMeshObsolete(false),
m_meshGenerator(nullptr), m_meshGenerator(nullptr),
m_resultMesh(nullptr), m_resultMesh(nullptr),
m_resultMeshCutFaceTransforms(nullptr),
m_resultMeshNodesCutFaces(nullptr),
m_isMeshGenerationSucceed(true), m_isMeshGenerationSucceed(true),
m_batchChangeRefCount(0), m_batchChangeRefCount(0),
m_currentOutcome(nullptr), m_currentOutcome(nullptr),
@ -80,6 +82,8 @@ void Document::applyPreferenceFlatShadingChange()
Document::~Document() Document::~Document()
{ {
delete m_resultMesh; delete m_resultMesh;
delete m_resultMeshCutFaceTransforms;
delete m_resultMeshNodesCutFaces;
delete m_postProcessedOutcome; delete m_postProcessedOutcome;
delete textureGuideImage; delete textureGuideImage;
delete textureImage; delete textureImage;
@ -1516,6 +1520,14 @@ void Document::meshReady()
delete m_resultMesh; delete m_resultMesh;
m_resultMesh = 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; m_isMeshGenerationSucceed = isSucceed;
delete m_currentOutcome; 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 bool Document::isPostProcessResultObsolete() const
{ {
return m_isPostProcessResultObsolete; return m_isPostProcessResultObsolete;
@ -1668,6 +1710,8 @@ void Document::textureReady()
delete m_resultTextureMesh; delete m_resultTextureMesh;
m_resultTextureMesh = m_textureGenerator->takeResultMesh(); m_resultTextureMesh = m_textureGenerator->takeResultMesh();
//addToolToMesh(m_resultTextureMesh);
m_textureImageUpdateVersion++; m_textureImageUpdateVersion++;
delete m_textureGenerator; delete m_textureGenerator;

View File

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

View File

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

View File

@ -61,7 +61,7 @@ public:
const std::set<QUuid> &generatedPreviewPartIds(); const std::set<QUuid> &generatedPreviewPartIds();
Outcome *takeOutcome(); Outcome *takeOutcome();
std::map<QUuid, nodemesh::Builder::CutFaceTransform> *takeCutFaceTransforms(); 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 generate();
void setGeneratedCacheContext(GeneratedCacheContext *cacheContext); void setGeneratedCacheContext(GeneratedCacheContext *cacheContext);
void setSmoothShadingThresholdAngleDegrees(float degrees); void setSmoothShadingThresholdAngleDegrees(float degrees);
@ -90,7 +90,7 @@ private:
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; 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(); void collectParts();
bool checkIsComponentDirty(const QString &componentIdString); 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++) for (int i = 0; i < mesh.m_edgeVertexCount; i++)
this->m_edgeVertices[i] = mesh.m_edgeVertices[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) { if (nullptr != mesh.m_textureImage) {
this->m_textureImage = new QImage(*mesh.m_textureImage); this->m_textureImage = new QImage(*mesh.m_textureImage);
} }
@ -332,3 +339,13 @@ void MeshLoader::exportAsObj(const QString &filename)
exportAsObj(&stream); 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 <QTextStream>
#include "outcome.h" #include "outcome.h"
#include "shadervertex.h" #include "shadervertex.h"
#include "toolmesh.h"
struct TriangulatedFace struct TriangulatedFace
{ {
@ -52,6 +53,7 @@ public:
static float m_defaultRoughness; static float m_defaultRoughness;
void exportAsObj(const QString &filename); void exportAsObj(const QString &filename);
void exportAsObj(QTextStream *textStream); void exportAsObj(QTextStream *textStream);
void updateTool(ShaderVertex *toolVertices, int vertexNum);
private: private:
ShaderVertex *m_triangleVertices = nullptr; ShaderVertex *m_triangleVertices = nullptr;
int m_triangleVertexCount = 0; int m_triangleVertexCount = 0;

View File

@ -8,21 +8,8 @@
#include "modelmeshbinder.h" #include "modelmeshbinder.h"
#include "ds3file.h" #include "ds3file.h"
ModelMeshBinder::ModelMeshBinder() : ModelMeshBinder::ModelMeshBinder(bool toolEnabled) :
m_mesh(nullptr), m_toolEnabled(toolEnabled)
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)
{ {
} }
@ -49,6 +36,8 @@ void ModelMeshBinder::initialize()
{ {
m_vaoTriangle.create(); m_vaoTriangle.create();
m_vaoEdge.create(); m_vaoEdge.create();
if (m_toolEnabled)
m_vaoTool.create();
} }
void ModelMeshBinder::paint(ModelShaderProgram *program) 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))); f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
m_vboEdge.release(); 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 { } else {
m_renderTriangleVertexCount = 0; m_renderTriangleVertexCount = 0;
m_renderEdgeVertexCount = 0; m_renderEdgeVertexCount = 0;
m_renderToolVertexCount = 0;
} }
} }
} }
@ -190,6 +207,18 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), m_hasAmbientOcclusionMap ? 1 : 0); program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), m_hasAmbientOcclusionMap ? 1 : 0);
f->glDrawArrays(GL_TRIANGLES, 0, m_renderTriangleVertexCount); 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() void ModelMeshBinder::cleanup()
@ -198,6 +227,10 @@ void ModelMeshBinder::cleanup()
m_vboTriangle.destroy(); m_vboTriangle.destroy();
if (m_vboEdge.isCreated()) if (m_vboEdge.isCreated())
m_vboEdge.destroy(); m_vboEdge.destroy();
if (m_toolEnabled) {
if (m_vboTool.isCreated())
m_vboTool.destroy();
}
delete m_texture; delete m_texture;
m_texture = nullptr; m_texture = nullptr;
delete m_normalMap; delete m_normalMap;

View File

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

View File

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

View File

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

View File

@ -1,17 +1,96 @@
#include "toolmesh.h" #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() void ToolMesh::generate()
{ {
// TODO: for (const auto &node: m_nodes) {
fillCube(&m_nodesVertices[node.first], node.second.position);
}
} }
ShaderVertex *ToolMesh::takeShaderVertices(int *shaderVertexCount) ShaderVertex *ToolMesh::takeShaderVertices(int *shaderVertexCount)
{ {
// TODO: int vertexCount = m_nodesVertices.size() * 12 * 3;
return nullptr; 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 <QVector3D>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <vector> #include <vector>
#include <map>
#include "shadervertex.h" #include "shadervertex.h"
class ToolMesh class ToolMesh
{ {
public: public:
void addNode(const QVector3D &position, float radius, const QMatrix4x4 &transform); ~ToolMesh();
void addNode(const QString &nodeId, const QVector3D &position);
void generate(); void generate();
ShaderVertex *takeShaderVertices(int *shaderVertexCount); ShaderVertex *takeShaderVertices(int *shaderVertexCount);
@ -16,12 +18,15 @@ private:
struct Node struct Node
{ {
QVector3D position; QVector3D position;
float radius;
QMatrix4x4 transform;
}; };
std::vector<Node> m_nodes; std::map<QString, Node> m_nodes;
ShaderVertex *m_shaderVertices = nullptr; 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 #endif

View File

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

View File

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