Skip to main content

noise_rs_ffi/
lib.rs

1// Copyright 2016 Phoenix Enero.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Exposes a subset of functions from `noise-rs` in a C-compatible FFI
10//! interface.
11//!
12//! ## Usage
13//!
14//! Use this library in a non-Rust setting. If you're programming in rust, just
15//! use `noise-rs` directly.
16//!
17//! ### Creating a Seed object
18//!
19//! Create a Seed using the `noise_seed_new` function. It accepts an unsigned
20//! 32-bit integer and returns a new pointer to the Seed object.
21//!
22//! ```c
23//! Seed *seed = noise_seed_new((uint32_t) 42);
24//! ```
25//!
26//! ### Using the Seed object for generating noise
27//!
28//! You can now use that pointer with the noise generation functions. Here's an
29//! example using 3D Perlin noise.
30//!
31//! ```c
32//! double val = noise_perlin3(seed, 0.2, 0.3, 1.5);
33//! ```
34//!
35//! ### Freeing the Seed object
36//!
37//! When you're done using the Seed object, you'll need to free it. To do that,
38//! use the `noise_seed_delete` function.
39//!
40//! ```c
41//! noise_seed_delete(seed);
42//! ```
43
44extern crate libc;
45extern crate noise;
46
47use libc::{c_double, uint32_t};
48
49/// Moves `x` onto the heap and returns a mutable pointer to it.
50fn heap_mut_ptr<T>(x: T) -> *mut T {
51    Box::into_raw(Box::new(x))
52}
53
54/// Returns a pointer to a heap-allocated `noise::Seed`. You must call
55/// `noise_seed_delete` to free the returned seed.
56#[no_mangle]
57pub unsafe extern "C" fn noise_seed_new(seed: uint32_t) -> *mut noise::Seed {
58    heap_mut_ptr(noise::Seed::new(seed as u32))
59}
60
61/// Delete the seed object.
62///
63/// ## C function signature
64#[no_mangle]
65pub unsafe extern "C" fn noise_seed_delete(seed: *mut noise::Seed) {
66    let seed = Box::from_raw(seed);
67    drop(seed)
68}
69
70macro_rules! wrap_noise {
71    ($wrapper_name:ident, $t:ty, $alg:expr, 2) => {
72        wrap_noise!($wrapper_name, $t, $alg, x, y);
73    };
74    ($wrapper_name:ident, $t:ty, $alg:expr, 3) => {
75        wrap_noise!($wrapper_name, $t, $alg, x, y, z);
76    };
77    ($wrapper_name:ident, $t:ty, $alg:expr, 4) => {
78        wrap_noise!($wrapper_name, $t, $alg, x, y, z, w);
79    };
80    ($wrapper_name:ident, $t:ty, $alg:expr $(, $arg:ident)*) => {
81        /// Generate noise values at position using a Seed object.
82        #[no_mangle]
83        pub unsafe fn $wrapper_name(seed: *mut noise::Seed $(, $arg: $t)*) -> $t {
84            let seed: &noise::Seed = &*seed;
85            $alg(&seed, &[$($arg),*])
86        }
87    };
88}
89
90// Perlin Noise
91wrap_noise!(noise_perlin2, c_double, noise::perlin2, 2);
92wrap_noise!(noise_perlin3, c_double, noise::perlin3, 3);
93wrap_noise!(noise_perlin4, c_double, noise::perlin4, 4);
94
95// OpenSimplex Noise
96wrap_noise!(noise_open_simplex2, c_double, noise::open_simplex2, 2);
97wrap_noise!(noise_open_simplex3, c_double, noise::open_simplex3, 3);
98
99// Cell noise (euclidean distance)
100wrap_noise!(noise_cell2_value, c_double, noise::cell2_value, 2);
101wrap_noise!(noise_cell3_value, c_double, noise::cell3_value, 3);
102wrap_noise!(noise_cell4_value, c_double, noise::cell4_value, 4);
103
104wrap_noise!(noise_cell2_range, c_double, noise::cell2_range, 2);
105wrap_noise!(noise_cell3_range, c_double, noise::cell3_range, 3);
106wrap_noise!(noise_cell4_range, c_double, noise::cell4_range, 4);
107
108wrap_noise!(noise_cell2_range_inv, c_double, noise::cell2_range_inv, 2);
109wrap_noise!(noise_cell3_range_inv, c_double, noise::cell3_range_inv, 3);
110wrap_noise!(noise_cell4_range_inv, c_double, noise::cell4_range_inv, 4);
111
112// Cell noise (Manhattan distance)
113wrap_noise!(noise_cell2_manhattan_value, c_double, noise::cell2_manhattan_value, 2);
114wrap_noise!(noise_cell3_manhattan_value, c_double, noise::cell3_manhattan_value, 3);
115wrap_noise!(noise_cell4_manhattan_value, c_double, noise::cell4_manhattan_value, 4);
116
117wrap_noise!(noise_cell2_manhattan_range, c_double, noise::cell2_manhattan, 2);
118wrap_noise!(noise_cell3_manhattan_range, c_double, noise::cell3_manhattan, 3);
119wrap_noise!(noise_cell4_manhattan_range, c_double, noise::cell4_manhattan, 4);
120
121wrap_noise!(noise_cell2_manhattan_range_inv, c_double, noise::cell2_manhattan_inv, 2);
122wrap_noise!(noise_cell3_manhattan_range_inv, c_double, noise::cell3_manhattan_inv, 3);
123wrap_noise!(noise_cell4_manhattan_range_inv, c_double, noise::cell4_manhattan_inv, 4);