3ds Max USD API Reference
Loading...
Searching...
No Matches
TranslationUtils.h
1//**************************************************************************/
2// Copyright (c) 1998-2020 Autodesk, Inc.
3// All rights reserved.
4//
5// Use of this software is subject to the terms of the Autodesk license
6// agreement provided at the time of installation or download, or which
7// otherwise accompanies this software in either electronic or hard copy form.
8//**************************************************************************/
9// DESCRIPTION: Translation utilities.
10// AUTHOR: Autodesk Inc.
11//***************************************************************************/
12#pragma once
13
14#include <inode.h>
15#include <mesh.h>
16
17#include "MaxUsd/MaxUSDAPI.h"
18#include "MaxUsd.h"
19
20#include <pxr/usd/usd/common.h>
21#include <pxr/usd/usdGeom/primvar.h>
22#include <pxr/usd/usdGeom/mesh.h>
23#include <pxr/usd/usd/stageCache.h>
24#include <pxr/usd/usdUtils/stageCache.h>
25
26// MAXX-63363: VS2019 v142: <experimental/filesystem> is deprecated and superseded by the C++17 <filesystem> header
27#if _MSVC_LANG > 201402L
28#include <filesystem>
29namespace fs = std::filesystem;
30#else
31#include <experimental/filesystem>
32namespace fs = std::experimental::filesystem;
33#endif
34
35class IParamBlock2;
36class ISkin;
37class Modifier;
38
39namespace MAXUSD_NS_DEF {
40
49template <class T>
50T fetchOrCreatePrim(const pxr::UsdStagePtr stage, const pxr::SdfPath& primPath, pxr::TfToken token)
51{
52 // Fetch or create the target prim. In a typical export scenario, a new prim will be defined here.
53 T prim = T(stage->GetPrimAtPath(primPath));
54 if (!prim)
55 {
56 // Using the sdf apis as such instead of UsdStage::Define prim is much faster.
57 {
58 pxr::SdfChangeBlock changeBlock;
59 const auto prim_spec = pxr::SdfCreatePrimInLayer(stage->GetRootLayer(), primPath);
60 prim_spec->SetSpecifier(pxr::SdfSpecifierDef);
61 prim_spec->SetTypeName(token);
62 }
63 prim = T(stage->GetPrimAtPath(primPath));
64 }
65 return prim;
66}
67
77bool wsmRequiresTransformToLocalSpace(INode* node, const TimeValue& time);
78
85Matrix3 getMaxObjectOffsetTransform(INode* node);
86
95void applyObjectOffsetTransform(INode* node, pxr::UsdGeomXformable& xformable, const TimeValue& time);
96
103MaxUSDAPI bool isValidChannel(int channel);
104
111MaxUSDAPI bool getValidIdentifier(const std::wstring& identifier, std::string& validIdentifier);
112
118MaxUSDAPI size_t getTypeDimension(const pxr::SdfValueTypeName& type);
119
131MaxUSDAPI bool validateMappedDataForMesh(size_t valueCount, const pxr::VtIntArray indices, const MNMesh& maxMesh,
132 const pxr::TfToken& interpolation, bool isIndexed);
133
142MaxUSDAPI bool isValidAbsolutePath(const fs::path& path);
143
154MaxUSDAPI bool findInstanceableNodes(
155 INode* node, INodeTab& instancesNode, const std::unordered_set<INode*>& eligibleNodes);
156
166MaxUSDAPI Object* getFirstDerivedObjectWithModifier(INode* node);
167
174{
175public:
176 MaxUSDAPI std::string getName(const std::string& name);
177 MaxUSDAPI void reset();
178
179private:
180 std::unordered_set<std::string> existingNames;
181 std::string getNextName(const std::string& name);
182};
183
188{
189public:
194 StageCacheScopeGuard(const pxr::UsdStageRefPtr& stage)
195 {
196 // If the stage was already present in the global cache, we don't need to add it,
197 // and we should not remove it in the destructor either. We want to leave the cache
198 // in the same state we found it.
199 auto& cache = pxr::UsdUtilsStageCache::Get();
200 if (!cache.Contains(cache.GetId(stage)))
201 {
202 id = cache.Insert(stage);
203 }
204 }
209 {
210 if (id.IsValid())
211 {
212 pxr::UsdUtilsStageCache::Get().Erase(id);
213 }
214 }
215
216private:
217 pxr::UsdStageCache::Id id;
218};
219
226MaxUSDAPI pxr::UsdTimeCode GetUsdTimeCodeFromMaxFrame(const pxr::UsdStageWeakPtr& stage, const double maxFrame);
227
234MaxUSDAPI double GetMaxFrameFromUsdTimeCode(const pxr::UsdStageWeakPtr& stage, const pxr::UsdTimeCode usdTimeCode);
235
243MaxUSDAPI pxr::UsdTimeCode GetTimeCode(const pxr::UsdStageWeakPtr& stage, const TimeValue& timeValue);
244
255MaxUSDAPI pxr::UsdTimeCode GetOffsetTimeCode(const pxr::UsdStageWeakPtr& stage, const TimeValue& timeValue,
256 const double customAnimStartFrame, const double customAnimationLength = 0);
257
263MaxUSDAPI double GetUsdToMaxScaleFactor(const pxr::UsdStageWeakPtr& stage);
264
271MaxUSDAPI pxr::GfMatrix4d GetStageAxisAndUnitRootTransform(pxr::UsdStageWeakPtr stage);
272
279MaxUSDAPI short FindParamId(IParamBlock2* pb2, const wchar_t* name);
280
286MaxUSDAPI std::string maxStringToUSDString(const wchar_t* utf16EncodedWideString);
287
293MaxUSDAPI std::string usdStringToLower(std::string utf8EncodedString);
294
300MaxUSDAPI WStr usdStringToMaxString(const std::string& utf8EncodedString);
301
306MaxUSDAPI bool hasUnicodeCharacter(const std::string& str);
307
309{
310 double startFrame{ 0.0 };
311 double endFrame{ 0.0 };
312 double samplesPerFrame{ 1.0 };
313
314 bool IsAnimated() const
315 {
316 return startFrame != endFrame;
317 };
318};
319
320
330MaxUSDAPI void convertFrames(
331 INode* node, std::function<void(Object*, const TimeValue&, const pxr::UsdTimeCode&)> convertFrame,
332 const TimeConfig& usdTimeConfig,
333 std::function<Interval(Object*, const TimeValue&)> objectValidityOverride = [](Object*, const TimeValue&) {
334 return FOREVER;
335 });
336
346MaxUSDAPI std::pair<pxr::VtArray<TimeValue>, pxr::VtArray<pxr::UsdTimeCode>> getFramesFromValidityInterval(
347 INode* node,
348 const TimeConfig& usdTimeConfig
349 );
350
356MaxUSDAPI bool isBoneObject(Object* object);
357
363MaxUSDAPI bool hasMorpherModifier(INode* node);
364
370MaxUSDAPI TimeValue getTicksFromFrame(double frame);
371
377MaxUSDAPI std::string getNonLocalizedClassName(ClassDesc* classDesc);
378
386MaxUSDAPI pxr::SdfPath VerifyOrMakeSkelRoot(const pxr::UsdStagePtr& usdStage, const pxr::SdfPath& path, const bool autoGenerate = true);
387
398template <class T>
399T VerifyOrMakePrimOfType(const pxr::UsdStagePtr& usdStage, const pxr::SdfPath& basePath,
400 const pxr::TfToken& primName)
401{
402 UniqueNameGenerator subsetNameGenerator;
403 std::string currentPrimString = subsetNameGenerator.getName(primName.GetString());
404 pxr::SdfPath currentPath = basePath.AppendElementString(currentPrimString);
405
406 pxr::UsdPrim prim = usdStage->GetPrimAtPath(currentPath);
407 while(prim && !prim.IsA<T>())
408 {
409 currentPrimString = subsetNameGenerator.getName(currentPrimString);
410 currentPath = basePath.AppendElementString(currentPrimString);
411 prim = usdStage->GetPrimAtPath(currentPath);
412 }
413
414 // if prim doesn't exist, create one and return
415 if(!prim)
416 {
417 return T::Define(usdStage, currentPath);
418 }
419
420 return T(prim);
421}
422
430pxr::UsdPrim FindRootmostXformOrSkelRoot(pxr::UsdStagePtr usdStage, const pxr::SdfPath& path);
431
438bool SetPrimHidden(IParamBlock2* usdCustomAttributePb, pxr::UsdPrim& translatedPrim);
439
446bool SetPrimKind(IParamBlock2* usdCustomAttributePb, pxr::UsdPrim& translatedPrim);
447
454bool SetPrimPurpose(IParamBlock2* usdCustomAttributePb, pxr::UsdPrim& translatedPrim);
455
462std::vector<ISkin*> getMaxSkinModifiers(INode* node, bool enabledOnly = true);
463
470std::vector<Modifier*> getAllModifiers(INode* node, bool enabledOnly = true);
471
476{
477 pxr::SdfPath path;
478 pxr::TfToken type;
479};
480typedef std::vector<maxUsd::PrimDef> PrimDefVector;
481typedef std::shared_ptr<PrimDefVector> PrimDefVectorPtr;
482
494enum class XformSplitRequirement
495{
497 Always,
499 ForOffsetObjects,
502 Never,
503};
504
509enum class MaterialAssignRequirement
510{
511 // Default material assignment.
512 Default,
513 // No material assignment. No material necessary, or material assignment handled differently.
514 NoAssignment
515};
516
521enum class InstancingRequirement
522{
523 // Instancing handled automatically. Only the first instance will hit the Write() method.
524 Default,
525 // Instancing is not handled automatically, it is left to the prim writer to decided how to
526 // handle instancing, or not..
527 NoInstancing
528};
529
536MaxUSDAPI pxr::GfMatrix4d getNodeTransform(INode* sourceNode, TimeValue time, bool YUp);
537
543class HasDependentSkinProc : public DependentEnumProc
544{
545public:
546 ReferenceTarget* node = nullptr;
547 bool hasDependentSkin = false;
548
549 HasDependentSkinProc(ReferenceTarget* target);
550
551 int proc(ReferenceMaker *rmaker) override;
552};
553
554} // namespace MAXUSD_NS_DEF
Callback helper class for enumerating Max node dependents with skin modifiers. This class is a callba...
Definition: TranslationUtils.h:544
RAII Scope guard for adding and remove a stage from the global stage cache.
Definition: TranslationUtils.h:188
StageCacheScopeGuard(const pxr::UsdStageRefPtr &stage)
Constructor, adds a stage to the global stage cache.
Definition: TranslationUtils.h:194
~StageCacheScopeGuard()
Destructor, removes the stage from the global stage cache.
Definition: TranslationUtils.h:208
Utility class to ensure every name is unique. To use, create an instance and call the getName functio...
Definition: TranslationUtils.h:174
Simple struct to define a Prim, from its path and type.
Definition: TranslationUtils.h:476
Definition: TranslationUtils.h:309