use std::collections::HashMap;
use std::marker::PhantomData;
use std::mem;
use device::Device;
use geometry::Geometry;
use ray::{IntersectContext, Ray, RayHit};
use ray_packet::{Ray4, RayHit4};
use ray_stream::{RayHitN, RayN};
use sys::*;
pub struct Scene<'a> {
pub(crate) handle: RTCScene,
device: PhantomData<&'a Device>,
geometry: HashMap<u32, Geometry<'a>>,
}
impl<'a> Scene<'a> {
pub fn new(device: &'a Device) -> Scene {
Scene {
handle: unsafe { rtcNewScene(device.handle) },
device: PhantomData,
geometry: HashMap::new(),
}
}
pub fn attach_geometry(&mut self, mesh: Geometry<'a>) -> u32 {
let id = unsafe { rtcAttachGeometry(self.handle, mesh.handle()) };
self.geometry.insert(id, mesh);
id
}
pub fn deattach_geometry(&mut self, id: u32) -> Option<Geometry<'a>> {
self.geometry.remove(&id)
}
pub fn get_geometry(&self, id: u32) -> Option<&Geometry<'a>> {
match self.geometry.get(&id) {
Some(g) => Some(g),
None => None,
}
}
pub fn get_geometry_mut(&mut self, id: u32) -> Option<&mut Geometry<'a>> {
match self.geometry.get_mut(&id) {
Some(g) => Some(g),
None => None,
}
}
pub fn iter(&self) -> std::collections::hash_map::Iter<u32, Geometry<'a>> {
self.geometry.iter()
}
pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<u32, Geometry<'a>> {
self.geometry.iter_mut()
}
pub fn commit(&'a self) -> CommittedScene<'a> {
unsafe {
rtcCommitScene(self.handle);
}
CommittedScene { scene: &self }
}
pub unsafe fn handle(&self) -> RTCScene {
self.handle
}
}
impl<'a> Drop for Scene<'a> {
fn drop(&mut self) {
unsafe {
rtcReleaseScene(self.handle);
}
}
}
unsafe impl<'a> Sync for Scene<'a> {}
pub struct CommittedScene<'a> {
pub(crate) scene: &'a Scene<'a>,
}
impl<'a> CommittedScene<'a> {
pub fn intersect(&self, ctx: &mut IntersectContext, ray: &mut RayHit) {
unsafe {
rtcIntersect1(
self.scene.handle,
ctx as *mut RTCIntersectContext,
ray as *mut RTCRayHit,
);
}
}
pub fn occluded(&self, ctx: &mut IntersectContext, ray: &mut Ray) {
unsafe {
rtcOccluded1(
self.scene.handle,
ctx as *mut RTCIntersectContext,
ray as *mut RTCRay,
);
}
}
pub fn intersect4(&self, ctx: &mut IntersectContext, ray: &mut RayHit4, valid: &[i32; 4]) {
unsafe {
rtcIntersect4(
valid.as_ptr(),
self.scene.handle,
ctx as *mut RTCIntersectContext,
ray as *mut RTCRayHit4,
);
}
}
pub fn occluded4(&self, ctx: &mut IntersectContext, ray: &mut Ray4, valid: &[i32; 4]) {
unsafe {
rtcOccluded4(
valid.as_ptr(),
self.scene.handle,
ctx as *mut RTCIntersectContext,
ray as *mut RTCRay4,
);
}
}
pub fn intersect_stream_aos(&self, ctx: &mut IntersectContext, rays: &mut Vec<RayHit>) {
let m = rays.len();
unsafe {
rtcIntersect1M(
self.scene.handle,
ctx as *mut RTCIntersectContext,
rays.as_mut_ptr(),
m as u32,
mem::size_of::<RayHit>(),
);
}
}
pub fn occluded_stream_aos(&self, ctx: &mut IntersectContext, rays: &mut Vec<Ray>) {
let m = rays.len();
unsafe {
rtcOccluded1M(
self.scene.handle,
ctx as *mut RTCIntersectContext,
rays.as_mut_ptr(),
m as u32,
mem::size_of::<Ray>(),
);
}
}
pub fn intersect_stream_soa(&self, ctx: &mut IntersectContext, rays: &mut RayHitN) {
let n = rays.len();
unsafe {
let mut rayhit = rays.as_rayhitnp();
rtcIntersectNp(
self.scene.handle,
ctx as *mut RTCIntersectContext,
&mut rayhit as *mut RTCRayHitNp,
n as u32,
);
}
}
pub fn occluded_stream_soa(&self, ctx: &mut IntersectContext, rays: &mut RayN) {
let n = rays.len();
unsafe {
let mut r = rays.as_raynp();
rtcOccludedNp(
self.scene.handle,
ctx as *mut RTCIntersectContext,
&mut r as *mut RTCRayNp,
n as u32,
);
}
}
pub fn bounds(&self) -> RTCBounds {
let mut bounds = RTCBounds {
lower_x: 0.0,
upper_x: 0.0,
lower_y: 0.0,
upper_y: 0.0,
lower_z: 0.0,
upper_z: 0.0,
align0: 0.0,
align1: 0.0,
};
unsafe {
rtcGetSceneBounds(self.handle(), &mut bounds as *mut RTCBounds);
}
bounds
}
pub unsafe fn handle(&self) -> RTCScene {
self.scene.handle
}
}
unsafe impl<'a> Sync for CommittedScene<'a> {}