View Full Version : CgTalk Maxscript Challenge 022: "Particles"

01 January 2009, 10:40 AM
CgTalk Maxscript Challenge 022: "Particles"
Thanks to David Wortley for the suggestion!

DESCRIPTION: Since particle flow has scriptable operators, it might be high time for everyone to play with it in a challenge! Try to control particles in a way the nodes can't, or extend ideas that have already been presented, such as fracturing objects crowd control systems. I'm keeping it broad so you can flex your brains. :)

This is a reasonably advanced version of the challenge, but I would encourage beginners and intermediates to find some of the great scripting tutorials out there and have a go at making something of your own.

DEADLINE: 14/2/2009


Do NOT post your code until the deadline!
Code from scratch. Try not to use pre-exisitng functions or plugins.
Show your script references, if any (eg. Looking at another script to assist you).
You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.
Post your final script inside [CODE] tags (located on your posting toolbar).
Post all code into THIS thread.
Post the max version you coded in, plus any maxscript extensions you used.
Try to finish the challenge in the proscribed time. There is no definite time limit.
NOTES: Remember that Bobo has a new DVD series out ( on this very subject!

01 January 2009, 11:08 PM
I'm in. Time to dust off Rifter.

01 January 2009, 12:48 PM
Suppose as it's my idea I better think of something as well...

02 February 2009, 02:39 AM
Just under a week before the "formal" deadline, has anyone been working on it? :)

02 February 2009, 07:13 AM
I was particularly interested in this challenge, but as I'm still in the middle of a lot of work, I barely managed to squeeze some time to dig up an old method I used roughly 3-4 years ago..
What I was generally after back then was to use PFlow to initialize the motion of the objects, then use Reactor to continue the motion with all the physics goodness.

I basically started by used the concept from this thread at Orbaz. (
- it uses a Birth Script and a Script Operator to control objects currently in the scene.

Birth Script:
on ChannelsUsed pCont do
pCont.useAge = true
pCont.useTM = true

on Init pCont do
global ChunksArray = $Chunk* as array
global fragTime = 0
global TM_Reset
TM_Reset = undefined

if ChunksArray != undefined do
if TM_Reset == undefined do TM_Reset = true
if TM_Reset do
Global ChunksArray_TM = for i in ChunksArray collect i.transform
TM_Reset = false

on Proceed pCont do
t = (pCont.getTimeEnd() as float)/ticksperframe
NumChunks = ChunksArray.count

if t == fragTime do
for i = 1 to NumChunks do
pCont.particleIndex = pCont.NumParticles()
pCont.particleAge = 0
pCont.particleTM = ChunksArray_TM[i]

and the Script Operator
on ChannelsUsed pCont do pCont.useTM = true

on Proceed pCont do
count = pCont.NumParticles()
ChunkCheck = (ChunksArray != undefined)
if chunkcheck do
for i in 1 to count do
pCont.particleIndex = i
j = pcont.particleID
ChunksArray[j].Transform = pCont.particleTM

The birth script will get and save the transforms of the objects to be used by the particles. Then the script operator will control the transforms of the scene geometry, moving, rotating, scaling them with pflow operators.

A particular setup would be like this:

The next thing to do (if you're already OK with the motion) is to bake out the motion to keyframes...

But since this method works directly with scene objects, it's not posiible to just bake them out using a PFlow Baker script. I totally forgot why I needed to control the actual objects and not just use thier .mesh property and feed it to pflow..

So in order to get the keyframes for the objects, all you need to do is:

(Under the Time Configuration Dialog)
- Set the Realtime Playback to OFF
- Set the Loop Playback to OFF

- Turn on ANIMATE
- PLAY the animation

- Turn OFF Pflow

After doing the above, we now have keyframes for the objects, and pflow can now be turned off (or deleted).

Next thing to do now is use the current baked motion and use Reactor to continue the animation. So I wrote another script to automate the simulation of each object.

The script was temporarily named "PFlow Per-Obj-Sim"

As what the name of the script says, it will simulate each object separately..
Object Collection -> assign the collection of objects that you want to simulate. Also make sure the these objects have reactor properties
Rigid Body Collection -> pick a Reactor Rigid Body Collection, with objects like walls and ground for the Object Collection to interact with. This reactor collection does NOT need to have the animated objects inside its collection list, because the script will be the one to add them during simulation.
Key Trim Offset -> this will delete N number of keyframes starting from the second to the last keyframe of the object.

If all went well with the setup, this would be the final animation.

Final Notes:
As some of you may obviously notice, there's no interaction between the objects :sad: .. that was because each object was simmed separately.. But for what I used this script for, there were just too many little chunks, that it was barely noticable..

I've attached a max file (max 9) and the per-obj-sim script.

* I hope that this didn't veer far too off from the challenge topic.
** I would also like to note that I initially did this with max6 so i can't assure if the code would still work flawlessly with new max versions.
*** also the upcoming Pflow Box2 definitely is a must for this kind of stuff.


02 February 2009, 05:43 AM
Just to add some ground to the Galagast's claim about upcoming PFTools: Box#2 - inspired by the script setup, I did a simple test with Box#2 functionality, quick and dirty. Here's the animation: ( (2.3 MB)

Oleg B.

03 March 2009, 01:09 PM
Funny i stumble across this thread :D as i just finished my first little script! YAY!

As i am just learning maxscript and saw a fracture geometry script ages ago on script spot called MBFracture ( this gave me the initial idea :)

But first i wanted to learn the basic' "For" loops and "if" statement!......Well this is what the basics it turned into :O

Basically I started on the weekend that has just finished, and made a similar little tool, no where in the realm of anything too fantastic and not really a tool for a team of people to use, but as it is my first attempt at a script (and i mean first!) so i am pretty happy with it overall result!

Also most of the reference came from watching the listener window and reading tones of maxscript help docs.

I hope this qualifies to enter:)!

Suggestion are definitely welcome!

BTW the little pflow to reactor script before is very cool, also very funny as that was going to be a little trial i was going to give myself later down thge track...o-well :) but i imagine that most of my idea would of already been made, just a case of doing it anyways so i learn :D

Cool hope you enjoy!

Okay to the script!

Things to know before hand....and this is because i am still learning and am grasping the concept of everything!

1. Currently the object it breaks needs to be under a file unit size of 100 (need to do a bounding box check on the object and feed that back to the script, but need to learn)
2. The object needs to be at world zero (need to move the cutting objects to the local position of the selected "to be cut" object)
3. For some reason the script crashes after a few goes...not sure why...
4. The object needs to be "water tight" ie haev not open edges, it crashs the script...not sure why.
5. Uncoment the "gc()" comand at own risk as this crashes the script when run (must have in incorrect place i gather)
6 You need to have the object you want to break selected first, before you execute the "Crack" button.(would like to make a list box for this, but need to learn more about how array's work ie actually write them)
7. Be kind! This is my very first attempt, but over-all i am happy with what i made!

Created by Kieran Ogden-Brunell March 2009
This script should break a selected object into chunks
Good for stone/rock debris

- Pick button for object
- List box for multi objects
- Bounding box function to drive crack plane sizes (currently this is a hard coded value of 120 in scene size)
- Dialog box for user enable cancel or continue
- Save "tick" option, so scene is saved before calculation
- Tick option to keep original mesh
- Iteration feature to run the simulation over the first pass cracks
- Minimum size threshold for breaking on first pass and iteration

-Crash's MAX randomly if used to much.
-Crash's MAX if gc() is used...sometimes...
-Process breaks if the crack planes are too small compared to the user object


rollout kobCracks "Crack Geometry"
edittext _oName "Name" fieldWidth: 160 height:16

spinner _pAmount "Crack Density" type:#integer range:[1,20,8]
spinner _pSegs "Crack Detail" type:#integer range:[10,30,20]
spinner _pNoiseHieght "Crack Shear" range:[0,120,55]
spinner _pSmoothAmount "Internal Smooth" range:[0,90,65]

button _create "Create Cracks" width:150 height:50 tooltip:"Crack Object!"--this should eventually name the seperate chunks!

on _create pressed do

if _pAmount.value >= 15 then messagebox "WARNING: Could become unstable!" --warns if you have too many planes need a cancel or continue dialog


-- create planes from the spinners value

_firstPlane = null

for j = 1 to _pAmount.value do

p= (plane()) = uniquename "cutPlanes"
if (j == 1) then _firstPlane = p
p.length = 150
p.width = 150
p.lengthsegs = _pSegs.value
p.widthsegs =_pSegs.value
p.wirecolor = [random 0 255,random 0 255,random 0 255]

--adding noise modifier to plane

addModifier p (Noisemodifier())
p.modifiers[#Noise].seed = random 1 1000
p.modifiers[#Noise].scale = random 45 85
p.modifiers[#Noise].fractal = on
p.modifiers[#Noise].strength = [(random 0.0 1),(random 0.0 1),(random _pNoiseHieght.value (_pNoiseHieght.value+5))]

--adding smooth modifier to plane

addModifier p (smooth())
p.modifiers[#smooth].autosmooth = on
p.modifiers[#smooth].threshold = _pSmoothAmount.value

--rotates planes in "for" a random value from 0 to 360 degrees

rotate p (eulerAngles (random 0 360) (random 0 360) (random 0 360))

--convert to edit poly
convertTo p (Editable_Poly)

if (j > 1) then polyop.attach _firstPlane p


-- this is the pro cutter section currently works with one cut
a = _firstPlane
c = $
ProCutter.CreateCutter #(a) 1 True True False True True
ProCutter.AddStocks a #(c) 1 1
Delete a

-- Rename objects to the name specified
all = $cutPlanes* = uniquename _oName.text


button _howToBox "Info" tooltip:"Info"

on _howToBox pressed do
messagebox "Create an Object or use an existing prop. \n Select the mesh you want to crack. \nPress Create Cracks to Run!"

button _aboutBox "About" tooltip:"About"

on _aboutBox pressed do
messagebox "This script creates cracks in selected objects\nCreated by Kieran Ogden-Brunell 2009"

createdialog kobCracks width:220 height:220


03 March 2009, 01:10 PM
mmmmMMMM Whoops just relised it was a particle comp...please dis-regard...sorry guys!!

but look by all means....

*runs and hides*


CGTalk Moderation
03 March 2009, 01:10 PM
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.