//-***************************************************************************** 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 ); } } }
//-***************************************************************************** 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 ); } }
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; }
//-***************************************************************************** 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; }
//-***************************************************************************** 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; } }