Forceflow / libmorton

C++ header-only library with methods to efficiently encode/decode Morton codes in/from 2D/3D coordinates
MIT License
596 stars 71 forks source link

morton codes out of bounds for N = 48 #85

Closed omarathon closed 8 months ago

omarathon commented 8 months ago

hello,

in the below function I use your library to re-map an input vector of integers in row-major order (corresponding to an NxN array) to a vector in z-order:

std::vector<int32_t> remapToMortonOrder(const std::vector<int32_t>& input, int N) {
    if (input.size() != N * N) {
        throw std::invalid_argument("Morton remap input size does not match the specified dimensions.");
    }

    std::vector<int32_t> output(N * N, 0);
    uint_fast32_t maxIndex = N * N - 1;

    for (int y = 0; y < N; ++y) {
        for (int x = 0; x < N; ++x) {
            int index = y * N + x;
            uint_fast32_t mortonCode = libmorton::morton2D_32_encode(static_cast<uint_fast16_t>(x), static_cast<uint_fast16_t>(y));
            if (mortonCode > maxIndex) {
                std::cerr << "Morton remap error: Morton code out of bounds - " << mortonCode << std::endl;
                throw std::out_of_range("Morton remap code exceeds the bounds of the output array.");
            }
            output[mortonCode] = input[index];
        }
    }
    return output;
}

somehow, this code works for N=2,4,8,16,32,64,128,256, but it does not work for N=48. with N=48, the generated mortonCode exceeds the max index of the output array.

am I using libmorton::morton2D_32_encode wrong?

thanks

Forceflow commented 8 months ago

I think you're making a logic error here. 48 is not a power of two, the rest of your test dimensions are.

Morton codes fit in the UPPER BOUND of the power of two of their active bits, in the power of two. So your morton codes in a 48x48 grid map on values in the range of 0 to (64*64)-1.