//-***************************************************************************** double XformOp::getZRotation() const { ABCA_ASSERT( m_type == kRotateOperation || m_type == kRotateZOperation, "Meaningless to get rotation angle from non-rotation op." ); if ( m_type == kRotateZOperation ) { return m_channels[0]; } else { Abc::M44d m; Abc::V3d rot; m.makeIdentity(); m.setAxisAngle( this->getVector(), DegreesToRadians( m_channels[3] ) ); Imath::extractEulerXYZ( m, rot ); return RadiansToDegrees( rot[2] ); } }
//-***************************************************************************** Abc::M44d XformSample::getMatrix() const { Abc::M44d ret; ret.makeIdentity(); for ( std::size_t i = 0 ; i < m_ops.size() ; ++i ) { Abc::M44d m; m.makeIdentity(); XformOp op = m_ops[i]; XformOperationType otype = op.getType(); if ( otype == kMatrixOperation ) { for ( std::size_t j = 0 ; j < 4 ; ++j ) { for ( std::size_t k = 0 ; k < 4 ; ++k ) { m.x[j][k] = op.getChannelValue( ( 4 * j ) + k ); } } } else if ( otype == kRotateXOperation ) { m.setAxisAngle( Abc::V3d( 1.0, 0.0, 0.0 ), DegreesToRadians( op.getChannelValue( 0 ) ) ); } else if ( otype == kRotateYOperation ) { m.setAxisAngle( Abc::V3d( 0.0, 1.0, 0.0 ), DegreesToRadians( op.getChannelValue( 0 ) ) ); } else if ( otype == kRotateZOperation ) { m.setAxisAngle( Abc::V3d( 0.0, 0.0, 1.0 ), DegreesToRadians( op.getChannelValue( 0 ) ) ); } else { Abc::V3d vec( op.getChannelValue( 0 ), op.getChannelValue( 1 ), op.getChannelValue( 2 ) ); if ( otype == kScaleOperation ) { m.setScale( vec ); } else if ( otype == kTranslateOperation ) { m.setTranslation( vec ); } else if ( otype == kRotateOperation ) { m.setAxisAngle( vec, DegreesToRadians( op.getChannelValue( 3 ) ) ); } } ret = m * ret; } return ret; }
//-***************************************************************************** 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 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; }