Created
April 28, 2026 16:58
-
-
Save jakubtomsu/82aba32bcd112cea00035558461fa05e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #+vet shadowing unused | |
| package morton | |
| import "base:intrinsics" | |
| // https://fgiesen.wordpress.com/2022/09/09/morton-codes-addendum/ | |
| // https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/ | |
| @(require_results) | |
| morton_encode_2d_u8 :: proc "contextless" (p: [2]u8) -> u16 #no_bounds_check { | |
| t: u32 = u32(p.x) | (u32(p.y) << 16) | |
| t = (t ~ (t << 4)) & 0x0f0f0f0f | |
| t = (t ~ (t << 2)) & 0x33333333 | |
| t = (t ~ (t << 1)) & 0x55555555 | |
| return u16((t >> 15) | (t & 0xffff)) | |
| } | |
| @(require_results) | |
| morton_decode_2d_u8 :: proc "contextless" (code: u32) -> [2]u8 #no_bounds_check { | |
| t: u32 = (code & 0x5555) | ((code & 0xaaaa) << 15) | |
| t = (t ~ (t >> 1)) & 0x33333333 | |
| t = (t ~ (t >> 2)) & 0x0f0f0f0f | |
| t ~= t >> 4 | |
| return {u8(t & 0xff), u8((t >> 16) & 0xff)} | |
| } | |
| @(require_results) | |
| morton_encode_3d_u8 :: proc "contextless" (p: [3]u8) -> (result: u32) #no_bounds_check { | |
| if true { | |
| v: #simd[4]u32 = {u32(p.x), u32(p.y), u32(p.z), 0} | |
| v &= 0x000003ff | |
| v = (v ~ intrinsics.simd_shl(v, 16)) & 0xff0000ff | |
| v = (v ~ intrinsics.simd_shl(v, 8)) & 0x0300f00f | |
| v = (v ~ intrinsics.simd_shl(v, 4)) & 0x030c30c3 | |
| v = (v ~ intrinsics.simd_shl(v, 2)) & 0x09249249 | |
| v = intrinsics.simd_shl(v, #simd[4]u32{0, 1, 2, 0}) | |
| result = intrinsics.simd_reduce_or(v) | |
| } else { | |
| result = (morton_part_by_2(u32(p.x)) << 0) | | |
| (morton_part_by_2(u32(p.y)) << 1) | | |
| (morton_part_by_2(u32(p.z)) << 2) | |
| } | |
| return result | |
| } | |
| @(require_results) | |
| morton_decode_3d_u8 :: proc "contextless" (code: u32) -> [3]u8 #no_bounds_check { | |
| return { | |
| u8(morton_compact_by_2(code >> 0)), | |
| u8(morton_compact_by_2(code >> 1)), | |
| u8(morton_compact_by_2(code >> 2)), | |
| } | |
| } | |
| // "Insert" a 0 bit after each of the 16 low bits of x | |
| @(require_results) | |
| morton_part_by_1 :: proc "contextless" (x: u32) -> u32 #no_bounds_check { | |
| x := x | |
| x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 | |
| x = (x ~ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 | |
| x = (x ~ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 | |
| x = (x ~ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 | |
| x = (x ~ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 | |
| return x; | |
| } | |
| // "Insert" two 0 bits after each of the 10 low bits of x | |
| @(require_results) | |
| morton_part_by_2 :: proc "contextless" (x: u32) -> u32 #no_bounds_check { | |
| x := x | |
| x &= 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210 | |
| x = (x ~ (x << 16)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210 | |
| x = (x ~ (x << 8)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210 | |
| x = (x ~ (x << 4)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10 | |
| x = (x ~ (x << 2)) & 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 | |
| return x; | |
| } | |
| // Inverse of part_by_1 - "delete" all odd-indexed bits | |
| @(require_results) | |
| morton_compact_by_1 :: proc "contextless" (x: u32) -> u32 #no_bounds_check { | |
| x := x | |
| x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0 | |
| x = (x ~ (x >> 1)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10 | |
| x = (x ~ (x >> 2)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210 | |
| x = (x ~ (x >> 4)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210 | |
| x = (x ~ (x >> 8)) & 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210 | |
| return x; | |
| } | |
| // Inverse of part_by_2 - "delete" all bits not at positions divisible by 3 | |
| @(require_results) | |
| morton_compact_by_2 :: proc "contextless" (x: u32) -> u32 #no_bounds_check { | |
| x := x | |
| x &= 0x09249249; // x = ---- 9--8 --7- -6-- 5--4 --3- -2-- 1--0 | |
| x = (x ~ (x >> 2)) & 0x030c30c3; // x = ---- --98 ---- 76-- --54 ---- 32-- --10 | |
| x = (x ~ (x >> 4)) & 0x0300f00f; // x = ---- --98 ---- ---- 7654 ---- ---- 3210 | |
| x = (x ~ (x >> 8)) & 0xff0000ff; // x = ---- --98 ---- ---- ---- ---- 7654 3210 | |
| x = (x ~ (x >> 16)) & 0x000003ff; // x = ---- ---- ---- ---- ---- --98 7654 3210 | |
| return x; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment