# Changsoo Eun

Archive for the talk Category

## Mini OSL tutorial #1 – Random map rotation per tile

Let me just borrow text from 3dsMax help. You guys should read manual all the time’ Three are many good in formation! I highlighted important aspect of 3dsMax OSL map for you!

Open shading language (OSL) is an open source shading language that is fairly simple to understand. It can be used in several different ways. You can use the OSL Map, which is an execution environment for OSL shaders inside of 3ds Max, and it works like any regular built-in 3ds Max map. There is also a category of pre-loaded OSL maps that you can easily use. In addition, you can use any OSL maps you download from the internet. Finally, you can creating a shader or map in OSL using our development tools. This is a much simpler method to create custom maps than developing the equivalent functionality as a 3ds Max C++ map.

OSL works in any renderer supporting the regular 3ds Max shading API (Scanline, vRay, Corona, etc.). It also works outside of renderers, anywhere in 3ds Max where a regular map is requested, such as in the Displacement modifier. It also works with renderers that support OSL natively, such as Arnold. In those cases, the execution environment inside the OSL map is not sued, instead, the OSL source code, the parameter values and shader bindings are sent to the renderer, which executes the OSL code. More renderers supporting OSL natively are appearing daily.

OSL uses “just-in-time” compilation and optimization of entire shade trees at once, as long as all the shaders in the shade tree are OSL shaders. You can mix OSL shaders and regular shaders, but the optimizations will suffer.

# As I posted before, You don’t have to code to use OSL maps in 3dsMax.

3dsMax OSL is seamlessly integrated just like all other C++ maps. There is ZERO difference in terms of how to use and where you can use. Also if you chain OSL map together, 3dsMax combine them the entire OSL chain and make a single shader under the hood. Essentially Slate ME is acting as an OSL node editor for you. Even better 3dsMax 2021 ships with 123 build-in shaders to start with. At these point, almost all 3dsMax legacy map could be replace with OSL. This mini tutorial is a very good example of using Slate ME as an OSL node editor.

At a Stack post, we god a question.

In this tutorial, the blender guru is using a custom tool in order to randomize the uv’s rotation so we can’t see anymore the repetitive pattern on a large scale tiling texture. He says that, as far as he knows, this kind of tool doesn’t exist in any other 3d software because it involves maths tricks and vectors and nobody wants to deal with this.

Good news! you don’t need custom node for this. Master Zap let me know how to do this with built-in OSL node. I’m posting the master;s answer with my explanation so you can go further.

First, this is the graph. 4 nodes!

Let’s see one by one.

#### UVTransform : Tiling

This OSL map is like Coordinate rollout in other maps. It allows you to move, rotate and scale uv coordinate. I tiled uv coordinate here. So, I tilted here with Tiling parameters.

Tip! You can connect one UVTransform to many OSL maps whicn means you can control the coordinate of all those map at once.

#### Noise : Give random value per tile

This map generates a random 0-1 value per tile which will be used as rotation value later.

As the name says, it is an OSL version of Noise map. It has 6 types of noise in a map. We will use Cell type which makes random pixel bitmap patter.

Then, set Scale to 1.0 and Octave to 1. This makes the noise function generates one value per tile. If you increase Scale or Octave, it will essentially divide each tile.

Then, turn off Step Function to prevent blending.

#### Multiply : convert to degree

Multiply 360 so we can get rotation value between 0-360. As you can see, you don’t have to make a map for value B. You can just type in B parameters of the map.

#### UVTransform : randomize uv rot

This map rotates UV per tile. You don;t need to set any value here. Just connect UVTransform : Tiling to Input(UVW) which inherit tiling from UVTransform : Tiling map. Then, connect Multiply : convert to degree to Rotate.

Now you can connect this map to any maps UVW port.

## rsPrvRender

A new year, a new adventure

## UIAccessor mini tutorial – How to control Make Preview dialog

I have been using jpg sequence for my Make Preview output. It is allways easier and more flexible to deal with image sequence than avi, mov or mp4.

The problem is Make Preview windows is the one of the old window which doesn’t have full exposure to Mmaxscript.  3dsMax dev added more argument for createPreview method in 3dsMax 2020. But, unfortunately some of option in the Make Preview dialog is still not available for Maxscript.

But, that doesn’t mean you can not set Make Preview automatically. 3dsMax has the ultimate hack(?) for controlling any UI component. UIAccessor and DialogMonitorOPS.

This allow you to emulate user interaction with UI like clicking button, choosing dropdown items and pressing Enter with Maxscript.

If you don’t want all these, the final template.

#### Skeleton code of DialogMonitorOPS

fn setMakePreview = (
local WindowHandle = DialogMonitorOPS.GetWindowHandle()
local WindowTitle =  (UIAccessor.GetWindowText WindowHandle)

if WindowTitle == "Make Preview" then (
print "Hello"
)
True
)

DialogMonitorOPS.enabled = true

max preview

DialogMonitorOPS.enabled = false 

DialogMonitorOPS.enabled = true

First, you need to turn on DialogMonitorOPS.so 3dsMax can monitor any UI. Of course, you don’t want to turn on this all the time. So, after our job is done, we will turn off.

Then, resister your function to run(setMakePreview) and give id. Again, after our job is done, make sure to unresister.

max preview

This runs Make Preview

DialogMonitorOPS.enabled = true

Unresister setMakePreview and turn off DialogMonitorOPS

Now let’s see the setMakePreview fucntion. This function will run all the time while DialogMonitorOPS is running.

The most important thing to know is that this function need to return true at the end. I forgot why. But, you MUST do it. So, just do it.

local WindowHandle = DialogMonitorOPS.GetWindowHandle()

How would you let Maxscript know which UI you want to control? We will use window handle or hwnd which is a unique id of each UI element. The above line will give is the handle of window which DialogMonitorOPS detected.

local WindowTitle = (UIAccessor.GetWindowText WindowHandle)

Then, this above line will give us the title of dialog.

if WindowTitle == “Make Preview” then (
print “Hello”
)
True

DialogMonitorOPS will check if the dialog is “Make Preview” dialog. If so, it will print Hello.

#### Let’s set custom output path

From now on I’ll only show setMakePreview function.

fn setMakePreview = (
local WindowHandle = DialogMonitorOPS.GetWindowHandle()
local WIndowTitle =  (UIAccessor.GetWindowText WindowHandle)

if WindowTitle == "Make Preview" then (
for i in (windows.getChildrenHWND WindowHandle) do (format "%\n" i)
UIAccessor.PressButtonByName WindowHandle "File..."
)
True
)

I removed print “Hello” and added UIAccessor.PressButtonByName WindowHandle “File…”. As you can read, this will find a button named “File…” and press it for you.

for i in (windows.getChildrenHWND WindowHandle) do (format “%\n” i)

What does this do? It just printed a bunch of things in Maxscript listener. This is how we sees what kinds of UI element is in the current dialog and fid a way to access each UI element. As I said in the begining, we use windows handle to specify UI element. This line will print out the information of all children of the dialog with given handle, Make Preview dialog. it gives us an array for each UI element. The important ones are first(hwnd of child), forth(UI type) and fifth( displayed text).

fn setMakePreview = (
local WindowHandle = DialogMonitorOPS.GetWindowHandle()
local WindowTitle =  (UIAccessor.GetWindowText WindowHandle)

if WindowTitle == "Make Preview" then (
UIAccessor.PressButtonByName WindowHandle "File..."
)
if WindowTitle == "Create Animated Sequence File..." then (
-- Set cusom output path
local edits = for i in (windows.getChildrenHWND WindowHandle) where i[4] == "Edit" collect i[1]
uiaccessor.setwindowtext edits[1] @"c:\temp\test_.jpg"
UIAccessor.PressButtonByName WindowHandle "&Save"
)
True
)

Because we pressed “File…” button. A new dialog pops up, “Create Animated Sequence File…”. In this dialog, we need to these.

1. Set custom output path
2. Set Save as Type to jpg
3. Press Save button

To set custom output path, we need to know hwnd of path input UI. But, if you check fifth item of array. Text input doesn’t have name! What should I do? Other information we have is type of control on fourth item. The type UI you can input text is “Edit”. So, I collected hwnd of “Edit”s. Fortunately 3dsMax seems collecting UI info in the same order from top to bottom. So, let’s try on the first one. You can use uiaccessor.setwindowtext to set value on Spinner of Edit. If you want to use own naming convention. Replace @”c:\temp\test_.jpg” with own function or variable.

uiaccessor.setwindowtext edits[1] @”c:\temp\test_.jpg”

The, press “Save” button.

UIAccessor.PressButtonByName WindowHandle “&Save”

Wait? why the name iis “&Save”. How do I know I need &? I also don’t know where & come from. But, I know “Save” did not work. So, I printed out all child UI elem data and checked the names.

Did it work? Maybe or Maybe not. Because 3dsmax remembers the format you used last time, if it was not jpg, Make Preview window will automatically switch to the format. So, we need to choose jpg from format dropdown. Now this is real fun!

fn setMakePreview = (
local WindowHandle = DialogMonitorOPS.GetWindowHandle()
local WindowTitle =  (UIAccessor.GetWindowText WindowHandle)

if WindowTitle == "Make Preview" then (
UIAccessor.PressButtonByName WindowHandle "File..."
)
if WindowTitle == "Create Animated Sequence File..." then (

local edits = for i in (windows.getChildrenHWND WindowHandle) where i[4] == "Edit" collect i[1]
uiaccessor.setwindowtext edits[1] @"c:\temp\reallyanothertest_.jpg"

local comboboxes = for i in (windows.getChildrenHWND WindowHandle) where i[4] == "ComboBox" collect i[1]
local filetypeHwnd = comboboxes[3]

local CB_SHOWDROPDOWN = 0x014F
local CB_SETCURSEL = 0x014E
local WM_LBUTTONDOWN = 0x0201
local WM_LBUTTONUP = 0x0202
windows.sendMessage filetypeHwnd CB_SHOWDROPDOWN 1 0 -- Open combobox dropdown
windows.sendMessage filetypeHwnd CB_SETCURSEL 7 0 -- Select 7th item
windows.sendMessage filetypeHwnd WM_LBUTTONDOWN 0 -1  -- Press left mouse button
windows.sendMessage filetypeHwnd WM_LBUTTONUP 0 -1  -- Raise left mouse button
windows.sendMessage filetypeHwnd CB_SHOWDROPDOWN 0 0    -- Close dropdown

UIAccessor.PressButtonByName WindowHandle "&Save"
)
True
)

I guess you already have figured out what this does. Yes, it collect hwnd of all comboboxes.Them 3rd one was the Save As Type dropdown.

local comboboxes = for i in (windows.getChildrenHWND WindowHandle) where i[4] == “ComboBox” collect i[1]
local filetypeHwnd = comboboxes[3]

All cool. Butn thet the heck is the next lines?

windows.sendMessage Sends a Win32 message to the HWND specified in the first argument. This is how you emulate UI interaction programmatically.

I commented on the code what each lines does. But, you may think how am I suppose to know all the secret code?

CGTalk maxscript forum has a lot of answers for common operations. You can also google windows message reference like this.

Now since you set jpg as a new format, JPEG Image Control windows pops up. This one is easy. We can just press OK button like this.

if WIndowTitle == “JPEG Image Control” then ( UIAccessor.PressButtonByName WindowHandle “OK” )

#### How about other controls like checkbox?

Since checkbox text usually doesn’t change, we can search the string pattern of fifth item to find hwnd. This is function to get hwnd using UI name. Then you can BM_SETCHECK window message to check the checkbox. if the first argument is 1, the chebox will be checked. If it is 0, the checkbox will be unchecked.

fn getChildHwndByName parent_hwnd childUIname = (
local child_hwnd = 0
for i in (windows.getChildrenHWND parent_hwnd) where matchPattern i[5] pattern:childUIname do (child_hwnd = i[1])
child_hwnd
)
local frameNumHwnd = (getChildHwndByName WindowHandle  "Frame Numbers" )
windows.sendMessage frameNumHwnd BM_SETCHECK 1 0

#### Runscript after Make Preview is done

If you want to automatically run image sequence player like PDPlayer or RAMPlayer or resister to Shotgun, simple add the code after max preview.

#### Final template code

Here is the cleaned final template code. If you don’t want to read all this, start from this.

the final template.

This is made in 3dsMax 2019. Other version might not work with this if there is UI difference.

## 3dsMax 2020 Preview Enhancement

3dsMax 2020 has some nice improvement for Make Preview.

• Much faster. 1.5 – 3x faster creation on local drives
• Capture size greater than viewport dimensions supported
• “Quality” setting accessible from Preview UI (Nitrous only)
• Default preview filename based on current scene filename
• 100% output resolution on by default
• MXS snippet can be executed per frame for custom strings
• Filename and MXS snippet values can be specified from MXS command line of CreatePreview()
• After executing the preview, the time slider is returned to the original starting frame
• “Play when done” accessible from Preview UI
• If running from MXS command line, avoid dialog boxes, output to listener instead

3dsMax 2020 also has the bug fix for “User defined” Per-view preset missing issue. This issue is related to the permission. If you are still on older version. Make sure to open the permission for folders under 3dsMax root to be able to choose “User Defined” Per-view preset in Make Preview. Or, upgrade to 2020.

## 3dsMax 2020.1 Hot Key Editor

One of the new feature of 3dsMax 2020.1 is the new Hot Key Editor plus Hot Keys and underlying system.

##### Hot Key Editor

The new Hot Key editor is cool. But, the more important change is the way of how the customized hot keys are stored and loaded. When you save and load hot keys in the past, 3dsMax had saved and loaded the entire hot key assignment. Because of this save/load mechanism, any newly added hot keys by 3dsMax dev would have lost when you load the hot keys from previous version. It was not possible to have a studio0wide custom hot keys since the hot keys would have gone when an artist load their own hot keys.

To solve this kinds of issues and make UI customization upgrade-safe, the new override based hot key customization engine is developed. Now 3dsMax stores only the changed hot key assignments in the file when users customize their hot keys. Then 3dsMax will override only the changed keys when the file is loaded.

This will allow users to keep the changed they made while still receiving updates from the global changes. Also you can deploy multiple level of hot key customization.  For example, you can have a studio-wide hot keys on top of 3dsmax default hot key while artist still can have own hot keys if they want.

##### New Hot Keys

Another change is the new hot keys.Yes, some of hot keys have been changed. This new hot key assignment is the fruit of the community effort of 3dsMax and beta users. There has been many feedback and discussion for the best hot keys on the beta. Special thanks to Sergio Santos for the great contribution. 3dsMax put a nice documentation with map images to show the complete list of changes like this. Please visit HERE for all images.

But, I know there are always ones who doesn’t want to change their 20 years old hot keys. For them, here is a hot key files to go back the legacy hot keys. Download it and load in the Hotkey Editor.

Download 3dsMaxLegacyHotKeys

If you have had customized hot key in pre-2019 version, this is the step to move to new hot key system.

1) Generate KBDX file using the maxscript command actionMan.saveKeyboardFile “C:\TEMP\LegacyDefaultUI-2019.kbdx”.
If you specify a KBDX extension, it will convert the entire active hotkey set to the legacy format through the old code. If you specify HSX, it will output in the new format and only contain user customizations.

2) Swap it out with the one in your UI_ln/CUI folder (rename the old one to keep a backup). This will use the new hotkey defaults as a reference point when doing the migration, and will treat every difference as a user customization, reaching the same result as if you remapped every single difference back to how it was in 2020-

## How to share your awesome MCGs – MCG Installation and network deployment

MCG had a big changed in 3dsMax 2018. This post is based on 3dsMax 2018+.

One of the biggest changes was Improved MCG Package Installation Experience. Let me just norrow the words from dev.

“In previous versions of MCG, the package installation process of an .mcg file involved the automatic extraction of its contained .maxtool and .maxcompound files into the user’s 3ds Max /Max Creation Graph/Tools/Downloads directory. A consequence of this installation method was that common compounds would often conflict with each other, resulting in duplication messages.

In MCG 2018, we’ve simplified the package installation process to make it much more robust. You can now install a .mcg file by dragging it into the viewport. All installed packages now reside in the user’s 3ds Max 2018/Max Creation Graph/Packages directory, and are evaluated as standalone .mcg files. No more file extraction, no more conflicts, no more problems.”

Basically, 3dsMax will consume .mcg package file directly and use the compound in that package first to avoid compound version conflict. Now .mcg file act much like a plugin dll file.

#### Packaging MCG

MCG Editor > File > Package Tool Graph… will allow you to package the current tool graph and all compound in a .mcg file.

#### Installing MCG

It means just copying .mcg file into MCG package folder, and drag and dropping .mcg file into 3dsMax viewport will do that f or you. The MCG packages folder is in your user folder/Autodesk. 2018/2019 shares the same structure. But, 2020 MCG package folder is a slightly different.
C:\Users\[username]\Autodesk\3ds Max 2020\User Tools\Max Creation Graph\Packages

#### ProceduralContent.ms

Before I tal about network deployment. I need to mention about this file first. The mCG is implemented with dotnet and Maxscript. The engine is dotnet and UI and communicaion with 3dsMax portion id Maxscript. This means we can actually see the source of many MCG functions which are in C:\Program Files\Autodesk\3ds Max 2020\scripts\Startup\ProceduralContent.ms file. If you dissect this file, you can learn a lot about how MCG is working.

#### Custom MCG Path

By default, 3dsMax uses the above MCG folders. But, you can also have own custom path for MCGs. RegisterCustomGraphPaths function in ProceduralContentOps struct in  ProceduralContent.ms manages how to set the path.

By default, it is set to use 3dsMax.ini file, C:\Users\[username]\AppData\Local\Autodesk\3dsMax\2020 – 64bit\ENU\3dsMax.ini. You can type getMaxiniFIle() in Maxscript Listener to get your 3dsMax.ini file path

You can add MCG Compound Directories, MCG Tools Directories, MCG Package Directories sections and add path like this.

[MCG Tools Directories]
tools_dir=C:\path\to\my\tools
other_tools=C:\path\to\other\tools
[MCG Compound Directories]
common_compounds=C:\path\to\my\compounds
experimental_compounds=C:\path\to\experimental\compounds
[MCG Package Directories]
networkPackages=\\path\to\network\packages

#### Custom MCG path without using 3dsMax.ini #1

But, what if you do not want to use 3dsMax.ini. The one way of using own .ini file for MCG path would be modifying ProceduralContent.ms. Open the file,C:\Program Files\Autodesk\3ds Max 2020\scripts\Startup\ProceduralContent.ms, search “getMAXIniFile()”. Then, replace with whatever path you want.

fn RegisterCustomGraphPaths =
(
local iniFile = getMAXIniFile()
local settings = dotNetClass "Viper3dsMaxBridge.Settings"

#### Custom MCG path without using 3dsMax.ini #2

But, then you have to modify on all workstations and render node. That might be too much. The next methods is taking the function from ProceduralContent.ms and make own script.

If you check the code, you can see all the functionality is coming from Viper3dsMaxBridge.Main dotnet class. So, I check what kinds of methods it has with showMethods command. CompileGraphsByFolder is what we need. There are a lot more methods. But, I revmoed not to scare you.

bridge = dotNetClass "Viper3dsMaxBridge.Main"
dotNetClass:Viper3dsMaxBridge.Main
showMethods bridge
.[static]CompileGraphsByFolder <System.String>folder
....

Now, this is the final maxscript you can use

local viperbridge = dotNetClass "Viper3dsMaxBridge.Main"
-- Just in case if Viper3dsMaxBridge.dll has not been loaded yet
if viperbridge == undefined then (
local bridgePath = (symbolicPaths.getPathValue "\$max") + @"\Viper3dsMaxBridge.dll"
viperbridge = dotNetClass "Viper3dsMaxBridge.Main"
)
viperbridge.CompileGraphsByFolder @"D:\myfolder1\"
viperbridge.CompileGraphsByFolder @"E:\myfolder2\

Put this in a .ms file like myMCGload.ms. Then, throw in one of your network shared plugin folder. I’m sure you probably already have a plugin folder for a free plugins. Any .ms fil in plugin folder will be automatically runs when 3dsMax start.

#### A few more things to know

• mcg files are registered in 3dsMax file as an asset. It will show up in Asset Tracker and asset metadata stream.
• If you use BackBurner and use Include Maps, .mcg filw will be submiited with the job like maps.
• When 3dsMax starts in slave mode, it will automatically evaulate all .mcg file in the folder where the max files are. Therefore, if you use 3rd party render farm, all you need to do is put .mcgs in the same folder as max file. You don’t need to set any path.

I hope this post is helpful for MCGers.

## 3dsMax 2020 – OSL update

3dsMax developer has changed their delivery model to continuous delivery. Instead of delivering a feature at one release, now a feature will be delivered continuously until all the planned feature is finished. The automatic OSL > HLSL conversion for viewport was the one of them. It has been improved in every PU since tisinception. Now almost all OSL shader will be automatically converted to HLSL including 3rd party OSL shaders.

Also, the viewport playback performance of animated OSL map has been greatly improved.

This is the viewport playback of the sample file for my OSL shader pack1 in 3dsMax 2019/2020.

## 3dsMax 2019.3 – Alembic update

Since I posted the Alembic improvement of 3dsMax 2019 release, each PU has been added more and more improvements continuously. Let’s check what has been added.

#### Per object metadata with .userProperties and .arbGeomParams

3dsMax 2019 introduced the export of per object propery. But, it was only compatible between 3dsMax. With the PU3 update, you can export/import per object properties via .userProperties and .arbGeomParams. This allows a greater compatibility between 3dsMax and Maya/Houdini.

Here is an example of Alembic file exported to Maya.

Here is some details.

##### Import
• It will read from both .arbGeomParams(Maya default) and .userProperties
• It supports integer, float, boolean, string.
• It supports animated value.
• If Extra Attribute is on shape node, it will be in Alembic Geom Parameters rollout(alembic_geom_attributes). If Extra Attribute is on transform node, it will be in Alembic XformParameters rollout(alembic_xform_attributes)
##### Export
• The custom attributes on the top modifier and case object will be exported.
• 3dsMax will use .userPripertiesfor export and store data on transform node by default.
• If you use the same custom attribute name alembic_geom_attributes and alembic_xform_attributes which 3dsMax alembic importer uses. You can even have control over where your custom attribute export goes. To store data on shape node, you need to make the alembic_geom_attributes on the baseObject.
• If you have duplicated name custom attributes on an object, none of custom attributes  will be exported. You will see the warning in Maxscript elistener.
• Layer name will be on transform node.
• Material name and Object ID will be shape node.
• 3dsMax will import Layer name/Material name/Object ID as custom attribut on the respective rollout, too

#### Alembic Inspector

This is added in PU1. This allows to browse the content of the alembic object even without opening the alembic file. Now PU3 allow you to open the Alembic Inspector for the already imported alembic files. Use the Alembic Inspector button in the Alembic container object(the root Alembic object with Alembic logo icon),

Alembic Inspector is also accessible via Maxscript. Link.

#### Maya compatble Multi UV and Vertex Color

Maya is very picky about reading the multi UV and vertex color in Alembic file. To send multi UV(UV channel 2+) to Maya,  you need to choose UV for Extra Channels type. Also vertex color data from Maya will be imported as a proper vertex color channel. Before PU3, the vertex color channel was imported as an UV 2+ channel.

#### Instancing Support

Support for instances allows files to be much smaller while maintaining complexity and can dramatically improve export speed. PU2.

#### Alembic library 1.7.5

Alembic library has been updated to 1.7,5 in PU2.

#### Alembic Transform Controller Performance improvemant

Alembic Transform controller playback is more than 2x faster in PU3. Also Source and Object browse buttons are added for Alembic Transform controller.

#### Material ID will be exported when all Material IDs for an object were the same

Before PU3, None if mMaterial ID was exported.

#### Alembic Peformance mode will only cache the current animation range

Before PU3, it was caching from frame 0 all the time.

#### Fixed High-speed rotations no longer deform objects

Thanks  for 3dsMax team for continuous effort to improve Alembic support!

## 3dsMax 2019.3 – OSL Viewport Support : OSL > HLSL

Since it is introduced in 3dsMax 2019, OSL Map has been comtinuously improved in every release.
There has been many updated on performance, OSL editor useability and viewport display.
The most important improvement among all is the viewport display.

Now 3dsMax viewpot can display almost all shippinig OSL and many 3rd party OSL shaders properly even as 3D procedural map.
How canit even support random 3rd party OSL shader?
The 3dsMax rendering team has developed automatic OSL > HLSL converter instead of making HLSL shader for each OSL shader.

The OSL shaders in the following images are all 3rd party OSL as 3D procedural map.
It is oddly satisfying to see all the 3D shaderes in the viewport exactly as renders.

And,,, a little bird told me even more stuff might come in the future. 🙂

## 3dsMax 2019.1 – Attaching large amounts of meshes is up to 7 times faster

3dsMax 2019.1 has been release with many improved features.

Many new features has been added to Alembic/OSL/Fluid/Arnold. Python and Project got some improvement. Plus 94 fixes.

One of the item among “Bringing your ideas to life in 3ds Max 2019.1 Update” was “Attaching large amounts of meshes is up to 7 times faster”.

So, I decided to test if it is true. The enhancement was done for Collapse utility. I think 3dsMax dev choose to enhance this because this is the only attach which keeps explicit normals.

I test total 4 files. I open the file and attach all geometries.
The result is… drum roll…

##### 05_TM_manyLowRes

Obj:5616 Verts:99,686 Faces: 165,505
2019 : 3.335s
2018 : 32.724
9.81 times faster

08_Static_Many
Obj:19913 Verts:2,264,540 Faces: 3,265,430
2019 : 11.2s
2018 : 2236s
199.35 times faster

bistro
Obj:2429 Verts:2,766,360 Faces: 3,850.480
2019 : 9.5s
2018 : 546s
57.23 times faster

EmeraldSquare
Obj:29596 Verts:9,065,430 Faces: 7,722,170
2019 : 274s
2018 : 19980s
72.95 times faster

It is actually far better than 7 times!

## 3dsMax 2019 – Alembic Improvement

Alembic is a geometry cache format developed by Sony Imageworks and ILM. It is a very powerful format. It can handle animated transform and deformation(include topology changing animation). It can also have custom meta data as much as you want.

Alembic has been added to 3dsMax 2016 and developed continuously  since then. I’ll go over Alembic improvement of 3dsMax 2018 first and show what has been added for each previous versions.

But, before we jump on the improvement list.Allow me go over how 3dsMax implementation works first. 3dsMax Alembic works more like referencing system. Each object in Alembic file is imported as separate object which has two component, AlembicObject for geometry data and AlembicXform Controller for transform animation data. This allows users to edit anything after it is imported. You can apply any modifiers, edit geometry, change controller setup and delete any objects. Imported Alembic object is just like any other object. In a way, it almost like ObjectXref.

Other way of using alembic is treating the entire alembic object as one object like VRayProxy or Arnold Procedural object.This makes overall workflow simpler and easy to manage. But, you lose granular control. I think It is good to have both workflow inside of 3dsMax.The more choice is always better.

## 3dsMax 2019

3dsMax Alembic supported faceset(material ID) and per vertex arbirary channel from the beginning. But, it never had support for per object metadata. Now you can export per object meta data using Custom Attribute and some export options in Export dialog.

You can choose to export the following data from Alembic Export Option dialog.

• Layer Name
• Material Name
• Object ID

Custom Attribute export supprts most data types like float, integer, string and boolean. It even support animated values.

BUT, Please keep in mid, Alembic format specification doesn’t have amy standard on this matter. Because 3dsMax write these data into Alembic file, it doesn’t mean that other DCC will magically read this data. User must figure out how to load this data in other DCC.

To know, how 3dsMax exporter stores these information, You can export a test Alembic file with HDF5 format and use the great tool called HDFView. This tool will show the entire structure of the Alembic file. Here is a sample screen grab.

As of now, the 3dsMax importer doesn’t support these data yet. I hope we would see the support for these meta data import soon.

#### UV/Extra Channel and FaceSet(MaterialID) name parsing

Since 3dsMax is rely on ID number for UV and Material ID. It was very challening to get consistent UV channel or maerial ID number when you import and update alembic file. At least, 3dsMax 2017 added a way to keeping uv channel and material ID number constsent between 3dsMax. Therefore, if you export from 3dsMax and import into 3dsMax, all uv channel IDs and material IDs are preseved. But, when you import an alembic from other DCC. You didn’t have any controls. It just came in the order of channel order inthe Alembic file.

Now alembic importer will check the faceset and extra channel name, and if the name is end with number, the number will be used as Material ID ot uv channel number. For example, if you name face group name as “group_7” in Houdini, the faces will get material id 7 when it is imported. THIS IS A SMPLE YET VERY IMPORTANT UPDATE!

Also when you export/import between 3dsMax, the data about the original uv channel and material ID is explicitly stored in the Alembic file instead of relying on naming convention. This makes the ID preservation between 3dsMax even more solid and allow the export the UV channel you set in 3dsMax. For eample, if you name your uv channel 2 as “the second UV“. the exported Alembic channel will have the name, “Max Map Channel the second UV

#### Option to choose what to export/Import

Now you can choose which channels to export and import. In the previous version, 3dsMax import/export everything it supported. The following image is the new import and export dialog.

Ont thing you need to know is that, there is a hidden ExtraChannels  Maxscript option for both import and export. What is ExtraChennels? For export, ExtraChannel means UV channel other than 1. For import, it is arbirary per vertex data other than UV. By default, it is on for both export and import.

This new options are also very important for troubleshooting. Alembic from a different DCC can easily have problematic data. At work, I found out that most of the crash while importing Alembic file turned out to be a bad data in the Alembic file(Especially normal and extra channel). Without this options, it was very hard to troubleshoot because you have to try to a data and export again iover and over again. Usually the normal and uv data caused the problem. Now with this option, I can just exclude some data to see whats causing problem. I can also decide not to import the problematic data instead od waiting for re-export.

Of course, this also allow to get better performance by removing unnecessary data.

#### Velocity Channel

Velocity channel in 3dsMax is a long story. It requires its own long post. In a nutshell, 3dsMax itself never has had the concept of velocity vertex channel at all. When you don’t even have the concept, it is abvious that the imported Alembic can not handle vertex velocity.

Finally 3dsMax dev added the vertex velocity channel support in the SDK. If the Alembic file has standard velocity(or v) channel, 3dsMax import the channel as vertex velocity channel. If you have been re-routing the v channel to extra channel. You don’t need to do that anymore.

But, this doesn’t mean that all renderers will magically start to see vertgex velocity channel. Each rednerer need to support the new velocity channel to utilize this data.

#### Vertex Color

Now you can export and import vertex color channel(uv chennel 0)

#### Subsampling

You can export Alembic file with subsampleing in the previous version of 3dsmax 2019. Butm the worklow was confusing. To export subsamples. You need to set 2 things.

• Set Every Nth Frame less than 1.0. IF you set 0.5, you will get 2 subsamples per frame.
• Then, you must be in tick mode. You need to set Time Display in Time Configuration dialog either FRAMETICKS ir MM:SS:TICKS

Now you dont need to turn on tick mode anymore. Also the Every Nth Frame option has been changed to Samples per Frame.

#### Option for Exporting Hidden Geo

In the previous version, 3dsMax Alembic Exporter export geometry data only for unhidden object. If your object is hidden, only transfom animator was exported. THis might make sense for some. But, it also make some users scratch their head for sure.

Now there is a Maxscript property to control this. In AlembicExport interface, .Hidden property controls this hehavior.

Here is a tip. You can utilize this behavior as a way to export only transform animation. If you want to export transform animation only without any geometry data. Turn off this option and hide all object and export.

#### Graceful warning/exit for import/export malfunction

Sometimes bad geometry causes crash when you export/import Alembic file.  3dsMax 2019 will pop-up an explanatory Alembic Export Malfunction message box and abort when the Alembic Export plug-in encounters an unexpected issue while exporting instead of crashing.

Generally 3dsMax 2019 handles geometry import a lot more stable than the previous versions. In many cases, 3dsmax importer will try to fix the problem and give you a best possible result. If Alembic library itself errors, 3dsMax will relay the error message.

#### Export Selected will grab only needed hierarchy.

Since alembic is designed to keep hierarchy, 3dsMax exporter is grabbing other necessary object when you Export Selected object. The problem in the previous version was that it is grabbing too much(the entire hierarchy tree). This is changed now. 3dsMax will grab only the immediate ancestors of selected object.

#### Better duplicated object name handling

If you have duplicated name object while exporingAlembic file, it can cause problems. In ideal world, user should check if they have the duplicated name objects before export. But, since that’s not ganna happen most time, 3dsMax will check the duplicated name and suffix nodel handle to make all object name unique.

#### Respect Maxscript #noPrompt option for duplicated name object handling for import

When an Alembic file is imported, you get a duplicated warning pop-up if there is already the same name object. When you use importFIle with #noPrompt option, this dialog will not pop up as it should be.

#### Alembic Container Object Icon

Alembic log shape icon insteaf of dummy for AlembicContainer object.

#### Remember dialog setting

The export and import will remmeber the last used settings.

#### Extra Channel UV Data Animation Fix

In the previous version, the Extra channel(UV 2+) animation was not imported if the channel has UV data(vertex data + face indice). It is fixed. Please do not confuse this with per vertex channel data which never has been a problem.

#### Performance Mode Stabilixation

The Performance Mode in AlembicContainer has been stablized a lot. This feature is probably the most underrated feature of 3dsMax considering how poerful it is. I’ll mpost about this feature someday.

## 3dsMax 2018

#### Visibility Support

Visibility track support is  added including visibility animation.

#### .ShapeSuffixMaxscript Option for Maya

Our little precious Maya could not handle the geometry name from Alembic file properly. Therefore, 3dsMax dev had to add a solution for them. If you tuen on this option, yout geometry name will get “Shape” suffix.

## 3dsMax 2017

#### Preserving UV Channel and Material ID number

When you export and import an Alembic file between 3dsMax, the UV channel ID and Material ID number will be preserved.

#### Extra Channel Import Support integer, float, vector, color

3dsMax 2016 only supported color and vector.

#### Proper Deformation Export for Object with Spacewrap

In the previous version, 3dsMax exported the object with SpaceWarp in World coordinate. If the object is not at the root level, the object will get double transform since the deformation animation already include the animation.

#### Alembic Performance Mode for Any Object

Alembic Performance Mode cab be used for any 3dsMax geometry. In the previous version, only AlembicObject without any modifier was supported.

In the previous release, UV data loading was unstable. Sometimes UV data corrupt after user scrub time slider. User need to use Channel Info dialog to copy UV channel data and paste back to the same channel to lock the UV data right after they import thr Alembic file. This is fixed.

#### Full Maxscript Exposure for Alembic Export

All Alembic Export funcions are exposed to Maxscript.

#### Preserving Object Name

3dsMax 2016 suffix “_mesh” for geometry. Now object will be exported with unchanged name,

#### AlembicContainer Object as Dummy

——————————————————————————————-

OK,  that’s it. I hope it is helpful for you.