From 91e64608159e814d3e385dc0ca82ff6a68daf78f Mon Sep 17 00:00:00 2001 From: Jeremy HU Date: Tue, 11 Oct 2022 08:38:03 +1100 Subject: [PATCH] Group base normal calculations to separate class --- application/application.pro | 4 ++ dust3d/mesh/base_normal.cc | 105 ++++++++++++++++++++++++++++++ dust3d/mesh/base_normal.h | 60 +++++++++++++++++ dust3d/mesh/rope_mesh.cc | 82 +---------------------- dust3d/mesh/rope_mesh.h | 21 ------ dust3d/mesh/stitch_mesh_builder.h | 2 +- dust3d/mesh/tube_mesh_builder.cc | 50 ++++++++++++++ dust3d/mesh/tube_mesh_builder.h | 52 +++++++++++++++ 8 files changed, 275 insertions(+), 101 deletions(-) create mode 100644 dust3d/mesh/base_normal.cc create mode 100644 dust3d/mesh/base_normal.h create mode 100644 dust3d/mesh/tube_mesh_builder.cc create mode 100644 dust3d/mesh/tube_mesh_builder.h diff --git a/application/application.pro b/application/application.pro index d0071253..04a51542 100644 --- a/application/application.pro +++ b/application/application.pro @@ -261,6 +261,8 @@ SOURCES += ../dust3d/base/vector3.cc HEADERS += ../dust3d/base/vector2.h HEADERS += ../dust3d/base/uuid.h SOURCES += ../dust3d/base/uuid.cc +HEADERS += ../dust3d/mesh/base_normal.h +SOURCES += ../dust3d/mesh/base_normal.cc HEADERS += ../dust3d/mesh/box_mesh.h SOURCES += ../dust3d/mesh/box_mesh.cc HEADERS += ../dust3d/mesh/centripetal_catmull_rom_spline.h @@ -303,6 +305,8 @@ HEADERS += ../dust3d/mesh/triangulate.h SOURCES += ../dust3d/mesh/triangulate.cc HEADERS += ../dust3d/mesh/trim_vertices.h SOURCES += ../dust3d/mesh/trim_vertices.cc +HEADERS += ../dust3d/mesh/tube_mesh_builder.h +SOURCES += ../dust3d/mesh/tube_mesh_builder.cc HEADERS += ../dust3d/mesh/weld_vertices.h SOURCES += ../dust3d/mesh/weld_vertices.cc HEADERS += ../dust3d/util/obj.h diff --git a/dust3d/mesh/base_normal.cc b/dust3d/mesh/base_normal.cc new file mode 100644 index 00000000..fbb478a7 --- /dev/null +++ b/dust3d/mesh/base_normal.cc @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016-2022 Jeremy HU . All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +namespace dust3d +{ + +std::pair BaseNormal::findNearestAxis(const Vector3 &direction) +{ + float maxDot = -1; + size_t nearAxisIndex = 0; + int positive = 1; + for (size_t i = 0; i < 3; ++i) { + const auto axis = axisDirection(i); + auto dot = Vector3::dotProduct(axis, direction); + auto positiveDot = std::abs(dot); + if (positiveDot >= maxDot) { + if (dot < 0) + positive = -1; + maxDot = positiveDot; + nearAxisIndex = i; + } + } + return {nearAxisIndex, positive}; +} + +std::vector BaseNormal::calculateCircleVertices(double radius, + size_t points, + const Vector3 &aroundAxis, + const Vector3 &startDirection, + const Vector3 &origin) +{ + constexpr auto roundAngle = 2.0 * Math::Pi; + auto stepAngle = roundAngle / points; + std::vector circlePoints; + circlePoints.reserve(points); + for (double angle = stepAngle * -0.5; + circlePoints.size() < points; + angle += stepAngle) { + circlePoints.push_back(origin + startDirection.rotated(aroundAxis, angle) * radius); + } + return circlePoints; +} + +Vector3 BaseNormal::calculateCircleBaseNormal(const std::vector &vertices) +{ + std::vector edgeDirections(vertices.size()); + for (size_t i = 0; i < edgeDirections.size(); ++i) { + size_t j = (i + 1) % edgeDirections.size(); + edgeDirections[i] = (vertices[j] - vertices[i]).normalized(); + } + Vector3 baseNormal; + for (size_t i = 0; i < edgeDirections.size(); ++i) { + size_t j = (i + 1) % edgeDirections.size(); + baseNormal += Vector3::crossProduct(-edgeDirections[i], edgeDirections[j]); + } + return baseNormal.normalized(); +} + +Vector3 BaseNormal::calculateTubeBaseNormal(const std::vector &vertices) +{ + std::vector edgeDirections(vertices.size()); + for (size_t i = 1; i < edgeDirections.size(); ++i) { + size_t h = i - 1; + edgeDirections[h] = (vertices[i] - vertices[h]).normalized(); + } + Vector3 baseNormal; + for (size_t i = 1; i < edgeDirections.size(); ++i) { + 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]); + } + if (baseNormal.isZero()) { + for (size_t h = 0; h + 1 < edgeDirections.size(); ++h) { + const auto §ionNormal = edgeDirections[h]; + auto axis = BaseNormal::findNearestAxis(sectionNormal); + baseNormal += axis.second * + Vector3::crossProduct(sectionNormal, BaseNormal::nextAxisDirection(axis.first)).normalized(); + } + } + return baseNormal.normalized(); +} + +} diff --git a/dust3d/mesh/base_normal.h b/dust3d/mesh/base_normal.h new file mode 100644 index 00000000..5d72c897 --- /dev/null +++ b/dust3d/mesh/base_normal.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2022 Jeremy HU . All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DUST3D_MESH_BASE_NORMAL_H_ +#define DUST3D_MESH_BASE_NORMAL_H_ + +#include +#include + +namespace dust3d +{ + +class BaseNormal +{ +public: + static std::pair findNearestAxis(const Vector3 &direction); + static inline const Vector3 &axisDirection(size_t index) + { + static const std::vector axisList = { + Vector3 {1, 0, 0}, + Vector3 {0, 1, 0}, + Vector3 {0, 0, 1}, + }; + return axisList[index]; + } + static inline const Vector3 &nextAxisDirection(size_t index) + { + return axisDirection((index + 1) % 3); + } + static std::vector calculateCircleVertices(double radius, + size_t points, + const Vector3 &aroundAxis=Vector3(0.0, 0.0, 1.0), + const Vector3 &startDirection=Vector3(0.0, 1.0, 0.0), + const Vector3 &origin=Vector3(0.0, 0.0, 0.0)); + static Vector3 calculateCircleBaseNormal(const std::vector &vertices); + static Vector3 calculateTubeBaseNormal(const std::vector &vertices); +}; + +} + +#endif diff --git a/dust3d/mesh/rope_mesh.cc b/dust3d/mesh/rope_mesh.cc index 6c2f7e9e..12dd3742 100644 --- a/dust3d/mesh/rope_mesh.cc +++ b/dust3d/mesh/rope_mesh.cc @@ -22,6 +22,7 @@ #include #include +#include #include namespace dust3d @@ -42,96 +43,19 @@ const std::vector> &RopeMesh::resultTriangles() return m_resultTriangles; } -std::pair RopeMesh::findNearestAxis(const Vector3 &direction) -{ - float maxDot = -1; - size_t nearAxisIndex = 0; - int positive = 1; - for (size_t i = 0; i < 3; ++i) { - const auto axis = axisDirection(i); - auto dot = Vector3::dotProduct(axis, direction); - auto positiveDot = std::abs(dot); - if (positiveDot >= maxDot) { - if (dot < 0) - positive = -1; - maxDot = positiveDot; - nearAxisIndex = i; - } - } - return {nearAxisIndex, positive}; -} - -std::vector RopeMesh::calculateCircleVertices(double radius, - size_t points, - const Vector3 &aroundAxis, - const Vector3 &startDirection, - const Vector3 &origin) -{ - constexpr auto roundAngle = 2.0 * Math::Pi; - auto stepAngle = roundAngle / points; - std::vector circlePoints; - circlePoints.reserve(points); - for (double angle = stepAngle * -0.5; - circlePoints.size() < points; - angle += stepAngle) { - circlePoints.push_back(origin + startDirection.rotated(aroundAxis, angle) * radius); - } - return circlePoints; -} - -Vector3 RopeMesh::calculateCircleBaseNormal(const std::vector &vertices) -{ - std::vector edgeDirections(vertices.size()); - for (size_t i = 0; i < edgeDirections.size(); ++i) { - size_t j = (i + 1) % edgeDirections.size(); - edgeDirections[i] = (vertices[j] - vertices[i]).normalized(); - } - Vector3 baseNormal; - for (size_t i = 0; i < edgeDirections.size(); ++i) { - size_t j = (i + 1) % edgeDirections.size(); - baseNormal += Vector3::crossProduct(-edgeDirections[i], edgeDirections[j]); - } - return baseNormal.normalized(); -} - -Vector3 RopeMesh::calculateTubeBaseNormal(const std::vector &vertices) -{ - std::vector edgeDirections(vertices.size()); - for (size_t i = 1; i < edgeDirections.size(); ++i) { - size_t h = i - 1; - edgeDirections[h] = (vertices[i] - vertices[h]).normalized(); - } - Vector3 baseNormal; - for (size_t i = 1; i < edgeDirections.size(); ++i) { - 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]); - } - if (baseNormal.isZero()) { - for (size_t h = 0; h + 1 < edgeDirections.size(); ++h) { - const auto §ionNormal = edgeDirections[h]; - auto axis = RopeMesh::findNearestAxis(sectionNormal); - baseNormal += axis.second * - Vector3::crossProduct(sectionNormal, RopeMesh::nextAxisDirection(axis.first)).normalized(); - } - } - return baseNormal.normalized(); -} - void RopeMesh::addRope(const std::vector &positions, bool isCircle) { if (positions.size() < 2) { dust3dDebug << "Expected at least 2 nodes, current:" << positions.size(); return; } - Vector3 baseNormal = isCircle ? calculateCircleBaseNormal(positions) : calculateTubeBaseNormal(positions); + Vector3 baseNormal = isCircle ? BaseNormal::calculateCircleBaseNormal(positions) : BaseNormal::calculateTubeBaseNormal(positions); std::vector> circles; circles.reserve(positions.size()); Vector3 forwardDirection = (positions[1] - positions[0]).normalized(); for (size_t i = isCircle ? 0 : 1; i < positions.size(); ++i) { size_t j = (i + 1) % positions.size(); - auto circlePositions = calculateCircleVertices(m_buildParameters.defaultRadius, + auto circlePositions = BaseNormal::calculateCircleVertices(m_buildParameters.defaultRadius, m_buildParameters.sectionSegments, forwardDirection, baseNormal, diff --git a/dust3d/mesh/rope_mesh.h b/dust3d/mesh/rope_mesh.h index bc038e53..a264bc18 100644 --- a/dust3d/mesh/rope_mesh.h +++ b/dust3d/mesh/rope_mesh.h @@ -46,27 +46,6 @@ private: std::vector m_resultVertices; std::vector> m_resultTriangles; BuildParameters m_buildParameters; - static std::pair findNearestAxis(const Vector3 &direction); - static inline const Vector3 &axisDirection(size_t index) - { - static const std::vector axisList = { - Vector3 {1, 0, 0}, - Vector3 {0, 1, 0}, - Vector3 {0, 0, 1}, - }; - return axisList[index]; - } - static inline const Vector3 &nextAxisDirection(size_t index) - { - return axisDirection((index + 1) % 3); - } - static std::vector calculateCircleVertices(double radius, - size_t points, - const Vector3 &aroundAxis=Vector3(0.0, 0.0, 1.0), - const Vector3 &startDirection=Vector3(0.0, 1.0, 0.0), - const Vector3 &origin=Vector3(0.0, 0.0, 0.0)); - static Vector3 calculateCircleBaseNormal(const std::vector &vertices); - static Vector3 calculateTubeBaseNormal(const std::vector &vertices); }; }; diff --git a/dust3d/mesh/stitch_mesh_builder.h b/dust3d/mesh/stitch_mesh_builder.h index a51133eb..ebfc8f9a 100644 --- a/dust3d/mesh/stitch_mesh_builder.h +++ b/dust3d/mesh/stitch_mesh_builder.h @@ -64,7 +64,7 @@ private: std::vector m_generatedVertices; std::vector> m_generatedFaces; std::vector m_generatedNormals; - size_t m_targetSegments = 15; + size_t m_targetSegments = 0; void interpolateSplinesToHaveEqualSizeOfNodesExceptClosingSplines(); std::vector> convertSplinesToStitchingPoints(const std::vector &splines); diff --git a/dust3d/mesh/tube_mesh_builder.cc b/dust3d/mesh/tube_mesh_builder.cc new file mode 100644 index 00000000..875e8a3a --- /dev/null +++ b/dust3d/mesh/tube_mesh_builder.cc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2022 Jeremy HU . All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +namespace dust3d +{ + +TubeMeshBuilder::TubeMeshBuilder(std::vector &&nodes, bool isCircle): + m_nodes(std::move(nodes)), + m_isCircle(isCircle) +{ +} + +void TubeMeshBuilder::preprocessNodes() +{ + // TODO: +} + +void TubeMeshBuilder::build() +{ + preprocessNodes(); + + if (m_nodes.empty()) + return; + + + // TODO: +} + +} diff --git a/dust3d/mesh/tube_mesh_builder.h b/dust3d/mesh/tube_mesh_builder.h new file mode 100644 index 00000000..a582d00f --- /dev/null +++ b/dust3d/mesh/tube_mesh_builder.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016-2022 Jeremy HU . All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DUST3D_MESH_TUBE_MESH_BUILDER_H_ +#define DUST3D_MESH_TUBE_MESH_BUILDER_H_ + +#include +#include + +namespace dust3d +{ + +class TubeMeshBuilder +{ +public: + struct Node + { + Vector3 origin; + double radius; + Uuid sourceId; + }; + + TubeMeshBuilder(std::vector &&nodes, bool isCircle); + void build(); +private: + std::vector m_nodes; + bool m_isCircle = false; + void preprocessNodes(); +}; + +}; + +#endif