3ds Max - Object Creation in MCG
In this tutorial, you learn how to add your own tools that appear as new objects in the Geometry command panel. The tool that you learn to put together is one you would use to replace children objects in a hierarchy.
- Recorded in: 3ds Max 2016
The interface in this tutorial applies to MCG 2017. The interface in MCG 2018 has been revised to a new node naming scheme.
00:00:06 --> 00:00:13
In this movie, you learn how to create MCG tools that you output as new objects, rather than modifiers.
00:00:14 --> 00:00:19
In fact, you learn to add your own category of objects to the Geometry command panel.
00:00:20 --> 00:00:28
The tool you will develop is one that enables you to replace child objects in a hierarchy by another scene object that you define.
00:00:29 --> 00:00:34
In a new session of 3ds Max, open the Max Creation Graph Editor
00:00:34 --> 00:00:40
Well, you already know this tool will end up as a creation tool, so you may as well start with that.
00:00:41 --> 00:00:48
Press X and then type "output". Choose Output: geometry to add that operator to the view.
00:00:49 --> 00:00:54
This is the end result of the graph. The tree you create will result in that output.
00:00:54 --> 00:01:01
What else do you know? You know that you need to specify a hierarchy of objects, more specifically the top parent.
00:01:02 --> 00:01:08
You also know you need to specify a substitute object to replace all children objects in that hierarchy.
00:01:09 --> 00:01:12
That's two main branches that need to feed into that output.
00:01:13 --> 00:01:17
You'll start by defining the branch that represents a hierarchy of objects.
00:01:18 --> 00:01:26
Since you're likely to select a scene object that represents the parent object, you start by defining a Parameter: INode operator.
00:01:27 --> 00:01:32
As a reminder, use the X key to open a search box to look for operators.
00:01:32 --> 00:01:38
This essentially will create a UI button that you can use to select a node, or an object in the scene.
00:01:38 --> 00:01:45
Rename the operator: "Parent" and press Enter. Drag its output socket.
00:01:45 --> 00:01:53
Usually, with such a node, you complement it with a check validity operator to make sure all is working properly.
00:01:53 --> 00:01:59
Search for the prefix "Check" and add a CheckNodeValidity operator to the tree.
00:02:00 --> 00:02:06
Next, you use this parent node tree to tap into all child objects associated with it.
00:02:07 --> 00:02:11
Add a ChildNodes operator to the tree.
00:02:13 --> 00:02:19
Note that the value output from that operator is an array, as in multiple objects.
00:02:19 --> 00:02:24
In essence, this represents the branch that taps into the chosen hierarchy.
00:02:25 --> 00:02:33
By defining a parent input node, you're also tapping into an array of children nodes associated with that parent.
00:02:33 --> 00:02:39
You can now tackle the second branch, the one that relates to the scene object you want to use as a substitute.
00:02:40 --> 00:02:46
In fact, since it's a scene object, it requires the same two operators that you started with earlier.
00:02:47 --> 00:02:51
You can select them and Shift+Move them to create copies.
00:02:52 --> 00:02:57
However, you need to rename the Parameter: INode operator to prevent any errors.
00:02:58 --> 00:03:07
Name it: "Substitute" or "Sub Object" or any name that makes better sense to you. Make sure you press Enter to confirm the name change.
00:03:08 --> 00:03:15
Next you need to collect the mesh information of that object, so you can use it as a substitute for every child object.
00:03:16 --> 00:03:23
Add a MeshFromNode operator to that branch to extract the geometry information from the selected object.
00:03:24 --> 00:03:28
Next you need a transform operator of some sort.
00:03:28 --> 00:03:33
You need one that you can use as a bridge between the extracted geometry of the substitute object,
00:03:34 --> 00:03:38
and the current transforms of every child in the hierarchy.
00:03:38 --> 00:03:45
Drag out the value (TriMesh) output socket and add a TransformMesh operator to that branch.
00:03:50 --> 00:04:00
For a matrix (Matrix) input, you want to use a WorldTransform operator that taps into the world transform data of each and every child object.
00:04:01 --> 00:04:03
Here is where it gets a little complicated:
00:04:03 --> 00:04:08
In order to combine the two branches into one tree, you need a Map operator.
00:04:09 --> 00:04:14
A Map operator is not a tool to be confused with what you use when you define materials.
00:04:14 --> 00:04:21
A Map operator in this context transforms an array into another array, based on a function.
00:04:22 --> 00:04:27
The Array input you want to use is easy to make out, as it derives from the hierarchy branch.
00:04:27 --> 00:04:34
However, the whole branch representing the substitute object is going to be wired as a function.
00:04:35 --> 00:04:45
So; make sure you wire the function output (not the value) of the TransformMesh operator to the function input of the Map operator.
00:04:46 --> 00:04:56
This ensures every child object is replaced by the substitute object, and that every substitution preserves its rightful transform data in the hierarchy.
00:04:57 --> 00:05:01
Still, note that the Map operator outputs an array.
00:05:03 --> 00:05:07
Add a CombineAllMeshes operator to the branch,
00:05:09 --> 00:05:13
before you hook everything up to the geometry output.
00:05:15 --> 00:05:21
Before you save the graph to test it out, choose Edit > Edit Graph Properties.
00:05:21 --> 00:05:31
Add any personal Info you want to have such as your name, company, description etc… but most importantly, choose a Category name.
00:05:32 --> 00:05:36
The name you type there will appear as a new entry in the Creation panel.
00:05:37 --> 00:05:41
In this movie, I will give it the name: MCG Tools.
00:05:43 --> 00:05:50
Next choose File > Save As and give your tool a name, such as "mySub".
00:05:51 --> 00:06:00
Make sure you save it to the Max Creation Graph folder under your user name, which is the default location for saving MCG tools.
00:06:01 --> 00:06:07
Once you have saved it, evaluate it using the Build menu or by pressing Ctrl+E.
00:06:08 --> 00:06:14
Check the Creation command panel menu. Note the presence of the new MCG Tools entry.
00:06:14 --> 00:06:19
Select it and notice the new button with the name you chose for your new tool.
00:06:20 --> 00:06:25
Before you use it though, you need some kind of a scene hierarchy and a substitute object.
00:06:26 --> 00:06:30
Create something simple, maybe a few helper points around a sphere.
00:06:31 --> 00:06:35
If you want, you can also vary their rotations and scales,
00:06:39 --> 00:06:43
just make sure you link all the helpers to the sphere.
00:06:59 --> 00:07:04
Create another object, such as a teapot, to use as a substitute.
00:07:09 --> 00:07:12
Now go to your new tool and select it.
00:07:17 --> 00:07:24
Click somewhere in the scene. Note the creation of a new object named mySub001
00:07:26 --> 00:07:36
Go to the Modify panel and select the parent object, the sphere in this case, and the Substitute object, which is the teapot.
00:07:37 --> 00:07:45
The substitutes are created, but they seem a little off the mark, although they do seem to follow the same transform pattern as the points.
00:07:46 --> 00:07:56
In fact, if you were to relocate the mySub001 object to the center of the world [0,0,0], everything seems to work beautifully then.
00:07:56 --> 00:08:01
You can fix that problem in the graph so you don't have to relocate the sub node.
00:08:02 --> 00:08:11
Make sure you delete the mySub001 object from the scene but keep the rest of the objects alone, and then go back to the graph.
00:08:12 --> 00:08:20
You need a little local transformation to ensure the position of the mySub node doesn't impact the substitutes' positioning.
00:08:21 --> 00:08:27
Add a MeshInLocalSpace operator to the graph. Here, you need a bit of rewiring.
00:08:27 --> 00:08:34
Wire the function output of that new operator to the function input of the Map operator.
00:08:36 --> 00:08:43
Also wire the value output of the substitute branch to the TriMesh input of the new operator.
00:08:44 --> 00:08:51
You still need to feed it with a "Geometry: Matrix" input, so go ahead and do that.
00:08:56 --> 00:08:58
Save and evaluate.
00:09:03 --> 00:09:07
Repeat the process again to test the results.
00:09:10 --> 00:09:16
The substitutes are positioned and oriented, and even scaled properly, based on the children objects.
00:09:17 --> 00:09:23
If you tried to move the mySub001 object, it has no effect on the substitutes.
00:09:24 --> 00:09:30
The fun part is that if you were to add more children objects to the existing hierarchy,
00:09:38 --> 00:09:44
you can refresh the solution by simply moving the original substitute object.
00:09:46 --> 00:09:56
Let's try to use this tool in a more practical scenario: open the scene named childsub.max you downloaded for this tutorial.
00:09:57 --> 00:10:04
The scene mostly has 2D shapes representing chairs and tables, much like you see in CAD drawings.
00:10:04 --> 00:10:07
The chair symbols are parented to their respective tables.
00:10:08 --> 00:10:13
There is also a 3D chair that you will use as a substitute object.
00:10:13 --> 00:10:17
Try the tool out, starting with the round table:
00:10:19 --> 00:10:24
select the circle as a parent and the 3D chair as a substitute.
00:10:24 --> 00:10:29
Apart from the absence of the material, the results seem conclusive.
00:10:30 --> 00:10:36
Try it now on the conference table, by adding a new node or simply by redefining the parent object.
00:10:37 --> 00:10:47
It's still working but in this case, there is a 90-degree offset between the original orientation of the 3D chair and 2D symbols.
00:10:48 --> 00:10:52
Rotating the original 3D chair at this point would have no effect.
00:10:52 --> 00:10:59
To fix that, you will add a new parameter to your graph, to cater for a Z-rotation in one direction or another.
00:11:00 --> 00:11:06
Go back to your graph, you will need a new TransformMesh operator and some rewiring.
00:11:06 --> 00:11:11
Copy an existing TransformMesh operator by Shift+Moving it.
00:11:14 --> 00:11:20
Drag out its matrix input socket and wire it to a RotationZMatrix operator.
00:11:23 --> 00:11:28
Drag out the radians (single) socket and connect it to a ToRadians operator.
00:11:29 --> 00:11:37
This ensures that you can still input values in degrees but this operator would convert them to radians for maximum compatibility.
00:11:38 --> 00:11:44
Finally, connect the degrees (Single) input to a Parameters (Single) operator.
00:11:45 --> 00:11:56
Set the min and max values to range from -360.0 to +360.0 with a default value of 0.0
00:11:57 --> 00:12:02
Remember to always explicitely define a ".0" decimal when dealing with single values.
00:12:03 --> 00:12:11
Rename the operator: "Rotation". You still need some rewiring to hook up this branch to the existing graph.
00:12:11 --> 00:12:18
Actually, it's quite simple: simply wire the MeshFromNode operator into the new TransformMesh operator,
00:12:19 --> 00:12:22
before rerouting back to the existing graph.
00:12:31 --> 00:12:33
Save and evaluate.
00:12:38 --> 00:12:43
You now have a new UI element to control the Z rotation of the substitutes.
00:12:43 --> 00:12:48
In this case you would need a -90 degree rotation.
00:12:53 --> 00:13:01
I'll end this tutorial on the following note: you'll notice that the tool as it stands doesn't preserve applied materials from the original object.
00:13:02 --> 00:13:08
This means that for the time being, you would need to sample that material in order to apply it to the substitutes.