Articles Category


XSItoMax.jpg

How to make XSI and MAX friends

If you work a lot with these two softwares you end playing and trying the craziest things to make them communicate as if they were friends. Probably other people have had the same idea but since I haven’t seen it posted online, I will explain this experiment that I did a while ago that amazed people at the studio the first time they saw it but then nobody could find a real application for it… to have XSI and MAX opened side by side , move an object in XSI and MAX would replicate in realtime the same movements, it looks so cool!

I knew 3dsmax could act as an OLE server and that XSI could create ActiveX controls easily. Taking advantage of this, I created a simple script in 3dsMax that registers a function that XSI can call using the "Max.Application.8" ActiveX control. It sounds difficult but it is actually really easy to code.

What if that maxcript function just moves an object in Max ? I could create a scripted operator in XSI that calls that function everytime the object moves inside XSI.

I captured a video where you can easily see the objects moving in both applications at the same time.

The explanation:

Setting up 3dsmax OLE server:
As I said before, 3dsmax must be acting as a OLE server.I’ve included a .reg file that basically does it for you , you just have to make sure that the last line of that file contains the location to your 3dsmax program ( currently it is pointing to ‘C:\3dsmax8\3dsmax.exe’ ).

  • Run the file ‘maxscript8.reg’ double clicking on it and 3dsmax will be ready to act as a OLE server. ( you can also refer to the Maxscript documentation for more details )

Making the magic happen:

  • Open Autodesk 3dsmax, and run the script XSItoMax.ms that registers the example function.
  • Open the 3dsmax file XSItoMax.max, that contains the cone object.
  • Run SoftImage XSI, and open the XSItoMax.scn file provided , that also contains the cone object.
  • Finally move the cone in XSI and, if everything went smooth, you should see it moving in 3dsmax at the same time, magic!

Just to clarify that I’ve done this experiment with 3dsmax version 8.0, and XSI version 5.0, so the scenes are saved with those versions.
In the zip file , I’ve also included a XSI plugin ("executeMaxCommandPlugin.js") that generalizes this experiment and allows to call any maxscript function from XSI, the trick is that it is just calling the "execute" maxscript function that accepts a string as input value (copy it to your XSI plugins directory, and you will have a new command ‘executeMaxCommand’ )

 

Download: [ xsitomax.zip XSItoMax.zip ]
Download: [ xsitomax.mov 720×470 XSItoMax.zip ]

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:
  1.  
  2. fn getControllers ref =
  3. (
  4.     local ctrlList = #()
  5.     local refList = refs.dependsOn ref
  6.  
  7.     for r in refList do   
  8.     (
  9.         if (isProperty r #keyable == true) then
  10.             append ctrlList r
  11.  
  12.         join ctrlList (getControllers r)
  13.     )
  14.  
  15.     return ctrlList
  16. )
  17.  
  18. -- we create our sphere object
  19. myObject = Geosphere radius:10
  20. myObjectControllers = getControllers myObject
  21. for c in myObjectControllers do
  22.     format "% - %\n" c (exprForMaxObject c)
  23.  

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:
  1.  
  2. fn getBitmapTextures ref =
  3. (
  4.     local bitmapList = #()
  5.     local refList = refs.dependsOn ref
  6.  
  7.     for r in refList do   
  8.     (
  9.         if (classof r == bitmaptexture) then
  10.             append bitmapList r
  11.  
  12.         join bitmapList (getBitmapTextures r)
  13.     )
  14.  
  15.     return bitmapList
  16. )
  17.  
  18. -- we create a standard material with a opacity map and a mix
  19. -- map in the diffuse channel that contains two textures
  20. mixTex= mixTexture map1:(bitmapTexture()) map2:(bitmapTexture())
  21. myMat = standard diffusemap:mixTex opacityMap:(bitmapTexture())
  22. myObject.mat = myMat
  23.  
  24. myObjectBitmatTextures = getBitmapTextures myObject.mat
  25. for t in myObjectBitmatTextures do
  26.     format "% - %\n" t (exprForMaxObject t)
  27.  

Example 3: Scene References
Here is a trick if you want to get almost all references that are in your scene:

MAXSCRIPT:
  1.  
  2. -- first we ask for the dependencies of the root node:
  3. rootRefs = refs.dependents rootNode
  4. -- returns:
  5. --   #(ReferenceTarget:Scene)
  6.  
  7. -- secondly we ask what objects depends on the scene reference:
  8. refs.dependson rootRefs[1]
  9. -- returns:
  10. --   #(ReferenceTarget:Material_Editor,ReferenceTarget:MtlBaseLib,
  11. --    ReferenceTarget:Default_Sound,$<root>,RenderEnvironment:(null),
  12. --    ReferenceTarget:NamedSelSetList,ReferenceTarget:Animatable,
  13. --    ReferenceTarget:Animatable,RenderEffects:(null),shadowMap:shadowMap,
  14. --    ReferenceTarget:LayerManager)
  15.  

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 ReferenceViewer.zip ]