#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LightGridConfig {
pub tiles_x: u32,
pub tiles_y: u32,
pub slices_z: u32,
pub max_lights_per_cell: u32,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LightGridCell {
pub light_indices: Vec<u32>,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LightGrid {
pub config: LightGridConfig,
pub cells: Vec<LightGridCell>,
}
#[allow(dead_code)]
pub fn default_light_grid_config() -> LightGridConfig {
LightGridConfig {
tiles_x: 16,
tiles_y: 9,
slices_z: 24,
max_lights_per_cell: 32,
}
}
#[allow(dead_code)]
pub fn new_light_grid(config: LightGridConfig) -> LightGrid {
let total = (config.tiles_x * config.tiles_y * config.slices_z) as usize;
let cells = vec![LightGridCell { light_indices: Vec::new() }; total];
LightGrid { config, cells }
}
#[allow(dead_code)]
pub fn total_cells(grid: &LightGrid) -> usize {
grid.cells.len()
}
#[allow(dead_code)]
pub fn cell_index(config: &LightGridConfig, x: u32, y: u32, z: u32) -> usize {
(z * config.tiles_y * config.tiles_x + y * config.tiles_x + x) as usize
}
#[allow(dead_code)]
pub fn assign_light_to_cell(grid: &mut LightGrid, cell_idx: usize, light_id: u32) -> bool {
if let Some(cell) = grid.cells.get_mut(cell_idx) {
if cell.light_indices.len() < grid.config.max_lights_per_cell as usize {
cell.light_indices.push(light_id);
return true;
}
}
false
}
#[allow(dead_code)]
pub fn clear_light_grid(grid: &mut LightGrid) {
for cell in &mut grid.cells {
cell.light_indices.clear();
}
}
#[allow(dead_code)]
pub fn lights_in_cell(grid: &LightGrid, cell_idx: usize) -> &[u32] {
grid.cells.get(cell_idx).map_or(&[], |c| &c.light_indices)
}
#[allow(dead_code)]
pub fn max_lights_per_cell_used(grid: &LightGrid) -> usize {
grid.cells.iter().map(|c| c.light_indices.len()).max().unwrap_or(0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let c = default_light_grid_config();
assert_eq!(c.tiles_x, 16);
}
#[test]
fn test_new_grid() {
let g = new_light_grid(default_light_grid_config());
assert_eq!(total_cells(&g), 16 * 9 * 24);
}
#[test]
fn test_cell_index() {
let c = default_light_grid_config();
let idx = cell_index(&c, 0, 0, 0);
assert_eq!(idx, 0);
}
#[test]
fn test_assign_light() {
let mut g = new_light_grid(default_light_grid_config());
assert!(assign_light_to_cell(&mut g, 0, 42));
}
#[test]
fn test_lights_in_cell() {
let mut g = new_light_grid(default_light_grid_config());
assign_light_to_cell(&mut g, 0, 42);
let lights = lights_in_cell(&g, 0);
assert_eq!(lights.len(), 1);
assert_eq!(lights[0], 42);
}
#[test]
fn test_clear() {
let mut g = new_light_grid(default_light_grid_config());
assign_light_to_cell(&mut g, 0, 1);
clear_light_grid(&mut g);
assert!(lights_in_cell(&g, 0).is_empty());
}
#[test]
fn test_max_lights() {
let config = LightGridConfig { tiles_x: 2, tiles_y: 2, slices_z: 1, max_lights_per_cell: 2 };
let mut g = new_light_grid(config);
assign_light_to_cell(&mut g, 0, 1);
assign_light_to_cell(&mut g, 0, 2);
assert!(!assign_light_to_cell(&mut g, 0, 3));
}
#[test]
fn test_max_used() {
let config = LightGridConfig { tiles_x: 2, tiles_y: 2, slices_z: 1, max_lights_per_cell: 10 };
let mut g = new_light_grid(config);
assign_light_to_cell(&mut g, 0, 1);
assign_light_to_cell(&mut g, 0, 2);
assert_eq!(max_lights_per_cell_used(&g), 2);
}
#[test]
fn test_empty_cell() {
let g = new_light_grid(default_light_grid_config());
assert!(lights_in_cell(&g, 0).is_empty());
}
#[test]
fn test_out_of_bounds() {
let g = new_light_grid(default_light_grid_config());
assert!(lights_in_cell(&g, 999999).is_empty());
}
}