Prepare for cut face offset modifier
parent
820aa90406
commit
eb91a8a16c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue