What's New: 3ds Max 2019 SDK
This topic describes new items and changes that affect the 3ds Max 2019 C++ SDK.
SDK Break
The 3ds Max 2019 SDK is not binary backward compatible with the 3ds Max 2018 SDK. This means that plugins will need to be re-compiled in order to work in 3ds Max 2019.
Qt
3ds Max 2019 uses Qt 5.6.3 which is binary compatible with Qt 5.6.2 used by 3ds Max 2018. 3rd party plugins can compile against the official Qt 5.6.3 version.
Plugin Installation
Improved support for loading binary dependencies
3ds Max will load dynamic-link libraries (dlls) that plugins have a link-time, or implicit, depency on from the folder where the plugin resides. In other words, the dll the plugin depends on does 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 non standard folder you want to load from - Load your dll.
- Use
SetDllDirectory()
again to restore the previous value. - The changes to the DLL search path are in effect for as short of a code-scope as possible
- Never call
SetDllDirectory(nullptr)
, 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.
Support for Autodesk Application Plug-in Packages
3ds Max will find and load plugins that have a PackageContent.xml file installed in one of the these two standard locations:
- %PROGRAMDATA%\Autodesk\ApplicationPlugins
- %APPDATA%\Autodesk\ApplicationPlugins
Using the Autodesk Application Plug-in Package format eliminates the need for plugin installers to deploy the plugin into the plugins folder of the 3ds Max installation, or to add the plugin's install directory to the user's Plugin.UserSettings.ini. Plugins do not need to be published on the Autodesk App Store in order to use the Autodesk Application Plug-in Package format. For more details, see Packaging Plug-ins
Parameter Blocks
Improved parameter block validation
Localized names of ParamBlock2 (PB2) parameters are now tested to ensure they use resource ids instead of string literals.
Using string literals instead of resource id generates the following error:
This means that the definition for parameter 'Uuid' in ParamBlockDesc2 'Object UUUID' has an invalid resource id for the localized name. Most likely the name was specified as a string literal instead of a resource id. For example:
XRefMaterial::pbEnableOverride, _T("enableOverride"), TYPE_BOOL, 0, _T(""),
should be:
XRefMaterial::pbEnableOverride, _T("enableOverride"), TYPE_BOOL, 0, IDS_XREFMATERIAL_ENABLE_OVERRIDE,
or
XRefMaterial::pbEnableOverride, _T("enableOverride"), TYPE_BOOL, 0, 0,
A resource id of 0 in this context is interpreted as a null string. Valid resource id values are in the range of 0 to 65535.
Improved support for saving to previous scene file versions of PB1 plugins migrated to PB2
The ParamBlock1 (PB1) to ParamBlock2 (PB2) migration documentation in the 3ds Max 2018 SDK help shows an implementation of BoxObject::SpecifySaveReferences()
that replaces the PB2 reference with a PB1 reference with a call to ReferenceSaveManager::ReplaceReferenceSlot()
. It was found that this was insufficient, as other objects may hold a reference to the PB2, and those references needed to point to the PB1.
An example of this is the Script Controller, which can hold a reference to the PB2 as part of a Target type variable. Adding the following code causes all references to the PB2 to use the PB1 instead in the saved file:
// register the reference slot replacement
referenceSaveManager.ReplaceReferenceSlot(PBLOCK_REF_NO, paramBlock1);
// register transferring all refs to the pb2 to the pb1
ReferenceSaveManager& pb2_referenceSaveManager = pblock2→GetReferenceSaveManager();
pb2_referenceSaveManager.SetReplacementReferenceTarget(paramBlock1);
For 3ds Max 2019, the bulk of the code needed in the implementation of ReferenceMaker::SpecifySaveReferences()
of the plugin being migrated from PB1 to PB2, was placed in a helper function exported by paramblk2.lib
. As a result, a typical implementation of this method becomes:
bool BoxObject::SpecifySaveReferences(ReferenceSaveManager& referenceSaveManager)
{
// if saving to previous version that used pb1 instead of pb2...
DWORD saveVersion = GetSavingVersion();
if (saveVersion != 0 && saveVersion <= MAX_RELEASE_R19)
{
ProcessPB2ToPB1SaveToPrevious(this, pblock2, PBLOCK_REF_NO, descVer1, PBLOCK_LENGTH, CURRENT_VERSION);
}
return __super::SpecifySaveReferences(referenceSaveManager);
}
Rendering
Open Shading Language (OSL)
3ds Max 2019 introduces support for the Open Shading Language (OSL). The new OSL Texmap is an execution environment for OSL shaders within 3ds Max. Being a regular 3ds Max Texmap object (shader) (i.e. it implements Textmap::EvalColor(), Texmap::EvalMono() and Texmap::EvalNormalPerturb() methods), it works in any renderer supporting the classic 3ds Max shader API (Scanline, vRay, Corona etc.). It also means it works outside of renderers, anywhere in 3ds Max where a regular texture map is requested, such as in the Displacement modifier, etc. It can also work with renderers that support OSL natively, such as Arnold. In that case, the execution environment inside the OSL Map is not used, instead, the OSL code, the parameter values, and shader bindings are sent to the renderer, which executes the OSL code itself.
Going forward the recommended way to write texture maps (shaders) for 3ds Max is through OSL.
For more information, see Open Shading Language Support.
Thread Safe EvalXXX Methods
class TexmapThreadSafe has been deprecated. The Texmap::EvalXXX() overrides of your plugin are required to be thread safe by definition. The Texmap::EvalXXX() overrides should not read or write directly or indirectly scene data. They should only read data in member variables local to the shader instance. 3ds Max guarantees a thread-safe execution of the Texmap::EvalXXX() methods by first ensuring that everything is updated (calling Texmap::Update()) from within the main thread, and then calling Texmap::EvalXXX() in multiple threads during rendering.
For compatibility, and as a safety measure, the TexmapThreadSafe interface still exists in the 3ds Max 2019 SDK. Rendering of a Texmap instance will be single-threaded when it uses class TexmapThreadSafe to set the thread safety to false, as follows:
// Error checking omitted for brevity
MaxSDK::TexmapThreadSafe* pTexmapThreadSafe = static_cast<MaxSDK::TexmapThreadSafe*>(GetInterface(ITEXMAP_THREAD_SAFE));
pTexmapThreadSafe->SetFunctionFlag(MaxSDK::TexmapThreadSafe::FunctionEvalMono, false);
pTexmapThreadSafe->SetFunctionFlag(MaxSDK::TexmapThreadSafe::FunctionEvalColor, false);
Note that class TexmapThreadSafe's semantics is only used when texture backing in 3ds Max (i.e. Interface::RenderTexmap()), and the scene rendering is always multi-threaded, unless explicitly disabled in the renderer.
Modeling
Vertex Velocity
The new IVertexVelocity
interface allows for easily extracting per-vertex velocity data computed from fluid simulations or Alembic and stored on the mesh. This interface simplifies the task of getting to the vertex velocity data stored in the map channels of a mesh.
Double precision geometric primitives
The following new classes have been added: class DPoint2
, class DBox2
, class DRay2
. Their functionality mirrors that of their floating point counterparts class Point2
, class Box2
, and class Ray
.
Miscellaneous
Custom File Stream API
3ds Max 2019 supports user defined data streams in scene files (.max).
The data streams can be accessed through MAXScript (see the CustomFileStream
and CustomSceneStreamManager
interfaces) and a C++ API found in maxsdk\include\customfilestreamapi.
The implementation of the CustomFileStream API and that of the two MAXScript interfaces is available in maxsdk\samples\utilities\customfilestream.
The CustomFileStreamAPI library does not have dependencies on the 3ds Max SDK, so you can write 3ds Max agnostic applications that use custom scene file data.
Qt related project settings
In order to prevent memory access violation issues when unloading plugins using Qt, the QT_NO_UNICODE_LITERAL was added to the PreProcessorDefinition setting in maxsdk/projectsettings/3dsmax.common.tools.settings.props
Improved robustness of some APIs
In an effort to reduce the chances for buffer overflow we modified several 3ds Max SDK functions to take MSTR&
arguments instead of MCHAR*
, or added buffer length arguments when we had to keep the MCHAR*
arguments.
Examples:
maxsdk\include\strclass.h
: Added buffer length arguments toSplitFilenameOld()
and thechar* (wchar_t*)
versions ofSplitFilename()
.maxsdk\include\systemutilities.h
: ModifiedUtilGetFolderPath()
,GetSpecDir()
, andTryCSIDLDir()
to acceptMSTR&
arguments instead of raw string buffer pointers.
Note that we will continue to make changes to the 3ds Max SDK in future releases in order to increase the robustness of 3ds Max.