Group base normal calculations to separate class
parent
5d5a1c04bd
commit
91e6460815
|
@ -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
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Jeremy HU <jeremy-at-dust3d dot org>. 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 <dust3d/mesh/base_normal.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
std::pair<size_t, int> 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<Vector3> 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<Vector3> 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<Vector3> &vertices)
|
||||
{
|
||||
std::vector<Vector3> 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<Vector3> &vertices)
|
||||
{
|
||||
std::vector<Vector3> 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Jeremy HU <jeremy-at-dust3d dot org>. 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 <vector>
|
||||
#include <dust3d/base/vector3.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
class BaseNormal
|
||||
{
|
||||
public:
|
||||
static std::pair<size_t, int> findNearestAxis(const Vector3 &direction);
|
||||
static inline const Vector3 &axisDirection(size_t index)
|
||||
{
|
||||
static const std::vector<Vector3> 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<Vector3> 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<Vector3> &vertices);
|
||||
static Vector3 calculateTubeBaseNormal(const std::vector<Vector3> &vertices);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <dust3d/base/debug.h>
|
||||
#include <dust3d/base/math.h>
|
||||
#include <dust3d/mesh/base_normal.h>
|
||||
#include <dust3d/mesh/rope_mesh.h>
|
||||
|
||||
namespace dust3d
|
||||
|
@ -42,96 +43,19 @@ const std::vector<std::vector<size_t>> &RopeMesh::resultTriangles()
|
|||
return m_resultTriangles;
|
||||
}
|
||||
|
||||
std::pair<size_t, int> 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<Vector3> 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<Vector3> 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<Vector3> &vertices)
|
||||
{
|
||||
std::vector<Vector3> 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<Vector3> &vertices)
|
||||
{
|
||||
std::vector<Vector3> 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<Vector3> &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<std::vector<size_t>> 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,
|
||||
|
|
|
@ -46,27 +46,6 @@ private:
|
|||
std::vector<Vector3> m_resultVertices;
|
||||
std::vector<std::vector<size_t>> m_resultTriangles;
|
||||
BuildParameters m_buildParameters;
|
||||
static std::pair<size_t, int> findNearestAxis(const Vector3 &direction);
|
||||
static inline const Vector3 &axisDirection(size_t index)
|
||||
{
|
||||
static const std::vector<Vector3> 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<Vector3> 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<Vector3> &vertices);
|
||||
static Vector3 calculateTubeBaseNormal(const std::vector<Vector3> &vertices);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ private:
|
|||
std::vector<Vector3> m_generatedVertices;
|
||||
std::vector<std::vector<size_t>> m_generatedFaces;
|
||||
std::vector<Vector3> m_generatedNormals;
|
||||
size_t m_targetSegments = 15;
|
||||
size_t m_targetSegments = 0;
|
||||
|
||||
void interpolateSplinesToHaveEqualSizeOfNodesExceptClosingSplines();
|
||||
std::vector<std::vector<StitchingPoint>> convertSplinesToStitchingPoints(const std::vector<Spline> &splines);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Jeremy HU <jeremy-at-dust3d dot org>. 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 <dust3d/mesh/tube_mesh_builder.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
TubeMeshBuilder::TubeMeshBuilder(std::vector<Node> &&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:
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Jeremy HU <jeremy-at-dust3d dot org>. 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 <dust3d/base/uuid.h>
|
||||
#include <dust3d/base/vector3.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
class TubeMeshBuilder
|
||||
{
|
||||
public:
|
||||
struct Node
|
||||
{
|
||||
Vector3 origin;
|
||||
double radius;
|
||||
Uuid sourceId;
|
||||
};
|
||||
|
||||
TubeMeshBuilder(std::vector<Node> &&nodes, bool isCircle);
|
||||
void build();
|
||||
private:
|
||||
std::vector<Node> m_nodes;
|
||||
bool m_isCircle = false;
|
||||
void preprocessNodes();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue