extern crate noise;
extern crate rexpaint;
use noise::{NoiseFn, Perlin, Turbulence};
use rand::random;
use rexpaint::{XpColor, XpFile};
use std::env;
use std::fs::File;
#[cfg_attr(rustfmt, rustfmt_skip)]
const CMAP_FIRE: &'static [XpColor] = &[
XpColor { r: 0, g: 0, b: 0 },
XpColor { r: 255, g: 0, b: 0 },
XpColor { r: 255, g: 255, b: 0 },
XpColor { r: 255, g: 255, b: 255 },
];
#[cfg_attr(rustfmt, rustfmt_skip)]
const CMAP_NEBULA: &'static [XpColor] = &[
XpColor { r: 0, g: 0, b: 0 },
XpColor { r: 0, g: 0, b: 128 },
XpColor { r: 128, g: 0, b: 254 },
];
fn lerp(a: XpColor, b: XpColor, i: f32) -> XpColor {
if i <= 0.0 {
a
} else if i >= 1.0 {
b
} else {
XpColor::new(
((a.r as f32) * (1.0 - i) + (b.r as f32) * i) as u8,
((a.g as f32) * (1.0 - i) + (b.g as f32) * i) as u8,
((a.b as f32) * (1.0 - i) + (b.b as f32) * i) as u8,
)
}
}
fn cmap_lookup(cmap: &[XpColor], value: f32) -> XpColor {
let i = ((value + 1.0) / 2.0) * ((cmap.len() - 1) as f32);
let n = (i as i32).max(0).min((cmap.len() as i32) - 2);
lerp(cmap[n as usize], cmap[n as usize + 1], i - n as f32)
}
fn main() {
let args: Vec<String> = env::args().collect();
let width = args
.get(1)
.and_then(|x| x.parse::<usize>().ok())
.unwrap_or(80);
let height = args
.get(2)
.and_then(|x| x.parse::<usize>().ok())
.unwrap_or(60);
let cmap_name = args.get(3).cloned().unwrap_or("fire".to_string());
let mut xp = XpFile::new(width, height);
let cmap = if cmap_name == "fire" {
CMAP_FIRE
} else if cmap_name == "nebula" {
CMAP_NEBULA
} else {
panic!("unknown color map {}", cmap_name);
};
println!(
"generating {}×{} noise.xp, color map \"{}\"",
width, height, cmap_name
);
let perlin = Perlin::new(random());
let turbulence = Turbulence::<_, Perlin>::new(&perlin);
for y in 0..height {
for x in 0..width {
let val = turbulence.get([
(x as f64) / ((width - 1) as f64),
(y as f64) / ((height - 1) as f64),
]) as f32;
let cell = xp.layers[0].get_mut(x, y).unwrap();
cell.bg = cmap_lookup(cmap, val);
}
}
let mut f = File::create("noise.xp").unwrap();
xp.write(&mut f).unwrap();
}