Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"populate noise" step of chunk generation #319

Merged
merged 27 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
96b79a2
implement populate noise step of chunk generation
kralverde Nov 23, 2024
c841a41
fix gitignore
kralverde Nov 23, 2024
44ccf62
pass thru seed
kralverde Nov 23, 2024
c0dd6d0
add counter for edge case
kralverde Nov 23, 2024
96915ba
add entire chunk test case
kralverde Nov 23, 2024
b4f2141
remove eclipse file
kralverde Nov 23, 2024
a49427f
remove packet timing
kralverde Nov 23, 2024
a3c77af
precompute float divisions
kralverde Nov 24, 2024
f9cf387
unsafe speed up
kralverde Nov 24, 2024
68949ec
slight aquifer optimization
kralverde Nov 24, 2024
fa0411d
tweak block pos packing
kralverde Nov 24, 2024
828cb67
optimize perlin map
kralverde Nov 25, 2024
014dfae
precompute aquifer random positions
kralverde Nov 25, 2024
74a1fe6
fix aquifer regression
kralverde Nov 25, 2024
c120b54
refactor samplers, add tests to aquifer, and move chunk extractor to …
kralverde Nov 26, 2024
f25e9aa
Merge branch 'master' into basic_chunk_generation
Snowiiii Nov 26, 2024
2fc5ddd
fix base density function error and add a bunch of test cases
kralverde Nov 28, 2024
487b3c1
ignore expensive tests by default
kralverde Nov 28, 2024
2a11487
remove un-needed lifetimes
kralverde Nov 28, 2024
4713a8c
Merge branch 'master' into basic_chunk_generation
kralverde Nov 28, 2024
6732a77
remove minecraft prefix from block lookups
kralverde Nov 28, 2024
69b516b
fix populate noise bench
kralverde Nov 29, 2024
6f0842f
slight optimizations
kralverde Nov 30, 2024
675ff9f
read files at runtime to speed up test compilation speed and remove i…
kralverde Nov 30, 2024
c13e22d
remove new lines from test data so people stop freaking out about lin…
kralverde Nov 30, 2024
04b1fce
make extractor the same
kralverde Dec 1, 2024
c8ac364
leverage branch prediction
kralverde Dec 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,7 @@ docs/.vitepress/cache
node_modules

run/

# Benchmarking
*perf.data*
*flamegraph.svg
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ edition = "2021"
lto = true
codegen-units = 1

[profile.bench]
debug = true

[profile.profiling]
inherits = "release"
debug = true
Expand Down
1 change: 1 addition & 0 deletions pumpkin-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
colored = "2"
md5 = "0.7.0"

enum_dispatch = "0.3.13"
59 changes: 59 additions & 0 deletions pumpkin-core/src/math/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use num_traits::PrimInt;

pub mod boundingbox;
pub mod position;
pub mod vector2;
Expand Down Expand Up @@ -30,3 +32,60 @@ pub fn magnitude(a: f64, b: f64, c: f64) -> f64 {
pub const fn get_section_cord(coord: i32) -> i32 {
coord >> 4
}

const MULTIPLY_DE_BRUIJN_BIT_POSITION: [u8; 32] = [
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26,
12, 18, 6, 11, 5, 10, 9,
];

/// Maximum return value: 31
pub const fn ceil_log2(value: u32) -> u8 {
let value = if value.is_power_of_two() {
value
} else {
smallest_encompassing_power_of_two(value)
};

MULTIPLY_DE_BRUIJN_BIT_POSITION[(((value as usize) * 125613361) >> 27) & 31]
}

/// Maximum return value: 30
pub const fn floor_log2(value: u32) -> u8 {
ceil_log2(value) - if value.is_power_of_two() { 0 } else { 1 }
}

pub const fn smallest_encompassing_power_of_two(value: u32) -> u32 {
let mut i = value - 1;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i + 1
}

#[inline]
pub fn floor_div<T>(x: T, y: T) -> T
where
T: PrimInt + From<i8>,
{
let div = x / y;
if (x ^ y) < 0.into() && div * y != x {
div - 1.into()
} else {
div
}
}

#[inline]
pub fn floor_mod<T>(x: T, y: T) -> T
where
T: PrimInt + From<i8>,
{
let rem = x % y;
if (x ^ y) < 0.into() && rem != 0.into() {
rem + y
} else {
rem
}
}
5 changes: 3 additions & 2 deletions pumpkin-core/src/math/vector2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use std::ops::{Add, Div, Mul, Neg, Sub};

use num_traits::Float;

#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq, Default)]
pub struct Vector2<T> {
pub x: T,
pub z: T,
}

impl<T: Math + Copy> Vector2<T> {
pub fn new(x: T, z: T) -> Self {
pub const fn new(x: T, z: T) -> Self {
Vector2 { x, z }
}

Expand Down Expand Up @@ -103,3 +103,4 @@ impl Math for f64 {}
impl Math for f32 {}
impl Math for i32 {}
impl Math for i64 {}
impl Math for i8 {}
9 changes: 6 additions & 3 deletions pumpkin-core/src/math/vector3.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::ops::{Add, Div, Mul, Sub};

use num_traits::Float;

#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq, Default)]
pub struct Vector3<T> {
pub x: T,
pub y: T,
Expand Down Expand Up @@ -80,6 +80,7 @@ impl<T: Math + Copy> Add for Vector3<T> {
}
}

/*
impl<T: Math + Copy> Neg for Vector3<T> {
type Output = Self;

Expand All @@ -91,6 +92,7 @@ impl<T: Math + Copy> Neg for Vector3<T> {
}
}
}
*/

impl<T> From<(T, T, T)> for Vector3<T> {
#[inline(always)]
Expand All @@ -108,7 +110,7 @@ impl<T> From<Vector3<T>> for (T, T, T) {

pub trait Math:
Mul<Output = Self>
+ Neg<Output = Self>
//+ Neg<Output = Self>
+ Add<Output = Self>
+ Div<Output = Self>
+ Sub<Output = Self>
Expand All @@ -119,3 +121,4 @@ impl Math for f64 {}
impl Math for f32 {}
impl Math for i32 {}
impl Math for i64 {}
impl Math for u8 {}
38 changes: 25 additions & 13 deletions pumpkin-core/src/random/legacy_rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ pub struct LegacyRand {
}

impl LegacyRand {
fn next_random(&mut self) -> u64 {
let l = self.seed;
fn next_random(&mut self) -> i64 {
let l = self.seed as i64;
let m = l.wrapping_mul(0x5DEECE66D).wrapping_add(11) & 0xFFFFFFFFFFFF;
self.seed = m;
self.seed = m as u64;
m
}

fn next(&mut self, bits: u64) -> i32 {
(self.next_random() >> (48 - bits)) as i32
}
}

impl GaussianGenerator for LegacyRand {
Expand All @@ -34,16 +38,12 @@ impl RandomImpl for LegacyRand {
}
}

fn next(&mut self, bits: u64) -> u64 {
self.next_random() >> (48 - bits)
}

fn split(&mut self) -> Self {
LegacyRand::from_seed(self.next_i64() as u64)
}

fn next_i32(&mut self) -> i32 {
self.next(32) as i32
self.next(32)
}

fn next_i64(&mut self) -> i64 {
Expand All @@ -59,7 +59,7 @@ impl RandomImpl for LegacyRand {
fn next_f64(&mut self) -> f64 {
let i = self.next(26);
let j = self.next(27);
let l = (i << 27).wrapping_add(j);
let l = ((i as i64) << 27).wrapping_add(j as i64);
l as f64 * 1.110223E-16f32 as f64
}

Expand All @@ -78,10 +78,10 @@ impl RandomImpl for LegacyRand {

fn next_bounded_i32(&mut self, bound: i32) -> i32 {
if (bound & bound.wrapping_sub(1)) == 0 {
((bound as u64).wrapping_mul(self.next(31)) >> 31) as i32
((bound as i64).wrapping_mul(self.next(31) as i64) >> 31) as i32
} else {
loop {
let i = self.next(31) as i32;
let i = self.next(31);
let j = i % bound;
if (i.wrapping_sub(j).wrapping_add(bound.wrapping_sub(1))) >= 0 {
return j;
Expand All @@ -91,6 +91,7 @@ impl RandomImpl for LegacyRand {
}
}

#[derive(Clone)]
pub struct LegacySplitter {
seed: u64,
}
Expand Down Expand Up @@ -120,7 +121,7 @@ impl RandomDeriverImpl for LegacySplitter {

#[cfg(test)]
mod test {
use crate::random::{RandomDeriverImpl, RandomImpl};
use crate::random::{legacy_rand::LegacySplitter, RandomDeriverImpl, RandomImpl};

use super::LegacyRand;

Expand Down Expand Up @@ -308,8 +309,19 @@ mod test {
#[test]
fn test_split() {
let mut original_rand = LegacyRand::from_seed(0);
let mut new_rand = original_rand.split();
assert_eq!(original_rand.next_i64(), -4962768465676381896i64);

let mut original_rand = LegacyRand::from_seed(0);
{
let splitter: LegacySplitter = original_rand.next_splitter();
assert_eq!(splitter.seed, (-4962768465676381896i64) as u64);

let mut rand = splitter.split_string("minecraft:offset");
assert_eq!(rand.next_i32(), 103436829);
}

let mut original_rand = LegacyRand::from_seed(0);
let mut new_rand = original_rand.split();
{
let splitter = new_rand.next_splitter();

Expand Down
33 changes: 7 additions & 26 deletions pumpkin-core/src/random/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ pub mod xoroshiro128;
pub enum RandomGenerator {
Xoroshiro(Xoroshiro),
Legacy(LegacyRand),
LegacyXoroshiro(Xoroshiro),
}

impl RandomGenerator {
#[inline]
pub fn split(&mut self) -> Self {
match self {
Self::Xoroshiro(rand) => Self::Xoroshiro(rand.split()),
Self::LegacyXoroshiro(rand) => Self::LegacyXoroshiro(rand.split()),
Self::Legacy(rand) => Self::Legacy(rand.split()),
}
}
Expand All @@ -25,25 +23,14 @@ impl RandomGenerator {
pub fn next_splitter(&mut self) -> RandomDeriver {
match self {
Self::Xoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()),
Self::LegacyXoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()),
Self::Legacy(rand) => RandomDeriver::Legacy(rand.next_splitter()),
}
}

#[inline]
pub fn next(&mut self, bits: u64) -> u64 {
match self {
Self::Xoroshiro(rand) => rand.next(bits),
Self::LegacyXoroshiro(rand) => rand.next(bits),
Self::Legacy(rand) => rand.next(bits),
}
}

#[inline]
pub fn next_i32(&mut self) -> i32 {
match self {
Self::Xoroshiro(rand) => rand.next_i32(),
Self::LegacyXoroshiro(rand) => rand.next_i32(),
Self::Legacy(rand) => rand.next_i32(),
}
}
Expand All @@ -52,7 +39,6 @@ impl RandomGenerator {
pub fn next_bounded_i32(&mut self, bound: i32) -> i32 {
match self {
Self::Xoroshiro(rand) => rand.next_bounded_i32(bound),
Self::LegacyXoroshiro(rand) => rand.next_bounded_i32(bound),
Self::Legacy(rand) => rand.next_bounded_i32(bound),
}
}
Expand All @@ -66,7 +52,6 @@ impl RandomGenerator {
pub fn next_i64(&mut self) -> i64 {
match self {
Self::Xoroshiro(rand) => rand.next_i64(),
Self::LegacyXoroshiro(rand) => rand.next_i64(),
Self::Legacy(rand) => rand.next_i64(),
}
}
Expand All @@ -75,7 +60,6 @@ impl RandomGenerator {
pub fn next_bool(&mut self) -> bool {
match self {
Self::Xoroshiro(rand) => rand.next_bool(),
Self::LegacyXoroshiro(rand) => rand.next_bool(),
Self::Legacy(rand) => rand.next_bool(),
}
}
Expand All @@ -84,7 +68,6 @@ impl RandomGenerator {
pub fn next_f32(&mut self) -> f32 {
match self {
Self::Xoroshiro(rand) => rand.next_f32(),
Self::LegacyXoroshiro(rand) => rand.next_f32(),
Self::Legacy(rand) => rand.next_f32(),
}
}
Expand All @@ -93,7 +76,6 @@ impl RandomGenerator {
pub fn next_f64(&mut self) -> f64 {
match self {
Self::Xoroshiro(rand) => rand.next_f64(),
Self::LegacyXoroshiro(rand) => rand.next_f64(),
Self::Legacy(rand) => rand.next_f64(),
}
}
Expand All @@ -102,7 +84,6 @@ impl RandomGenerator {
pub fn next_gaussian(&mut self) -> f64 {
match self {
Self::Xoroshiro(rand) => rand.next_gaussian(),
Self::LegacyXoroshiro(rand) => rand.next_gaussian(),
Self::Legacy(rand) => rand.next_gaussian(),
}
}
Expand All @@ -125,6 +106,7 @@ impl RandomGenerator {
}
}

#[derive(Clone)]
pub enum RandomDeriver {
Xoroshiro(XoroshiroSplitter),
Legacy(LegacySplitter),
Expand Down Expand Up @@ -163,8 +145,6 @@ pub trait RandomImpl {

fn next_splitter(&mut self) -> impl RandomDeriverImpl;

fn next(&mut self, bits: u64) -> u64;

fn next_i32(&mut self) -> i32;

fn next_bounded_i32(&mut self, bound: i32) -> i32;
Expand Down Expand Up @@ -215,17 +195,17 @@ fn hash_block_pos(x: i32, y: i32, z: i32) -> i64 {
l >> 16
}

fn java_string_hash(string: &str) -> u32 {
fn java_string_hash(string: &str) -> i32 {
// All byte values of latin1 align with
// the values of U+0000 - U+00FF making this code
// equivalent to both java hash implementations

let mut result = 0u32;
let mut result = 0i32;

for char_encoding in string.encode_utf16() {
result = 31u32
result = 31i32
.wrapping_mul(result)
.wrapping_add(char_encoding as u32);
.wrapping_add(char_encoding as i32);
}
result
}
Expand Down Expand Up @@ -271,12 +251,13 @@ mod tests {
ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄ\
ÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞ\
ßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ",
(-1992287231i32) as u32,
-1992287231i32,
),
("求同存异", 847053876),
// This might look wierd because hebrew is text is right to left
("אבְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ:", 1372570871),
("संस्कृत-", 1748614838),
("minecraft:offset", -920384768i32),
];

for (string, value) in values {
Expand Down
Loading