use math::*;
use Format;
pub struct ColourSet {
count: usize,
points: [Vec3; 16],
weights: [f32; 16],
remap: [i8; 16],
transparent: bool,
}
impl ColourSet {
pub fn new(rgba: &[[u8; 4]; 16], mask: u32, format: Format, alpha_weighted: bool) -> ColourSet {
let mut set = ColourSet {
count: 0,
points: [Vec3::new(0f32, 0f32, 0f32); 16],
weights: [0f32; 16],
remap: [0i8; 16],
transparent: false,
};
for i in 0..rgba.len() {
let bit = 1u32 << i;
if (mask & bit) == 0 {
set.remap[i] = -1;
continue;
}
if (format == Format::Bc1) && (rgba[i][3] < 128u8) {
set.remap[i] = -1;
set.transparent = true;
continue;
}
for j in 0..rgba.len() {
if j == i {
let x = f32::from(rgba[i][0]) / 255f32;
let y = f32::from(rgba[i][1]) / 255f32;
let z = f32::from(rgba[i][2]) / 255f32;
let w = (i32::from(rgba[i][3]) + 1) as f32 / 256f32;
set.points[set.count] = Vec3::new(x, y, z);
set.weights[set.count] = if alpha_weighted { w } else { 1f32 };
set.remap[i] = set.count as i8;
set.count += 1;
break;
}
let oldbit = 1u32 << j;
let duplicate = ((mask & oldbit) != 0)
&& (rgba[i][0] == rgba[j][0])
&& (rgba[i][1] == rgba[j][1])
&& (rgba[i][2] == rgba[j][2])
&& (format != Format::Bc1 || rgba[j][3] >= 128u8);
if duplicate {
let index = set.remap[j];
let w = (i32::from(rgba[i][3]) + 1) as f32 / 256f32;
set.weights[index as usize] += if alpha_weighted { w } else { 1f32 };
set.remap[i] = index;
break;
}
}
}
for w in set.weights.iter_mut() {
*w = w.sqrt();
}
set
}
pub fn is_transparent(&self) -> bool {
self.transparent
}
pub fn points(&self) -> &[Vec3] {
&self.points[..self.count]
}
pub fn weights(&self) -> &[f32] {
&self.weights[..self.count]
}
pub fn count(&self) -> usize {
self.count
}
pub fn remap_indices(&self, source: &[u8; 16], target: &mut [u8; 16]) {
for (i, target) in target.iter_mut().enumerate() {
let j = self.remap[i];
if j == -1 {
*target = 3;
} else {
*target = source[j as usize];
}
}
}
}