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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright (c) 2024 Melody Madeline Lyons
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use fmod_sys::*;
use std::ffi::{c_float, c_int};
use crate::{FmodResultExt, Result};
use crate::{Geometry, System, Vector};
impl System {
/// [`Geometry`] creation function. This function will create a base geometry object which can then have polygons added to it.
///
/// Polygons can be added to a geometry object using [`Geometry::add_polygon`]. For best efficiency, avoid overlapping of polygons and long thin polygons.
///
/// A geometry object stores its polygons in a group to allow optimization for line testing, insertion and updating of geometry in real-time.
/// Geometry objects also allow for efficient rotation, scaling and translation of groups of polygons.
///
/// It is important to set the value of maxworldsize to an appropriate value using [`System::set_geometry_settings`].
pub fn create_geometry(&self, max_polygons: c_int, max_vertices: c_int) -> Result<Geometry> {
let mut geometry = std::ptr::null_mut();
unsafe {
FMOD_System_CreateGeometry(
self.inner.as_ptr(),
max_polygons,
max_vertices,
&raw mut geometry,
)
.to_result()?;
Ok(Geometry::from_ffi(geometry))
}
}
/// Sets the maximum world size for the geometry engine for performance / precision reasons.
///
/// FMOD uses an efficient spatial partitioning system to store polygons for ray casting purposes.
/// The maximum size of the world should (`max_world_size`) be set to allow processing within a known range.
/// Outside of this range, objects and polygons will not be processed as efficiently.
/// Excessive world size settings can also cause loss of precision and efficiency.
///
/// Setting `max_world_size` should be done first before creating any geometry.
/// It can be done any time afterwards but may be slow in this case.
pub fn set_geometry_settings(&self, max_world_size: c_float) -> Result<()> {
unsafe { FMOD_System_SetGeometrySettings(self.inner.as_ptr(), max_world_size).to_result() }
}
/// Retrieves the maximum world size for the geometry engine.
///
/// FMOD uses an efficient spatial partitioning system to store polygons for ray casting purposes.
/// The maximum size of the world should (`max_world_size`) be set to allow processing within a known range.
/// Outside of this range, objects and polygons will not be processed as efficiently.
/// Excessive world size settings can also cause loss of precision and efficiency.
pub fn get_geometry_settings(&self) -> Result<c_float> {
let mut max_world_size = 0.0;
unsafe {
FMOD_System_GetGeometrySettings(self.inner.as_ptr(), &raw mut max_world_size)
.to_result()?;
}
Ok(max_world_size)
}
/// Creates a geometry object from a block of memory which contains pre-saved geometry data.
///
/// This function avoids the need to manually create and add geometry for faster start time.
pub fn load_geometry(&self, data: &[u8]) -> Result<Geometry> {
let mut geometry = std::ptr::null_mut();
unsafe {
FMOD_System_LoadGeometry(
self.inner.as_ptr(),
data.as_ptr().cast(),
data.len() as c_int,
&raw mut geometry,
)
.to_result()?;
Ok(Geometry::from_ffi(geometry))
}
}
/// Calculates geometry occlusion between a listener and a sound source.
///
/// If single sided polygons have been created, it is important to get the source and listener positions around the right way,
/// as the occlusion from point A to point B may not be the same as the occlusion from point B to point A.
pub fn get_geometry_occlusion(
&self,
listener: Vector,
source: Vector,
) -> Result<(c_float, c_float)> {
let mut direct = 0.0;
let mut reverb = 0.0;
unsafe {
FMOD_System_GetGeometryOcclusion(
self.inner.as_ptr(),
std::ptr::from_ref(&listener).cast(),
std::ptr::from_ref(&source).cast(),
&raw mut direct,
&raw mut reverb,
)
.to_result()?;
}
Ok((direct, reverb))
}
}