Пример #1
0
Imath::Box3d AlembicInput::boundAtSample( size_t sampleIndex ) const
{	
	const MetaData &md = m_data->object.getMetaData();

	if( !m_data->object.getParent() )
	{
		// top of archive
		return GetIArchiveBounds( *(m_data->archive) ).getValue( ISampleSelector( (index_t)sampleIndex ) );
	}
	else if( IXform::matches( md ) )
	{
		IXform iXForm( m_data->object, kWrapExisting );
		IXformSchema &iXFormSchema = iXForm.getSchema();
		
		if( !iXFormSchema.getChildBoundsProperty() )
		{
			throw IECore::Exception( "No stored bounds available" );
		}
		
		XformSample sample;
		iXFormSchema.get( sample, ISampleSelector( (index_t)sampleIndex ) );
		return sample.getChildBounds();
	}
	else
	{
		IGeomBaseObject geomBase( m_data->object, kWrapExisting );
		return geomBase.getSchema().getValue( ISampleSelector( (index_t)sampleIndex ) ).getSelfBounds();
	}

	return Box3d();
}
//-*****************************************************************************
void xformTreeCreate()
{
    OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), "Xform_tree.abc" );
    std::vector<OXform> xforms;
    OObject root( archive, kTop);
    recurseCreateXform( root, 4, 4, xforms );
    std::cout << "Total xforms created " << xforms.size() << std::endl;

    XformSample samp;
    XformOp transop( kTranslateOperation, kTranslateHint );
    XformOp rotatop( kRotateOperation, kRotateHint );
    XformOp scaleop( kScaleOperation, kScaleHint );
    samp.addOp( transop, V3d(42.0, 42.0, 42.0) );
    samp.addOp( rotatop, V3d(0.0, 0.0, 1.0), 10.0 );
    samp.addOp( rotatop, V3d(0.0, 1.0, 0.0), 20.0 );
    samp.addOp( rotatop, V3d(1.0, 0.0, 0.0), 30.0 );
    samp.addOp( scaleop, V3d(4.0, 4.0, 4.0) );

    for (std::vector<OXform>::iterator i = xforms.begin(); i != xforms.end();
         ++i)
    {
        i->getSchema().set(samp);
    }

}
//-*****************************************************************************
void recurseCreateXform(OObject & iParent, int children, int level,
                        std::vector<OXform> & oCreated)
{
    for (int i = 0; i < children; ++i)
    {
        std::ostringstream strm;
        strm << "level" << "_" << i;
        std::string xformName = strm.str();
        OXform xform( iParent, xformName );
        XformSample samp;
        XformOp transop( kTranslateOperation, kTranslateHint );
        XformOp rotatop( kRotateOperation, kRotateHint );
        XformOp scaleop( kScaleOperation, kScaleHint );
        samp.addOp( transop, V3d(0.0, 0.0, 0.0) );
        samp.addOp( rotatop, V3d(0.0, 0.0, 1.0), 0.0 );
        samp.addOp( rotatop, V3d(0.0, 1.0, 0.0), 0.0 );
        samp.addOp( rotatop, V3d(1.0, 0.0, 0.0), 0.0 );
        samp.addOp( scaleop, V3d(1.0, 1.0, 1.0) );
        xform.getSchema().set(samp);
        oCreated.push_back( xform );
        if ( level > 0 )
        {
            recurseCreateXform( xform, children, level - 1, oCreated );
        }
    }
}
Пример #4
0
Imath::M44d AlembicInput::transformAtTime( double time ) const
{
	M44d result;
	
	if( IXform::matches( m_data->object.getMetaData() ) )
	{
		size_t index0, index1;
		double lerpFactor = sampleIntervalAtTime( time, index0, index1 );

		IXform iXForm( m_data->object, kWrapExisting );
		IXformSchema &iXFormSchema = iXForm.getSchema();
	
		if( index0 == index1 )
		{
			XformSample sample;
			iXFormSchema.get( sample, ISampleSelector( (index_t)index0 ) );
			result = sample.getMatrix();
		}
		else
		{
			XformSample sample0;
			iXFormSchema.get( sample0, ISampleSelector( (index_t)index0 ) );
			XformSample sample1;
			iXFormSchema.get( sample1, ISampleSelector( (index_t)index1 ) );
			
			if( sample0.getNumOps() != sample1.getNumOps() ||
				sample0.getNumOpChannels() != sample1.getNumOpChannels() 
			)
			{
				throw IECore::Exception( "Unable to interpolate samples of different sizes" );
			}
					
			XformSample interpolatedSample;
			for( size_t opIndex = 0; opIndex < sample0.getNumOps(); opIndex++ )
			{
				XformOp op0 = sample0.getOp( opIndex );
				XformOp op1 = sample1.getOp( opIndex );			
				XformOp interpolatedOp( op0.getType(), op0.getHint() );
				for( size_t channelIndex = 0; channelIndex < op0.getNumChannels(); channelIndex++ )
				{
					interpolatedOp.setChannelValue(
						channelIndex,
						lerp( op0.getChannelValue( channelIndex ), op1.getChannelValue( channelIndex ), lerpFactor )
					);
				}
				
				interpolatedSample.addOp( interpolatedOp );
			}
			
			result = interpolatedSample.getMatrix();
		}
	}
	
	return result;
}
Пример #5
0
//-*****************************************************************************
void OWrapExisting()
{
    Alembic::Abc::OArchive archive(
        Alembic::AbcCoreHDF5::WriteArchive(),
        "playground_owrap.abc"
                                  );

    Alembic::Abc::OObject archiveTop = archive.getTop();

    Alembic::Util::shared_ptr< Alembic::Abc::OObject > objAPtr =
        makeXform( archiveTop );

    Alembic::Util::shared_ptr< Alembic::Abc::OObject > objBPtr =
        subdCube( *objAPtr );

    //
    // NOW THE FUN BEGINS
    //
    TESTING_ASSERT( Alembic::AbcGeom::OSubD::matches( objBPtr->getHeader() ) );
    {
        Alembic::Util::shared_ptr< Alembic::AbcGeom::OSubD > subdObjPtr =
            Alembic::Util::dynamic_pointer_cast< Alembic::AbcGeom::OSubD >
                ( objBPtr );
        Alembic::AbcGeom::OSubD subdObj = *subdObjPtr;

        std::cout << "wrapped-existing subd has "
                  << subdObj.getSchema().getNumSamples() << " num samples."
                  << std::endl;


        std::vector<V3f> verts( 8, V3f(2.0, 2.0, 2.0 ) );
        Alembic::AbcGeom::OSubDSchema::Sample sample;
        sample.setPositions( Alembic::Abc::V3fArraySample( &(verts[0]),
                                                           verts.size() ) );
        subdObj.getSchema().set( sample );
        TESTING_ASSERT( subdObj.getSchema().getNumSamples() == 2 );
    }

    TESTING_ASSERT( Alembic::AbcGeom::OXform::matches( objAPtr->getHeader() ) );
    {
        XformOp transop( kTranslateOperation, kTranslateHint );
        XformOp scaleop( kScaleOperation, kScaleHint );

        XformSample samp;
        samp.addOp( transop, V3d( 4.0, 5.0, 6.0 ) );
        samp.addOp( scaleop, V3d( 8.0, 10.0, 12.0 ) );

        Alembic::Util::shared_ptr< Alembic::AbcGeom::OXform > xformObjPtr =
            Alembic::Util::dynamic_pointer_cast< Alembic::AbcGeom::OXform >
                ( objAPtr );
        Alembic::AbcGeom::OXform xformObj = *xformObjPtr;
        xformObj.getSchema().set( samp );
        TESTING_ASSERT( xformObj.getSchema().getNumSamples() == 2 );
    }
}
Пример #6
0
Imath::M44d AlembicInput::transformAtSample( size_t sampleIndex ) const
{
	M44d result;
	if( IXform::matches( m_data->object.getMetaData() ) )
	{
		IXform iXForm( m_data->object, kWrapExisting );
		IXformSchema &iXFormSchema = iXForm.getSchema();
		XformSample sample;
		iXFormSchema.get( sample, ISampleSelector( (index_t)sampleIndex ) );
		return sample.getMatrix();
	}
	return result;
}
//-*****************************************************************************
void accumXform( M44d &xf, IObject obj )
{
    if ( ISimpleXform::matches( obj.getMetaData() ) )
    {
        ISimpleXform x( obj, kWrapExisting );
        xf *= x.getSchema().getValue().getMatrix();
    }
    else if ( IXform::matches( obj.getMetaData() ) )
    {
        IXform x( obj, kWrapExisting );
        XformSample xs;
        x.getSchema().get( xs );
        xf *= xs.getMatrix();
    }
}
IECore::ObjectPtr FromAlembicXFormConverter::doAlembicConversion( const Alembic::Abc::IObject &iObject, const Alembic::Abc::ISampleSelector &sampleSelector, const IECore::CompoundObject *operands ) const
{
	IXform iXForm( iObject, kWrapExisting );
	IXformSchema &iXFormSchema = iXForm.getSchema();
	XformSample sample;
	iXFormSchema.get( sample, sampleSelector );
	M44d m = sample.getMatrix();
	return new M44fData(
		M44f( 
			m[0][0], m[0][1], m[0][2], m[0][3],
			m[1][0], m[1][1], m[1][2], m[1][3],
			m[2][0], m[2][1], m[2][2], m[2][3],
			m[3][0], m[3][1], m[3][2], m[3][3]
		)
	);
}
Пример #9
0
//-*****************************************************************************
Alembic::Util::shared_ptr< Alembic::Abc::OObject >
makeXform( Alembic::Abc::OObject & parent )
{
    Alembic::Util::shared_ptr< Alembic::AbcGeom::OXform > xformObjPtr
        ( new Alembic::AbcGeom::OXform( parent, "myXform" ) );

    // add a couple of ops
    XformOp transop( kTranslateOperation, kTranslateHint );
    XformOp scaleop( kScaleOperation, kScaleHint );

    XformSample samp;
    samp.addOp( transop, V3d( 1.0, 2.0, 3.0 ) );
    samp.addOp( scaleop, V3d( 2.0, 4.0, 6.0 ) );

    Alembic::AbcGeom::OXformSchema &schema = xformObjPtr->getSchema();

    schema.set( samp );

    return xformObjPtr;
}
Пример #10
0
//-*****************************************************************************
void IXformSchema::get( XformSample &oSamp, const Abc::ISampleSelector &iSS ) const
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "IXformSchema::get()" );

    oSamp.reset();

    if ( ! valid() ) { return; }

    oSamp = m_sample;

    if ( m_inheritsProperty && m_inheritsProperty.getNumSamples() > 0 )
    {
        oSamp.setInheritsXforms( m_inheritsProperty.getValue( iSS ) );
    }

    if ( ! m_valsProperty ) { return; }

    AbcA::index_t numSamples = 0;
    if ( m_useArrayProp )
    {
        numSamples = m_valsProperty->asArrayPtr()->getNumSamples();
    }
    else
    {
        numSamples = m_valsProperty->asScalarPtr()->getNumSamples();
    }

    if ( numSamples == 0 ) { return; }

    AbcA::index_t sampIdx = iSS.getIndex( m_valsProperty->getTimeSampling(),
                                          numSamples );

    if ( sampIdx < 0 ) { return; }

    this->getChannelValues( sampIdx, oSamp );

    ALEMBIC_ABC_SAFE_CALL_END();
}
Пример #11
0
//-*****************************************************************************
bool XformSample::isTopologyEqual( const XformSample & iSample )
{
    if (getNumOps() != iSample.getNumOps())
    {
        return false;
    }

    std::vector<XformOp>::const_iterator opA, opB;
    for ( opA = m_ops.begin(), opB = iSample.m_ops.begin(); opA != m_ops.end();
          ++opA, ++opB )
    {
        if ( opA->getType() != opB->getType() )
        {
            return false;
        }
    }

    return true;
}
Пример #12
0
void accumXform( Imath::M44d &xf, IObject obj, chrono_t curTime, bool interpolate)
{
    if ( IXform::matches( obj.getHeader() ) )
    {
        Imath::M44d mtx;
        IXform x( obj, kWrapExisting );
        XformSample xs;
        x.getSchema().get( xs );

        if (!x.getSchema().isConstant()) {

            TimeSamplingPtr timeSampler = x.getSchema().getTimeSampling();

            if (interpolate) {

                //std::pair<index_t, chrono_t> lSamp;// = timeSampler->getFloorIndex(curTime, x.getSchema().getNumSamples());
                Alembic::AbcCoreAbstract::index_t floorIdx, ceilIdx;

                double amt = getWeightAndIndex(curTime, timeSampler,
                                               x.getSchema().getNumSamples(), floorIdx, ceilIdx);

                if (amt != 0 && floorIdx != ceilIdx) {

                    const ISampleSelector iss_start(floorIdx);//lSamp.first);
                    Imath::M44d mtx_start = x.getSchema().getValue(iss_start).getMatrix();

                    //std::pair<index_t, chrono_t> rSamp = timeSampler->getCeilIndex(curTime, x.getSchema().getNumSamples());
                    const ISampleSelector iss_end(ceilIdx);//rSamp.first);
                    Imath::M44d mtx_end = x.getSchema().getValue(iss_end).getMatrix();


                    Imath::V3d s_l,s_r,h_l,h_r,t_l,t_r;
                    Imath::Quatd quat_l,quat_r;



                    DecomposeXForm(mtx_start, s_l, h_l, quat_l, t_l);
                    DecomposeXForm(mtx_end, s_r, h_r, quat_r, t_r);


                    if ((quat_l ^ quat_r) < 0)
                    {
                        quat_r = -quat_r;
                    }

                    mtx =  RecomposeXForm(Imath::lerp(s_l, s_r, amt),
                                          Imath::lerp(h_l, h_r, amt),
                                          Imath::slerp(quat_l, quat_r, amt),
                                          Imath::lerp(t_l, t_r, amt));


                }

                else {
                    const ISampleSelector iss(curTime);
                    xs = x.getSchema().getValue(iss);
                    mtx = xs.getMatrix();
                }

            }



            else { // no interpolation, get nearest sample
                const ISampleSelector iss(curTime);
                xs = x.getSchema().getValue(iss);
                mtx = xs.getMatrix();
            }

        }
        else {
            mtx = xs.getMatrix();
        }
        xf *= mtx;
    }
}
//-*****************************************************************************
void xformOut()
{
    OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), "Xform1.abc" );

    OXform a( OObject( archive, kTop ), "a" );
    OXform b( a, "b" );
    OXform c( b, "c" );
    OXform d( c, "d" );
    OXform e( d, "e" );
    OXform f( e, "f" );
    OXform g( f, "g" );

    XformOp transop( kTranslateOperation, kTranslateHint );
    XformOp scaleop( kScaleOperation, kScaleHint );
    XformOp matrixop( kMatrixOperation, kMatrixHint );

    TESTING_ASSERT( a.getSchema().getNumSamples() == 0 );

    OBox3dProperty childBounds = a.getSchema().getChildBoundsProperty();

    XformSample asamp;
    for ( size_t i = 0; i < 20; ++i )
    {
        asamp.addOp( transop, V3d( 12.0, i + 42.0, 20.0 ) );

        if ( i >= 18 )
        {
            childBounds.set( Abc::Box3d( V3d( -1.0, -1.0, -1.0 ),
                                         V3d( 1.0, 1.0, 1.0 ) ) );
        }
        else
        {
            childBounds.set( Abc::Box3d() );
        }

        a.getSchema().set( asamp );
    }

    XformSample bsamp;
    for ( size_t i = 0 ; i < 20 ; ++i )
    {
        bsamp.setInheritsXforms( (bool)(i&1) );

        b.getSchema().set( bsamp );
    }

    // for c we write nothing

    XformSample dsamp;
    dsamp.addOp( scaleop, V3d( 3.0, 6.0, 9.0 ) );
    d.getSchema().set( dsamp );

    XformSample esamp;
    M44d identmat;
    identmat.makeIdentity();

    esamp.addOp( transop, V3d( 0.0, 0.0, 0.0 ) );
    esamp.addOp( XformOp( kMatrixOperation, kMatrixHint ), identmat );
    esamp.addOp( scaleop, V3d( 1.0, 1.0, 1.0 ) );
    e.getSchema().set( esamp );

    XformSample fsamp;
    fsamp.addOp( transop, V3d( 3.0, -4.0, 5.0 ) );
    f.getSchema().set( fsamp );

    // this will cause the Xform's values property to be an ArrayProperty,
    // since there will be 20 * 16 channels.
    XformSample gsamp;
    Abc::M44d gmatrix;
    gmatrix.makeIdentity();
    for ( size_t i = 0 ; i < 20 ; ++i )
    {
        gmatrix.x[0][1] = (double)i;
        gsamp.addOp( matrixop, gmatrix );
    }
    g.getSchema().set( gsamp );
}
//-*****************************************************************************
void sparseTest()
{
    XformOp transOp( kTranslateOperation, kTranslateHint );
    XformOp scaleOp( kScaleOperation, kScaleHint );

    std::string nameA = "sparseXformTestA.abc";
    {
        OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), nameA );

        OXform transStatic( OObject( archive ),  "transStatic" );
        XformSample asamp;
        asamp.addOp( scaleOp, V3d( 2.0, 1.0, 2.0 ) );
        transStatic.getSchema().set( asamp );

        OXform transAnim( transStatic, "transAnim" );
        XformSample bsamp;
        bsamp.addOp( transOp, V3d( 3.0, 4.0, 5.0 ) );
        transAnim.getSchema().set( bsamp );
        bsamp[0].setTranslate( V3d( 4.0, 5.0, 6.0 ) );
        transAnim.getSchema().set( bsamp );

        OXform identA( transAnim, "ident" );
        OXform identB( identA, "ident" );

        OXform transStatic2( identB, "transStatic" );
        transStatic2.getSchema().set( asamp );

        OXform transAnim2( transStatic2, "transAnim" );
        transAnim2.getSchema().set( bsamp );
        bsamp[0].setTranslate( V3d( 5.0, 6.0, 7.0 ) );
        transAnim.getSchema().set( bsamp );

    }

    std::string nameB = "sparseXformTestB.abc";
    {
        OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), nameB );

        // set this now as animated translate
        OXform transStatic( OObject( archive ),  "transStatic", kSparse );
        XformSample asamp;
        asamp.addOp( transOp, V3d( 1.0, 1.0, 1.0) );
        transStatic.getSchema().set( asamp );
        asamp[0].setTranslate( V3d( 2.0, 2.0, 2.0 ) );
        transStatic.getSchema().set( asamp );

        // this one will be static
        OXform transAnim( transStatic, "transAnim", kSparse );
        XformSample bsamp;
        bsamp.addOp( scaleOp, V3d( 0.5, 0.5, 0.5 ) );
        transAnim.getSchema().set( bsamp );

        // from identity to static
        OXform identA( transAnim, "ident", kSparse );
        identA.getSchema().set( bsamp );

        // from identity to animated
        OXform identB( identA, "ident", kSparse );
        identB.getSchema().set( asamp );
        asamp[0].setTranslate( V3d( 3.0, 3.0, 3.0 ) );
        identB.getSchema().set( asamp );

        // don't set anything on these so they will be identity
        OXform transStatic2( identB, "transStatic", kSparse );
        OXform transAnim2( transStatic2, "transAnim", kSparse );
    }

    {
        std::vector< std::string > names;
        names.push_back( nameA );
        names.push_back( nameB );
        Alembic::AbcCoreFactory::IFactory factory;
        IArchive archive = factory.getArchive( names );

        IXform transStatic( IObject( archive ), "transStatic" );
        TESTING_ASSERT( !transStatic.getSchema().isConstantIdentity() );
        TESTING_ASSERT( !transStatic.getSchema().isConstant() );

        IXform transAnim( transStatic, "transAnim" );
        TESTING_ASSERT( !transAnim.getSchema().isConstantIdentity() );
        TESTING_ASSERT( transAnim.getSchema().isConstant() );

        IXform identA( transAnim, "ident" );
        TESTING_ASSERT( !identA.getSchema().isConstantIdentity() );
        TESTING_ASSERT( identA.getSchema().isConstant() );

        IXform identB( identA, "ident");
        TESTING_ASSERT( !identB.getSchema().isConstantIdentity() );
        TESTING_ASSERT( !identB.getSchema().isConstant() );

        IXform transStatic2( identB, "transStatic" );
        TESTING_ASSERT( transStatic2.getSchema().isConstantIdentity() );

        IXform transAnim2( transStatic2, "transAnim" );
        TESTING_ASSERT( transAnim2.getSchema().isConstantIdentity() );
    }
}
//-*****************************************************************************
void someOpsXform()
{
    std::string name = "someOpsXform.abc";
    {
        OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(), name );

        OXform a( OObject( archive, kTop ), "a" );

        OBox3dProperty bnds = CreateOArchiveBounds( archive );

        XformOp transop( kTranslateOperation, kTranslateHint );
        XformOp scaleop( kScaleOperation, kScaleHint );

        XformSample asamp;

        // scale
        asamp.addOp( scaleop, V3d( 2.0, 1.0, 2.0 ) );

        // Maya-like shear
        XformOp shearmatrixop( kMatrixOperation, kMayaShearHint );
        M44d shearmat;
        shearmat.makeIdentity();

        asamp.addOp( shearmatrixop, shearmat );

        // rotate x axis
        XformOp rotop( kRotateOperation, kRotateHint );
        asamp.addOp( rotop, V3d( 1.0, 0.0, 0.0 ), 1.57 );

        // rotate y axis, angle will be animated
        asamp.addOp( rotop, V3d( 0.0, 1.0, 0.0 ), 0.125 );

        // rotate z axis, use a different hint for fun
        XformOp rotorientop( kRotateOperation, kRotateOrientationHint );
        asamp.addOp( rotorientop, V3d( 0.0, 0.0, 1.0 ), 0.1 );

        // translate with animated y and z, different hint for fun
        XformOp transpivotop( kTranslateOperation, kRotatePivotPointHint );
        asamp.addOp( transpivotop, V3d( 0.0, 0.0, 0.0 ) );

        a.getSchema().set( asamp );
        bnds.set( Box3d( V3d( -0.1, -0.1, -0.1 ),
                         V3d(  0.1,  0.1,  0.1 ) ) );

        for (size_t i = 1; i < 5 ; ++i)
        {
            asamp.addOp( scaleop, V3d( 2 * ( i + 1 ),
                                       1.0, 2.0 ) );

            shearmat.x[1][0] = (double)i;
            shearmat.x[2][0] = (double)( (int)i * -1.0 );
            shearmat.x[2][1] = 0.0;

            asamp.addOp( shearmatrixop, shearmat );

            asamp.addOp( rotop, V3d( 1.0, 0.0, 0.0 ),
                         1.57 );
            asamp.addOp( rotop, V3d( 0.0, 1.0, 0.0 ),
                         0.125 * ( i + 1 ) );
            asamp.addOp( rotorientop, V3d( 0.0, 0.0, 1.0 ),
                         0.1 * ( i + 1 ) );

            asamp.addOp( transpivotop, V3d( 0.0, 3.0 * i, 4.0 * i ) );

            a.getSchema().set( asamp );
            double iVal = static_cast< double >( i );
            bnds.set( Box3d( V3d( -iVal, -iVal, -iVal ),
                             V3d(  iVal,  iVal,  iVal ) ) );
        }

    }

    {
        IArchive archive( Alembic::AbcCoreOgawa::ReadArchive(), name );

        IXform a( IObject( archive, kTop ), "a" );
        IBox3dProperty bnds = GetIArchiveBounds( archive );

        XformSample asamp;

        a.getSchema().get( asamp );

        TESTING_ASSERT( a.getSchema().getNumOps() == 6 );

        TESTING_ASSERT( asamp[0].isScaleOp() );
        TESTING_ASSERT( asamp[0].getHint() == kScaleHint );

        TESTING_ASSERT( asamp[1].isMatrixOp() );
        TESTING_ASSERT( asamp[1].getHint() == kMayaShearHint );

        TESTING_ASSERT( asamp[2].isRotateOp() );
        TESTING_ASSERT( asamp[2].getHint() == kRotateHint );

        TESTING_ASSERT( asamp[3].getType() == kRotateOperation );
        TESTING_ASSERT( asamp[3].getHint() == kRotateHint );

        TESTING_ASSERT( asamp[4].getType() == kRotateOperation );
        TESTING_ASSERT( asamp[4].getHint() == kRotateOrientationHint );

        TESTING_ASSERT( asamp[5].getType() == kTranslateOperation );
        TESTING_ASSERT( asamp[5].getHint() == kRotatePivotPointHint );

        TESTING_ASSERT( asamp[0].isXAnimated() );
        TESTING_ASSERT( !asamp[0].isYAnimated() );
        TESTING_ASSERT( !asamp[0].isZAnimated() );

        TESTING_ASSERT( !asamp[1].isChannelAnimated(0) );  // [0][0]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(1) );  // [0][1]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(2) );  // [0][2]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(3) );  // [0][3]
        TESTING_ASSERT( asamp[1].isChannelAnimated(4) );   // [1][0]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(5) );  // [1][1]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(6) );  // [1][2]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(7) );  // [1][3]
        TESTING_ASSERT( asamp[1].isChannelAnimated(8) );   // [2][0]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(9) );  // [2][1]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(10) ); // [2][2]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(11) ); // [2][3]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(12) ); // [3][0]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(13) ); // [3][1]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(14) ); // [3][2]
        TESTING_ASSERT( !asamp[1].isChannelAnimated(15) ); // [3][3]

        TESTING_ASSERT( !asamp[2].isXAnimated() );
        TESTING_ASSERT( !asamp[2].isYAnimated() );
        TESTING_ASSERT( !asamp[2].isZAnimated() );
        TESTING_ASSERT( !asamp[2].isAngleAnimated() );

        TESTING_ASSERT( !asamp[3].isXAnimated() );
        TESTING_ASSERT( !asamp[3].isYAnimated() );
        TESTING_ASSERT( !asamp[3].isZAnimated() );
        TESTING_ASSERT( asamp[3].isAngleAnimated() );

        TESTING_ASSERT( !asamp[4].isXAnimated() );
        TESTING_ASSERT( !asamp[4].isYAnimated() );
        TESTING_ASSERT( !asamp[4].isZAnimated() );
        TESTING_ASSERT( asamp[4].isAngleAnimated() );

        TESTING_ASSERT( !asamp[5].isXAnimated() );
        TESTING_ASSERT( asamp[5].isYAnimated() );
        TESTING_ASSERT( asamp[5].isZAnimated() );

        // OK, now check the values came through
        M44d shearmat;
        shearmat.makeIdentity();

        TESTING_ASSERT( asamp[0].getScale() == V3d( 2.0, 1.0, 2.0 ) );

        TESTING_ASSERT( asamp[1].getMatrix() == shearmat );

        TESTING_ASSERT( asamp[2].getAxis() == V3d( 1.0, 0.0, 0.0 ) );
        TESTING_ASSERT( almostEqual( asamp[2].getAngle(), 1.57 ) );

        TESTING_ASSERT( asamp[3].getAxis() == V3d( 0.0, 1.0, 0.0 ) );
        TESTING_ASSERT( almostEqual( asamp[3].getAngle(), 0.125 ) );

        TESTING_ASSERT( asamp[4].getAxis() == V3d( 0.0, 0.0, 1.0 ) );
        TESTING_ASSERT( almostEqual( asamp[4].getAngle(), 0.1 ) );

        TESTING_ASSERT( asamp[5].getTranslate() == V3d( 0.0, 0.0, 0.0 ) );

        TESTING_ASSERT( bnds.getValue() == Box3d( V3d( -0.1, -0.1, -0.1 ),
                                                  V3d(  0.1,  0.1,  0.1 ) ) );

        for ( index_t i = 1; i < 5 ; ++i )
        {
            a.getSchema().get( asamp, ISampleSelector( i ) );

            TESTING_ASSERT( asamp[0].getScale()
                            == V3d( 2 * ( i + 1 ), 1.0, 2.0 ) );

            shearmat.x[1][0] = (double)i;
            shearmat.x[2][0] = (double)( (int)i * -1.0 );
            shearmat.x[2][1] = 0.0;

            TESTING_ASSERT( asamp[1].getMatrix() == shearmat );

            TESTING_ASSERT( asamp[2].getAxis() == V3d( 1.0, 0.0, 0.0 ) );
            TESTING_ASSERT( almostEqual( asamp[2].getAngle(), 1.57 ) );

            TESTING_ASSERT( asamp[3].getAxis() == V3d( 0.0, 1.0, 0.0 ) );
            TESTING_ASSERT( almostEqual( asamp[3].getAngle(),
                                         0.125 * ( i + 1 ) ) );

            TESTING_ASSERT( asamp[4].getAxis() == V3d( 0.0, 0.0, 1.0 ) );
            TESTING_ASSERT( almostEqual( asamp[4].getAngle(),
                                         0.1 * ( i + 1 ) ) );

            V3d tvec( 0.0, 3.0 * i, 4.0 * i );

            TESTING_ASSERT( tvec.equalWithAbsError( asamp[5].getTranslate(),
                                                    VAL_EPSILON ) );
            Box3d b = bnds.getValue( ISampleSelector( i ) );
            double iVal = static_cast< double >( i );
            TESTING_ASSERT( b == Box3d( V3d( -iVal, -iVal, -iVal ),
                                        V3d(  iVal,  iVal,  iVal ) ) );
        }

        std::cout << "tested all xforms in " << name << std::endl;
    }
}
//-*****************************************************************************
void xformIn()
{
    IArchive archive( Alembic::AbcCoreOgawa::ReadArchive(), "Xform1.abc" );

    Abc::M44d identity;
    XformSample xs;

    IXform a( IObject( archive, kTop ), "a" );
    std::cout << "'a' num samples: " << a.getSchema().getNumSamples() << std::endl;

    TESTING_ASSERT( a.getSchema().getNumOps() == 1 );
    TESTING_ASSERT( a.getSchema().getInheritsXforms() );
    for ( index_t i = 0; i < 20; ++i )
    {
        XformSample xs;
        a.getSchema().get( xs, Abc::ISampleSelector( i ) );
        TESTING_ASSERT( xs.getNumOps() == 1 );
        TESTING_ASSERT( xs[0].isTranslateOp() );
        TESTING_ASSERT( xs[0].isYAnimated() == true );
        TESTING_ASSERT( xs[0].isXAnimated() == false );
        TESTING_ASSERT( xs[0].isZAnimated() == false );

        TESTING_ASSERT( xs.getTranslation() == V3d( 12.0, i+42.0, 20.0 ) );
        TESTING_ASSERT( xs.getMatrix() ==
                        Abc::M44d().setTranslation( V3d(12.0, i+42.0, 20.0)) );
    }

    IXform b( a, "b" );
    b.getSchema().get( xs );
    TESTING_ASSERT( b.getSchema().getTimeSampling()->getTimeSamplingType().isUniform() );
    // the schema is not static, because set() was called 20 times on it.
    TESTING_ASSERT( !b.getSchema().isConstant() );
    TESTING_ASSERT( b.getSchema().getNumSamples() == 20 );
    TESTING_ASSERT( xs.getNumOps() == 0 );
    TESTING_ASSERT( b.getSchema().getNumOps() == 0 );
    TESTING_ASSERT( xs.getMatrix() == identity );
    for (size_t i = 0; i < 20; ++i)
    {
        AbcA::index_t j = i;
        TESTING_ASSERT( b.getSchema().getInheritsXforms( ISampleSelector( j ) )
                        == (i&1) );
    }

    IXform c( b, "c" );
    xs = c.getSchema().getValue();
    TESTING_ASSERT( xs.getNumOps() == 0 );
    TESTING_ASSERT( c.getSchema().getNumOps() == 0 );
    TESTING_ASSERT( xs.getMatrix() == identity );
    TESTING_ASSERT( c.getSchema().getInheritsXforms() );
    TESTING_ASSERT( c.getSchema().isConstantIdentity() );


    IXform d( c, "d" );
    xs = d.getSchema().getValue();
    TESTING_ASSERT( xs.getNumOps() == 1 );
    TESTING_ASSERT( d.getSchema().getNumOps() == 1 );
    TESTING_ASSERT( xs[0].isScaleOp() );
    TESTING_ASSERT( ! ( xs[0].isXAnimated() || xs[0].isYAnimated()
                        || xs[0].isZAnimated() ) );
    TESTING_ASSERT( xs.getScale().equalWithAbsError( V3d( 3.0, 6.0, 9.0 ),
                                                     VAL_EPSILON ) );
    TESTING_ASSERT( xs.getMatrix() ==
                    Abc::M44d().setScale( V3d(3.0, 6.0, 9.0)) );
    TESTING_ASSERT( d.getSchema().getInheritsXforms() );

    IXform e( d, "e" );
    TESTING_ASSERT( e.getSchema().isConstantIdentity() );
    TESTING_ASSERT( e.getSchema().isConstant() );
    TESTING_ASSERT( e.getSchema().getNumOps() == 3 );

    IXform f( e, "f" );
    TESTING_ASSERT( f.getSchema().isConstant() ); // is constant
    TESTING_ASSERT( ! f.getSchema().isConstantIdentity() ); // not identity

    IXform g( f, "g" );
    Abc::M44d gmatrix;
    gmatrix.makeIdentity();
    XformSample gsamp = g.getSchema().getValue();
    TESTING_ASSERT( gsamp.getNumOps() == 20 );
    TESTING_ASSERT( gsamp.getNumOpChannels() == 20 * 16 );
    TESTING_ASSERT( g.getSchema().getNumSamples() == 1 );
    TESTING_ASSERT( g.getSchema().isConstant() );
    TESTING_ASSERT( !g.getSchema().isConstantIdentity() );
    for ( size_t i = 0 ; i < 20 ; ++i )
    {
        TESTING_ASSERT( gsamp[i].getChannelValue( 1 ) == (double)i );
    }

    std::cout << "Tested all xforms in first test!" << std::endl;

}