Implement rope mesh builder
parent
78893729b4
commit
5b06f64fdd
|
@ -287,6 +287,8 @@ HEADERS += ../dust3d/mesh/resolve_triangle_source_node.h
|
|||
SOURCES += ../dust3d/mesh/resolve_triangle_source_node.cc
|
||||
HEADERS += ../dust3d/mesh/resolve_triangle_tangent.h
|
||||
SOURCES += ../dust3d/mesh/resolve_triangle_tangent.cc
|
||||
HEADERS += ../dust3d/mesh/rope_mesh.h
|
||||
SOURCES += ../dust3d/mesh/rope_mesh.cc
|
||||
HEADERS += ../dust3d/mesh/smooth_normal.h
|
||||
SOURCES += ../dust3d/mesh/smooth_normal.cc
|
||||
HEADERS += ../dust3d/mesh/stitch_mesh_builder.h
|
||||
|
|
|
@ -64,7 +64,8 @@ void MeshGenerator::process()
|
|||
previewTriangleVertexNormals,
|
||||
it->second.color,
|
||||
it->second.metalness,
|
||||
it->second.roughness);
|
||||
it->second.roughness,
|
||||
it->second.vertexProperties.empty() ? nullptr : &it->second.vertexProperties);
|
||||
}
|
||||
|
||||
if (nullptr != m_object)
|
||||
|
|
|
@ -68,11 +68,13 @@ ModelMesh::ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum) :
|
|||
{
|
||||
}
|
||||
|
||||
ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
|
||||
ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices,
|
||||
const std::vector<std::vector<size_t>> &triangles,
|
||||
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
|
||||
const dust3d::Color &color,
|
||||
float metalness,
|
||||
float roughness)
|
||||
float roughness,
|
||||
const std::vector<std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/>> *vertexProperties)
|
||||
{
|
||||
m_triangleVertexCount = (int)triangles.size() * 3;
|
||||
m_triangleVertices = new ModelOpenGLVertex[m_triangleVertexCount];
|
||||
|
@ -83,10 +85,6 @@ ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::ve
|
|||
const dust3d::Vector3 *srcVert = &vertices[vertexIndex];
|
||||
const dust3d::Vector3 *srcNormal = &(triangleVertexNormals)[i][j];
|
||||
ModelOpenGLVertex *dest = &m_triangleVertices[destIndex];
|
||||
dest->colorR = color.r();
|
||||
dest->colorG = color.g();
|
||||
dest->colorB = color.b();
|
||||
dest->alpha = color.alpha();
|
||||
dest->posX = srcVert->x();
|
||||
dest->posY = srcVert->y();
|
||||
dest->posZ = srcVert->z();
|
||||
|
@ -95,8 +93,22 @@ ModelMesh::ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::ve
|
|||
dest->normX = srcNormal->x();
|
||||
dest->normY = srcNormal->y();
|
||||
dest->normZ = srcNormal->z();
|
||||
dest->metalness = metalness;
|
||||
dest->roughness = roughness;
|
||||
if (nullptr == vertexProperties) {
|
||||
dest->colorR = color.r();
|
||||
dest->colorG = color.g();
|
||||
dest->colorB = color.b();
|
||||
dest->alpha = color.alpha();
|
||||
dest->metalness = metalness;
|
||||
dest->roughness = roughness;
|
||||
} else {
|
||||
const auto &property = (*vertexProperties)[vertexIndex];
|
||||
dest->colorR = std::get<0>(property).r();
|
||||
dest->colorG = std::get<0>(property).g();
|
||||
dest->colorB = std::get<0>(property).b();
|
||||
dest->alpha = std::get<0>(property).alpha();
|
||||
dest->metalness = std::get<1>(property);
|
||||
dest->roughness = std::get<2>(property);
|
||||
}
|
||||
dest->tangentX = 0;
|
||||
dest->tangentY = 0;
|
||||
dest->tangentZ = 0;
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
class ModelMesh
|
||||
{
|
||||
public:
|
||||
ModelMesh(const std::vector<dust3d::Vector3> &vertices, const std::vector<std::vector<size_t>> &triangles,
|
||||
ModelMesh(const std::vector<dust3d::Vector3> &vertices,
|
||||
const std::vector<std::vector<size_t>> &triangles,
|
||||
const std::vector<std::vector<dust3d::Vector3>> &triangleVertexNormals,
|
||||
const dust3d::Color &color=dust3d::Color::createWhite(),
|
||||
float metalness=0.0,
|
||||
float roughness=0.0);
|
||||
float roughness=0.0,
|
||||
const std::vector<std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/>> *vertexProperties=nullptr);
|
||||
ModelMesh(dust3d::Object &object);
|
||||
ModelMesh(ModelOpenGLVertex *triangleVertices, int vertexNum);
|
||||
ModelMesh(const ModelMesh &mesh);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace dust3d
|
|||
namespace Math
|
||||
{
|
||||
|
||||
const double Pi = 3.14159265358979323846;
|
||||
constexpr double Pi = 3.14159265358979323846;
|
||||
|
||||
inline bool isZero(double number)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
namespace dust3d
|
||||
{
|
||||
|
||||
Vector3 Vector3::rotated(const Vector3 &unitAxis, double angle)
|
||||
Vector3 Vector3::rotated(const Vector3 &unitAxis, double angle) const
|
||||
{
|
||||
double c = std::cos(angle);
|
||||
double s = std::sin(angle);
|
||||
|
|
|
@ -334,7 +334,7 @@ public:
|
|||
return std::acos(dotProduct(first.normalized(), second.normalized()));
|
||||
}
|
||||
|
||||
Vector3 rotated(const Vector3 &unitAxis, double angle);
|
||||
Vector3 rotated(const Vector3 &unitAxis, double angle) const;
|
||||
|
||||
private:
|
||||
double m_data[3] = {0.0};
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <dust3d/base/part_base.h>
|
||||
#include <dust3d/base/snapshot_xml.h>
|
||||
#include <dust3d/base/cut_face.h>
|
||||
#include <dust3d/mesh/rope_mesh.h>
|
||||
#include <dust3d/mesh/stitch_mesh_builder.h>
|
||||
#include <dust3d/mesh/stroke_mesh_builder.h>
|
||||
#include <dust3d/mesh/stroke_modifier.h>
|
||||
|
@ -411,11 +412,16 @@ void MeshGenerator::flattenLinks(const std::unordered_map<size_t, size_t> &links
|
|||
}
|
||||
|
||||
std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combineStitchingMesh(const std::vector<std::string> &partIdStrings,
|
||||
const std::vector<std::string> &componentIdStrings,
|
||||
GeneratedComponent &componentCache)
|
||||
{
|
||||
std::vector<StitchMeshBuilder::Spline> splines;
|
||||
splines.reserve(partIdStrings.size());
|
||||
for (const auto &partIdString: partIdStrings) {
|
||||
std::vector<Uuid> componentIds(componentIdStrings.size());
|
||||
for (size_t i = 0; i < componentIdStrings.size(); ++i)
|
||||
componentIds[i] = componentIdStrings[i];
|
||||
for (size_t partIndex = 0; partIndex < partIdStrings.size(); ++partIndex) {
|
||||
const auto &partIdString = partIdStrings[partIndex];
|
||||
std::vector<StitchMeshBuilder::Node> builderNodes;
|
||||
std::map<std::string, size_t> builderNodeIdStringToIndexMap;
|
||||
for (const auto &nodeIdString: m_partNodeIds[partIdString]) {
|
||||
|
@ -473,15 +479,14 @@ std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combineStitchingMesh(const st
|
|||
splines.emplace_back(StitchMeshBuilder::Spline {
|
||||
std::move(orderedBuilderNodes),
|
||||
isCircle,
|
||||
isClosing
|
||||
isClosing,
|
||||
componentIds[partIndex]
|
||||
});
|
||||
}
|
||||
|
||||
auto stitchMeshBuilder = std::make_unique<StitchMeshBuilder>(std::move(splines));
|
||||
stitchMeshBuilder->build();
|
||||
|
||||
// stitchMeshBuilder->splines();
|
||||
|
||||
collectSharedQuadEdges(stitchMeshBuilder->generatedVertices(),
|
||||
stitchMeshBuilder->generatedFaces(),
|
||||
&componentCache.sharedQuadEdges);
|
||||
|
@ -491,6 +496,51 @@ std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combineStitchingMesh(const st
|
|||
if (mesh && mesh->isNull())
|
||||
mesh.reset();
|
||||
|
||||
// Generate preview for each stitching line
|
||||
for (const auto &spline: stitchMeshBuilder->splines()) {
|
||||
RopeMesh::BuildParameters buildParameters;
|
||||
RopeMesh ropeMesh(buildParameters);
|
||||
std::vector<Vector3> positions(spline.nodes.size());
|
||||
for (size_t i = 0; i < spline.nodes.size(); ++i)
|
||||
positions[i] = spline.nodes[i].origin;
|
||||
ropeMesh.addRope(positions, spline.isCircle);
|
||||
|
||||
ComponentPreview stitchingLinePreview;
|
||||
if (mesh)
|
||||
mesh->fetch(stitchingLinePreview.vertices, stitchingLinePreview.triangles);
|
||||
size_t startIndex = stitchingLinePreview.vertices.size();
|
||||
|
||||
stitchingLinePreview.color = Color(1.0, 1.0, 1.0, 0.2);
|
||||
for (const auto &ropeVertex: ropeMesh.resultVertices()) {
|
||||
stitchingLinePreview.vertices.emplace_back(ropeVertex);
|
||||
}
|
||||
stitchingLinePreview.vertexProperties.resize(stitchingLinePreview.vertices.size());
|
||||
auto modelProperty = std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/> {
|
||||
stitchingLinePreview.color,
|
||||
stitchingLinePreview.metalness,
|
||||
stitchingLinePreview.roughness
|
||||
};
|
||||
auto lineProperty = std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/> {
|
||||
Color(1.0, 1.0, 1.0, 1.0),
|
||||
stitchingLinePreview.metalness,
|
||||
stitchingLinePreview.roughness
|
||||
};
|
||||
for (size_t i = 0; i < startIndex; ++i) {
|
||||
stitchingLinePreview.vertexProperties[i] = modelProperty;
|
||||
}
|
||||
for (size_t i = startIndex; i < stitchingLinePreview.vertexProperties.size(); ++i) {
|
||||
stitchingLinePreview.vertexProperties[i] = lineProperty;
|
||||
}
|
||||
for (const auto &ropeTriangles: ropeMesh.resultTriangles()) {
|
||||
stitchingLinePreview.triangles.emplace_back(std::vector<size_t> {
|
||||
startIndex + ropeTriangles[0],
|
||||
startIndex + ropeTriangles[1],
|
||||
startIndex + ropeTriangles[2]
|
||||
});
|
||||
}
|
||||
addComponentPreview(spline.sourceId, ComponentPreview(stitchingLinePreview));
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
@ -996,17 +1046,8 @@ std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combineComponentMesh(const st
|
|||
groupMeshes.emplace_back(std::make_tuple(std::move(childMesh), group.first, String::join(group.second, "|")));
|
||||
}
|
||||
if (!stitchingParts.empty()) {
|
||||
auto stitchingMesh = combineStitchingMesh(stitchingParts, componentCache);
|
||||
auto stitchingMesh = combineStitchingMesh(stitchingParts, stitchingComponents, componentCache);
|
||||
if (stitchingMesh && !stitchingMesh->isNull()) {
|
||||
|
||||
// Generate preview for each stitching line
|
||||
ComponentPreview stitchingLinePreview;
|
||||
if (stitchingMesh)
|
||||
stitchingMesh->fetch(stitchingLinePreview.vertices, stitchingLinePreview.triangles);
|
||||
stitchingLinePreview.color = Color(1.0, 1.0, 1.0, 0.2);
|
||||
for (const auto &it: stitchingComponents)
|
||||
addComponentPreview(it, ComponentPreview(stitchingLinePreview));
|
||||
|
||||
groupMeshes.emplace_back(std::make_tuple(std::move(stitchingMesh), CombineMode::Normal, String::join(stitchingComponents, ":")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
Color color = Color(1.0, 1.0, 1.0);
|
||||
float metalness = 0.0;
|
||||
float roughness = 1.0;
|
||||
std::vector<std::tuple<dust3d::Color, float/*metalness*/, float/*roughness*/>> vertexProperties;
|
||||
};
|
||||
|
||||
MeshGenerator(Snapshot *snapshot);
|
||||
|
@ -144,6 +145,7 @@ private:
|
|||
GeneratedComponent &componentCache);
|
||||
std::unique_ptr<MeshCombiner::Mesh> combineMultipleMeshes(std::vector<std::tuple<std::unique_ptr<MeshCombiner::Mesh>, CombineMode, std::string>> &&multipleMeshes, bool recombine=true);
|
||||
std::unique_ptr<MeshCombiner::Mesh> combineStitchingMesh(const std::vector<std::string> &partIdStrings,
|
||||
const std::vector<std::string> &componentIdStrings,
|
||||
GeneratedComponent &componentCache);
|
||||
std::string componentColorName(const std::map<std::string, std::string> *component);
|
||||
void collectUncombinedComponent(const std::string &componentIdString);
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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/base/debug.h>
|
||||
#include <dust3d/base/math.h>
|
||||
#include <dust3d/mesh/rope_mesh.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
RopeMesh::RopeMesh(const BuildParameters ¶meters):
|
||||
m_buildParameters(parameters)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<Vector3> &RopeMesh::resultVertices()
|
||||
{
|
||||
return m_resultVertices;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Vector3 baseNormal = isCircle ? calculateCircleBaseNormal(positions) : calculateTubeBaseNormal(positions);
|
||||
std::vector<std::vector<size_t>> circles;
|
||||
circles.reserve(positions.size());
|
||||
for (size_t j = isCircle ? 0 : 1; j < positions.size(); ++j) {
|
||||
size_t i = (j + positions.size() - 1) % positions.size();
|
||||
auto circlePositions = calculateCircleVertices(m_buildParameters.defaultRadius,
|
||||
m_buildParameters.sectionSegments,
|
||||
(positions[j] - positions[i]).normalized(),
|
||||
baseNormal,
|
||||
positions[i]);
|
||||
std::vector<size_t> indices(circlePositions.size());
|
||||
for (size_t k = 0; k < indices.size(); ++k) {
|
||||
indices[k] = m_resultVertices.size();
|
||||
m_resultVertices.push_back(circlePositions[k]);
|
||||
}
|
||||
circles.emplace_back(indices);
|
||||
}
|
||||
for (size_t j = isCircle ? 0 : 1; j < circles.size(); ++j) {
|
||||
size_t i = (j + circles.size() - 1) % circles.size();
|
||||
const auto &circlesI = circles[i];
|
||||
const auto &circlesJ = circles[j];
|
||||
for (size_t m = 0; m < circlesI.size(); ++m) {
|
||||
size_t n = (m + 1) % circlesI.size();
|
||||
m_resultTriangles.emplace_back(std::vector<size_t> {
|
||||
circlesI[m], circlesI[n], circlesJ[n]
|
||||
});
|
||||
m_resultTriangles.emplace_back(std::vector<size_t> {
|
||||
circlesJ[n], circlesJ[m], circlesI[m]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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_ROPE_MESH_H_
|
||||
#define DUST3D_MESH_ROPE_MESH_H_
|
||||
|
||||
#include <vector>
|
||||
#include <dust3d/base/vector3.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
||||
class RopeMesh
|
||||
{
|
||||
public:
|
||||
struct BuildParameters
|
||||
{
|
||||
double defaultRadius = 0.01;
|
||||
size_t sectionSegments = 5;
|
||||
};
|
||||
|
||||
RopeMesh(const BuildParameters ¶meters);
|
||||
void addRope(const std::vector<Vector3> &positions, bool isCircle);
|
||||
const std::vector<Vector3> &resultVertices();
|
||||
const std::vector<std::vector<size_t>> &resultTriangles();
|
||||
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);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@
|
|||
#define DUST3D_MESH_STITCH_MESH_BUILDER_H_
|
||||
|
||||
#include <dust3d/base/vector3.h>
|
||||
#include <dust3d/base/uuid.h>
|
||||
|
||||
namespace dust3d
|
||||
{
|
||||
|
@ -42,6 +43,7 @@ public:
|
|||
std::vector<Node> nodes;
|
||||
bool isCircle = false;
|
||||
bool isClosing = false;
|
||||
Uuid sourceId;
|
||||
};
|
||||
|
||||
StitchMeshBuilder(std::vector<Spline> &&splines);
|
||||
|
|
Loading…
Reference in New Issue