Hello Widam3D,
I’am happy if my script is useful to you. It need some improvements.
I think an multi path system will be interesting.
I try to learn maxscript by doing some small script like this one.
But, i have a lot of things to learn (or understand) in maxscript.
I just tried this script and the max script listener gave me general exception error. I’m using 2011 but I have no idea what’s wrong.
EDIT: I’m a complete twit, I tried to paste this code into the maxscript editor, not into a script operator in pflow.
EDIT AGAIN: Nope, I have no idea how to implement this apparently simple script. Where do I paste the code? I did rename a spline Line01 from Line001 but I still don’t know what else I need to do. Someone help this particle newbie out please.
Hello Guys,
I made some improvements to my script.
I see that the latest script made the particles over the path but they stay oriented by the emitter.
So i tried to make a banking script to make the particle follow the orientation of the spline during
the travelling.
To use as Script Operator
on ChannelsUsed pCont do
(
pCont.useTM = true
pCont.useAge = true
pCont.usePosition = true
pCont.useVector = true
)
on Init pCont do ()
on Proceed pCont do
(
count = pCont.NumParticles()
splPath = $Line01 -- Path to follow. Put your path name here
PartEmitter = $'PFlow Emitter 01' -- Emitter to get his position
KnotPnt = (getKnotPoint splPath 1 1) -- First Knot position of the Path
NumFrames = 100 -- Number of frame that the particle take to travel over the Path
sw_Banking = True -- True/False : If you want the particle follow the orientation of the Path.
sw_AlignToPath = True -- True/False : If you want the particles follow the path from emitter (False) or directly on the Spline Path (True).
sw_ReorientParticles = False -- True/False : If you want the Transform Matrix of the particle be oriented to the Path. Useful for shape Orientation.
--sw_DelPartatEnd = True -- Delete Particle at the end of the path
if sw_Banking != True and sw_Banking != False do sw_Banking = True -- If there is something different in sw_Banking than True or False, we put True in sw_Banking
for i in 1 to count do -- loop in the particles
(
pCont.particleIndex = i
PathPartPos = (pCont.particleAge as float/ticksperframe)/NumFrames -- Get a percentage beetween 0.0 and 1.0 with the pCont.particleAge to calculate the travel position on the path (192 ticks per frame)
if sw_Banking == False do -- if you don't want the Banking
(
if pCont.particleNew do pCont.particleVector = (pCont.particlePosition - KnotPnt) -- if it's a new particle. Store a vector from the particle position to the first PathKnot
if PathPartPos <= 1.0 do -- Set the new particle position if PathPartPos is smaller than 1.0
(
if sw_AlignToPath == True do pCont.particlePosition = (lengthInterp splPath PathPartPos) -- with sw_AlignToPath
if sw_AlignToPath == False do pCont.particlePosition = (lengthInterp splPath PathPartPos) + (pCont.particleVector) -- without sw_AlignToPath
)--end if
)--end if
if sw_Banking == True do -- if you want the Banking
(
if pCont.particleNew do pCont.particleVector = (pCont.particlePosition - PartEmitter.pos) -- if it's a new particle. Store a vector from the particle position to the Emitter Position
if PathPartPos <= 1.0 do -- if PathPartPos is smaller than 1.0
(
-- Axis reconstruction - Thanks to Bobo for the explanation in the Max Help File ("How do I align the UVW_Modifier's Gizmo to a selected face?" section)
ZNormal = (lengthTangent splPath 1 PathPartPos) -- get direction for the Position on the Path with LengthTangent function
worldUpVector = [0,0,1] --Set up of the world
rightVector = normalize (cross worldUpVector ZNormal) --set RightVector (X axe)
upVector = normalize ( cross rightVector ZNormal ) --set upVector at 90° of the system
Pos_RightVector = RightVector*pCont.particleVector.y --set length of x vector for particle position
Pos_upVector = upVector*pCont.particleVector.z --set length of y vector for particle position
if sw_AlignToPath == True do pCont.particlePosition = ((Pos_RightVector + Pos_upVector) + (lengthInterp splPath PathPartPos)) -- Calculate the Particle Position on the Path
if sw_AlignToPath == False do
(
PartPos_Vect = (lengthInterp splPath PathPartPos) - (getKnotPoint splPath 1 1) -- Vector from first pathKnot and current path coordinates.
pCont.particlePosition = ((Pos_RightVector + Pos_upVector) + PartEmitter.pos) + PartPos_Vect -- Calculate the Particle Position and offset it from the center of the emitter
)--end if
if sw_ReorientParticles == True do pCont.particleTM = (matrix3 rightVector ZNormal upVector pCont.particlePosition) -- Create a Matrix for the particle shape Orientation
)--end if
)--end if
)--end for
)--end proceed
on Release pCont do ()
To use as a Script Test :
on ChannelsUsed pCont do
(
pCont.useTM = true
pCont.useAge = true
pCont.usePosition = true
pCont.useVector = true
pCont.useTime = true
)
on Init pCont do ()
on Proceed pCont do
(
count = pCont.NumParticles()
splPath = $Line01 -- Path to follow. Put your path name here
PartEmitter = $'PFlow Emitter 01' -- Emitter to get his position
KnotPnt = (getKnotPoint splPath 1 1) -- First Knot position of the Path
NumFrames = 100 -- Number of frame that the particle take to travel over the Path
sw_Banking = True -- True/False : If you want the particle follow the orientation of the Path.
sw_AlignToPath = True -- True/False : If you want the particles follow the path from emitter (False) or directly on the Spline Path (True).
sw_ReorientParticles = True -- True/False : If you want the Transform Matrix of the particle be oriented to the Path. Useful for shape Orientation.
splEndPrcnt = 0.99999 --The percentage of the spline the script take to send particles in the following event.
--Avoid a value of 1.0 with "sw_ReorientParticles = True" because the particle will reorient on the last spline knot.
--It will create a strange movement of the particle at this moment.
if sw_Banking != True and sw_Banking != False do sw_Banking = True -- If there is something different in sw_Banking than True or False, we put True in sw_Banking
for i in 1 to count do -- loop in the particles
(
pCont.particleIndex = i
PathPartPos = (pCont.particleAge as float/ticksperframe)/NumFrames -- Get a percentage beetween 0.0 and 1.0 with the pCont.particleAge to calculate the travel position on the path (192 ticks per frame)
if sw_Banking == False do -- if you don't want the Banking
(
if pCont.particleNew do pCont.particleVector = (pCont.particlePosition - KnotPnt) -- if it's a new particle. Store a vector from the particle position to the first PathKnot
if PathPartPos <= splEndPrcnt then -- Set the new particle position if PathPartPos is smaller than 1.0
(
if sw_AlignToPath == True do pCont.particlePosition = (lengthInterp splPath PathPartPos) -- with sw_AlignToPath
if sw_AlignToPath == False do pCont.particlePosition = (lengthInterp splPath PathPartPos) + (pCont.particleVector) -- without sw_AlignToPath
)--end if
else
(
pCont.particleTestStatus = true
pCont.particleTestTime = pCont.particleTime
)
)--end if
if sw_Banking == True do -- if you want the Banking
(
if pCont.particleNew do pCont.particleVector = (pCont.particlePosition - PartEmitter.pos) -- if it's a new particle. Store a vector from the particle position to the Emitter Position
if PathPartPos <= splEndPrcnt then -- if PathPartPos is smaller than 1.0
(
-- Axis reconstruction - Thanks to Bobo for the explanation in the Max Help File ("How do I align the UVW_Modifier's Gizmo to a selected face?" section)
ZNormal = (lengthTangent splPath 1 PathPartPos) -- get direction for the Position on the Path with LengthTangent function
worldUpVector = [0,0,1] --Set up of the world
rightVector = normalize (cross worldUpVector ZNormal) --set RightVector (X axe)
upVector = normalize ( cross rightVector ZNormal ) --set upVector at 90° of the system
Pos_RightVector = RightVector*pCont.particleVector.y --set length of x vector for particle position
Pos_upVector = upVector*pCont.particleVector.z --set length of y vector for particle position
if sw_AlignToPath == True do pCont.particlePosition = ((Pos_RightVector + Pos_upVector) + (lengthInterp splPath PathPartPos)) -- Calculate the Particle Position on the Path
if sw_AlignToPath == False do
(
PartPos_Vect = (lengthInterp splPath PathPartPos) - (getKnotPoint splPath 1 1) -- Vector from first pathKnot and current path coordinates.
pCont.particlePosition = ((Pos_RightVector + Pos_upVector) + PartEmitter.pos) + PartPos_Vect -- Calculate the Particle Position and offset it from the center of the emitter
)--end if
if sw_ReorientParticles == True do pCont.particleTM = (matrix3 rightVector ZNormal upVector pCont.particlePosition) -- Create a Matrix for the particle shape Orientation
)--end if
else
(
pCont.particleTestStatus = true
pCont.particleTestTime = pCont.particleTime
)
)--end if
)--end for
)--end proceed
on Release pCont do ()
There are variables and switches (sw_) to modify the behavior of the particles over the path.
There are some example of how they affect the animation.
"sw_Banking" activate the banking. Put False in it and the particles behavior will be the same than
the older script.
sw_AlignToPath = True, sw_ReorientParticles = True
[img] http://www.alienstrabism.com/perso/pflow/pathf_ao.gif [/img]
sw_AlignToPath = True, sw_ReorientParticles = False
[img] http://www.alienstrabism.com/perso/pflow/pathf_a.gif [/img]
sw_AlignToPath = False, sw_ReorientParticles = True
[img] http://www.alienstrabism.com/perso/pflow/pathf_o.gif [/img]
sw_AlignToPath = True, sw_ReorientParticles = False with a Spin in the event.
[img] http://www.alienstrabism.com/perso/pflow/pathf_as.gif [/img]
A bunch of planes trapped in a vortex. :)
[img] http://www.alienstrabism.com/perso/pflow/pathf_ap.gif [/img]
I put some comments to help you to understand the script. I'am learning maxscript too ;)
My script is certainly "improvable" in is efficiency. I hope it will be useful for you. :)
Cheers.
Thanks a lot Johnny,
There are some tools to do the same thing. I wanted to code something myself.
So, by now, I must optimize the animated Gif because it’s a bit heavy.
Great Script BebeteLANUITE, thanks for the link scrimski
with a rating from Bobo it must be good
This is my first time using Particle Flow and your script has worked well.
The only thing is i cant get the banking, align to path or reorient particles switches working, none of the changes to the switches that i made in the script seemed to have worked (and then save – is that all i need to do?) I just changed from True to False.
The vertical series of blue arrows is flows along an animated spline representing a hydraulic hose. This moves from side to side as the pistons operate. The animation is working well though i cant get the arrows to orient to the spline. As you can see they all point up but i need them to be aligned exactly so as to represent hydraulic flow along a hose. Can you see what i may have done wrong? Do other operators override the script?
NSF / Andrew You need to insert a Script Operator in the particle view –> edit script and paste BebeteLANUITE script to replace the exsiting script. Rename the spline and particle source in the script to reflect your own. Save viola…
BebeteLANUITE – you mentioned there were other methodologies to achieve the same effect of particles along animated splines, can you suggest others?
Hello Jobwallis,
I'am happy if my script was useful for you.
So i look to your work and your image. I tried to do the same thing than you and it works for me.
So I see just one thing in the Script on your image.
at the line :
PartEmitter =
you type :
PartEmitter = $Manif -> Pist LH
In maxscript, the spaces in names must be code as underscore "_".
PFlow Emitter 01 --> becomes in maxscript --> $PFlow_Emitter_01
But you can type it like this :
$'PFlow Emitter 01'
So your object name becomes :
PartEmitter = $Manif_->_Pist_LH
or
PartEmitter = $'Manif -> Pist LH'
The second way is interesting because it let you the freedom to write the name with spaces.
So you can test this to see if i works because the rest of your flow seems to be ok.
If this don’t work tell me and i’ll look further
In fact, i think there a lot of method to achieve the same result in maxscript.
But there are some tools/plugins for 3dsmax to get the same results with less scripting, i think.
I think to the ToolBoxes from orbaz.com that add a lot of cool stuffes to PFlow. (I didn't test them yet. But they sound good). There is "Thinking Particles" from cebas. (I didn't test it but a friend tell me it's pretty good). So I think one of this plugin can do what you want.
So i'am not a big artist in particle system. I wrote the script to learn maxscript and to solve my problem at this moment ;-).
Hope this help you.
Hi BebeteLANUITE
I have tried your amendments though to no effect.
If you have a chance could you have a look at the file and see if you can detect what is wrong.
download max 2009 file
It is odd that i have changed many of the switches and they have no result.
I even changed the name of the particle source to the name of the speed by icon and this didnt change anything either so i have an error somewhere.
thanks
i think part of my problem is that changes to the script that i make are not being reflected.
I deleted all of the text in the script and saved without any effect.
I deleted the operator and reloaded your script with the name changes that you suggested in your post and it fails to work at all. All the particles are static at the start of the spline.
Makes me think what is wrong is that i am not properly making the changes i make apparent on the script operator. All you need to do is save the script right?
OK i fixed it now it is aligned to the spline.
I got your switches to work.
the problem was that changes to the script were not being reflected in the scene when i saved, i actually had to close the script window for changes to be reflected. I think thats pretty odd.
any way i’ll prob have more questions soon.
thanks