Notifications
Clear all

[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.

5 Replies

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