Skip to main content

cumulus3d_dense/
cache.rs

1/*
2 * cache.rs
3 *
4 * Copyright (c) 2026 ParkSangWoo
5 *
6 * Author(s):
7 *
8 *      ParkSangWoo <dev.parksangwoo@gmail.com>
9 *
10 *
11 * This file is part of cumulus3d.
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 *      http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 * SPDX-License-Identifier: Apache-2.0
26 */
27
28//! Depth map cache: (image name + pose/intrinsics/size hash, settings hash) → final depth, normal and validity mask.
29//! Keeps overlapping zones from recomputing images with the same pose.
30
31use std::collections::{HashMap, VecDeque};
32use std::sync::{Arc, Mutex};
33
34/// One cached view (final scale): pre-filter depth (input to other views' geometric runs) and final depth, normal and cost (fusion input).
35#[derive(Clone, Debug)]
36pub struct CachedDepth {
37    /// Width (pixels).
38    pub width: usize,
39    /// Height (pixels).
40    pub height: usize,
41    /// Final depth before filtering (input to other views' geometric runs).
42    pub raw_depth: Vec<f32>,
43    /// Depth after the filter (0 = invalid).
44    pub depth: Vec<f32>,
45    /// Normal in the reference camera coordinates.
46    pub normal: Vec<[f32; 3]>,
47    /// Final aggregated cost.
48    pub cost: Vec<f32>,
49}
50
51type Entries = (HashMap<(u64, u64), Arc<CachedDepth>>, VecDeque<(u64, u64)>);
52
53/// Depth map cache (thread-safe; when over capacity, the oldest entries are dropped first).
54pub struct DepthMapCache {
55    inner: Mutex<Entries>,
56    capacity: usize,
57}
58
59impl Default for DepthMapCache {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl DepthMapCache {
66    /// Capacity of 512 views.
67    pub fn new() -> Self {
68        Self::with_capacity(512)
69    }
70    /// Creates a cache with the given capacity (minimum 1).
71    pub fn with_capacity(capacity: usize) -> Self {
72        Self { inner: Mutex::new((HashMap::new(), VecDeque::new())), capacity: capacity.max(1) }
73    }
74    /// Looks up by key (image geometry hash, settings hash).
75    pub fn get(&self, key: (u64, u64)) -> Option<Arc<CachedDepth>> {
76        self.inner.lock().unwrap_or_else(|e| e.into_inner()).0.get(&key).cloned()
77    }
78    /// Inserts. When over capacity, the oldest entries are dropped first.
79    pub fn insert(&self, key: (u64, u64), v: Arc<CachedDepth>) {
80        let mut g = self.inner.lock().unwrap_or_else(|e| e.into_inner());
81        if g.0.insert(key, v).is_none() {
82            g.1.push_back(key);
83        }
84        while g.1.len() > self.capacity {
85            if let Some(k) = g.1.pop_front() {
86                g.0.remove(&k);
87            }
88        }
89    }
90    /// Number of stored views.
91    pub fn len(&self) -> usize {
92        self.inner.lock().unwrap_or_else(|e| e.into_inner()).0.len()
93    }
94    /// Whether it is empty.
95    pub fn is_empty(&self) -> bool {
96        self.len() == 0
97    }
98}