diff --git a/dust3d.pro b/dust3d.pro index b3d99e27..091aab98 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -344,9 +344,6 @@ HEADERS += src/combinemode.h SOURCES += src/polycount.cpp HEADERS += src/polycount.h -SOURCES += src/cutdocument.cpp -HEADERS += src/cutdocument.h - SOURCES += src/cutface.cpp HEADERS += src/cutface.h @@ -403,12 +400,6 @@ HEADERS += src/boundingboxmesh.h SOURCES += src/regionfiller.cpp HEADERS += src/regionfiller.h -SOURCES += src/cyclefinder.cpp -HEADERS += src/cyclefinder.h - -SOURCES += src/shortestpath.cpp -HEADERS += src/shortestpath.h - SOURCES += src/meshwrapper.cpp HEADERS += src/meshwrapper.h @@ -442,24 +433,12 @@ HEADERS += src/booleanmesh.h SOURCES += src/remesher.cpp HEADERS += src/remesher.h -SOURCES += src/clothsimulator.cpp -HEADERS += src/clothsimulator.h - -SOURCES += src/componentlayer.cpp -HEADERS += src/componentlayer.h - SOURCES += src/isotropicremesh.cpp HEADERS += src/isotropicremesh.h -SOURCES += src/clothforce.cpp -HEADERS += src/clothforce.h - SOURCES += src/projectfacestonodes.cpp HEADERS += src/projectfacestonodes.h -SOURCES += src/simulateclothmeshes.cpp -HEADERS += src/simulateclothmeshes.h - SOURCES += src/ddsfile.cpp HEADERS += src/ddsfile.h diff --git a/src/clothforce.cpp b/src/clothforce.cpp deleted file mode 100644 index 9bff2b12..00000000 --- a/src/clothforce.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include "clothforce.h" - -IMPL_ClothForceFromString -IMPL_ClothForceToString -IMPL_ClothForceToDispName diff --git a/src/clothforce.h b/src/clothforce.h deleted file mode 100644 index 2dd429e0..00000000 --- a/src/clothforce.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef DUST3D_CLOTH_FORCE_H -#define DUST3D_CLOTH_FORCE_H -#include - -enum class ClothForce -{ - Gravitational = 0, - Centripetal, - Count -}; -ClothForce ClothForceFromString(const char *forceString); -#define IMPL_ClothForceFromString \ -ClothForce ClothForceFromString(const char *forceString) \ -{ \ - QString force = forceString; \ - if (force == "Gravitational") \ - return ClothForce::Gravitational; \ - if (force == "Centripetal") \ - return ClothForce::Centripetal; \ - return ClothForce::Gravitational; \ -} -const char *ClothForceToString(ClothForce force); -#define IMPL_ClothForceToString \ -const char *ClothForceToString(ClothForce force) \ -{ \ - switch (force) { \ - case ClothForce::Gravitational: \ - return "Gravitational"; \ - case ClothForce::Centripetal: \ - return "Centripetal"; \ - default: \ - return "Gravitational"; \ - } \ -} -QString ClothForceToDispName(ClothForce force); -#define IMPL_ClothForceToDispName \ -QString ClothForceToDispName(ClothForce force) \ -{ \ - switch (force) { \ - case ClothForce::Gravitational: \ - return QObject::tr("Gravitational"); \ - case ClothForce::Centripetal: \ - return QObject::tr("Centripetal"); \ - default: \ - return QObject::tr("Gravitational"); \ - } \ -} - -#endif diff --git a/src/clothsimulator.cpp b/src/clothsimulator.cpp deleted file mode 100644 index 9e2d3daf..00000000 --- a/src/clothsimulator.cpp +++ /dev/null @@ -1,290 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "clothsimulator.h" -#include "booleanmesh.h" - -typedef CGAL::Simple_cartesian K; -typedef K::Point_3 Point; -typedef K::Triangle_3 Triangle; -typedef CGAL::Polyhedron_3 Polyhedron; -typedef Polyhedron::HalfedgeDS HalfedgeDS; -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; -typedef CGAL::Side_of_triangle_mesh Point_inside; - -template -class Build_mesh : public CGAL::Modifier_base { -public: - Build_mesh(const std::vector *vertices, - const std::vector> *faces) : - m_vertices(vertices), - m_faces(faces) - { - }; - void operator()(HDS& hds) - { - // Postcondition: hds is a valid polyhedral surface. - CGAL::Polyhedron_incremental_builder_3 B(hds, false); - B.begin_surface(m_vertices->size(), m_faces->size()); - typedef typename HDS::Vertex Vertex; - typedef typename Vertex::Point Point; - for (const auto &it: *m_vertices) - B.add_vertex(Point(it.x(), it.y(), it.z())); - for (const auto &it: *m_faces) { - B.begin_facet(); - B.add_vertex_to_facet(it[0]); - B.add_vertex_to_facet(it[1]); - B.add_vertex_to_facet(it[2]); - B.end_facet(); - } - B.end_surface(); - }; -private: - const std::vector *m_vertices = nullptr; - const std::vector> *m_faces = nullptr; -}; - -// System parameters -//namespace SystemParam { -// static const int n = 61; // must be odd, n * n = n_vertices | 61 -// static const float h = 0.001f; // time step, smaller for better results | 0.008f = 0.016f/2 -// static const float m = 0.25f / (n * n); // point mass | 0.25f -// static const float a = 0.993f; // damping, close to 1.0 | 0.993f -// static const float g = 9.8f * m; // gravitational force | 9.8f -//} - -// Point - mesh collision node -class CgMeshCollisionNode : public CgPointNode { -private: - Tree *m_aabbTree = nullptr; - Point_inside *m_insideTester = nullptr; - Polyhedron m_polyhedron; -public: - CgMeshCollisionNode(mass_spring_system *system, float *vbuff, - const std::vector &collisionVertices, - const std::vector> &collisionTriangles) : - CgPointNode(system, vbuff) - { - if (!collisionTriangles.empty()) { - Build_mesh mesh(&collisionVertices, &collisionTriangles); - m_polyhedron.delegate(mesh); - m_aabbTree = new Tree(faces(m_polyhedron).first, faces(m_polyhedron).second, m_polyhedron); - m_aabbTree->accelerate_distance_queries(); - m_insideTester = new Point_inside(*m_aabbTree); - } - } - - ~CgMeshCollisionNode() - { - delete m_insideTester; - delete m_aabbTree; - }; - - bool query(unsigned int i) const - { - return false; - }; - - void satisfy() - { - for (unsigned int i = 0; i < system->n_points; i++) { - auto offset = 3 * i; - Point point(vbuff[offset + 0], - vbuff[offset + 1], - vbuff[offset + 2]); - if (nullptr != m_insideTester && - (*m_insideTester)(point) != CGAL::ON_UNBOUNDED_SIDE) { - Point closestPoint = m_aabbTree->closest_point(point); - vbuff[offset + 0] = closestPoint.x(); - vbuff[offset + 1] = closestPoint.y(); - vbuff[offset + 2] = closestPoint.z(); - } - } - } - - void fixPoints(CgPointFixNode *fixNode) - { - for (unsigned int i = 0; i < system->n_points; i++) { - auto offset = 3 * i; - Point point(vbuff[offset + 0], - vbuff[offset + 1], - vbuff[offset + 2]); - if (nullptr != m_insideTester && - (*m_insideTester)(point) != CGAL::ON_UNBOUNDED_SIDE) { - fixNode->fixPoint(i); - } - } - } - - void collectErrorPoints(std::vector *points) - { - for (unsigned int i = 0; i < system->n_points; i++) { - auto offset = 3 * i; - Point point(vbuff[offset + 0], - vbuff[offset + 1], - vbuff[offset + 2]); - if (nullptr != m_insideTester && - (*m_insideTester)(point) != CGAL::ON_UNBOUNDED_SIDE) { - points->push_back(i); - } - } - } -}; - -ClothSimulator::ClothSimulator(const std::vector &vertices, - const std::vector> &faces, - const std::vector &collisionVertices, - const std::vector> &collisionTriangles, - const std::vector &externalForces) : - m_vertices(vertices), - m_faces(faces), - m_collisionVertices(collisionVertices), - m_collisionTriangles(collisionTriangles), - m_externalForces(externalForces) -{ -} - -ClothSimulator::~ClothSimulator() -{ - delete m_massSpringSystem; - delete m_massSpringSolver; - delete m_rootNode; - delete m_deformationNode; - delete m_meshCollisionNode; - delete m_fixNode; -} - -void ClothSimulator::setStiffness(float stiffness) -{ - m_stiffness = 1.0f + 5.0f * stiffness; -} - -void ClothSimulator::convertMeshToCloth() -{ - m_clothPointSources.reserve(m_vertices.size()); - m_clothPointBuffer.reserve(m_vertices.size() * 3); - - std::map oldVertexToNewMap; - auto addPoint = [&](size_t index) { - auto findNew = oldVertexToNewMap.find(index); - if (findNew != oldVertexToNewMap.end()) - return findNew->second; - const auto &position = m_vertices[index]; - m_clothPointBuffer.push_back(position.x()); - m_clothPointBuffer.push_back(position.y()); - m_clothPointBuffer.push_back(position.z()); - size_t newIndex = m_clothPointSources.size(); - m_clothPointSources.push_back(index); - oldVertexToNewMap.insert({index, newIndex}); - return newIndex; - }; - - std::set> oldEdges; - for (const auto &it: m_faces) { - for (size_t i = 0; i < it.size(); ++i) { - size_t j = (i + 1) % it.size(); - if (oldEdges.find(std::make_pair(it[i], it[j])) != oldEdges.end()) - continue; - m_clothSprings.push_back({addPoint(it[i]), addPoint(it[j])}); - oldEdges.insert({it[i], it[j]}); - oldEdges.insert({it[j], it[i]}); - } - } -} - -void ClothSimulator::getCurrentVertices(std::vector *currentVertices) -{ - *currentVertices = m_vertices; - for (size_t newIndex = 0; newIndex < m_clothPointSources.size(); ++newIndex) { - size_t oldIndex = m_clothPointSources[newIndex]; - auto offset = newIndex * 3; - (*currentVertices)[oldIndex] = QVector3D(m_clothPointBuffer[offset + 0], - m_clothPointBuffer[offset + 1], - m_clothPointBuffer[offset + 2]); - } -} - -void ClothSimulator::step() -{ - if (nullptr == m_massSpringSolver) - return; - - m_massSpringSolver->solve(5); - m_massSpringSolver->solve(5); - - CgSatisfyVisitor visitor; - visitor.satisfy(*m_rootNode); -} - -void ClothSimulator::create() -{ - convertMeshToCloth(); - - if (m_clothPointSources.empty()) - return; - - float mass = 0.25f / m_clothPointSources.size(); - float gravitationalForce = 9.8f * mass; - float damping = 0.993f; // damping, close to 1.0 | 0.993f; - float timeStep = 0.001f; //smaller for better results | 0.008f = 0.016f/2; - - mass_spring_system::VectorXf masses(mass * mass_spring_system::VectorXf::Ones((unsigned int)m_clothSprings.size())); - - mass_spring_system::EdgeList springList(m_clothSprings.size()); - mass_spring_system::VectorXf restLengths(m_clothSprings.size()); - mass_spring_system::VectorXf stiffnesses(m_clothSprings.size()); - - for (size_t i = 0; i < m_clothSprings.size(); ++i) { - const auto &source = m_clothSprings[i]; - springList[i] = mass_spring_system::Edge(source.first, source.second); - restLengths[i] = (m_vertices[m_clothPointSources[source.first]] - m_vertices[m_clothPointSources[source.second]]).length() * 0.8; - stiffnesses[i] = m_stiffness; - } - - mass_spring_system::VectorXf fext(m_clothPointSources.size() * 3); - for (size_t i = 0; i < m_clothPointSources.size(); ++i) { - const auto &externalForce = m_externalForces[i] * gravitationalForce; - auto offset = i * 3; - fext[offset + 0] = externalForce.x(); - fext[offset + 1] = externalForce.y(); - fext[offset + 2] = externalForce.z(); - } - - m_massSpringSystem = new mass_spring_system(m_clothPointSources.size(), m_clothSprings.size(), timeStep, springList, restLengths, - stiffnesses, masses, fext, damping); - - m_massSpringSolver = new MassSpringSolver(m_massSpringSystem, m_clothPointBuffer.data()); - - // deformation constraint parameters - const float tauc = 0.12f; // critical spring deformation | 0.12f - const unsigned int deformIter = 15; // number of iterations | 15 - - std::vector structSprintIndexList; - structSprintIndexList.reserve(springList.size()); - m_deformationNode = - new CgSpringDeformationNode(m_massSpringSystem, m_clothPointBuffer.data(), tauc, deformIter); - m_deformationNode->addSprings(structSprintIndexList); - - m_rootNode = new CgRootNode(m_massSpringSystem, m_clothPointBuffer.data()); - m_rootNode->addChild(m_deformationNode); - - m_meshCollisionNode = new CgMeshCollisionNode(m_massSpringSystem, m_clothPointBuffer.data(), - m_collisionVertices, - m_collisionTriangles); - - m_fixNode = new CgPointFixNode(m_massSpringSystem, m_clothPointBuffer.data()); - m_meshCollisionNode->fixPoints(m_fixNode); - m_deformationNode->addChild(m_fixNode); - - m_rootNode->addChild(m_meshCollisionNode); -} diff --git a/src/clothsimulator.h b/src/clothsimulator.h deleted file mode 100644 index 9b95f0f5..00000000 --- a/src/clothsimulator.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DUST3D_CLOTH_SIMULATOR_H -#define DUST3D_CLOTH_SIMULATOR_H -#include -#include -#include - -struct mass_spring_system; -class MassSpringSolver; -class CgRootNode; -class CgSpringDeformationNode; -class CgMeshCollisionNode; -class CgPointFixNode; - -class ClothSimulator : public QObject -{ - Q_OBJECT -public: - ClothSimulator(const std::vector &vertices, - const std::vector> &faces, - const std::vector &collisionVertices, - const std::vector> &collisionTriangles, - const std::vector &externalForces); - ~ClothSimulator(); - void setStiffness(float stiffness); - void create(); - void step(); - void getCurrentVertices(std::vector *currentVertices); -private: - std::vector m_vertices; - std::vector> m_faces; - std::vector m_collisionVertices; - std::vector> m_collisionTriangles; - std::vector m_externalForces; - std::vector m_clothPointBuffer; - std::vector m_clothPointSources; - std::vector> m_clothSprings; - float m_stiffness = 1.0f; - QVector3D m_offset; - mass_spring_system *m_massSpringSystem = nullptr; - MassSpringSolver *m_massSpringSolver = nullptr; - CgRootNode *m_rootNode = nullptr; - CgSpringDeformationNode *m_deformationNode = nullptr; - CgMeshCollisionNode *m_meshCollisionNode = nullptr; - CgPointFixNode *m_fixNode = nullptr; - void convertMeshToCloth(); -}; - -#endif diff --git a/src/componentlayer.cpp b/src/componentlayer.cpp deleted file mode 100644 index 603c0929..00000000 --- a/src/componentlayer.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include "componentlayer.h" - -IMPL_ComponentLayerToString -IMPL_ComponentLayerFromString -IMPL_ComponentLayerToDispName \ No newline at end of file diff --git a/src/componentlayer.h b/src/componentlayer.h deleted file mode 100644 index 0202a819..00000000 --- a/src/componentlayer.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef DUST3D_COMPONENT_LAYER_H -#define DUST3D_COMPONENT_LAYER_H -#include - -enum class ComponentLayer -{ - Body = 0, - Cloth, - Count -}; -ComponentLayer ComponentLayerFromString(const char *layerString); -#define IMPL_ComponentLayerFromString \ -ComponentLayer ComponentLayerFromString(const char *layerString) \ -{ \ - QString layer = layerString; \ - if (layer == "Body") \ - return ComponentLayer::Body; \ - if (layer == "Cloth") \ - return ComponentLayer::Cloth; \ - return ComponentLayer::Body; \ -} -const char *ComponentLayerToString(ComponentLayer layer); -#define IMPL_ComponentLayerToString \ -const char *ComponentLayerToString(ComponentLayer layer) \ -{ \ - switch (layer) { \ - case ComponentLayer::Body: \ - return "Body"; \ - case ComponentLayer::Cloth: \ - return "Cloth"; \ - default: \ - return "Body"; \ - } \ -} -QString ComponentLayerToDispName(ComponentLayer layer); -#define IMPL_ComponentLayerToDispName \ -QString ComponentLayerToDispName(ComponentLayer layer) \ -{ \ - switch (layer) { \ - case ComponentLayer::Body: \ - return QObject::tr("Body"); \ - case ComponentLayer::Cloth: \ - return QObject::tr("Cloth"); \ - default: \ - return QObject::tr("Body"); \ - } \ -} - -#endif diff --git a/src/cutdocument.cpp b/src/cutdocument.cpp deleted file mode 100644 index 2ee72b43..00000000 --- a/src/cutdocument.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include -#include "cutdocument.h" - -const float CutDocument::m_nodeRadius = 0.05; -const float CutDocument::m_nodeScaleFactor = 0.5; - -bool CutDocument::hasPastableNodesInClipboard() const -{ - return false; -} - -bool CutDocument::originSettled() const -{ - return false; -} - -bool CutDocument::isNodeEditable(QUuid nodeId) const -{ - Q_UNUSED(nodeId); - return true; -} - -bool CutDocument::isEdgeEditable(QUuid edgeId) const -{ - Q_UNUSED(edgeId); - return true; -} - -void CutDocument::copyNodes(std::set nodeIdSet) const -{ - Q_UNUSED(nodeIdSet); -} - -void CutDocument::saveHistoryItem() -{ - CutHistoryItem item; - toCutTemplate(item.cutTemplate); - m_undoItems.push_back(item); -} - -bool CutDocument::undoable() const -{ - return m_undoItems.size() >= 2; -} - -bool CutDocument::redoable() const -{ - return !m_redoItems.empty(); -} - -void CutDocument::undo() -{ - if (!undoable()) - return; - m_redoItems.push_back(m_undoItems.back()); - m_undoItems.pop_back(); - const auto &item = m_undoItems.back(); - fromCutTemplate(item.cutTemplate); -} - -void CutDocument::redo() -{ - if (m_redoItems.empty()) - return; - m_undoItems.push_back(m_redoItems.back()); - const auto &item = m_redoItems.back(); - fromCutTemplate(item.cutTemplate); - m_redoItems.pop_back(); -} - -void CutDocument::paste() -{ - // void -} - -void CutDocument::reset() -{ - nodeMap.clear(); - edgeMap.clear(); - partMap.clear(); - m_cutNodeIds.clear(); - emit cleanup(); - emit cutTemplateChanged(); -} - -void CutDocument::clearHistories() -{ - m_undoItems.clear(); - m_redoItems.clear(); -} - -void CutDocument::toCutTemplate(std::vector &cutTemplate) -{ - for (const auto &nodeId: m_cutNodeIds) { - auto findNode = nodeMap.find(nodeId); - if (findNode == nodeMap.end()) - continue; - QVector2D position = nodeToCutPosition({findNode->second.getX(), - findNode->second.getY(), - findNode->second.getZ() - }); - cutTemplate.push_back(position); - } -} - -QVector2D CutDocument::nodeToCutPosition(const QVector3D &nodePosition) -{ - return {(nodePosition.x() * 2 - (float)1) / m_nodeScaleFactor, - (nodePosition.y() * 2 - (float)1) / m_nodeScaleFactor}; -} - -QVector3D CutDocument::cutToNodePosition(const QVector2D &cutPosition) -{ - return {(cutPosition.x() * m_nodeScaleFactor + 1) * (float)0.5, - (cutPosition.y() * m_nodeScaleFactor + 1) * (float)0.5, - (float)0}; -} - -void CutDocument::fromCutTemplate(const std::vector &cutTemplate) -{ - reset(); - - std::set newAddedNodeIds; - std::set newAddedEdgeIds; - - m_partId = QUuid::createUuid(); - auto &part = partMap[m_partId]; - part.id = m_partId; - - for (const auto &position: cutTemplate) { - SkeletonNode node; - node.partId = m_partId; - node.id = QUuid::createUuid(); - node.setRadius(m_nodeRadius); - auto nodePosition = cutToNodePosition(position); - node.setX(nodePosition.x()); - node.setY(nodePosition.y()); - node.setZ(nodePosition.z()); - nodeMap[node.id] = node; - newAddedNodeIds.insert(node.id); - m_cutNodeIds.push_back(node.id); - } - - for (size_t i = 0; i < m_cutNodeIds.size(); ++i) { - size_t j = (i + 1) % m_cutNodeIds.size(); - const QUuid &firstNodeId = m_cutNodeIds[i]; - const QUuid &secondNodeId = m_cutNodeIds[j]; - - SkeletonEdge edge; - edge.partId = m_partId; - edge.id = QUuid::createUuid(); - edge.nodeIds.push_back(firstNodeId); - edge.nodeIds.push_back(secondNodeId); - edgeMap[edge.id] = edge; - newAddedEdgeIds.insert(edge.id); - nodeMap[firstNodeId].edgeIds.push_back(edge.id); - nodeMap[secondNodeId].edgeIds.push_back(edge.id); - } - - for (const auto &nodeIt: newAddedNodeIds) { - emit nodeAdded(nodeIt); - } - for (const auto &edgeIt: newAddedEdgeIds) { - emit edgeAdded(edgeIt); - } - - emit cutTemplateChanged(); -} - -void CutDocument::moveNodeBy(QUuid nodeId, float x, float y, float z) -{ - auto it = nodeMap.find(nodeId); - if (it == nodeMap.end()) { - qDebug() << "Find node failed:" << nodeId; - return; - } - it->second.addX(x); - it->second.addY(y); - it->second.addZ(z); - emit nodeOriginChanged(it->first); - emit cutTemplateChanged(); -} - -void CutDocument::setNodeOrigin(QUuid nodeId, float x, float y, float z) -{ - auto it = nodeMap.find(nodeId); - if (it == nodeMap.end()) { - qDebug() << "Find node failed:" << nodeId; - return; - } - it->second.setX(x); - it->second.setY(y); - it->second.setZ(z); - auto part = partMap.find(it->second.partId); - if (part != partMap.end()) - part->second.dirty = true; - emit nodeOriginChanged(nodeId); - emit cutTemplateChanged(); -} - diff --git a/src/cutdocument.h b/src/cutdocument.h deleted file mode 100644 index be34a2b5..00000000 --- a/src/cutdocument.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef DUST3D_CUT_DOCUMENT_H -#define DUST3D_CUT_DOCUMENT_H -#include -#include -#include "skeletondocument.h" - -struct CutHistoryItem -{ - std::vector cutTemplate; -}; - -class CutDocument : public SkeletonDocument -{ - Q_OBJECT -signals: - void cleanup(); - void nodeAdded(QUuid nodeId); - void edgeAdded(QUuid edgeId); - void nodeOriginChanged(QUuid nodeId); - void cutTemplateChanged(); - -public: - bool undoable() const override; - bool redoable() const override; - bool hasPastableNodesInClipboard() const override; - bool originSettled() const override; - bool isNodeEditable(QUuid nodeId) const override; - bool isEdgeEditable(QUuid edgeId) const override; - void copyNodes(std::set nodeIdSet) const override; - - void reset(); - void toCutTemplate(std::vector &cutTemplate); - void fromCutTemplate(const std::vector &cutTemplate); - -public slots: - void saveHistoryItem(); - void clearHistories(); - void undo() override; - void redo() override; - void paste() override; - - void moveNodeBy(QUuid nodeId, float x, float y, float z); - void setNodeOrigin(QUuid nodeId, float x, float y, float z); - -public: - static const float m_nodeRadius; - static const float m_nodeScaleFactor; - -private: - std::deque m_undoItems; - std::deque m_redoItems; - std::vector m_cutNodeIds; - QUuid m_partId; - - QVector2D nodeToCutPosition(const QVector3D &nodePosition); - QVector3D cutToNodePosition(const QVector2D &cutPosition); -}; - -#endif - diff --git a/src/cyclefinder.cpp b/src/cyclefinder.cpp deleted file mode 100644 index 15785438..00000000 --- a/src/cyclefinder.cpp +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include -#include -#include -#include "cyclefinder.h" -#include "shortestpath.h" - -// -// The cycle finder implement the following method: -// 1. Remove edge -// 2. Find shortest alternative path between the removed edge -// https://www.geeksforgeeks.org/find-minimum-weight-cycle-undirected-graph/ -// - -CycleFinder::CycleFinder(const std::vector &nodePositions, - const std::vector> &edges) : - m_nodeNum(nodePositions.size()), - m_nodePositions(nodePositions), - m_edges(edges) -{ -} - -void CycleFinder::prepareWeights() -{ - m_edgeLengths.resize(m_edges.size(), 1); - for (size_t i = 0; i < m_edges.size(); ++i) { - const auto &edge = m_edges[i]; - auto length = m_nodePositions[edge.first].distanceToPoint( - m_nodePositions[edge.second]) * 10000; - m_edgeLengths[i] = length; - m_edgeLengthMap.insert({std::make_pair(edge.first, edge.second), length}); - m_edgeLengthMap.insert({std::make_pair(edge.second, edge.first), length}); - } -} - -bool CycleFinder::validateCycleByFlatness(const std::vector &cycle) -{ - // Validate cycle by mesaure the flatness of the face - // Flatness = Average variation of corner normals - if (cycle.empty()) - return false; - std::vector normals; - for (size_t i = 0; i < cycle.size(); ++i) { - size_t h = (i + cycle.size() - 1) % cycle.size(); - size_t j = (i + 1) % cycle.size(); - QVector3D vh = m_nodePositions[cycle[h]]; - QVector3D vi = m_nodePositions[cycle[i]]; - QVector3D vj = m_nodePositions[cycle[j]]; - if (QVector3D::dotProduct((vj - vi).normalized(), - (vi - vh).normalized()) <= 0.966) { // 15 degrees - auto vertexNormal = QVector3D::normal(vj - vi, vh - vi); - normals.push_back(vertexNormal); - } - } - if (normals.empty()) - return false; - float sumOfDistance = 0; - for (size_t i = 0; i < normals.size(); ++i) { - size_t j = (i + 1) % normals.size(); - sumOfDistance += (normals[i] - normals[j]).length(); - } - float flatness = sumOfDistance / normals.size(); - if (flatness >= m_invalidFlatness) { - return false; - } - return true; -} - -int CycleFinder::calculateCycleLength(const std::vector &cycle) -{ - float cycleLength = 0; - for (size_t i = 0; i < cycle.size(); ++i) { - size_t j = (i + 1) % cycle.size(); - auto edge = std::make_pair(cycle[i], cycle[j]); - auto findEdgeLength = m_edgeLengthMap.find(edge); - if (findEdgeLength == m_edgeLengthMap.end()) - continue; - cycleLength += findEdgeLength->second; - } - return cycleLength; -} - -void CycleFinder::find() -{ - prepareWeights(); - - if (m_edges.empty()) - return; - - std::queue> waitEdges; - std::set> visited; - std::map, size_t> halfEdgeToCycleMap; - - auto isPathValid = [&](const std::vector &path) { - for (size_t i = 0; i < path.size(); ++i) { - size_t j = (i + 1) % path.size(); - auto edge = std::make_pair(path[i], path[j]); - if (m_halfEdges.find(edge) != m_halfEdges.end()) { - return false; - } - } - std::map oppositeCycleEdgeLengths; - for (size_t i = 0; i < path.size(); ++i) { - size_t j = (i + 1) % path.size(); - auto oppositeEdge = std::make_pair(path[j], path[i]); - auto findOpposite = halfEdgeToCycleMap.find(oppositeEdge); - if (findOpposite == halfEdgeToCycleMap.end()) - continue; - oppositeCycleEdgeLengths[findOpposite->second] += m_edgeLengthMap[oppositeEdge]; - } - for (const auto &it: oppositeCycleEdgeLengths) { - if (it.first >= m_cycleLengths.size()) { - qDebug() << "Find cycle length failed, should not happen"; - return false; - } - const auto &fullLength = m_cycleLengths[it.first]; - if (fullLength <= 0) { - qDebug() << "Cycle length invalid, should not happen"; - return false; - } - if ((float)it.second / fullLength >= 0.5) { - // Half of the edges (measured by sum of length) have been used by opposite face - return false; - } - } - if (!validateCycleByFlatness(path)) - return false; - return true; - }; - - std::map, size_t> edgeIndexMap; - for (size_t i = 0; i < m_edges.size(); ++i) { - const auto &edge = m_edges[i]; - edgeIndexMap.insert({edge, i}); - edgeIndexMap.insert({std::make_pair(edge.second, edge.first), i}); - } - - waitEdges.push(m_edges[0]); - while (!waitEdges.empty()) { - auto currentEdge = waitEdges.front(); - waitEdges.pop(); - if (visited.find(currentEdge) != visited.end()) - continue; - visited.insert(currentEdge); - - auto edges = m_edges; - auto weights = m_edgeLengths; - std::vector path; - removeEdgeFrom(currentEdge, &edges, &weights); - if (!shortestPath(m_nodeNum, edges, weights, currentEdge.first, currentEdge.second, &path)) - continue; - - bool isValid = isPathValid(path); - - if (!isValid) - continue; - - for (size_t i = 0; i < path.size(); ++i) { - size_t j = (i + 1) % path.size(); - auto edge = std::make_pair(path[i], path[j]); - m_halfEdges.insert(edge); - halfEdgeToCycleMap.insert({edge, m_cycles.size()}); - } - - m_cycles.push_back(path); - m_cycleLengths.push_back(calculateCycleLength(path)); - - // Update weights - for (size_t i = 0; i < path.size(); ++i) { - size_t j = (i + 1) % path.size(); - auto edge = std::make_pair(path[i], path[j]); - auto index = edgeIndexMap[edge]; - m_edgeLengths[index] += 100000; - } - - // Add opposite edges to wait queue - for (size_t i = 0; i < path.size(); ++i) { - size_t j = (i + 1) % path.size(); - auto oppositeEdge = std::make_pair(path[j], path[i]); - if (visited.find(oppositeEdge) != visited.end()) - continue; - waitEdges.push(oppositeEdge); - } - } -} - -const std::vector> &CycleFinder::getCycles() -{ - return m_cycles; -} - -void CycleFinder::removeEdgeFrom(const std::pair &edge, - std::vector> *edges, - std::vector *edgeLengths) -{ - auto oppositeEdge = std::make_pair(edge.second, edge.first); - for (auto it = edges->begin(); it != edges->end(); ++it) { - if (*it == edge || *it == oppositeEdge) { - auto index = it - edges->begin(); - edgeLengths->erase(edgeLengths->begin() + index); - edges->erase(it); - break; - } - } -} diff --git a/src/cyclefinder.h b/src/cyclefinder.h deleted file mode 100644 index 606a34a4..00000000 --- a/src/cyclefinder.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DUST3D_CYCLE_FINDER -#define DUST3D_CYCLE_FINDER -#include -#include -#include - -class CycleFinder -{ -public: - CycleFinder(const std::vector &nodePositions, - const std::vector> &edges); - void find(); - const std::vector> &getCycles(); -private: - size_t m_nodeNum = 0; - std::vector m_nodePositions; - std::vector> m_edges; - std::vector m_edgeLengths; - std::map, int> m_edgeLengthMap; - std::vector> m_cycles; - std::vector m_cycleLengths; - std::set> m_cycleEdges; - std::set> m_halfEdges; - float m_invalidFlatness = 1.0; - void removeEdgeFrom(const std::pair &edge, - std::vector> *edges, - std::vector *edgeLengths); - void prepareWeights(); - bool validateCycleByFlatness(const std::vector &cycle); - int calculateCycleLength(const std::vector &cycle); -}; - -#endif - diff --git a/src/document.cpp b/src/document.cpp index a74b30f5..af2acf41 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -21,8 +21,6 @@ #include "meshgenerator.h" unsigned long Document::m_maxSnapshot = 1000; -const float Component::defaultClothStiffness = 0.5f; -const size_t Component::defaultClothIteration = 350; Document::Document() : SkeletonDocument(), @@ -1230,16 +1228,6 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId component["smoothSeam"] = QString::number(componentIt.second.smoothSeam); if (componentIt.second.polyCount != PolyCount::Original) component["polyCount"] = PolyCountToString(componentIt.second.polyCount); - if (componentIt.second.layer != ComponentLayer::Body) - component["layer"] = ComponentLayerToString(componentIt.second.layer); - if (componentIt.second.clothStiffnessAdjusted()) - component["clothStiffness"] = QString::number(componentIt.second.clothStiffness); - if (componentIt.second.clothIterationAdjusted()) - component["clothIteration"] = QString::number(componentIt.second.clothIteration); - if (componentIt.second.clothForceAdjusted()) - component["clothForce"] = ClothForceToString(componentIt.second.clothForce); - if (componentIt.second.clothOffsetAdjusted()) - component["clothOffset"] = QString::number(componentIt.second.clothOffset); QStringList childIdList; for (const auto &childId: componentIt.second.childrenIds) { childIdList.append(childId.toString()); @@ -1682,19 +1670,6 @@ void Document::addFromSnapshot(const Snapshot &snapshot, enum SnapshotSource sou if (smoothSeamIt != componentKv.second.end()) component.setSmoothSeam(smoothSeamIt->second.toFloat()); component.polyCount = PolyCountFromString(valueOfKeyInMapOrEmpty(componentKv.second, "polyCount").toUtf8().constData()); - component.layer = ComponentLayerFromString(valueOfKeyInMapOrEmpty(componentKv.second, "layer").toUtf8().constData()); - auto findClothStiffness = componentKv.second.find("clothStiffness"); - if (findClothStiffness != componentKv.second.end()) - component.clothStiffness = findClothStiffness->second.toFloat(); - auto findClothIteration = componentKv.second.find("clothIteration"); - if (findClothIteration != componentKv.second.end()) - component.clothIteration = findClothIteration->second.toUInt(); - auto findClothForce = componentKv.second.find("clothForce"); - if (findClothForce != componentKv.second.end()) - component.clothForce = ClothForceFromString(valueOfKeyInMapOrEmpty(componentKv.second, "clothForce").toUtf8().constData()); - auto findClothOffset = componentKv.second.find("clothOffset"); - if (findClothOffset != componentKv.second.end()) - component.clothOffset = valueOfKeyInMapOrEmpty(componentKv.second, "clothOffset").toFloat(); //qDebug() << "Add component:" << component.id << " old:" << componentKv.first << "name:" << component.name; if ("partId" == linkDataType) { QUuid partId = oldNewIdMap[QUuid(linkData)]; @@ -2508,76 +2483,6 @@ void Document::setComponentPolyCount(QUuid componentId, PolyCount count) emit skeletonChanged(); } -void Document::setComponentLayer(QUuid componentId, ComponentLayer layer) -{ - Component *component = (Component *)findComponent(componentId); - if (nullptr == component) - return; - if (component->layer == layer) - return; - - component->layer = layer; - component->dirty = true; - emit componentLayerChanged(componentId); - emit skeletonChanged(); -} - -void Document::setComponentClothStiffness(QUuid componentId, float stiffness) -{ - Component *component = (Component *)findComponent(componentId); - if (nullptr == component) - return; - if (qFuzzyCompare(component->clothStiffness, stiffness)) - return; - - component->clothStiffness = stiffness; - component->dirty = true; - emit componentClothStiffnessChanged(componentId); - emit skeletonChanged(); -} - -void Document::setComponentClothIteration(QUuid componentId, size_t iteration) -{ - Component *component = (Component *)findComponent(componentId); - if (nullptr == component) - return; - if (component->clothIteration == iteration) - return; - - component->clothIteration = iteration; - component->dirty = true; - emit componentClothIterationChanged(componentId); - emit skeletonChanged(); -} - -void Document::setComponentClothForce(QUuid componentId, ClothForce force) -{ - Component *component = (Component *)findComponent(componentId); - if (nullptr == component) - return; - if (component->clothForce == force) - return; - - component->clothForce = force; - component->dirty = true; - emit componentClothForceChanged(componentId); - emit skeletonChanged(); -} - -void Document::setComponentClothOffset(QUuid componentId, float offset) -{ - Component *component = (Component *)findComponent(componentId); - if (nullptr == component) - return; - if (qFuzzyCompare(component->clothOffset, offset)) - return; - - component->clothOffset = offset; - component->dirty = true; - emit componentClothOffsetChanged(componentId); - emit skeletonChanged(); -} - void Document::createNewComponentAndMoveThisIn(QUuid componentId) { auto component = componentMap.find(componentId); diff --git a/src/document.h b/src/document.h index 10809a8e..5d5bc49f 100644 --- a/src/document.h +++ b/src/document.h @@ -26,8 +26,6 @@ #include "preferences.h" #include "paintmode.h" #include "proceduralanimation.h" -#include "componentlayer.h" -#include "clothforce.h" #include "texturepainter.h" class MaterialPreviewsGenerator; @@ -45,8 +43,6 @@ public: class Component { public: - static const float defaultClothStiffness; - static const size_t defaultClothIteration; Component() { } @@ -69,11 +65,6 @@ public: float smoothAll = 0.0; float smoothSeam = 0.0; PolyCount polyCount = PolyCount::Original; - ComponentLayer layer = ComponentLayer::Body; - float clothStiffness = defaultClothStiffness; - ClothForce clothForce = ClothForce::Gravitational; - float clothOffset = 0.0f; - size_t clothIteration = defaultClothIteration; std::vector childrenIds; QString linkData() const { @@ -193,22 +184,6 @@ public: { return smoothAllAdjusted() || smoothSeamAdjusted(); } - bool clothStiffnessAdjusted() const - { - return fabs(clothStiffness - Component::defaultClothStiffness) >= 0.01; - } - bool clothIterationAdjusted() const - { - return clothIteration != defaultClothIteration; - } - bool clothForceAdjusted() const - { - return ClothForce::Gravitational != clothForce; - } - bool clothOffsetAdjusted() const - { - return fabs(clothOffset - 0.0) >= 0.01; - } private: std::set m_childrenIdSet; }; @@ -314,10 +289,6 @@ signals: void componentSmoothSeamChanged(QUuid componentId); void componentPolyCountChanged(QUuid componentId); void componentLayerChanged(QUuid componentId); - void componentClothStiffnessChanged(QUuid componentId); - void componentClothIterationChanged(QUuid componentId); - void componentClothForceChanged(QUuid componentId); - void componentClothOffsetChanged(QUuid componentId); void nodeRemoved(QUuid nodeId); void edgeRemoved(QUuid edgeId); void nodeRadiusChanged(QUuid nodeId); @@ -585,11 +556,6 @@ public slots: void setComponentSmoothAll(QUuid componentId, float toSmoothAll); void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam); void setComponentPolyCount(QUuid componentId, PolyCount count); - void setComponentLayer(QUuid componentId, ComponentLayer layer); - void setComponentClothStiffness(QUuid componentId, float stiffness); - void setComponentClothIteration(QUuid componentId, size_t iteration); - void setComponentClothForce(QUuid componentId, ClothForce force); - void setComponentClothOffset(QUuid componentId, float offset); void hideOtherComponents(QUuid componentId); void lockOtherComponents(QUuid componentId); void hideAllComponents(); diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 7d322825..dffdf1f6 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -987,7 +987,6 @@ DocumentWindow::DocumentWindow() : connect(m_partTreeWidget, &PartTreeWidget::setComponentSmoothAll, m_document, &Document::setComponentSmoothAll); connect(m_partTreeWidget, &PartTreeWidget::setComponentSmoothSeam, m_document, &Document::setComponentSmoothSeam); connect(m_partTreeWidget, &PartTreeWidget::setComponentPolyCount, m_document, &Document::setComponentPolyCount); - connect(m_partTreeWidget, &PartTreeWidget::setComponentLayer, m_document, &Document::setComponentLayer); connect(m_partTreeWidget, &PartTreeWidget::moveComponent, m_document, &Document::moveComponent); connect(m_partTreeWidget, &PartTreeWidget::removeComponent, m_document, &Document::removeComponent); connect(m_partTreeWidget, &PartTreeWidget::hideOtherComponents, m_document, &Document::hideOtherComponents); @@ -1002,10 +1001,6 @@ DocumentWindow::DocumentWindow() : connect(m_partTreeWidget, &PartTreeWidget::setPartVisibleState, m_document, &Document::setPartVisibleState); connect(m_partTreeWidget, &PartTreeWidget::setPartColorState, m_document, &Document::setPartColorState); connect(m_partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode); - connect(m_partTreeWidget, &PartTreeWidget::setComponentClothStiffness, m_document, &Document::setComponentClothStiffness); - connect(m_partTreeWidget, &PartTreeWidget::setComponentClothIteration, m_document, &Document::setComponentClothIteration); - connect(m_partTreeWidget, &PartTreeWidget::setComponentClothForce, m_document, &Document::setComponentClothForce); - connect(m_partTreeWidget, &PartTreeWidget::setComponentClothOffset, m_document, &Document::setComponentClothOffset); connect(m_partTreeWidget, &PartTreeWidget::setPartTarget, m_document, &Document::setPartTarget); connect(m_partTreeWidget, &PartTreeWidget::setPartBase, m_document, &Document::setPartBase); connect(m_partTreeWidget, &PartTreeWidget::hideDescendantComponents, m_document, &Document::hideDescendantComponents); diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index 0046c54e..f5477578 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -17,11 +17,9 @@ #include "triangulatefaces.h" #include "remesher.h" #include "polycount.h" -#include "clothsimulator.h" #include "isotropicremesh.h" #include "projectfacestonodes.h" #include "document.h" -#include "simulateclothmeshes.h" #include "meshstroketifier.h" #include "fileforever.h" #include "snapshotxml.h" @@ -915,11 +913,6 @@ CombineMode MeshGenerator::componentCombineMode(const std::map combineMode = CombineMode::Inversion; if (componentRemeshed(component)) combineMode = CombineMode::Uncombined; - if (combineMode == CombineMode::Normal) { - if (ComponentLayer::Body != ComponentLayerFromString(valueOfKeyInMapOrEmpty(*component, "layer").toUtf8().constData())) { - combineMode = CombineMode::Uncombined; - } - } } return combineMode; } @@ -928,17 +921,9 @@ bool MeshGenerator::componentRemeshed(const std::map *componen { if (nullptr == component) return false; - bool isCloth = false; - if (ComponentLayer::Cloth == ComponentLayerFromString(valueOfKeyInMapOrEmpty(*component, "layer").toUtf8().constData())) { - if (nullptr != polyCountValue) - *polyCountValue = PolyCountToValue(PolyCount::VeryHighPoly); - isCloth = true; - } auto polyCount = PolyCountFromString(valueOfKeyInMapOrEmpty(*component, "polyCount").toUtf8().constData()); if (nullptr != polyCountValue) *polyCountValue = PolyCountToValue(polyCount); - if (isCloth) - return true; return polyCount != PolyCount::Original; } @@ -967,47 +952,6 @@ QString MeshGenerator::componentColorName(const std::map *comp return QString(); } -ComponentLayer MeshGenerator::componentLayer(const std::map *component) -{ - if (nullptr == component) - return ComponentLayer::Body; - return ComponentLayerFromString(valueOfKeyInMapOrEmpty(*component, "layer").toUtf8().constData()); -} - -float MeshGenerator::componentClothStiffness(const std::map *component) -{ - if (nullptr == component) - return Component::defaultClothStiffness; - auto findClothStiffness = component->find("clothStiffness"); - if (findClothStiffness == component->end()) - return Component::defaultClothStiffness; - return findClothStiffness->second.toFloat(); -} - -size_t MeshGenerator::componentClothIteration(const std::map *component) -{ - if (nullptr == component) - return Component::defaultClothIteration; - auto findClothIteration = component->find("clothIteration"); - if (findClothIteration == component->end()) - return Component::defaultClothIteration; - return findClothIteration->second.toUInt(); -} - -ClothForce MeshGenerator::componentClothForce(const std::map *component) -{ - if (nullptr == component) - return ClothForce::Gravitational; - return ClothForceFromString(valueOfKeyInMapOrEmpty(*component, "clothForce").toUtf8().constData()); -} - -float MeshGenerator::componentClothOffset(const std::map *component) -{ - if (nullptr == component) - return 0.0f; - return valueOfKeyInMapOrEmpty(*component, "clothOffset").toFloat(); -} - MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &componentIdString, CombineMode *combineMode) { MeshCombiner::Mesh *mesh = nullptr; @@ -1616,8 +1560,6 @@ void MeshGenerator::collectUncombinedComponent(const QString &componentIdString) { const auto &component = findComponent(componentIdString); if (CombineMode::Uncombined == componentCombineMode(component)) { - if (ComponentLayer::Body != componentLayer(component)) - return; const auto &componentCache = m_cacheContext->components[componentIdString]; if (nullptr == componentCache.mesh || componentCache.mesh->isNull()) { qDebug() << "Uncombined mesh is null"; @@ -1638,90 +1580,6 @@ void MeshGenerator::collectUncombinedComponent(const QString &componentIdString) } } -void MeshGenerator::collectClothComponentIdStrings(const QString &componentIdString, - std::vector *componentIdStrings) -{ - const auto &component = findComponent(componentIdString); - if (ComponentLayer::Cloth == componentLayer(component)) { - const auto &componentCache = m_cacheContext->components[componentIdString]; - if (nullptr == componentCache.mesh) { - return; - } - componentIdStrings->push_back(componentIdString); - return; - } - for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) { - if (childIdString.isEmpty()) - continue; - collectClothComponentIdStrings(childIdString, componentIdStrings); - } -} - -void MeshGenerator::collectClothComponent(const QString &componentIdString) -{ - if (m_clothCollisionTriangles.empty()) - return; - - std::vector componentIdStrings; - collectClothComponentIdStrings(componentIdString, &componentIdStrings); - - std::vector clothMeshes(componentIdStrings.size()); - for (size_t i = 0; i < componentIdStrings.size(); ++i) { - const auto &componentIdString = componentIdStrings[i]; - const auto &componentCache = m_cacheContext->components[componentIdString]; - if (nullptr == componentCache.mesh) { - return; - } - const auto &component = findComponent(componentIdString); - auto &clothMesh = clothMeshes[i]; - componentCache.mesh->fetch(clothMesh.vertices, clothMesh.faces); - clothMesh.clothForce = componentClothForce(component); - clothMesh.clothOffset = componentClothOffset(component); - clothMesh.clothStiffness = componentClothStiffness(component); - clothMesh.clothIteration = componentClothIteration(component); - clothMesh.objectNodeVertices = &componentCache.objectNodeVertices; - //m_object->clothNodes.insert(m_object->clothNodes.end(), componentCache.objectNodes.begin(), componentCache.objectNodes.end()); - //m_object->nodes.insert(m_object->nodes.end(), componentCache.objectNodes.begin(), componentCache.objectNodes.end()); - for (const auto &objectNode: componentCache.objectNodes) { - auto newNode = objectNode; - newNode.layer = ComponentLayer::Cloth; - m_object->nodes.push_back(newNode); - } - m_object->edges.insert(m_object->edges.end(), componentCache.objectEdges.begin(), componentCache.objectEdges.end()); - } - simulateClothMeshes(&clothMeshes, - &m_clothCollisionVertices, - &m_clothCollisionTriangles); - for (auto &clothMesh: clothMeshes) { - auto vertexStartIndex = m_object->vertices.size(); - auto updateVertexIndices = [=](std::vector> &faces) { - for (auto &it: faces) { - for (auto &subIt: it) - subIt += vertexStartIndex; - } - }; - updateVertexIndices(clothMesh.faces); - m_object->vertices.insert(m_object->vertices.end(), clothMesh.vertices.begin(), clothMesh.vertices.end()); - for (const auto &it: clothMesh.faces) { - if (4 == it.size()) { - m_object->triangles.push_back(std::vector { - it[0], it[1], it[2] - }); - m_object->triangles.push_back(std::vector { - it[2], it[3], it[0] - }); - } else if (3 == it.size()) { - m_object->triangles.push_back(it); - } - } - m_object->triangleAndQuads.insert(m_object->triangleAndQuads.end(), clothMesh.faces.begin(), clothMesh.faces.end()); - for (size_t i = 0; i < clothMesh.vertices.size(); ++i) { - const auto &source = clothMesh.vertexSources[i]; - m_nodeVertices.push_back(std::make_pair(clothMesh.vertices[i], source)); - } - } -} - void MeshGenerator::generateSmoothTriangleVertexNormals(const std::vector &vertices, const std::vector> &triangles, const std::vector &triangleNormals, std::vector> *triangleVertexNormals) @@ -1968,25 +1826,6 @@ void MeshGenerator::generate() collectUncombinedComponent(QUuid().toString()); collectIncombinableComponentMeshes(QUuid().toString()); - // Fetch nodes as body nodes before cloth nodes collecting - //std::set> bodyNodeMap; - //m_object->bodyNodes.reserve(m_object->nodes.size()); - //for (const auto &it: m_object->nodes) { - // if (it.joined) { - // bodyNodeMap.insert({it.partId, it.nodeId}); - // m_object->bodyNodes.push_back(it); - // } - //} - //m_object->bodyEdges.reserve(m_object->edges.size()); - //for (const auto &it: m_object->edges) { - // if (bodyNodeMap.find(it.first) == bodyNodeMap.end()) - // continue; - // if (bodyNodeMap.find(it.second) == bodyNodeMap.end()) - // continue; - // m_object->bodyEdges.push_back(it); - //} - - collectClothComponent(QUuid().toString()); collectErroredParts(); postprocessObject(m_object); diff --git a/src/meshgenerator.h b/src/meshgenerator.h index 605c1182..c906138b 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -12,8 +12,6 @@ #include "snapshot.h" #include "combinemode.h" #include "model.h" -#include "componentlayer.h" -#include "clothforce.h" class GeneratedPart { @@ -170,15 +168,7 @@ private: GeneratedComponent &componentCache); MeshCombiner::Mesh *combineMultipleMeshes(const std::vector> &multipleMeshes, bool recombine=true); QString componentColorName(const std::map *component); - ComponentLayer componentLayer(const std::map *component); - float componentClothStiffness(const std::map *component); - size_t componentClothIteration(const std::map *component); - ClothForce componentClothForce(const std::map *component); - float componentClothOffset(const std::map *component); void collectUncombinedComponent(const QString &componentIdString); - void collectClothComponent(const QString &componentIdString); - void collectClothComponentIdStrings(const QString &componentIdString, - std::vector *componentIdStrings); void cutFaceStringToCutTemplate(const QString &cutFaceString, std::vector &cutTemplate); void remesh(const std::vector &inputNodes, const std::vector> &interpolatedNodes, diff --git a/src/object.h b/src/object.h index e883caef..4c1ea2d2 100644 --- a/src/object.h +++ b/src/object.h @@ -8,7 +8,6 @@ #include #include #include "bonemark.h" -#include "componentlayer.h" struct ObjectNode { @@ -26,7 +25,6 @@ struct ObjectNode QUuid mirroredByPartId; BoneMark boneMark = BoneMark::None; QVector3D direction; - ComponentLayer layer = ComponentLayer::Body; bool joined = true; }; diff --git a/src/objectxml.cpp b/src/objectxml.cpp index 05ddc039..269c6678 100644 --- a/src/objectxml.cpp +++ b/src/objectxml.cpp @@ -43,8 +43,6 @@ void saveObjectToXmlStream(const Object *object, QXmlStreamWriter *writer) writer->writeAttribute("mirroredByPartId", node.mirroredByPartId.toString()); if (node.boneMark != BoneMark::None) writer->writeAttribute("boneMark", BoneMarkToString(node.boneMark)); - if (ComponentLayer::Body != node.layer) - writer->writeAttribute("layer", ComponentLayerToString(node.layer)); if (!node.joined) writer->writeAttribute("joined", "false"); writer->writeEndElement(); @@ -250,7 +248,6 @@ void loadObjectFromXmlStream(Object *object, QXmlStreamReader &reader) node.mirrorFromPartId = QUuid(reader.attributes().value("mirrorFromPartId").toString()); node.mirroredByPartId = QUuid(reader.attributes().value("mirroredByPartId").toString()); node.boneMark = BoneMarkFromString(reader.attributes().value("boneMark").toString().toUtf8().constData()); - node.layer = ComponentLayerFromString(reader.attributes().value("layer").toString().toUtf8().constData()); QString joinedString = reader.attributes().value("joined").toString(); if (!joinedString.isEmpty()) node.joined = isTrueValueString(joinedString); diff --git a/src/parttreewidget.cpp b/src/parttreewidget.cpp index 75046e93..b14b5882 100644 --- a/src/parttreewidget.cpp +++ b/src/parttreewidget.cpp @@ -257,119 +257,6 @@ void PartTreeWidget::mousePressEvent(QMouseEvent *event) handleSingleClick(event->pos()); } -void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &componentId) -{ - const Component *component = nullptr; - - if (componentId.isNull()) - return; - - component = m_document->findComponent(componentId); - if (nullptr == component) - return; - - QMenu popupMenu; - - QWidget *popup = new QWidget; - - FloatNumberWidget *clothStiffnessWidget = new FloatNumberWidget; - clothStiffnessWidget->setItemName(tr("Stiffness")); - clothStiffnessWidget->setRange(0.0f, 1.0f); - clothStiffnessWidget->setValue(component->clothStiffness); - - connect(clothStiffnessWidget, &FloatNumberWidget::valueChanged, [=](float value) { - emit setComponentClothStiffness(componentId, value); - emit groupOperationAdded(); - }); - - QPushButton *clothStiffnessEraser = new QPushButton(QChar(fa::eraser)); - Theme::initAwesomeToolButton(clothStiffnessEraser); - - connect(clothStiffnessEraser, &QPushButton::clicked, [=]() { - clothStiffnessWidget->setValue(Component::defaultClothStiffness); - emit groupOperationAdded(); - }); - - QHBoxLayout *clothStiffnessLayout = new QHBoxLayout; - clothStiffnessLayout->addWidget(clothStiffnessEraser); - clothStiffnessLayout->addWidget(clothStiffnessWidget); - - IntNumberWidget *clothIterationWidget = new IntNumberWidget; - clothIterationWidget->setItemName(tr("Iteration")); - clothIterationWidget->setRange(0, 1000); - clothIterationWidget->setValue(component->clothIteration); - - connect(clothIterationWidget, &IntNumberWidget::valueChanged, [=](int value) { - //emit setComponentClothIteration(componentId, value); - //emit groupOperationAdded(); - }); - - QPushButton *clothIterationEraser = new QPushButton(QChar(fa::eraser)); - Theme::initAwesomeToolButton(clothIterationEraser); - - connect(clothIterationEraser, &QPushButton::clicked, [=]() { - clothIterationWidget->setValue(Component::defaultClothIteration); - emit groupOperationAdded(); - }); - - QHBoxLayout *clothIterationLayout = new QHBoxLayout; - clothIterationLayout->addWidget(clothIterationEraser); - clothIterationLayout->addWidget(clothIterationWidget); - - FloatNumberWidget *clothOffsetWidget = new FloatNumberWidget; - clothOffsetWidget->setItemName(tr("Offset")); - clothOffsetWidget->setRange(0.0f, 1.0f); - clothOffsetWidget->setValue(component->clothOffset); - - connect(clothOffsetWidget, &FloatNumberWidget::valueChanged, [=](float value) { - emit setComponentClothOffset(componentId, value); - emit groupOperationAdded(); - }); - - QPushButton *clothOffsetEraser = new QPushButton(QChar(fa::eraser)); - Theme::initAwesomeToolButton(clothOffsetEraser); - - connect(clothOffsetEraser, &QPushButton::clicked, [=]() { - clothOffsetWidget->setValue(0.0); - emit groupOperationAdded(); - }); - - QHBoxLayout *clothOffsetLayout = new QHBoxLayout; - clothOffsetLayout->addWidget(clothOffsetEraser); - clothOffsetLayout->addWidget(clothOffsetWidget); - - QComboBox *clothForceSelectBox = new QComboBox; - for (size_t i = 0; i < (size_t)ClothForce::Count; ++i) { - ClothForce force = (ClothForce)i; - clothForceSelectBox->addItem(ClothForceToDispName(force)); - } - clothForceSelectBox->setCurrentIndex((int)component->clothForce); - connect(clothForceSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - emit setComponentClothForce(component->id, (ClothForce)index); - emit groupOperationAdded(); - }); - QFormLayout *clothForceFormLayout = new QFormLayout; - clothForceFormLayout->addRow(tr("Force"), clothForceSelectBox); - QHBoxLayout *clothForceLayout = new QHBoxLayout; - clothForceLayout->addLayout(clothForceFormLayout); - clothForceLayout->addStretch(); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(clothStiffnessLayout); - //mainLayout->addLayout(clothIterationLayout); - mainLayout->addLayout(clothOffsetLayout); - mainLayout->addLayout(clothForceLayout); - - popup->setLayout(mainLayout); - - QWidgetAction action(this); - action.setDefaultWidget(popup); - - popupMenu.addAction(&action); - - popupMenu.exec(mapToGlobal(pos)); -} - std::vector PartTreeWidget::collectSelectedComponentIds(const QPoint &pos) { std::set unorderedComponentIds = m_selectedComponentIds; @@ -486,33 +373,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted) } } - QHBoxLayout *componentLayerLayout = nullptr; - if (nullptr != component) { - if (nullptr == part || part->hasLayerFunction()) { - QPushButton *clothSettingButton = new QPushButton(); - connect(clothSettingButton, &QPushButton::clicked, this, [=]() { - showClothSettingMenu(mapFromGlobal(QCursor::pos()), component->id); - }); - clothSettingButton->setIcon(Theme::awesome()->icon(fa::gear)); - if (ComponentLayer::Cloth != component->layer) - clothSettingButton->hide(); - QComboBox *componentLayerSelectBox = new QComboBox; - for (size_t i = 0; i < (size_t)ComponentLayer::Count; ++i) { - ComponentLayer layer = (ComponentLayer)i; - componentLayerSelectBox->addItem(ComponentLayerToDispName(layer)); - } - componentLayerSelectBox->setCurrentIndex((int)component->layer); - connect(componentLayerSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { - clothSettingButton->setVisible(ComponentLayer::Cloth == (ComponentLayer)index); - emit setComponentLayer(component->id, (ComponentLayer)index); - emit groupOperationAdded(); - }); - componentLayerLayout = new QHBoxLayout; - componentLayerLayout->addWidget(componentLayerSelectBox); - componentLayerLayout->addWidget(clothSettingButton); - componentLayerLayout->setStretch(0, 1); - } if (nullptr == part || part->hasCombineModeFunction()) { combineModeSelectBox = new QComboBox; @@ -669,8 +530,6 @@ void PartTreeWidget::showContextMenu(const QPoint &pos, bool shorted) componentSettingsLayout->addRow(tr("Target"), partTargetSelectBox); if (nullptr != combineModeSelectBox) componentSettingsLayout->addRow(tr("Mode"), combineModeSelectBox); - if (nullptr != componentLayerLayout) - componentSettingsLayout->addRow(tr("Layer"), componentLayerLayout); QVBoxLayout *newLayout = new QVBoxLayout; newLayout->addLayout(layout); diff --git a/src/parttreewidget.h b/src/parttreewidget.h index 2fe48222..4e75c594 100644 --- a/src/parttreewidget.h +++ b/src/parttreewidget.h @@ -24,7 +24,6 @@ signals: void setComponentSmoothAll(QUuid componentId, float toSmoothAll); void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam); void setComponentPolyCount(QUuid componentId, PolyCount count); - void setComponentLayer(QUuid componentId, ComponentLayer layer); void setPartTarget(QUuid partId, PartTarget target); void setPartBase(QUuid partId, PartBase base); void moveComponent(QUuid componentId, QUuid toParentId); @@ -42,10 +41,6 @@ signals: void setPartVisibleState(QUuid partId, bool visible); void setPartColorState(QUuid partId, bool hasColor, QColor color); void setComponentCombineMode(QUuid componentId, CombineMode combineMode); - void setComponentClothStiffness(QUuid componentId, float clothStiffness); - void setComponentClothIteration(QUuid componentId, size_t iteration); - void setComponentClothForce(QUuid componentId, ClothForce force); - void setComponentClothOffset(QUuid componentId, float offset); void hideDescendantComponents(QUuid componentId); void showDescendantComponents(QUuid componentId); void lockDescendantComponents(QUuid componentId); @@ -91,7 +86,6 @@ public slots: void groupCollapsed(QTreeWidgetItem *item); void removeAllContent(); void showContextMenu(const QPoint &pos, bool shorted=false); - void showClothSettingMenu(const QPoint &pos, const QUuid &componentId); protected: QSize sizeHint() const override; void mousePressEvent(QMouseEvent *event) override; diff --git a/src/partwidget.cpp b/src/partwidget.cpp index 35429e0f..23823567 100644 --- a/src/partwidget.cpp +++ b/src/partwidget.cpp @@ -16,7 +16,6 @@ #include "materiallistwidget.h" #include "infolabel.h" #include "cutface.h" -#include "cutdocument.h" #include "skeletongraphicswidget.h" #include "shortcuts.h" #include "graphicscontainerwidget.h" diff --git a/src/riggenerator.cpp b/src/riggenerator.cpp index 9b8ab68d..988f4a2b 100644 --- a/src/riggenerator.cpp +++ b/src/riggenerator.cpp @@ -149,8 +149,6 @@ void RigGenerator::buildNeighborMap() std::map, size_t> nodeIdToIndexMap; for (size_t i = 0; i < m_object->nodes.size(); ++i) { const auto &node = m_object->nodes[i]; - if (ComponentLayer::Body != node.layer) - continue; nodeIdToIndexMap.insert({{node.partId, node.nodeId}, i}); m_neighborMap.insert({i, {}}); } @@ -220,8 +218,6 @@ void RigGenerator::buildBoneNodeChain() size_t middleStartNodeIndex = m_object->nodes.size(); for (size_t nodeIndex = 0; nodeIndex < m_object->nodes.size(); ++nodeIndex) { const auto &node = m_object->nodes[nodeIndex]; - if (ComponentLayer::Body != node.layer) - continue; if (!BoneMarkIsBranchNode(node.boneMark)) continue; m_branchNodesMapByMark[(int)node.boneMark].push_back(nodeIndex); @@ -655,21 +651,15 @@ void RigGenerator::computeSkinWeights() std::map, size_t> nodeIdToIndexMap; for (size_t nodeIndex = 0; nodeIndex < m_object->nodes.size(); ++nodeIndex) { const auto &node = m_object->nodes[nodeIndex]; - if (ComponentLayer::Body != node.layer) - continue; nodeIdToIndexMap[{node.partId, node.nodeId}] = nodeIndex; } if (!nodeIdToIndexMap.empty()) { for (size_t nonBodyNodeIndex = 0; nonBodyNodeIndex < m_object->nodes.size(); ++nonBodyNodeIndex) { const auto &nonBodyNode = m_object->nodes[nonBodyNodeIndex]; - if (ComponentLayer::Body == nonBodyNode.layer) - continue; std::vector> distance2s; distance2s.reserve(m_object->nodes.size()); for (size_t nodeIndex = 0; nodeIndex < m_object->nodes.size(); ++nodeIndex) { const auto &node = m_object->nodes[nodeIndex]; - if (ComponentLayer::Body != node.layer) - continue; distance2s.push_back(std::make_pair(nodeIndex, (nonBodyNode.origin - node.origin).lengthSquared())); } diff --git a/src/shortestpath.cpp b/src/shortestpath.cpp deleted file mode 100644 index 19a0df37..00000000 --- a/src/shortestpath.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "shortestpath.h" - -using namespace boost; - -bool shortestPath(size_t nodeNum, - const std::vector> &edges, - const std::vector &weights, - size_t start, - size_t stop, - std::vector *path) -{ - typedef adjacency_list < listS, vecS, undirectedS, - no_property, property < edge_weight_t, int > > graph_t; - typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; - typedef graph_traits < graph_t >::edge_descriptor edge_descriptor; - typedef std::pair Edge; - - size_t edgeNum = edges.size(); -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - graph_t g(nodeNum); - property_map::type weightmap = get(edge_weight, g); - for (std::size_t j = 0; j < edgeNum; ++j) { - edge_descriptor e; bool inserted; - tie(e, inserted) = add_edge(edges[j].first, edges[j].second, g); - weightmap[e] = weights[j]; - } -#else - graph_t g(edges.data(), edges.data() + edgeNum, weights.data(), nodeNum); - property_map::type weightmap = get(edge_weight, g); -#endif - - std::vector p(num_vertices(g)); - std::vector d(num_vertices(g)); - vertex_descriptor s = vertex(start, g); - -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // VC++ has trouble with the named parameters mechanism - property_map::type indexmap = get(vertex_index, g); - dijkstra_shortest_paths(g, s, &p[0], &d[0], weightmap, indexmap, - std::less(), closed_plus(), - (std::numeric_limits::max)(), 0, - default_dijkstra_visitor()); -#else - dijkstra_shortest_paths(g, s, predecessor_map(&p[0]).distance_map(&d[0])); -#endif - - auto current = stop; - while (current != start) { - path->push_back(current); - size_t next = p[current]; - if (next == current) - return false; - current = next; - } - path->push_back(current); - - return true; -} diff --git a/src/shortestpath.h b/src/shortestpath.h deleted file mode 100644 index aa1ccce4..00000000 --- a/src/shortestpath.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef DUST3D_SHORTEST_PATH -#define DUST3D_SHORTEST_PATH -#include -#include - -/* - -Example code: - - std::vector nodeNames = { - "A", //0 - "B", //1 - "C", //2 - "D", //3 - "E", //4 - "F" //5 - }; - std::vector> edges = { - {1,0}, - {1,3}, - {1,4}, - {3,4}, - {3,5}, - {4,5}, - {5,2}, - {0,2} - }; - std::vector weights(edges.size(), 1); - weights[7] = 10; - weights[4] = 10; - std::vector path; - shortestPath(nodeNames.size(), edges, weights, 0, 5, &path); - for (const auto &it: path) { - qDebug() << nodeNames[it]; - } - -*/ - -bool shortestPath(size_t nodeNum, - const std::vector> &edges, - const std::vector &weights, - size_t start, - size_t stop, - std::vector *path); - -#endif diff --git a/src/simulateclothmeshes.cpp b/src/simulateclothmeshes.cpp deleted file mode 100644 index f0faf744..00000000 --- a/src/simulateclothmeshes.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include "simulateclothmeshes.h" -#include "positionkey.h" -#include "util.h" -#include "clothsimulator.h" - -class ClothMeshesSimulator -{ -public: - ClothMeshesSimulator(std::vector *clothMeshes, - const std::vector *clothCollisionVertices, - const std::vector> *clothCollisionTriangles) : - m_clothMeshes(clothMeshes), - m_clothCollisionVertices(clothCollisionVertices), - m_clothCollisionTriangles(clothCollisionTriangles) - { - } - void simulate(ClothMesh *clothMesh) const - { - const auto &filteredClothFaces = clothMesh->faces; - std::map> positionMap; - std::pair defaultSource; - for (const auto &it: *clothMesh->objectNodeVertices) { - if (!it.second.first.isNull()) - defaultSource.first = it.second.first; - positionMap.insert({PositionKey(it.first), it.second}); - } - clothMesh->vertexSources.resize(clothMesh->vertices.size(), defaultSource); - for (size_t i = 0; i < clothMesh->vertices.size(); ++i) { - auto findSource = positionMap.find(PositionKey(clothMesh->vertices[i])); - if (findSource == positionMap.end()) - continue; - clothMesh->vertexSources[i] = findSource->second; - } - - std::vector &filteredClothVertices = clothMesh->vertices; - std::vector externalForces; - std::vector postProcessDirections; - const auto &clothForce = clothMesh->clothForce; - float clothOffset = 0.01f + (clothMesh->clothOffset * 0.05f); - if (ClothForce::Centripetal == clothForce) { - externalForces.resize(filteredClothVertices.size()); - postProcessDirections.resize(filteredClothVertices.size()); - for (size_t i = 0; i < filteredClothFaces.size(); ++i) { - const auto &face = filteredClothFaces[i]; - auto faceForceDirection = -polygonNormal(filteredClothVertices, face); - for (const auto &vertex: face) - externalForces[vertex] += faceForceDirection; - } - for (size_t i = 0; i < externalForces.size(); ++i) { - auto &it = externalForces[i]; - it.normalize(); - postProcessDirections[i] = it * clothOffset; - it = (it + QVector3D(0.0f, -1.0f, 0.0f)).normalized(); - } - } else { - postProcessDirections.resize(filteredClothVertices.size(), QVector3D(0.0f, -1.0f, 0.0f) * clothOffset); - externalForces.resize(filteredClothVertices.size(), QVector3D(0.0f, -1.0f, 0.0f)); - } - ClothSimulator clothSimulator(filteredClothVertices, - filteredClothFaces, - *m_clothCollisionVertices, - *m_clothCollisionTriangles, - externalForces); - clothSimulator.setStiffness(clothMesh->clothStiffness); - clothSimulator.create(); - for (size_t i = 0; i < clothMesh->clothIteration; ++i) - clothSimulator.step(); - clothSimulator.getCurrentVertices(&filteredClothVertices); - for (size_t i = 0; i < filteredClothVertices.size(); ++i) { - filteredClothVertices[i] -= postProcessDirections[i]; - } - } - void operator()(const tbb::blocked_range &range) const - { - for (size_t i = range.begin(); i != range.end(); ++i) { - simulate(&(*m_clothMeshes)[i]); - } - } -private: - std::vector *m_clothMeshes = nullptr; - const std::vector *m_clothCollisionVertices = nullptr; - const std::vector> *m_clothCollisionTriangles = nullptr; -}; - -void simulateClothMeshes(std::vector *clothMeshes, - const std::vector *clothCollisionVertices, - const std::vector> *clothCollisionTriangles) -{ - tbb::parallel_for(tbb::blocked_range(0, clothMeshes->size()), - ClothMeshesSimulator(clothMeshes, - clothCollisionVertices, - clothCollisionTriangles)); -} diff --git a/src/simulateclothmeshes.h b/src/simulateclothmeshes.h deleted file mode 100644 index e0db0958..00000000 --- a/src/simulateclothmeshes.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DUST3D_SIMULATE_CLOTH_MESHES_H -#define DUST3D_SIMULATE_CLOTH_MESHES_H -#include -#include -#include -#include "clothforce.h" - -struct ClothMesh -{ - std::vector vertices; - std::vector> faces; - std::vector> vertexSources; - const std::vector>> *objectNodeVertices; - ClothForce clothForce; - float clothOffset; - float clothStiffness; - size_t clothIteration; -}; - -void simulateClothMeshes(std::vector *clothMeshes, - const std::vector *clothCollisionVertices, - const std::vector> *clothCollisionTriangles); - -#endif