Implement Ken Perlin's 'Improved Noise' algorithm and add example
This commit is contained in:
parent
c206d7dc3c
commit
f68c488163
2 changed files with 161 additions and 9 deletions
50
examples/perlin.rs
Normal file
50
examples/perlin.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
|
||||
// refer to the AUTHORS file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! An example of using perlin noise
|
||||
|
||||
// Noise rendering based off rust/src/test/bench/noise.rs
|
||||
|
||||
extern mod lmath;
|
||||
|
||||
use std::uint::range;
|
||||
use lmath::noise::perlin::Perlin;
|
||||
use lmath::math::Point2;
|
||||
|
||||
static WIDTH: uint = 100;
|
||||
static HEIGHT: uint = 100;
|
||||
|
||||
fn main() {
|
||||
let symbols = [" ", "░", "▒", "▓", "█", "█"];
|
||||
let mut pixels = [[0f32, ..WIDTH], ..HEIGHT];
|
||||
|
||||
let perlin = Perlin::new::<f32>();
|
||||
|
||||
for range(0, HEIGHT) |y| {
|
||||
for range(0, WIDTH) |x| {
|
||||
pixels[y][x] = perlin.noise2(
|
||||
Point2::new(x as f32 * 0.1f32,
|
||||
y as f32 * 0.1f32)
|
||||
) * 0.5f32 + 0.5f32;
|
||||
};
|
||||
};
|
||||
|
||||
for range(0, HEIGHT) |y| {
|
||||
for range(0, WIDTH) |x| {
|
||||
print(symbols[pixels[y][x] / 0.2f32 as int]);
|
||||
}
|
||||
println("");
|
||||
}
|
||||
}
|
|
@ -13,24 +13,126 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! An implementation of Ken Perlin's [Improved Noise]
|
||||
//! (http://mrl.nyu.edu/~perlin/noise/) algorithm.
|
||||
|
||||
use std::num::cast;
|
||||
|
||||
use math::{Point2, Point3};
|
||||
|
||||
pub struct Perlin<T>;
|
||||
pub struct Perlin<T> {
|
||||
// permutation table
|
||||
priv ptable: [uint, ..512],
|
||||
}
|
||||
|
||||
impl<T> Perlin<T> {
|
||||
impl<T:Clone + Float> Perlin<T> {
|
||||
pub fn new() -> Perlin<T> {
|
||||
fail!("Not yet implemented!")
|
||||
// TODO: generate random permutation table
|
||||
Perlin { ptable: P }
|
||||
}
|
||||
|
||||
pub fn noise1(&self, _x: T) -> T {
|
||||
fail!("Not yet implemented!")
|
||||
pub fn noise1(&self, t: T) -> T {
|
||||
self.noise3(Point3::new(t, zero!(T), zero!(T)))
|
||||
}
|
||||
|
||||
pub fn noise2(&self, _pos: Point2<T>) -> T {
|
||||
fail!("Not yet implemented!")
|
||||
pub fn noise2(&self, pos: Point2<T>) -> T {
|
||||
self.noise3(Point3::new(pos.x.clone(), pos.y.clone(), zero!(T)))
|
||||
}
|
||||
|
||||
pub fn noise3(&self, _pos: Point3<T>) -> T {
|
||||
fail!("Not yet implemented!")
|
||||
pub fn noise3(&self, pos: Point3<T>) -> T {
|
||||
// Find the unit cube that contains the point
|
||||
let X = pos.x.floor().to_uint() & 255;
|
||||
let Y = pos.y.floor().to_uint() & 255;
|
||||
let Z = pos.z.floor().to_uint() & 255;
|
||||
|
||||
// Find the relative X, Y, Z of point in the cube
|
||||
let x = pos.x - pos.x.floor();
|
||||
let y = pos.y - pos.y.floor();
|
||||
let z = pos.z - pos.z.floor();
|
||||
|
||||
// Compute the fade curves for X, Y, Z
|
||||
let u = fade(x.clone());
|
||||
let v = fade(y.clone());
|
||||
let w = fade(z.clone());
|
||||
|
||||
// Hash coordinates of the 8 cube corners
|
||||
let A = self.ptable[X ] + Y;
|
||||
let AA = self.ptable[A ] + Z;
|
||||
let AB = self.ptable[A + 1] + Z;
|
||||
let B = self.ptable[X + 1] + Y;
|
||||
let BA = self.ptable[B ] + Z;
|
||||
let BB = self.ptable[B + 1] + Z;
|
||||
|
||||
// Add the blended results from the 8 corners of the cube
|
||||
lerp(w, lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA ], x.clone(), y.clone(), z.clone()),
|
||||
grad(self.ptable[BA ], x-one!(T), y.clone(), z.clone())),
|
||||
lerp(u.clone(), grad(self.ptable[AB ], x.clone(), y-one!(T), z.clone()),
|
||||
grad(self.ptable[BB ], x-one!(T), y-one!(T), z.clone()))),
|
||||
lerp(v.clone(), lerp(u.clone(), grad(self.ptable[AA + 1], x.clone(), y.clone(), z-one!(T)),
|
||||
grad(self.ptable[BA + 1], x-one!(T), y.clone(), z-one!(T))),
|
||||
lerp(u.clone(), grad(self.ptable[AB + 1], x.clone(), y-one!(T), z-one!(T)),
|
||||
grad(self.ptable[BB + 1], x-one!(T), y-one!(T), z-one!(T)))))
|
||||
}
|
||||
}
|
||||
|
||||
fn fade<T:Num + NumCast>(t: T) -> T {
|
||||
t * t * t * (t * (t * cast(6) - cast(15)) + cast(10))
|
||||
}
|
||||
|
||||
fn lerp<T:Num + NumCast>(t: T, a: T, b: T) -> T {
|
||||
a + t * (b - a)
|
||||
}
|
||||
|
||||
fn grad<T:Clone + Num + NumCast>(hash: uint, x: T, y: T, z: T) -> T {
|
||||
let h = hash & 15;
|
||||
|
||||
let u = match h {
|
||||
0..7 => x.clone(),
|
||||
_ => y.clone(),
|
||||
};
|
||||
let v = match h {
|
||||
0..3 => y.clone(),
|
||||
12 | 14 => x.clone(),
|
||||
_ => z.clone(),
|
||||
};
|
||||
|
||||
(if (h & 1) == 0 { u } else { -u }) +
|
||||
(if (h & 2) == 0 { v } else { -v })
|
||||
}
|
||||
|
||||
/// Permutation table
|
||||
static P: [uint, ..512] = [
|
||||
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
|
||||
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
|
||||
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
|
||||
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
|
||||
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
|
||||
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
|
||||
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
|
||||
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
|
||||
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
|
||||
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
|
||||
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
|
||||
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
|
||||
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
|
||||
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
|
||||
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
|
||||
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
|
||||
|
||||
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
|
||||
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
|
||||
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
|
||||
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
|
||||
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
|
||||
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
|
||||
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
|
||||
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
|
||||
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
|
||||
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
|
||||
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
|
||||
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
|
||||
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
|
||||
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
|
||||
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
|
||||
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue