Skip to content

Commit

Permalink
Improve Alembic plugin to read assets with ArResolver to support othe…
Browse files Browse the repository at this point in the history
…r sources except local files

Alembic plugin only accepts assets that are from local paths. In order to fix this, we need to use ArResolver/ArAsset to read/write contents so customized resolver can read assets
from other locations. However, interfaces of Alembic library have limitations that can only accept local urls or `std::istream`. This PR uses the following solution:

Open assets with `ArResolver`. Instead of reading them into the memory, we get the mapped file path with
[ArchGetFileName](https://github.com/PixarAnimationStudios/OpenUSD/blob/59992d21/pxr/base/arch/fileSystem.h#L177) from `ArAsset::GetFileUnsafe`.

Fixes #2961
Closes #3302

(Internal change: 2353336)
  • Loading branch information
roggiezhang-nv authored and pixar-oss committed Jan 27, 2025
1 parent d7dc4ad commit 14f0905
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions pxr/usd/plugin/usdAbc/alembicReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@
/// \file alembicReader.cpp

#include "pxr/pxr.h"
#include "pxr/usd/ar/asset.h"
#include "pxr/usd/ar/resolvedPath.h"
#include "pxr/usd/ar/resolver.h"
#include "pxr/usd/plugin/usdAbc/alembicReader.h"
#include "pxr/usd/plugin/usdAbc/alembicUtil.h"
#include "pxr/usd/usdGeom/hermiteCurves.h"
#include "pxr/usd/usdGeom/tokens.h"
#include "pxr/usd/usdGeom/xformable.h"
#include "pxr/usd/sdf/schema.h"
#include "pxr/base/arch/fileSystem.h"
#include "pxr/base/work/threadLimits.h"
#include "pxr/base/trace/trace.h"
#include "pxr/base/tf/envSetting.h"
#include "pxr/base/tf/staticData.h"
#include "pxr/base/tf/staticTokens.h"
#include "pxr/base/tf/ostreamMethods.h"
#include "pxr/base/tf/fileUtils.h"
#include <Alembic/Abc/ArchiveInfo.h>
#include <Alembic/Abc/IArchive.h>
#include <Alembic/Abc/IObject.h>
Expand Down Expand Up @@ -801,6 +806,8 @@ class _ReaderContext {
const ISampleSelector& selector,
const UsdAbc_AlembicDataAny& value) const;

std::string _OpenAndGetMappedFilePath(const std::string& filePath);

// Custom auto-lock that safely ignores a NULL pointer.
class _Lock {
public:
Expand Down Expand Up @@ -853,6 +860,10 @@ class _ReaderContext {
_PrimMap _prims;
Prim* _pseudoRoot;
UsdAbc_TimeSamples _allTimeSamples;

// Asset holders to keep a reference alive so that resolver doesn't
// attempt to cleanup asset until the asset is no longer in use.
std::vector<std::shared_ptr<ArAsset>> _assetHolders;
};

static
Expand All @@ -872,6 +883,36 @@ _ReaderContext::_ReaderContext() :
// Do nothing
}

std::string
_ReaderContext::_OpenAndGetMappedFilePath(const std::string& filePath)
{
// Return as it is if it's a local path or symlink.
if (!TfIsFile(filePath, true))
{
// Open asset with Ar to support URLs other than local paths.
std::shared_ptr<ArAsset> asset =
ArGetResolver().OpenAsset(ArResolvedPath(filePath));
if (asset)
{
FILE* fileHandle; size_t fileOffset;
std::tie(fileHandle, fileOffset) = asset->GetFileUnsafe();
// Check file offset also to ensure that the .abc file
// we're looking at isn't embedded in a .usdz or other package
if (fileHandle && fileOffset == 0)
{
// If file handle is presented, use mapped file path instead of original one.
const std::string mappedFilePath = ArchGetFileName(fileHandle);
_assetHolders.emplace_back(std::move(asset));

return mappedFilePath;
}
}
}

// Otherwise, fallback to original asset path.
return filePath;
}

bool
_ReaderContext::Open(const std::string& filePath, std::string* errorLog,
const SdfFileFormat::FileFormatArguments& args)
Expand All @@ -883,11 +924,11 @@ _ReaderContext::Open(const std::string& filePath, std::string* errorLog,
auto abcLayers = args.find("abcLayers");
if (abcLayers != args.end()) {
for (auto&& l : TfStringSplit(abcLayers->second, ",")) {
layeredABC.emplace_back(std::move(l));
layeredABC.emplace_back(_OpenAndGetMappedFilePath(l));
}
}
}
layeredABC.emplace_back(filePath);
layeredABC.emplace_back(_OpenAndGetMappedFilePath(filePath));

#if PXR_HDF5_SUPPORT_ENABLED && !H5_HAVE_THREADSAFE
// HDF5 may not be thread-safe.
Expand Down Expand Up @@ -1507,6 +1548,7 @@ _ReaderContext::_Clear()
_allTimeSamples.clear();
_instanceSources.clear();
_instances.clear();
_assetHolders.clear();
}

const _ReaderContext::Prim*
Expand Down

0 comments on commit 14f0905

Please sign in to comment.