Skip to content

Commit cd1b018

Browse files
authored
add coordinates (#39)
1 parent 1336df4 commit cd1b018

3 files changed

Lines changed: 200 additions & 0 deletions

File tree

packages/engine/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod core;
2+
pub mod world;
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
use super::{ChunkPosition, CHUNK_SIZE};
2+
3+
pub type WorldUnit = i64;
4+
pub type ChunkUnit = usize;
5+
pub type IndexUnit = usize;
6+
7+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8+
pub enum Coordinate {
9+
/// Coordinates for the entire world.
10+
World(WorldUnit, WorldUnit, WorldUnit),
11+
/// Coordinates inside of a chunk.
12+
Chunk(usize, usize, usize),
13+
/// Coordiantes inside of a chunk's index.
14+
Index(IndexUnit),
15+
}
16+
17+
impl Coordinate {
18+
pub fn world_to_chunk(
19+
x: WorldUnit,
20+
y: WorldUnit,
21+
z: WorldUnit,
22+
) -> (ChunkUnit, ChunkUnit, ChunkUnit) {
23+
let adjust = |value: WorldUnit| {
24+
let remainder = value % CHUNK_SIZE as WorldUnit;
25+
if remainder < 0 {
26+
(remainder + CHUNK_SIZE as WorldUnit) as ChunkUnit
27+
} else {
28+
remainder as ChunkUnit
29+
}
30+
};
31+
32+
(adjust(x), adjust(y), adjust(z))
33+
}
34+
35+
pub fn chunk_to_world(
36+
x: ChunkUnit,
37+
y: ChunkUnit,
38+
z: ChunkUnit,
39+
chunk_position: &ChunkPosition,
40+
) -> (WorldUnit, WorldUnit, WorldUnit) {
41+
let x = (chunk_position.x * CHUNK_SIZE as i32) as WorldUnit
42+
+ x as WorldUnit;
43+
let y = (chunk_position.y * CHUNK_SIZE as i32) as WorldUnit
44+
+ y as WorldUnit;
45+
let z = (chunk_position.z * CHUNK_SIZE as i32) as WorldUnit
46+
+ z as WorldUnit;
47+
48+
(x, y, z)
49+
}
50+
51+
pub fn chunk_to_index(x: ChunkUnit, y: ChunkUnit, z: ChunkUnit) -> usize {
52+
x + (y * CHUNK_SIZE) + (z * CHUNK_SIZE * CHUNK_SIZE)
53+
}
54+
55+
pub fn index_to_chunk(index: usize) -> (ChunkUnit, ChunkUnit, ChunkUnit) {
56+
let x = index % CHUNK_SIZE;
57+
let y = (index / CHUNK_SIZE) % CHUNK_SIZE;
58+
let z = index / (CHUNK_SIZE * CHUNK_SIZE);
59+
(x, y, z)
60+
}
61+
62+
pub fn to_world(&self, chunk_position: &ChunkPosition) -> Self {
63+
match self {
64+
Coordinate::World(_, _, _) => *self,
65+
Coordinate::Chunk(x, y, z) => {
66+
let world_coordinates =
67+
Self::chunk_to_world(*x, *y, *z, chunk_position);
68+
Coordinate::World(
69+
world_coordinates.0,
70+
world_coordinates.1,
71+
world_coordinates.2,
72+
)
73+
}
74+
Coordinate::Index(index) => {
75+
let chunk_coordinates = Self::index_to_chunk(*index);
76+
let world_coordinates = Self::chunk_to_world(
77+
chunk_coordinates.0,
78+
chunk_coordinates.1,
79+
chunk_coordinates.2,
80+
chunk_position,
81+
);
82+
Coordinate::World(
83+
world_coordinates.0,
84+
world_coordinates.1,
85+
world_coordinates.2,
86+
)
87+
}
88+
}
89+
}
90+
91+
pub fn to_chunk(&self) -> Self {
92+
match self {
93+
Coordinate::World(x, y, z) => {
94+
let chunk_coordinates = Self::world_to_chunk(*x, *y, *z);
95+
Coordinate::Chunk(
96+
chunk_coordinates.0,
97+
chunk_coordinates.1,
98+
chunk_coordinates.2,
99+
)
100+
}
101+
Coordinate::Chunk(_, _, _) => *self,
102+
Coordinate::Index(index) => {
103+
let chunk_coordinates = Self::index_to_chunk(*index);
104+
Coordinate::Chunk(
105+
chunk_coordinates.0,
106+
chunk_coordinates.1,
107+
chunk_coordinates.2,
108+
)
109+
}
110+
}
111+
}
112+
113+
pub fn to_index(&self) -> Self {
114+
match self {
115+
Coordinate::World(x, y, z) => {
116+
let chunk_coordinates = Self::world_to_chunk(*x, *y, *z);
117+
let index_coordinates = Self::chunk_to_index(
118+
chunk_coordinates.0,
119+
chunk_coordinates.1,
120+
chunk_coordinates.2,
121+
);
122+
Coordinate::Index(index_coordinates)
123+
}
124+
Coordinate::Chunk(x, y, z) => {
125+
let index_coordinates = Self::chunk_to_index(*x, *y, *z);
126+
Coordinate::Index(index_coordinates)
127+
}
128+
Coordinate::Index(_) => *self,
129+
}
130+
}
131+
}
132+
133+
#[cfg(test)]
134+
pub mod tests {
135+
use super::*;
136+
137+
#[test]
138+
fn world_to_chunk() {
139+
let world_coord = Coordinate::World(324, 6, -452);
140+
let chunk_coord = world_coord.to_chunk();
141+
142+
assert_eq!(chunk_coord, Coordinate::Chunk(4, 6, 28));
143+
}
144+
145+
#[test]
146+
fn world_to_index() {
147+
let world_coord = Coordinate::World(-324, 140, 9420);
148+
let index_coord = world_coord.to_index();
149+
150+
assert_eq!(index_coord, Coordinate::Index(12700))
151+
}
152+
153+
#[test]
154+
fn chunk_to_world() {
155+
let chunk_coord = Coordinate::Chunk(0, 12, 4);
156+
let chunk_position = ChunkPosition { x: 0, y: -2, z: 32 };
157+
let world_coord = chunk_coord.to_world(&chunk_position);
158+
159+
assert_eq!(world_coord, Coordinate::World(0, -52, 1028));
160+
}
161+
162+
#[test]
163+
fn chunk_to_index() {
164+
let chunk_coord = Coordinate::Chunk(4, 15, 31);
165+
let index_coord = chunk_coord.to_index();
166+
167+
assert_eq!(index_coord, Coordinate::Index(32228));
168+
}
169+
170+
#[test]
171+
fn index_to_world() {
172+
let index_coord = Coordinate::Index(19008);
173+
let chunk_position = ChunkPosition {
174+
x: -452,
175+
y: 17,
176+
z: -4,
177+
};
178+
let world_coord = index_coord.to_world(&chunk_position);
179+
180+
assert_eq!(world_coord, Coordinate::World(-14464, 562, -110));
181+
}
182+
183+
#[test]
184+
fn index_to_chunk() {
185+
let index_coord = Coordinate::Index(6473);
186+
let chunk_coord = index_coord.to_chunk();
187+
188+
assert_eq!(chunk_coord, Coordinate::Chunk(9, 10, 6))
189+
}
190+
}

packages/engine/src/world/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub mod coordinate;
2+
3+
pub const CHUNK_SIZE: usize = 32;
4+
5+
pub struct ChunkPosition {
6+
pub x: i32,
7+
pub y: i32,
8+
pub z: i32,
9+
}

0 commit comments

Comments
 (0)