Bonjour,
Je suis actuellement entrain d'implémenter un système de particules dans un environement en 2D. Pour le moment le programme peut traiter environ 2 000 particules avant de commencer a ramer. Je commence a être a cours d'idée sur les optimisations que je peut faire pour augmenter le nombre de particules. J'ai donc plusieurs questions :
- Le conteneur choisis pour les particules vous semble t-il correct ?
- La répartition des particules dans une grille est-elle correct ?
- Est que une ligne de code vous parait bizarre ?
En vous remerciant d'avance pour vos aides
Le code:
Les conteneurs dans ParticleSystem.h
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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); } }
et la classe ParticleContact
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 std::vector<std::shared_ptr<Particle>> mParticles; std::vector<ParticleContact> mParticleContacts;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class ParticleContact { public: ParticleContact() {} ParticleContact(int p1, int p2, float distance, float weight) { mParticule1 = p1; mParticule2 = p2; mDistance = distance; mWeight = weight; } virtual ~ParticleContact() {} int mParticule1; int mParticule2; float mDistance; float mWeight; };
Partager