commit 95ca73881d3574d11836b15c9f57c5612e2be527
parent 4d4daf18edfc2abab152ec4b2bb816f39e7a459d
Author: amin <dev@aminmesbah.com>
Date: Sat, 11 May 2019 20:58:16 +0000
Fix chunks spanning [-1, 0] room index boundary
Now we can successfully traverse the boundary between positive and
negative room indices.
FossilOrigin-Name: a69aee9835c126cc7a6343332e74d766b0887f80a2129b83489fd5ada4928b71
Diffstat:
5 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -64,7 +64,7 @@ internal void game_init(struct GameMemory *game_memory, v2u framebuffer)
//world_room_set(game_state->world, collision_test_zone, &game_state->world_allocator);
//world_room_set(game_state->world, knytt_hanging_fly_village, &game_state->world_allocator);
- i32 s = 0;
+ i32 s = -100;
i32 f = 100;
for (i32 x = s; x < f; x++)
{
@@ -221,9 +221,7 @@ void game_update_and_render(struct GameMemory *game_memory, struct GameInput *ga
math_print(current_room_i);
printf("Current Actual Room: ");
math_print(r->index);
- printf("Expected Chunk Index: ");
- math_print(c_i);
- printf("Actual Chunk Index: ");
+ printf("Chunk Index: ");
math_print(c->index);
}
diff --git a/src/game.h b/src/game.h
@@ -17,6 +17,8 @@
#include "world.h"
#include "platform.h"
+static_assert(-1 == ~0, "Implementation doesn't use two's complement");
+
// One tile is one square meter
#define TILE_SIZE 1.0f
diff --git a/src/intrinsics.h b/src/intrinsics.h
@@ -5,3 +5,25 @@
static_assert(__has_builtin(__builtin_clz), "No builtin clz intrinsic");
#define intr_clz(x) __builtin_clz((x))
+
+internal inline i32 intr_mod(i32 x, i32 y)
+{
+ // NOTE(amin): There are multiple valid definitions of an operation that
+ // gets the remainder of an integer division: `x / y`. Such an operation
+ // must satisfy this equation:
+ //
+ // x == (quotient * y) + remainder
+ //
+ // The value computed for `remainder` will differ (when x or y is negative)
+ // based on the method of computing `quotient`.
+ //
+ // C's `%` operator is based on truncated integer division. This operation
+ // is often called 'rem' in other languages.
+ //
+ // Python's `%` operator is based on floored integer division. This
+ // operation is often called 'mod' in other languages.
+ //
+ // Here we implement 'mod'.
+ i32 result = ((x % y) + y) % y;
+ return result;
+}
diff --git a/src/world.c b/src/world.c
@@ -31,15 +31,12 @@ internal struct AbsolutePos world_pos_recanonicalize(struct AbsolutePos p)
internal inline v2i world_room_get_chunk_index(v2i room_i)
{
- // NOTE(amin): integer division here is intentional. We want a square of
- // CHUNK_NUM_ROOMS rooms to all have the same chunk index.
+ // NOTE(amin): truncated integer division here is intentional. We want a
+ // square of CHUNK_NUM_ROOMS rooms to all have the same chunk index.
- // TODO: Figure out the difference between % in c and % in python that
- // gives this expression the desired behavior in the latter and not in the
- // former.
v2i chunk_i = {
- (room_i.x - (room_i.x % CHUNK_ROOMS_PER_SIDE)) / CHUNK_ROOMS_PER_SIDE,
- (room_i.y - (room_i.y % CHUNK_ROOMS_PER_SIDE)) / CHUNK_ROOMS_PER_SIDE,
+ (room_i.x - (intr_mod(room_i.x, CHUNK_ROOMS_PER_SIDE))) / CHUNK_ROOMS_PER_SIDE,
+ (room_i.y - (intr_mod(room_i.y, CHUNK_ROOMS_PER_SIDE))) / CHUNK_ROOMS_PER_SIDE,
};
return chunk_i;
}
@@ -126,7 +123,12 @@ internal struct WorldChunk* world_chunk_get_or_create(struct World *world, v2i c
internal size_t world_room_get_index_within_chunk(v2i room_i)
{
- static_assert(-1 == ~0, "implementation doesn't use two's complement");
+ // TODO: assert that no chunk ever spans the [-1, 0] room index boundary.
+
+ // NOTE(amin): Because we are using only the lower bits here, we will get
+ // index collisions if both positive and negative numbers appear in the
+ // same chunk. For example with two's complement, the first 7 bits of 127
+ // and -1 are identical.
v2u room_i_lower_bits = {
room_i.x & CHUNK_MASK_FOR_INTERNAL_ROOM_INDEX,
room_i.y & CHUNK_MASK_FOR_INTERNAL_ROOM_INDEX,
diff --git a/src/world.h b/src/world.h
@@ -13,7 +13,7 @@ static_assert(
);
// TODO: Tune chunk size
-#define CHUNK_ROOMS_PER_SIDE 2
+#define CHUNK_ROOMS_PER_SIDE 4
static_assert(
math_is_pow_2(CHUNK_ROOMS_PER_SIDE),
"Must be a power of 2 for the chunk mask to work"