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"); } }
OVisibilityProperty CreateVisibilityProperty( OObject & iObject, uint32_t iTimeSamplingID) { // If client code calls this function twice they'll get an exception. // We aren't currently being nice and returning the existing property. OVisibilityProperty visibilityProperty( iObject.getProperties(), kVisibilityPropertyName, iTimeSamplingID ); return visibilityProperty; }
//-***************************************************************************** void makeDeepHierarchy( OObject parent, const int level ) { if ( level > DEPTH ) { OCompoundProperty p = parent.getProperties(); OInt32ArrayProperty iap( p, "intArrayProp", TimeSamplingType() ); iap.set( intArraySamp ); return; } makeDeepHierarchy( OObject( parent, boost::lexical_cast<std::string>( level ) ), level + 1 ); }
OVisibilityProperty CreateVisibilityProperty( OObject & iObject, AbcA::TimeSamplingPtr iTimeSampling ) { OVisibilityProperty emptyProperty; if ( iTimeSampling ) { uint32_t iTimeSamplingID; iTimeSamplingID = iObject.getArchive().addTimeSampling( *iTimeSampling ); return CreateVisibilityProperty( iObject, iTimeSamplingID ); } return emptyProperty; }
//-***************************************************************************** void OCompoundProperty::init( OObject iObject, const Argument &iArg0, const Argument &iArg1 ) { getErrorHandler().setPolicy( GetErrorHandlerPolicy( iObject, iArg0, iArg1 ) ); ALEMBIC_ABC_SAFE_CALL_BEGIN( "OCompoundProperty::init( OObject )" ); m_property = iObject.getProperties().getPtr(); ALEMBIC_ABC_SAFE_CALL_END_RESET(); }
//-***************************************************************************** void makeDeepHierarchy( OObject parent, const int level ) { if ( level > DEPTH ) { OCompoundProperty p = parent.getProperties(); OInt32ArrayProperty iap( p, "intArrayProp", 0 ); iap.set( intArraySamp ); return; } std::ostringstream strm; strm << level; std::string levelName = strm.str(); makeDeepHierarchy( OObject( parent, levelName ), level + 1 ); }
void errorHandlerTest(bool useOgawa) { { OArchive archive; if (useOgawa) { archive = OArchive( Alembic::AbcCoreOgawa::WriteArchive(), "throwTest.abc", ErrorHandler::kThrowPolicy ); } else { archive = OArchive( Alembic::AbcCoreHDF5::WriteArchive(), "throwTest.abc", ErrorHandler::kThrowPolicy ); } OObject archiveTop = archive.getTop(); ABCA_ASSERT( archiveTop.getErrorHandler().getPolicy() == ErrorHandler::kThrowPolicy, "Error: Not kThrowPolicy" ); OObject childQuiet(archiveTop, "childQuiet", ErrorHandler::kQuietNoopPolicy ); OObject childNoisy(archiveTop, "childNoisy", ErrorHandler::kNoisyNoopPolicy ); OObject grandchildQuiet(childQuiet, "grandchildQuiet" ); OObject grandchildNoisy(childNoisy, "grandchildNoisy" ); ABCA_ASSERT( childQuiet.getErrorHandler().getPolicy() == ErrorHandler::kQuietNoopPolicy, "Error: Not kQuietNoopPolicy" ); ABCA_ASSERT( childNoisy.getErrorHandler().getPolicy() == ErrorHandler::kNoisyNoopPolicy, "Error: Not kNoisyNoopPolicy" ); ABCA_ASSERT( grandchildQuiet.getErrorHandler().getPolicy() == ErrorHandler::kQuietNoopPolicy, "Error: Not kQuietNoopPolicy" ); ABCA_ASSERT( grandchildNoisy.getErrorHandler().getPolicy() == ErrorHandler::kNoisyNoopPolicy, "Error: Not kNoisyNoopPolicy" ); } { AbcF::IFactory factory; factory.setPolicy( ErrorHandler::kThrowPolicy ); AbcF::IFactory::CoreType coreType; IArchive archive = factory.getArchive("throwTest.abc", coreType); IObject archiveTop = archive.getTop(); ABCA_ASSERT( archiveTop.getErrorHandler().getPolicy() == ErrorHandler::kThrowPolicy, "Error: Not kThrowPolicy" ); IObject childQuiet(archiveTop, "childQuiet", ErrorHandler::kQuietNoopPolicy ); IObject childNoisy(archiveTop, "childNoisy", ErrorHandler::kNoisyNoopPolicy ); IObject grandchildQuiet(childQuiet, "grandchildQuiet" ); IObject grandchildNoisy(childNoisy, "grandchildNoisy" ); ABCA_ASSERT( childQuiet.getErrorHandler().getPolicy() == ErrorHandler::kQuietNoopPolicy, "Error: Not kQuietNoopPolicy" ); ABCA_ASSERT( childNoisy.getErrorHandler().getPolicy() == ErrorHandler::kNoisyNoopPolicy, "Error: Not kNoisyNoopPolicy" ); ABCA_ASSERT( grandchildQuiet.getErrorHandler().getPolicy() == ErrorHandler::kQuietNoopPolicy, "Error: Not kQuietNoopPolicy" ); ABCA_ASSERT( grandchildNoisy.getErrorHandler().getPolicy() == ErrorHandler::kNoisyNoopPolicy, "Error: Not kNoisyNoopPolicy" ); } }
//-***************************************************************************** //-***************************************************************************** // 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; }
//-***************************************************************************** // a recursive function that reads all inputs and write to the given oObject // node if there's no gap in the frame range for animated nodes // void visitObjects(std::vector< IObject > & iObjects, OObject & oParentObj) { OObject outObj; const AbcA::ObjectHeader & header = iObjects[0].getHeader(); // there are a number of things that needs to be checked for each node // to make sure they can be properly stitched together // // for xform node: // locator or normal xform node // if an xform node, numOps and type of ops match // static or no, and if not, timesampling type matches // if sampled, timesampling type should match // if sampled, no frame gaps // if (IXform::matches(header)) { OXformSchema oSchema; init< IXform, IXformSchema, OXform, OXformSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); ICompoundPropertyVec iCompoundProps; iCompoundProps.reserve(iObjects.size()); ICompoundProperty cp = iObjects[0].getProperties(); iCompoundProps.push_back(cp); bool isLocator = cp.getPropertyHeader("locator")?true:false; for (size_t i = 1; i < iObjects.size(); i++) { ICompoundProperty cp = iObjects[i].getProperties(); iCompoundProps.push_back(cp); } // stitch the operations if this is an xform node for (size_t i = 0; i < iObjects.size(); i++) { IXformSchema iSchema = IXform(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); index_t numSamples = iSchema.getNumSamples(); index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { XformSample samp = iSchema.getValue(reqIdx); oSchema.set(samp); } } // stitch "locator" if it's a locator OCompoundProperty oCompoundProp = outObj.getProperties(); if (isLocator) { const PropertyHeader * propHeaderPtr = iCompoundProps[0].getPropertyHeader("locator"); stitchScalarProp(*propHeaderPtr, iCompoundProps, oCompoundProp); } } else if (ISubD::matches(header)) { OSubDSchema oSchema; init< ISubD, ISubDSchema, OSubD, OSubDSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the SubDSchema // for (size_t i = 0; i < iObjects.size(); i++) { ISubDSchema iSchema = ISubD(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); index_t numSamples = iSchema.getNumSamples(); IV2fGeomParam uvs = iSchema.getUVsParam(); if (i == 0 && uvs) { oSchema.setUVSourceName(GetSourceName(uvs.getMetaData())); } index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { ISubDSchema::Sample iSamp = iSchema.getValue(reqIdx); OSubDSchema::Sample oSamp; Abc::P3fArraySamplePtr posPtr = iSamp.getPositions(); if (posPtr) oSamp.setPositions(*posPtr); Abc::V3fArraySamplePtr velocPtr = iSamp.getVelocities(); if (velocPtr) oSamp.setVelocities(*velocPtr); Abc::Int32ArraySamplePtr faceIndicesPtr = iSamp.getFaceIndices(); if (faceIndicesPtr) oSamp.setFaceIndices(*faceIndicesPtr); Abc::Int32ArraySamplePtr faceCntPtr = iSamp.getFaceCounts(); if (faceCntPtr) oSamp.setFaceCounts(*faceCntPtr); oSamp.setFaceVaryingInterpolateBoundary(iSamp.getFaceVaryingInterpolateBoundary()); oSamp.setFaceVaryingPropagateCorners(iSamp.getFaceVaryingPropagateCorners()); oSamp.setInterpolateBoundary(iSamp.getInterpolateBoundary()); Abc::Int32ArraySamplePtr creaseIndicesPtr = iSamp.getCreaseIndices(); if (creaseIndicesPtr) oSamp.setCreaseIndices(*creaseIndicesPtr); Abc::Int32ArraySamplePtr creaseLenPtr = iSamp.getCreaseLengths(); if (creaseLenPtr) oSamp.setCreaseLengths(*creaseLenPtr); Abc::FloatArraySamplePtr creaseSpPtr = iSamp.getCreaseSharpnesses(); if (creaseSpPtr) oSamp.setCreaseSharpnesses(*creaseSpPtr); Abc::Int32ArraySamplePtr cornerIndicesPtr = iSamp.getCornerIndices(); if (cornerIndicesPtr) oSamp.setCornerIndices(*cornerIndicesPtr); Abc::FloatArraySamplePtr cornerSpPtr = iSamp.getCornerSharpnesses(); if (cornerSpPtr) oSamp.setCreaseSharpnesses(*cornerSpPtr); Abc::Int32ArraySamplePtr holePtr = iSamp.getHoles(); if (holePtr) oSamp.setHoles(*holePtr); oSamp.setSubdivisionScheme(iSamp.getSubdivisionScheme()); // set uvs IV2fGeomParam::Sample iUVSample; OV2fGeomParam::Sample oUVSample; if (uvs) { getOGeomParamSamp <IV2fGeomParam, IV2fGeomParam::Sample, OV2fGeomParam::Sample>(uvs, iUVSample, oUVSample, reqIdx); oSamp.setUVs(oUVSample); } oSchema.set(oSamp); } } } else if (IPolyMesh::matches(header)) { OPolyMeshSchema oSchema; init< IPolyMesh, IPolyMeshSchema, OPolyMesh, OPolyMeshSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the PolySchema // for (size_t i = 0; i < iObjects.size(); i++) { IPolyMeshSchema iSchema = IPolyMesh(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); index_t numSamples = iSchema.getNumSamples(); IN3fGeomParam normals = iSchema.getNormalsParam(); IV2fGeomParam uvs = iSchema.getUVsParam(); if (i == 0 && uvs) { oSchema.setUVSourceName(GetSourceName(uvs.getMetaData())); } index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { IPolyMeshSchema::Sample iSamp = iSchema.getValue(reqIdx); OPolyMeshSchema::Sample oSamp; Abc::P3fArraySamplePtr posPtr = iSamp.getPositions(); if (posPtr) oSamp.setPositions(*posPtr); Abc::V3fArraySamplePtr velocPtr = iSamp.getVelocities(); if (velocPtr) oSamp.setVelocities(*velocPtr); Abc::Int32ArraySamplePtr faceIndicesPtr = iSamp.getFaceIndices(); if (faceIndicesPtr) oSamp.setFaceIndices(*faceIndicesPtr); Abc::Int32ArraySamplePtr faceCntPtr = iSamp.getFaceCounts(); if (faceCntPtr) oSamp.setFaceCounts(*faceCntPtr); // set uvs IV2fGeomParam::Sample iUVSample; OV2fGeomParam::Sample oUVSample; if (uvs) { getOGeomParamSamp <IV2fGeomParam, IV2fGeomParam::Sample, OV2fGeomParam::Sample>(uvs, iUVSample, oUVSample, reqIdx); oSamp.setUVs(oUVSample); } // set normals IN3fGeomParam::Sample iNormalsSample; ON3fGeomParam::Sample oNormalsSample; if (normals) { getOGeomParamSamp <IN3fGeomParam, IN3fGeomParam::Sample, ON3fGeomParam::Sample>(normals, iNormalsSample, oNormalsSample, reqIdx); oSamp.setNormals(oNormalsSample); } oSchema.set(oSamp); } } } else if (ICamera::matches(header)) { OCameraSchema oSchema; init< ICamera, ICameraSchema, OCamera, OCameraSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the CameraSchemas // for (size_t i = 0; i < iObjects.size(); i++) { ICameraSchema iSchema = ICamera(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); index_t numSamples = iSchema.getNumSamples(); index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { oSchema.set(iSchema.getValue(reqIdx)); } } } else if (ICurves::matches(header)) { OCurvesSchema oSchema; init< ICurves, ICurvesSchema, OCurves, OCurvesSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the CurvesSchemas // for (size_t i = 0; i < iObjects.size(); i++) { ICurvesSchema iSchema = ICurves(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); IV2fGeomParam iUVs = iSchema.getUVsParam(); IN3fGeomParam iNormals = iSchema.getNormalsParam(); IFloatGeomParam iWidths = iSchema.getWidthsParam(); IFloatArrayProperty iKnots = iSchema.getKnotsProperty(); IUcharArrayProperty iOrders = iSchema.getOrdersProperty(); index_t numSamples = iSchema.getNumSamples(); index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { ICurvesSchema::Sample iSamp = iSchema.getValue(reqIdx); OCurvesSchema::Sample oSamp; Abc::P3fArraySamplePtr posPtr = iSamp.getPositions(); if (posPtr) oSamp.setPositions(*posPtr); Abc::V3fArraySamplePtr velocPtr = iSamp.getVelocities(); if (velocPtr) oSamp.setVelocities(*velocPtr); oSamp.setType(iSamp.getType()); Abc::Int32ArraySamplePtr curvsNumPtr = iSamp.getCurvesNumVertices(); if (curvsNumPtr) oSamp.setCurvesNumVertices(*curvsNumPtr); oSamp.setWrap(iSamp.getWrap()); oSamp.setBasis(iSamp.getBasis()); Abc::FloatArraySamplePtr knotsPtr = iSamp.getKnots(); if (knotsPtr) { oSamp.setKnots(*knotsPtr); } Abc::UcharArraySamplePtr ordersPtr = iSamp.getOrders(); if (ordersPtr) { oSamp.setOrders(*ordersPtr); } IFloatGeomParam::Sample iWidthSample; OFloatGeomParam::Sample oWidthSample; if (iWidths) { getOGeomParamSamp <IFloatGeomParam, IFloatGeomParam::Sample, OFloatGeomParam::Sample>(iWidths, iWidthSample, oWidthSample, reqIdx); oSamp.setWidths(oWidthSample); } IV2fGeomParam::Sample iUVSample; OV2fGeomParam::Sample oUVSample; if (iUVs) { getOGeomParamSamp <IV2fGeomParam, IV2fGeomParam::Sample, OV2fGeomParam::Sample>(iUVs, iUVSample, oUVSample, reqIdx); oSamp.setUVs(oUVSample); } IN3fGeomParam::Sample iNormalsSample; ON3fGeomParam::Sample oNormalsSample; if (iNormals) { getOGeomParamSamp <IN3fGeomParam, IN3fGeomParam::Sample, ON3fGeomParam::Sample>(iNormals, iNormalsSample, oNormalsSample, reqIdx); oSamp.setNormals(oNormalsSample); } oSchema.set(oSamp); } } } else if (IPoints::matches(header)) { OPointsSchema oSchema; init< IPoints, IPointsSchema, OPoints, OPointsSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the PointsSchemas // for (size_t i = 0; i < iObjects.size(); i++) { IPointsSchema iSchema = IPoints(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); IFloatGeomParam iWidths = iSchema.getWidthsParam(); index_t numSamples = iSchema.getNumSamples(); index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { IPointsSchema::Sample iSamp = iSchema.getValue(reqIdx); OPointsSchema::Sample oSamp; Abc::P3fArraySamplePtr posPtr = iSamp.getPositions(); if (posPtr) oSamp.setPositions(*posPtr); Abc::UInt64ArraySamplePtr idPtr = iSamp.getIds(); if (idPtr) oSamp.setIds(*idPtr); Abc::V3fArraySamplePtr velocPtr = iSamp.getVelocities(); if (velocPtr) oSamp.setVelocities(*velocPtr); IFloatGeomParam::Sample iWidthSample; OFloatGeomParam::Sample oWidthSample; if (iWidths) { getOGeomParamSamp <IFloatGeomParam, IFloatGeomParam::Sample, OFloatGeomParam::Sample>(iWidths, iWidthSample, oWidthSample, reqIdx); oSamp.setWidths(oWidthSample); } oSchema.set(oSamp); } } } else if (INuPatch::matches(header)) { ONuPatchSchema oSchema; init< INuPatch, INuPatchSchema, ONuPatch, ONuPatchSchema >(iObjects, oParentObj, oSchema); outObj = oSchema.getObject(); // stitch the NuPatchSchemas // for (size_t i = 0; i < iObjects.size(); i++) { INuPatchSchema iSchema = INuPatch(iObjects[i], Alembic::Abc::kWrapExisting).getSchema(); index_t numSamples = iSchema.getNumSamples(); IN3fGeomParam normals = iSchema.getNormalsParam(); IV2fGeomParam uvs = iSchema.getUVsParam(); index_t reqIdx = getIndexSample(oSchema.getNumSamples(), oSchema.getTimeSampling(), numSamples, iSchema.getTimeSampling()); for (; reqIdx < numSamples; reqIdx++) { INuPatchSchema::Sample iSamp = iSchema.getValue(reqIdx); ONuPatchSchema::Sample oSamp; Abc::P3fArraySamplePtr posPtr = iSamp.getPositions(); if (posPtr) oSamp.setPositions(*posPtr); Abc::V3fArraySamplePtr velocPtr = iSamp.getVelocities(); if (velocPtr) oSamp.setVelocities(*velocPtr); oSamp.setNu(iSamp.getNumU()); oSamp.setNv(iSamp.getNumV()); oSamp.setUOrder(iSamp.getUOrder()); oSamp.setVOrder(iSamp.getVOrder()); Abc::FloatArraySamplePtr uKnotsPtr = iSamp.getUKnot(); if (uKnotsPtr) oSamp.setUKnot(*uKnotsPtr); Abc::FloatArraySamplePtr vKnotsPtr = iSamp.getVKnot(); if (vKnotsPtr) oSamp.setVKnot(*vKnotsPtr); IV2fGeomParam::Sample iUVSample; OV2fGeomParam::Sample oUVSample; if (uvs) { getOGeomParamSamp <IV2fGeomParam, IV2fGeomParam::Sample, OV2fGeomParam::Sample>(uvs, iUVSample, oUVSample, reqIdx); oSamp.setUVs(oUVSample); } IN3fGeomParam::Sample iNormalsSample; ON3fGeomParam::Sample oNormalsSample; if (normals) { getOGeomParamSamp <IN3fGeomParam, IN3fGeomParam::Sample, ON3fGeomParam::Sample>(normals, iNormalsSample, oNormalsSample, reqIdx); oSamp.setNormals(oNormalsSample); } if (iSchema.hasTrimCurve()) { oSamp.setTrimCurve(iSamp.getTrimNumLoops(), *(iSamp.getTrimNumCurves()), *(iSamp.getTrimNumVertices()), *(iSamp.getTrimOrders()), *(iSamp.getTrimKnots()), *(iSamp.getTrimMins()), *(iSamp.getTrimMaxes()), *(iSamp.getTrimU()), *(iSamp.getTrimV()), *(iSamp.getTrimW())); } oSchema.set(oSamp); } } } else { outObj = OObject(oParentObj, header.getName(), header.getMetaData()); // collect the top level compound property ICompoundPropertyVec iCompoundProps(iObjects.size()); for (size_t i = 0; i < iObjects.size(); i++) { iCompoundProps[i] = iObjects[i].getProperties(); } OCompoundProperty oCompoundProperty = outObj.getProperties(); stitchCompoundProp(iCompoundProps, oCompoundProperty); } // After done writing THIS OObject node, if input nodes have children, // go deeper. // Otherwise we are done here size_t numChildren = iObjects[0].getNumChildren(); // check to make sure all of our iObjects have the same number of children for (size_t j = 1; j < iObjects.size(); j++) { if (numChildren != iObjects[j].getNumChildren()) { std::cerr << "ERROR: " << iObjects[j].getFullName() << " in " << iObjects[j].getArchive().getName() << " has a different number of children than " << iObjects[0].getFullName() << " in " << iObjects[0].getArchive().getName() << std::endl; exit(1); } } for (size_t i = 0 ; i < numChildren; i++ ) { std::vector< IObject > iChildObjects; for (size_t f = 0; f < iObjects.size(); f++) { iChildObjects.push_back(iObjects[f].getChild(i)); } visitObjects(iChildObjects, outObj); } }
//-***************************************************************************** void diabolicalInstance( const std::string& iArchiveName, bool useOgawa ) { /* a0 b0 (points to a0) / | a1 b1 (points to a1) / | a2 b2 (points to b2) */ { OArchive archive; if (useOgawa) { archive = OArchive( Alembic::AbcCoreOgawa::WriteArchive(), iArchiveName, ErrorHandler::kThrowPolicy ); } else { archive = OArchive( Alembic::AbcCoreHDF5::WriteArchive(), iArchiveName, ErrorHandler::kThrowPolicy ); } OObject topobj = archive.getTop(); OObject a0( topobj, "a0" ); TESTING_ASSERT( topobj.addChildInstance( a0, "b0" ) ); OObject a1( a0, "a1" ); TESTING_ASSERT( a0.addChildInstance( a1, "b1" ) ); OObject a2( a1, "a2" ); TESTING_ASSERT( a1.addChildInstance( a2, "b2" ) ); } { AbcF::IFactory factory; IArchive archive = factory.getArchive( iArchiveName ); IObject topObject = archive.getTop(); IObject a0( topObject.getChild(0) ); TESTING_ASSERT( !a0.isInstanceDescendant() ); TESTING_ASSERT( a0.getFullName() == "/a0" ); TESTING_ASSERT( !a0.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0.getParent().getFullName() == "/" ); IObject b0( topObject.getChild(1) ); TESTING_ASSERT( b0.isInstanceDescendant() ); TESTING_ASSERT( b0.getName() == "b0" ); TESTING_ASSERT( b0.getFullName() == "/b0" ); TESTING_ASSERT( !b0.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0.getParent().getFullName() == "/" ); IObject a0a1( a0.getChild(0) ); TESTING_ASSERT( !a0a1.isInstanceDescendant() ); TESTING_ASSERT( a0a1.getName() == "a1" ); TESTING_ASSERT( a0a1.getFullName() == "/a0/a1" ); TESTING_ASSERT( !a0a1.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0a1.getParent().getName() == "a0" ); TESTING_ASSERT( a0a1.getParent().getFullName() == "/a0" ); IObject a0b1( a0.getChild(1) ); TESTING_ASSERT( a0b1.isInstanceDescendant() ); TESTING_ASSERT( a0b1.getName() == "b1" ); TESTING_ASSERT( a0b1.getFullName() == "/a0/b1" ); TESTING_ASSERT( !a0b1.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0b1.getParent().getName() == "a0" ); TESTING_ASSERT( a0b1.getParent().getFullName() == "/a0" ); IObject b0a1( b0.getChild(0) ); TESTING_ASSERT( b0a1.isInstanceDescendant() ); TESTING_ASSERT( b0a1.getParent().isInstanceDescendant() ); IObject b0b1( b0.getChild(1) ); TESTING_ASSERT( b0b1.isInstanceDescendant() ); TESTING_ASSERT( b0b1.getName() == "b1" ); TESTING_ASSERT( b0b1.getFullName() == "/b0/b1" ); TESTING_ASSERT( b0b1.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0b1.getParent().getName() == "b0" ); TESTING_ASSERT( b0b1.getParent().getFullName() == "/b0" ); IObject a0a1a2( a0a1.getChild(0) ); TESTING_ASSERT( !a0a1a2.isInstanceDescendant() ); TESTING_ASSERT( a0a1a2.getName() == "a2" ); TESTING_ASSERT( a0a1a2.getFullName() == "/a0/a1/a2" ); TESTING_ASSERT( !a0a1a2.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0a1a2.getParent().getName() == "a1" ); TESTING_ASSERT( a0a1a2.getParent().getFullName() == "/a0/a1" ); TESTING_ASSERT( !a0a1a2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( a0a1a2.getParent().getParent().getName() == "a0" ); TESTING_ASSERT( a0a1a2.getParent().getParent().getFullName() == "/a0" ); IObject a0a1b2( a0a1.getChild(1) ); TESTING_ASSERT( a0a1b2.isInstanceDescendant() ); TESTING_ASSERT( a0a1b2.getName() == "b2" ); TESTING_ASSERT( a0a1b2.getFullName() == "/a0/a1/b2" ); TESTING_ASSERT( !a0a1b2.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0a1b2.getParent().getName() == "a1" ); TESTING_ASSERT( a0a1b2.getParent().getFullName() == "/a0/a1" ); TESTING_ASSERT( !a0a1b2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( a0a1b2.getParent().getParent().getName() == "a0" ); TESTING_ASSERT( a0a1b2.getParent().getParent().getFullName() == "/a0" ); IObject a0b1a2( a0b1.getChild(0) ); TESTING_ASSERT( a0b1a2.isInstanceDescendant() ); TESTING_ASSERT( a0b1a2.getName() == "a2" ); TESTING_ASSERT( a0b1a2.getFullName() == "/a0/b1/a2" ); TESTING_ASSERT( a0b1a2.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0b1a2.getParent().getName() == "b1" ); TESTING_ASSERT( a0b1a2.getParent().getFullName() == "/a0/b1" ); TESTING_ASSERT( !a0b1a2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( a0b1a2.getParent().getParent().getName() == "a0" ); TESTING_ASSERT( a0b1a2.getParent().getParent().getFullName() == "/a0" ); IObject a0b1b2( a0b1.getChild(1) ); TESTING_ASSERT( a0b1b2.isInstanceDescendant() ); TESTING_ASSERT( a0b1b2.getName() == "b2" ); TESTING_ASSERT( a0b1b2.getFullName() == "/a0/b1/b2" ); TESTING_ASSERT( a0b1b2.getParent().isInstanceDescendant() ); TESTING_ASSERT( a0b1b2.getParent().getName() == "b1" ); TESTING_ASSERT( a0b1b2.getParent().getFullName() == "/a0/b1" ); TESTING_ASSERT( !a0b1b2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( a0b1b2.getParent().getParent().getName() == "a0" ); TESTING_ASSERT( a0b1b2.getParent().getParent().getFullName() == "/a0" ); IObject b0a1a2( b0a1.getChild(0) ); TESTING_ASSERT( b0a1a2.isInstanceDescendant() ); TESTING_ASSERT( b0a1a2.getName() == "a2" ); TESTING_ASSERT( b0a1a2.getFullName() == "/b0/a1/a2" ); TESTING_ASSERT( b0a1a2.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0a1a2.getParent().getName() == "a1" ); TESTING_ASSERT( b0a1a2.getParent().getFullName() == "/b0/a1" ); TESTING_ASSERT( b0a1a2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( b0a1a2.getParent().getParent().getName() == "b0" ); TESTING_ASSERT( b0a1a2.getParent().getParent().getFullName() == "/b0" ); IObject b0a1b2( b0a1.getChild(1) ); TESTING_ASSERT( b0a1b2.isInstanceDescendant() ); TESTING_ASSERT( b0a1b2.getName() == "b2" ); TESTING_ASSERT( b0a1b2.getFullName() == "/b0/a1/b2" ); TESTING_ASSERT( b0a1b2.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0a1b2.getParent().getName() == "a1" ); TESTING_ASSERT( b0a1b2.getParent().getFullName() == "/b0/a1" ); TESTING_ASSERT( b0a1b2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( b0a1b2.getParent().getParent().getName() == "b0" ); TESTING_ASSERT( b0a1b2.getParent().getParent().getFullName() == "/b0" ); IObject b0b1a2( b0b1.getChild(0) ); TESTING_ASSERT( b0b1a2.isInstanceDescendant() ); TESTING_ASSERT( b0b1a2.getName() == "a2" ); TESTING_ASSERT( b0b1a2.getFullName() == "/b0/b1/a2" ); TESTING_ASSERT( b0b1a2.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0b1a2.getParent().getName() == "b1" ); TESTING_ASSERT( b0b1a2.getParent().getFullName() == "/b0/b1" ); TESTING_ASSERT( b0b1a2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( b0b1a2.getParent().getParent().getName() == "b0" ); TESTING_ASSERT( b0b1a2.getParent().getParent().getFullName() == "/b0" ); IObject b0b1b2( b0b1.getChild(1) ); TESTING_ASSERT( b0b1b2.isInstanceDescendant() ); TESTING_ASSERT( b0b1b2.getName() == "b2" ); TESTING_ASSERT( b0b1b2.getFullName() == "/b0/b1/b2" ); TESTING_ASSERT( b0b1b2.getParent().isInstanceDescendant() ); TESTING_ASSERT( b0b1b2.getParent().getName() == "b1" ); TESTING_ASSERT( b0b1b2.getParent().getFullName() == "/b0/b1" ); TESTING_ASSERT( b0b1b2.getParent().getParent().isInstanceDescendant() ); TESTING_ASSERT( b0b1b2.getParent().getParent().getName() == "b0" ); TESTING_ASSERT( b0b1b2.getParent().getParent().getFullName() == "/b0" ); } }
//-***************************************************************************** //-***************************************************************************** //-***************************************************************************** // PARTICLES WRITER //-***************************************************************************** //-***************************************************************************** //-***************************************************************************** void RunAndWriteParticles ( OObject &iParent, const ParticleSystem::Parameters &iParams, size_t iNumFrames, chrono_t iFps ) { // Make the particle system. ParticleSystem parts( iParams ); // Create the time sampling type. TimeSampling ts(iFps, 0.0); Alembic::Util::uint32_t tsidx = iParent.getArchive().addTimeSampling(ts); // Create our object. OPoints partsOut( iParent, "simpleParticles", tsidx ); std::cout << "Created Simple Particles" << std::endl; // Add attributes OPointsSchema &pSchema = partsOut.getSchema(); MetaData mdata; SetGeometryScope( mdata, kVaryingScope ); OV3fArrayProperty velOut( pSchema, "velocity", mdata, tsidx ); OC3fArrayProperty rgbOut( pSchema, "Cs", tsidx ); OFloatArrayProperty ageOut( pSchema, "age", tsidx ); // Get seconds per frame. chrono_t iSpf = 1.0 / iFps; // CJH: Until we fix zero-array-property bug, loop a few frames. for ( int preRoll = 0; preRoll < 100; ++preRoll ) { parts.timeStep( iSpf ); if ( parts.numParticles() > 0 ) { break; } } ABCA_ASSERT( parts.numParticles() > 0, "Degenerate particle system" ); // Loop over the frames. for ( index_t sampIndex = 0; sampIndex < ( index_t )iNumFrames; ++sampIndex ) { // First, write the sample. OPointsSchema::Sample psamp( V3fArraySample( parts.positionVec() ), UInt64ArraySample( parts.idVec() ) ); pSchema.set( psamp ); velOut.set( V3fArraySample( parts.velocityVec() ) ); rgbOut.set( C3fArraySample( parts.colorVec() ) ); ageOut.set( FloatArraySample( parts.ageVec() ) ); // Now time step. parts.timeStep( iSpf ); // Print! std::cout << "Wrote " << parts.numParticles() << " particles to frame: " << sampIndex << std::endl; } // End it. std::cout << "Finished Sim, About to finish writing" << std::endl; }