MCG Tutorial: How to make a Select By Face Area Modifier

So you want to make a Select Face By Area modifier in MCG…. here’s a quick guide.

You want two things to start with for making any modifier which modulates your existing mesh… a Modifier:TriMesh as your input and an Output: Modifier as your output Node.
Save this as “SelectFaceByArea.maxtool” in the Tools folder of MCG. You can Run this (Ctrl+E) and you’ll find it in your modifier stack and if you apply it, it will just return your original mesh.


Searching for *FaceSelection we find the “SetFaceSelection” Node, when we look at the Description for this node it says:

Signature: (TriMesh, IArray[Boolean]) -> TriMesh

So this means the node wants a TriMesh Input and will give us a TriMesh Output which we can see from the colour coding of the sockets so we can straight away plug this in between our input and output nodes. But what about this faceSelection(IArray) third socket…. Well looking at the description it says IArray[Boolean] so it wants an array of booleans to tell it which faces it wants to select. So our array must be the same size as the number of faces in the mesh.


When we look we for a node which might take our mesh and get the faces we find two, MeshFace and MeshFaces, one gives us just the one specified face and the other gives us all the faces. Using the MeshFaces node we get an IArray of faces as an output. We can plug this into our Modifier: Trimesh Node as a second connection. Looking at the description of the MeshFaces Node we see the Signature says (TriMesh) -> IArray[Face3] So it’s going to make an array of Face3 Values. You’ll find a FaceArea Node which has an input of “Face (face3)” so we can now say we want to loop over all our face3 values in the array. Now when you look for a loop node in MCG you will be dissapointed.. there isn’t one… this seems really strange at first but once you’re used to it, you’ll see why. What we want here is a ‘Map’ node… that takes an IArray and outputs an IArray and it performs a function on each item in the array.


The fxn(Func) input is where we want to define what our function is… So what is our function? We want to go test every face against a value to see if it’s Less than it. So we are starting with a size, comparing it against a size, and returning a true/false value. Which is good as we want to start with an IArray of face3 values and end up with an IArray of Boolean (true/false) values. Our faceArea node outputs a ‘Single’ value, which is basically a float.. we want to test it against another single value so we could either define the value within MGG or we could make it a Parameter so the user can play with the value… so let’s do that. Create a Parameter:Single and then join both of these up with a LessThanOrEqual Node… which should hopefully make sense. The LessThanOrEqual node can have ‘Any’ inputs or outputs, but your inputs should match in type.. you can’t compare Integers and Singles as it doesn’t do type conversion for you, so you may need in another case to use a ‘asFloat’ node as well.


So that’s our function in isolation. Now take the Function(fxn) output of the LessThanOrEqual node and connect it into the fxn(Func) input socket of the Map node. You’ll notice of course that the face3 socket of the FaceArea node doesn’t have anything in it. This is where MCG’s user experience is a bit tricky to get at first. The Map node throws out each item in the IArray and it’s actually clever enough to know where the argument is supposed to go. With the socket open it knows this is where to throw the array item to. So we’ve now got a function which tests our parameter against the face area.


One last annoying user experience quirk. If you Save and Run this (Ctrl+E) it won’t look like it’s working, but actually it is… MCG can’t invoke the sub-selection mode in the modifier stack. So if you put a PolySelect modifier below yours and set it to Face mode, now your tool will work.


Posted in 3dsmax, Lessons, MCG | Leave a comment

MCG Drop the Population

The Populate feature in 3dsmax is one of the most frustrating for me… the technology behind it is pretty damn awesome but the implementation is immensely frustrating, it’s awful for scripts/tool developers as there’s very little to access.  The quality of the models hasn’t been improved and the UI for making people look how you want them is very tricky to use.  When you know how you can actually make people look like business people.


One of the most common frustrations is that the people can only walk on flat surfaces, putting ramps in is complicated and this doesn’t allow you to put things like kerbs in for people to walk off or have slightly undulating surfaces.  Someone asked if it was possible for Autodesk to add support for uneven surfaces and that gave me an idea.  Can we use MCG to move the meshes down to the surface? MCG is pretty good for doing ray-testing and manipulating meshes, so I gave it a go.  Here’s a Dave-friendly way of trying to explain how it works. It’s a fairly simple graph so I recommend opening it up and having a look!  It can probably be used for other things too so have a play and let me know!


The challenge was to work out how to do a hit-test from the point of the character down to an object below. We start by using the Modifier (Matrix) which if we get the row4 element gets us the position of our node in world space. But how do we do a hit test I wondered….. which wasn’t too complicated to do once I discovered the Ray node which wants a position and a vector (direction made from ‘Z axis’ and turned downwards using the ‘Negate’node), this fires a ray off and you pass that to ‘NodeIntersects’ node which is which object in the scene you want to see if the ray intersects with, pass these two together and you’ll get a Tuple Value which consists of a ray and a boolean value, so with this we can find out where our intersection is and if it actually intersected as well. A Tuple value is two values together and to get just one out we use a PairItem1 node which gives us the first value, which in this case is the intersection Ray, so we use the node RayPosition to get the position of the ray and then we extract the Z point of this vector 3 to be able to put this into a new vector 3 value, which is an XYZ value, we want to offset the vertices in our mesh only in X (because Populate is weird) so we set Y and Z to a constant single (float) of 0.0 and then pass our new Z value to it and then pass this new vector to the OffsetMesh node.   I added a little extra Z Offset value to make sure that we could adjust the alignment if it wasn’t quite right (normally isn’t it turns out).

Version 1.1

If the Populate flow was created not at 0 in Z Axis you had to do a fairly hefty manual offset, now you just need to select your Populate Flow node as well and it doesn’t matter how high your Flow is, it’ll still conform down. Note, moving your flow node up and down after creating people won’t be interactive with this tool.

You can get it here on ScriptSpot.

I have real hopes for what MCG will bring to 3dsmax, little things like this are easy to set up and extremely powerful!   I wonder if I can make a Populate person walk along a custom spline… hmmmm

Posted in Uncategorized | 1 Comment

Power Masker

The 3dsmax UI only allows you to set material effects ID up to 16 channels. The VRayMtl allows you to go beyond this using the effects ID override but other types of materials don’t have any UI to adjust this. This tool using a backdoor into 3dsmax to set the effects ID beyond the 16 limit imposed by the UI.

This means you can create masks for every material in your scene. Using this tool you can either assign effects IDs by hand or just press to automatically create them and their mask render elements.

You can also make a Vray Multi-matte mask for each layer in the scene too, this uses the include/exclude lists rather than the GBuffferIds, so that you can therefore use the GBuffer IDs for doing variation with texture maps or mask objects individually if you want to.

Get it on ScriptSpot!


Posted in MaxScript, Uncategorized | 2 Comments

Nothing is ever finished…

Last week I released a little script called the VRay Material Override Excluder. Just to prove nothing is ever finished, even the name has changed since I last blogged about it on here.

Updates include, support for VRay Material Override Include/Exclude list from the render settings, get the material from there too, override XRefScene object materials and use multiple wildcard entries to filter out material names that you don’t want to exclude.

I really hope all this power will encourage you to be more organised with your scenes!

You’ll hear a lot from software companies talking about ‘Agile’ developments these days, and being responsive and being able to improve and quickly add new bits to plugins/scripts/software is really important to be competitive and relevant.

I love the power of crowd-sourcing for ideas, you are never smart enough to think of every use-case scenario, you will never find all the bugs yourself, and you don’t have every different version of max to test your tools with. It’s something about 3dsmax users in particular which makes them so passionate about using the software, they care, it’s why Autodesk will never be able to kill off 3dsmax.  I put up a script on a website and instantly I get feedback, ‘this doesn’t work as I expect’, ‘oh it can’t do this?’, ‘it would be awesome if it could do this…!’ In the matter of one week I pretty much doubled the code size whilst putting in protection to make sure the script would never crash and would work in every situation and have some new functionality.  What I lose in publicly releasing this scripts I gain massively in feedback, it’s a huge amount more powerful and with the enthusiasm and persistent drive to want more and better tools I find it helps me stay focused on getting the tool finished rather than being resigned to the scrap-heap of scripts I have somewhere on my old laptop.

The next thing is how do I make this script professional? It started as a 10 line bit of code on the Chaosgroup forum… now it’s 700 lines long and can do so much. But it’s still a script in a rollout. There’s no API, you can’t assign hot-keys to the main functionality, and if you are doing chalk setups every day as part of your job you may want a one-click button to set all your options. This is where setting up a script as a struct is such a good idea.  I will at some point soon convert this script and expose the functions within the script so that you can make your own tools that interface with it.  It’s a change in style I started to adopt a few months ago whilst working on some personal ideas with some 3d friends, learning from people like Daniel Santana from YCDIVFX, I’ve been building struct scripts with APIs so that they can be used by other TDs in their tools.

To be continued…

Posted in 3dsmax, MaxScript | Leave a comment

Chalk Mat Switcher

Do you use the Vray Material Override to do chalk renders and wish that it would allow you to exclude certain materials? Like VRayLightMtl and any refractive materials like glass? Well now you can using this little script.  It sets up a Shell Material which allows you to switch from one material setup to another. So even if those pesky VRayLightMtls and refractive materials are within Multi-sub materials then you’ll still be able to exclude them. Give it a go, test it out and let me know how it works for you! Cheers to Fraggle from the Chaosgroup forums for giving me the motivation to do this one, I’m sure I’ll find a use for it at some point too. It should be easy enough to hack it for Mental Ray or other renderers.


Choose the Material Editor Sample Slot you want to get your Chalk Shader from, that’s down bottom left in Slate or one of the sample slots in the Compact-Material-Editor.  Keep the excludes on for whichever materials you want to preserve (let me know if you want more there). You can keep refractive materials and automatically desaturate refraction / fog / exit colour/maps.

You can choose to keep opacity maps/bump maps/ displace maps this will work with nested materials, multi-sub, VrayBlends etc… You can also exclude by a material name, and using Wildcards you can exclude all materials which have glass in their name for instance by putting in *glass* into the name exclude box.

You can also get your the objects you have in your include/exclude List in the VRay Material Override Exclude Dialog.


Press ‘Create Chalk Setup’ and your scene is now ready to render with chalk materials on, you can press ‘Go Material’ at any point to return to the original materials, and press ‘Go Chalk’ to go back to rendering chalks. Press ‘Remove Chalk Setup’ to revert back to how your scene was, even if you close and reopen the script.

Hold Shift on the ‘Go Chalk’ and ‘Go Material’ buttons to turn just the selected objects to Chalk or Material.


Get it here on ScriptSpot!

Posted in Uncategorized | Leave a comment

Sometimes there is a simpler way…

A few weeks ago I needed to have a dynamic way of selecting all the Face/Material IDs of an object and deleting everything else. My first thought was, well the Poly_Select modifier has a select by Face/Material ID. However that isn’t dynamic, if your underlying mesh changes, the Poly Select doesn’t update…. sigh.

I thought about a scripted approach with an Edit Poly modifier, but decided that was going to be too slow.

In the end I had a demo of Genome from Thinkbox (an awesome tool, if not a bit scary at first). And I made a cool little custom modifier that allowed me to select by Material ID, or select by not the Material ID.

This worked, but then the other day I realised I had over-engineered the solution. There’s a modifier which I use over and over again to make things procedural, and it’s one of 3ds Max’s most powerful tools. Volume Select allows you to keep things procedural, you can create volume shapes to recreate the manual process of going into a sub-selection and drawing out a marquee to select polygons, you can use Soft-Selection as well which is always nice. You can also select by a map material which is super useful, especially as it supports 3d maps. However the one feature I’d completely forgotten about is that it can also select by material ID! You can also Invert the selection in this modifier and thus use a DeleteMesh modifier (Again one that is under-used by most people because they don’t realise when you have a stack-selection it become very useful!)

select_by_material_ID_1 select_by_material_ID_2

Posted in 3dsmax | Leave a comment

A chance to heckle me…

I’m really pleased to be invited to give a talk at EUE (End-User-Event) in Holland this coming June. I plan to give a slightly technical talk and show some secret things I’ve been working on for the last couple of years.

If you’re based in Europe, I cannot rate this event highly enough! 250 3ds max artists in a pub, in a beautiful Dutch city. You’ll learn loads, meet some amazing people, make connections and contacts that will be infinitely useful.

Book your ticket now whilst the air-fares are cheap!

Posted in Uncategorized | 1 Comment

pFlow – Put Nodes on the Same Layer as the PFlow Source

Ever wanted to have PFlow nodes on the same layer as your PFlow Source object? But you don’t see them in the scene explorer and can’t select them in the viewport.

Well here’s a script that can do it!

—-This script puts all the Pflow events and nodes on the same layer as the PFlow Source Object

fn getPFlowChildren theNode theSource =
thechildren = for o in getpropnames theNode where (getnodebyname o) != undefined collect (getnodebyname o)
for o in theChildren do
theSource.layer.addNode o
getPFlowChildren o theSource

if classof o == Event do
for n in (refs.dependentNodes o) do theSource.layer.addNode n

for o in getclassinstances PF_Source do
theFlow = (refs.dependentnodes o)[1]
getPFlowChildren theFlow theFlow
for theNode in (refs.dependentNodes theFlow) do
theFlow.layer.addNode theNode

Posted in Uncategorized | 5 Comments

Sub-Object Isolate Toggle

One of those things which is possible when you know where the buttons are, but it should really be on a hot-key. Assign this to a shortcut key to be able to isolate within subobject mode, Vertex/Face/Element 🙂

–Toggles Isolation of editable Poly subobject face selection
if isEPolyIsolate == undefined do global isEPolyIsolate = false

if selection.count == 1 and classof selection[1] == Editable_Poly do
if not isEPolyIsolate then
with redraw off
actionMan.executeAction 0 “40044”
$.EditablePoly.Hide #CurrentLevel
actionMan.executeAction 0 “40044”
isEPolyIsolate = true
$.EditablePoly.unhideAll #CurrentLevel
isEPolyIsolate = false

Posted in Uncategorized | 1 Comment

Lesson 14: Key principles of understanding working with MaxScript

Here are the key principles to working with MaxScript, you need to know about all the things listed below to be able to understand how to write scripts. Here is a brief overview and description of each thing, I’ll try get around to linking everything to the relevant section on my blog.

Value Types

These are the key types of variables in maxscript.

String – “Text, always within quotations marks, \ is an escape characterm \t would be a tab, to avoid this you can type\\t or put@ before the first quotation”
Integer – A whole Number, 1,2,3 typing in 1.2 as integer would give you 1, typing 1.8 as integer would also give you 1, rounding does not take place automatically you need to write a function for it.
Float – A non-whole number, 1.2232 for example.
Boolean – a True or False value
Point2 – two values, [x,y], 2-dimensional position for bitmaps for example or [width,height], values are float within…. [1.23,5]
Point3 – three values, [x,y,z] or [r,g,b] this is a 3-dimensional position or colo(u)r value.
Color – expressed as (color 128 128 128) or (color 128 128 128 255), it’s either an RGB value with an assume alpha value of 255 (solid), or an RGBA value.
Box2 – This is an area of a 2d space, (Box2 x y w h), x-position, y-position, width and height
StringStream – Like a string value, but better for memory for large values, and formatting values.
FileStream – A StringStream value that is written/read from a file.
Array – A collection of values, this can be a mix of types: #(1,1.2,abc,”test”)

Class System

You need to be able to understand how the class system works in max, how things are sub-classes of superclasses, and which category

ClassOf – Find what class a max object belongs to, ie Classof $VRayLight001 returns VRayLight
SuperClassOf – findout what Superclass an object belongs to, SuperClassOf $VRayLight001 returns Light
GetClassinstances – get an array of all the objects which are of the specified class, getClassInstances VRaylight returns #(VrayLight001,VRayLight002)

Inspecting Things

ShowProperties – Shows the properties of the object, showProperties (Box()) will show all properties that can be set Box001.height =1o for example
ShowMethods – Shows the Methods associated with the object, treat theses as functions for targeted objects. layer.getlayerbyname “test”, note that there is no = , you’re not setting a value you’re calling a function.
ShowInterfaces – will show the Properties and the Methods associated with the object

Iterating and Looping

For i Loops – Iteration loops going through a numeric sequence, for i = 1 to 1000 by 2 do…..
For o Loops – For variable in collection do… for o in objects do o.boxmode = true
Collecting Loops – For when you want to go through an array and filter the items. ar_Objs = (for o in objects where o.boxmode collect o)

Functions – Call a function with arguments – testFunction valA valB – and understand how to return a value.

Understanding the Help File

To be able to learn more you’ve got to be able to understand what <BOOL>, <VOID> mean in the help file.

Posted in 3dsmax, Lessons, MaxScript | 2 Comments