-
Notifications
You must be signed in to change notification settings - Fork 23
/
Simulation.cpp
132 lines (107 loc) · 4.41 KB
/
Simulation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <NvFlex.h>
#include <NvFlexExt.h>
#include <NvFlexDevice.h>
#include "declarations.h"
#include "types.h"
#include <string>
#include <random>
void sleep(int sec) {
std::this_thread::sleep_for(std::chrono::milliseconds(sec));
}
using namespace std::chrono;
steady_clock::time_point curtime() {
return std::chrono::high_resolution_clock::now();
}
void FLEX_API::flexSolveThread() {
//runs always while sim is active
NvFlexCopyDesc copyDesc;
copyDesc.dstOffset = 0;
copyDesc.srcOffset = 0;
int waterPhase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid);
int particleLoop = 0;
while (SimValid) {
//no work to do yet
float fps = 1.f / *flexMap["simFPS"];
if (!ParticleCount && !particleQueue.size() || !simTimescale) {
sleep(fps * 1000.f);
continue;
}
bufferMutex->lock();
//grab current time vs time it takes to iterate through everything
steady_clock::time_point timeStart = curtime();
//because we are in a buffer lock, the simulation might have already been shut down (even with the while loop check!)
if (!SimValid) {
bufferMutex->unlock();
break;
}
mapBuffers();
//loop through queue and add requested particles (AndrewEathan was here)
if (particleQueue.size()) {
for (Particle& particle : particleQueue) {
if (ParticleCount >= flexSolverDesc.maxParticles) {
if (flexSolverDesc.maxParticles <= 0) break;
int offset = (ParticleCount + particleLoop) % flexSolverDesc.maxParticles;
simBuffers->particles[offset] = particle.pos;
simBuffers->velocities[offset] = particle.vel;
simBuffers->phases[offset] = waterPhase;
simBuffers->activeIndices[offset] = offset;
particleLoop = (particleLoop + 1) % flexSolverDesc.maxParticles;
continue;
}
//apply data from queue
simBuffers->particles[ParticleCount] = particle.pos;
simBuffers->velocities[ParticleCount] = particle.vel;
simBuffers->phases[ParticleCount] = waterPhase;
simBuffers->activeIndices[ParticleCount] = ParticleCount;
ParticleCount++;
}
particleQueue.clear();
}
//update prop positions (start at 1 because world never moves)
for (int i = 1; i < props.size(); i++) {
Prop* prop = &props[i];
simBuffers->positions[i] = prop->pos;
simBuffers->rotations[i] = prop->ang;
simBuffers->prevPositions[i] = prop->lastPos;
simBuffers->prevRotations[i] = prop->lastAng;
prop->lastPos = prop->pos;
prop->lastAng = prop->ang;
}
//copy to particle host to be used in rendering
memcpy(particleBufferHost, simBuffers->particles, sizeof(float4) * ParticleCount);
//unmap buffers
unmapBuffers();
//write to device (async)
NvFlexSetParticles(flexSolver, particleBuffer, NULL);
NvFlexSetVelocities(flexSolver, velocityBuffer, NULL);
NvFlexSetPhases(flexSolver, phaseBuffer, NULL);
NvFlexSetActive(flexSolver, activeBuffer, NULL);
NvFlexSetSprings(flexSolver, indicesBuffer, lengthsBuffer, coefficientsBuffer, springCount);
NvFlexSetActiveCount(flexSolver, ParticleCount);
NvFlexSetShapes(flexSolver, geometryBuffer, geoPosBuffer, geoQuatBuffer, geoPrevPosBuffer, geoPrevQuatBuffer, geoFlagsBuffer, PropCount);
NvFlexSetParams(flexSolver, flexParams);
NvFlexExtSetForceFields(forceFieldData->forceFieldCallback, forceFieldData->forceFieldBuffer, forceFieldData->forceFieldCount);
//NvFlexSetDiffuseParticles(flexSolver, diffusePosBuffer, diffuseVelBuffer, diffuseCount);
//grab end time
milliseconds diff = duration_cast<milliseconds>(curtime() - timeStart);
//tick the solver
NvFlexUpdateSolver(flexSolver, fps * 8 * simTimescale + (float)(diff.count()) / 1000.f, 3, false);
copyDesc.elementCount = ParticleCount;
NvFlexGetParticles(flexSolver, particleBuffer, ©Desc);
NvFlexGetVelocities(flexSolver, velocityBuffer, ©Desc);
NvFlexGetPhases(flexSolver, phaseBuffer, ©Desc);
NvFlexGetActive(flexSolver, activeBuffer, ©Desc);
NvFlexGetDiffuseParticles(flexSolver, diffusePosBuffer, NULL, diffuseSingleBuffer);
// get diffuse particles data (we never set it)
int* particleCount = (int*)NvFlexMap(diffuseSingleBuffer, eNvFlexMapWait);
float4* particlePos = (float4*)NvFlexMap(diffusePosBuffer, eNvFlexMapWait);
diffuseCount = particleCount[0];
memcpy(diffuseBufferHost, particlePos, sizeof(float4) * diffuseCount);
NvFlexUnmap(diffuseSingleBuffer);
NvFlexUnmap(diffusePosBuffer);
//dont forget to unlock our buffer
bufferMutex->unlock();
//sleep until next frame
sleep(fps * 1000.f);
}
}