embree3_arm/
scene.rs

1use std::collections::HashMap;
2use std::marker::PhantomData;
3use std::mem;
4
5use device::Device;
6use geometry::Geometry;
7use ray::{IntersectContext, Ray, RayHit};
8use ray_packet::{Ray4, RayHit4};
9use ray_stream::{RayHitN, RayN};
10use sys::*;
11
12/// A scene containing various geometry for rendering. Geometry
13/// can be added and removed by attaching and detaching it, after
14/// which the scene BVH can be built via `commit` which will
15/// return a `CommittedScene` which can be used for ray queries.
16pub struct Scene<'a> {
17    pub(crate) handle: RTCScene,
18    /// We don't need to actually keep a reference to the device,
19    /// we just need to track its lifetime for correctness
20    device: PhantomData<&'a Device>,
21    geometry: HashMap<u32, Geometry<'a>>,
22}
23
24impl<'a> Scene<'a> {
25    pub fn new(device: &'a Device) -> Scene {
26        Scene {
27            handle: unsafe { rtcNewScene(device.handle) },
28            device: PhantomData,
29            geometry: HashMap::new(),
30        }
31    }
32    /// Attach a new geometry to the scene. Returns the scene local ID which
33    /// can than be used to find the hit geometry from the ray ID member.
34    /// A geometry can only be attached to one Scene at a time, per the Embree
35    /// documentation. The geometry can be detached from the scene to move
36    /// it to another one.
37    pub fn attach_geometry(&mut self, mesh: Geometry<'a>) -> u32 {
38        let id = unsafe { rtcAttachGeometry(self.handle, mesh.handle()) };
39        self.geometry.insert(id, mesh);
40        id
41    }
42    /// Detach the geometry from the scene
43    pub fn deattach_geometry(&mut self, id: u32) -> Option<Geometry<'a>> {
44        self.geometry.remove(&id)
45    }
46    /// Look up a geometry in the scene by the ID returned from `attach_geometry`
47    pub fn get_geometry(&self, id: u32) -> Option<&Geometry<'a>> {
48        match self.geometry.get(&id) {
49            Some(g) => Some(g),
50            None => None,
51        }
52    }
53    /// Look up a geometry in the scene by the ID returned from `attach_geometry`
54    pub fn get_geometry_mut(&mut self, id: u32) -> Option<&mut Geometry<'a>> {
55        match self.geometry.get_mut(&id) {
56            Some(g) => Some(g),
57            None => None,
58        }
59    }
60    /// Get an iterator over the geometry map
61    pub fn iter(&self) -> std::collections::hash_map::Iter<u32, Geometry<'a>> {
62        self.geometry.iter()
63    }
64    /// Get an iterator over the geometry map
65    pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<u32, Geometry<'a>> {
66        self.geometry.iter_mut()
67    }
68    /// Commit the scene to build the BVH on top of the geometry to allow
69    /// for ray tracing the scene. The returned `CommittedScene` can be
70    /// used for intersection and occlusion tests. The `Scene` can't
71    /// be modified while the `CommittedScene` is active.
72    pub fn commit(&'a self) -> CommittedScene<'a> {
73        unsafe {
74            rtcCommitScene(self.handle);
75        }
76        CommittedScene { scene: &self }
77    }
78    /// Get the underlying handle to the scene, e.g. for passing it to
79    /// native code or ISPC kernels.
80    pub unsafe fn handle(&self) -> RTCScene {
81        self.handle
82    }
83}
84
85impl<'a> Drop for Scene<'a> {
86    fn drop(&mut self) {
87        unsafe {
88            rtcReleaseScene(self.handle);
89        }
90    }
91}
92
93unsafe impl<'a> Sync for Scene<'a> {}
94
95/// A committed scene with a BVH built over the geometry
96/// which can be used for ray queries.
97pub struct CommittedScene<'a> {
98    pub(crate) scene: &'a Scene<'a>,
99}
100
101impl<'a> CommittedScene<'a> {
102    pub fn intersect(&self, ctx: &mut IntersectContext, ray: &mut RayHit) {
103        unsafe {
104            rtcIntersect1(
105                self.scene.handle,
106                ctx as *mut RTCIntersectContext,
107                ray as *mut RTCRayHit,
108            );
109        }
110    }
111    pub fn occluded(&self, ctx: &mut IntersectContext, ray: &mut Ray) {
112        unsafe {
113            rtcOccluded1(
114                self.scene.handle,
115                ctx as *mut RTCIntersectContext,
116                ray as *mut RTCRay,
117            );
118        }
119    }
120    pub fn intersect4(&self, ctx: &mut IntersectContext, ray: &mut RayHit4, valid: &[i32; 4]) {
121        unsafe {
122            rtcIntersect4(
123                valid.as_ptr(),
124                self.scene.handle,
125                ctx as *mut RTCIntersectContext,
126                ray as *mut RTCRayHit4,
127            );
128        }
129    }
130    pub fn occluded4(&self, ctx: &mut IntersectContext, ray: &mut Ray4, valid: &[i32; 4]) {
131        unsafe {
132            rtcOccluded4(
133                valid.as_ptr(),
134                self.scene.handle,
135                ctx as *mut RTCIntersectContext,
136                ray as *mut RTCRay4,
137            );
138        }
139    }
140    pub fn intersect_stream_aos(&self, ctx: &mut IntersectContext, rays: &mut Vec<RayHit>) {
141        let m = rays.len();
142        unsafe {
143            rtcIntersect1M(
144                self.scene.handle,
145                ctx as *mut RTCIntersectContext,
146                rays.as_mut_ptr(),
147                m as u32,
148                mem::size_of::<RayHit>(),
149            );
150        }
151    }
152    pub fn occluded_stream_aos(&self, ctx: &mut IntersectContext, rays: &mut Vec<Ray>) {
153        let m = rays.len();
154        unsafe {
155            rtcOccluded1M(
156                self.scene.handle,
157                ctx as *mut RTCIntersectContext,
158                rays.as_mut_ptr(),
159                m as u32,
160                mem::size_of::<Ray>(),
161            );
162        }
163    }
164    pub fn intersect_stream_soa(&self, ctx: &mut IntersectContext, rays: &mut RayHitN) {
165        let n = rays.len();
166        unsafe {
167            let mut rayhit = rays.as_rayhitnp();
168            rtcIntersectNp(
169                self.scene.handle,
170                ctx as *mut RTCIntersectContext,
171                &mut rayhit as *mut RTCRayHitNp,
172                n as u32,
173            );
174        }
175    }
176    pub fn occluded_stream_soa(&self, ctx: &mut IntersectContext, rays: &mut RayN) {
177        let n = rays.len();
178        unsafe {
179            let mut r = rays.as_raynp();
180            rtcOccludedNp(
181                self.scene.handle,
182                ctx as *mut RTCIntersectContext,
183                &mut r as *mut RTCRayNp,
184                n as u32,
185            );
186        }
187    }
188    pub fn bounds(&self) -> RTCBounds {
189        let mut bounds = RTCBounds {
190            lower_x: 0.0,
191            upper_x: 0.0,
192            lower_y: 0.0,
193            upper_y: 0.0,
194            lower_z: 0.0,
195            upper_z: 0.0,
196            align0: 0.0,
197            align1: 0.0,
198        };
199        unsafe {
200            rtcGetSceneBounds(self.handle(), &mut bounds as *mut RTCBounds);
201        }
202        bounds
203    }
204    /// Get the underlying handle to the scene, e.g. for passing it to
205    /// native code or ISPC kernels.
206    pub unsafe fn handle(&self) -> RTCScene {
207        self.scene.handle
208    }
209}
210
211unsafe impl<'a> Sync for CommittedScene<'a> {}