There are many reasons you might want to access mesh information in a MASH network, we’ll take a look at two of those reasons here.
- In part 1 we’ll look at turning points off based on mesh normals.
- In part 2 we’ll look at setting point Ids based on mesh vertex colours.
For the mesh normals, the process is fairly easy, we ask the MASH API to give us the Distribute node of the network, we then ask the Distribute node for the mesh you’re distributing on, once we have that mesh, we query the closest normal to the MASH point. The end goal here is to say ‘if the mesh normal is pointing more then 20 degrees away from up, turn the point off’. In the above images this has the effect of turning the trees off on steep slopes.
Check out the script. You can copy and paste this onto any Python node (make sure your MASH network has a mesh distribution, otherwise there will be no normals to sample!).
The World node has this ‘slope’ filtering built in, but this kind of technique is useful if you aren’t using that node (for whatever reason, e.g. you want to have a completely manual placement via the Placer node, or you want a more random scattering via the Distribute node).
If performance is important to you, I highly recommend investigating the MMeshIntersector class and using that instead of MFnMesh’s closest normal command as the mesh intersector is a lot faster at this task (it takes a bit more setup which would confuse the example, so I haven’t used it here).
import MASH.api as mapi
import maya.api.OpenMaya as om
# gets a dag path from an object name
sel = om.MSelectionList()
# initialise the MASH network data for the Python node
md = openMASH.MASHData(thisNode)
# get the number of objects in the network
count = md.count()
# get the MASH network API object
waiter = mapi.getWaiterFromNode(thisNode)
network = mapi.Network(waiter)
# get the input mesh on the distribute node
meshName = cmds.listConnections(network.distribute+".inputMesh", sh=True)
# get a mesh function set for the mesh on the distribute node
meshPath = getDagPath(meshName)
meshFn = om.MFnMesh(meshPath)
# we're comparing with up
comparisonVector = om.MVector(0,1,0)
for i in range(count):
# get the closest normal to the point - note, this is SLOW
pt = om.MPoint(md.position[i].x, md.position[i].y, md.position[i].z)
normal = meshFn.getClosestNormal(pt, om.MSpace.kWorld)
# compare angles and turn off points where needed
deltaAngle = math.degrees(normal.angle(comparisonVector))
# the angle is in degrees so the result is
# "if the difference between this normal and 'up' is more then 20 degrees, turn the point off"
if deltaAngle > 20:
md.outVisibility[i] = 0
#tell MASH to write the network data