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 all 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 @@ -126,3 +126,7 @@ 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 @@ -26,6 +26,9 @@ opt-level = 1
lto = true
codegen-units = 1

[profile.bench]
debug = true

[profile.profiling]
inherits = "release"
debug = true
Expand Down
3 changes: 3 additions & 0 deletions extractor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ dependencies {
modImplementation("net.fabricmc:fabric-language-kotlin:${project.property("kotlin_loader_version")}")

modImplementation("net.fabricmc.fabric-api:fabric-api:${project.property("fabric_version")}")

// To allow for reflection
implementation(kotlin("reflect"))
}

tasks.processResources {
Expand Down
2 changes: 2 additions & 0 deletions extractor/src/main/kotlin/de/snowii/extractor/Extractor.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.snowii.extractor

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import de.snowii.extractor.extractors.*
Expand Down Expand Up @@ -32,6 +33,7 @@ class Extractor : ModInitializer {
Tags(),
Items(),
Blocks(),
Tests(),
)

val outputDirectory: Path
Expand Down
142 changes: 142 additions & 0 deletions extractor/src/main/kotlin/de/snowii/extractor/extractors/Tests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@

package de.snowii.extractor.extractors

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import de.snowii.extractor.Extractor
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.registry.BuiltinRegistries
import net.minecraft.registry.RegistryKeys
import net.minecraft.registry.RegistryWrapper
import net.minecraft.registry.RegistryWrapper.WrapperLookup
import net.minecraft.registry.entry.RegistryEntry.Reference
import net.minecraft.server.MinecraftServer
import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters
import net.minecraft.util.math.ChunkPos
import net.minecraft.world.gen.chunk.AquiferSampler
import net.minecraft.world.gen.chunk.Blender
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings
import net.minecraft.world.gen.chunk.ChunkNoiseSampler
import net.minecraft.world.gen.chunk.GenerationShapeConfig
import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos;
import net.minecraft.world.gen.densityfunction.DensityFunction.EachApplier;
import net.minecraft.world.gen.densityfunction.DensityFunctionTypes
import net.minecraft.world.gen.noise.NoiseConfig

import java.lang.reflect.Method
import java.util.Arrays
import kotlin.reflect.full.createType
import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.jvm.javaMethod
import kotlin.reflect.KFunction

class Tests : Extractor.Extractor {
override fun fileName(): String = "chunk.json"

private fun createFluidLevelSampler(settings: ChunkGeneratorSettings): AquiferSampler.FluidLevelSampler {
val fluidLevel = AquiferSampler.FluidLevel(-54, Blocks.LAVA.getDefaultState());
val i = settings.seaLevel();
val fluidLevel2 = AquiferSampler.FluidLevel(i, settings.defaultFluid());
return AquiferSampler.FluidLevelSampler {_, y, _ -> if (y < Math.min(-54, i)) fluidLevel else fluidLevel2};
}

private fun get_index(config: GenerationShapeConfig, x: Int, y: Int, z: Int): Int {
if (x < 0 || y < 0 || z < 0) {
System.err.println("Bad local pos");
System.exit(1);
}
return config.height() * 16 * x + 16 * y + z
}

// This is basically just what NoiseChunkGenerator is doing
private fun populate_noise(start_x: Int, start_z: Int, sampler: ChunkNoiseSampler, config: GenerationShapeConfig, settings: ChunkGeneratorSettings): IntArray? {
val result = IntArray(16 * 16 * config.height())

for (method: KFunction<*> in sampler::class.declaredFunctions) {
if (method.name.equals("sampleBlockState")) {
sampler.sampleStartDensity()
val k = config.horizontalCellBlockCount()
val l = config.verticalCellBlockCount()

val m = 16 / k
val n = 16 / k

val cellHeight = config.height() / l
val minimumCellY = config.minimumY() / l

for (o in 0..<m) {
sampler.sampleEndDensity(o)
for (p in 0..<n) {
for (r in (0..<cellHeight).reversed()) {
sampler.onSampledCellCorners(r, p)
for (s in (0..<l).reversed()) {
val t = (minimumCellY + r) * l + s
val d = s.toDouble() / l.toDouble()
sampler.interpolateY(t, d)
for (w in 0..<k) {
val x = start_x + o * k + w
val y = x and 15
val e = w.toDouble() / k.toDouble()
sampler.interpolateX(x, e)
for (z in 0..<k) {
val aa = start_z + p * k + z
val ab = aa and 15
val f = z.toDouble() / k.toDouble()
sampler.interpolateZ(aa, f)
var blockstate = method.call(sampler) as BlockState?
if (blockstate == null) {
blockstate = settings.defaultBlock()
}
val index = this.get_index(config, y, t - config.minimumY(), ab)
result[index] = Block.getRawIdFromState(blockstate)
}
}
}
}
}
sampler.swapBuffers()
}
sampler.stopInterpolation()
return result
}
}
System.err.println("No valid method found for block state sampler!");
return null;
}

// Dumps a chunk to an array of block state ids
override fun extract(server: MinecraftServer): JsonElement {
val topLevelJson = JsonArray()
val seed = 0L
val chunk_pos = ChunkPos(7, 4)

val lookup = BuiltinRegistries.createWrapperLookup()
val wrapper = lookup.getOrThrow(RegistryKeys.CHUNK_GENERATOR_SETTINGS)
val noise_params = lookup.getOrThrow(RegistryKeys.NOISE_PARAMETERS)

val ref = wrapper.getOrThrow(ChunkGeneratorSettings.OVERWORLD)
val settings = ref.value()
val config = NoiseConfig.create(settings, noise_params, seed)

// Overworld shape config
val shape = GenerationShapeConfig(-64, 384, 1, 2)
val test_sampler = ChunkNoiseSampler(16 / shape.horizontalCellBlockCount(), config, chunk_pos.startX, chunk_pos.startZ,
shape, object: DensityFunctionTypes.Beardifying{
override fun maxValue(): Double = 0.0
override fun minValue(): Double = 0.0
override fun sample(pos: NoisePos): Double = 0.0
override fun fill(densities: DoubleArray, applier: EachApplier) {densities.fill(0.0)}
}, settings, createFluidLevelSampler(settings), Blender.getNoBlending())

val data = populate_noise(chunk_pos.startX, chunk_pos.startZ, test_sampler, shape, settings)
data?.forEach { state ->
topLevelJson.add(state)
}

return topLevelJson
}
}
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 @@ num-derive.workspace = true
colored = "2"
md5 = "0.7.0"

enum_dispatch = "0.3.13"
9 changes: 9 additions & 0 deletions pumpkin-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ pub enum ProfileAction {
ForcedNameChange,
UsingBannedSkin,
}

#[macro_export]
macro_rules! assert_eq_delta {
($x:expr, $y:expr, $d:expr) => {
if !(2f64 * ($x - $y).abs() <= $d * ($x.abs() + $y.abs())) {
panic!("{} vs {} ({} vs {})", $x, $y, ($x - $y).abs(), $d);
}
};
}
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 @@ -4,14 +4,14 @@ use num_traits::Float;

use super::vector3::Vector3;

#[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 @@ -114,3 +114,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 {}
Loading