diff --git a/application/sources/component_property_widget.cc b/application/sources/component_property_widget.cc index 88718a7b..704e0e5b 100644 --- a/application/sources/component_property_widget.cc +++ b/application/sources/component_property_widget.cc @@ -164,8 +164,19 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document, emit groupOperationAdded(); }); + QCheckBox *roundEndStateBox = new QCheckBox(); + Theme::initCheckbox(roundEndStateBox); + roundEndStateBox->setText(tr("Round end")); + roundEndStateBox->setChecked(m_part->rounded); + + connect(roundEndStateBox, &QCheckBox::stateChanged, this, [=]() { + emit setPartRoundState(m_partId, roundEndStateBox->isChecked()); + emit groupOperationAdded(); + }); + QHBoxLayout *optionsLayout = new QHBoxLayout; optionsLayout->addStretch(); + optionsLayout->addWidget(roundEndStateBox); optionsLayout->addWidget(chamferStateBox); optionsLayout->addWidget(subdivStateBox); @@ -194,6 +205,7 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document, connect(this, &ComponentPropertyWidget::setPartCutRotation, m_document, &Document::setPartCutRotation); connect(this, &ComponentPropertyWidget::setPartSubdivState, m_document, &Document::setPartSubdivState); connect(this, &ComponentPropertyWidget::setPartChamferState, m_document, &Document::setPartChamferState); + connect(this, &ComponentPropertyWidget::setPartRoundState, m_document, &Document::setPartRoundState); connect(this, &ComponentPropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot); setLayout(mainLayout); diff --git a/application/sources/component_property_widget.h b/application/sources/component_property_widget.h index 846f76dd..078c4d8f 100644 --- a/application/sources/component_property_widget.h +++ b/application/sources/component_property_widget.h @@ -19,6 +19,7 @@ signals: void setPartDeformUnified(const dust3d::Uuid &partId, bool unified); void setPartSubdivState(const dust3d::Uuid &partId, bool subdived); void setPartChamferState(const dust3d::Uuid &partId, bool chamfered); + void setPartRoundState(const dust3d::Uuid &partId, bool rounded); void setPartCutRotation(const dust3d::Uuid &partId, float cutRotation); void groupOperationAdded(); public: diff --git a/dust3d/mesh/mesh_generator.cc b/dust3d/mesh/mesh_generator.cc index dfc99de8..38f9ca7a 100644 --- a/dust3d/mesh/mesh_generator.cc +++ b/dust3d/mesh/mesh_generator.cc @@ -664,6 +664,7 @@ std::unique_ptr MeshGenerator::combinePartMesh(const std::st buildParameters.deformUnified = deformUnified; buildParameters.baseNormalRotation = cutRotation * Math::Pi; buildParameters.cutFace = cutTemplate; + buildParameters.frontEndRounded = buildParameters.backEndRounded = rounded; auto tubeMeshBuilder = std::make_unique(buildParameters, std::move(meshNodes), isCircle); tubeMeshBuilder->build(); diff --git a/dust3d/mesh/tube_mesh_builder.cc b/dust3d/mesh/tube_mesh_builder.cc index 94888283..0df02322 100644 --- a/dust3d/mesh/tube_mesh_builder.cc +++ b/dust3d/mesh/tube_mesh_builder.cc @@ -49,8 +49,33 @@ const std::vector> &TubeMeshBuilder::generatedFaces() return m_generatedFaces; } +void TubeMeshBuilder::applyRoundEnd() +{ + if (m_isCircle) + return; + + if (m_nodes.size() <= 1) + return; + + if (m_buildParameters.frontEndRounded) { + auto newNode = m_nodes.front(); + newNode.radius *= 0.5; + newNode.origin += (m_nodes[0].origin - m_nodes[1].origin).normalized() * newNode.radius; + m_nodes.insert(m_nodes.begin(), newNode); + } + + if (m_buildParameters.backEndRounded) { + auto newNode = m_nodes.back(); + newNode.radius *= 0.5; + newNode.origin += (m_nodes[m_nodes.size() - 1].origin - m_nodes[m_nodes.size() - 2].origin).normalized() * newNode.radius; + m_nodes.emplace_back(newNode); + } +} + void TubeMeshBuilder::preprocessNodes() { + applyRoundEnd(); + // TODO: Interpolate... } diff --git a/dust3d/mesh/tube_mesh_builder.h b/dust3d/mesh/tube_mesh_builder.h index fd0ec653..20d6c5a1 100644 --- a/dust3d/mesh/tube_mesh_builder.h +++ b/dust3d/mesh/tube_mesh_builder.h @@ -41,6 +41,8 @@ public: double deformWidth = 1.0; bool deformUnified = false; double baseNormalRotation = 0.0; + bool frontEndRounded = false; + bool backEndRounded = false; }; TubeMeshBuilder(const BuildParameters &buildParameters, std::vector &&nodes, bool isCircle); @@ -64,6 +66,7 @@ private: std::vector buildCutFaceVertices(const Vector3 &origin, double radius, const Vector3 &forwardDirection); + void applyRoundEnd(); }; };