[Closed] MassFX Maxscript quick reference
I was playing around with MassFX and found both the Help file and CGtalk’s forums lacked a practical example of using MassFX with maxscript.
So, I wrote a quick and dirty ‘Getting Started with MassFX’ script. Here ya go:
--massFX maxscript playground
( --main
--setup the physx options we need
local myPhysx = PhysXPanelInterface.instance
myPhysx.useGroundPlane = true
myPhysx.onLastFrame = 2 --stop simulation on last frame
myPhysx.useMultiThread = true
--define massFX rigid body modifier
local myMassFX = MassFX_RBody()
myMassFX.type = 2 --set the mesh to be kinematic, to be switched later
myMassFX.switchType = true --must have
myMassFX.switchTypeAtFrame = 1 --the mesh becomes 'active' on this frame
--**this would be the frame at which an impact activates the obj
--create a random number of boxes, randomly rotate, randomly position
local myBox = Box lengthsegs:1 widthsegs:1 heightsegs:1 length:20 width:20 height:20 mapcoords:on pos:[0,0,0] isSelected:off
max modify mode
for i=1 to 10 do
(
local newObj = copy myBox
newObj.pos = [(random 0 360),(random 0 360),(random 0 360)]
ranRotate = eulerangles (random 0 360) (random 0 360) (random 0 360)
rotate newObj ranRotate
addModifier newObj (myMassFX)
)
delete myBox --we use the copy method cause it's faster than creating each box
nvpx.InitializePhysX
nvpx.CreateToolbar()
nvpx.ShowToolbar true
) --end main
Run the script, it creates some boxes, assigns them rigidBody modifiers, and pops open the MassFX tollbar. Just press the button that looks like a play button with a gear behind it to start the simulation.
Hopefully this helps someone looking for a reference on how to use MassFX in their scripts.
As you can see from the example above, integrating this into a fracturing script like GARP’s Fracture Voroni is trivial.
Please note this only works with Max2012.
Here is the example above with additional code that fragments the cubes. It’s pretty quick too, but I’m sure it could be faster.
--massFX maxscript playground 2
( --main
resetMaxFile #noPrompt
--setup the physx options we need
local myPhysx = PhysXPanelInterface.instance
myPhysx.useGroundPlane = true
myPhysx.onLastFrame = 2 --stop simulation on last frame
myPhysx.useMultiThread = true
--define massFX rigid body modifier
local myMassFX = MassFX_RBody()
myMassFX.type = 2 --set the mesh to be kinematic, to be switched later
myMassFX.switchType = true --must have
myMassFX.switchTypeAtFrame = 1 --the mesh becomes 'active' on this frame
--**this would be the frame at which an impact activates the obj
--create a random number of boxes, randomly rotate, randomly position
local myBox = Box lengthsegs:1 widthsegs:1 heightsegs:1 length:20 width:20 height:20 mapcoords:on pos:[0,0,0] isSelected:off
max modify mode
for i=1 to 10 do
(
local newObj = copy myBox
centerPivot newObj
newObj.pos = [0,0,0]
--slice up the box
for g=1 to 3 do
(
local thePlane = plane width:100000 length:100000 widthSegs:2 lengthSegs:2 isSelected:off
thePlane.pos = [0,0,0]
seed (random 0 10000)
local myRand = eulerangles (random -1000 1000) (random -1000 1000) (random -1000 1000); rotate thePlane myRand
addModifier newObj (sliceModifier slice_type:1)
newObj.slice.slice_plane.pos = thePlane.pos
newObj.slice.slice_plane.transform = thePlane.transform
delete thePlane
addModifier newObj (cap_holes())
convertToPoly newObj
)
newObj.pos = [(random 0 360),(random 0 360),(random 0 360)]
ranRotate = eulerangles (random 0 360) (random 0 360) (random 0 360)
rotate newObj ranRotate
--detach all the subelements via haavard's method
for f in newObj.faces do
(
el = polyop.getElementsUsingFace newObj f
polyop.detachFaces newObj el asNode:true name:"fragment"
)
delete newObj
)
delete myBox --we use the copy method cause it's faster than creating each box
for node in Geometry do (centerPivot node; addModifier node (myMassFX))
nvpx.InitializePhysX
nvpx.CreateToolbar()
nvpx.ShowToolbar true
) --end main
The above code suffers from a fatal flaw: the modifiers are all instanced, and therefore use the wrong mesh for collision detection. Here’s a script with unique massFX modifiers:
--massFX maxscript
( --main
resetMaxFile #noPrompt
local start = timeStamp()
--setup the physx options we need
local myPhysx = PhysXPanelInterface.instance
myPhysx.useGroundPlane = true
myPhysx.onLastFrame = 2 --stop simulation on last frame
myPhysx.useMultiThread = true
--create a random number of boxes, randomly rotate, randomly position
local myBox = Box lengthsegs:1 widthsegs:1 heightsegs:1 length:20 width:20 height:20 mapcoords:on pos:[0,0,0] isSelected:off
max modify mode
for i=1 to 10 do
(
local newObj = copy myBox
centerPivot newObj
newObj.pos = [0,0,0]
--slice up the box
for g=1 to 5 do
(
local thePlane = plane width:1000 length:1000 widthSegs:2 lengthSegs:2 isSelected:off
thePlane.pos = [0,0,0]
seed (random 0 1000)
local myRand = eulerangles (random -1000 1000) (random -1000 1000) (random -1000 1000); rotate thePlane myRand
addModifier newObj (sliceModifier slice_type:1)
newObj.slice.slice_plane.pos = thePlane.pos
newObj.slice.slice_plane.transform = thePlane.transform
delete thePlane
addModifier newObj (cap_holes())
convertToPoly newObj
)
newObj.pos = [(random -360 360),(random -360 360),(random 100 360)]
ranRotate = eulerangles (random 0 360) (random 0 360) (random 0 360)
rotate newObj ranRotate
--detach all the subelements via haavard's method
for f in newObj.faces do
(
el = polyop.getElementsUsingFace newObj f
polyop.detachFaces newObj el asNode:true name:"fragment"
)
delete newObj
)
delete myBox --we use the copy method cause it's faster than creating each box
for node in Geometry do
(
--define massFX rigid body modifier
local myMassFX = MassFX_RBody()
myMassFX.type = 2 --set the mesh to be kinematic, to be switched later
myMassFX.switchType = true --must have
myMassFX.switchTypeAtFrame = 1 --the mesh becomes 'active' on this frame
myMassFX.bounciness = 0.2
myMassFX.ContinuousCollisionDetection = true
centerPivot node
addModifier node (myMassFX)
)
nvpx.InitializePhysX
nvpx.CreateToolbar()
nvpx.ShowToolbar true
local myTotalTime = ((timeStamp() - start) / 1000.0) as string
myTotalTime += " seconds taken for completion."
print myTotalTime
gc()
) --end main
An interesting thing happens on my machine if you run the script above twice in a row.
And by interesting I mean “unknown system exception”.
Would you run the script above twice in a row and see if max throws an error?
So, max is crashing when trying to apply a massFX modifier to certain meshes.
I added this bit of code to the code above:
for node in Geometry do
(
--define massFX rigid body modifier
local myMassFX = MassFX_RBody()
myMassFX.type = 2 --set the mesh to be kinematic, to be switched later
myMassFX.switchType = true --must have
myMassFX.switchTypeAtFrame = 1 --the mesh becomes 'active' on this frame
myMassFX.bounciness = 0.2
myMassFX.ContinuousCollisionDetection = true
centerPivot node
[b]try(addModifier node (myMassFX))catch(print node)[/b]
)
Max prints out a series of nodes that didn’t get the MassFX_RBody modifier applied to them.
In the scene I can verify this by selecting one of the meshes. No modifier is applied.
When I try to manually apply a MassFX_RBody modifier to the mesh in question, Max immediately stops working and crashes.
Can anyone else duplicate this problem?
So I ran the script a few times and logged the output from the listener window.
The exception manifests intermittently. I can’t duplicate it 100% of the time, but it’s there.
I made sure to restart max after a while to check and see if that changes anything.
Here’s the log:
Welcome to MAXScript.
Note: PhysX SDK initialized
Note: PhysX Plugin initialized
Max to Physcs Geometry Scale = 1.0
$Editable_Poly:fragment115 @ [94.685944,71.217796,287.948486]
$Editable_Poly:fragment116 @ [99.709534,79.688889,291.352081]
$Editable_Poly:fragment117 @ [90.710770,77.665176,280.564270]
$Editable_Poly:fragment118 @ [95.938469,83.103012,282.806793]
$Editable_Poly:fragment119 @ [97.865189,80.446938,295.045837]
$Editable_Poly:fragment120 @ [100.425980,80.167351,287.453094]
$Editable_Poly:fragment121 @ [94.907379,85.647964,288.264435]
$Editable_Poly:fragment122 @ [95.361069,82.139923,281.967896]
$Editable_Poly:fragment123 @ [220.776306,256.302124,269.160370]
$Editable_Poly:fragment124 @ [216.473007,252.574310,278.670105]
$Editable_Poly:fragment125 @ [211.349625,259.073181,266.812927]
$Editable_Poly:fragment126 @ [217.996796,251.554337,270.565948]
$Editable_Poly:fragment127 @ [219.728149,255.360535,271.419647]
$Editable_Poly:fragment128 @ [212.491425,264.921448,272.536713]
$Editable_Poly:fragment129 @ [209.408722,255.502472,267.895447]
$Editable_Poly:fragment130 @ [209.895630,255.622620,277.283569]
$Editable_Poly:fragment131 @ [216.429886,252.602310,278.876312]
$Editable_Poly:fragment132 @ [212.286835,257.101257,277.582794]
$Editable_Poly:fragment133 @ [218.367157,251.344238,269.611725]
$Editable_Poly:fragment134 @ [210.033905,255.309677,270.630463]
$Editable_Poly:fragment135 @ [216.979767,251.973633,268.954285]
"2.408 seconds taken for completion."
$Editable_Poly:fragment001 @ [280.327148,165.357849,200.208160]
$Editable_Poly:fragment002 @ [281.521545,154.366852,192.948059]
$Editable_Poly:fragment003 @ [274.887604,161.821152,201.182312]
$Editable_Poly:fragment004 @ [286.114441,159.227737,200.109009]
$Editable_Poly:fragment005 @ [272.403900,159.290802,197.910233]
$Editable_Poly:fragment006 @ [282.173065,154.074707,193.741409]
$Editable_Poly:fragment007 @ [283.467743,156.760742,195.539932]
$Editable_Poly:fragment008 @ [272.428314,157.877609,197.844666]
$Editable_Poly:fragment009 @ [280.327148,165.357849,200.208160]
$Editable_Poly:fragment010 @ [273.199066,157.875534,198.806564]
$Editable_Poly:fragment011 @ [283.103271,157.667953,195.146637]
$Editable_Poly:fragment012 @ [276.912720,163.884277,203.850220]
$Editable_Poly:fragment013 @ [283.388916,157.381714,203.487747]
$Editable_Poly:fragment014 @ [329.891754,-18.258015,359.596222]
$Editable_Poly:fragment015 @ [323.985291,-5.730327,350.746490]
$Editable_Poly:fragment016 @ [331.788727,-10.700636,360.197601]
$Editable_Poly:fragment017 @ [330.142365,-17.259594,359.675659]
$Editable_Poly:fragment018 @ [322.107208,-16.026695,356.111176]
$Editable_Poly:fragment019 @ [331.768402,-9.365793,351.880554]
$Editable_Poly:fragment020 @ [330.643311,-14.045615,352.683197]
$Editable_Poly:fragment021 @ [321.780121,-16.202301,359.349640]
$Editable_Poly:fragment022 @ [329.767334,-17.075876,349.707550]
$Editable_Poly:fragment023 @ [324.374969,-15.400731,349.917328]
$Editable_Poly:fragment024 @ [330.471497,-14.861547,353.400513]
$Editable_Poly:fragment025 @ [329.745117,-17.669960,352.668976]
$Editable_Poly:fragment026 @ [331.012238,-12.108441,350.056335]
$Editable_Poly:fragment027 @ [324.827789,-16.672241,355.641846]
$Editable_Poly:fragment028 @ [246.751678,-79.443710,352.840088]
$Editable_Poly:fragment029 @ [250.496567,-70.636826,354.768219]
$Editable_Poly:fragment030 @ [253.318604,-84.316605,358.794403]
$Editable_Poly:fragment031 @ [250.032684,-72.996315,360.999634]
$Editable_Poly:fragment032 @ [252.635239,-81.463943,352.208160]
$Editable_Poly:fragment033 @ [253.147797,-79.787430,352.881104]
$Editable_Poly:fragment034 @ [245.998077,-76.096146,356.897491]
$Editable_Poly:fragment035 @ [258.671417,-76.223366,357.647461]
$Editable_Poly:fragment036 @ [248.721146,-74.696976,353.954071]
$Editable_Poly:fragment037 @ [255.920288,-74.912735,361.289612]
$Editable_Poly:fragment038 @ [250.245773,-71.152451,354.703491]
$Editable_Poly:fragment039 @ [254.923996,-73.977722,355.213165]
$Editable_Poly:fragment040 @ [254.849457,-83.550659,357.121765]
$Editable_Poly:fragment041 @ [-170.214066,136.279587,207.118362]
$Editable_Poly:fragment042 @ [-169.565170,148.517853,207.375595]
$Editable_Poly:fragment043 @ [-176.621063,143.932861,207.235489]
$Editable_Poly:fragment044 @ [-173.123886,135.721359,205.847717]
$Editable_Poly:fragment045 @ [-164.059021,140.252213,206.072327]
$Editable_Poly:fragment046 @ [-171.661087,146.947205,210.078323]
$Editable_Poly:fragment047 @ [-172.580963,147.384537,199.130936]
$Editable_Poly:fragment048 @ [-169.561432,145.555145,210.406189]
$Editable_Poly:fragment049 @ [-168.744736,146.966949,207.508743]
$Editable_Poly:fragment050 @ [-170.324646,142.858749,209.236084]
$Editable_Poly:fragment051 @ [-165.452179,139.028854,209.800186]
...*
"2.758 seconds taken for completion."
6362068L
**restarted max**
Welcome to MAXScript.
Note: PhysX SDK initialized
Note: PhysX Plugin initialized
Max to Physcs Geometry Scale = 1.0
"1.686 seconds taken for completion."
6347384L
"1.629 seconds taken for completion."
6346224L
"1.675 seconds taken for completion."
6347336L
"1.751 seconds taken for completion."
6346232L
"1.767 seconds taken for completion."
6347336L
"1.798 seconds taken for completion."
6346232L
"1.803 seconds taken for completion."
6347336L
**no problems this time around, ???????**
**restarted max**
Welcome to MAXScript.
Note: PhysX SDK initialized
Note: PhysX Plugin initialized
Max to Physcs Geometry Scale = 1.0
$Editable_Poly:fragment075 @ [94.685944,71.217796,287.948486]
$Editable_Poly:fragment076 @ [99.709534,79.688889,291.352081]
$Editable_Poly:fragment077 @ [90.710770,77.665176,280.564270]
$Editable_Poly:fragment078 @ [95.938469,83.103012,282.806793]
$Editable_Poly:fragment079 @ [97.865189,80.446938,295.045837]
$Editable_Poly:fragment080 @ [100.425980,80.167351,287.453094]
$Editable_Poly:fragment081 @ [94.907379,85.647964,288.264435]
$Editable_Poly:fragment082 @ [95.361069,82.139923,281.967896]
...*
"2.119 seconds taken for completion."
6367028L
$Editable_Poly:fragment @ [-170.214066,136.279587,207.118362]
$Editable_Poly:fragment001 @ [-169.565170,148.517853,207.375595]
$Editable_Poly:fragment002 @ [-176.621063,143.932861,207.235489]
$Editable_Poly:fragment003 @ [-173.123886,135.721359,205.847717]
$Editable_Poly:fragment004 @ [-164.059021,140.252213,206.072327]
$Editable_Poly:fragment005 @ [-171.661087,146.947205,210.078323]
$Editable_Poly:fragment006 @ [-172.580963,147.384537,199.130936]
$Editable_Poly:fragment007 @ [-169.561432,145.555145,210.406189]
$Editable_Poly:fragment008 @ [-168.744736,146.966949,207.508743]
$Editable_Poly:fragment009 @ [-170.324646,142.858749,209.236084]
$Editable_Poly:fragment010 @ [-165.452179,139.028854,209.800186]
$Editable_Poly:fragment011 @ [-166.826141,138.603958,205.059387]
$Editable_Poly:fragment012 @ [-168.725449,146.721359,207.726273]
$Editable_Poly:fragment013 @ [-168.403763,145.622879,208.281174]
$Editable_Poly:fragment014 @ [-67.088753,-167.036453,141.330872]
$Editable_Poly:fragment015 @ [-61.055084,-166.802734,136.652374]
$Editable_Poly:fragment016 @ [-61.993446,-166.947525,140.523743]
$Editable_Poly:fragment017 @ [-64.657333,-166.994019,140.945724]
$Editable_Poly:fragment018 @ [-63.327579,-161.698517,132.937683]
$Editable_Poly:fragment019 @ [-63.255241,-161.725525,133.745605]
$Editable_Poly:fragment020 @ [-63.060120,-161.704544,133.205124]
$Editable_Poly:fragment021 @ [-63.070793,-166.966324,140.694397]
$Editable_Poly:fragment022 @ [-63.253979,-161.723053,133.674667]
$Editable_Poly:fragment023 @ [-67.029556,-167.035431,141.321503]
$Editable_Poly:fragment024 @ [-61.991329,-161.677582,132.795242]
$Editable_Poly:fragment025 @ [-69.275589,-171.796448,133.515717]
$Editable_Poly:fragment026 @ [-62.874474,-161.732254,134.073074]
$Editable_Poly:fragment027 @ [0.468079,180.152176,240.738785]
$Editable_Poly:fragment028 @ [4.250955,175.848602,232.017822]
$Editable_Poly:fragment029 @ [9.135759,185.332458,241.034973]
$Editable_Poly:fragment030 @ [4.890072,176.332657,230.891678]
$Editable_Poly:fragment031 @ [4.126886,175.852936,235.572845]
$Editable_Poly:fragment032 @ [11.747146,182.151443,240.036621]
$Editable_Poly:fragment033 @ [4.985987,176.705170,240.900665]
$Editable_Poly:fragment034 @ [1.521538,179.077850,235.344025]
$Editable_Poly:fragment035 @ [9.890162,180.490112,234.657028]
$Editable_Poly:fragment036 @ [5.213295,176.889359,240.908371]
$Editable_Poly:fragment037 @ [3.951722,175.859055,240.591919]
$Editable_Poly:fragment038 @ [7.314209,181.315018,230.970200]
$Editable_Poly:fragment039 @ [8.162771,179.279282,241.008392]
$Editable_Poly:fragment040 @ [6.425142,182.768707,240.943497]
$Editable_Poly:fragment041 @ [94.525856,72.756310,283.574097]
$Editable_Poly:fragment042 @ [90.965111,82.439285,288.028229]
$Editable_Poly:fragment043 @ [102.181572,78.527000,286.230530]
$Editable_Poly:fragment044 @ [90.725365,78.990784,282.707764]
$Editable_Poly:fragment045 @ [100.488548,79.366196,289.799896]
$Editable_Poly:fragment046 @ [97.236107,77.857605,283.852112]
$Editable_Poly:fragment047 @ [94.685944,71.217796,287.948486]
$Editable_Poly:fragment048 @ [99.709534,79.688889,291.352081]
$Editable_Poly:fragment049 @ [90.710770,77.665176,280.564270]
$Editable_Poly:fragment050 @ [95.938469,83.103012,282.806793]
$Editable_Poly:fragment051 @ [97.865189,80.446938,295.045837]
$Editable_Poly:fragment052 @ [100.425980,80.167351,287.453094]
$Editable_Poly:fragment053 @ [94.907379,85.647964,288.264435]
$Editable_Poly:fragment054 @ [95.361069,82.139923,281.967896]
...*
"2.678 seconds taken for completion."
6365908L
**restarted max**
Welcome to MAXScript.
Note: PhysX SDK initialized
Note: PhysX Plugin initialized
Max to Physcs Geometry Scale = 1.0
$Editable_Poly:fragment087 @ [94.685944,71.217796,287.948486]
$Editable_Poly:fragment088 @ [99.709534,79.688889,291.352081]
$Editable_Poly:fragment089 @ [90.710770,77.665176,280.564270]
$Editable_Poly:fragment090 @ [95.938469,83.103012,282.806793]
$Editable_Poly:fragment091 @ [97.865189,80.446938,295.045837]
$Editable_Poly:fragment092 @ [100.425980,80.167351,287.453094]
$Editable_Poly:fragment093 @ [94.907379,85.647964,288.264435]
$Editable_Poly:fragment094 @ [95.361069,82.139923,281.967896]
...*
"2.14 seconds taken for completion."
6340992L
What’s interesting to note is that there is a pattern to when the modifier fails to be applied.
In the first run, it fails on #115, in the second run, it fails immediately on #1.
Upon a restart, it works as expected for several runs.
Upon a restart, it fails on #75. Then it fails immediately on #1 again.
Upon a restart, it fails on #87. I assume it would fail on #1 if I chose to do another run here.
Thoughts? Anyone?
*… = removed text
I had to remove some text from the listener logs, as cgtalk’s forums won’t let you post a message that exceeds 25,000 characters.
I like your idea to swich type so you decide the frame the simulation begins! very helpfull! and good fragmentation basis script too. Thanks