Skip to content

Commit

Permalink
Added support for RGBA color custom data.
Browse files Browse the repository at this point in the history
  • Loading branch information
FractalFir committed Jun 9, 2023
1 parent 545b4ad commit 6f7598a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 11 deletions.
132 changes: 125 additions & 7 deletions src/custom_data.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::read_extension::ReadExt;
use crate::tmf::SectionType;
use crate::{FloatType, IndexType, TMFImportError, MAX_SEG_SIZE};
use crate::{FloatType, IndexType, TMFImportError, MAX_SEG_SIZE,Vector4};
#[derive(Clone, Debug)]
pub(crate) struct CustomDataSegment {
name: Vec<u8>,
Expand Down Expand Up @@ -50,27 +50,34 @@ pub enum CustomData {
CustomIndex(Box<[IndexType]>, usize),
CustomIntiger(Box<[IndexType]>, usize),
CustomFloat(Box<[FloatType]>, FloatType),
CustomColorRGBA(Box<[Vector4]>, FloatType),
}
impl CustomData {
/// Returns the index data if custom segment is an index segment. Returns the index array and max index.
pub fn is_index(&self) -> Option<(&[IndexType], usize)> {
pub fn as_index(&self) -> Option<(&[IndexType], usize)> {
match self {
Self::CustomIndex(array, max_index) => Some((array, *max_index)),
_ => None,
}
}
pub fn is_intiger(&self) -> Option<(&[IndexType], usize)> {
pub fn as_intiger(&self) -> Option<(&[IndexType], usize)> {
match self {
Self::CustomIntiger(array, max_index) => Some((array, *max_index)),
_ => None,
}
}
pub fn is_float(&self) -> Option<(&[FloatType], FloatType)> {
pub fn as_float(&self) -> Option<(&[FloatType], FloatType)> {
match self {
Self::CustomFloat(array, prec) => Some((array, *prec)),
_ => None,
}
}
pub fn as_color_rgba(&self) -> Option<(&[Vector4], FloatType)> {
match self {
Self::CustomColorRGBA(array, prec) => Some((array, *prec)),
_ => None,
}
}
fn write<W: std::io::Write>(&self, target: &mut W) -> std::io::Result<()> {
match self {
Self::CustomIndex(data, max_index) => {
Expand All @@ -79,7 +86,7 @@ impl CustomData {
Self::CustomIntiger(data, max_index) => {
crate::vertices::save_triangles(data, *max_index, target)
}
CustomData::CustomFloat(data, prec) => {
Self::CustomFloat(data, prec) => {
use crate::unaligned_rw::{UnalignedRWMode, UnalignedWriter};
let mut max = FloatType::MIN;
let mut min = FloatType::MAX;
Expand All @@ -104,6 +111,26 @@ impl CustomData {
}
Ok(())
}
Self::CustomColorRGBA(data,prec)=>{
use crate::unaligned_rw::{UnalignedRWMode, UnalignedWriter};
let prec_bits = (1.0/prec.min(1.0)).log2().ceil() as u8;
let mul = ((1 << prec_bits) - 1) as FloatType;
target.write_all(&(data.len() as u64).to_le_bytes())?;
target.write_all(&[prec_bits])?;
let prec = UnalignedRWMode::precision_bits(prec_bits);
let mut writer = UnalignedWriter::new(target);
for entry in data.iter() {
let entry_r = (entry.0 * mul) as u64;
let entry_g = (entry.1 * mul) as u64;
let entry_b = (entry.2 * mul) as u64;
let entry_a = (entry.3 * mul) as u64;
writer.write_unaligned(prec, entry_r)?;
writer.write_unaligned(prec, entry_g)?;
writer.write_unaligned(prec, entry_b)?;
writer.write_unaligned(prec, entry_a)?;
}
Ok(())
}
}?;
Ok(())
}
Expand All @@ -112,11 +139,15 @@ impl CustomData {
Self::CustomIndex(_, _) => SectionType::CustomIndexSegment,
Self::CustomIntiger(_, _) => SectionType::CustomIntigerSegment,
Self::CustomFloat(_, _) => SectionType::CustomFloatSegment,
Self::CustomColorRGBA(_,_) => SectionType::CustomColorRGBASegment,
}
}
fn new_float(floats: &[FloatType], prec: FloatType) -> Self {
Self::CustomFloat(floats.into(), prec)
}
fn new_color_rgba(colors: &[Vector4], prec: FloatType) -> Self {
Self::CustomColorRGBA(colors.into(), prec)
}
fn new_index(indices: &[IndexType], max_index: Option<usize>) -> Self {
let max_index = match max_index {
Some(max_index) => max_index,
Expand All @@ -142,6 +173,11 @@ impl From<&[FloatType]> for CustomData {
Self::new_float(floats, 0.01)
}
}
impl From<&[Vector4]> for CustomData {
fn from(colors: &[Vector4]) -> Self {
Self::new_color_rgba(colors, 0.01)
}
}
impl CustomDataSegment {
pub(crate) fn encode<W: std::io::Write>(&self, target: &mut W) -> std::io::Result<SectionType> {
target.write_all(&[self.name_len])?;
Expand All @@ -159,6 +195,9 @@ impl CustomDataSegment {
let mut name = [0; u8::MAX as usize];
src.read_exact(&mut name[..(name_len as usize)])?;
match kind {
/*SectionType::CustomColorSegment =>{
}*/
SectionType::CustomIndexSegment => {
let result = crate::vertices::read_triangles(&mut src, ctx)?;
Ok(Self::new_raw(
Expand Down Expand Up @@ -204,6 +243,26 @@ impl CustomDataSegment {
name_len,
))
}
SectionType::CustomColorRGBASegment=>{
use crate::unaligned_rw::{UnalignedRWMode, UnalignedReader};
let len = src.read_u64()?;
let prec_bits = src.read_u8()?;
let prec = UnalignedRWMode::precision_bits(prec_bits);
let mut reader = UnalignedReader::new(src);
let mut res = vec![(0.0,0.0,0.0,0.0); len as usize];
let div = ((1_u64 << prec_bits) - 1) as f64;
for vec4 in &mut res {
let (r,g) = reader.read2_unaligned(prec)?;
let (b,a) = reader.read2_unaligned(prec)?;
*vec4 = (((r as f64) / div) as FloatType,((g as f64) / div) as FloatType,((b as f64) / div) as FloatType,((a as f64) / div) as FloatType);
}
let prec = ((1.0 / ((1_u64 << prec_bits) as f64)) as FloatType) * 0.99999;
Ok(Self::new_raw(
CustomData::new_color_rgba(&res, prec),
name,
name_len,
))
}
_ => panic!("InternalError: Invalid custom section type, must be custom!"),
}
}
Expand Down Expand Up @@ -236,7 +295,7 @@ fn index_data() {
let read_indices = r_mesh
.lookup_custom_data("custom_index")
.expect("Could not find the custom index array!");
let (read_indices, _) = read_indices.is_index().unwrap();
let (read_indices, _) = read_indices.as_index().unwrap();
assert_eq!(index_data, read_indices);
}
#[test]
Expand Down Expand Up @@ -266,7 +325,7 @@ fn float_data() {
.lookup_custom_data("custom_float")
.expect("Could not find the custom float array!");

let (read_floats, _) = read_floats.is_float().unwrap();
let (read_floats, _) = read_floats.as_float().unwrap();

for index in 0..read_floats.len() {
assert!(
Expand All @@ -278,3 +337,62 @@ fn float_data() {
);
}
}
#[test]
#[cfg(all(feature = "obj_import", test))]
fn color_rgba_data() {
use crate::{TMFMesh, TMFPrecisionInfo};
init_test_env();
let mut file = std::fs::File::open("testing/susan.obj").unwrap();
let (mut tmf_mesh, name) = TMFMesh::read_from_obj_one(&mut file).unwrap();
let color_rgba_data: [Vector4; 3] = [
(0.9, 0.19, 0.2, 0.7867), (0.431224, 0.534345, 0.64336, 0.78634), (0.776565, 0.87575, 0.954,0.3543)
];
tmf_mesh
.add_custom_data(color_rgba_data[..].into(), "custom_color_rgba")
.unwrap();
tmf_mesh.verify().unwrap();
assert!(name == "Suzanne", "Name should be Suzanne but is {name}");
let prec = TMFPrecisionInfo::default();
let mut out = Vec::new();
{
tmf_mesh.write_tmf_one(&mut out, &prec, name).unwrap();
}
let (r_mesh, name) = TMFMesh::read_tmf_one(&mut (&out as &[u8])).unwrap();
assert!(name == "Suzanne", "Name should be Suzanne but is {name}");
r_mesh.verify().unwrap();
let read_color_rgbas = r_mesh
.lookup_custom_data("custom_color_rgba")
.expect("Could not find the custom color_rgba array!");

let (read_color_rgbas, _) = read_color_rgbas.as_color_rgba().unwrap();
for index in 0..read_color_rgbas.len() {
assert!(
(read_color_rgbas[index].0 - color_rgba_data[index].0).abs() <= 0.01,
"{} diff {:?} {:?} > 0.01!",
index,
read_color_rgbas[index],
color_rgba_data[index]
);
assert!(
(read_color_rgbas[index].1 - color_rgba_data[index].1).abs() <= 0.01,
"{} diff {:?} {:?} > 0.01!",
index,
read_color_rgbas[index],
color_rgba_data[index]
);
assert!(
(read_color_rgbas[index].2 - color_rgba_data[index].2).abs() <= 0.01,
"{} diff {:?} {:?} > 0.01!",
index,
read_color_rgbas[index],
color_rgba_data[index]
);
assert!(
(read_color_rgbas[index].3 - color_rgba_data[index].3).abs() <= 0.01,
"{} diff {:?} {:?} > 0.01!",
index,
read_color_rgbas[index],
color_rgba_data[index]
);
}
}
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub type FloatType = f32;
pub type FloatType = f64;
/// Type used for representing 3d floating-point vectors
pub type Vector3 = (FloatType, FloatType, FloatType);
pub type Vector4 = (FloatType, FloatType, FloatType, FloatType);
/// Type used for representing 2d floating-point vectors
pub type Vector2 = (FloatType, FloatType);
use crate::custom_data::CustomDataSegment;
Expand Down Expand Up @@ -1005,7 +1006,7 @@ mod testing {
&mut (&out as &[u8]),
))
.unwrap();
todo!();
//todo!();
}
#[test]
#[cfg(feature = "obj_import")]
Expand Down
2 changes: 1 addition & 1 deletion src/reorder_triangles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@ fn read_susan_obj() {
.write_tmf_one(&mut out, &TMFPrecisionInfo::default(), "SUSAN")
.unwrap();

todo!();
//todo!();
}
6 changes: 4 additions & 2 deletions src/tmf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub(crate) enum SectionType {
CustomVector2Segment = 19,
CustomVector3Segment = 20,
CustomVector4Segment = 21,
CustomColorSegment = 23,
CustomColorRGBASegment = 23,
CustomIntigerSegment = 24,
SharedTriangleSegment = 25,
}
Expand Down Expand Up @@ -70,6 +70,7 @@ impl SectionType {
10 => Self::TangentTriangleSegment,
15 => Self::CustomIndexSegment,
16 => Self::CustomFloatSegment,
23 => Self::CustomColorRGBASegment,
24 => Self::CustomIntigerSegment,
25 => Self::SharedTriangleSegment,
_ => Self::Invalid,
Expand Down Expand Up @@ -418,7 +419,8 @@ impl DecodedSegment {
| SectionType::TangentTriangleSegment => decode_triangle_seg(seg, ctx).await,
SectionType::CustomIndexSegment
| SectionType::CustomIntigerSegment
| SectionType::CustomFloatSegment => decode_custom_seg(seg, ctx).await,
| SectionType::CustomFloatSegment |
SectionType::CustomColorRGBASegment => decode_custom_seg(seg, ctx).await,
SectionType::SharedTriangleSegment => {
if seg.data.len() < 1 {
return Err(TMFImportError::IO(std::io::Error::from(
Expand Down
1 change: 1 addition & 0 deletions src/tmf_importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ pub(crate) async fn decode_custom_seg(
SectionType::CustomIndexSegment
| SectionType::CustomFloatSegment
| SectionType::CustomIntigerSegment
| SectionType::CustomColorRGBASegment
) {
let mut data: &[u8] = seg.data();
Ok(DecodedSegment::AppendCustom(CustomDataSegment::read(
Expand Down

0 comments on commit 6f7598a

Please sign in to comment.