#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->outcomeNodeVertices) { 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)); }