2

我需要在 C++ 中构思一个高效的粒子系统,它可以处理大量粒子并施加力。

以下是要求:

  • 动态地高效地创建和销毁大量粒子和力。

  • 粒子存储 x/y/z 位置和速度、质量、空气摩擦力以及可能的其他一些其他属性。

  • 粒子不需要扩展(没有继承图)。

  • 力是多态对象,主要有一个 getAcceleration() 虚拟方法。

  • 可以对一个粒子施加多个力或不施加力。

  • 一种力只作用于一个粒子,当这个粒子死亡时,力就没有意义了,应该删除。

  • 一个力可以涉及多个粒子(包括它所施加的那个)。

  • 当一个粒子死亡(被移除)时,涉及它的力可能也会也可能不会死亡,具体取决于力的类型。

  • 引擎必须能够在每一帧迭代所有粒子和所有力才能执行计算

我想要一个漂亮而清晰的对象模型,以便它可以很好地维护和扩展。

附加信息:

可以显示力(在屏幕上绘制小箭头),因此将它们建模为真实对象可能会很好。
粒子通常由“物理对象”创建,该对象创建一个或多个粒子(对它们施加力)并且可以随时移除它们(如果物理对象变得不动,如果它离开屏幕,或任何原因) .
(请注意,力不仅是由“物理对象”产生的。)

到目前为止,我已经完成了一个尝试最小化动态分配的草案,因为它们很慢,并且粒子可能每秒都会大量出现和死亡。

#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,或尝试将其最小化。这种最小化可以通过创建一个内存池并将其用于对象分配来实现。

看起来你想要一个用于粒子的对象池和一个用于力的对象池。

http://pastie.org/private/ivmu9ogvrf5vurjrwuqmka

该代码是一个非常简单且不太健壮的内存池,但可以为您提供一些关于如何实现它的更好的想法。

于 2012-07-11T19:03:56.247 回答
0

以下是关于架构的一些小观察,我会让其他人解决内存管理本身的问题

虚拟调用需要一次处理尽可能多的粒子,因此您可能希望getAcceleration()通过更密集的东西重新考虑您的单个界面,例如computeAccelerationsForParticles( std::vector<int>& particleIndices)or computeAccelerationsForParticles( ParticleGroup& particleGroup)。通过这种方式,虚拟呼叫的开销从每个粒子一次到每个力组一次

这种架构意味着您需要按力组跟踪粒子。如果您想显示粒子特定数据(如力),您可以添加一个粒子调试结构,该结构仅在不为空时更新,因此在进行“无窗口”模拟时不会获得该开销

于 2012-07-11T20:02:45.203 回答