funny world gen (translated Terrain4J's noise to rust for funsies)
This commit is contained in:
parent
1519a1c065
commit
cb12591f5d
6 changed files with 292 additions and 26 deletions
62
Cargo.lock
generated
62
Cargo.lock
generated
|
|
@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
|
|
@ -652,6 +652,8 @@ dependencies = [
|
|||
"log",
|
||||
"mars",
|
||||
"pollster",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
|
|
@ -669,6 +671,17 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
|
|
@ -990,7 +1003,7 @@ version = "0.1.34"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -1659,6 +1672,15 @@ dependencies = [
|
|||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "presser"
|
||||
version = "0.3.1"
|
||||
|
|
@ -1719,6 +1741,36 @@ version = "5.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.5"
|
||||
|
|
@ -2222,6 +2274,12 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.3+wasi-0.2.9"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ console_error_panic_hook = "0.1.7"
|
|||
bytemuck = { version = "1.25.0", features = [ "derive" ]}
|
||||
image = { version = "0.24", default-features = false, features = ["png", "jpeg"]}
|
||||
mars = { path = "../Mars" }
|
||||
rand = "0.8"
|
||||
rand_chacha = "0.3"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
console_error_panic_hook = "0.1.6"
|
||||
|
|
|
|||
114
src/app.rs
114
src/app.rs
|
|
@ -2,6 +2,8 @@ use std::collections::HashMap;
|
|||
// Credit of most code to https://sotrh.github.io/learn-wgpu/ since I'm not familiar with wgpu
|
||||
use crate::render::Renderer;
|
||||
use crate::world::{SimpleObject, World};
|
||||
use crate::permutation_array;
|
||||
use crate::noise2d;
|
||||
use glam::{Affine3A, EulerRot, Mat4, Quat, Vec2, Vec3, Vec4};
|
||||
use std::sync::Arc;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
|
@ -16,6 +18,8 @@ use winit::{
|
|||
keyboard::{KeyCode, PhysicalKey},
|
||||
window::Window,
|
||||
};
|
||||
use crate::noise2d::Noise2D;
|
||||
use crate::permutation_array::PermutationArray;
|
||||
|
||||
struct Controller {
|
||||
buttons: HashMap<MouseButton, bool>,
|
||||
|
|
@ -38,9 +42,12 @@ pub struct AppState {
|
|||
controller: Controller,
|
||||
window: Arc<Window>,
|
||||
clients: Vec<SimpleObject>,
|
||||
chunks: Vec<(i32, i32)>,
|
||||
Permutation: PermutationArray,
|
||||
}
|
||||
|
||||
const BLOCKS: i32 = 1;
|
||||
const BLOCKS: i32 = 100;
|
||||
|
||||
|
||||
impl AppState {
|
||||
// We don't need this to be async right now,
|
||||
|
|
@ -48,6 +55,9 @@ impl AppState {
|
|||
pub async fn new(window: Arc<Window>) -> Result<AppState, Box<dyn std::error::Error>> {
|
||||
let mut world = World::new();
|
||||
world.add_renderer(Renderer::new(&window).await?);
|
||||
let mut Permutation: PermutationArray = PermutationArray::new();
|
||||
Permutation.generate_permutation_array(0);
|
||||
let mut chunks = Vec::new();
|
||||
let mut clients = Vec::new();
|
||||
{
|
||||
let file = world
|
||||
|
|
@ -65,35 +75,39 @@ impl AppState {
|
|||
//let normal = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/normal.png"));
|
||||
//let roughness = &renderer.load_texture_from_bytes(include_bytes!("assets/plank/roughness.png"));
|
||||
//let mat = renderer.new_material(color,normal,roughness);
|
||||
for x in -BLOCKS..BLOCKS {
|
||||
for y in -BLOCKS..BLOCKS {
|
||||
let block = block.hard_clone();
|
||||
world.add_object(block.clone());
|
||||
{
|
||||
let mut model = block.0.borrow_mut();
|
||||
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
|
||||
Vec3::new(-x as f32 * 3.0, -8.0, -y as f32 * 3.0),
|
||||
)
|
||||
* Mat4::from_rotation_z((x * y) as f32 / 1.23);
|
||||
model.model.as_mut().unwrap().instance.color = Vec4::new(
|
||||
0.3,
|
||||
(x + BLOCKS) as f32 / BLOCKS as f32,
|
||||
(y + BLOCKS) as f32 / BLOCKS as f32,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
clients.push(block)
|
||||
}
|
||||
}
|
||||
// for x in -BLOCKS..BLOCKS {
|
||||
// for y in -BLOCKS..BLOCKS {
|
||||
// let block = block.hard_clone();
|
||||
// world.add_object(block.clone());
|
||||
// {
|
||||
// let mut model = block.0.borrow_mut();
|
||||
// model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
|
||||
// Vec3::new(-x as f32 * 1.0, Noise2D::fractal_noise(x as f64 * 0.1, y as f64*0.1, 5, 10.0, 0.05, &Permutation).round() as i64 as f32, -y as f32 * 1.0),
|
||||
// )
|
||||
// * Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/);
|
||||
// model.model.as_mut().unwrap().instance.color = Vec4::new(
|
||||
// 0.3,
|
||||
// (x + BLOCKS) as f32 / BLOCKS as f32,
|
||||
// (y + BLOCKS) as f32 / BLOCKS as f32,
|
||||
// 1.0,
|
||||
// );
|
||||
// }
|
||||
// clients.push(block)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Ok(Self {
|
||||
world,
|
||||
clients,
|
||||
controller: Controller::new(),
|
||||
window,
|
||||
chunks,
|
||||
Permutation
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn bounds(&self) -> (u32, u32) {
|
||||
let size = self.window.inner_size();
|
||||
(size.width, size.height)
|
||||
|
|
@ -152,6 +166,42 @@ impl App {
|
|||
proxy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn GenerateChunk(ChunkX: i32, ChunkY: i32, size: i32, state: &mut AppState){
|
||||
if(state.chunks.contains(&(ChunkX, ChunkY))){
|
||||
return;
|
||||
}
|
||||
let file = state.world
|
||||
.renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.load_from_gltf(include_bytes!("assets/cube.glb"));
|
||||
let block = file.first_object().unwrap();
|
||||
|
||||
for x in 0..size {
|
||||
for y in 0..size {
|
||||
let worldPosX = ChunkX * size + x;
|
||||
let worldPosY = ChunkY * size + y;
|
||||
let block = block.hard_clone();
|
||||
state.world.add_object(block.clone());
|
||||
{
|
||||
let mut model = block.0.borrow_mut();
|
||||
model.model.as_mut().unwrap().instance.transform = Mat4::from_translation(
|
||||
Vec3::new(worldPosX as f32 * 1.0, Noise2D::fractal_noise(worldPosX as f64 * 0.25, worldPosY as f64*0.25, 10, 20.0, 0.05, &state.Permutation).round() as i64 as f32, worldPosY as f32 * 1.0),
|
||||
)
|
||||
* Mat4::from_rotation_z(0f32 /*(x * y) as f32 / 1.23*/);
|
||||
model.model.as_mut().unwrap().instance.color = Vec4::new(
|
||||
0.3,
|
||||
(x + size) as f32 / size as f32,
|
||||
(y + size) as f32 / size as f32,
|
||||
1.0,
|
||||
);
|
||||
}
|
||||
state.clients.push(block);
|
||||
}
|
||||
}
|
||||
state.chunks.push((ChunkX, ChunkY));
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler<AppState> for App {
|
||||
|
|
@ -261,13 +311,28 @@ impl ApplicationHandler<AppState> for App {
|
|||
movement.y -= 1.0;
|
||||
}
|
||||
|
||||
let PosX = state.world.renderer.as_ref().unwrap().eye.frame.translation.x;
|
||||
let Posy = state.world.renderer.as_ref().unwrap().eye.frame.translation.z;
|
||||
|
||||
let WorldPosX = (PosX / 16.0).floor() as i32;
|
||||
let WorldPosY = (Posy / 16.0).floor() as i32;
|
||||
let startX = WorldPosX - 5;
|
||||
let endX = WorldPosX + 5;
|
||||
let startY = WorldPosY - 5;
|
||||
let endY = WorldPosY + 5;
|
||||
|
||||
for x in startX..endX {
|
||||
for y in startY..endY {
|
||||
App::GenerateChunk(x, y, 16, state);
|
||||
}
|
||||
}
|
||||
state
|
||||
.world
|
||||
.renderer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.eye
|
||||
.control(movement * 0.1);
|
||||
.control(movement * 0.5);
|
||||
match state.world.renderer.as_mut().unwrap().render(&state.window) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
|
|
@ -285,7 +350,7 @@ impl ApplicationHandler<AppState> for App {
|
|||
.unwrap()
|
||||
.instance
|
||||
.transform *= Mat4::from_rotation_translation(
|
||||
Quat::from_euler(EulerRot::XYZ, 0.001, -0.001, 0.001),
|
||||
Quat::from_euler(EulerRot::XYZ,0.00,0.00,0.00 /*0.001, -0.001, 0.001*/),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
);
|
||||
}
|
||||
|
|
@ -308,6 +373,9 @@ impl ApplicationHandler<AppState> for App {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
pub fn run() -> anyhow::Result<()> {
|
||||
|
|
|
|||
|
|
@ -3,3 +3,5 @@ pub mod app;
|
|||
pub mod render;
|
||||
pub mod web;
|
||||
pub mod world;
|
||||
pub mod permutation_array;
|
||||
pub mod noise2d;
|
||||
97
src/noise2d.rs
Normal file
97
src/noise2d.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
use crate::permutation_array;
|
||||
use crate::permutation_array::PermutationArray;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Vector2d {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
impl Vector2d {
|
||||
pub fn new(x: f64, y: f64) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub fn dot(&self, other: Vector2d) -> f64 {
|
||||
self.x * other.x + self.y * other.y
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Noise2D;
|
||||
|
||||
impl Noise2D {
|
||||
pub fn gen_gradient_vector(p: i32) -> Vector2d {
|
||||
match p & 3 {
|
||||
0 => Vector2d::new(1.0, 1.0),
|
||||
1 => Vector2d::new(-1.0, 1.0),
|
||||
2 => Vector2d::new(-1.0, -1.0),
|
||||
_ => Vector2d::new(1.0, -1.0),
|
||||
}
|
||||
}
|
||||
|
||||
fn fade(t: f64) -> f64 {
|
||||
t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
|
||||
}
|
||||
|
||||
fn lerp(t: f64, x: f64, y: f64) -> f64 {
|
||||
x + t * (y - x)
|
||||
}
|
||||
|
||||
pub fn noise_2d(x: f64, y: f64, permutation: &[i32; 512]) -> f64 {
|
||||
let x_floor = x.floor();
|
||||
let y_floor = y.floor();
|
||||
|
||||
let x_grid = (x_floor as i32) & 255;
|
||||
let y_grid = (y_floor as i32) & 255;
|
||||
|
||||
let xd = x - x_floor;
|
||||
let yd = y - y_floor;
|
||||
|
||||
let tr = Vector2d::new(xd - 1.0, yd - 1.0);
|
||||
let tl = Vector2d::new(xd, yd - 1.0);
|
||||
let br = Vector2d::new(xd - 1.0, yd);
|
||||
let bl = Vector2d::new(xd, yd);
|
||||
|
||||
let x_idx = x_grid as usize;
|
||||
let y_idx = y_grid as usize;
|
||||
|
||||
let value_tr = permutation[permutation[x_idx + 1] as usize + y_idx + 1];
|
||||
let value_tl = permutation[permutation[x_idx] as usize + y_idx + 1];
|
||||
let value_br = permutation[permutation[x_idx + 1] as usize + y_idx];
|
||||
let value_bl = permutation[permutation[x_idx] as usize + y_idx];
|
||||
|
||||
let d_tr = tr.dot(Self::gen_gradient_vector(value_tr));
|
||||
let d_tl = tl.dot(Self::gen_gradient_vector(value_tl));
|
||||
let d_br = br.dot(Self::gen_gradient_vector(value_br));
|
||||
let d_bl = bl.dot(Self::gen_gradient_vector(value_bl));
|
||||
|
||||
let u = Self::fade(xd);
|
||||
let v = Self::fade(yd);
|
||||
|
||||
Self::lerp(
|
||||
u,
|
||||
Self::lerp(v, d_bl, d_tl),
|
||||
Self::lerp(v, d_br, d_tr),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fractal_noise(
|
||||
x: f64,
|
||||
y: f64,
|
||||
octaves: i32,
|
||||
mut amplitude: f64,
|
||||
mut frequency: f64,
|
||||
permutation: &PermutationArray,
|
||||
) -> f64 {
|
||||
let mut fractal_noise = 0.0;
|
||||
|
||||
for _ in 0..octaves {
|
||||
let layer = amplitude * Self::noise_2d(x * frequency, y * frequency, permutation.get_permutation());
|
||||
fractal_noise += layer;
|
||||
amplitude *= 0.5;
|
||||
frequency *= 2.0;
|
||||
}
|
||||
|
||||
fractal_noise
|
||||
}
|
||||
}
|
||||
39
src/permutation_array.rs
Normal file
39
src/permutation_array.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
use rand::{Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
//i translated the Terrain4J Noise2D to Rust so i can mess around with the cubes
|
||||
pub struct PermutationArray {
|
||||
permutation: [i32; 512],
|
||||
}
|
||||
|
||||
impl PermutationArray {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
permutation: [0; 512],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_permutation(&self) -> &[i32; 512] {
|
||||
&self.permutation
|
||||
}
|
||||
|
||||
pub fn generate_permutation_array(&mut self, seed: i64) {
|
||||
let mut seed_bytes = [0u8; 32];
|
||||
seed_bytes[0..8].copy_from_slice(&(seed as u64).to_le_bytes());
|
||||
let mut rnd = ChaCha8Rng::from_seed(seed_bytes);
|
||||
|
||||
self.permutation = [0; 512];
|
||||
for i in 0..256 {
|
||||
self.permutation[i] = i as i32;
|
||||
}
|
||||
|
||||
for p in (1..256).rev() {
|
||||
let index = rnd.gen_range(0..=p);
|
||||
self.permutation.swap(p, index);
|
||||
}
|
||||
|
||||
for i in 0..256 {
|
||||
self.permutation[i + 256] = self.permutation[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue