2

C++ で効率的な粒子システムを考える必要があります。これは、力が適用された多数の粒子を処理します。

要件は次のとおりです。

  • 大量のパーティクルとフォースを動的に効率的に作成および破棄します。

  • パーティクルは、x/y/z 位置と速度、質量、空気摩擦、およびその他のプロパティを保存します。

  • パーティクルを拡張する必要はありません (継承グラフはありません)。

  • フォースは、主に getAcceleration() 仮想メソッドを持つポリモーフィック オブジェクトです。

  • 1 つのパーティクルに複数の力を適用することも、まったく適用しないこともできます。

  • 1 つの力は 1 つの粒子にのみ適用されます。この粒子が消滅すると、その力はもはや意味を持たなくなり、削除する必要があります。

  • 力には、複数の粒子 (力が適用されるものを含む) が含まれる場合があります。

  • 1 つのパーティクルが消滅する (除去される) と、フォースのタイプに応じて、それに関連するフォースも消滅する場合と消滅しない場合があります。

  • エンジンは、計算を実行するために、各フレームですべてのパーティクルとすべての力を反復処理できる必要があります。

適切に維持および拡張できるように、適切で明確なオブジェクト モデルが必要です。

追加情報:

力を表示することができるので (画面上に小さな矢印を描く)、それらを実際のオブジェクトとしてモデル化するとよいでしょう。
通常、パーティクルは「物理オブジェクト」によって作成されます。このオブジェクトは、1 つまたは複数のパーティクルを作成し (それらに力を適用)、必要なときにいつでも削除できます (物理オブジェクトが動かなくなった場合、画面から離れた場合、またはその他の理由)。 .
(ただし、力は「物理オブジェクト」によってのみ作成されるわけではないことに注意してください。)

これまでのところ、動的割り当てを最小限に抑えようとする草案にたどり着きました。動的割り当ては遅く、毎秒大量のパーティクルが出現して消滅する可能性が高いからです。

#include <vector>

typedef double nb_t;

struct Particle {
    nb_t x, y;
    nb_t sx, sy;
    nb_t mass;
    nb_t air_friction;
};

class Force {
public:
    virtual nb_t get_x_component() = 0;
    virtual nb_t get_y_component() = 0;
    virtual ~Force() = 0;
};

class Engine {
protected:
    std::vector<Particle> particles;
    std::vector<Force*> forces;
public:
    void refresh();
    void addParticle(Particle& p);
    void removeParticle(int index);
    // ...
};

しかし、では、粒子の所有者 (より正確にはその作成者である物理オブジェクト) は、どのようにしてその粒子を追跡し、その除去を命令できるのでしょうか?
スマート ポインターは便利だと思いますが、参照カウントが適切かどうかはわかりません。死亡したパーティクルはメモリから即座に削除して、他のパーティクルを割り当てられるようにする必要があるためです。

また、順序に関係なく (ベクトルのように) オブジェクトを配列に格納する STL コンテナーはありませんか (unordered_vector?)、削除しようとする要素の代わりに最後の要素を配置します。要素の削除は、次のすべての要素を翻訳する必要はありませんか?

何が一番いいと思いますか?効率性、明快さ、およびスケーラビリティを維持するために、どのような妥協案が考えられますか?

4

2 に答える 2

1

オブジェクトの作成と削除に関しては、new または delete を呼び出したくないか、これを最小限に抑えようとします。この最小化は、メモリ プールを作成し、それをオブジェクトの割り当てに使用することで実現できます。

1 つはパーティクル用、もう 1 つはフォース用のオブジェクトのプールが必要なようです。

http://pastie.org/private/ivmu9ogvrf5vurjrwuqmka

このコードは非常に単純で、あまり堅牢ではないメモリ プールですが、実装方法についてより良いアイデアが得られる可能性があります。

于 2012-07-11T19:03:56.247 に答える
0

ここにアーキテクチャに関する小さな観察があります。メモリ管理自体の問題については他の人に対処させます

仮想呼び出しは一度にできるだけ多くのパーティクルを処理する必要があるため、単一のgetAcceleration()インターフェイスをより密度の高いものcomputeAccelerationsForParticles( std::vector<int>& particleIndices)computeAccelerationsForParticles( ParticleGroup& particleGroup). このようにして、仮想呼び出しのオーバーヘッドは、パーティクルごとに 1 回からフォース グループごとに 1 回に分散されます。

このアーキテクチャは、力グループごとに粒子を追跡する必要があることを意味します。パーティクル固有のデータ (フォースなど) を表示する場合は、が null でない場合にのみ更新されるパーティクル デバッグ構造を追加して、「ウィンドウレス」シミュレーションを実行するときにそのオーバーヘッドを取得しないようにすることができます。

于 2012-07-11T20:02:45.203 に答える