How to clear particles?

Hello, I’ve a problem with particles. I use many particles in my application: I create an effect, and after some seconds I would remove it.

But I don’t know the “correct” approach to destroy an effect. I copy a little example to show the problem:

import direct.directbase.DirectStart
from panda3d.core import AmbientLight,DirectionalLight
from panda3d.core import Point3,Vec3,Vec4
from panda3d.core import Filename
from direct.particles.Particles import Particles
from direct.particles.ParticleEffect import ParticleEffect
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Sequence

class World(DirectObject):
  def __init__(self):
    self.accept( '1', self.stopParticle )
    base.disableMouse()
    camera.setPos(0,-20,2)
    base.enableParticles()
    self.t = loader.loadModel("models/teapot")
    self.t.setPos(0,10,0)
    self.t.reparentTo(render)
    self.rotateTeapot()
    self.setupLights()
    self.p = ParticleEffect()
    self.loadParticleConfig('steam.ptf')

  def loadParticleConfig(self, file):
    self.p.cleanup()
    self.p = ParticleEffect()
    self.p.loadConfig(Filename(file))        
    self.p.start(self.t)
    self.p.setPos(3.000, 0.000, 2.250)
	
  def stopParticle(self):
    #self.p.cleanup()
    self.p.softStop()
    taskMgr.doMethodLater( 10, self.printNodes, 'print nodes' )
	
  def printNodes(self,task):
    print( render.ls() )

  def rotateTeapot(self):		
    Sequence(
      self.t.hprInterval(2, Point3(0, 0, 0) , startHpr=Point3(360, 0, 0))
    ).loop()
  
  def setupLights(self):
    ambientLight = AmbientLight("ambientLight")
    ambientLight.setColor(Vec4(.4, .4, .35, 1))
    directionalLight = DirectionalLight("directionalLight")
    directionalLight.setDirection(Vec3( 0, 8, -2.5 ) )
    directionalLight.setColor(Vec4( 0.9, 0.8, 0.9, 1 ) )
    self.t.setLight(self.t.attachNewNode(directionalLight))
    self.t.setLight(self.t.attachNewNode(ambientLight))

w = World()
run()

(it’s only a modification of the example provided by Panda, so it can be launched from the same folder and it’ll find the resources needed)

When the user press the key ‘1’, the method stopParticle is called. If the method is defined as follows:

  def stopParticle(self):
    #self.p.cleanup()
    self.p.softStop()
    taskMgr.doMethodLater( 10, self.printNodes, 'print nodes' )

The effect is stopped (and removed from screen), but it remains still in the scene graph - in the console I see:

c:\Panda3D-1.7.0\samples\Particles>python try.py
[...]
PandaNode render S:(CullFaceAttrib RescaleNormalAttrib)
  [...]
    PandaNode particle-effect-2 T:(pos 3 0 2.25)
      PhysicalNode particles-1
        GeomNode BaseParticleRenderer render node (1 geoms: S:(ColorAttrib Rende
rModeAttrib TexMatrixAttrib TextureAttrib TexGenAttrib TransparencyAttrib))
      ForceNode vertex (1 forces)

So, the node corresponding the effect, PandaNode particle-effect-2, is alive.

Instead, if I define the method as follows:

  def stopParticle(self):
    self.p.cleanup()
    #self.p.softStop()
    taskMgr.doMethodLater( 10, self.printNodes, 'print nodes' )

The node is correctly cleared: in the console, there is not the node PandaNode particle-effect-2. But, in this case, I’ve another problem: when the method self.p.cleanup is called, the application freezes (the teapot stops about half a second).

So, if I use softStop I don’t see any freezes, but the node remains in the scene graph. If I use cleanup, the node is effectively cleared, but the application freezes. Is there a way to remove the particle effect from the scene graph, without freezing the application? Very thanks!

Hmm, I’m pretty sure that cleanup() is the correct method to call, but I don’t know why it would be causing a temporary freeze of your application. I don’t see anything in there that ought to be doing that. Are you sure that the freeze isn’t coming from somewhere else?

David

Wow, you’re right, thanks! I tried the same code on the same hardware, but with a different operative system, and with cleanup I see no freezes (on Seven 64 bit I see the freeze, on Ubuntu 64 bit I don’t see the freeze). So, the problem is not in the hardware side, and not in the Panda side, maybe could be a driver issue?!? :confused:

As a reminder (if others will have the same problem): I found a simple workaround, I can parent the particle to another node and remove it, and this “transitively” removes the particle effect.

I did another test, this time on a MacMini, Snow Leopard (same Panda 1.7.0). But, also in this case, the teapot freezes a bit.

I can’t do other tests (I haven’t other machines), and now I’m wondering if it’s really only a problem of my Windows’s settings, because on the MacMini I get the same problem.

Does anyone interested about the problem could tell me if that code executes correctly or not? That is, if pressing the ‘1’ key the teapot freezes?

To simplify things, I prepared a zip file with all the necessary for the test, it’s here (the download link is in the bottom part of the central table, near “Save file to your PC”), and can be launched with ipython main.py[/i]. Very thanks!

Freeze confirmed on Windows Vista.

Hmm, yes, on closer inspection it does appear that cleanup() is awfully aggressive, and spends a lot of time doing lots of fiddly operations within Python, which can add up to a sizeable chug.

This clearly needs to be optimized better.

David

It’s not valid. :cry: I tried the workaround in a more complex situation (where I analyze the frame rate trend, not only the scenegraph) and it doesn’t work: this correctly removes the node from scenegraph, but the frame rate doesn’t improve. :cry: