use std::ops::{Add, Sub};
use super::implementation::rotation::Rotation;
use super::structs::{Block, Position};
use super::transition_sides::TransitionSide;
#[derive(Debug, PartialEq)]
pub struct RegularCellIndex {
pub x: usize,
pub y: usize,
pub z: usize,
}
#[derive(Clone, Copy)]
pub struct RegularVoxelDelta {
pub x: isize,
pub y: isize,
pub z: isize,
}
#[derive(Debug, PartialEq)]
pub struct RegularVoxelIndex {
pub x: isize,
pub y: isize,
pub z: isize,
}
impl Add<&RegularVoxelDelta> for &RegularCellIndex {
type Output = RegularVoxelIndex;
fn add(self, rhs: &RegularVoxelDelta) -> Self::Output {
RegularVoxelIndex {
x: self.x as isize + rhs.x,
y: self.y as isize + rhs.y,
z: self.z as isize + rhs.z,
}
}
}
impl Add<RegularVoxelDelta> for &RegularVoxelIndex {
type Output = RegularVoxelIndex;
fn add(self, rhs: RegularVoxelDelta) -> Self::Output {
RegularVoxelIndex {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct TransitionCellIndex {
pub side: TransitionSide,
pub cell_u: usize,
pub cell_v: usize,
}
impl TransitionCellIndex {
pub fn from(side: TransitionSide, cell_u: usize, cell_v: usize) -> Self {
Self { side, cell_u, cell_v }
}
}
#[derive(Copy, Clone, Debug)]
pub struct HighResolutionVoxelDelta {
pub u: isize,
pub v: isize,
pub w: isize,
}
#[derive(Debug)]
pub struct HighResolutionVoxelIndex {
pub cell: TransitionCellIndex,
pub delta: HighResolutionVoxelDelta,
}
impl HighResolutionVoxelIndex {
pub fn from(
side: TransitionSide,
cell_u: usize,
cell_v: usize,
u: isize,
v: isize,
w: isize,
) -> Self {
HighResolutionVoxelIndex {
cell: TransitionCellIndex::from(side, cell_u, cell_v),
delta: HighResolutionVoxelDelta::from(u, v, w),
}
}
pub fn on_regular_grid(&self) -> bool {
let du_on_regular_grid = (self.delta.u % 2) == 0;
let dv_on_regular_grid = (self.delta.v % 2) == 0;
let dw_on_regular_grid = self.delta.w == 0;
du_on_regular_grid && dv_on_regular_grid && dw_on_regular_grid
}
pub fn as_regular_index(
&self,
rotation: &Rotation,
block_subdivisions: usize,
) -> RegularVoxelIndex {
debug_assert!(rotation.side == self.cell.side);
let cell_u = self.delta.u as usize / 2;
let cell_v = self.delta.v as usize / 2;
let regular_index =
rotation.to_regular_voxel_index(block_subdivisions, &self.cell, cell_u, cell_v);
regular_index
}
pub fn to_position_in_block(&self, block: &Block) -> Position {
let rotation = Rotation::for_side(self.cell.side);
let position_in_block = rotation.to_position_in_block(block.subdivisions, self);
position_in_block
}
pub fn to_higher_res_neighbour_block_index(&self, this_block_size: usize) -> RegularVoxelIndex {
let higher_res_block_size = this_block_size as isize * 2;
let cell = self.cell;
let delta = self.delta;
let rot = Rotation::for_side(cell.side);
let x = higher_res_block_size * (rot.uvw_base.x + rot.w.x)
+ delta.w * rot.w.x
+ (2 * cell.cell_u as isize + delta.u) * rot.u.x
+ (2 * cell.cell_v as isize + delta.v) * rot.v.x;
let y = higher_res_block_size * (rot.uvw_base.y + rot.w.y)
+ delta.w * rot.w.y
+ (2 * cell.cell_u as isize + delta.u) * rot.u.y
+ (2 * cell.cell_v as isize + delta.v) * rot.v.y;
let z = higher_res_block_size * (rot.uvw_base.z + rot.w.z)
+ delta.w * rot.w.z
+ (2 * cell.cell_u as isize + delta.u) * rot.u.z
+ (2 * cell.cell_v as isize + delta.v) * rot.v.z;
RegularVoxelIndex { x, y, z }
}
}
impl HighResolutionVoxelDelta {
pub const fn from(u: isize, v: isize, w: isize) -> Self {
Self { u, v, w }
}
}
impl Add<&HighResolutionVoxelDelta> for &TransitionCellIndex {
type Output = HighResolutionVoxelIndex;
fn add(self, rhs: &HighResolutionVoxelDelta) -> Self::Output {
HighResolutionVoxelIndex {
cell: *self,
delta: *rhs,
}
}
}
impl Add<&HighResolutionVoxelDelta> for &HighResolutionVoxelIndex {
type Output = HighResolutionVoxelIndex;
fn add(self, rhs: &HighResolutionVoxelDelta) -> Self::Output {
HighResolutionVoxelIndex {
cell: self.cell,
delta: HighResolutionVoxelDelta::from(
self.delta.u + rhs.u,
self.delta.v + rhs.v,
self.delta.w + rhs.w,
),
}
}
}
impl Sub<&HighResolutionVoxelDelta> for &HighResolutionVoxelIndex {
type Output = HighResolutionVoxelIndex;
fn sub(self, rhs: &HighResolutionVoxelDelta) -> Self::Output {
HighResolutionVoxelIndex {
cell: self.cell,
delta: HighResolutionVoxelDelta::from(
self.delta.u - rhs.u,
self.delta.v - rhs.v,
self.delta.w - rhs.w,
),
}
}
}