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:

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);
    }
}
Les conteneurs dans ParticleSystem.h

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
std::vector<std::shared_ptr<Particle>> mParticles;
        std::vector<ParticleContact> mParticleContacts;
et la classe ParticleContact

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;
};