Browse Source

Revise Morton location code functions to be templated, closes #7

master
C. J. Howard 9 months ago
parent
commit
d261feab3a
6 changed files with 177 additions and 100 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +1
    -0
      src/game/states/play-state.cpp
  3. +3
    -2
      src/geom/mesh-accelerator.cpp
  4. +0
    -86
      src/geom/morton.cpp
  5. +170
    -10
      src/geom/morton.hpp
  6. +2
    -2
      src/utility/bit-math.hpp

+ 1
- 0
CMakeLists.txt View File

@ -14,6 +14,7 @@ find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG)
find_package(OpenAL REQUIRED CONFIG)
find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib")
# Determine dependencies
set(STATIC_LIBS
dr_wav

+ 1
- 0
src/game/states/play-state.cpp View File

@ -458,6 +458,7 @@ void play_state_enter(game_context* ctx)
std::cout << "similarity62: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum62<int>) << std::endl;
std::cout << "similarity80: " << genetics::protein::similarity<float>(protein_b.begin(), protein_b.end(), protein_c.begin(), genetics::matrix::blosum80<int>) << std::endl;
}
void play_state_exit(game_context* ctx)

+ 3
- 2
src/geom/mesh-accelerator.cpp View File

@ -141,7 +141,8 @@ void mesh_accelerator::query_nearest_recursive(float& nearest_t, geom::mesh::fac
aabb<float> mesh_accelerator::get_node_bounds(octree32::node_type node) const
{
// Decode Morton location of node
auto [x, y, z] = morton::decode_3d(octree32::location(node));
std::uint32_t x, y, z;
morton::decode(octree32::location(node), x, y, z);
float3 node_location = float3{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
// Get node dimensions at node depth
@ -167,7 +168,7 @@ octree32::node_type mesh_accelerator::find_node(const float3& point) const
transformed_point = transformed_point / node_dimensions[octree32::max_depth];
// Encode transformed point as a Morton location code
std::uint32_t location = morton::encode_3d(
std::uint32_t location = morton::encode(
static_cast<std::uint32_t>(transformed_point.x),
static_cast<std::uint32_t>(transformed_point.y),
static_cast<std::uint32_t>(transformed_point.z));

+ 0
- 86
src/geom/morton.cpp View File

@ -1,86 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "morton.hpp"
namespace geom {
namespace morton {
std::uint32_t encode_2d(std::uint32_t x, std::uint32_t y)
{
auto interleave = [](std::uint32_t x) -> std::uint32_t
{
x &= 0x0000ffff;
x = (x ^ (x << 8)) & 0x00ff00ff;
x = (x ^ (x << 4)) & 0x0f0f0f0f;
x = (x ^ (x << 2)) & 0x33333333;
x = (x ^ (x << 1)) & 0x55555555;
return x;
};
return (interleave(y) << 1) + interleave(x);
}
std::uint32_t encode_3d(std::uint32_t x, std::uint32_t y, std::uint32_t z)
{
auto interleave = [](std::uint32_t x) -> std::uint32_t
{
x &= 0x000003ff;
x = (x ^ (x << 16)) & 0xff0000ff;
x = (x ^ (x << 8)) & 0x0300f00f;
x = (x ^ (x << 4)) & 0x030c30c3;
x = (x ^ (x << 2)) & 0x09249249;
return x;
};
return interleave(x) | (interleave(y) << 1) | (interleave(z) << 2);
}
std::array<uint32_t, 2> decode_2d(std::uint32_t code)
{
auto unravel = [](std::uint32_t x) -> std::uint32_t
{
x &= 0x55555555;
x = (x ^ (x >> 1)) & 0x33333333;
x = (x ^ (x >> 2)) & 0x0f0f0f0f;
x = (x ^ (x >> 4)) & 0x00ff00ff;
x = (x ^ (x >> 8)) & 0x0000ffff;
return x;
};
return {unravel(code >> 0), unravel(code >> 1)};
}
std::array<uint32_t, 3> decode_3d(std::uint32_t code)
{
auto unravel = [](std::uint32_t x) -> std::uint32_t
{
x &= 0x09249249;
x = (x ^ (x >> 2)) & 0x030c30c3;
x = (x ^ (x >> 4)) & 0x0300f00f;
x = (x ^ (x >> 8)) & 0xff0000ff;
x = (x ^ (x >> 16)) & 0x000003ff;
return x;
};
return {unravel(code >> 0), unravel(code >> 1), unravel(code >> 2)};
}
} // namespace morton
} // namespace geom

+ 170
- 10
src/geom/morton.hpp View File

@ -21,27 +21,187 @@
#define ANTKEEPER_GEOM_MORTON_HPP
#include <array>
#include <cstdint>
#include <cstdlib>
namespace geom {
/// Morton location code encoding and decoding functions.
namespace morton {
/// Encodes 2D coordinates as a 32-bit Morton location code.
std::uint32_t encode_2d(std::uint32_t x, std::uint32_t y);
/**
* Encodes 2D coordinates as a Morton location code.
*
* @param[in] x X-coordinate to encode.
* @param[in] y Y-coordinate to encode.
* @return Morton location code.
*/
template <typename T>
T encode(T x, T y);
/**
* Encodes 3D coordinates as a Morton location code.
*
* @param[in] x X-coordinate to encode.
* @param[in] y Y-coordinate to encode.
* @param[in] z Z-coordinate to encode.
* @return Morton location code.
*/
template <typename T>
T encode(T x, T y, T z);
/**
* Decodes 2D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
*/
template <typename T>
void decode(T code, T& x, T& y);
/**
* Decodes 3D coordinates from a Morton location code.
*
* @param[in] code Morton location code to decode.
* @param[out] x Decoded x-coordinate.
* @param[out] y Decoded y-coordinate.
* @param[out] z Decoded z-coordinate.
*/
template <typename T>
void decode(T code, T& x, T& y, T& z);
/// Encodes 3D coordinates as a 32-bit Morton location code.
std::uint32_t encode_3d(std::uint32_t x, std::uint32_t y, std::uint32_t z);
template <typename T>
T encode(T x, T y)
{
auto expand = [](T x) -> T
{
x &= (1 << (sizeof(T) << 2)) - 1;
if constexpr(sizeof(T) >= 8)
x = (x ^ (x << 16)) & T(0x0000ffff0000ffff);
if constexpr(sizeof(T) >= 4)
x = (x ^ (x << 8)) & T(0x00ff00ff00ff00ff);
if constexpr(sizeof(T) >= 2)
x = (x ^ (x << 4)) & T(0x0f0f0f0f0f0f0f0f);
x = (x ^ (x << 2)) & T(0x3333333333333333);
x = (x ^ (x << 1)) & T(0x5555555555555555);
return x;
};
return expand(x) | (expand(y) << 1);
}
/// Decodes X and Y coordinates from a 32-bit Morton location code.
std::array<uint32_t, 2> decode_2d(std::uint32_t code);
template <typename T>
T encode(T x, T y, T z)
{
auto expand = [](T x) -> T
{
if constexpr(sizeof(T) == 1)
{
x &= 0x3;
x = (x | x << 2) & 0x9;
}
else if constexpr(sizeof(T) == 2)
{
x &= 0x001f;
x = (x | x << 8) & 0x100f;
x = (x | x << 4) & 0x10c3;
x = (x | x << 2) & 0x1249;
}
else if constexpr(sizeof(T) == 4)
{
x &= 0x00003ff;
x = (x | x << 16) & 0x30000ff;
x = (x | x << 8) & 0x300f00f;
x = (x | x << 4) & 0x30c30c3;
x = (x | x << 2) & 0x9249249;
}
else if constexpr(sizeof(T) == 8)
{
x &= 0x00000000001fffff;
x = (x | x << 32) & 0x001f00000000ffff;
x = (x | x << 16) & 0x001f0000ff0000ff;
x = (x | x << 8) & 0x100f00f00f00f00f;
x = (x | x << 4) & 0x10c30c30c30c30c3;
x = (x | x << 2) & 0x1249249249249249;
}
/// Decodes X, Y, and Z coordinates from a 32-bit Morton location code.
std::array<uint32_t, 3> decode_3d(std::uint32_t code);
return x;
};
return expand(x) | (expand(y) << 1) | (expand(z) << 2);
}
template <typename T>
void decode(T code, T& x, T& y)
{
auto compress = [](T x) -> T
{
x &= T(0x5555555555555555);
x = (x ^ (x >> 1)) & T(0x3333333333333333);
x = (x ^ (x >> 2)) & T(0x0f0f0f0f0f0f0f0f);
if constexpr(sizeof(T) >= 2)
x = (x ^ (x >> 4)) & T(0x00ff00ff00ff00ff);
if constexpr(sizeof(T) >= 4)
x = (x ^ (x >> 8)) & T(0x0000ffff0000ffff);
if constexpr(sizeof(T) >= 8)
x = (x ^ (x >> 16)) & T(0x00000000ffffffff);
return x;
};
x = compress(code);
y = compress(code >> 1);
}
template <typename T>
void decode(T code, T& x, T& y, T& z)
{
auto compress = [](T x) -> T
{
if constexpr(sizeof(T) == 1)
{
x &= 0x9;
x = (x ^ x >> 2) & 0x3;
}
else if constexpr(sizeof(T) == 2)
{
x &= 0x1249;
x = (x ^ x >> 2) & 0x10c3;
x = (x ^ x >> 4) & 0x100f;
x = (x ^ x >> 8) & 0x001f;
}
else if constexpr(sizeof(T) == 4)
{
x &= 0x9249249;
x = (x ^ x >> 2) & 0x30c30c3;
x = (x ^ x >> 4) & 0x300f00f;
x = (x ^ x >> 8) & 0x30000ff;
x = (x ^ x >> 16) & 0x00003ff;
}
else if constexpr(sizeof(T) == 8)
{
x &= 0x1249249249249249;
x = (x ^ x >> 2) & 0x10c30c30c30c30c3;
x = (x ^ x >> 4) & 0x100f00f00f00f00f;
x = (x ^ x >> 8) & 0x001f0000ff0000ff;
x = (x ^ x >> 16) & 0x001f00000000ffff;
x = (x ^ x >> 32) & 0x00000000001fffff;
}
return x;
};
x = compress(code);
y = compress(code >> 1);
z = compress(code >> 2);
}
} // namespace morton
} // namespace geom
#endif // ANTKEEPER_GEOM_MORTON_HPP

+ 2
- 2
src/utility/bit-math.hpp View File

@ -20,8 +20,8 @@
#ifndef ANTKEEPER_BIT_MATH_HPP
#define ANTKEEPER_BIT_MATH_HPP
namespace bit
{
/// Bitwise math
namespace bit {
/**
* Compresses the even bits of a value into the lower half, then clears the upper half.

Loading…
Cancel
Save