Question

when creating a PF Source node in a scene I can select this system in maxscript and iterate through all the particles using a for loop and pf.particleIndex

However, when I use maxscript to loop through the geometry in a scene and generate a PF Source for each object pf.NumParticles() returns 0 and pf.particlePosition of pf.particleIndex = i returns 0 0 0 for coord.x, .y and .z

geo = #()

for OBJ in Geometry do (
    append geo OBJ
)

for OBJ in geo do ( 
    with undo off (
        -- define color for current object
        r = random 128 192
        g = random 128 192
        b = random 128 192

        -- create a particle system
        pf = PF_Source() 
        pf.Quantity_Viewport = 100

        ParticleFlow.BeginEdit()

        -- enable render
        rp = RenderParticles()
        pf.AppendAction rp

        -- create birth
        a1 = Birth()
        a1.Amount = random 1000 2000
        a1.Emit_Start = 0
        a1.Emit_Stop = 0

        -- position to surface of current object
        a2 = Position_Object()
        a2.Location = 3
        a2.Emitter_Objects = #(OBJ)

        -- show in viewport
        a3 = DisplayParticles()
        a3.type = 2
        a3.color = (color r g b)

        -- add the event to the flow
        e1 = Event()
        e1.AppendAction a1
        e1.AppendAction a2
        e1.AppendAction a3

        ParticleFlow.EndEdit()

        -- create the "complete" particle system
        pf.appendInitialActionList e1

        -- get particle coordinates
        particleAmount = pf.NumParticles()
        print particleAmount
        for i = 1 to particleAmount do (
            pf.particleIndex = i
            coord = pf.particlePosition
            print coord
        )
    )
)

-- garbage collection
gc()

Is there some way to, I don't know, refresh the PF Source in the script so it is aware of there being particles in the system.

Was it helpful?

Solution

There's a known issue with PF, when creating it with maxscript you have to reload it, for example using hold/fetch:

geo = geometry as array

for OBJ in geo do
(
    -- create a particle system
    local pf = PF_Source Quantity_Viewport:100
    -- save its identifier for later
    local handle = pf.iNode.handle
    local particleAmount = random 1000 2000

    ParticleFlow.BeginEdit()

    -- enable render
    pf.AppendAction (RenderParticles())

    -- add the event to the flow
    local e1 = Event()
    -- create birth
    e1.AppendAction (Birth Amount:particleAmount Emit_Start:0 Emit_Stop:0)
    -- position to surface of current object
    e1.AppendAction (Position_Object Location:3 Emitter_Objects:#(OBJ))
    -- show in viewport
    e1.AppendAction (DisplayParticles type:2 color:(random [128,128,128] [192,192,192]))

    ParticleFlow.EndEdit()

    -- create the "complete" particle system
    pf.appendInitialActionList e1

    -- force particle flow to update particles
    holdMaxFile()
    fetchMaxFile quiet:true

    -- get the particle flow node again
    pf = maxOps.getNodeByHandle handle

    -- get particle coordinates
    for i = 1 to particleAmount do
    (
        pf.particleID = i
        coord = pf.particlePosition
        format "index: %, pos: %\n" pf.particleIndex coord
    )
)

On the other hand if you only need random particles on surface, PArray might be a better solution for you:

geo = geometry as array

for OBJ in geo do
(
    local particleAmount = random 1000 2000
    local pa = PArray emitter:obj formation:0 speed:0 Birth_Rate:particleAmount viewPercent:100 \
        Emitter_Start:0f Emitter_Stop:0f wirecolor:(random [128,128,128] [192,192,192])

    for i = 1 to particleAmount do
        format "index: %, pos: %\n" i (particlePos pa i)
) 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top