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
//! Geometry-neutral reusable scalar fields.
#[diplomat::bridge]
pub mod ffi {
use super::super::shared::ffi::NucleationError;
use diplomat_runtime::{DiplomatStr, DiplomatWrite};
use std::fmt::Write;
/// The closed interval a field's values are analytically proven to lie in.
#[diplomat::out]
pub struct FieldRange {
pub min: f32,
pub max: f32,
}
/// Immutable scalar field evaluated over world-space `(x, y, z)`.
///
/// A `Field3` has scalar semantics only. It may be shared by geometry and
/// material consumers without being reinterpreted as a signed-distance field.
#[diplomat::opaque]
pub struct Field3(pub(crate) crate::field::Field3);
impl Field3 {
/// Deterministic value-noise FBM normalized to `[-1, 1]`.
pub fn value_noise_fbm(
frequency: f32,
seed: i32,
octaves: u32,
) -> Result<Box<Field3>, NucleationError> {
crate::field::Field3::value_noise_fbm(frequency, seed, octaves)
.map(|field| Box::new(Field3(field)))
.map_err(|_| NucleationError::InvalidArgument)
}
pub fn eval_at(&self, x: f32, y: f32, z: f32) -> f32 {
self.0.eval(x, y, z)
}
/// The field's analytically proven output range.
///
/// Returns `NotFound` when no range can be proven — callers mapping a
/// field onto a gradient must handle that rather than silently
/// propagating a sentinel into their `lo`/`hi` bounds.
pub fn output_range(&self) -> Result<FieldRange, NucleationError> {
self.0
.output_range()
.map(|range| FieldRange {
min: range[0],
max: range[1],
})
.ok_or(NucleationError::NotFound)
}
pub fn from_json_string(json: &DiplomatStr) -> Result<Box<Field3>, NucleationError> {
let json = std::str::from_utf8(json).map_err(|_| NucleationError::InvalidArgument)?;
crate::field::Field3::from_json(json)
.map(|field| Box::new(Field3(field)))
.map_err(|_| NucleationError::Parse)
}
pub fn to_json(&self, write: &mut DiplomatWrite) -> Result<(), NucleationError> {
let json = self.0.to_json().map_err(|_| NucleationError::Serialize)?;
let _ = write!(write, "{json}");
Ok(())
}
}
}