1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use na::RealField;

use crate::bounding_volume::AABB;
use crate::pipeline::broad_phase::{
    BroadPhase, BroadPhaseInterferenceHandler, BroadPhasePairFilter,
};
use crate::pipeline::narrow_phase::{InteractionGraph, NarrowPhase};
use crate::pipeline::object::{CollisionGroupsPairFilter, CollisionObjectRef, CollisionObjectSet};

struct CollisionWorldInterferenceHandler<'a, 'b, N, Objects, Filter>
where
    N: RealField,
    Objects: CollisionObjectSet<N>,
    Filter:
        BroadPhasePairFilter<N, Objects::CollisionObject, Objects::CollisionObjectHandle> + ?Sized,
{
    narrow_phase: &'b mut NarrowPhase<N, Objects::CollisionObjectHandle>,
    interactions: &'b mut InteractionGraph<N, Objects::CollisionObjectHandle>,
    objects: &'a Objects,
    pair_filters: Option<&'a Filter>,
}

impl<'a, 'b, N: RealField, Objects, Filter>
    BroadPhaseInterferenceHandler<Objects::CollisionObjectHandle>
    for CollisionWorldInterferenceHandler<'a, 'b, N, Objects, Filter>
where
    Objects: CollisionObjectSet<N>,
    Filter:
        BroadPhasePairFilter<N, Objects::CollisionObject, Objects::CollisionObjectHandle> + ?Sized,
{
    fn is_interference_allowed(
        &mut self,
        b1: &Objects::CollisionObjectHandle,
        b2: &Objects::CollisionObjectHandle,
    ) -> bool {
        let o1 = try_ret!(self.objects.collision_object(*b1), false);
        let o2 = try_ret!(self.objects.collision_object(*b2), false);
        let filter_by_groups = CollisionGroupsPairFilter;

        filter_by_groups.is_pair_valid(o1, o2, *b1, *b2)
            && self
                .pair_filters
                .map(|f| f.is_pair_valid(o1, o2, *b1, *b2))
                .unwrap_or(true)
    }

    fn interference_started(
        &mut self,
        b1: &Objects::CollisionObjectHandle,
        b2: &Objects::CollisionObjectHandle,
    ) {
        self.narrow_phase
            .handle_interaction(self.interactions, self.objects, *b1, *b2, true)
    }

    fn interference_stopped(
        &mut self,
        b1: &Objects::CollisionObjectHandle,
        b2: &Objects::CollisionObjectHandle,
    ) {
        self.narrow_phase
            .handle_interaction(&mut self.interactions, self.objects, *b1, *b2, false)
    }
}

/// Performs the broad-phase.
///
/// This will update the broad-phase internal structure, and create potential interaction pairs in the interaction graph.
/// A `pair_filters` can be provided to filter out pairs of object that should not be considered.
pub fn perform_broad_phase<N: RealField, Objects>(
    objects: &Objects,
    broad_phase: &mut (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
    narrow_phase: &mut NarrowPhase<N, Objects::CollisionObjectHandle>,
    interactions: &mut InteractionGraph<N, Objects::CollisionObjectHandle>,
    pair_filters: Option<
        &(impl BroadPhasePairFilter<N, Objects::CollisionObject, Objects::CollisionObjectHandle>
              + ?Sized),
    >,
) where
    Objects: CollisionObjectSet<N>,
{
    // Take changes into account.
    objects.foreach(|_, co| {
        let flags = co.update_flags();
        let proxy_handle = co.proxy_handle().expect(crate::NOT_REGISTERED_ERROR);

        if flags.needs_bounding_volume_update() {
            broad_phase.deferred_set_bounding_volume(proxy_handle, co.compute_swept_aabb());
        }

        if flags.needs_broad_phase_redispatch() {
            broad_phase.deferred_recompute_all_proximities_with(proxy_handle);
        }
    });

    // Update the broad-phase.
    broad_phase.update(&mut CollisionWorldInterferenceHandler {
        interactions,
        narrow_phase,
        pair_filters,
        objects,
    });
}

/// Performs the narrow-phase.
///
/// This will update all interactions in the interaction graph by computing new contacts,
/// and proximities.
pub fn perform_narrow_phase<N, Objects>(
    objects: &Objects,
    narrow_phase: &mut NarrowPhase<N, Objects::CollisionObjectHandle>,
    interactions: &mut InteractionGraph<N, Objects::CollisionObjectHandle>,
) where
    N: RealField,
    Objects: CollisionObjectSet<N>,
{
    narrow_phase.update(interactions, objects);
}

/// Performs the broad-phase and the narrow-phase.
///
/// This execute a complete collision detection pipeline by performing the broad-phase first and then
/// the narrow-phase.
pub fn perform_all_pipeline<'a, N, Objects>(
    objects: &Objects,
    broad_phase: &mut (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
    narrow_phase: &mut NarrowPhase<N, Objects::CollisionObjectHandle>,
    interactions: &mut InteractionGraph<N, Objects::CollisionObjectHandle>,
    pair_filters: Option<
        &'a (impl BroadPhasePairFilter<N, Objects::CollisionObject, Objects::CollisionObjectHandle>
                 + ?Sized),
    >,
) where
    N: RealField,
    Objects: CollisionObjectSet<N>,
{
    perform_broad_phase(
        objects,
        broad_phase,
        narrow_phase,
        interactions,
        pair_filters,
    );
    perform_narrow_phase(objects, narrow_phase, interactions);
}