@@ -26,21 +26,22 @@ void FlexBuffers::destroy() {
26
26
// clears all particles
27
27
void FlexSolver::reset () {
28
28
reset_cloth ();
29
- copy_particles.elementCount = 0 ;
30
29
copy_active.elementCount = 0 ;
31
30
particle_queue.clear ();
32
31
33
32
// clear diffuse
34
33
NvFlexSetDiffuseParticles (solver, NULL , NULL , 0 );
35
34
hosts.diffuse_count [0 ] = 0 ;
36
35
37
- // These buffers are getted AND setted, so we need to make sure they are mapped before adding more particles
38
- NvFlexMap (buffers.particle_pos , eNvFlexMapWait);
36
+ memset (hosts.particle_lifetime , 0 , sizeof (float ) * get_max_particles ());
37
+
38
+ /*
39
+ NvFlexMap(buffers.particle_pos, eNvFlexMapWait); // These buffers are getted AND setted, so we need to make sure they are mapped before adding more particles
39
40
NvFlexUnmap(buffers.particle_pos);
40
41
if (get_parameter("reaction_forces") > 2) {
41
42
NvFlexMap(buffers.particle_vel, eNvFlexMapWait);
42
43
NvFlexUnmap(buffers.particle_vel);
43
- }
44
+ }*/
44
45
}
45
46
46
47
void FlexSolver::reset_cloth () {
@@ -50,7 +51,7 @@ void FlexSolver::reset_cloth() {
50
51
}
51
52
52
53
int FlexSolver::get_active_particles () {
53
- return copy_particles .elementCount + particle_queue.size ();
54
+ return copy_active .elementCount + particle_queue.size ();
54
55
}
55
56
56
57
int FlexSolver::get_active_triangles () {
@@ -78,33 +79,36 @@ std::vector<FlexMesh>* FlexSolver::get_meshes() {
78
79
}
79
80
80
81
// Resets particle to base parameters
81
- void FlexSolver::set_particle (int index, Particle particle) {
82
- hosts.particle_pos [index] = particle.pos ;
83
- hosts.particle_smooth [index] = particle.pos ;
84
- hosts.particle_vel [index] = particle.vel ;
85
- hosts.particle_phase [index] = particle.phase ;
86
- hosts.particle_active [index] = index;
87
- hosts.particle_ani0 [index] = Vector4D (0 , 0 , 0 , 0 );
88
- hosts.particle_ani1 [index] = Vector4D (0 , 0 , 0 , 0 );
89
- hosts.particle_ani2 [index] = Vector4D (0 , 0 , 0 , 0 );
82
+ void FlexSolver::set_particle (int particle_index, int active_index, Particle particle) {
83
+ hosts.particle_pos [particle_index] = particle.pos ;
84
+ hosts.particle_smooth [particle_index] = particle.pos ;
85
+ hosts.particle_vel [particle_index] = particle.vel ;
86
+ hosts.particle_phase [particle_index] = particle.phase ;
87
+ hosts.particle_lifetime [particle_index] = particle.lifetime ;
88
+ hosts.particle_ani0 [particle_index] = Vector4D (0 , 0 , 0 , 0 );
89
+ hosts.particle_ani1 [particle_index] = Vector4D (0 , 0 , 0 , 0 );
90
+ hosts.particle_ani2 [particle_index] = Vector4D (0 , 0 , 0 , 0 );
91
+ hosts.particle_active [active_index] = particle_index;
90
92
}
91
93
92
94
void FlexSolver::add_particle (Particle particle) {
93
95
if (solver == nullptr ) return ;
94
96
if (get_active_particles () >= get_max_particles ()) return ;
95
97
96
- set_particle (get_active_particles (), particle);
98
+ // set_particle(get_active_particles(), particle);
97
99
particle_queue.push_back (particle);
98
100
}
99
101
100
102
inline int _grid (int x, int y, int x_size) { return y * x_size + x; }
101
- void FlexSolver::add_cloth (Particle particle, Vector2D size) {
103
+ void FlexSolver::add_cloth (Particle particle, Vector2D size) { // TODO: FIX
102
104
float radius = parameters.solidRestDistance ;
103
105
particle.phase = FlexPhase::CLOTH; // force to cloth
106
+ particle.lifetime = FLT_MAX; // no die
104
107
particle.pos .x -= size.x * radius / 2.0 ;
105
108
particle.pos .y -= size.y * radius / 2.0 ;
109
+
106
110
NvFlexCopyDesc desc;
107
- desc.srcOffset = copy_particles .elementCount ;
111
+ desc.srcOffset = copy_active .elementCount ;
108
112
desc.dstOffset = desc.srcOffset ;
109
113
desc.elementCount = 0 ;
110
114
@@ -123,7 +127,7 @@ void FlexSolver::add_cloth(Particle particle, Vector2D size) {
123
127
if (get_active_particles () >= get_max_particles ()) break ;
124
128
125
129
// Add particle
126
- int index = copy_particles .elementCount ++;
130
+ int index = copy_active .elementCount ++;
127
131
particle_pos[index] = particle.pos + Vector4D (x * radius, y * radius, 0 , 0 );
128
132
particle_vel[index] = particle.vel ;
129
133
particle_phase[index] = particle.phase ; // force to cloth
@@ -181,7 +185,7 @@ void FlexSolver::add_cloth(Particle particle, Vector2D size) {
181
185
NvFlexSetVelocities (solver, buffers.particle_vel , &desc);
182
186
NvFlexSetPhases (solver, buffers.particle_phase , &desc);
183
187
NvFlexSetActive (solver, buffers.particle_active , &desc);
184
- NvFlexSetActiveCount (solver, copy_particles .elementCount );
188
+ NvFlexSetActiveCount (solver, copy_active .elementCount );
185
189
NvFlexSetDynamicTriangles (solver, buffers.triangle_indices , NULL , copy_triangles.elementCount );
186
190
NvFlexSetSprings (solver, buffers.spring_indices , buffers.spring_restlengths , buffers.spring_stiffness , copy_springs.elementCount );
187
191
}
@@ -224,31 +228,49 @@ bool FlexSolver::tick(float dt, NvFlexMapFlags wait) {
224
228
225
229
// Avoid ticking if the deltatime ends up being zero, as it invalidates the simulation
226
230
dt *= get_parameter (" timescale" );
227
- if (dt > 0 && get_active_particles () > 0 ) {
231
+ if (dt > 0 && (get_active_particles () > 0 || get_active_diffuse () > 0 )) {
232
+
233
+ // Invalidate particles with bad lifetimes
234
+ // TODO: This could potentially be modified to work in a compute shader during FleX updates, would this be faster? (is this algorithm even parallelizable?)
235
+ bool active_modified = false ;
236
+ for (int i = 0 ; i < copy_active.elementCount ; i++) {
237
+ float & particle_life = hosts.particle_lifetime [hosts.particle_active [i]];
238
+ particle_life -= dt;
239
+ if (particle_life <= 0 ) {
240
+ hosts.particle_active [i] = hosts.particle_active [--copy_active.elementCount ];
241
+ active_modified = true ;
242
+ i--; // we just shifted a particle that wont be iterated over, go back and check it
243
+ }
244
+ }
245
+
228
246
// Map positions to CPU memory
229
247
if (!particle_queue.empty ()) {
248
+ // These are both getted AND setted, so we *have* to map them
249
+ NvFlexGetVelocities (solver, buffers.particle_vel , NULL );
250
+ hosts.particle_pos = (Vector4D*)NvFlexMap (buffers.particle_pos , eNvFlexMapWait);
251
+ hosts.particle_vel = (Vector*)NvFlexMap (buffers.particle_vel , eNvFlexMapWait);
230
252
// Add queued particles
231
- for (int i = 0 ; i < particle_queue.size (); i++) {
232
- int particle_index = copy_particles.elementCount + i;
233
- // particle_pos[particle_index] = particle_queue[i].pos;
234
- set_particle (particle_index, particle_queue[i]);
253
+ int particle_index = 0 ;
254
+ for (int i = 0 ; particle_index < particle_queue.size () && i < get_max_particles (); i++) {
255
+ if (hosts.particle_lifetime [i] <= 0 ) {
256
+ set_particle (i, copy_active.elementCount ++, particle_queue[particle_index++]);
257
+ }
235
258
}
259
+ NvFlexUnmap (buffers.particle_pos );
260
+ NvFlexUnmap (buffers.particle_vel );
236
261
237
- // Only copy what we just added
238
- NvFlexCopyDesc desc;
239
- desc.dstOffset = copy_particles.elementCount ;
240
- desc.elementCount = particle_queue.size ();
241
- desc.srcOffset = desc.dstOffset ;
242
-
243
- copy_particles.elementCount += particle_queue.size ();
244
262
particle_queue.clear ();
245
-
263
+
246
264
// Update particle information
247
- NvFlexSetParticles (solver, buffers.particle_pos , &desc);
248
- NvFlexSetVelocities (solver, buffers.particle_vel , &desc);
249
- NvFlexSetPhases (solver, buffers.particle_phase , &desc);
250
- NvFlexSetActive (solver, buffers.particle_active , &desc);
251
- NvFlexSetActiveCount (solver, copy_particles.elementCount );
265
+ NvFlexSetParticles (solver, buffers.particle_pos , NULL );
266
+ NvFlexSetVelocities (solver, buffers.particle_vel , NULL );
267
+ NvFlexSetPhases (solver, buffers.particle_phase , NULL );
268
+ active_modified = true ;
269
+ }
270
+
271
+ if (active_modified) {
272
+ NvFlexSetActive (solver, buffers.particle_active , ©_active);
273
+ NvFlexSetActiveCount (solver, copy_active.elementCount );
252
274
}
253
275
254
276
// write to device (async)
@@ -269,23 +291,23 @@ bool FlexSolver::tick(float dt, NvFlexMapFlags wait) {
269
291
NvFlexUpdateSolver (solver, dt, (int )get_parameter (" substeps" ), false );
270
292
271
293
// read back (async)
272
- NvFlexGetParticles (solver, buffers.particle_pos , ©_particles );
294
+ NvFlexGetParticles (solver, buffers.particle_pos , NULL );
273
295
NvFlexGetDiffuseParticles (solver, buffers.diffuse_pos , buffers.diffuse_vel , buffers.diffuse_count );
274
296
275
297
if (get_active_triangles () > 0 ) {
276
- NvFlexGetNormals (solver, buffers.triangle_normals , ©_particles );
298
+ NvFlexGetNormals (solver, buffers.triangle_normals , NULL );
277
299
}
278
300
279
301
if (parameters.anisotropyScale != 0 ) {
280
- NvFlexGetAnisotropy (solver, buffers.particle_ani0 , buffers.particle_ani1 , buffers.particle_ani2 , ©_particles );
302
+ NvFlexGetAnisotropy (solver, buffers.particle_ani0 , buffers.particle_ani1 , buffers.particle_ani2 , NULL );
281
303
}
282
304
283
305
if (parameters.smoothing != 0 ) {
284
- NvFlexGetSmoothParticles (solver, buffers.particle_smooth , ©_particles );
306
+ NvFlexGetSmoothParticles (solver, buffers.particle_smooth , NULL );
285
307
}
286
308
287
309
if (get_parameter (" reaction_forces" ) > 1 ) {
288
- NvFlexGetVelocities (solver, buffers.particle_vel , ©_particles );
310
+ NvFlexGetVelocities (solver, buffers.particle_vel , NULL );
289
311
NvFlexGetContacts (solver, buffers.contact_planes , buffers.contact_vel , buffers.contact_indices , buffers.contact_count );
290
312
}
291
313
@@ -542,7 +564,12 @@ FlexSolver::FlexSolver(NvFlexLibrary* library, int particles) {
542
564
buffers.spring_restlengths = buffers.init (library, &hosts.spring_restlengths , particles * 2 );
543
565
buffers.spring_stiffness = buffers.init (library, &hosts.spring_stiffness , particles * 2 );
544
566
567
+ // This is the only exception buffer, as it is never sent to the GPU
568
+ hosts.particle_lifetime = (float *)malloc (sizeof (float ) * particles);
569
+
545
570
force_field_callback = NvFlexExtCreateForceFieldCallback (solver);
571
+
572
+ reset ();
546
573
};
547
574
548
575
// Free memory
@@ -562,6 +589,7 @@ FlexSolver::~FlexSolver() {
562
589
563
590
// Free buffers / hosts
564
591
buffers.destroy ();
592
+ free ((void *)hosts.particle_lifetime );
565
593
566
594
NvFlexDestroySolver (solver); // bye bye solver
567
595
solver = nullptr ;
0 commit comments