fmod/core/system/
geometry.rs

1// Copyright (c) 2024 Lily Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use fmod_sys::*;
8use std::ffi::{c_float, c_int};
9
10use crate::{Geometry, System, Vector};
11
12impl System {
13    /// [`Geometry`] creation function. This function will create a base geometry object which can then have polygons added to it.
14    ///
15    /// Polygons can be added to a geometry object using [`Geometry::add_polygon`]. For best efficiency, avoid overlapping of polygons and long thin polygons.
16    ///
17    /// A geometry object stores its polygons in a group to allow optimization for line testing, insertion and updating of geometry in real-time.
18    /// Geometry objects also allow for efficient rotation, scaling and translation of groups of polygons.
19    ///
20    /// It is important to set the value of maxworldsize to an appropriate value using [`System::set_geometry_settings`].
21    pub fn create_geometry(&self, max_polygons: c_int, max_vertices: c_int) -> Result<Geometry> {
22        let mut geometry = std::ptr::null_mut();
23        unsafe {
24            FMOD_System_CreateGeometry(self.inner, max_polygons, max_vertices, &mut geometry)
25                .to_result()?;
26        }
27        Ok(geometry.into())
28    }
29
30    /// Sets the maximum world size for the geometry engine for performance / precision reasons.
31    ///
32    /// FMOD uses an efficient spatial partitioning system to store polygons for ray casting purposes.
33    /// The maximum size of the world should (`max_world_size`) be set to allow processing within a known range.
34    /// Outside of this range, objects and polygons will not be processed as efficiently.
35    /// Excessive world size settings can also cause loss of precision and efficiency.
36    ///
37    /// Setting `max_world_size` should be done first before creating any geometry.
38    /// It can be done any time afterwards but may be slow in this case.
39    pub fn set_geometry_settings(&self, max_world_size: c_float) -> Result<()> {
40        unsafe { FMOD_System_SetGeometrySettings(self.inner, max_world_size).to_result() }
41    }
42
43    /// Retrieves the maximum world size for the geometry engine.
44    ///
45    /// FMOD uses an efficient spatial partitioning system to store polygons for ray casting purposes.
46    /// The maximum size of the world should (`max_world_size`) be set to allow processing within a known range.
47    /// Outside of this range, objects and polygons will not be processed as efficiently.
48    /// Excessive world size settings can also cause loss of precision and efficiency.
49    pub fn get_geometry_settings(&self) -> Result<c_float> {
50        let mut max_world_size = 0.0;
51        unsafe {
52            FMOD_System_GetGeometrySettings(self.inner, &mut max_world_size).to_result()?;
53        }
54        Ok(max_world_size)
55    }
56
57    /// Creates a geometry object from a block of memory which contains pre-saved geometry data.
58    ///
59    /// This function avoids the need to manually create and add geometry for faster start time.
60    pub fn load_geometry(&self, data: &[u8]) -> Result<Geometry> {
61        let mut geometry = std::ptr::null_mut();
62        unsafe {
63            FMOD_System_LoadGeometry(
64                self.inner,
65                data.as_ptr().cast(),
66                data.len() as c_int,
67                &mut geometry,
68            )
69            .to_result()?;
70        }
71        Ok(geometry.into())
72    }
73
74    /// Calculates geometry occlusion between a listener and a sound source.
75    ///
76    /// If single sided polygons have been created, it is important to get the source and listener positions around the right way,
77    /// as the occlusion from point A to point B may not be the same as the occlusion from point B to point A.
78    pub fn get_geometry_occlusion(
79        &self,
80        listener: Vector,
81        source: Vector,
82    ) -> Result<(c_float, c_float)> {
83        let mut direct = 0.0;
84        let mut reverb = 0.0;
85        unsafe {
86            FMOD_System_GetGeometryOcclusion(
87                self.inner,
88                std::ptr::from_ref(&listener).cast(),
89                std::ptr::from_ref(&source).cast(),
90                &mut direct,
91                &mut reverb,
92            )
93            .to_result()?;
94        }
95        Ok((direct, reverb))
96    }
97}