Skip to content

[BUG] resampleToMatch is not translation invariant for level-sets #1992

Open
@andrewerf

Description

@andrewerf

Environment

Operating System: Arch Linux
OpenVDB Version: 11.0.0-6

Describe the bug

When we have a translated grid, resampleToMatch produces significantly different (worse) result compared to the original grid.

To Reproduce

Run the MRE with the given input grid.

#define IMATH_HALF_NO_LOOKUP_TABLE
#include <openvdb/openvdb.h>
#include <openvdb/version.h>
#include <openvdb/tools/GridTransformer.h>
#include <openvdb/io/Stream.h>
#include <fstream>


auto transform( openvdb::FloatGrid& sourceGrid )
{
    openvdb::Mat4R trMat;
    trMat.setToTranslation( openvdb::math::Vec3d{ 10.0, 10.0, 10.0 } );
    auto tr = sourceGrid.transform().copy();
    tr->postMult( trMat );

    openvdb::FloatGrid::Ptr targetGrid = openvdb::FloatGrid::create( sourceGrid.background() );
    targetGrid->setGridClass( sourceGrid.getGridClass() );
    targetGrid->setTransform( tr );
    openvdb::tools::resampleToMatch<openvdb::tools::BoxSampler>( sourceGrid, *targetGrid );
    targetGrid->setTransform( openvdb::math::Transform::createLinearTransform( 1.0f ) );
    return targetGrid;
}


auto resample( const openvdb::FloatGrid& sourceGrid, float scale )
{
    openvdb::Mat4R trMat;
    trMat.setToScale( openvdb::Vec3R{ scale, scale, scale } );
    auto tr = sourceGrid.transform().copy();
    tr->postMult( trMat );

    openvdb::FloatGrid::Ptr targetGrid = openvdb::FloatGrid::create( sourceGrid.background() );
    targetGrid->setGridClass( sourceGrid.getGridClass() );
    targetGrid->setTransform( tr );
    openvdb::tools::resampleToMatch<openvdb::tools::BoxSampler>( sourceGrid, *targetGrid );
    targetGrid->setTransform( openvdb::math::Transform::createLinearTransform( 1.0f ) );
    return targetGrid;
}

int main()
{
    openvdb::initialize();

    std::string path = "icosahedron.vdb";
    std::ifstream file( path, std::ios::binary );
    if ( !file )
        return 1;

    openvdb::io::Stream stream( file, false );
    auto grids = stream.getGrids();
    openvdb::GridBase::Ptr baseGrid = grids->at( 0 );
    file.close();

    openvdb::FloatGrid::Ptr sourceGrid = openvdb::gridPtrCast<openvdb::FloatGrid>( baseGrid );
    auto shiftedGrid = transform( *sourceGrid );

    {
        openvdb::io::File outFile( "icosahedron_shifted.vdb" );
        outFile.write( { shiftedGrid } );
        outFile.close();
    }
    {
        auto downsampledOrig = resample( *sourceGrid, 3.f );
        openvdb::io::File outFile( "icosahedron_downsampled.vdb" );
        outFile.write( { downsampledOrig } );
        outFile.close();
    }
    {
        auto downsampledShifted = resample( *shiftedGrid, 3.f );
        openvdb::io::File outFile( "icosahedron_downsampled_shifted.vdb" );
        outFile.write( { downsampledShifted } );
        outFile.close();
    }

    return 0;
}

The program produces the following grids (here slices are shown), corresponding to shifted, downsampled, and shifted-and-then-downsampled cases correspondingly:

As we can see, simple translation doesn't impact the grid quality. Downsampling on the original grid also works well. However, downsampling after the translation nearly destroys the grid.

Expected behavior

Translation (or maybe even other transformations) should not impact resampling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions