3ds Max References
References are like record of the relationships that exist between objects and elements of the scene. For example a Boolean-object is dependent upon its two operand objects, so anytime one of them changes the Boolean-object gets notified so it can calculate the new result, a lookat constraint is dependent upon the look-at object that is pointing to (target camera could be an example of this), or consider a simple sphere where the radius is animated, anytime this parameter is changed notifies the sphere object in order to make it bigger or smaller. References are not usually very well known by scripters, however Max architecture is heavily based on them, so I thought that some useful examples could help scripters to understand their utility. I've been playing with references enough to say that they can give you access to all the information you need from an element of your scene, areas that you couldn't access through getPropNames or subAnims.
How do I use references?
refs.dependents <MAXWrapper_object> [immediateOnly:<boolean>]
would give us an array of elements that depend of the object specified. Note that those elements could be objects, controllers, parameter blocks, etc... all of them are references to the object specified. If immediateOnly parameter is true, only the immediate dependents of the specified object would be returned.
refs.dependsOn <MAXWrapper_object>
would return an array of elements that the specified object directly depends on. For example if we ask a sphere what are its dependencies, it returns the transform controller, the sphere parameter block, and the layer where the sphere is located.
refs.dependencyLoopTest <MAXWrapper_object> <maxwrapper_object>
basically allows us to test the dependency loop between two references in the scene. For example if object A had a look-at constraint that points to Object B, and we try to create a look-at constraint for this object B, we couldn't use the object A as a target because it would create an infinite loop: I'm looking what you are looking, but ey! you were looking what I was looking , but ... wasn't I looking what you were looking ? ...
Example 1: Accessing to all controllers of an object
References become very handy in cases where you would have go through all properties/subanim/controllers/submaterials etc. Imagine you want to grab all the controllers of an object in your scene. The typical approach to this problem would be to get the subanims and go through them looking for controllers. But what happens if some controllers have subcontrollers or a controller depends of a different controller.
MAXSCRIPT:
-
-
fn getControllers ref =
-
(
-
local ctrlList = #()
-
local refList = refs.dependsOn ref
-
-
for r in refList do
-
(
-
if (isProperty r #keyable == true) then
-
append ctrlList r
-
-
join ctrlList (getControllers r)
-
)
-
-
return ctrlList
-
)
-
-
-- we create our sphere object
-
myObject = Geosphere radius:10
-
myObjectControllers = getControllers myObject
-
for c in myObjectControllers do
-
format "% - %\n" c (exprForMaxObject c)
-
Example 2: Accessing all bitmaps textures of a material With a simple modification we could grab all the bitmap textures from a material, no matter how deep they are inside submaterials, mix maps, composite maps, etc ...
MAXSCRIPT:
-
-
fn getBitmapTextures ref =
-
(
-
local bitmapList = #()
-
local refList = refs.dependsOn ref
-
-
for r in refList do
-
(
-
if (classof r == bitmaptexture) then
-
append bitmapList r
-
-
join bitmapList (getBitmapTextures r)
-
)
-
-
return bitmapList
-
)
-
-
-- we create a standard material with a opacity map and a mix
-
-- map in the diffuse channel that contains two textures
-
mixTex= mixTexture map1:(bitmapTexture()) map2:(bitmapTexture())
-
myMat = standard diffusemap:mixTex opacityMap:(bitmapTexture())
-
myObject.mat = myMat
-
-
myObjectBitmatTextures = getBitmapTextures myObject.mat
-
for t in myObjectBitmatTextures do
-
format "% - %\n" t (exprForMaxObject t)
-
Example 3: Scene References
Here is a trick if you want to get almost all references that are in your scene:
MAXSCRIPT:
-
-
-- first we ask for the dependencies of the root node:
-
rootRefs = refs.dependents rootNode
-
-- returns:
-
-- #(ReferenceTarget:Scene)
-
-
-- secondly we ask what objects depends on the scene reference:
-
refs.dependson rootRefs[1]
-
-- returns:
-
-- #(ReferenceTarget:Material_Editor,ReferenceTarget:MtlBaseLib,
-
-- ReferenceTarget:Default_Sound,$<root>,RenderEnvironment:(null),
-
-- ReferenceTarget:NamedSelSetList,ReferenceTarget:Animatable,
-
-- ReferenceTarget:Animatable,RenderEffects:(null),shadowMap:shadowMap,
-
-- ReferenceTarget:LayerManager)
-
As you can see, it returns an array of very useful references, that we could recurse to grab almost everything in the scene.
Example 4: Show me all!
Last week I noticed that there was an activeX installed in the 3dsMax root directory, it is called addFlow4.ocx so I investigated a bit more and voila! we have an Flowcharting activeX installed by default! very interesting to create flowcharts like the schematic editor. I was thinking that combining references with a powerful way to see them will make us understand much better the way 3ds max works under the hood, so I wondered what if I create the flowchart of the references in the scene, or for the selected object, or for the current renderer... This a script that uses both, references and the flow activeX and it displays the all references that are going on in the current scene.
I hope this helps, and people consider using more often references in their scripts.
Download: [ ReferenceViewer.ms
]