How to delete ParticleGroups/Emitters

10 views
Skip to first unread message

Collin

unread,
Dec 23, 2008, 12:49:06 PM12/23/08
to General discussion of the Lepton particle engine for Python
In my small 2d app I'm dynamically constructing particle groups and
emitters to display some cool particle effects. When the particles
are all dead, how do I ensure that those resources are deleted? I've
been browsing the API docs, but I haven't seen how to do this.

Thanks,
--Collin

Casey Duncan

unread,
Dec 23, 2008, 1:46:11 PM12/23/08
to py-lept...@googlegroups.com

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.

Collin Arnold

unread,
Dec 23, 2008, 8:54:47 PM12/23/08
to py-lept...@googlegroups.com
Ah, that is really interesting - thanks for explaining it to me.  I've worked out a different solution to get around allocating/deleting particle groups, and I think this solution is quite more performant than my previous design, especially now that I understand better how it works.  I've been experimenting with Lepton and I've seen how amazing it's performance really is - you've done a really great job!

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?

Thanks for the help,
--Collin
Muzzle Flare Diagram.png

Casey Duncan

unread,
Dec 24, 2008, 2:47:53 AM12/24/08
to py-lept...@googlegroups.com
On Tue, Dec 23, 2008 at 6:54 PM, Collin Arnold <collin...@gmail.com> wrote:
> Ah, that is really interesting - thanks for explaining it to me. I've
> worked out a different solution to get around allocating/deleting particle
> groups, and I think this solution is quite more performant than my previous
> design, especially now that I understand better how it works. I've been
> experimenting with Lepton and I've seen how amazing it's performance really
> is - you've done a really great job!

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

Collin

unread,
Dec 24, 2008, 1:39:21 PM12/24/08
to General discussion of the Lepton particle engine for Python
> 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.

I was thinking that adding a simple rotation attribute to the
StaticEmitter could do the job as well, maybe more straight-forward.
Then, the velocities and deviations could be specified relative to the
positive x-axis and then rotated after they have been calculated.
Since I'm passing in an angle to the function, that would be
convenient for me as well.

> 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.

Thanks for the suggestion, but that is what I attempted first, and the
results were not at all what I was looking for. With this approach,
all of the particles shoot away from the muzzle, and it does not
achieve the look I want. I want to set the axis-aligned deviation
equal to the axis-aligned velocity, so that some particles hand around
the end of the muzzle - this gives a nice 'streak' look, and
concentrates the particles at the end of the muzzle rather than out in
front of it.

> 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.

I appreciate that, but I have written very fast Vector and Angle
classes (based off of your ctypes.Array approach, but with a ton of
performance enhancements) that give me the functionality I need to
accomplish this pretty easily. I spent a long time benchmarking the
Vector classes in Lepton and Pymunk and my own home-brewed, and
eventually got my class to work about 15% faster (on average) than
your Vec3 and 25% faster than Pymunk's Vec2d. I can pass along my
Geom module if you would be interested in seeing it, or incorporating
it into Lepton.

Here are some benchmark results, if you are interested:
Loading chipmunk for Windows (32bit) [C:\Python25\Lib\site-packages
\pymunk-0.8.1-py2.5.egg\pymunk\chipmunk.dll]
Working with : 100000 vectors
Construct Vec2d : 0.331000089645
Scale Vec2d : 0.460999965668
Add Vec2d : 0.310000181198
Construct Vec3 : 0.230999946594
Scale Vec3 : 0.240000009537
Add Vec3 : 0.501000165939
Construct Vector : 0.149999856949
Scale Vector : 0.230000019073
Add Vector : 0.481000185013
Hash Vector : 0.19000005722

> 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.

Thanks, I could use some advice. I think I will try modifying lepton
to add in the rotation attribute, but first I could use some
clarification - the StaticEmitter object is defined in C in
emittermodule.c, which I am currently using, but I found that in
emitter.py there is a PointEmitter class (which I can't seem to
instantiate). How do these interact? What/where would I need to make
modifications to get the behavior I am looking for? I can look into
the domain approach if you would prefer that solution, or think it
will be easier, though I don't understand it as well.

Cheers,
--Collin

On Dec 23, 11:47 pm, "Casey Duncan" <casey.dun...@gmail.com> wrote:

Casey Duncan

unread,
Dec 27, 2008, 1:40:31 PM12/27/08
to py-lept...@googlegroups.com
On Wed, Dec 24, 2008 at 11:39 AM, Collin <collin...@gmail.com> wrote:
>
>> 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.
>
> I was thinking that adding a simple rotation attribute to the
> StaticEmitter could do the job as well, maybe more straight-forward.
> Then, the velocities and deviations could be specified relative to the
> positive x-axis and then rotated after they have been calculated.
> Since I'm passing in an angle to the function, that would be
> convenient for me as well.

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

Collin Arnold

unread,
Dec 30, 2008, 5:50:26 PM12/30/08
to py-lept...@googlegroups.com
Ah, ok.  Thanks for the input.  I think I'll take your recommended approach - I'll let you know how it goes!

Thanks,
--Collin
Reply all
Reply to author
Forward
0 new messages