diff --git a/dust3d/mesh/base_normal.cc b/dust3d/mesh/base_normal.cc index fbb478a7..cc684ae8 100644 --- a/dust3d/mesh/base_normal.cc +++ b/dust3d/mesh/base_normal.cc @@ -89,7 +89,7 @@ Vector3 BaseNormal::calculateTubeBaseNormal(const std::vector &vertices size_t h = i - 1; // >15 degrees && < 165 degrees if (std::abs(Vector3::dotProduct(edgeDirections[h], edgeDirections[i])) < 0.966) - baseNormal += Vector3::crossProduct(edgeDirections[h], edgeDirections[i]); + baseNormal += Vector3::crossProduct(-edgeDirections[h], edgeDirections[i]); } if (baseNormal.isZero()) { for (size_t h = 0; h + 1 < edgeDirections.size(); ++h) { diff --git a/dust3d/mesh/mesh_generator.cc b/dust3d/mesh/mesh_generator.cc index 1736b7dd..768a062b 100644 --- a/dust3d/mesh/mesh_generator.cc +++ b/dust3d/mesh/mesh_generator.cc @@ -93,6 +93,18 @@ void MeshGenerator::chamferFace(std::vector *face) } } +void MeshGenerator::subdivideFace(std::vector *face) +{ + auto oldFace = *face; + face->resize(oldFace.size() * 2); + for (size_t i = 0, n = 0; i < oldFace.size(); ++i) { + size_t h = (i + oldFace.size() - 1) % oldFace.size(); + size_t j = (i + 1) % oldFace.size(); + (*face)[n++] = oldFace[h] * 0.125 + oldFace[i] * 0.75 + oldFace[j] * 0.125; + (*face)[n++] = (oldFace[i] + oldFace[j]) * 0.5; + } +} + bool MeshGenerator::isWatertight(const std::vector> &faces) { std::set> halfEdges; @@ -596,6 +608,8 @@ std::unique_ptr MeshGenerator::combinePartMesh(const std::st cutFaceStringToCutTemplate(cutFaceString, cutTemplate); if (chamfered) chamferFace(&cutTemplate); + if (subdived) + subdivideFace(&cutTemplate); std::string cutRotationString = String::valueOrEmpty(part, "cutRotation"); if (!cutRotationString.empty()) { diff --git a/dust3d/mesh/mesh_generator.h b/dust3d/mesh/mesh_generator.h index 6571d84d..48cd9523 100644 --- a/dust3d/mesh/mesh_generator.h +++ b/dust3d/mesh/mesh_generator.h @@ -163,6 +163,7 @@ private: bool fetchPartOrderedNodes(const std::string &partIdString, std::vector *meshNodes, bool *isCircle); static void chamferFace(std::vector *face); + static void subdivideFace(std::vector *face); static bool isWatertight(const std::vector> &faces); static void flattenLinks(const std::unordered_map &links, std::vector *array, diff --git a/dust3d/mesh/tube_mesh_builder.cc b/dust3d/mesh/tube_mesh_builder.cc index 16b9fec7..5e613370 100644 --- a/dust3d/mesh/tube_mesh_builder.cc +++ b/dust3d/mesh/tube_mesh_builder.cc @@ -20,6 +20,7 @@ * SOFTWARE. */ +#include #include #include @@ -139,6 +140,11 @@ void TubeMeshBuilder::build() }); } } + if (!m_isCircle) { + m_generatedFaces.emplace_back(cutFaceIndices.back()); + m_generatedFaces.emplace_back(cutFaceIndices.front()); + std::reverse(m_generatedFaces.back().begin(), m_generatedFaces.back().end()); + } } }