Menu Close

Category: csTools

csGPUhittest

Download

This script allows you to toggle GPU hit testing on or off. You can create a toolbar button that displays the current status of GPU hit testing and enables you to switch it on or off.

It is under “csTools”

So, what the heck is GPU hit test?

When navigating the 3ds Max viewport, 3ds Max often needs to determine what is underneath the cursor.

For example, in 3ds Max, when you hover over an object, it shows the object’s name under the cursor. When zooming or panning, 3ds Max must calculate the cursor’s 3D position. Similarly, when selecting an object or sub-object, 3ds Max needs to determine what is underneath the cursor.

This process is called hit testing. 3dsMax cast a ray from the cursor point and detect that the ray hits. So, as you can expect, the more object and polygon you have, the more time. If you have ever experienced a hiccup for slight delay when you start zoom, pan or select object. That could be caused by the hit test time.

Around 3ds Max 2014, when the development team was focused on improving hit testing performance, they created a GPU-based version of hit testing. However, this approach had some issues, and since 3ds Max still had a software driver mode that relied on CPU hit testing, the team decided to improve the CPU version instead. Eventually, they achieved similar performance with the CPU, and the GPU version was gradually forgotten.

However, the code for the GPU version was still present, and it could be enabled using Maxscript.

nitrousgraphicsmanager.HardwareHitTestEnabled=true

But, help clearly warns you. 🙂

Now, in 3ds Max 2025.2, there is a bug in CPU hit testing, and enabling the GPU version can be used as a workaround. Interestingly, after a decade of GPU advancements, it also appears to deliver better results.

This is a comment from Ash JJ VI on Facebook Stack group.

I’ve talked to some of my colleagues and most of them have massive viewport performance gains with this enabled. On average they have high core count CPUs (but lower Ghz ~= 3Ghz) but quite beefy Nvidia cards. But indeed it comes with some drawbacks, so far I (only) found that:
You can’t select the PhysicalCamera object unless it’s targeted (then you can select the target line, but even that is wonky and works only with region selection) or also works if you select with a big rectangle around it so you select the (invisible) cone as well, no problem with the other camera objects.
ForestPack, RailClone, if disabled or not generating anything can only be selected with region selection.
Most of the Forces and Deflectors can only be selected with region selection.
I have no problems with splines, lights, meshes, or selecting any of the subobjects in both low or high poly objects, in a mix of scenes.
I found so far that, I have far better accuracy when selecting objects in my scene. No more selecting objects behind the view for instance, some objects were hardly selectable in some cases, I don’t have that anymore. In some scenes (didn’t have to be big or complex even), there was always one second delay before panning or orbitting, this has completely vanished as well as a higher FPS in viewport 2-3x sometimes, and a lot snappier navigation.

 

With the script, you could easily switch between CPU/GPU hit test as you need.

csSyncPersToCam

!!! Updated to 1.1 If you have downloaded 1.0, please download again !!!

This is a simple script that syncs a camera with an active perspective view. If you want to control a camera view just like perspective view navigation, this is the script for you.

How to use is simple. Select a camera to sync from drop down and turn on Sync. If you turn off the button or close the dialog, the sync will stop.

A few things to remember!

  • It can’t support targeted camera. Use Free camera or turn off “Targeted” for a Physical camera.
  • It controls “fov” parameter. So, as long as the camera has and is set to control with “fov” parameter, it would work. THis also means you must turn on “Specify FOV” for Physical camera.
Download csSyncPersToCam 1.1

 

Substitute modifier mini tutorial and csStackCache

Substitute modifier is one of the most underrated modifiers in 3dsMax and one of my favorite modifiers. As the name suggests, this modifier replaces the object’s mesh/poly. How to use is very simple. Just apply the modifier, turn on “Pick Scene Object” button and pick an object in the scene to substitute.

You can choose to use the substitute mesh only for viewport or render.

You can also choose to use an object from another max file.

We can think about a few useful situations such as…

  • I already have a big stack and animation started from Box. Now I wanted to start from ChamferBox instead of Box.
  • I can substitute highres objects with low res ones only for viewport to make viewport faster.
  • I can have low res placement holder objects in the scene and substitute with highres objects in another max file.
  • You can have multiple versions of mesh in an object while keeping all the connection to other portions of 3dsMax.

BUT! That’s not all. Substitute modifier has more super powers.

It automatically disables the evaluation of all the modifiers under it

It makes sense since the Substitute modifier provides a mesh from the stack point. Whatever at the below of the stack doesn’t do anything in any way. The best part is that you don’t have to set anything manually. This modifier just does it. Combined with the feature that allow to use Substitute modifier only for viewport display, this provide a great work around to improve the scene performance when you have a lot of hires animated meshes.

For example…

  • if you substitute an animated tree with a static low res tree, this modifier blocks the evaluation of animation.
  • If you have an animated alembic cache object, this modifier will stop loading the alembic file every time when you scrub through. In the following image, I snapshot a frame and used that for display using Substitute modifier. You can see alembic object stopped loading  the cache file.
  • Turn off VRayVolumeGrid preview which will load files and update every frame. Make a preview mesh and use Substitute modifier to display it. This will allow you to directly place vdb without waiting for every singler cache file loading.

It can embed the replacement mesh data in the modifier

This is a really really powerful feature. After you pick an object from the scene, you can delete the object. Then, the modifier will hold the mesh information in itself which essentially act as a cache modifier.

This means that you can collapse the stack while keeping all the history. l Some of you probably have been duplicating objects and collapse in the scene and save a copy in another max file for future use. You don’t need to do that any more. Everything can be just stored in the same scene

one of the benefit of caching a big stack is to improve max file loading time. I want to cover this topic in depth some day. In short, 3dsMax file doesn’t save the result of stack in the .max file. If you make a Box and apply Bend modifier. 3dsMax just stores the class(Box, Bend and its parameters. Then, when the file is loaded, it evaluates all the classes and generates a mesh. This means if you have very big stack or very calculation intensive modifiers. The file opening can take a long time. That’s why some modifiers like Boolean, Conform or Retopology have own caching mechanism. With Substitute modifier, you can cache any objects with modifier in the scene if you want. Obviously, it has a trade off. It will increase the max file size. You gotta pick your poison.

Another benefit is that it can be used as a countermeasure for possible mesh corruption. As a procedural evaluation system, if anything goes wrong in the middle of the stack, the above of the stack would produce an unwanted result. For example, Edit Poly is an awesome and powerful modifier. But, it can be fragile with certain operations. In fact, Edit Poly never stored the result of change in the modifier. It is actually a mini stack in a stack. It stores every operation you did and re-execute then you open the file. So, even tho it is slim, there is a chance that one of hundreds of operations, especially one that removes or adds sub-objects, could go wrong. For that case, you can use Substitute modifier to lock/freeze the status of stack.

csStackCache

So, I made a small script called csStackCache to take advantage of Substitute modifier’s super power. You can find from csTools > csStackCach in the Customize UI dialog.

How to use is simple.

  1. Select objects that you want to cache.
    • All – all geometry objects
    • Selection – Selected objects
    • Selection Set – the chosen selection set
  2. Press “Cache”.
    This script will add a Substitute modifier named “csStackCache” just above of the first viewport enabled modifier. In the following image, It is added under TurboSmooth because it was set to Off in Viewport.

    If you already had “csStackCache”, it will use the position. So, if you need to add “csStackCache” at certain position. Use the “Add Cache” button to add and move around it. Then, Cache them. For example, if you have any animated modifiers, you will need to cache blow the modifiers. If you cache above them, it will freeze animation.
  3. If you want to remove “csStackCache”, select objects in the same way and pres “Remove Cache
You can download csStackCache from here.

BUT! I want really want to set a built-in “Cache” button in this modifier. That will be much faster than my scripted solution. So, please visit here and vote for me!
https://forums.autodesk.com/t5/3ds-max-ideas/add-quot-cache-quot-button-in-the-substitute-modifier/idi-p/12470220

 

csSetClippingPlane

There has been many requests for providing a way to adjust clipping plane by numbers.
Your voice was heard. 3dsMax 2024.2 bring MXS exposure for the clipping plane.

vpSetting = NitrousGraphicsManager.GetActiveViewportSetting()
vpSetting.ViewportClippingEnabled = true
vpSetting.ViewportClipNear = 0.05
vpSetting.ViewportClipFar = 0.8
vpSetting.ResetViewportClipNearFar()

Note: Same as UI, the allowed range of near/far is [- 0.1, 1.1], and the specified value should obey the rule: near < far

Of course, I know there are many who don’t/can’t script. So, I made a script for you which you saw in my video.

Download csSetClippingPlane here!

csMakePreview 1.21

csMakePreview is a scripted UI of the newly improved MXS createPreview function in 3dsMax 2024. For the details, please check this post. Now it has been updated to 1.21 with a few new features including the new Mini mode.

Download csMakePreview 1.21 Here   Download csMakePreview 1.21 Application Package Here

Mini Mode

  • Press Mini Mode button to change to Mini mode.
    Mini mode on.off status will be saved in the settings file which means it will be kept across max session.
  • Only few options are exposed in Mini mode.
    The intended workflow is making presets using full mode and use for Mini mode.
    .
  • If you want to return to full mode, click “Mini” button.

Other new features

  • Custom resolution by pixel. Turn on the “Resolution” button and set the preview resolution as you want.
  • <version> token.
    It’ll add 3 digit padded version number.
    This value is saved for each scene file. So, you will know which version you used last time for the scene.
  • Preview path preview button
    This button will show the preview of the resolved preview path. If you press button, the preview path will be printed in the listener.
  • Open/P{lay button will be disabled then there are no files in the preview path.
    When button is disabled, the line color will be slightly darker(left).
  • Quality Override for the temporary override of ShadowMap size and Anti-Aliasing setting.
  • Play When Done moved to Settings dialog.

Other features

csMakePreview looks similar and based on 3dsMmax MakePreview. But, it has a few additional features.

  • Use Current Viewport Settings check button
    If this button is on, the current Viewport Preset/Stylem Edges Faces and Texture settings of the active viewport will be used. Basically, it will make a preview as you can see in the viewport. This is on by default.
  • The output path textbox is editable.
    You can directly type/edit in the textbox.
  • Token support!
    It supports all tokens in “Name Template”.  You can also use any global variable or global function.
    For example, you can make a  setPrefiewPath global function and set <setPrefiewPath> as path. This script will run the global function and use the result as the output path.
    Ot, If you want to add fps in the name, you can use <FrameRate>.
  • mpt4 support via ffmpeg
    You need to download ffmpeg by yourself and set the path in the Settings dialog. Eventually.
  • Ramplayer, ChaosPlayer, Custom player support.
    To use a custom player, you need to make csPlayPreview global function with 4 arguments [output path], [fps],  [start], [end].
  • Play Preview button
  • Open the preview folder button
  • Presets
    you can save/load as many as presets you want.

 

cs_sme_drop

It seems everybody loves the new multiple image drag and drop to Slate material editor in 3dsMax 2024.1.

As I mentioned in the video. You can make own function for the new callback. Here is an example script that supports VRay, Corona, Arnold and OSL map. You can add this as a startup script folder. It will auto-detect VRay, Corona, Arnold, FStorm, Octane, Redshift and make a native image loader for each renderer. If you edit as “local useOSL = true”, it will generate OSL UberBitmap.

Here is the download Download - Updated to 1.2

Here is the code.

-- cs_sme_drop v1.1
-- by Changsoo Eun
-- www.changsooeun.com
(
local maxver = (maxversion())
if maxver.count > 7 and maxver[8] > 2023 and maxver[5] > 0 then (
fn cs_sme_drop test urls pos = (
if not test then (
for f in urls do (
-- Set this to true if you want OSL UberBitmap
local useOSL = false
local amap = (bitmaptexture())
amap.filename = f
if useOSL then 
(
amap = (osl_UberBitmap2b())
amap.filename = f
)
else
(
if Corona != undefined and ((classof renderers.current) == Corona) then (
amap = (CoronaBitmap())
amap.filename = f
)
if vray != undefined and (matchpattern (renderers.current as string) pattern:"*v_ray*") then (
amap = (vrayhdri())
amap.HDRIMapName = f
)
if (matchpattern (renderers.current as string) pattern:"*FStorm*") then (
amap = (FStormBitmap())
amap.filename = f
)
if (matchpattern (renderers.current as string) pattern:"*octane*") then (
amap = (RGB_image())
amap.filename = f
)
if (matchpattern (renderers.current as string) pattern:"*redshift*") then (
amap = (RS_Bitmap())
amap.tex0_filename = f
)
if Arnold != undefined and ((classof renderers.current) == Arnold) then (
amap = (ai_image())
amap.filename = f
)
)
if useOSL then (
pos.x += 100
)
else(
pos.y += 100
)
amap.name = (getFilenameFile f)
(sme.getview sme.activeview).createnode amap pos
)
)
true
)
sme.fileDropCallback = cs_sme_drop
)
else (
messagebox "3dssMax 2024.1+ is required"
)
)

 

csMakePreview

3dsMax 2024 bring a lot of new features. Some of them are hard to show in a video. This is one of those features.

I always have wanted to have a modified version of Make Preview. For example, if you are a pipe guy at a studio, you probably would not want to give assess to the output path to artists. How about forcing some consistent studio-default options?

I have used UIAccessor in the past. I also know some studio just made their own make preview utility. But, with the update in 3dsMax 2020, I really wanted to use Max’s own Make Preview engine since it can make bigger than screen size preview.

There is a MXS command, createPreview. But, it didn’t have all the functionality of UI version. Especially, there was no way to control viewport settings. Finally, the 3dsMax 2024 createPreview function exposes every single UI option to MXS function.

So, I re-created Make Preview dialog as a script for the following reasons.

  • I wanted to check if it still misses anything compared to UI.
  • I wanted to give a template implementation for other users.
  • I wanted to add some of the features that users wanted
Download csMakePreview from here.

The added features

  • Use Current Viewport Settings checkbutton – If this button is on, the current Viewport Preset/Stylem Edges Faces and Texture settings of the active viewport will be used. Basically, it will make a preview as you can see in the viewport. This is on by default.
  • The output path textbox is editable. You can directly type/edit in the textbox.
  • Token! It supports all tokens in “Name Template”.  You can also use any global variable or global function.
    For example, you can make a  setPrefiewPath global function and set <setPrefiewPath> as path. This script will run the global function and use the result as the output path.
    Ot, If you want to add fps in the name, you can use <FrameRate>.
  • mpt4 support via ffmpeg – you need to download ffmpeg by yourself and set the path in the Settings dialog. Eventually.
  • Ramplayer, ChaosPlayer, Custom player support.
    To use a custom player, you need to make csPlayPreview global function with 4 arguments [output path], [fps],  [start], [end].
  • Set default button –  you can save default settings per user.
  • Play Preview button
  • Open the preview folder button
  • Presets – you can save/load as many as presets you want.

SmartExtrude Toggle

Smart Extrude is awesome. But, I know sometimes you want to be not so smart.
Good news. There is a maxscript property which you can turn on/off “Smart”.

Editable_Poly and Edit_Poly has #enableEnhancedHotkeyExtrude property, and as you expect, it turns Smart Extrude on/off.

For your convenience, I made a simple macroscript. Unzip and drag and drop to a viewport. Since it is a macroscript, you can make button or assign to a hotkey or add to the quad menu and etc.
Download

Because this is a property of Editable Poly and Edit Poly modifier, each Editable Poly/Edit Poly will remember the on.off status.

If you want to turn off all the time, you can use DefaultParamInterface or CustomDefaultParamManager or just run the following code to set off by default.

DefaultParamInterface.SetDefaultParamValue Editable_Poly "enableEnhancedHotkeyExtrude" false persistent:true
DefaultParamInterface.SetDefaultParamValue Edit_Poly "enableEnhancedHotkeyExtrude" false persistent:true

 

 

csArrayMaker

3dsMax 2023.2 has been released with the new feature-packed Array modifier.

This is an array/tile “rigger” based on the new Array modifier. I originally wanted to make a series of tutorials. But, I had to admit that typical Max users are too lazy to follow all the steps. So, I just made this script. I still hope to have some tutorials. But, you can just use this meanwhile.
Download

 

The generated object is “rigged”. If you change the base object size, the array/tile will adapt to it.

  • 4 geometric patterns – Circle, Diamond, Triangle, Hexagon
  • 4 tile types – Herringbone, Chevron, Wood Strip, Basker Weave
  • Option to make Chamferd/Non-Chamfered version
  • Initial Size option
  • Clone UV ID
  • 5 Material presets
    • Bitmap projection
    • Random Color MTL – random color between 2 colors per clone.
    • Random Switcher MTL – randomly chosen colors per clone among 5 given color. You can change the amount of color.
    • Random UV Offset Bitmap MTL – randomly offset UV transform and color for a bitmap.
    • Random Advanced Wood MTL – randomly offset UV 3D transform and Advanced Wood material