void recursivelyReadChildren( IObject& parent ) { unsigned int numChildren = parent.getNumChildren(); std::cout << " has " << numChildren << " children" << std::endl; for (unsigned int ii=0; ii<numChildren; ii++) { IObject child = parent.getChild(ii); std::cout << " " << child.getName(); unsigned int expectedChildren = 2; if (child.getName().substr(6,1) == "2") // bottom of the hierarchy expectedChildren = 0; unsigned int children = child.getNumChildren(); ABCA_ASSERT( children == expectedChildren, "Expected " << expectedChildren << " children " << "but found " << children ); recursivelyReadChildren( child ); } return; }
//-***************************************************************************** void layerTest() { std::string fileName = "objectLayer1.abc"; std::string fileName2 = "objectLayer2.abc"; { OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName ); OObject child( archive.getTop(), "child" ); OObject childCool( child, "cool" ); OObject childGuy( child, "guy" ); OObject childA( archive.getTop(), "childA" ); OObject childAA( childA, "A" ); } { OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName2 ); OObject child( archive.getTop(), "child" ); OObject childCool( child, "cool" ); OObject childGal( child, "gal" ); OObject childA( archive.getTop(), "childB" ); OObject childAA( childA, "B" ); } { std::vector< std::string > files; files.push_back( fileName ); files.push_back( fileName2 ); Alembic::AbcCoreFactory::IFactory factory; IArchive archive = factory.getArchive( files ); // child, childA, childB TESTING_ASSERT( archive.getTop().getNumChildren() == 3 ); IObject child = archive.getTop().getChild("child"); TESTING_ASSERT( child.getNumChildren() == 3 ); TESTING_ASSERT( child.getChild("cool").valid() ); TESTING_ASSERT( child.getChild("cool").getNumChildren() == 0 ); TESTING_ASSERT( child.getChild("guy").valid() ); TESTING_ASSERT( child.getChild("guy").getNumChildren() == 0 ); TESTING_ASSERT( child.getChild("gal").valid() ); TESTING_ASSERT( child.getChild("gal").getNumChildren() == 0 ); IObject childA = archive.getTop().getChild("childA"); TESTING_ASSERT( childA.getNumChildren() == 1 ); TESTING_ASSERT( childA.getChild("A").valid() ); TESTING_ASSERT( childA.getChild("A").getNumChildren() == 0 ); IObject childB = archive.getTop().getChild("childB"); TESTING_ASSERT( childB.getNumChildren() == 1 ); TESTING_ASSERT( childB.getChild("B").valid() ); TESTING_ASSERT( childB.getChild("B").getNumChildren() == 0 ); } }
//-***************************************************************************** void pruneTest() { std::string fileName = "objectPrune1.abc"; std::string fileName2 = "objectPrune2.abc"; { OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName ); OObject child( archive.getTop(), "child" ); OObject childCool( child, "cool" ); OObject childGuy( child, "guy" ); OObject childA( archive.getTop(), "childA" ); OObject childAA( childA, "A" ); OObject childB( archive.getTop(), "childB" ); OObject childBB( childB, "B" ); } { MetaData md; Alembic::AbcCoreLayer::SetPrune( md, true ); OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName2 ); OObject child( archive.getTop(), "child" ); OObject childGuy( child, "guy", md ); OObject childA( archive.getTop(), "childA" ); OObject childAA( childA, "A", md ); OObject childAB( childA, "B", md ); OObject childB( archive.getTop(), "childB", md ); } { std::vector< std::string > files; files.push_back( fileName ); files.push_back( fileName2 ); Alembic::AbcCoreFactory::IFactory factory; IArchive archive = factory.getArchive( files ); // child, childA, childB TESTING_ASSERT( archive.getTop().getNumChildren() == 2 ); IObject child = archive.getTop().getChild("child"); TESTING_ASSERT( child.getNumChildren() == 1 ); TESTING_ASSERT( child.getChild("cool").valid() ); TESTING_ASSERT( child.getChild("cool").getNumChildren() == 0 ); IObject childA = archive.getTop().getChild("childA"); TESTING_ASSERT( childA.getNumChildren() == 0 ); } }
void readFlatHierarchy(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 10, "Expected 10 children, found " << numChildren ); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names for (int ii=0; ii<numChildren; ii++) { IObject child( archiveTop, archiveTop.getChildHeader(ii).getName() ); std::cout << " " << child.getName(); const unsigned int children = child.getNumChildren(); std::cout << " has " << children << " children" << std::endl; ABCA_ASSERT( children == 0, "Expected no children, found " << children ); } // Done - the archive closes itself }
void readDeepHierarchy(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const unsigned int numChildren = archiveTop.getNumChildren(); std::cout << "The archive has " << numChildren << " children:" << std::endl; ABCA_ASSERT( numChildren == 2, "Expected 2 children, found " << numChildren ); // Iterate through them, print out their names for (unsigned int ii=0; ii<numChildren; ii++) { IObject child( archiveTop, archiveTop.getChildHeader(ii).getName() ); std::cout << " " << child.getName(); recursivelyReadChildren( child ); } // do it again to make sure we clean up after ourselves properly IArchive archive2 = factory.getArchive(archiveName, coreType); IObject archiveTop2 = archive2.getTop(); // Done - the archive closes itself }
void readEmptyCompoundProperties(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 2, "Wrong number of children (expected 2)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names for (int ii=0; ii<numChildren; ii++) { IObject child( archiveTop, archiveTop.getChildHeader(ii).getName() ); std::cout << " " << child.getName(); std::cout << " has " << child.getNumChildren() << " children" << std::endl; // Properties ICompoundProperty props = child.getProperties(); int numProperties = props.getNumProperties(); std::cout << " ..and " << numProperties << " properties" << std::endl; std::vector<std::string> propNames; for (int pp=0; pp<numProperties; pp++) propNames.push_back( props.getPropertyHeader(pp).getName() ); for (int jj=0; jj<numProperties; jj++) { std::cout << " ..named " << propNames[jj] << std::endl; std::cout << " ..with type: "; PropertyType pType = props.getPropertyHeader(jj).getPropertyType(); if (pType == kCompoundProperty) { std::cout << "compound" << std::endl; } else if (pType == kScalarProperty) { std::cout << "scalar" << std::endl; } else if (pType == kArrayProperty) { std::cout << "array" << std::endl; } } } // Done - the archive closes itself }
void getObjectTimeSpan(IObject obj, chrono_t& first, chrono_t& last, bool doChildren) { if ( Alembic::AbcGeom::IPolyMesh::matches(obj.getHeader()) ) { IPolyMesh iPoly(obj, Alembic::Abc::kWrapExisting); getPolyMeshTimeSpan(iPoly, first, last); } else if ( Alembic::AbcGeom::ISubD::matches(obj.getHeader()) ) { ISubD iSub(obj, Alembic::Abc::kWrapExisting); getSubDTimeSpan(iSub, first, last); } else if ( Alembic::AbcGeom::IXform::matches(obj.getHeader()) ) { IXform iXf(obj, Alembic::Abc::kWrapExisting); getXformTimeSpan(iXf, first, last, false); } else if ( Alembic::AbcGeom::ICamera::matches(obj.getHeader()) ) { ICamera iCam(obj, Alembic::Abc::kWrapExisting); getCameraTimeSpan(iCam, first, last); } if (doChildren) { // do this object's children too for (unsigned i=0; i < obj.getNumChildren(); ++i) { IObject child( obj.getChild( i )); getObjectTimeSpan(child, first, last, doChildren); } } }
//-***************************************************************************** void getABCTimeSpan(IArchive archive, chrono_t& first, chrono_t& last) { // TO DO: Is the childBounds property reliable to get the full archive's span? if (!archive.valid()) return; IObject archiveTop = archive.getTop(); if ( archiveTop.getProperties().getPropertyHeader( ".childBnds" ) != NULL ) { // Try to get timing from childBounds first IBox3dProperty childbnds = Alembic::Abc::IBox3dProperty( archive.getTop().getProperties(), ".childBnds", ErrorHandler::kQuietNoopPolicy); TimeSamplingPtr ts = childbnds.getTimeSampling(); first = std::min(first, ts->getSampleTime(0) ); last = std::max(last, ts->getSampleTime(childbnds.getNumSamples()-1) ); return; } unsigned int numChildren = archiveTop.getNumChildren(); for (unsigned i=0; i<numChildren; ++i) // Visit every object to get its first and last sample { IObject obj( archiveTop.getChild( i )); getObjectTimeSpan(obj, first, last, true); } }
void scopingTest(bool useOgawa) { { OObject top; { OArchive archive; if (useOgawa) { archive = CreateArchiveWithInfo( Alembic::AbcCoreOgawa::WriteArchive(), "archiveScopeTest.abc", "Alembic test", "", MetaData() ); } else { archive = CreateArchiveWithInfo( Alembic::AbcCoreHDF5::WriteArchive(), "archiveScopeTest.abc", "Alembic test", "", MetaData() ); } top = archive.getTop(); } OObject childA( top, "a"); OObject childB( top, "b"); ODoubleProperty prop(top.getProperties(), "prop", 0); TESTING_ASSERT(prop.getObject().getArchive().getName() == "archiveScopeTest.abc"); } { IObject top; { AbcF::IFactory factory; AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive("archiveScopeTest.abc", coreType); TESTING_ASSERT( (useOgawa && coreType == AbcF::IFactory::kOgawa) || (!useOgawa && coreType == AbcF::IFactory::kHDF5) ); top = archive.getTop(); double start, end; GetArchiveStartAndEndTime( archive, start, end ); TESTING_ASSERT( start == DBL_MAX && end == -DBL_MAX ); } TESTING_ASSERT(top.getNumChildren() == 2 ); TESTING_ASSERT(top.getChildHeader("a") != NULL); TESTING_ASSERT(top.getChildHeader("b") != NULL); TESTING_ASSERT( ! top.getParent().valid() ); TESTING_ASSERT( top.getArchive().getName() == "archiveScopeTest.abc"); IScalarProperty prop(top.getProperties(), "prop"); TESTING_ASSERT(prop.valid()); TESTING_ASSERT(prop.getObject().getArchive().getName() == "archiveScopeTest.abc"); } }
//-***************************************************************************** void visitObject( IObject iObj ) { std::string path = iObj.getFullName(); const MetaData &md = iObj.getMetaData(); if ( IPolyMeshSchema::matches( md ) || ISubDSchema::matches( md ) ) { Box3d bnds = getBounds( iObj ); std::cout << path << " " << bnds.min << " " << bnds.max << std::endl; } // now the child objects for ( size_t i = 0 ; i < iObj.getNumChildren() ; i++ ) { visitObject( IObject( iObj, iObj.getChildHeader( i ).getName() ) ); } }
//-***************************************************************************** void simpleTestIn( const std::string &iArchiveName ) { IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), iArchiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); TESTING_ASSERT( archiveTop.getNumChildren() == NUM_TOP_CHILDREN ); for ( int i = 0 ; i < NUM_TOP_CHILDREN ; i++ ) { std::string cname = boost::lexical_cast<std::string>( i ); IObject obj( archiveTop, cname ); readDeepHierarchy( obj, 0, obj ); } TESTING_ASSERT( PATHS.size() == NUM_TOP_CHILDREN ); }
//-***************************************************************************** void getABCTimeSpan(IArchive archive, chrono_t& first, chrono_t& last) { // TO DO: Is the childBounds property reliable to get the full archive's span? if (!archive.valid()) return; IObject archiveTop = archive.getTop(); unsigned int numChildren = archiveTop.getNumChildren(); for (unsigned i=0; i<numChildren; ++i) { IObject obj( archiveTop.getChild( i )); getObjectTimeSpan(obj, first, last, true); } }
bool getNamedCamera( IObject iObjTop, const std::string &iName, ICamera &iCam ) { // Return true if found const Alembic::AbcGeom::MetaData &md = iObjTop.getMetaData(); if ( (iObjTop.getName() == iName) && (ICamera::matches( md )) ) { iCam = ICamera(iObjTop, kWrapExisting ); return true; } // now the child objects for ( size_t i = 0 ; i < iObjTop.getNumChildren() ; i++ ) { if (getNamedCamera(IObject( iObjTop, iObjTop.getChildHeader( i ).getName() ), iName, iCam )) return true; } return false; }
//-***************************************************************************** void simpleTestIn( const std::string &iArchiveName ) { AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(iArchiveName, coreType); IObject archiveTop = archive.getTop(); TESTING_ASSERT( archiveTop.getNumChildren() == ( size_t )NUM_TOP_CHILDREN ); for ( int i = 0 ; i < NUM_TOP_CHILDREN ; i++ ) { std::ostringstream strm; strm << i; std::string cname = strm.str(); IObject obj( archiveTop, cname ); readDeepHierarchy( obj, 0, obj ); } TESTING_ASSERT( PATHS.size() == ( size_t ) NUM_TOP_CHILDREN ); }
//-***************************************************************************** void visitObject( IObject iObj, std::string iIndent ) { // Object has a name, a full name, some meta data, // and then it has a compound property full of properties. std::string path = iObj.getFullName(); if ( path != "/" ) { std::cout << "Object " << "name=" << path << std::endl; } // Get the properties. ICompoundProperty props = iObj.getProperties(); visitProperties( props, iIndent ); // now the child objects for ( size_t i = 0 ; i < iObj.getNumChildren() ; i++ ) { visitObject( IObject( iObj, iObj.getChildHeader( i ).getName() ), iIndent ); } }
void readUInt32ArrayProperty(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. std::cout << "Reading " << archiveName << std::endl; IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const unsigned int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 1, "Wrong number of children (expected 1)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); std::cout << " named '" << child.getName() << "'"; // Properties ICompoundProperty props = child.getProperties(); size_t numProperties = props.getNumProperties(); // only top-level props ABCA_ASSERT( numProperties == 1, "Expected 1 property, found " << numProperties); std::cout << " with one property"; std::vector<std::string> propNames(1); propNames[0] = props.getPropertyHeader(0).getName(); std::cout << " named '" << propNames[0] << "'" << std::endl; PropertyType pType = props.getPropertyHeader(0).getPropertyType(); ABCA_ASSERT( pType == kArrayProperty, "Expected an array property, but didn't find one" ); std::cout << " which is an array property"; DataType dType = props.getPropertyHeader(0).getDataType(); ABCA_ASSERT( dType.getPod() == kUint32POD, "Expected an unsigned int (kUint32POD) property, but didn't" " find one" ); // We know this is an array property (I'm eliding the if/else // statements required to recognize and handle this properly) IUInt32ArrayProperty primes( props, propNames[0] ); size_t numSamples = primes.getNumSamples(); std::cout << ".. it has " << numSamples << " samples" << std::endl; ABCA_ASSERT( numSamples == 5, "Expected 5 samples, found " << numSamples ); const TimeSampling ts = primes.getTimeSampling(); std::cout << "..with time/value pairs: " << std::endl;; for (int ss=0; ss<numSamples; ss++) { std::cout << " "; ISampleSelector iss( (index_t) ss); std::cout << ts.getSampleTime( (index_t) ss ) << " / "; UInt32ArraySamplePtr samplePtr; primes.get( samplePtr, iss ); std::cout << "[ "; size_t numPoints = samplePtr->size(); for ( size_t jj=0 ; jj<numPoints ; jj++ ) std::cout << (*samplePtr)[jj] << " "; std::cout << "]" << std::endl; // ASSERT that we are reading the correct values for ( size_t jj=0 ; jj<numPoints ; jj++ ) ABCA_ASSERT( (*samplePtr)[jj] == g_primes[jj], "Incorrect value read from archive." ); } std::cout << std::endl; // Done - the archive closes itself }
//-***************************************************************************** void replaceTest() { std::string fileName = "objectReplace1.abc"; std::string fileName2 = "objectReplace2.abc"; { OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName ); OObject child( archive.getTop(), "child" ); OObject childCool( child, "cool" ); OObject childCooler( childCool, "cooler" ); OObject childGuy( child, "guy" ); OObject childGuyA( childGuy, "A" ); OObject childA( archive.getTop(), "childA" ); OObject childAA( childA, "A" ); OObject childB( archive.getTop(), "childB" ); OObject childBB( childB, "B" ); } { MetaData md; Alembic::AbcCoreLayer::SetReplace( md, true ); OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), fileName2 ); OObject child( archive.getTop(), "child" ); OObject childGuy( child, "guy", md ); OObject childCool( child, "cool", md ); OObject childCoolA( childCool, "A" ); OObject childCoolB( childCool, "B", md ); OObject childA( archive.getTop(), "childA", md ); OObject childB( archive.getTop(), "childB", md ); OObject childBA( childB, "A", md ); OObject childBC( childB, "C", md ); OObject childBCA( childBC, "A", md ); } { std::vector< std::string > files; files.push_back( fileName ); files.push_back( fileName2 ); Alembic::AbcCoreFactory::IFactory factory; IArchive archive = factory.getArchive( files ); IObject root = archive.getTop(); // child, childA, childB TESTING_ASSERT( root.getNumChildren() == 3 ); IObject child( root, "child" ); TESTING_ASSERT( child.getNumChildren() == 2 ); TESTING_ASSERT( IObject( child, "cool" ).valid() ); TESTING_ASSERT( IObject( child, "guy" ).valid() ); TESTING_ASSERT( IObject( child, "cool" ).getNumChildren() == 2 ); TESTING_ASSERT( IObject( child, "guy" ).getNumChildren() == 0 ); IObject childCool( child, "cool" ); TESTING_ASSERT( IObject( childCool, "A" ).valid() ); TESTING_ASSERT( IObject( childCool, "A" ).getNumChildren() == 0 ); TESTING_ASSERT( IObject( childCool, "B" ).valid() ); TESTING_ASSERT( IObject( childCool, "B" ).getNumChildren() == 0 ); IObject childA( root, "childA" ); TESTING_ASSERT( childA.getNumChildren() == 0 ); IObject childB( root, "childB" ); TESTING_ASSERT( childB.getNumChildren() == 2 ); TESTING_ASSERT( IObject( childB, "A" ).valid() ); TESTING_ASSERT( IObject( childB, "C" ).valid() ); TESTING_ASSERT( IObject( childB, "A" ).getNumChildren() == 0 ); TESTING_ASSERT( IObject( childB, "C" ).getNumChildren() == 1 ); IObject childBC( childB, "C" ); TESTING_ASSERT( IObject( childBC, "A" ).valid() ); TESTING_ASSERT( IObject( childBC, "A" ).getNumChildren() == 0 ); } }
void readSimpleProperties(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const int numChildren = archiveTop.getNumChildren(); TESTING_ASSERT( numChildren == 4 ); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names for (int ii=0; ii<numChildren; ii++) { IObject child( archiveTop, archiveTop.getChildHeader( ii ).getName() ); std::cout << " " << child.getName(); std::cout << " has " << child.getNumChildren() << " children" << std::endl; // Properties ICompoundProperty props = child.getProperties(); int numProperties = props.getNumProperties(); std::cout << " ..and " << numProperties << " simple properties" << std::endl; std::vector<std::string> propNames; for (int pp=0; pp<numProperties; pp++) propNames.push_back( props.getPropertyHeader(pp).getName() ); for (int jj=0; jj<numProperties; jj++) { std::cout << " ..named " << propNames[jj] << std::endl; std::cout << " ..with type: "; PropertyType pType = props.getPropertyHeader(jj).getPropertyType(); if (pType == kCompoundProperty) { std::cout << "compound" << std::endl; } else if (pType == kScalarProperty) { std::cout << "scalar" << std::endl; } else if (pType == kArrayProperty) { std::cout << "array" << std::endl; } DataType dType = props.getPropertyHeader(jj).getDataType(); std::cout << " ..with POD-type: "; switch (dType.getPod()) { case kBooleanPOD: std::cout << "boolean" << std::endl; break; // Char/UChar case kUint8POD: std::cout << "unsigned char" << std::endl; break; case kInt8POD: std::cout << "char" << std::endl; break; // Short/UShort case kUint16POD: std::cout << "short unsigned int" << std::endl; break; case kInt16POD: std::cout << "short int" << std::endl; break; // Int/UInt case kUint32POD: std::cout << "unsigned int" << std::endl; break; case kInt32POD: std::cout << "int" << std::endl; break; // Long/ULong case kUint64POD: std::cout << "unsigned long int" << std::endl; break; case kInt64POD: std::cout << "long int" << std::endl; break; // Half/Float/Double case kFloat16POD: std::cout << "half" << std::endl; break; case kFloat32POD: std::cout << "float" << std::endl; break; case kFloat64POD: std::cout << "double" << std::endl; break; case kStringPOD: std::cout << "string" << std::endl; break; case kUnknownPOD: default: std::cout << " Unknown! (this is bad)" << std::endl; }; TimeSamplingPtr ts = GetCompoundPropertyReaderPtr(props)-> getScalarProperty( propNames[jj] )->getTimeSampling(); int numSamples = ts->getNumStoredTimes(); std::cout << " ..and " << ts->getTimeSamplingType() << std::endl << " ..and " << numSamples << " samples at times: "; if (numSamples > 0) { std::cout << " ( "; for (int ss=0; ss<numSamples; ss++) std::cout << ts->getSampleTime(ss) << " "; std::cout << ")"; } std::cout << std::endl; std::cout << " ..and values: "; if (numSamples > 0) { for (int ss=0; ss<numSamples; ss++) { ISampleSelector iss( (index_t) ss); switch (dType.getPod()) { // Boolean case kBooleanPOD: { IBoolProperty prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } // Char/UChar case kUint8POD: { IUcharProperty prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kInt8POD: { ICharProperty prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } // Short/UShort case kUint16POD: { IUInt16Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kInt16POD: { IInt16Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } // Int/UInt case kUint32POD: { IUInt32Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kInt32POD: { IInt32Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } // Long/ULong case kUint64POD: { IUInt64Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kInt64POD: { IInt64Property prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } // Half/Float/Double case kFloat16POD: // iostream doesn't understand float_16's //printSampleValue( IHalfProperty( props, propNames[jj] ), // iss ); break; case kFloat32POD: { IFloatProperty prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kFloat64POD: { IDoubleProperty prop( props, propNames[jj] ); printSampleValue( prop, iss ); break; } case kUnknownPOD: default: std::cout << " Unknown! (this is bad)" << std::endl; }; } } std::cout << std::endl; std::cout << std::endl; // done parsing property } } // Done - the archive closes itself }
void readV3fArrayProperty(const std::string &archiveName, bool useOgawa) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. std::cout << "Reading " << archiveName << std::endl; AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); TESTING_ASSERT( (useOgawa && coreType == AbcF::IFactory::kOgawa) || (!useOgawa && coreType == AbcF::IFactory::kHDF5) ); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const unsigned int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 1, "Wrong number of children (expected 1)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); std::cout << " named '" << child.getName() << "'"; // Properties ICompoundProperty props = child.getProperties(); size_t numProperties = props.getNumProperties(); // only top-level props ABCA_ASSERT( numProperties == 1, "Expected 1 property, found " << numProperties); std::cout << " with one property"; std::vector<std::string> propNames(1); propNames[0] = props.getPropertyHeader(0).getName(); std::cout << " named '" << propNames[0] << "'" << std::endl; PropertyType pType = props.getPropertyHeader(0).getPropertyType(); ABCA_ASSERT( pType == kArrayProperty, "Expected an array property, but didn't find one" ); std::cout << " which is an array property"; DataType dType = props.getPropertyHeader(0).getDataType(); ABCA_ASSERT( dType.getPod() == kFloat32POD, "Expected an v3f property, but didn't find one" ); // We know this is an array property (I'm eliding the if/else // statements required to recognize and handle this properly) IV3fArrayProperty positions( props, propNames[0] ); size_t numSamples = positions.getNumSamples(); std::cout << ".. it has " << numSamples << " samples" << std::endl; ABCA_ASSERT( numSamples == 5, "Expected 5 samples, found " << numSamples ); TimeSamplingPtr ts = positions.getTimeSampling(); std::cout << "..with time/value pairs: " << std::endl;; for (unsigned int ss=0; ss<numSamples; ss++) { std::cout << " "; ISampleSelector iss( (index_t) ss); std::cout << ts->getSampleTime( (index_t) ss ) << " / "; V3fArraySamplePtr samplePtr; positions.get( samplePtr, iss ); std::cout << "[ "; size_t numPoints = samplePtr->size(); for ( size_t jj=0 ; jj<numPoints ; jj++ ) std::cout << (*samplePtr)[jj] << " "; std::cout << "]" << std::endl; if (ss == 2) // no entries in sample #2 { ABCA_ASSERT( numPoints == 0, "Expected an empty sample, but found " << numPoints << " entries." ); } else { for ( size_t jj=0 ; jj<numPoints ; jj++ ) ABCA_ASSERT( (*samplePtr)[jj] == g_vectors[jj], "Incorrect value read from archive." ); } } ABCA_ASSERT( archive.getMaxNumSamplesForTimeSamplingIndex(1) == (index_t) numSamples, "Incorrect number of max samples in readV3fArrayProperty." ); std::cout << std::endl; // Done - the archive closes itself double start, end; GetArchiveStartAndEndTime( archive, start, end ); TESTING_ASSERT( almostEqual(start, 123.0) ); TESTING_ASSERT( almostEqual(end, 123.0 + 4.0 / 24.0) ); }
void IGeom::setupWithObject(IObject object) { size_t numChildren = object.getNumChildren(); for (size_t i = 0; i < numChildren; ++i) { const ObjectHeader &ohead = object.getChildHeader(i); ofPtr<IGeom> dptr; if (Alembic::AbcGeom::IPolyMesh::matches(ohead)) { Alembic::AbcGeom::IPolyMesh pmesh(object, ohead.getName()); if (pmesh) { dptr.reset(new ofxAlembic::IPolyMesh(pmesh)); } } else if (Alembic::AbcGeom::IPoints::matches(ohead)) { Alembic::AbcGeom::IPoints points(object, ohead.getName()); if (points) { dptr.reset(new ofxAlembic::IPoints(points)); } } else if (Alembic::AbcGeom::ICurves::matches(ohead)) { Alembic::AbcGeom::ICurves curves(object, ohead.getName()); if (curves) { dptr.reset(new ofxAlembic::ICurves(curves)); } } else if (Alembic::AbcGeom::INuPatch::matches(ohead)) { ofLogError("ofxAlembic") << "INuPatch not implemented"; assert(false); // Alembic::AbcGeom::INuPatch nuPatch(object, ohead.getName()); // if ( nuPatch ) // { // dptr.reset( new INuPatchDrw( nuPatch ) ); // } } else if (Alembic::AbcGeom::IXform::matches(ohead)) { Alembic::AbcGeom::IXform xform(object, ohead.getName()); if (xform) { dptr.reset(new ofxAlembic::IXform(xform)); } } else if (Alembic::AbcGeom::ISubD::matches(ohead)) { ofLogError("ofxAlembic") << "ISubD not implemented"; assert(false); // Alembic::AbcGeom::ISubD subd(object, ohead.getName()); // if ( subd ) // { // dptr.reset( new ISubDDrw( subd ) ); // } } else if (Alembic::AbcGeom::ICamera::matches(ohead)) { Alembic::AbcGeom::ICamera camera(object, ohead.getName()); if (camera) { dptr.reset(new ofxAlembic::ICamera(camera)); } } else { ofLogError("ofxAlembic") << "unknown object type: " << ohead.getFullName(); } if (dptr && dptr->valid()) { dptr->index = m_children.size(); m_children.push_back(dptr); m_minTime = std::min(m_minTime, dptr->m_minTime); m_maxTime = std::max(m_maxTime, dptr->m_maxTime); } } }
void readProperty(const std::string &archiveName, bool useOgawa) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. std::cout << "Reading " << archiveName << std::endl; AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive(archiveName, coreType); ABCA_ASSERT( (useOgawa && coreType == AbcF::IFactory::kOgawa) || (!useOgawa && coreType == AbcF::IFactory::kHDF5), "File did not open as the expected type." ); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const unsigned int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 1, "Wrong number of children (expected 1)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names IObject child( archiveTop, archiveTop.getChildHeader( 0 ).getName() ); std::cout << " " << child.getName(); // Properties ICompoundProperty props = child.getProperties(); size_t numProperties = props.getNumProperties(); // only top-level props ABCA_ASSERT( numProperties == 1, "Expected 1 property, found " << numProperties); std::cout << " with one property"; std::vector<std::string> propNames(1); propNames[0] = props.getPropertyHeader(0).getName(); std::cout << " named " << propNames[0] << std::endl; PropertyType pType = props.getPropertyHeader(0).getPropertyType(); ABCA_ASSERT( pType == kScalarProperty, "Expected a scalar property, but didn't find one" ); std::cout << " which is a scalar property"; DataType dType = props.getPropertyHeader(0).getDataType(); ABCA_ASSERT( dType.getPod() == kFloat64POD, "Expected a double (kFloat64POD) property, but didn't" " find one" ); // We know this is a scalar property (I'm eliding the if/else // statements required to recognize this) IDoubleProperty mass( props, propNames[0] ); size_t numSamples = mass.getNumSamples(); std::cout << ".. it has " << numSamples << " samples" << std::endl; //ABCA_ASSERT( numSamples == 5, "Expected 5 samples, found " << numSamples ); TimeSamplingPtr ts = mass.getTimeSampling(); std::cout << "..with time/value pairs: "; for (unsigned int ss=0; ss<numSamples; ss++) { ISampleSelector iss( (index_t) ss); std::cout << ts->getSampleTime( (index_t) ss ) << "/"; printSampleValue( mass, iss ); std::cout << " "; double timeDiff = ts->getSampleTime( (index_t) ss ) - (g_startTime + (ss*(g_dt/3.0))); ABCA_ASSERT( fabs(timeDiff) < 1e-12, "Incorrect sample time read" ); double massDiff = mass.getValue( iss ) - (1.0 + 0.1*ss); ABCA_ASSERT( fabs(massDiff) < 1e-12, "Incorrect sample value read" ); } ABCA_ASSERT( archive.getMaxNumSamplesForTimeSamplingIndex(1) == (index_t) numSamples, "Incorrect number of max samples for Time Sampling ID 1."); std::cout << std::endl; // Done - the archive closes itself }
//-***************************************************************************** //-***************************************************************************** // DO IT. //-***************************************************************************** //-***************************************************************************** int main( int argc, char *argv[] ) { if (argc < 4) { std::cerr << "USAGE: " << argv[0] << " outFile.abc inFile1.abc" << " inFile2.abc (inFile3.abc ...)" << std::endl; return -1; } { size_t numInputs = argc - 2; std::vector< chrono_t > minVec; minVec.reserve(numInputs); std::vector< IArchive > iArchives; iArchives.reserve(numInputs); std::map< chrono_t, size_t > minIndexMap; size_t rootChildren = 0; Alembic::AbcCoreFactory::IFactory factory; factory.setPolicy(ErrorHandler::kThrowPolicy); Alembic::AbcCoreFactory::IFactory::CoreType coreType; for (int i = 2; i < argc; ++i) { IArchive archive = factory.getArchive(argv[i], coreType); if (!archive.valid() || archive.getTop().getNumChildren() < 1) { std::cerr << "ERROR: " << argv[i] << " not a valid Alembic file" << std::endl; return 1; } IObject iRoot = archive.getTop(); size_t numChildren = iRoot.getNumChildren(); if (i == 2) { rootChildren = numChildren; } else if (rootChildren != numChildren) { std::cerr << "ERROR: " << argv[i] << " doesn't have the same number of children as: " << argv[i-1] << std::endl; } // reorder the input files according to their mins chrono_t min = DBL_MAX; Alembic::Util::uint32_t numSamplings = archive.getNumTimeSamplings(); if (numSamplings > 1) { // timesampling index 0 is special, so it will be skipped // // make sure all the other timesampling objects start at // the same time or throw here // min = archive.getTimeSampling(1)->getSampleTime(0); for (Alembic::Util::uint32_t s = 2; s < numSamplings; ++s) { chrono_t thisMin = archive.getTimeSampling(s)->getSampleTime(0); if (fabs(thisMin - min) > 1e-5) { std::cerr << "ERROR: " << argv[i] << " has non-default TimeSampling objects" << " that don't start at the same time." << std::endl; return 1; } } minVec.push_back(min); if (minIndexMap.count(min) == 0) { minIndexMap.insert(std::make_pair(min, i-2)); } else if (argv[2] != argv[i]) { std::cerr << "ERROR: overlapping frame range between " << argv[2] << " and " << argv[i] << std::endl; return 1; } } else { std::cerr << "ERROR: " << archive.getName() << " only has default (static) TimeSampling." << std::endl; return 1; } iArchives.push_back(archive); } // now reorder the input nodes so they are in increasing order of their // min values in the frame range std::sort(minVec.begin(), minVec.end()); std::vector< IArchive > iOrderedArchives; iOrderedArchives.reserve(numInputs); for (size_t f = 0; f < numInputs; ++f) { size_t index = minIndexMap.find(minVec[f])->second; iOrderedArchives.push_back(iArchives[index]); } std::string appWriter = "AbcStitcher"; std::string fileName = argv[1]; std::string userStr; // Create an archive with the default writer OArchive oArchive; if (coreType == Alembic::AbcCoreFactory::IFactory::kHDF5) { oArchive = CreateArchiveWithInfo( Alembic::AbcCoreHDF5::WriteArchive(), fileName, appWriter, userStr, ErrorHandler::kThrowPolicy); } else if (coreType == Alembic::AbcCoreFactory::IFactory::kOgawa) { oArchive = CreateArchiveWithInfo( Alembic::AbcCoreOgawa::WriteArchive(), fileName, appWriter, userStr, ErrorHandler::kThrowPolicy); } OObject oRoot = oArchive.getTop(); if (!oRoot.valid()) return -1; std::vector<IObject> iRoots; iRoots.resize(numInputs); for (size_t f = 0; f < rootChildren; ++f) { for (size_t g = 0; g < numInputs; ++g) { iRoots[g] = iOrderedArchives[g].getTop().getChild(f); } visitObjects(iRoots, oRoot); } // collect the top level compound property ICompoundPropertyVec iCompoundProps; iCompoundProps.reserve(numInputs); for (size_t f = 0; f < numInputs; ++f) { iCompoundProps.push_back(iRoots[f].getParent().getProperties()); } OCompoundProperty oCompoundProperty = oRoot.getProperties(); stitchCompoundProp(iCompoundProps, oCompoundProperty); } return 0; }
void readProperty(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. std::cout << "Reading " << archiveName << std::endl; IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); // Determine the number of (top level) children the archive has const unsigned int numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 1, "Wrong number of children (expected 3)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; // Iterate through them, print out their names IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); std::cout << " " << child.getName(); // Properties ICompoundProperty props = child.getProperties(); size_t numProperties = props.getNumProperties(); // only top-level props ABCA_ASSERT( numProperties == 1, "Expected 1 property, found " << numProperties); std::cout << " has a simple property"; std::vector<std::string> propNames(1); propNames[0] = props.getPropertyHeader(0).getName(); std::cout << " named " << propNames[0] << std::endl; PropertyType pType = props.getPropertyHeader(0).getPropertyType(); ABCA_ASSERT( pType == kScalarProperty, "Expected a scalar property, but didn't find one" ); DataType dType = props.getPropertyHeader(0).getDataType(); ABCA_ASSERT( dType.getPod() == kFloat64POD, "Expected a double (kFloat64POD) property, but didn't" " find one" ); // We know this is a scalar property (I'm eliding the if/else // statements required to recognize this) IDoubleProperty mass( props, propNames[0] ); size_t numSamples = mass.getNumSamples(); std::cout << ".. it has " << numSamples << " samples" << std::endl; ABCA_ASSERT( numSamples == 5, "Expected 5 samples, found " << numSamples ); std::cout << "..with values: "; for (int ss=0; ss<numSamples; ss++) { ISampleSelector iss( (index_t) ss); printSampleValue( mass, iss ); double massDiff = mass.getValue( iss ) - (33.0 + 0.1*ss); ABCA_ASSERT( fabs(massDiff) < 1e-12, "Incorrect sample value read" ); } std::cout << std::endl; // Done - the archive closes itself }
void readNestedCommpoundWithVis(const std::string &archiveName) { // Open an existing archive for reading. Indicate that we want // Alembic to throw exceptions on errors. IArchive archive( Alembic::AbcCoreOgawa::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); TESTING_ASSERT_THROW( GetIArchiveBounds( archive ), Alembic::Util::Exception ); IBox3dProperty boxProp = GetIArchiveBounds( archive, ErrorHandler::kQuietNoopPolicy ); TESTING_ASSERT( !boxProp.valid() ); ICharProperty topVisibility = GetVisibilityProperty (archiveTop); std::cout << "Does this object have VisibilityProperty? " << (bool) (true == topVisibility) << std::endl; ABCA_ASSERT( topVisibility == false, "top object should not have a visibility property"); // Determine the number of (top level) children the archive has const size_t numChildren = archiveTop.getNumChildren(); ABCA_ASSERT( numChildren == 2, "Wrong number of children (expected 2)"); std::cout << "The archive has " << numChildren << " children:" << std::endl; IObject child1; IObject otherChild; // Iterate through them, print out their names for ( size_t ii=0; ii <numChildren; ii++) { IObject child( archiveTop, archiveTop.getChildHeader(ii).getName() ); std::cout << " " << child.getName(); std::cout << " has " << child.getNumChildren() << " children" << std::endl; // Properties ICompoundProperty props = child.getProperties(); size_t numProperties = props.getNumProperties(); std::cout << " ..and " << numProperties << " properties" << std::endl; std::vector<std::string> propNames; for ( size_t pp=0 ; pp < numProperties ; ++pp ) { propNames.push_back( props.getPropertyHeader(pp).getName() ); } for ( size_t jj=0; jj<numProperties; ++jj) { std::cout << " ..named " << propNames[jj] << std::endl; std::cout << " ..with type: "; PropertyType pType = props.getPropertyHeader(jj).getPropertyType(); if (pType == kCompoundProperty) { std::cout << "compound" << std::endl; ICompoundProperty prop( props, propNames[jj] ); std::cout << " Accessing this nested prop for its obj -" << prop.getObject ().getName () << std::endl; } else if (pType == kScalarProperty) { std::cout << "scalar" << std::endl; } else if (pType == kArrayProperty) { std::cout << "array" << std::endl; } } ICharProperty childVisibility; childVisibility = GetVisibilityProperty (child); if (ii == 1) { child1 = child; // This is child_1. It should have visibility property // and it should be set to hidden ABCA_ASSERT( childVisibility == true, "child_1 should have a visibility property"); ABCA_ASSERT( childVisibility.getValue () == kVisibilityHidden, "child_1 visibility should be hidden"); ABCA_ASSERT( childVisibility.getValue () == GetVisibility (child), "child_1 visibility should match call value from GetVisibility ()"); std::cout << " child_1 visibility correctly set to hidden" << std::endl; } else { otherChild = child; ABCA_ASSERT( childVisibility == false, "child object should not have a visibility property"); } } // Test that IsAncestorInvisible () works // // child of child1 (which is hidden) means that this child should be // hidden too IObject child1SubObject( child1, "nested_object"); ABCA_ASSERT( IsAncestorInvisible (archiveTop) == false, "top root should be visible"); ABCA_ASSERT( IsAncestorInvisible (child1SubObject) == true, "object under child1 should eval to being not visible"); ABCA_ASSERT( IsAncestorInvisible (child1) == true, "child1 should eval to being not visible"); ABCA_ASSERT( IsAncestorInvisible (otherChild) == false, "other object should eval to being visible"); // Done - the archive closes itself }
void readWriteColorArrayProperty(const std::string &archiveName) { { OArchive archive( Alembic::AbcCoreHDF5::WriteArchive(), archiveName, ErrorHandler::kThrowPolicy ); OObject archiveTop = archive.getTop(); OObject child( archiveTop, "test" ); OCompoundProperty childProps = child.getProperties(); OC3fArrayProperty shades( childProps, "shades", TimeSamplingType( 1.0 ) ); std::vector < C3f > grays(8); grays[0].x = 0.0; grays[0].y = 0.0; grays[0].z = 0.0; grays[1].x = 0.125; grays[1].y = 0.125; grays[1].z = 0.125; grays[2].x = 0.25; grays[2].y = 0.25; grays[2].z = 0.25; grays[3].x = 0.375; grays[3].y = 0.375; grays[3].z = 0.375; grays[4].x = 0.5; grays[4].y = 0.5; grays[4].z = 0.5; grays[5].x = 0.625; grays[5].y = 0.625; grays[5].z = 0.625; grays[6].x = 0.75; grays[6].y = 0.75; grays[6].z = 0.75; grays[7].x = 0.875; grays[7].y = 0.875; grays[7].z = 0.875; // let's write 4 different color3f[2] Dimensions d; d.setRank(2); d[0] = 2; d[1] = 4; C3fArraySample cas(&(grays.front()), d); shades.set(cas); } { // now read it IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), archiveName, ErrorHandler::kThrowPolicy ); IObject archiveTop = archive.getTop(); const unsigned int numChildren = archiveTop.getNumChildren(); IObject child( archiveTop, archiveTop.getChildHeader(0).getName() ); ICompoundProperty props = child.getProperties(); IC3fArrayProperty shades( props, "shades" ); C3fArraySamplePtr samplePtr; shades.get( samplePtr ); ABCA_ASSERT( samplePtr->getDimensions().rank() == 2, "Incorrect rank on the sample." ); ABCA_ASSERT( samplePtr->getDimensions().numPoints() == 8, "Incorrect number of total points." ); ABCA_ASSERT( samplePtr->getDimensions()[0] == 2, "Incorrect size on dimension 0." ); ABCA_ASSERT( samplePtr->getDimensions()[1] == 4, "Incorrect size on dimension 1." ); for (size_t i = 0; i < 8; ++i) { ABCA_ASSERT( (*samplePtr)[i].x == i/8.0 && (*samplePtr)[i].x == (*samplePtr)[i].y && (*samplePtr)[i].x == (*samplePtr)[i].z, "Color [" << i << "] is incorrect."); } } }