rafx_framework/visibility/
visibility_resource.rs

1use crate::render_features::RenderObjectHandle;
2use crate::visibility::view_frustum_arc::ViewFrustumArc;
3use crate::visibility::visibility_object_allocator::{
4    VisibilityObjectAllocator, VisibilityObjectId,
5};
6use crate::visibility::visibility_object_arc::{CullModel, VisibilityObjectArc};
7use crate::visibility::ObjectId;
8use crossbeam_channel::Sender;
9use rafx_visibility::geometry::Transform;
10use rafx_visibility::{AsyncCommand, ModelHandle, VisibilityObject, VisibilityWorld, ZoneHandle};
11
12pub struct VisibilityObjectInfo<'a> {
13    arc: VisibilityObjectArc,
14    obj: &'a VisibilityObject,
15}
16
17impl<'a> VisibilityObjectInfo<'a> {
18    pub fn object_id(&self) -> ObjectId {
19        self.arc.object_id()
20    }
21
22    pub fn render_objects(&self) -> &[RenderObjectHandle] {
23        self.arc.render_objects()
24    }
25
26    pub fn transform(&self) -> Transform {
27        self.obj.transform.unwrap_or_default()
28    }
29
30    pub fn previous_frame_transform(&self) -> Option<Transform> {
31        self.obj.previous_frame_transform
32    }
33
34    pub fn model_handle(&self) -> &Option<ModelHandle> {
35        &self.obj.cull_model
36    }
37}
38
39pub struct VisibilityResource {
40    allocator: VisibilityObjectAllocator,
41    commands: Sender<AsyncCommand>,
42    dynamic_zone: ZoneHandle,
43    static_zone: ZoneHandle,
44}
45
46impl VisibilityResource {
47    pub fn new() -> Self {
48        let mut visibility_world = VisibilityWorld::new();
49        let static_zone = visibility_world.inner.new_zone();
50        let dynamic_zone = visibility_world.inner.new_zone();
51        let commands = visibility_world.new_async_command_sender();
52        let allocator = VisibilityObjectAllocator::new(visibility_world);
53
54        VisibilityResource {
55            commands,
56            static_zone,
57            dynamic_zone,
58            allocator,
59        }
60    }
61
62    pub fn world(&self) -> &VisibilityWorld {
63        self.allocator.world()
64    }
65
66    pub fn update(&mut self) {
67        self.allocator.update();
68    }
69
70    pub fn register_view_frustum(&mut self) -> ViewFrustumArc {
71        self.allocator
72            .new_view_frustum(Some(self.static_zone), Some(self.dynamic_zone))
73    }
74
75    pub fn register_static_view_frustum(&mut self) -> ViewFrustumArc {
76        self.allocator
77            .new_view_frustum(Some(self.static_zone), None)
78    }
79
80    pub fn register_dynamic_view_frustum(&mut self) -> ViewFrustumArc {
81        self.allocator
82            .new_view_frustum(None, Some(self.dynamic_zone))
83    }
84
85    /// Returns a smart pointer to a handle representing a static object.
86    /// A static object is a hint to the visibility world that the object's transform changes rarely.
87    /// Most geometry in the world is static -- buildings, trees, rocks, grass, and so on.
88    pub fn register_static_object(
89        &mut self,
90        object_id: ObjectId,
91        cull_model: CullModel,
92        render_objects: Vec<RenderObjectHandle>,
93    ) -> VisibilityObjectArc {
94        self.register_object(object_id, cull_model, render_objects, self.static_zone)
95    }
96
97    /// Returns a smart pointer to a handle representing a dynamic object.
98    /// A dynamic object is a hint to the visibility world that the object's transform changes often.
99    /// Characters, projectiles, vehicles, and moving platforms are examples of dynamic geometry.
100    pub fn register_dynamic_object(
101        &mut self,
102        object_id: ObjectId,
103        cull_model: CullModel,
104        render_objects: Vec<RenderObjectHandle>,
105    ) -> VisibilityObjectArc {
106        self.register_object(object_id, cull_model, render_objects, self.dynamic_zone)
107    }
108
109    fn register_object(
110        &mut self,
111        object_id: ObjectId,
112        cull_model: CullModel,
113        render_objects: Vec<RenderObjectHandle>,
114        zone: ZoneHandle,
115    ) -> VisibilityObjectArc {
116        self.allocator
117            .new_object(object_id, cull_model, render_objects, Some(zone))
118    }
119
120    pub fn visibility_object_arc(
121        &self,
122        id: VisibilityObjectId,
123    ) -> Option<VisibilityObjectArc> {
124        self.allocator.object_ref(id)
125    }
126
127    pub fn visibility_object_info(
128        &self,
129        id: VisibilityObjectId,
130    ) -> Option<VisibilityObjectInfo> {
131        let arc = self.allocator.object_ref(id);
132        if let Some(arc) = arc {
133            let obj = self
134                .world()
135                .inner
136                .visibility_object(arc.visibility_object_handle());
137            if let Some(obj) = obj {
138                return Some(VisibilityObjectInfo { arc, obj });
139            }
140        }
141
142        None
143    }
144}
145
146impl Drop for VisibilityResource {
147    fn drop(&mut self) {
148        let _ = self
149            .commands
150            .send(AsyncCommand::DestroyZone(self.static_zone));
151        let _ = self
152            .commands
153            .send(AsyncCommand::DestroyZone(self.dynamic_zone));
154    }
155}