sectorsync_core/
interest.rs1use crate::entity::{EntityRecord, EntityTags};
4use crate::ids::ClientId;
5use crate::spatial::{Frustum3, Position3};
6
7#[derive(Clone, Copy, Debug, PartialEq)]
9pub struct ViewerQuery {
10 pub client_id: ClientId,
12 pub position: Position3,
14 pub radius: f32,
16 pub max_entities: usize,
18}
19
20impl ViewerQuery {
21 pub fn radius_squared(self) -> f32 {
23 self.radius * self.radius
24 }
25}
26
27pub trait VisibilityFilter {
29 fn is_visible(&self, viewer: &ViewerQuery, entity: &EntityRecord) -> bool;
31}
32
33#[derive(Clone, Copy, Debug, Default)]
35pub struct RangeOnlyVisibility;
36
37impl VisibilityFilter for RangeOnlyVisibility {
38 fn is_visible(&self, viewer: &ViewerQuery, entity: &EntityRecord) -> bool {
39 entity.position.distance_squared(viewer.position) <= viewer.radius_squared()
40 }
41}
42
43#[derive(Clone, Copy, Debug, PartialEq)]
45pub struct FrustumVisibility {
46 pub frustum: Frustum3,
48}
49
50impl FrustumVisibility {
51 pub const fn new(frustum: Frustum3) -> Self {
53 Self { frustum }
54 }
55}
56
57impl VisibilityFilter for FrustumVisibility {
58 fn is_visible(&self, _viewer: &ViewerQuery, entity: &EntityRecord) -> bool {
59 self.frustum
60 .intersects_bounds(entity.position, entity.bounds)
61 }
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66pub struct TagVisibility {
67 pub required: EntityTags,
69 pub excluded: EntityTags,
71}
72
73impl TagVisibility {
74 pub const fn new(required: EntityTags, excluded: EntityTags) -> Self {
76 Self { required, excluded }
77 }
78
79 pub const fn require(required: EntityTags) -> Self {
81 Self::new(required, EntityTags::EMPTY)
82 }
83
84 pub const fn exclude(excluded: EntityTags) -> Self {
86 Self::new(EntityTags::EMPTY, excluded)
87 }
88}
89
90impl VisibilityFilter for TagVisibility {
91 fn is_visible(&self, _viewer: &ViewerQuery, entity: &EntityRecord) -> bool {
92 entity.tags.contains(self.required) && !entity.tags.intersects(self.excluded)
93 }
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Eq)]
98pub struct AndVisibility<A, B> {
99 pub left: A,
101 pub right: B,
103}
104
105impl<A, B> AndVisibility<A, B> {
106 pub const fn new(left: A, right: B) -> Self {
108 Self { left, right }
109 }
110}
111
112impl<A, B> VisibilityFilter for AndVisibility<A, B>
113where
114 A: VisibilityFilter,
115 B: VisibilityFilter,
116{
117 fn is_visible(&self, viewer: &ViewerQuery, entity: &EntityRecord) -> bool {
118 self.left.is_visible(viewer, entity) && self.right.is_visible(viewer, entity)
119 }
120}