Skip to main content

cumulus3d_dense/
cache.rs

1//! 깊이맵 캐시: (영상 이름 + 자세·내부 매개변수·크기 해시, 설정 해시) → 최종 깊이·법선·유효 표시.
2//! 겹치는 구역에서 같은 자세의 영상을 다시 계산하지 않게 한다.
3
4use std::collections::{HashMap, VecDeque};
5use std::sync::{Arc, Mutex};
6
7/// 캐시된 뷰 하나(최종 스케일): 필터 전 깊이(다른 뷰의 기하 실행 입력)와 최종 깊이·법선·비용(융합 입력).
8#[derive(Clone, Debug)]
9pub struct CachedDepth {
10    /// 너비(픽셀).
11    pub width: usize,
12    /// 높이(픽셀).
13    pub height: usize,
14    /// 필터 전 최종 깊이(다른 뷰의 기하 실행 입력).
15    pub raw_depth: Vec<f32>,
16    /// 필터 통과 깊이(무효 0).
17    pub depth: Vec<f32>,
18    /// 기준 카메라 좌표 법선.
19    pub normal: Vec<[f32; 3]>,
20    /// 최종 집계 비용.
21    pub cost: Vec<f32>,
22}
23
24type Entries = (HashMap<(u64, u64), Arc<CachedDepth>>, VecDeque<(u64, u64)>);
25
26/// 깊이맵 캐시(스레드 안전, 용량 초과 시 오래된 것부터 버림).
27pub struct DepthMapCache {
28    inner: Mutex<Entries>,
29    capacity: usize,
30}
31
32impl Default for DepthMapCache {
33    fn default() -> Self {
34        Self::new()
35    }
36}
37
38impl DepthMapCache {
39    /// 용량 512 뷰.
40    pub fn new() -> Self {
41        Self::with_capacity(512)
42    }
43    /// 용량을 정해 만든다(최소 1).
44    pub fn with_capacity(capacity: usize) -> Self {
45        Self { inner: Mutex::new((HashMap::new(), VecDeque::new())), capacity: capacity.max(1) }
46    }
47    /// 열쇠 (영상 기하 해시, 설정 해시) 로 찾는다.
48    pub fn get(&self, key: (u64, u64)) -> Option<Arc<CachedDepth>> {
49        self.inner.lock().unwrap_or_else(|e| e.into_inner()).0.get(&key).cloned()
50    }
51    /// 넣는다. 용량을 넘으면 가장 오래된 항목부터 버린다.
52    pub fn insert(&self, key: (u64, u64), v: Arc<CachedDepth>) {
53        let mut g = self.inner.lock().unwrap_or_else(|e| e.into_inner());
54        if g.0.insert(key, v).is_none() {
55            g.1.push_back(key);
56        }
57        while g.1.len() > self.capacity {
58            if let Some(k) = g.1.pop_front() {
59                g.0.remove(&k);
60            }
61        }
62    }
63    /// 저장된 뷰 수.
64    pub fn len(&self) -> usize {
65        self.inner.lock().unwrap_or_else(|e| e.into_inner()).0.len()
66    }
67    /// 비어 있는지.
68    pub fn is_empty(&self) -> bool {
69        self.len() == 0
70    }
71}