Ejemplo n.º 1
0
//-*****************************************************************************
void OFaceSetSchema::set( const Sample &iSamp )
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OFaceSetSchema::set()" );

    // We could add sample integrity checking here.
    if ( m_facesProperty.getNumSamples () == 0 )
    {
        // First sample must provide faces
        ABCA_ASSERT( iSamp.getFaces() ,
                     "Sample 0 must provide the faces that make up the faceset." );
        m_facesProperty.set( iSamp.getFaces() );
    }
    else
    {
        SetPropUsePrevIfNull( m_facesProperty, iSamp.getFaces() );
    }

    // We've now set the sample for the m_faces property.
    if ( iSamp.getSelfBounds().hasVolume() )
    {
        // Caller explicity set bounds for this sample of the faceset.
        m_selfBoundsProperty.set( iSamp.getSelfBounds() );
    }
    else
    {
        m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        // NYI compute self bounds via parent mesh's faces
    }

    if (m_facesExclusive != kFaceSetNonExclusive)
    {
        // The user has changed the exclusivity hint from the
        // default so we'll create a property now and store.
        _recordExclusivityHint();
    }
    ALEMBIC_ABC_SAFE_CALL_END();
}
Ejemplo n.º 2
0
//-*****************************************************************************
void OCurvesSchema::set( const OCurvesSchema::Sample &iSamp )
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OCurvesSchema::set()" );

    Alembic::Util::uint8_t basisAndType[4];
    basisAndType[0] = iSamp.getType();
    basisAndType[1] = iSamp.getWrap();
    basisAndType[2] = iSamp.getBasis();

    // repeat so we don't have to change the data layout and bump up
    // the version number
    basisAndType[3] = basisAndType[2];

    // do we need to create velocities prop?
    if ( iSamp.getVelocities() && !m_velocitiesProperty )
    {
        m_velocitiesProperty = Abc::OV3fArrayProperty( this->getPtr(),
            ".velocities", m_positionsProperty.getTimeSampling() );

        std::vector<V3f> emptyVec;
        const V3fArraySample empty(emptyVec);
        const size_t numSamps = m_positionsProperty.getNumSamples();
        for ( size_t i = 0 ; i < numSamps ; ++i )
        {
            m_velocitiesProperty.set( empty );
        }
    }

    // do we need to create uvs?
    if ( iSamp.getUVs() && !m_uvsParam )
    {
        std::vector<V2f> emptyVals;
        std::vector<Util::uint32_t> emptyIndices;

        OV2fGeomParam::Sample empty;

        if ( iSamp.getUVs().getIndices() )
        {
            empty = OV2fGeomParam::Sample( Abc::V2fArraySample( emptyVals ),
                Abc::UInt32ArraySample( emptyIndices ),
                iSamp.getUVs().getScope() );

            // UVs are indexed
            m_uvsParam = OV2fGeomParam( this->getPtr(), "uv", true,
                                        empty.getScope(), 1,
                                        this->getTimeSampling() );
        }
        else
        {
            empty = OV2fGeomParam::Sample( Abc::V2fArraySample( emptyVals ),
                                           iSamp.getUVs().getScope() );

            // UVs are not indexed
            m_uvsParam = OV2fGeomParam( this->getPtr(), "uv", false,
                                   empty.getScope(), 1,
                                   this->getTimeSampling() );
        }

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_uvsParam.set( empty );
        }
    }

    // do we need to create normals?
    if ( iSamp.getNormals() && !m_normalsParam )
    {
        std::vector<V3f> emptyVals;
        std::vector<Util::uint32_t> emptyIndices;

        ON3fGeomParam::Sample empty;

        if ( iSamp.getNormals().getIndices() )
        {
            empty = ON3fGeomParam::Sample( Abc::V3fArraySample( emptyVals ),
                Abc::UInt32ArraySample( emptyIndices ),
                iSamp.getNormals().getScope() );

            // normals are indexed
            m_normalsParam = ON3fGeomParam( this->getPtr(), "N", true,
                empty.getScope(), 1, this->getTimeSampling() );
        }
        else
        {
            empty = ON3fGeomParam::Sample( Abc::V3fArraySample( emptyVals ),
                                           iSamp.getNormals().getScope() );

            // normals are not indexed
            m_normalsParam = ON3fGeomParam( this->getPtr(), "N", false,
                                        empty.getScope(), 1,
                                        this->getTimeSampling() );
        }

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_normalsParam.set( empty );
        }
    }

    // do we need to create widths?
    if ( iSamp.getWidths().getVals() && !m_widthsParam )
    {
        std::vector<float> emptyVals;
        std::vector<Util::uint32_t> emptyIndices;
        OFloatGeomParam::Sample empty;

        if ( iSamp.getWidths().getIndices() )
        {
            empty = OFloatGeomParam::Sample( Abc::FloatArraySample( emptyVals ),
                Abc::UInt32ArraySample( emptyIndices ),
                iSamp.getWidths().getScope() );

            // widths are indexed for some weird reason which is
            // technically ok, just wasteful
            m_widthsParam = OFloatGeomParam( this->getPtr(), "width", true,
                                             iSamp.getWidths().getScope(),
                                             1, this->getTimeSampling() );
        }
        else
        {
            empty = OFloatGeomParam::Sample( Abc::FloatArraySample( emptyVals ),
                                             iSamp.getWidths().getScope() );

            // widths are not indexed
            m_widthsParam = OFloatGeomParam( this->getPtr(), "width", false,
                                             iSamp.getWidths().getScope(), 1,
                                             this->getTimeSampling() );
        }

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_widthsParam.set( empty );
        }
    }

    if ( iSamp.getPositionWeights() && !m_positionWeightsProperty)
    {
        m_positionWeightsProperty = Abc::OFloatArrayProperty( *this, "w",
            this->getTimeSampling() );

        std::vector<float> emptyVec;
        Alembic::Abc::FloatArraySample emptySamp( emptyVec );

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_positionWeightsProperty.set( emptySamp );
        }
    }

    if ( iSamp.getOrders() && !m_ordersProperty)
    {
        m_ordersProperty = Abc::OUcharArrayProperty( *this, ".orders",
                                                     this->getTimeSampling() );

        std::vector<uint8_t> emptyVec;
        Alembic::Abc::UcharArraySample emptySamp( emptyVec );

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_ordersProperty.set( emptySamp );
        }
    }

    if ( iSamp.getKnots() && !m_knotsProperty)
    {
        m_knotsProperty = Abc::OFloatArrayProperty( *this, ".knots",
            this->getTimeSampling() );

        std::vector<float> emptyVec;
        Alembic::Abc::FloatArraySample emptySamp( emptyVec );

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_knotsProperty.set( emptySamp );
        }
    }

    // We could add sample integrity checking here.
    if ( m_positionsProperty.getNumSamples() == 0 )
    {
        // First sample must be valid on all points.
        ABCA_ASSERT( iSamp.getPositions(),
                     "Sample 0 must have valid data for all mesh components" );

        m_positionsProperty.set( iSamp.getPositions() );
        m_nVerticesProperty.set( iSamp.getCurvesNumVertices() );

        m_basisAndTypeProperty.set( basisAndType );

        if ( m_velocitiesProperty )
        { m_velocitiesProperty.set( iSamp.getVelocities() ); }

        if ( iSamp.getSelfBounds().isEmpty() )
        {
            // OTypedScalarProperty::set() is not referentially transparent,
            // so we need a a placeholder variable.
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() )
                           );

            m_selfBoundsProperty.set( bnds );

        }
        else { m_selfBoundsProperty.set( iSamp.getSelfBounds() ); }

        // process uvs
        if ( iSamp.getUVs() )
        {
            m_uvsParam.set( iSamp.getUVs() );
        }

        // process normals
        if ( iSamp.getNormals() )
        {
            m_normalsParam.set( iSamp.getNormals() );
        }

        // process widths
        if ( iSamp.getWidths() )
        {
            m_widthsParam.set( iSamp.getWidths() );
        }

        // process position weights
        if ( iSamp.getPositionWeights() )
        {
            m_positionWeightsProperty.set( iSamp.getPositionWeights() );
        }

        // process orders
        if ( iSamp.getOrders() )
        {
            m_ordersProperty.set( iSamp.getOrders() );
        }

        // process knots
        if ( iSamp.getKnots() )
        {
            m_knotsProperty.set( iSamp.getKnots() );
        }
    }
    else
    {
        SetPropUsePrevIfNull( m_positionsProperty, iSamp.getPositions() );
        SetPropUsePrevIfNull( m_nVerticesProperty, iSamp.getCurvesNumVertices() );

        // if number of vertices were specified, then the basis and type
        // was specified
        if ( m_nVerticesProperty )
        {
            m_basisAndTypeProperty.set( basisAndType );
        }
        else
        {
            m_basisAndTypeProperty.setFromPrevious();
        }

        if ( m_velocitiesProperty )
        { SetPropUsePrevIfNull( m_velocitiesProperty, iSamp.getVelocities() ); }

        if ( m_uvsParam )
        { m_uvsParam.set( iSamp.getUVs() ); }

        if ( m_normalsParam )
        { m_normalsParam.set( iSamp.getNormals() ); }

        if ( m_widthsParam )
        { m_widthsParam.set( iSamp.getWidths() ); }

        if ( m_positionWeightsProperty )
        {
            SetPropUsePrevIfNull( m_positionWeightsProperty,
                                  iSamp.getPositionWeights() );
        }

        if ( m_ordersProperty )
        {
            SetPropUsePrevIfNull( m_ordersProperty, iSamp.getOrders() );
        }

        if ( m_knotsProperty )
        {
            SetPropUsePrevIfNull( m_knotsProperty, iSamp.getKnots() );
        }

        // update bounds
        if ( iSamp.getSelfBounds().hasVolume() )
        {
            m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        }
        else if ( iSamp.getPositions() )
        {
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() )
                           );
            m_selfBoundsProperty.set( bnds );
        }
        else
        {
            m_selfBoundsProperty.setFromPrevious();
        }
    }

    ALEMBIC_ABC_SAFE_CALL_END();
}
//-*****************************************************************************
void OCurvesSchema::set( const OCurvesSchema::Sample &iSamp )
{
    if( m_selectiveExport || iSamp.isPartialSample() )
    {
        selectiveSet( iSamp );
        return;
    }

    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OCurvesSchema::set()" );

    Alembic::Util::uint8_t basisAndType[4];
    calcBasisAndType( basisAndType, iSamp );

    if ( iSamp.getVelocities() && !m_velocitiesProperty )
    {
        createVelocityProperty();
    }

    if ( iSamp.getUVs() && !m_uvsParam )
    {
        createUVsProperty( iSamp );
    }

    if ( iSamp.getNormals() && !m_normalsParam )
    {
        createNormalsProperty( iSamp );
    }

    if ( iSamp.getWidths().getVals() && !m_widthsParam )
    {
        createWidthProperty( iSamp );
    }

    if ( iSamp.getPositionWeights() && !m_positionWeightsProperty)
    {
        createPositionWeightsProperty();
    }

    if ( iSamp.getOrders() && !m_ordersProperty)
    {
        createOrdersProperty();
    }

    if ( iSamp.getKnots() && !m_knotsProperty)
    {
        createKnotsProperty();
    }

    // We could add sample integrity checking here.
    if ( m_numSamples == 0 )
    {
        // First sample must be valid on all points.
        ABCA_ASSERT( iSamp.getPositions(),
                     "Sample 0 must have valid data for all mesh components" );

        m_positionsProperty.set( iSamp.getPositions() );
        m_nVerticesProperty.set( iSamp.getCurvesNumVertices() );

        m_basisAndTypeProperty.set( basisAndType );

        if ( m_velocitiesProperty )
        { m_velocitiesProperty.set( iSamp.getVelocities() ); }

        if ( iSamp.getSelfBounds().isEmpty() )
        {
            // OTypedScalarProperty::set() is not referentially transparent,
            // so we need a a placeholder variable.
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() )
                           );

            m_selfBoundsProperty.set( bnds );

        }
        else { m_selfBoundsProperty.set( iSamp.getSelfBounds() ); }

        // process uvs
        if ( iSamp.getUVs() )
        {
            m_uvsParam.set( iSamp.getUVs() );
        }

        // process normals
        if ( iSamp.getNormals() )
        {
            m_normalsParam.set( iSamp.getNormals() );
        }

        // process widths
        if ( iSamp.getWidths() )
        {
            m_widthsParam.set( iSamp.getWidths() );
        }

        // process position weights
        if ( iSamp.getPositionWeights() )
        {
            m_positionWeightsProperty.set( iSamp.getPositionWeights() );
        }

        // process orders
        if ( iSamp.getOrders() )
        {
            m_ordersProperty.set( iSamp.getOrders() );
        }

        // process knots
        if ( iSamp.getKnots() )
        {
            m_knotsProperty.set( iSamp.getKnots() );
        }
    }
    else
    {
        SetPropUsePrevIfNull( m_positionsProperty, iSamp.getPositions() );
        SetPropUsePrevIfNull( m_nVerticesProperty, iSamp.getCurvesNumVertices() );

        // if number of vertices were specified, then the basis and type
        // was specified
        if ( m_nVerticesProperty )
        {
            m_basisAndTypeProperty.set( basisAndType );
        }
        else
        {
            m_basisAndTypeProperty.setFromPrevious();
        }

        if ( m_velocitiesProperty )
        { SetPropUsePrevIfNull( m_velocitiesProperty, iSamp.getVelocities() ); }

        if ( m_uvsParam )
        { m_uvsParam.set( iSamp.getUVs() ); }

        if ( m_normalsParam )
        { m_normalsParam.set( iSamp.getNormals() ); }

        if ( m_widthsParam )
        { m_widthsParam.set( iSamp.getWidths() ); }

        if ( m_positionWeightsProperty )
        {
            SetPropUsePrevIfNull( m_positionWeightsProperty,
                                  iSamp.getPositionWeights() );
        }

        if ( m_ordersProperty )
        {
            SetPropUsePrevIfNull( m_ordersProperty, iSamp.getOrders() );
        }

        if ( m_knotsProperty )
        {
            SetPropUsePrevIfNull( m_knotsProperty, iSamp.getKnots() );
        }

        // update bounds
        if ( iSamp.getSelfBounds().hasVolume() )
        {
            m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        }
        else if ( iSamp.getPositions() )
        {
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() )
                           );
            m_selfBoundsProperty.set( bnds );
        }
        else
        {
            m_selfBoundsProperty.setFromPrevious();
        }
    }

    m_numSamples++;

    ALEMBIC_ABC_SAFE_CALL_END();
}
//-*****************************************************************************
void OCurvesSchema::selectiveSet( const OCurvesSchema::Sample &iSamp )
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OCurvesSchema::selectiveSet()" );

    Alembic::Util::uint8_t basisAndType[4];
    calcBasisAndType( basisAndType, iSamp );

    if ( iSamp.getPositions() && !m_positionsProperty )
    {
        createPositionProperty();
    }

    if ( m_positionsProperty )
    {
        SetPropUsePrevIfNull( m_positionsProperty, iSamp.getPositions() );

        if ( iSamp.getSelfBounds().hasVolume() )
        {
            m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        }
        else if ( iSamp.getPositions() )
        {
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() ) );
            m_selfBoundsProperty.set( bnds );
        }
        else
        {
            m_selfBoundsProperty.setFromPrevious();
        }
    }

    if( iSamp.getCurvesNumVertices() && !m_nVerticesProperty )
    {
        createVertexProperties();
    }

    if( m_nVerticesProperty )
    {
        SetPropUsePrevIfNull( m_nVerticesProperty, iSamp.getCurvesNumVertices() );
        m_basisAndTypeProperty.set( basisAndType );
    }

    if ( iSamp.getVelocities() && !m_velocitiesProperty )
    {
        createVelocityProperty();
    }

    if ( m_velocitiesProperty )
    {
        SetPropUsePrevIfNull( m_velocitiesProperty, iSamp.getVelocities() );
    }

    if ( iSamp.getUVs() && !m_uvsParam )
    {
        createUVsProperty( iSamp );
    }

    if ( m_uvsParam )
    {
        m_uvsParam.set( iSamp.getUVs() );
    }

    if ( iSamp.getNormals() && !m_normalsParam )
    {
        createNormalsProperty( iSamp );
    }

    if ( m_normalsParam )
    {
        m_normalsParam.set( iSamp.getNormals() );
    }

    if ( iSamp.getWidths().getVals() && !m_widthsParam )
    {
        createWidthProperty( iSamp );
    }

    if ( m_widthsParam )
    {
        m_widthsParam.set( iSamp.getWidths() );
    }

    if ( iSamp.getPositionWeights() && !m_positionWeightsProperty)
    {
        createPositionWeightsProperty();
    }

    if ( m_positionWeightsProperty )
    {
        SetPropUsePrevIfNull( m_positionWeightsProperty,
                              iSamp.getPositionWeights() );
    }

    if ( iSamp.getOrders() && !m_ordersProperty)
    {
        createOrdersProperty();
    }

    if ( m_ordersProperty )
    {
        SetPropUsePrevIfNull( m_ordersProperty, iSamp.getOrders() );
    }

    if ( iSamp.getKnots() && !m_knotsProperty)
    {
        createKnotsProperty();
    }

    if ( m_knotsProperty )
    {
        SetPropUsePrevIfNull( m_knotsProperty, iSamp.getKnots() );
    }

    m_numSamples++;

    ALEMBIC_ABC_SAFE_CALL_END();
}
Ejemplo n.º 5
0
//-*****************************************************************************
void OFaceSetSchema::set( const Sample &iSamp )
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OFaceSetSchema::set()" );

    Abc::Box3d emptyBox;
    emptyBox.makeEmpty();
    // do we need to create child bounds?
    if ( iSamp.getChildBounds().hasVolume() && !m_childBoundsProperty)
    {
        m_childBoundsProperty = Abc::OBox3dProperty( this->getPtr(), 
            ".childBnds", m_facesProperty.getTimeSampling() );

        // -1 because we just dis an m_positions set above
        size_t numSamples = m_facesProperty.getNumSamples() - 1;

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_childBoundsProperty.set( emptyBox );
        }
    }

    // We could add sample integrity checking here.
    if ( m_facesProperty.getNumSamples () == 0 )
    {
        // First sample must provide faces
        ABCA_ASSERT( iSamp.getFaces() ,
                     "Sample 0 must provide the faces that make up the faceset." );
        m_facesProperty.set( iSamp.getFaces() );

        if (m_childBoundsProperty)
        { 
            m_childBoundsProperty.set( iSamp.getChildBounds() ); 
        }
    }
    else
    {
        SetPropUsePrevIfNull( m_facesProperty, iSamp.getFaces() );

        if ( m_childBoundsProperty )
        {
            SetPropUsePrevIfNull( m_childBoundsProperty, 
                iSamp.getChildBounds() );
        }
    }

    // We've now set the sample for the m_faces property.
    if ( iSamp.getSelfBounds().hasVolume() )
    {
        // Caller explicity set bounds for this sample of the faceset.
        m_selfBoundsProperty.set( iSamp.getSelfBounds() );
    }
    else
    {
        m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        // NYI compute self bounds via parent mesh's faces
    }

    if (m_facesExclusive != kFaceSetNonExclusive)
    {
        // The user has changed the exclusivity hint from the
        // default so we'll create a property now and store.
        _recordExclusivityHint();
    }
    ALEMBIC_ABC_SAFE_CALL_END();
}
Ejemplo n.º 6
0
//-*****************************************************************************
void OPolyMeshSchema::set( const Sample &iSamp )
{
    ALEMBIC_ABC_SAFE_CALL_BEGIN( "OPolyMeshSchema::set()" );

    // do we need to create velocities prop?
    if ( iSamp.getVelocities() && !m_velocitiesProperty )
    {
        m_velocitiesProperty = Abc::OV3fArrayProperty( this->getPtr(),
            ".velocities", m_positionsProperty.getTimeSampling() );

        std::vector<V3f> emptyVec;
        const V3fArraySample empty( emptyVec );
        const size_t numSamps = m_positionsProperty.getNumSamples();
        for ( size_t i = 0 ; i < numSamps ; ++i )
        {
            m_velocitiesProperty.set( empty );
        }
    }

    // do we need to create uvs?
    if ( iSamp.getUVs() && !m_uvsParam )
    {
        std::vector<V2f> emptyVals;
        std::vector<Util::uint32_t> emptyIndices;

        OV2fGeomParam::Sample empty;
        AbcA::MetaData mdata;
        SetSourceName( mdata, m_uvSourceName );

        if ( iSamp.getUVs().getIndices() )
        {
            empty = OV2fGeomParam::Sample( Abc::V2fArraySample( emptyVals ),
                Abc::UInt32ArraySample( emptyIndices ),
                iSamp.getUVs().getScope() );

            // UVs are indexed
            m_uvsParam = OV2fGeomParam( this->getPtr(), "uv", true,
                                   empty.getScope(), 1,
                                   this->getTimeSampling(), mdata );
        }
        else
        {
            empty = OV2fGeomParam::Sample( Abc::V2fArraySample( emptyVals ),
                                           iSamp.getUVs().getScope() );

            // UVs are not indexed
            m_uvsParam = OV2fGeomParam( this->getPtr(), "uv", false,
                                   empty.getScope(), 1,
                                   this->getTimeSampling() , mdata );
        }

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_uvsParam.set( empty );
        }
    }

    // do we need to create normals?
    if ( iSamp.getNormals() && !m_normalsParam )
    {
        std::vector<V3f> emptyVals;
        std::vector<Util::uint32_t> emptyIndices;

        ON3fGeomParam::Sample empty;

        if ( iSamp.getNormals().getIndices() )
        {
            empty = ON3fGeomParam::Sample( Abc::V3fArraySample( emptyVals ),
                Abc::UInt32ArraySample( emptyIndices ),
                iSamp.getNormals().getScope() );

            // normals are indexed
            m_normalsParam = ON3fGeomParam( this->getPtr(), "N", true,
                empty.getScope(), 1, this->getTimeSampling() );
        }
        else
        {
            empty = ON3fGeomParam::Sample( Abc::V3fArraySample( emptyVals ),
                                           iSamp.getNormals().getScope() );

            // normals are not indexed
            m_normalsParam = ON3fGeomParam( this->getPtr(), "N", false,
                                        empty.getScope(), 1,
                                        this->getTimeSampling() );
        }

        size_t numSamples = m_positionsProperty.getNumSamples();

        // set all the missing samples
        for ( size_t i = 0; i < numSamples; ++i )
        {
            m_normalsParam.set( empty );
        }
    }

    // We could add sample integrity checking here.
    if ( m_positionsProperty.getNumSamples() == 0 )
    {
        // First sample must be valid on all points.
        ABCA_ASSERT( iSamp.getPositions() &&
                     iSamp.getFaceIndices() &&
                     iSamp.getFaceCounts(),
                     "Sample 0 must have valid data for all mesh components" );

        m_positionsProperty.set( iSamp.getPositions() );
        m_indicesProperty.set( iSamp.getFaceIndices() );
        m_countsProperty.set( iSamp.getFaceCounts() );

        if ( m_velocitiesProperty )
        { SetPropUsePrevIfNull( m_velocitiesProperty, iSamp.getVelocities() ); }

        if ( iSamp.getSelfBounds().isEmpty() )
        {
            // OTypedScalarProperty::set() is not referentially transparent,
            // so we need a a placeholder variable.
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() ) );
            m_selfBoundsProperty.set( bnds );
        }
        else { m_selfBoundsProperty.set( iSamp.getSelfBounds() ); }

        if ( iSamp.getUVs().getVals() )
        {
            m_uvsParam.set( iSamp.getUVs() );
        }
        if ( iSamp.getNormals().getVals() )
        {
            m_normalsParam.set( iSamp.getNormals() );
        }
    }
    else
    {
        SetPropUsePrevIfNull( m_positionsProperty, iSamp.getPositions() );
        SetPropUsePrevIfNull( m_indicesProperty, iSamp.getFaceIndices() );
        SetPropUsePrevIfNull( m_countsProperty, iSamp.getFaceCounts() );

        if ( m_velocitiesProperty )
        {
            SetPropUsePrevIfNull( m_velocitiesProperty, iSamp.getVelocities() );
        }

        if ( iSamp.getSelfBounds().hasVolume() )
        {
            m_selfBoundsProperty.set( iSamp.getSelfBounds() );
        }
        else if ( iSamp.getPositions() )
        {
            Abc::Box3d bnds(
                ComputeBoundsFromPositions( iSamp.getPositions() ) );
            m_selfBoundsProperty.set( bnds );
        }
        else
        {
            m_selfBoundsProperty.setFromPrevious();
        }

        // OGeomParam will automatically use SetPropUsePrevIfNull internally
        if ( m_uvsParam ) { m_uvsParam.set( iSamp.getUVs() ); }
        if ( m_normalsParam ) { m_normalsParam.set( iSamp.getNormals() ); }
    }

    ALEMBIC_ABC_SAFE_CALL_END();
}