Particles

Hi guys,

I started with particles and I’m playing well =)
I’m using setPos() to change the particle position, but I don’t want to
move the entire particle system, I want to move just the initial point to where
the mouse is. If you understand me I think that’s quite simple to you. :smiley:

Thank your attention!

i had the same problem at my game (how to get and set individual paricles), thats why i wrote my own dynamic system…

but i will be glad to hear how it works with panda3d particles.

greetz
dirk

are you searching for something like this :smiley: thats a reduced demo how my particular system works…

https://discourse.panda3d.org/viewtopic.php?p=43304#43304

i’ve had a similar problem where i wanted to have the particles being parented to render, but created at a specific location. dont really know if that is currently not possible. however you can add forces onto the particles. i’m using this method in the maze game for the torch particles, it’s not really good but at least a option which may be sufficient.

maze with source can be donwloaded from: http://www.nouser.org/PMW/pmwiki.php/Portfolio/SparetimeMaze

(in the second screenshot you can see the torch beeing affected by the force)

i’ve just decided to try it again, and guess. i’ve found it:

        self.p = ParticleEffect()
        self.p.loadConfig(Filename(file))
        self.p.start(render)
        psystem = self.p.getParticlesList()[0]
        psystem.setRenderParent(render)

self.p.start(render) # decides where the particles are emitted from
psystem.setRenderParent(render) # decides in what coordinate system the particles move

here’s a modified Tut-Steam-Example.py:

# Author: Shao Zhang and Phil Saltzman
# Last Updated: 4/20/2005
#
# This tutorial shows how to take an existing particle effect taken from a
# .ptf file and run it in a general Panda project. 

import direct.directbase.DirectStart
from pandac.PandaModules import BaseParticleEmitter,BaseParticleRenderer
from pandac.PandaModules import PointParticleFactory,SpriteParticleRenderer
from pandac.PandaModules import LinearNoiseForce,DiscEmitter
from pandac.PandaModules import LightAttrib,TextNode
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import Point3,Vec3,Vec4
from pandac.PandaModules import Filename
from direct.particles.Particles import Particles
from direct.particles.ParticleEffect import ParticleEffect
from direct.particles.ForceGroup import ForceGroup
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import sys

HELPTEXT = """
1: Load Steam
2: Load Dust
3: Load Fountain
4: Load Smoke
5: Load Smokering
6: Load Fireish
ESC: Quit
"""

font = loader.loadFont("cmss12")

class World(DirectObject):
    def __init__(self):
        self.root = render.attachNewNode('particleCenter')
        self.root.setPos(0,10,0)
        self.root.hprInterval(4, Point3(360,0,0), startHpr=Point3(0,0,0)).loop()
        #Standard title and instruction text
        self.title = OnscreenText(
            text="Panda3D: Tutorial - Particles", font = font,
            style=1, fg=(1,1,1,1), pos=(0.8,-0.95), scale = .07)
        self.escapeEvent = OnscreenText(
            text=HELPTEXT, font = font,
            style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
            align=TextNode.ALeft, scale = .05)

        #More standard initialization
        self.accept('escape', sys.exit)
        self.accept('1', self.loadParticleConfig , ['steam.ptf'])
        self.accept('2', self.loadParticleConfig , ['dust.ptf'])
        self.accept('3', self.loadParticleConfig , ['fountain.ptf'])
        self.accept('4', self.loadParticleConfig , ['smoke.ptf'])
        self.accept('5', self.loadParticleConfig , ['smokering.ptf'])
        self.accept('6', self.loadParticleConfig , ['fireish.ptf'])
        
        self.accept('escape', sys.exit)
        base.disableMouse()
        camera.setPos(0,-20,2)
        base.setBackgroundColor( 0, 0, 0 )

        #This command is required for Panda to render particles
        base.enableParticles()
        self.t = loader.loadModel("models/teapot")
        self.t.setPos(0,2,0)
        self.t.reparentTo(self.root)
        self.setupLights()
        self.p = ParticleEffect()
        self.loadParticleConfig('steam.ptf')

    def loadParticleConfig(self,file):
        #Start of the code from steam.ptf
        self.p.cleanup()
        self.p = ParticleEffect()
        self.p.loadConfig(Filename(file))        
        #Sets particles to birth relative to the teapot, but to render at toplevel
        self.p.start(self.t)
        self.p.setPos(3.000, 0.000, 2.250)
#        print dir(self.p)
#        print self.p.getParticlesList()
        psystem = self.p.getParticlesList()[0]
#        self.p.HprInterval(1,360,Vec3(360,360,1)).loop()
#        psystem.setSpawnRenderNodePath(render)
        psystem.setRenderParent(render)
    
    #Setup lighting
    def setupLights(self):
        lAttrib = LightAttrib.makeAllOff()
        ambientLight = AmbientLight( "ambientLight" )
        ambientLight.setColor( Vec4(.4, .4, .35, 1) )
        lAttrib = lAttrib.addLight( ambientLight )
        directionalLight = DirectionalLight( "directionalLight" )
        directionalLight.setDirection( Vec3( 0, 8, -2.5 ) )
        directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) )
        lAttrib = lAttrib.addLight( directionalLight )
        #set lighting on teapot so steam doesn't get affected
        self.t.attachNewNode( directionalLight.upcastToPandaNode() ) 
        self.t.attachNewNode( ambientLight.upcastToPandaNode() ) 
        self.t.node().setAttrib( lAttrib )

w = World()
run()

thats cool, but i already noticed that. i think he mean, how to change the velocity for individual particles. something like

 particle[x].setVelo(1,0,0)

or he means the emitter, i dont know what he mean by initalpoint, init the velocity or where the particles emits from?

I mean the emitter, the point that emits the particles,

That’s my .ptf file:

self.reset()
self.setPos(0.000, 0.000, 0.000)
self.setHpr(0.000, 0.000, 0.000)
self.setScale(1.000, 1.000, 1.000)
p0 = Particles.Particles('particles-1')
# Particles parameters
p0.setFactory("ZSpinParticleFactory")
p0.setRenderer("SpriteParticleRenderer")
p0.setEmitter("DiscEmitter")
p0.setPoolSize(8)
p0.setBirthRate(0.0400)
p0.setLitterSize(20)
p0.setLitterSpread(1)
p0.setSystemLifespan(0.0000)
p0.setLocalVelocityFlag(1)
p0.setSystemGrowsOlderFlag(0)
# Factory parameters
p0.factory.setLifespanBase(1.0000)
p0.factory.setLifespanSpread(1.2000)
p0.factory.setMassBase(1.0000)
p0.factory.setMassSpread(0.0000)
p0.factory.setTerminalVelocityBase(400.0000)
p0.factory.setTerminalVelocitySpread(0.0000)
# Z Spin factory parameters
p0.factory.setInitialAngle(0.0000)
p0.factory.setInitialAngleSpread(0.0000)
p0.factory.enableAngularVelocity(1)
p0.factory.setAngularVelocity(150.0000)
p0.factory.setAngularVelocitySpread(0.0000)
# Renderer parameters
p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAINOUT)
p0.renderer.setUserAlpha(1.00)
# Sprite parameters
p0.renderer.addTextureFromFile('Particles/effect001.png')
p0.renderer.setColor(Vec4(1.00, 1.00, 1.00, 1.00))
p0.renderer.setXScaleFlag(1)
p0.renderer.setYScaleFlag(1)
p0.renderer.setAnimAngleFlag(0)
p0.renderer.setInitialXScale(0.0010)
p0.renderer.setFinalXScale(0.1000)
p0.renderer.setInitialYScale(0.0010)
p0.renderer.setFinalYScale(0.1000)
p0.renderer.setNonanimatedTheta(0.0000)
p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PPBLENDLINEAR)
p0.renderer.setAlphaDisable(0)
# Emitter parameters
p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE)
p0.emitter.setAmplitude(1.0000)
p0.emitter.setAmplitudeSpread(0.0100)
p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 0.0000))
p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000))
p0.emitter.setRadiateOrigin(Point3(0.0000, 3.0000, 3.0000))
# Disc parameters
p0.emitter.setRadius(0.2000)
self.addParticles(p0)

I don’t know which command do what I want, setPos move the whole system as I said. Look at this program:

asantee.net/gamespace/ethano … nglish.htm

Video:
youtube.com/watch?v=enM9F_AHFDY

download:
asantee.net/gamespace/ethano … .1.1.0.zip

Panda can do that? if Panda can’t, why?

Thank you guys! :smiley:

Do what, exactly? Emit particles at a certain point and then have them move independently of that point? If so, then the code that Hypnos demonstrated is exactly what you want. There are two frames of reference for particles – The emitter node, and what node you want the particles to move relative to.

By using setRenderParent(render), you’re telling the particles to move in the primary scene graph’s frame of reference. Which means if your emitter is moving around relative to render, then the particles will be “left behind” in the render’s frame of reference.

Panda can do what is shown in that video, and a whole lot more. It’s particle system is a lot more complicated than what I saw in that video. However, it’s not easy to use and there are some heinous bugs lurking in the system. (Pro-rsoft fixed a nasty one recently that had to do with a setSystemGrowsOlderFlag(), IIRC.) Treeform has a post on this forum about some Python patches you can do to the particle editor to make it not upchuck anytime you enter a zero in some of the fields.

There’s very little documentation concerning particles in Panda, and AFAIK there are no Disney lectures on how to use it. This is probably one of the most glaringly bad areas were Panda needs some work. I plan on devoting some time to this when I can.

Thank you for making things a bit clearer =D

I didn’t try hypno’s code yet, I’ll try it soon as possible.

I have other question by now, and it is about particle renderer type, I’m using SpriteParticleRenderer but the particle panel does not give me the PointParticleRenderer variables ‘StartColor’ and ‘EndColor’. is It possible to add another particle renderer in a way that my sprite changes from starting color to ending color?

Yeah, particles are very poorly documented, but his snippet should do exactly what you want.

As for the startColor/EndColor, you can change the color of a particle effect using the SpriteParticleRenderer too, but there are no variables of that name. However, instead of using them, you set up a linear blend operation on the renderer itself.

To do this, under the ParticalEditor, go under the Interpolate tab when you select the Renderer. Then use Add Segment to add the kind of segment you want. (Linear, sinusoidal sweep, etc.)

From there, select the Linear Begin and End colors using sliders, or entering values by hand into the RGBA boxes.

This is the code that it generates:

self.renderer.getColorInterpolationManager().addSinusoid(0.0,1.0,Vec4(0.0,1.0,0.0,1.0),Vec4(0.0,0.0,1.0,1.0),1.0,1)

Thank you guys very much!!, fenrir, hypnos!

My particle system is working the way I want but I’m still beginner. Now I have problem with its scale.

        
   self.p = ParticleEffect()
   self.p.loadConfig(Filename('Particles/effect1.ptf'))
   self.p.start(render2d)
   self.p.setPos(0, 0, 0)
   self.p.setScale(0.3)

   self.psystem = self.p.getParticlesList()[0]
   self.psystem.setRenderParent(render2d)        
   print dir(self.psystem)

self.psystem makes the particles bigger, I think self.p.setScale(0.3) is being ignored. I don’t know how to fix this.

you have to scale the parent of the particle system you have it render under.

instead of:

self.psystem.setRenderParent(render2d)

do:

psystemParent = render2d.attachNewNode()
self.psystem.setRenderParent(psystemParent)
psystemParent.setScale(0.3)

btw: are you really sure you want to attach a particlesystem to render2d?

not sure if this has already been mentioned, but the particle-panel-sample gives you a small editor for particlesystems. (not great but the best you can get atm)

I’m attaching the particlesystem to render2d to keep track of the mouse cursor. I don’t know if this is the right method but it is working. I don’t want this particlesystem in the 3d window. Instruction is very appreciated if I’m doing wrong.

Thank you again!