Hi,
Particles are not allocated individually for efficiency, they are
allocated in bulk inside a group. Since allocation is expensive and it
is expected that particles will be created and destroyed in large
quantities, this makes things fast. Typically a particle system
reaches an equilibrium where particles are being created and destroyed
at roughly the same rate. In this state no memory allocation occurs as
lepton keeps enough memory allocated to hold the maximum number of
particles that have been alive at once.
Groups never get smaller, so if you had 100,000 particles alive and
you now have none, there is still space for 100k particles allocated
so long as the groups exist. It is assumed that if you needed 100k
particles before, you will probably need that many again in the near
future, so it holds onto the memory in anticipation of more particles.
However, if the group objects are deleted -- removed from the particle
system and no longer referenced from your program anywhere -- the
space for the particles is freed.
I think the only time it would be desirable to deallocate particle
space would be if you did some one-time special effects (such as a
cut-scene, intro, etc) which needed to create a huge amount of
particles and then you needed the memory for other things. In this
case I would suggest creating a separate particle system containing
all the groups, emitters etc. that you need. These could be stored in
a single object in your game. When you are done, you would delete the
top-level object and all of the memory devoted to the particle system
and its groups would be freed.
Note that only particle groups use an appreciable amount of memory.
Objects like emitters, controllers, renderers and systems are very
small. Particles use about 144 bytes of memory apiece, so 100k
particles would require a little under 14MB of memory, not a lot on
today's machines. Lepton is deliberately built for speed over other
considerations, such as frugal use of memory, though the fact that
particles are allocated in bulk at the C-level (rather than being
individual python objects) means there is almost no per-particle
memory overhead.
-Casey
P.S. If you come up with any interesting particle effects you would
like to share, I'd love to see screenshots and better yet sample code.
There's always room for more interesting examples that ship with
lepton.
Thanks. I hope to make some time soon to finish off some features for
a 0.7a release. There are a lot of good improvements since 0.6a.
> I've built an explosion effect generator into my small 2d app now, based on
> the splode.py example, and it's looking pretty nice. But, I'm now trying to
> build a directional explosion generator, and I've run into a problem. I've
> worked out the parameters I need to emit particles in a nice expanding cone
> (a muzzle flash-type flare effect), but I need the cone of particles to be
> emittable in any arbitrary direction, so:
> -- Is there a way to specify an angle/direction of emission for particles
> out of an emitter? I can use the velocity attribute of the template
> particle to give it a direction, but I need to be able to specify deviation
> information parallel and perpendicular to it's direction of travel, rather
> than in the x/y directions. Maybe the attached diagram will help explain
> the problem. I'm trying to achieve non-axis aligned particle deviations.
> Is this possible?
It is possible, though it is perhaps not as straightforward as it
could be. Eventually we will have a cone shaped domain that can be
used as a source for velocity values, until then you can use the
velocity deviation.
A simple approximation would be to first compute a vector which is the
mean velocity of the particles to use as the travel direction. This
would be pointing parallel to the muzzle in the same direction as the
bullet fires. Then use a deviation vector that is equal in all
directions, but smaller in magnitude than the mean velocity. The
larger the magnitude of the deviation, the bigger the spread. This
should make an approximate cone shaped emission, though it may
influence the parallel velocity more than desired.
If that's the case, then you should just modify your axis-aligned code
to rotate both the travel direction vector and deviation vector in the
desired direction. How you do this depends on how you represent the
muzzle direction. If using Euler angles
(http://en.wikipedia.org/wiki/Euler_angles) with yaw, pitch and roll
values this is a straightforward bit of trig. Or you can use a
rotation matrix, quaternions or some combination thereof.
If you need more specific help with doing that rotation, I might have
a moment or two tomorrow, as it is I wanted to send this off now to at
least give you a start. I have a few Xmas related things to take care
of tonight, so I'm a little shorter on time than usual 8^)
-Casey
Emitters have no inherent notion of geometry, so I don't think you'll
find that approach practical. The point of using a domain as the
source for various particle attribute (position, velocity, color ,etc)
is that its sole job is to define a 3D spacial geometry and it can do
so any way you wish without restriction.
I think the easiest approach to get what you want is to create a class
that implements part of the domain interface (in particular the
generate() method). If you pass this object as the source of the
velocity particle attribute, it will call the generate() method each
time it creates a particle and use the value it returns (a sequence of
3 numbers) as the velocity for that particle.
So define a class that takes three arguments, an apex point, a base
point and a base radius. The class would define the generate() method
to return points either inside the cone or on it's surface, you're
choice. The latter could be combined with a small deviation to make it
look more "organic" as a perfectly flat curve may look too fake.
To code this, I would first generate a point inside of an axis-aligned
cone the same size as the cone defined in the instance. Then I would
do a rotate and translate on the point according to the actual apex
and base points and return the result. Ideally you would just create a
4x4 transformation matrix when the domain is created to do this in one
fell swoop inside generate(). The translation part is easy, it's just
the apex point. Rotation is a bit more involved. You could get that I
think by creating a quaternion using the cross-product of the vector
created by the axis-aligned apex and base points and the vector
created by the actual apex and base point (i.e., the direction
vector). This cross product will return the proper axis of rotation
between the two which becomes the x, y, z coordinates of the quat. The
rotation can be calculated using the arccosine of the dot product of
these two vectors, this becomes the w coordinate of the quat. The quat
can be made into a 3x3 rotation matrix and the translation can be
added in to make it a 4x4.
I haven't found time these last few days to code this up, but I may
this weekend. There is a nice Euclid module that could be used to do
some of the "heavy lifting" as it contains quaternion and matrix
classes already. I expect lepton will have C implementations of
vectors, matrices and quaternions exposed to python eventually. It
already has many vector operations coded in C, but they currently
aren't "pythonified".
-Casey