1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#![allow(dead_code, non_snake_case)]

use std::mem;
extern crate libc;
use libc::{ c_int, c_double, int64_t, int16_t, c_void };

#[repr(C)]
struct RawOsnContext {
    perm: *const int64_t,
    permGradIndex3D: *const int64_t,
}

#[link(name = "opensimplex")]
extern {
    fn open_simplex_noise(seed: int64_t, ctx: *mut *mut RawOsnContext) -> c_int;
    fn open_simplex_noise_free(ctx: *mut RawOsnContext) -> c_void;
    fn open_simplex_noise_init_perm(ctx: *mut RawOsnContext, p: *const int16_t, nelements: c_int) -> c_int;
    fn open_simplex_noise2(ctx: *const RawOsnContext, x: c_double, y: c_double) -> c_double;
    fn open_simplex_noise3(ctx: *const RawOsnContext, x: c_double, y: c_double, z: c_double) -> c_double;
    fn open_simplex_noise4(ctx: *const RawOsnContext, x: c_double, y: c_double, z: c_double, w: c_double) -> c_double;
}

pub struct OsnContext {
    ctx: *mut RawOsnContext,
}

impl Drop for OsnContext {
    fn drop(&mut self) {
        unsafe { open_simplex_noise_free(self.ctx) };
    }
}

impl OsnContext {
    pub fn new(seed: i64) -> Option<OsnContext> {
        let mut ctx: *mut RawOsnContext = unsafe { mem::uninitialized() };
        let res = unsafe { open_simplex_noise(seed, &mut ctx as *mut *mut RawOsnContext) };
        if res == 0 {
            Some(OsnContext {
                ctx: ctx,
            })
        } else {
            None
        }
    }

    unsafe fn as_c_arg(&self) -> *mut RawOsnContext {
        self.ctx as *mut RawOsnContext
    }

    pub fn noise2(&self, x: f64, y: f64) -> f64 {
        unsafe { open_simplex_noise2(self.as_c_arg(), x, y) }
    }
    pub fn noise3(&self, x: f64, y: f64, z: f64) -> f64 {
        unsafe { open_simplex_noise3(self.as_c_arg(), x, y, z) }
    }
    pub fn noise4(&self, x: f64, y: f64, z: f64, w: f64) -> f64 {
        unsafe { open_simplex_noise4(self.as_c_arg(), x, y, z, w) }
    }
}

#[test]
fn test_basics() {
    let ctx = OsnContext::new(123).unwrap();
    let ctx2 = OsnContext::new(122).unwrap();

    assert!(ctx.noise2(1.0, 1.0) != ctx2.noise2(1.0, 1.0));
    assert!(ctx.noise2(1.0, 1.0) == ctx.noise2(1.0, 1.0));

    assert!(ctx.noise3(1.0, 1.0, 1.0) != ctx2.noise3(1.0, 1.0, 1.0));
    assert!(ctx.noise3(1.0, 1.0, 1.0) == ctx.noise3(1.0, 1.0, 1.0));

    assert!(ctx.noise4(1.0, 1.0, 1.0, 1.0) != ctx2.noise4(1.0, 1.0, 1.0, 1.0));
    assert!(ctx.noise4(1.0, 1.0, 1.0, 1.0) == ctx.noise4(1.0, 1.0, 1.0, 1.0));
}