PDA

View Full Version : deleteparticle


frilansspion
05-31-2011, 10:39 AM
hello!
Im trying to learn a little bit of pflow scripting (starting today) and its not going very well. Im trying to do something relatively simple - deleting some particles using a script operator. well basically I just dont really understand the syntax of the script language not to mention the way pflow works. but after wasting a good few hours on the internet I thought it quickest just to ask here.
basically Im trying to filter out and delete particles that are too close to each other, in order to populate an area with object instances without overlap.
why doesnt this work?


on Proceed pCont do
(
count = pCont.NumParticles()
minDistance = 0.001

for i in 1 to count do
(
pCont.particleIndex = i
curPos = pCont.particlePosition


for j in 1 to count do
(
if j == i then
(

)
else
(
pCont.particleIndex = j
checkPos = pCont.particlePosition
distance = length (checkPos - curPos)
if distance < minDistance then
pCont.deleteParticle j
)

)
pCont.particleIndex = i
)
)


this seems to delete all the particles no matter how small minDistance is. can anyone see whats wrong just looking at this? like I said I just started so it might be a completely mental way to try to go about it.

btw Im aware that deleting a particle like that would probably cause the ids to change or at least crash the loop next time around when that particle doesnt exist anymore... Ill deal with that if I get that far. or is that the problem already?
thanks...

haavard
05-31-2011, 12:12 PM
Hi,
this seems to work for me:

on Proceed pCont do
(
count = pCont.NumParticles()
minDistance = 10

for i in 1 to count do
(
pCont.particleIndex = i
curPos = pCont.particlePosition

for j in 1 to count where j != i do
(
pCont.particleIndex = j
checkPos = pCont.particlePosition
dist = distance checkPos curPos
if dist < minDistance then
pCont.deleteParticle j
)
)
)

The main difference that I could see is that you used a reserved word "distance" as a variable name (although it should work none the less). Are you sure that you are explicitly saying that you use the position channel in the channelsUsed handler at the top?

frilansspion
05-31-2011, 12:43 PM
hey mate!
thanks a lot for your help!
no I didnt know you needed to put pCont.usePosition = true in the bit up top (although I should have guessed it). thanks!!
but even so I cant seem to get it to work. even copy-pasting your script....with any value other than 0 for minDistance all particles disappear and with 0 none does (as they shouldnt of course)
out of interest when you tried it did you check just for it to run ok or did it delete just some of the particles for you like it was intended? (Im not so sure about the logic of the script either but thought I could iron out the wrinkles after it does anything similar to what I want)

also thanks for cleaning things up a bit =D


edit. I have my script operator under the default event along with birth and all that lot by the way. is this whats wrong? like I said Im kinda fumbling in the dark with all this. I should really dig into some beginner tutorials...but I was hoping this would be easy enough not to learn the whole thing...

haavard
05-31-2011, 01:39 PM
That is weird. Maybe you got some crazy scale in your scene?
If your particles are uniformly distributed you could check the average distance for each particle and try to set the minDistance according to that value. Say like 20% of the average distance.

I've uploaded the scene I tested it on here (max2012): http://folk.ntnu.no/havardsc/tmp/pFlowDistanceDelete.max

frilansspion
06-01-2011, 01:50 AM
well Im not completely sure but I dont think so. the PF emitter is 300x300 or something and the particles are random in there. and I tried a lot of values ranging from 0.0000001 to 1000.

I only have max 2010 =( thanks so much for the effort though. Ill try to find a way to open that file...

edit:
can I ask by the way how you would check if a particle exists? it seems prudent to check for that in both loops before having any properties accessed...not that it seems to be erroring out because of that at this point, but could be good to know.
looking at the method reference (bottom of file) it kind of looks like you have to get the Id based on an index and then theres a function to check if theres a particle with that Id. which makes no sense since getting the id from the index would kind of require that the particle exists? I dont get it.
Ive tried it but cant get it to work anyways. dont know if its to do with the Id not caring whether the particle has been deleted or not. Are there other ways of checking? maybe using age or lifespan or something?

edit2:
d'oh! I found where I was going wrong basically. I hadnt realised that the order of the operators under the event made a difference and could be changed. I thought it was more like properties.
so now only some of the particles are deleted. good!
however. its not behaving like I would expect really. more particles than Id like are deleted but still some that are too close to each other remain. but I guess this is a logic thing. I think starting with checking that particles still exist would be a way forward (as question above) or any more info on how the pf system evaluates deleted particles would be helpful. like, are particles deleted at the end of an update loop and so their indices are still there for the rest of the loop? (in which case checking if i and j exist should fix it?) or is the whole index sequence renumbered at the moment deleteParticle is called? (in which case Id need some recursive thing that starts over every time something is deleted?

question n. if I only want to do this whole thing ONCE per scene basically (at frame 1) should I put this loop in a different method (in init?) or should I just check current frame within the proceed method and only calculate if frame 1?


edit3:
I in the end tried this slightly different approach of "tagging" particles to be deleted through their integer value (if you wonder why its "5" its because I was uncertain of what the default was - 1 or 0 - and wanted to avoid both), and then deleting them in another loop. just to be on the safe side. and this seems to work better - but only if its allowed to iterate through a few frames. which I dont understand.
it should go through every particle and if it isnt tagged, check what particles are too close to it and tag them. whats going wrong? it should work the first time?



on ChannelsUsed pCont do
(
pCont.useInteger = true
pCont.usePosition = true
)

on Init pCont do
(

)

on Proceed pCont do
(
count = pCont.NumParticles()
minDist = 25

for i in 1 to count do
(
if (pCont.getParticleInteger i) != 5 then
(
curPos = pCont.getParticlePosition i

for j in 1 to count where j != i do
(

if (pCont.getParticleInteger j) != 5 then
(
checkPos = pCont.getParticlePosition j
dist = distance checkPos curPos
if dist < minDist then
(
pCont.setParticleInteger j 5
)
)

)
)

)
for i in 1 to count do
(
if (pCont.getParticleInteger i) == 5 then
pCont.deleteParticle i
)

)

JohnnyRandom
06-01-2011, 09:14 PM
If you only want one evaluation you can nest your for loops within an if/then and at whatever time = true evaluate. There is also isParticleNew but I don't think that would be the best fit for this case.

Oh and default for script integer/float/vector/matrix is always 0.

frilansspion
06-02-2011, 02:44 AM
cheers for that johnny!

ah. I think I tried "if currentFrame == 1 then" because I thought I had seen it in some script somewheres on the web, but its "currentTime" isnt it.
is "if currentTime < 0 then" the right way of setting it up? Im not getting any errors with that added in but I dont get it to have evaluated at all either. Im not really getting how to debug scripts in max, right now Im just seeing in the listener if there are errors but little detail.
(Im setting the sim start to -10 and want to only evaluate before frame 0. so at least it doesnt update when Im working with the scene. until Ive figured out how to get the result in one go)

edit.
with "if currentTime < 1" it seems to work. like it needs at least one of the frames to be evaluated to be on the scene timeline. (mine starts at 0) if anybody can explain/define that behavior further itd be much appreciated =)

JohnnyRandom
06-02-2011, 04:15 AM
Always listen to Dr. Oleg "It is best to use the time functions provided with the PFlow Maxscript interface." Words to live by, I spent a lot of time bungling time and random value functions in PFlow, when he had already provided everything.

An example would go something like this to evaluate at the end of the integration step on frame 50:


t2 = pCont.getTimeEnd()

if t2 == 50 then
(
for i in theCount do
(
something spectacular
)
)


For a duration, you could:


t2 = pCont.getTimeEnd()

if t2 >= 50 and t2 <= 60 then
(
for i in theCount do
(
something spectacular
)
)

frilansspion
06-06-2011, 08:00 AM
thanks for that! I wouldnt have figured that one out by myself...what a silly name for a function that gets the current frame? noted.

haavard
06-06-2011, 11:06 AM
It has that name for a reason. It's "counter part", getTimeStart() clocks the start of each new integration step, while getTimeEnd() clocks the end of each integration step.

To see the difference consider this snippet:

on Proceed pCont do
(

tStart = pCont.getTimeStart() as float
tEnd = pCont.getTimeEnd() as float
timeDif = tEnd - tStart

print tStart
print tEnd
print timeDif

)
and change the integration step for the particle system to see how the time delta changes :)

CGTalk Moderation
06-06-2011, 11:06 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.