예제 #1
0
//-*****************************************************************************
void ReadParticles( const std::string &iFileName )
{
    IArchive archive( Alembic::AbcCoreOgawa::ReadArchive(),
                      iFileName );
    IObject topObj( archive, kTop );

    IPoints points( topObj, "simpleParticles" );
    IPointsSchema& pointsSchema = points.getSchema();

    index_t numSamps = pointsSchema.getNumSamples();
    std::cout << "\n\nReading points back in. Num frames: "
              << numSamps << std::endl;

    IV3fArrayProperty velProp( pointsSchema, "velocity" );
    IC3fArrayProperty rgbProp( pointsSchema, "Cs" );
    IFloatArrayProperty ageProp( pointsSchema, "age" );

    for ( index_t samp = 0; samp < numSamps; ++samp )
    {
        IPointsSchema::Sample psamp;
        pointsSchema.get( psamp, samp );

        Box3f bounds;
        bounds.makeEmpty();
        size_t numPoints = psamp.getPositions()->size();
        for ( size_t p = 0; p < numPoints; ++p )
        {
            bounds.extendBy( (*(psamp.getPositions()))[p] );
        }
        std::cout << "Sample: " << samp << ", numPoints: " << numPoints
                  << ", bounds: " << bounds.min
                  << " to " << bounds.max << std::endl;
    }
}
예제 #2
0
//-*****************************************************************************
void ProcessPoints( IPoints &points, ProcArgs &args )
{
    IPointsSchema &ps = points.getSchema();
    TimeSamplingPtr ts = ps.getTimeSampling();
    
    SampleTimeSet sampleTimes;
    
    //for now, punt on the changing point count case -- even for frame ranges
    //for which the point count isn't changing
    
    if ( ps.getIdsProperty().isConstant() )
    {
        //grab only the current time
        sampleTimes.insert( args.frame / args.fps );
    }
    else
    {
         GetRelevantSampleTimes( args, ts, ps.getNumSamples(), sampleTimes );
    }
    
    
    bool multiSample = sampleTimes.size() > 1;
    
    if ( multiSample ) { WriteMotionBegin( args, sampleTimes ); }
    
    for ( SampleTimeSet::iterator iter = sampleTimes.begin();
          iter != sampleTimes.end(); ++iter )
    {
        ISampleSelector sampleSelector( *iter );
        
        IPointsSchema::Sample sample = ps.getValue( sampleSelector );
        
        
        ParamListBuilder paramListBuilder;
        paramListBuilder.add( "P", (RtPointer)sample.getPositions()->get() );
        
        ICompoundProperty arbGeomParams = ps.getArbGeomParams();
        AddArbitraryGeomParams( arbGeomParams,
                    sampleSelector, paramListBuilder );
        
        RiPointsV(sample.getPositions()->size(),
                paramListBuilder.n(),
                paramListBuilder.nms(),
                paramListBuilder.vals() );
    }
    
    if ( multiSample ) { RiMotionEnd(); }
    
}
예제 #3
0
//-*****************************************************************************
void IPointsDrw::setTime( chrono_t iSeconds )
{
    IObjectDrw::setTime( iSeconds );
    if ( !valid() )
    {
        return;
    }

    // Use nearest for now.
    ISampleSelector ss( iSeconds, ISampleSelector::kNearIndex );
    IPointsSchema::Sample psamp;
    m_points.getSchema().get( psamp, ss );
    m_positions = psamp.getPositions();

    // Update bounds from positions
    m_bounds.makeEmpty();
    if ( m_positions )
    {
        size_t numPoints = m_positions->size();
        for ( size_t p = 0; p < numPoints; ++p )
        {
            m_bounds.extendBy( (*m_positions)[p] );
        }
    }

    // If we have a color prop, update it
    if ( m_colorProp )
    {
        m_colors = m_colorProp.getValue( ss );
    }

    if ( m_normalProp )
    {
        m_normals = m_normalProp.getValue( ss );
    }
}
예제 #4
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);
    }

}
예제 #5
0
void pointTestReadWrite()
{
    {
        OArchive archive( Alembic::AbcCoreOgawa::WriteArchive(),
            "particlesOut2.abc" );
        OObject topObj( archive, kTop );
        OPoints ptsObj(topObj, "somePoints");

        std::vector< V3f > positions;
        std::vector< V3f > velocities;
        std::vector< Alembic::Util::uint64_t > ids;
        std::vector< Alembic::Util::float32_t > widths;
        for (int i = 0; i < 100; ++i)
        {
            OFloatGeomParam::Sample widthSamp;
            widthSamp.setScope(kVertexScope);
            widthSamp.setVals(FloatArraySample(widths));

            OPointsSchema::Sample psamp(V3fArraySample( positions ),
                UInt64ArraySample( ids ), V3fArraySample( velocities ),
                widthSamp );

            ptsObj.getSchema().set(psamp);

            positions.push_back(V3f(i, i, i));
            velocities.push_back(V3f(100.0-i, 0, 0));
            ids.push_back(i*10);
            widths.push_back(0.1 + i * 0.05);
        }
    }

    {
        IArchive archive( Alembic::AbcCoreOgawa::ReadArchive(),
                          "particlesOut2.abc" );

        IObject topObj = archive.getTop();
        IPoints points( topObj, "somePoints" );
        IPointsSchema& pointsSchema = points.getSchema();
        IFloatGeomParam widthProp = pointsSchema.getWidthsParam();
        TESTING_ASSERT( widthProp.getScope() == kVertexScope );
        for ( size_t i = 0; i < 100; ++i )
        {
            IPointsSchema::Sample pointSamp;
            pointsSchema.get(pointSamp, i);

            IFloatGeomParam::Sample widthSamp;
            widthProp.getExpanded(widthSamp, i);
            TESTING_ASSERT( pointSamp.getPositions()->size() == i );
            TESTING_ASSERT( pointSamp.getVelocities()->size() == i );
            TESTING_ASSERT( pointSamp.getIds()->size() == i );
            TESTING_ASSERT( widthSamp.getVals()->size() == i );
            for ( size_t j = 0; j < i; ++j )
            {
                TESTING_ASSERT( (*pointSamp.getPositions())[j] ==
                                V3f(j, j, j) );

                TESTING_ASSERT( (*pointSamp.getVelocities())[j] ==
                                V3f(100-j, 0, 0) );

                TESTING_ASSERT( (*pointSamp.getIds())[j] == j * 10 );

                TESTING_ASSERT( almostEqual( (*widthSamp.getVals())[j],
                                0.1 + j * 0.05, 7 ) );
            }
        }
    }
}