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
| void ParticleSystem::computeParticles(Map *pMap)
{
int widthCell = 32;
int heightCell = 32;
int nbCellWidth = pMap->WIDTH * 32 / widthCell + 1;
int nbCellHeight = pMap->HEIGHT * 32 / heightCell + 1;
std::vector<int> grid[nbCellHeight][nbCellWidth];
for(int i = 0; i<mParticles.size(); i++){
int x = mParticles[i]->mPositionY/heightCell;
int y = mParticles[i]->mPositionX/widthCell;
grid[x][y].push_back(i);
}
// trouver les particules voisines
for(int i = 0; i<nbCellHeight; i++)
for(int j = 0; j<nbCellWidth; j++)
{
while(!grid[i][j].empty()){
int particule = grid[i][j].back(); // remove particle par la fin pour O(1)
grid[i][j].pop_back();
for(int x = -1; x<=1; x++){
for(int y = -1; y<=1; y++){
int a = i + x;
int b = j + y;
if(a < 0 || a >=nbCellHeight || b < 0 || b >= nbCellWidth)
continue;
for(int z = 0; z<grid[a][b].size(); z++)
{
int voisin = grid[a][b][z];
float dx = mParticles[voisin]->mPositionX - mParticles[particule]->mPositionX;
float dy = mParticles[voisin]->mPositionY - mParticles[particule]->mPositionY;
float distance2 = dx * dx + dy * dy;
if(distance2 < mParticleWidth * mParticleWidth){
float distance = sqrt(distance2);
float weight = (1.0f-distance/mParticleWidth);
ParticleContact contact(particule, voisin, distance, weight);
mParticleContacts.push_back(contact);
}
}
}
}
mParticles[particule]->mDensity=0.0f;
mParticles[particule]->mPressure=0.0f;
mParticles[particule]->mVelocityY -= GRAVITY;
}
}
// compute density
for(int i = 0; i<mParticleContacts.size(); i++){
int p1 = mParticleContacts[i].mParticule1;
int p2 = mParticleContacts[i].mParticule2;
mParticles[p1]->mDensity += mParticleContacts[i].mWeight;
mParticles[p2]->mDensity += mParticleContacts[i].mWeight;
}
while(!mParticleContacts.empty()){
ParticleContact contact = mParticleContacts.back();
mParticleContacts.pop_back();
int p1 = contact.mParticule1;
int p2 = contact.mParticule2;
//compute pressure
mParticles[p1]->mPressure = std::max(0.0f, n * (mParticles[p1]->mDensity - w0));
mParticles[p2]->mPressure = std::max(0.0f, n * (mParticles[p2]->mDensity - w0));
//compute force
float nX = (mParticles[p2]->mPositionX - mParticles[p1]->mPositionX)/contact.mDistance;
float nY = (mParticles[p2]->mPositionY - mParticles[p1]->mPositionY)/contact.mDistance;
mParticles[p1]->mVelocityX += TIME_STEP * a * (mParticles[p1]->mPressure + mParticles[p2]->mPressure)
* contact.mWeight * nX;
mParticles[p1]->mVelocityY += TIME_STEP * a * (mParticles[p1]->mPressure + mParticles[p2]->mPressure)
* contact.mWeight * nY;
mParticles[p2]->mVelocityX += TIME_STEP * a * (mParticles[p1]->mPressure + mParticles[p2]->mPressure)
* contact.mWeight * -nX;
mParticles[p2]->mVelocityY += TIME_STEP * a * (mParticles[p1]->mPressure + mParticles[p2]->mPressure)
* contact.mWeight * -nY;
mParticles[p1]->mVelocityX += TIME_STEP * VISCOSITY * (mParticles[p2]->mVelocityX - mParticles[p1]->mVelocityX);
mParticles[p1]->mVelocityY += TIME_STEP * VISCOSITY * (mParticles[p2]->mVelocityY - mParticles[p1]->mVelocityY);
mParticles[p2]->mVelocityX += TIME_STEP * VISCOSITY * (mParticles[p1]->mVelocityX - mParticles[p2]->mVelocityX);
mParticles[p2]->mVelocityY += TIME_STEP * VISCOSITY * (mParticles[p1]->mVelocityY - mParticles[p2]->mVelocityY);
}
// update position
for (int i = 0; i < mParticles.size(); ++i) {
mParticles[i]->updatePosition(pMap ,TIME_STEP);
}
} |
Partager