Skip to content

Commit

Permalink
[usdAbc] Pass Sdf arguments to Alembic plugin.
Browse files Browse the repository at this point in the history
         Add ability to read the entire hierarchy in under a single parent.
	 Add ability to load layered Alembic.
  • Loading branch information
rzulak committed Feb 19, 2020
1 parent d0d449a commit 5a795b2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 105 deletions.
11 changes: 6 additions & 5 deletions pxr/usd/plugin/usdAbc/alembicData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ typedef std::set<double> UsdAbc_TimeSamples;

#define XXX_UNSUPPORTED(M) TF_RUNTIME_ERROR("Alembic file " #M "() not supported")

UsdAbc_AlembicData::UsdAbc_AlembicData()
UsdAbc_AlembicData::UsdAbc_AlembicData(const SdfFileFormat::FileFormatArguments* args)
{
// Do nothing
if (args && !args->empty())
_arguments.reset(new SdfFileFormat::FileFormatArguments(*args));
}

UsdAbc_AlembicData::~UsdAbc_AlembicData()
Expand All @@ -119,9 +120,9 @@ UsdAbc_AlembicData::~UsdAbc_AlembicData()
}

UsdAbc_AlembicDataRefPtr
UsdAbc_AlembicData::New()
UsdAbc_AlembicData::New(const SdfFileFormat::FileFormatArguments* args)
{
return TfCreateRefPtr(new UsdAbc_AlembicData);
return TfCreateRefPtr(new UsdAbc_AlembicData(args));
}

bool
Expand All @@ -148,7 +149,7 @@ UsdAbc_AlembicData::Open(const std::string& filePath)
//_reader->SetFlag(UsdAbc_AlembicContextFlagNames->verbose);

// Open the archive.
if (_reader->Open(filePath)) {
if (_reader->Open(filePath, _arguments ? _arguments.get() : nullptr)) {
return true;
}

Expand Down
6 changes: 4 additions & 2 deletions pxr/usd/plugin/usdAbc/alembicData.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "pxr/pxr.h"
#include "pxr/usd/sdf/data.h"
#include "pxr/usd/sdf/fileFormat.h"
#include "pxr/base/tf/declarePtrs.h"
#include <boost/shared_ptr.hpp>

Expand All @@ -43,7 +44,7 @@ class UsdAbc_AlembicData : public SdfAbstractData {
/// Returns a new \c UsdAbc_AlembicData object. Outside a successful
/// \c Open() and \c Close() pairing, the data acts as if it contains
/// a pseudo-root prim spec at the absolute root path.
static UsdAbc_AlembicDataRefPtr New();
static UsdAbc_AlembicDataRefPtr New(const SdfFileFormat::FileFormatArguments* = nullptr);

/// Opens the Alembic file at \p filePath read-only (closing any open
/// file). Alembic is not meant to be used as an in-memory store for
Expand Down Expand Up @@ -103,14 +104,15 @@ class UsdAbc_AlembicData : public SdfAbstractData {
EraseTimeSample(const SdfPath&, double);

protected:
UsdAbc_AlembicData();
UsdAbc_AlembicData(const SdfFileFormat::FileFormatArguments*);
virtual ~UsdAbc_AlembicData();

// SdfAbstractData overrides
virtual void _VisitSpecs(SdfAbstractDataSpecVisitor* visitor) const;

private:
boost::shared_ptr<class UsdAbc_AlembicDataReader> _reader;
std::unique_ptr<SdfFileFormat::FileFormatArguments> _arguments;
};


Expand Down
2 changes: 1 addition & 1 deletion pxr/usd/plugin/usdAbc/alembicFileFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ UsdAbcAlembicFileFormat::~UsdAbcAlembicFileFormat()
SdfAbstractDataRefPtr
UsdAbcAlembicFileFormat::InitData(const FileFormatArguments& args) const
{
return UsdAbc_AlembicData::New();
return UsdAbc_AlembicData::New(&args);
}

bool
Expand Down
166 changes: 70 additions & 96 deletions pxr/usd/plugin/usdAbc/alembicReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,7 @@
#include <Alembic/Abc/ITypedArrayProperty.h>
#include <Alembic/Abc/ITypedScalarProperty.h>
#include <Alembic/AbcCoreAbstract/Foundation.h>

#ifdef PXR_MULTIVERSE_SUPPORT_ENABLED
#include <Alembic/AbcCoreGit/All.h>
#endif // PXR_MULTIVERSE_SUPPORT_ENABLED

#ifdef PXR_HDF5_SUPPORT_ENABLED
#include <Alembic/AbcCoreHDF5/All.h>
#endif // PXR_HDF5_SUPPORT_ENABLED

#include <Alembic/AbcCoreOgawa/All.h>
#include <Alembic/AbcCoreFactory/IFactory.h>
#include <Alembic/AbcGeom/GeometryScope.h>
#include <Alembic/AbcGeom/ICamera.h>
#include <Alembic/AbcGeom/ICurves.h>
Expand Down Expand Up @@ -132,7 +123,7 @@ _GetNumOgawaStreams()
static_cast<int>(WorkGetConcurrencyLimit()));
}

#ifdef PXR_HDF5_SUPPORT_ENABLED
#if PXR_HDF5_SUPPORT_ENABLED && !H5_HAVE_THREADSAFE
// A global mutex until our HDF5 library is thread safe. It has to be
// recursive to handle the case where we write an Alembic file using an
// UsdAbc_AlembicData as the source.
Expand Down Expand Up @@ -701,7 +692,8 @@ class _ReaderContext {
/// @{

/// Open an archive.
bool Open(const std::string& filePath, std::string* errorLog);
bool Open(const std::string& filePath, std::string* errorLog,
const SdfFileFormat::FileFormatArguments* args);

/// Close the archive.
void Close();
Expand Down Expand Up @@ -788,14 +780,6 @@ class _ReaderContext {
typedef std::set<_ObjectPtr> _ObjectReaderSet;
typedef std::map<_ObjectPtr, _ObjectReaderSet> _SourceToInstancesMap;

// Open an archive of different formats.
bool _OpenHDF5(const std::string& filePath, IArchive*,
std::string* format, std::recursive_mutex** mutex) const;
bool _OpenOgawa(const std::string& filePath, IArchive*,
std::string* format, std::recursive_mutex** mutex) const;
bool _OpenGit(const std::string& filePath, IArchive*,
std::string* format, std::recursive_mutex** mutex) const;

// Walk the object hierarchy looking for instances and instance sources.
static void _FindInstances(const IObject& parent,
_SourceToInstancesMap* instances);
Expand Down Expand Up @@ -894,22 +878,58 @@ _ReaderContext::_ReaderContext() :
}

bool
_ReaderContext::Open(const std::string& filePath, std::string* errorLog)
_ReaderContext::Open(const std::string& filePath, std::string* errorLog,
const SdfFileFormat::FileFormatArguments* args)
{
Close();

IArchive archive;
std::vector<std::string> layeredABC;
if (args) {
const auto abcLayers = args->find("abcLayers");
if (abcLayers != args->end()) {
for (auto&& l : TfStringSplit(abcLayers->second, ",")) {
layeredABC.emplace_back(std::move(l));
}
}
}
layeredABC.emplace_back(filePath);

#if PXR_HDF5_SUPPORT_ENABLED && !H5_HAVE_THREADSAFE
// HDF5 may not be thread-safe.
using lock_guard = std::lock_guard<std::recursive_mutex>;
std::unique_ptr<std::lock_guard<std::recursive_mutex>> hfd5Lock(new lock_guard(*_hdf5));
#endif

using IFactory = ::Alembic::AbcCoreFactory::IFactory;
IFactory factory;
IFactory::CoreType abcType;
factory.setPolicy(Abc::ErrorHandler::Policy::kQuietNoopPolicy);
factory.setOgawaNumStreams(_GetNumOgawaStreams());
IArchive archive = factory.getArchive(layeredABC, abcType);

#if PXR_HDF5_SUPPORT_ENABLED && !H5_HAVE_THREADSAFE
if (abcType == IFactory::kHDF5 || abcType == IFactory::kLayer) {
// An HDF5, or layered which may have an HDF5 layer
_mutex = &*_hdf5;
} else {
// Don't need the HDF5 lock
hfd5Lock.reset();
}
#endif

std::string format;
if (!(_OpenOgawa(filePath, &archive, &format, &_mutex) ||
_OpenHDF5(filePath, &archive, &format, &_mutex) ||
_OpenGit(filePath, &archive, &format, &_mutex))) {
*errorLog = "Unsupported format";
switch (abcType) {
case IFactory::kHDF5: format = "HDF5"; break;
case IFactory::kOgawa: format = "Ogawa"; break;
case IFactory::kLayer: format = "Layer"; break;
default:
case IFactory::kUnknown: format = "Unknown"; break;
}
if (!archive.valid()) {
*errorLog = TfStringPrintf("Unsupported format: '%s'", format.c_str());
return false;
}

// Lock _mutex if it exists for remainder of this method.
_Lock lock(_mutex);

// Get info.
uint32_t apiVersion;
std::string writer, version, date, comment;
Expand All @@ -923,7 +943,7 @@ _ReaderContext::Open(const std::string& filePath, std::string* errorLog)
}

// Cut over.
_archive = archive;
_archive = std::move(archive);

// Fill pseudo-root in the cache.
const SdfPath rootPath = SdfPath::AbsoluteRootPath();
Expand Down Expand Up @@ -973,8 +993,24 @@ _ReaderContext::Open(const std::string& filePath, std::string* errorLog)
_SetupInstancing(instances, promotable, &usedRootNames);
}

// Re-root so the <defaultPrim> is actually the archive!
TfToken abcReRoot;
if (args) {
const auto reRoot = args->find("abcReRoot");
if (reRoot != args->end())
abcReRoot = TfToken(reRoot->second);
}

// Fill rest of the cache.
_ReadPrimChildren(*this, root, rootPath, *_pseudoRoot);
if (!abcReRoot.IsEmpty()) {
SdfPath compPath = rootPath.AppendChild(abcReRoot);
auto& xform = _prims[compPath];
xform.typeName = UsdAbcPrimTypeNames->Xform;
xform.specifier = SdfSpecifierDef;
_ReadPrimChildren(*this, root, compPath, xform);
_pseudoRoot->children.emplace_back(std::move(abcReRoot));
} else
_ReadPrimChildren(*this, root, rootPath, *_pseudoRoot);

// Append the masters to the pseudo-root. We use lexicographical order
// but the order doesn't really matter. We also note here the Alembic
Expand Down Expand Up @@ -1327,69 +1363,6 @@ _ReaderContext::ListTimeSamplesForPath(const SdfPath& path) const
return empty;
}

bool
_ReaderContext::_OpenHDF5(
const std::string& filePath,
IArchive* result,
std::string* format,
std::recursive_mutex** mutex) const
{
#ifdef PXR_HDF5_SUPPORT_ENABLED
// HDF5 may not be thread-safe.
std::lock_guard<std::recursive_mutex> lock(*_hdf5);

*format = "HDF5";
*result = IArchive(Alembic::AbcCoreHDF5::ReadArchive(),
filePath, ErrorHandler::kQuietNoopPolicy);
if (*result) {
// Single thread access to HDF5.
*mutex = &*_hdf5;
return true;
}
return false;
#else
return false;
#endif // PXR_HDF5_SUPPORT_ENABLED
}

bool
_ReaderContext::_OpenOgawa(
const std::string& filePath,
IArchive* result,
std::string* format,
std::recursive_mutex** mutex) const
{
*format = "Ogawa";
#if ALEMBIC_LIBRARY_VERSION >= 10709
*result = IArchive(
Alembic::AbcCoreOgawa::ReadArchive(
_GetNumOgawaStreams(),
TfGetEnvSetting(USD_ABC_READ_ARCHIVE_USE_MMAP)),
filePath, ErrorHandler::kQuietNoopPolicy);
#else
*result = IArchive(Alembic::AbcCoreOgawa::ReadArchive(_GetNumOgawaStreams()),
filePath, ErrorHandler::kQuietNoopPolicy);
#endif
return *result;
}

bool
_ReaderContext::_OpenGit(
const std::string& filePath,
IArchive* result,
std::string* format,
std::recursive_mutex** mutex) const
{
#ifdef PXR_MULTIVERSE_SUPPORT_ENABLED
*format = "Git";
*result = IArchive(Alembic::AbcCoreGit::ReadArchive(),
filePath, ErrorHandler::kQuietNoopPolicy);
return *result;
#else
return false;
#endif // PXR_MULTIVERSE_SUPPORT_ENABLED
}

void
_ReaderContext::_FindInstances(
const IObject& parent,
Expand Down Expand Up @@ -4057,13 +4030,14 @@ UsdAbc_AlembicDataReader::~UsdAbc_AlembicDataReader()
}

bool
UsdAbc_AlembicDataReader::Open(const std::string& filePath)
UsdAbc_AlembicDataReader::Open(const std::string& filePath,
const SdfFileFormat::FileFormatArguments* args)
{
TRACE_FUNCTION();

_errorLog.clear();
try {
if (_impl->Open(filePath, &_errorLog)) {
if (_impl->Open(filePath, &_errorLog, args)) {
return true;
}
}
Expand Down
3 changes: 2 additions & 1 deletion pxr/usd/plugin/usdAbc/alembicReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "pxr/pxr.h"
#include "pxr/usd/sdf/abstractData.h"
#include "pxr/usd/sdf/fileFormat.h"
#include "pxr/base/tf/token.h"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
Expand All @@ -54,7 +55,7 @@ class UsdAbc_AlembicDataReader : boost::noncopyable {

/// Open a file. Returns \c true on success; errors are reported by
/// \c GetErrors().
bool Open(const std::string& filePath);
bool Open(const std::string& filePath, const SdfFileFormat::FileFormatArguments*);

/// Close the file.
void Close();
Expand Down

0 comments on commit 5a795b2

Please sign in to comment.