extracted noise and sampler modules
This commit is contained in:
parent
a81f464567
commit
fc2055b65f
4 changed files with 116 additions and 107 deletions
|
@ -1,8 +1,8 @@
|
|||
var ctx;
|
||||
var image;
|
||||
var memory;
|
||||
const width = 256;
|
||||
const height = 224;
|
||||
const width = 160;
|
||||
const height = 144;
|
||||
|
||||
function blit_frame() {
|
||||
ctx.putImageData(image, 0, 0);
|
||||
|
|
|
@ -14,6 +14,9 @@ use libm::{self, Libm};
|
|||
extern crate nalgebra as na;
|
||||
use nalgebra::{Vector2};
|
||||
|
||||
mod sampler;
|
||||
mod noise;
|
||||
|
||||
extern {
|
||||
fn blit_frame();
|
||||
fn blit_text(text: *const u8, len: u32, x: i32, y: i32, size: u8);
|
||||
|
@ -28,8 +31,8 @@ fn draw_text(text: &str, x: i32, y: i32, size: u8) {
|
|||
}
|
||||
}
|
||||
|
||||
const WIDTH: usize = 256;
|
||||
const HEIGHT: usize = 224;
|
||||
const WIDTH: usize = 160;
|
||||
const HEIGHT: usize = 144;
|
||||
|
||||
#[no_mangle]
|
||||
static mut BUFFER: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
||||
|
@ -77,7 +80,7 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) {
|
|||
let offset = Vector2::new(64120.0, 7320.0);
|
||||
let point = point + offset;
|
||||
let mut n = 0.0;
|
||||
n += (sample_map_inter(point / 64.0, &MAP)-0.5)* 0.6;
|
||||
n += (sampler::sample_map_inter(point / 64.0, &MAP)-0.5)* 0.6;
|
||||
n += noise::noise(point / 64.0, rand) / 1.0;
|
||||
n += noise::noise(point / 32.0, rand) / 2.0;
|
||||
n += noise::noise(point / 16.0, rand) / 4.0;
|
||||
|
@ -102,38 +105,6 @@ fn render_frame(buffer: &mut [u32; WIDTH*HEIGHT]) {
|
|||
//draw_text("hi from rust", 0,100,30);
|
||||
}
|
||||
|
||||
fn sample_map_inter(point: Vector2<f32>, map: &[u8]) -> f32 {
|
||||
let x = libm::floorf(point.x) as usize % MAP_WIDTH;
|
||||
let y = libm::floorf(point.y) as usize % MAP_HEIGHT;
|
||||
let p0 = Vector2::new(libm::floorf(point.x), libm::floorf(point.y));
|
||||
let p1 = p0 + Vector2::new(1.0, 0.0);
|
||||
let p2 = p0 + Vector2::new(0.0, 1.0);
|
||||
let p3 = p0 + Vector2::new(1.0, 1.0);
|
||||
|
||||
let tx = point.x - libm::floorf(point.x);
|
||||
let ty = point.y - libm::floorf(point.y);
|
||||
|
||||
let top = (1.0 - tx) * sample_map(p0, map) as f32 + tx * sample_map(p1, map) as f32;
|
||||
let bot = (1.0 - tx) * sample_map(p2, map) as f32 + tx * sample_map(p3, map) as f32;
|
||||
|
||||
(1.0-ty) * top + ty * bot
|
||||
}
|
||||
|
||||
fn sample_map(point: Vector2<f32>, map: &[u8]) -> u8 {
|
||||
const MARGIN: usize = 3;
|
||||
let x = libm::floorf(point.x) as usize % (MAP_WIDTH + MARGIN);
|
||||
let y = libm::floorf(point.y) as usize % (MAP_HEIGHT + MARGIN);
|
||||
|
||||
if x >= MAP_WIDTH || y >= MAP_HEIGHT {
|
||||
if x-y > 12 {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
map[y*MAP_WIDTH + x]
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -146,73 +117,3 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
mod noise {
|
||||
use libm::Libm;
|
||||
use nalgebra::Vector2;
|
||||
|
||||
pub type PerlinBuf = [u32; 512];
|
||||
|
||||
pub fn generate(seed: u32) -> PerlinBuf {
|
||||
let mut rand = seed;
|
||||
let mut data: PerlinBuf = [0; 512];
|
||||
for item in data.iter_mut() {
|
||||
rand = xorshift(rand);
|
||||
*item = rand;
|
||||
}
|
||||
|
||||
data
|
||||
}
|
||||
|
||||
fn xorshift(state: u32) -> u32 {
|
||||
// impl from wikipedia
|
||||
let mut state = state;
|
||||
state ^= state << 13;
|
||||
state ^= state >> 17;
|
||||
state ^= state << 5;
|
||||
state
|
||||
}
|
||||
|
||||
fn fade(t: f32) -> f32 {
|
||||
t*t*t*(t*(t*6.0-15.0)+10.0)
|
||||
}
|
||||
|
||||
fn lerp(a: f32, b:f32, d:f32) -> f32 {
|
||||
a * (1.0-d) + b * d
|
||||
}
|
||||
|
||||
fn grad(p: Vector2<f32>, b: PerlinBuf) -> Vector2<f32> {
|
||||
const width: usize = 16;
|
||||
|
||||
|
||||
let x = p.x as usize % width;
|
||||
let y = p.y as usize % width;
|
||||
|
||||
let one = b[x*width + y] as f32;
|
||||
let two = b[(x*width + y + 1)%512] as f32;
|
||||
|
||||
Vector2::new(one, two).normalize()
|
||||
}
|
||||
|
||||
pub fn noise(p: Vector2<f32>, b: PerlinBuf) -> f32 {
|
||||
let p0 = Vector2::new(libm::floorf(p.x), libm::floorf(p.y));
|
||||
let p1 = p0 + Vector2::new(1.0, 0.0);
|
||||
let p2 = p0 + Vector2::new(0.0, 1.0);
|
||||
let p3 = p0 + Vector2::new(1.0, 1.0);
|
||||
|
||||
let g0 = grad(p0, b);
|
||||
let g1 = grad(p1, b);
|
||||
let g2 = grad(p2, b);
|
||||
let g3 = grad(p3, b);
|
||||
|
||||
let tx = p.x - p0.x;
|
||||
let ftx = fade(tx);
|
||||
let ty = p.y - p0.y;
|
||||
let fty = fade(ty);
|
||||
|
||||
let p0p1 = (1.0 - ftx) * g0.dot(&(p-p0)) + ftx * g1.dot(&(p-p1));
|
||||
let p2p3 = (1.0 - ftx) * g2.dot(&(p-p2)) + ftx * g3.dot(&(p-p3));
|
||||
|
||||
|
||||
(1.0 - fty) * p0p1 + fty * p2p3
|
||||
}
|
||||
}
|
||||
|
|
68
pirates/src/noise.rs
Normal file
68
pirates/src/noise.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use libm::Libm;
|
||||
use nalgebra::Vector2;
|
||||
|
||||
pub type PerlinBuf = [u32; 512];
|
||||
|
||||
pub fn generate(seed: u32) -> PerlinBuf {
|
||||
let mut rand = seed;
|
||||
let mut data: PerlinBuf = [0; 512];
|
||||
for item in data.iter_mut() {
|
||||
rand = xorshift(rand);
|
||||
*item = rand;
|
||||
}
|
||||
|
||||
data
|
||||
}
|
||||
|
||||
fn xorshift(state: u32) -> u32 {
|
||||
// impl from wikipedia
|
||||
let mut state = state;
|
||||
state ^= state << 13;
|
||||
state ^= state >> 17;
|
||||
state ^= state << 5;
|
||||
state
|
||||
}
|
||||
|
||||
fn fade(t: f32) -> f32 {
|
||||
t*t*t*(t*(t*6.0-15.0)+10.0)
|
||||
}
|
||||
|
||||
fn lerp(a: f32, b:f32, d:f32) -> f32 {
|
||||
a * (1.0-d) + b * d
|
||||
}
|
||||
|
||||
fn grad(p: Vector2<f32>, b: PerlinBuf) -> Vector2<f32> {
|
||||
const width: usize = 16;
|
||||
|
||||
|
||||
let x = p.x as usize % width;
|
||||
let y = p.y as usize % width;
|
||||
|
||||
let one = b[x*width + y] as f32;
|
||||
let two = b[(x*width + y + 1)%512] as f32;
|
||||
|
||||
Vector2::new(one, two).normalize()
|
||||
}
|
||||
|
||||
pub fn noise(p: Vector2<f32>, b: PerlinBuf) -> f32 {
|
||||
let p0 = Vector2::new(libm::floorf(p.x), libm::floorf(p.y));
|
||||
let p1 = p0 + Vector2::new(1.0, 0.0);
|
||||
let p2 = p0 + Vector2::new(0.0, 1.0);
|
||||
let p3 = p0 + Vector2::new(1.0, 1.0);
|
||||
|
||||
let g0 = grad(p0, b);
|
||||
let g1 = grad(p1, b);
|
||||
let g2 = grad(p2, b);
|
||||
let g3 = grad(p3, b);
|
||||
|
||||
let tx = p.x - p0.x;
|
||||
let ftx = fade(tx);
|
||||
let ty = p.y - p0.y;
|
||||
let fty = fade(ty);
|
||||
|
||||
let p0p1 = (1.0 - ftx) * g0.dot(&(p-p0)) + ftx * g1.dot(&(p-p1));
|
||||
let p2p3 = (1.0 - ftx) * g2.dot(&(p-p2)) + ftx * g3.dot(&(p-p3));
|
||||
|
||||
|
||||
(1.0 - fty) * p0p1 + fty * p2p3
|
||||
}
|
40
pirates/src/sampler.rs
Normal file
40
pirates/src/sampler.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use super::MAP_HEIGHT;
|
||||
|
||||
use super::MAP_WIDTH;
|
||||
|
||||
use libm::Libm;
|
||||
|
||||
use nalgebra::Vector2;
|
||||
|
||||
pub(crate) fn sample_map_inter(point: Vector2<f32>, map: &[u8]) -> f32 {
|
||||
let x = libm::floorf(point.x) as usize % MAP_WIDTH;
|
||||
let y = libm::floorf(point.y) as usize % MAP_HEIGHT;
|
||||
let p0 = Vector2::new(libm::floorf(point.x), libm::floorf(point.y));
|
||||
let p1 = p0 + Vector2::new(1.0, 0.0);
|
||||
let p2 = p0 + Vector2::new(0.0, 1.0);
|
||||
let p3 = p0 + Vector2::new(1.0, 1.0);
|
||||
|
||||
let tx = point.x - libm::floorf(point.x);
|
||||
let ty = point.y - libm::floorf(point.y);
|
||||
|
||||
let top = (1.0 - tx) * sample_map(p0, map) as f32 + tx * sample_map(p1, map) as f32;
|
||||
let bot = (1.0 - tx) * sample_map(p2, map) as f32 + tx * sample_map(p3, map) as f32;
|
||||
|
||||
(1.0-ty) * top + ty * bot
|
||||
}
|
||||
|
||||
pub(crate) fn sample_map(point: Vector2<f32>, map: &[u8]) -> u8 {
|
||||
const MARGIN: usize = 3;
|
||||
let x = libm::floorf(point.x) as usize % (MAP_WIDTH + MARGIN);
|
||||
let y = libm::floorf(point.y) as usize % (MAP_HEIGHT + MARGIN);
|
||||
|
||||
if x >= MAP_WIDTH || y >= MAP_HEIGHT {
|
||||
if x-y > 12 {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
map[y*MAP_WIDTH + x]
|
||||
|
||||
}
|
Loading…
Reference in a new issue