//-*****************************************************************************
void cameraTest()
{
    std::string fileName = "camera1.abc";
    {
        OArchive archive( Alembic::AbcCoreHDF5::WriteArchive(), fileName );
        CameraSample samp;
        OCamera simpleCamObj( OObject( archive, kTop ), "simpleCam" );
        simpleCamObj.getSchema().set( samp );

        OCamera camObj( OObject( archive, kTop ), "cam" );
        OCameraSchema camSchema = camObj.getSchema();
        samp.addOp( FilmBackXformOp( kScaleFilmBackOperation, "scale" ) );
        samp.addOp( FilmBackXformOp( kTranslateFilmBackOperation, "offset" ) );
        camSchema.set( samp );

        samp[0].setScale( V2d( 2.0, 3.0 ) );
        samp[1].setChannelValue( 0, 4.0 );
        samp[1].setChannelValue( 1, 5.0 );
        samp.setLensSqueezeRatio( 2.0 );
        samp.setHorizontalAperture( 4.8 );
        samp.setVerticalFilmOffset( 3.0 );
        camSchema.set( samp );
    }

    {
        M33d identity;
        identity.makeIdentity();

        CameraSample samp;

        IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), fileName );
        ICamera simpleCam( IObject( archive, kTop ), "simpleCam" );
        ICamera cam( IObject( archive, kTop ), "cam" );

        // all default data
        simpleCam.getSchema().get( samp );
        TESTING_ASSERT( simpleCam.getSchema().getNumSamples() == 1 );
        TESTING_ASSERT( almostEqual( samp.getFocalLength(), 35.0 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalAperture(), 3.6 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalAperture(), 2.4 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalFilmOffset(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalFilmOffset(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getLensSqueezeRatio(), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanLeft(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanRight(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanTop(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanBottom(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getFStop(), 5.6 ) );
        TESTING_ASSERT( almostEqual( samp.getFocusDistance(), 5.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterOpen(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterClose(), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp.getNearClippingPlane(), 0.1 ) );
        TESTING_ASSERT( almostEqual( samp.getFarClippingPlane(), 100000.0 ) );
        TESTING_ASSERT( samp.getNumOps() == 0 );
        TESTING_ASSERT( samp.getNumOpChannels() == 0 );
        TESTING_ASSERT( samp.getFilmBackMatrix() == identity );

        TESTING_ASSERT( cam.getSchema().getNumSamples() == 2 );

        cam.getSchema().get( samp );
        TESTING_ASSERT( almostEqual( samp.getFocalLength(), 35.0 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalAperture(), 3.6 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalAperture(), 2.4 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalFilmOffset(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalFilmOffset(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getLensSqueezeRatio(), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanLeft(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanRight(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanTop(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanBottom(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getFStop(), 5.6 ) );
        TESTING_ASSERT( almostEqual( samp.getFocusDistance(), 5.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterOpen(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterClose(), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp.getNearClippingPlane(), 0.1 ) );
        TESTING_ASSERT( almostEqual( samp.getFarClippingPlane(), 100000.0 ) );
        TESTING_ASSERT( samp.getNumOps() == 2 );
        TESTING_ASSERT( samp.getNumOpChannels() == 4 );
        TESTING_ASSERT( samp[0].getHint() == "scale" );
        TESTING_ASSERT( samp[0].getType() == kScaleFilmBackOperation );
        TESTING_ASSERT( samp[0].getNumChannels() == 2 );
        TESTING_ASSERT( almostEqual( samp[0].getChannelValue(0), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp[0].getChannelValue(1), 1.0 ) );
        TESTING_ASSERT( samp[1].getHint() == "offset" );
        TESTING_ASSERT( samp[1].getType() == kTranslateFilmBackOperation );
        TESTING_ASSERT( samp[1].getNumChannels() == 2 );
        TESTING_ASSERT( almostEqual( samp[1].getChannelValue(0), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp[1].getChannelValue(1), 0.0 ) );
        TESTING_ASSERT( samp.getFilmBackMatrix() == identity );

        cam.getSchema().get( samp, 1 );
        TESTING_ASSERT( almostEqual( samp.getFocalLength(), 35.0 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalAperture(), 4.8 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalAperture(), 2.4 ) );
        TESTING_ASSERT( almostEqual( samp.getHorizontalFilmOffset(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getVerticalFilmOffset(), 3.0 ) );
        TESTING_ASSERT( almostEqual( samp.getLensSqueezeRatio(), 2.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanLeft(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanRight(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanTop(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getOverScanBottom(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getFStop(), 5.6 ) );
        TESTING_ASSERT( almostEqual( samp.getFocusDistance(), 5.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterOpen(), 0.0 ) );
        TESTING_ASSERT( almostEqual( samp.getShutterClose(), 1.0 ) );
        TESTING_ASSERT( almostEqual( samp.getNearClippingPlane(), 0.1 ) );
        TESTING_ASSERT( almostEqual( samp.getFarClippingPlane(), 100000.0 ) );
        TESTING_ASSERT( samp.getNumOps() == 2 );
        TESTING_ASSERT( samp.getNumOpChannels() == 4 );
        TESTING_ASSERT( samp[0].getHint() == "scale" );
        TESTING_ASSERT( samp[0].getType() == kScaleFilmBackOperation );
        TESTING_ASSERT( samp[0].getNumChannels() == 2 );
        TESTING_ASSERT( almostEqual( samp[0].getChannelValue(0), 2.0 ) );
        TESTING_ASSERT( almostEqual( samp[0].getChannelValue(1), 3.0 ) );
        TESTING_ASSERT( samp[0].getScale().equalWithAbsError( V2d( 2.0, 3.0 ),
            VAL_EPSILON ) );
        TESTING_ASSERT( samp[1].getHint() == "offset" );
        TESTING_ASSERT( samp[1].getType() == kTranslateFilmBackOperation );
        TESTING_ASSERT( samp[1].getNumChannels() == 2 );
        TESTING_ASSERT( almostEqual( samp[1].getChannelValue(0), 4.0 ) );
        TESTING_ASSERT( almostEqual( samp[1].getChannelValue(1), 5.0 ) );
        TESTING_ASSERT( samp[1].getTranslate().equalWithAbsError(
            V2d( 4.0, 5.0 ), VAL_EPSILON ) );

        M33d m;
        m.makeIdentity();
        m.scale( V2d( 2.0, 3.0 ) );
        m.translate( V2d( 4.0, 5.0 ) );
        TESTING_ASSERT( samp.getFilmBackMatrix().equalWithAbsError( m,
            VAL_EPSILON ) );
    }
}
Example #2
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 corePropertiesTest()
{
    std::string fileName = "camera2.abc";
    {
        OArchive archive( Alembic::AbcCoreHDF5::WriteArchive(), fileName );
        CameraSample samp;

        OCamera camObj( OObject( archive, kTop ), "cam" );
        OCameraSchema camSchema = camObj.getSchema();

        // set some nonsense values just to test reading/writing
        for ( std::size_t i = 0; i < 10; ++i )
        {
            samp.setFocalLength( i * 1000.0 + 1.0 );
            samp.setHorizontalAperture( i * 1000.0 + 2.0 );
            samp.setVerticalAperture( i * 1000.0 + 3.0 );
            samp.setHorizontalFilmOffset( i * 1000.0 + 4.0 );
            samp.setVerticalFilmOffset( i * 1000.0 + 5.0 );
            samp.setLensSqueezeRatio( i * 1000.0 + 6.0 );
            samp.setOverScanLeft( i * 1000.0 + 7.0 );
            samp.setOverScanRight( i * 1000.0 + 8.0 );
            samp.setOverScanTop( i * 1000.0 + 9.0 );
            samp.setOverScanBottom( i * 1000.0 + 10.0 );
            samp.setFStop( i * 1000.0 + 11.0 );
            samp.setFocusDistance( i * 1000.0 + 12.0 );
            samp.setShutterOpen( i * 1000.0 + 13.0 );
            samp.setShutterClose( i * 1000.0 + 14.0 );
            samp.setNearClippingPlane( i * 1000.0 + 15.0 );
            samp.setFarClippingPlane( i * 1000.0 + 16.0 );
            camSchema.set( samp );
        }
    }

    {
        M33d identity;
        identity.makeIdentity();

        CameraSample samp;

        IArchive archive( Alembic::AbcCoreHDF5::ReadArchive(), fileName );
        ICamera cam( IObject( archive, kTop ), "cam" );

        TESTING_ASSERT( cam.getSchema().getNumSamples() == 10 );

        for ( std::size_t i; i < 10; ++i )
        {
            cam.getSchema().get( samp );
            TESTING_ASSERT( almostEqual( samp.getFocalLength(),
                1000.0 * i + 1.0 ) );
            TESTING_ASSERT( almostEqual( samp.getHorizontalAperture(),
                1000.0 * i + 2.0 ) );
            TESTING_ASSERT( almostEqual( samp.getVerticalAperture(),
                1000.0 * i + 3.0 ) );
            TESTING_ASSERT( almostEqual( samp.getHorizontalFilmOffset(),
                1000.0 * i + 4.0 ) );
            TESTING_ASSERT( almostEqual( samp.getVerticalFilmOffset(),
                1000.0 * i + 5.0 ) );
            TESTING_ASSERT( almostEqual( samp.getLensSqueezeRatio(),
                1000.0 * i + 6.0 ) );
            TESTING_ASSERT( almostEqual( samp.getOverScanLeft(),
                1000.0 * i + 7.0 ) );
            TESTING_ASSERT( almostEqual( samp.getOverScanRight(),
                1000.0 * i + 8.0 ) );
            TESTING_ASSERT( almostEqual( samp.getOverScanTop(),
                1000.0 * i + 9.0 ) );
            TESTING_ASSERT( almostEqual( samp.getOverScanBottom(),
                1000.0 * i + 10.0 ) );
            TESTING_ASSERT( almostEqual( samp.getFStop(),
                1000.0 * i + 11.0 ) );
            TESTING_ASSERT( almostEqual( samp.getFocusDistance(),
                1000.0 * i + 12.0 ) );
            TESTING_ASSERT( almostEqual( samp.getShutterOpen(),
                1000.0 * i + 13.0 ) );
            TESTING_ASSERT( almostEqual( samp.getShutterClose(),
                1000.0 * i + 14.0 ) );
            TESTING_ASSERT( almostEqual( samp.getNearClippingPlane(),
                1000.0 * i + 15.0 ) );
            TESTING_ASSERT( almostEqual( samp.getFarClippingPlane(),
                1000.0 * i + 16.0 ) );
            TESTING_ASSERT( samp.getNumOps() == 0 );
            TESTING_ASSERT( samp.getNumOpChannels() == 0 );
        }
    }
}