25 int _num_particles_width,
26 int _num_particles_height,
29 double _smoothThreshold,
30 double _heightThreshold,
33 : constraint_iterations(rigidness),
35 smoothThreshold(_smoothThreshold),
36 heightThreshold(_heightThreshold),
37 num_particles_width(_num_particles_width),
38 num_particles_height(_num_particles_height),
39 origin_pos(_origin_pos),
49 double time_step2 = time_step * time_step;
109 unsigned vertCount =
static_cast<unsigned>(
getSize());
120 for (
int i = 0; i <
getSize(); ++i) {
121 const Particle& particle = particles[i];
147 int particleCount =
static_cast<int>(particles.size());
149 #pragma omp parallel for
150 for (
int i = 0; i < particleCount; i++) {
151 particles[i].timeStep();
158 #pragma omp parallel for
159 for (
int j = 0; j < particleCount; j++) {
160 particles[j].satisfyConstraintSelf(constraint_iterations);
177 for (
int i = 0; i < particleCount; i++) {
178 if (particles[i].isMovable()) {
179 double diff =
std::abs(particles[i].old_pos.y - particles[i].pos.y);
180 if (diff > maxDiff) maxDiff = diff;
188 int particleCount =
static_cast<int>(particles.size());
191 #pragma omp parallel for
192 for (
int i = 0; i < particleCount; i++) {
193 particles[i].addForce(direction);
199 assert(particles.size() == heightvals.size());
201 int particleCount =
static_cast<int>(particles.size());
202 #pragma omp parallel for
203 for (
int i = 0; i < particleCount; i++) {
220 std::vector<XY> connected;
221 std::vector<std::vector<int>> neibors;
225 connected.push_back(
XY(x, y));
226 particles[index].isVisited =
true;
229 while (!que.empty()) {
230 Particle& ptc_f = particles[que.front()];
232 int cur_x = ptc_f.
pos_x;
233 int cur_y = ptc_f.
pos_y;
234 std::vector<int> neighbor;
242 connected.push_back(
XY(cur_x - 1, cur_y));
245 neighbor.push_back(sum - 1);
246 ptc_left.
c_pos = sum - 1;
248 neighbor.push_back(ptc_left.
c_pos);
259 connected.push_back(
XY(cur_x + 1, cur_y));
262 neighbor.push_back(sum - 1);
263 ptc_right.
c_pos = sum - 1;
265 neighbor.push_back(ptc_right.
c_pos);
276 connected.push_back(
XY(cur_x, cur_y - 1));
279 neighbor.push_back(sum - 1);
280 ptc_bottom.
c_pos = sum - 1;
282 neighbor.push_back(ptc_bottom.
c_pos);
293 connected.push_back(
XY(cur_x, cur_y + 1));
296 neighbor.push_back(sum - 1);
297 ptc_top.
c_pos = sum - 1;
299 neighbor.push_back(ptc_top.
c_pos);
303 neibors.push_back(neighbor);
308 std::vector<int> edgePoints;
319 const std::vector<double>& heightvals,
320 std::vector<int>& edgePoints) {
321 for (
size_t i = 0; i < connected.size(); i++) {
322 int x = connected[i].x;
323 int y = connected[i].y;
330 if (
std::abs(heightvals[index] - heightvals[index_ref]) <
332 ptc.
pos.
y - heightvals[index] < heightThreshold) {
333 Vec3 offsetVec(0, heightvals[index] - ptc.
pos.
y, 0);
334 particles[index].offsetPos(offsetVec);
336 edgePoints.push_back(
static_cast<int>(i));
346 if (
std::abs(heightvals[index] - heightvals[index_ref]) <
348 ptc.
pos.
y - heightvals[index] < heightThreshold) {
349 Vec3 offsetVec(0, heightvals[index] - ptc.
pos.
y, 0);
350 particles[index].offsetPos(offsetVec);
352 edgePoints.push_back(
static_cast<int>(i));
362 if (
std::abs(heightvals[index] - heightvals[index_ref]) <
364 ptc.
pos.
y - heightvals[index] < heightThreshold) {
365 Vec3 offsetVec(0, heightvals[index] - ptc.
pos.
y, 0);
366 particles[index].offsetPos(offsetVec);
368 edgePoints.push_back(
static_cast<int>(i));
378 if (
std::abs(heightvals[index] - heightvals[index_ref]) <
380 ptc.
pos.
y - heightvals[index] < heightThreshold) {
381 Vec3 offsetVec(0, heightvals[index] - ptc.
pos.
y, 0);
382 particles[index].offsetPos(offsetVec);
384 edgePoints.push_back(
static_cast<int>(i));
394 const std::vector<XY>& connected,
395 const std::vector<std::vector<int>>& neibors,
396 const std::vector<double>& heightvals) {
397 std::vector<bool> visited(connected.size(),
false);
400 for (
size_t i = 0; i < edgePoints.size(); i++) {
401 que.push(edgePoints[i]);
402 visited[edgePoints[i]] =
true;
405 while (!que.empty()) {
406 int index = que.front();
411 for (
size_t i = 0; i < neibors[index].size(); i++) {
414 connected[neibors[index][i]].x;
415 if (
std::abs(heightvals[index_center] - heightvals[index_neibor]) <
417 fabs(particles[index_neibor].pos.y - heightvals[index_neibor]) <
420 heightvals[index_neibor] -
421 particles[index_neibor].pos.y,
423 particles[index_neibor].offsetPos(offsetVec);
424 particles[index_neibor].makeUnmovable();
425 if (visited[neibors[index][i]] ==
false) {
426 que.push(neibors[index][i]);
427 visited[neibors[index][i]] =
true;
435 std::string filepath =
"cloth_nodes.txt";
437 filepath =
"cloth_nodes.txt";
441 std::ofstream f1(filepath);
444 for (
size_t i = 0; i < particles.size(); i++) {
446 f1 << std::fixed << std::setprecision(8) << particles[i].pos.x <<
" "
447 << particles[i].pos.z <<
" " << -particles[i].pos.y <<
std::endl;
454 std::string filepath =
"cloth_movable.txt";
456 filepath =
"cloth_movable.txt";
460 std::ofstream f1(filepath);
462 for (
size_t i = 0; i < particles.size(); i++) {
463 if (particles[i].isMovable())
464 f1 << std::fixed << std::setprecision(8) << particles[i].pos.x
465 <<
" " << particles[i].pos.z <<
" " << -particles[i].pos.y
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
void saveToFile(std::string path="")
void addForce(const Vec3 &direction)
void findUnmovablePoint(const std::vector< XY > &connected, const std::vector< double > &heightvals, std::vector< int > &edgePoints)
void saveMovableToFile(std::string path="")
Cloth(const Vec3 &origin_pos, int num_particles_width, int num_particles_height, double step_x, double step_y, double smoothThreshold, double heightThreshold, int rigidness, double time_step)
void handle_slop_connected(const std::vector< int > &edgePoints, const std::vector< XY > &connected, const std::vector< std::vector< int >> &neighbors, const std::vector< double > &heightvals)
Particle & getParticle(int x, int y)
ccMesh * toMesh() const
Converts the cloth to a CC mesh structure.
void offsetPos(const Vec3 v)
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
bool reserve(std::size_t n)
Reserves the memory to store the vertex indexes (3 per triangle)
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
virtual void setEnabled(bool state)
Sets the "enabled" property.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
__host__ __device__ float2 fabs(float2 v)
__host__ __device__ int2 abs(int2 v)
QTextStream & endl(QTextStream &stream)
static const std::string path