What's New: 3ds Max 2023 SDK
This topic describes new items and changes that affect the 3ds Max 2023 C++ SDK.
- SDK Break
- Compiler Upgrade
- Instance Display API
- Instance Rendering API
- Volume Display API
- Max to viewport material conversion API
SharedMesh
class- AutoBackup
- User Interface
- Software Security
- Geom lib updates
- Manipulator Improvements
- Deprecated features
SDK Break
3ds Max 2023 is an SDK breaking release. Plugins compiled for 3ds Max 2022 will need to be recompiled to work in 3ds Max 2023 builds.
Compiler Upgrade
3ds Max 2023 has been compiled with Visual Studio 2019 16.10.4, MSVC Platform Toolset v142, and Windows Platform SDK 10.0.19041.0.
Conformance improvements and bug fixes are made in every major and minor release of Microsoft C/C++ in Visual Studio (MSVC). These changes could potentially cause new build errors and warnings in code that previously compiled cleanly, and could also cause different runtime behavior. 3ds Max benefited from several code improvements because of migrating to the new compiler.
To learn more about MSVC conformance improvements, bug fixes, and potential upgrade issues, refer to Microsoft's Visual Studio documentation:
- C++ Conformance Improvements in Visual Studio 2019
- Overview of potential upgrade issues (Visual C++)
- Compiler warnings by compiler version
There is no single correct method of fixing upgrade issues, but the Microsoft C++ Porting and Upgrade Guide provides suggestions for a phased approach. In the 3ds Max SDK, the Platform Toolset, Windows SDK version, and C++ Language Standard are specified in the 3dsmax.general.project.settings.props
property sheet.
Instance Display API
This new API allows an object plugin to display many instances in the viewport without creating them all in the scene. The plugin describes the instance data based on a single object, and 3ds Max creates efficient representations of that object on the GPU. The instances can have different transforms, materials, mapping coordinates, and vertex colors. Examples of plugins that would benefit from using this API are particle systems, scattering tools, instancers, etc.
To take advantage of this API, plugins should use the methods of class InstanceDisplayGeometry
, which are implemented by 3ds Max. For more details, please see maxsdk\include\graphics\InstanceDisplayGeometry.h, and the sample project located in maxsdk\howto\objects\InstancedObject\ folder of the 3ds Max SDK.
Instance Rendering API
This new API allows object plugins (the producer) to produce many instances for rendering purposes efficiently, and allows renderers (the consumer) to access them and render them efficiently. Examples of plugins that would produce many instances of things to be rendered are particle systems, scattering tools, instancers, etc.
Class RenderTimeInstancingInterface
allows a renderer to access an object's instancing information so that it can do efficient instancing at render-time. This interface is implemented by an object and called by a renderer. A renderer should not call the object's GetRenderMesh()
method if the object supports the RenderTimeInstancingInterface
interface. However, even if an object implements this interface, it should ideally still implement GetRenderMesh()
to return an aggregate mesh of all instances, so that a renderer that does not support RenderTimeInstancingInterface
will still render it.
The API supports passing material, UVW, transform, motion blur and custom channel info per instance to the renderer.
Note that the Arnold rendering plugin for 3ds Max 2023 supports this new API, making it easy for 3rd party plugins to experiment with it and support it.
For more information, please see the maxsdk\include\Rendering\RenderTimeInstancing.h header file. For an example of an object that produces instances using this API, please see the maxsdk\howto\objects\RenderTimeInstancedObject\ sample project in the 3ds Max SDK.
Volume Display API
This new API simplifies displaying a volume in the viewport when a plugin provides the voxels data, positions and display options. 3ds Max will convert the voxels data on the GPU and display it according to the different supported viewport modes such as wireframe, shaded, and so on. This API proposes many options for the display such as: bounding box, wireframe, voxels, volume with a voxel color and opacity, black body, turbo gradient, or gradient custom texmaps color modes are also available. So far, it supports the volume grids of type fog and level sets. You can use a slice axis to show only a part of the volume at display time. The voxels' grid data can be normalized automatically, or manually, or not normalized at all.
You can use a 1D density transfer texture to remove some parts of the voxels data at display time, so a 3rd party can control how the volume looks. It also provides support for selection hit testing and wireframe display.
For detailed information about this API please see the header file located in maxsdk\include\graphics\ViewportVolumeDisplay.h, and the sample plugin found in maxsdk\howto\objects\VolumeSampleObject.
Max to viewport material conversion API
There are additional helper functions in MaxSDK::Graphics::MaterialConversionHelper
to convert from a 3ds Max material (Mtl
class) into a Nitrous viewport material (BaseMaterialHandle
class) with the function ConvertMaxToNitrousMaterial()
, and to create a Nitrous viewport material from a physical material preset with the function GetNitrousMaterialFromPhysicalMaterialPreset()
.
For detailed information about this API please see the header file located in maxsdk\include\Graphics\MaterialConversionHelper.h
SharedMesh
class
SharedMesh
is a class to share a mesh between different classes. It uses reference counting and gets automatically deleted and the pointer null'ed once its ref count reaches 0.
For detailed information about this API please see the header file located in maxsdk\include\SharedMesh.h.
AutoBackup
There are additional methods for controlling Auto Backup during long running operations.
IAutoBackup::SetTempDisable and IAutoBackup::GetTempDisable
- Temporarily disables Autobackup. Use this during operations where Autobackup should not occur (for example, Computations on separate threads, heavy scene manipulations).
class AutoBackupDisableHelper
- Helper class to temporarily disable and re-enable Autobackup during a computation.
Plugin Packages Improvements
The Plugin Package description file (PackageContents.xml) now supports environment variable definitions of type string and path. Plugins often make use of env vars to configure themselves or their environment. Hotkey definitions can now be specified as part of the package definition.
For more information see Packaging Plug-ins.
User Interface
Class QmaxRollupContainer
exposed.
When you need to create a pure Qt dialog with closable groups/rollups, similar to the ones used in the command panel, use QmaxRollupContainer
widget and add QmaxRollup's to it. The QmaxRollupContainer
will act as a host for the rollups and will take care of the proper layout and scrollbar adjustments.
For detailed information about this API see the header file located in maxsdk\include\Qt\QmaxRollupContainer.h
Software Security
Safe Script Execution
Addition of enum value MaxSDK::AssetManagement::AssetType::kScript
- An asset file reflecting any script file other than a pre- or post-render script file.
Addition of enum value MAXScript::ScriptSource::Dynamic
– To be used for scripts that are dynamically generated at runtime and could contain input from various sources that are interpreted as scripted commands. Dynamic scripts will always execute with restricted security rights, regardless of Safe Scene Script Execution settings.
Addition of ExecuteScriptAsset()
function - Executes the given script file specified as an AssetUser. This function should be used for executing script files whose name is stored in the scene file.
Addition of MAXScript::ScriptSource
argument to ExecuteMAXScriptScript()
function - specifies the security rights of the evaluated script string.
Secure way for plugins to load binary dependencies
3ds Max will load dynamic-link libraries (DLLs) that plugins have a link-time (implicit) dependency on from the folder where the plugin resides. In other words, the DLLs the plugin depends on do not have to be installed in 3ds Max's root folder (<maxroot>
), nor does the plugin need to do extra work to load the dlls at run-time (by calling LoadLibrary()
for example).
Simply deploy the DLLs the plugin depends on side-by-side within the same folder where the plugin resides, and 3ds Max will be able to load the plugin.
If a plugin needs to explicitly load a DLL, the safest way is to load it by specifying a complete path. If a plugin needs to change the DLL search path, it must respect the following rules:
- The
SetDllDirectory()
API is used instead ofAddDllDirectory()
to modify the DLL search path - Save the value returned by
GetDllDirectory()
- Use
SetDllDirectory()
to specify the nonstandard folder you want to load from - Load the DLL.
- Use
SetDllDirectory()
again to restore the previous value. - Keep the changes to the DLL search path in effect for as short of a code-scope as possible
- Never call
SetDllDirectory(nullptr)
as it adds the current working directory to the search path and causes a security vulnerability.
For more information see the MSDN topic on Dynamic-Link Library Security.
Geom lib updates
Geom headers moved to its own folder
All the header files that make up the 3ds Max geom library have moved to maxsdk\include\geom. To make it easy for your project to absorb this change, you could add the $(MaxSdkGeomInc)
path to the list of include paths of your project settings. To benefit from this your code needs to include geom header files without a qualified path.
Geom support for std::span
in the form of geo::span
Span is a very simple type. You can think of it as a "view" on some memory. It holds a non-owning pointer to some data and a size. You can create spans from std::vector
, from Tab, from raw arrays, etc. Using geo::span
is much safer than passing raw pointers around, and it supports developer-friendly features such as ranged for loops.
// Creating spans from a std::vector.
std::vector<int> v;
geo::span<const int> const_vec_span{v};
geo::span<int> vec_span{v};
// Creating spans from a Tab.
Tab<int> t;
geo::span<const int> const_tab_span{t};
geo::span<int> tab_span{t};
// You can create spans from a pointer and a size.
const int* buffer;
geo::span<const int> buf_span{buffer, 10};
// You can create spans from iterators, as long as they point to contiguous memory.
std::vector<int> v2;
geo::span<int> range_span{v2.begin(), v2.begin() + 5};
For more information on std::span
see https://en.cppreference.com/w/cpp/container/span
Manipulator Improvements
All/Active Manipulator Display Control
Previously, when an object and modifiers applied to it both had Manipulators, when editing the modifier, both the modifier's manipulators and the base object's manipulators were active at the same time. This could cause problems due to conflicts between the two sets of manipulators -- the user might inadvertently click on the base object's manipulator when the intention was to click on the modifier's manipulator.
3ds Max 2023 allows the user to set the Manipulator system to display all the manipulators for an object (legacy behavior) or display only the manipulators for the active object or modifier. This is available in the main menu, Customize > Preferences > Gizmos > Manipulators (Object / Only Active).
Developers can detect and set this behavior programmatically via the IManipulatorManager interface (see 3dswin\src\maxsdk\include\manipulator.h):
virtual ObjectManipulatorDisplayMode GetObjectManipulatorMode()
virtual ObjectManipulatorDisplayMode SetObjectManipulatorMode(ObjectManipulatorDisplayMode newMode)
ObjectManipulatorDisplayMode
is defined as:
kAllManipulators = 0,
kActiveManipulators = 1,
Manipulator Right Button Mouse Interaction
Manipulators can now use the right mouse button for interaction in addition to the left mouse button.
3ds Max 2023 adds the following to the Manipulator class:
virtual void OnRButtonDown(TimeValue t, ViewExp* pVpt, IPoint2& m, DWORD flags, ManipHitData* pHitData) {}
virtual void OnRButtonUp(TimeValue t, ViewExp* pVpt, IPoint2& m, DWORD flags, ManipHitData* pHitData) {}
These methods are called when the right mouse button is clicked or released, respectively. Functionality is essentially the same as for the left mouse button.
Deprecated features
- Combustion Map
- Panorama Exporter's support for Quicktime VR output format