Skip to content

Commit

Permalink
Some inititial infrastructure for custom mesh data.
Browse files Browse the repository at this point in the history
  • Loading branch information
FractalFir committed May 20, 2023
1 parent a6ab33f commit d9a5be3
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 54 deletions.
84 changes: 84 additions & 0 deletions src/custom_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::IndexType;
use crate::tmf::SectionType;
#[derive(Clone)]
pub struct CustomDataSegment {
name: [u8; u8::MAX as usize],
name_len: u8,
data: CustomData,
}
#[derive(Debug, Copy, Clone)]
pub enum DataSegmentError {
NoName,
NameTooLong,
}
impl CustomDataSegment {
pub fn new(data: CustomData, name: &str) -> Result<Self, DataSegmentError> {
let bytes = name.as_bytes();
let len = name.len();
if len > u8::MAX as usize {
return Err(DataSegmentError::NameTooLong);
} else if len == 0 {
return Err(DataSegmentError::NoName);
}
let name_len = len as u8;
let mut name = [0; u8::MAX as usize];
for index in 0..bytes.len() {
name[index] = bytes[index];
}
Ok(Self {
name,
name_len,
data,
})
}
}
#[derive(Clone)]
pub enum CustomData {
CustomIndex(Box<[IndexType]>),
}
impl CustomData{
fn section_type(&self)->SectionType{
match self{
Self::CustomIndex(_)=>SectionType::CustomIndexSegment,
}
}
}
impl From<&[IndexType]> for CustomData {
fn from(indices: &[IndexType]) -> Self {
Self::CustomIndex(indices.into())
}
}
impl CustomDataSegment{
pub(crate) fn write<W:std::io::Write>(&self,target:&mut W)->std::io::Result<()>{
target.write(&(self.data.section_type() as u16).to_le_bytes())?;
todo!();
}
fn read<R:std::io::Read>(src:&mut R)->Self{
todo!();
}
}
#[cfg(test)]
fn init_test_env() {
std::fs::create_dir_all("target/test_res").unwrap();
}
#[test]
#[cfg(all(feature = "obj_import",test))]
fn index_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 index_data:[IndexType;10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let index_data_seg = CustomDataSegment::new(CustomData::from(&index_data[..]), "custom_index").unwrap();
tmf_mesh.add_custom_data(index_data_seg);
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();
}
10 changes: 9 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! This means that while saving a model may take a slightly longer time (2-4x loading), models can be loaded at considerable speed(loading a model with around 40 000 points takes 1.6 ms)
//! ## Feature flags
#![doc = document_features::document_features!()]
mod custom_data;
mod material;
#[cfg(feature = "model_importer")]
mod model_importer;
Expand All @@ -16,10 +17,10 @@ mod obj;
/// Module used when saving vertex grups
mod pile_map;
mod tmf;
mod tmf_segment;
/// Module used to handle reads of data which is not bit aligned(for example, 3 or 17 bits). This is the module that allows for heavy compression used in this format.
#[doc(hidden)]
pub mod unaligned_rw;
mod tmf_segment;
mod utilis;
mod uv;
mod verify;
Expand Down Expand Up @@ -48,6 +49,8 @@ pub type FloatType = f64;
pub type Vector3 = (FloatType, FloatType, FloatType);
/// Type used for representing 2d floating-point vectors
pub type Vector2 = (FloatType, FloatType);
use crate::custom_data::CustomData;
use crate::custom_data::CustomDataSegment;
#[doc(inline)]
use crate::material::MaterialInfo;
#[doc(inline)]
Expand Down Expand Up @@ -92,6 +95,7 @@ pub struct TMFMesh {
uvs: Option<Box<[Vector2]>>,
uv_triangles: Option<Box<[IndexType]>>,
materials: Option<MaterialInfo>,
custom_data: Vec<CustomDataSegment>,
}
impl Default for TMFMesh {
/// Creates default, empty [`TMFMesh`]. Equivalent to [`TMFMesh::empty`] call.
Expand Down Expand Up @@ -575,6 +579,7 @@ impl TMFMesh {
vertex_triangles: None,
vertices: None,
materials: None,
custom_data: Vec::new(),
}
}
/// Reads all meshes from a .tmf file.
Expand Down Expand Up @@ -627,6 +632,9 @@ impl TMFMesh {
Ok(vec_first(meshes))
}
}
pub fn add_custom_data(&mut self, custom_data: CustomDataSegment) {
self.custom_data.push(custom_data);
}
}
#[cfg(test)]
mod testing {
Expand Down
3 changes: 2 additions & 1 deletion src/lz77.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ fn bwise_memcpy(
todo!("Coping not implemented yet, but target is:{target:?}!");
}
//Not finished yet!
#[test]#[ignore]
#[test]
#[ignore]
fn test_bwise_cpy() {
let a: [CompressionType; 2] = [
0b0000000111110110111110110100001111100001100011101011001000000010,
Expand Down
11 changes: 6 additions & 5 deletions src/normals.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::unaligned_rw::{UnalignedRWMode, UnalignedReader, UnalignedWriter};
use crate::{FloatType, IndexType, Vector3};
use std::io::{Read, Result, Write};
#[cfg(feature = "double_precision")]
use std::f64::consts::FRAC_PI_2;
#[cfg(not(feature = "double_precision"))]
use std::f32::consts::FRAC_PI_2;
#[cfg(feature = "double_precision")]
use std::f64::consts::FRAC_PI_2;
use std::io::{Read, Result, Write};
#[derive(Clone, Copy, PartialEq)]
/// Setting dictating how much can any normal in a model deviate, expressed as an angle.
pub struct NormalPrecisionMode(u8);
Expand Down Expand Up @@ -279,7 +279,7 @@ mod test_normal {
fn map_size(prec: &NormalPrecisionMode) -> u128 {
let asine_bits = prec.bits();
let z_bits = prec.bits();
let sign_bits = 3;//3 signs 1 bit each
let sign_bits = 3; //3 signs 1 bit each
let toatal_bits = asine_bits + z_bits + sign_bits;
1 << toatal_bits
}
Expand Down Expand Up @@ -317,7 +317,8 @@ pub(crate) fn map_prune(
}
}
for index in normal_faces {
*index = map[normal_to_map_index(normals[*index as usize], &prec.normal_precision) as usize];
*index =
map[normal_to_map_index(normals[*index as usize], &prec.normal_precision) as usize];
//assert!(((*index) as usize) < new_normals.len());
}
*normals = new_normals;
Expand Down
33 changes: 18 additions & 15 deletions src/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ pub fn read_from_obj<R: Read>(reader: &mut R) -> Result<Vec<(TMFMesh, String)>>
let lines = reader.lines();
let mut res = Vec::new();
for line in lines {
if let Some(mesh_and_name) = parse_line(line, &mut oi)? { res.push(mesh_and_name) };
if let Some(mesh_and_name) = parse_line(line, &mut oi)? {
res.push(mesh_and_name)
};
}
res.push(oi.finish());
Ok(res)
Expand Down Expand Up @@ -153,22 +155,21 @@ fn save_obj<W: Write>(
};
// Ensure normal triangle array, if present, has the right length.
if let Some(normal_triangles) = mesh.get_normal_triangles() {
if normal_triangles.len() != vert_triangle_len {
return Err(Error::new(
ErrorKind::Other,
"Number of triangles in the vertex triangle and normal triangle array differs.",
));
}
if normal_triangles.len() != vert_triangle_len {
return Err(Error::new(
ErrorKind::Other,
"Number of triangles in the vertex triangle and normal triangle array differs.",
));
}
}
// Ensure uv triangle array, if present, has the right length.
if let Some(uv_triangles) = mesh.get_uv_triangles() {

if uv_triangles.len() != vert_triangle_len {
return Err(Error::new(
ErrorKind::Other,
"Number of triangles in the vertex triangle and uv triangle array differs.",
));
}
if uv_triangles.len() != vert_triangle_len {
return Err(Error::new(
ErrorKind::Other,
"Number of triangles in the vertex triangle and uv triangle array differs.",
));
}
}
// TODO: this part can be rewritten to be more efficient by checking if arrays are present beforehand.
for i in 0..vert_triangle_len {
Expand All @@ -187,7 +188,9 @@ fn save_obj<W: Write>(
}
}
}
if let Some(normals) = normals { write!(w, "/{}", normals[i] + index_offset.2)? };
if let Some(normals) = normals {
write!(w, "/{}", normals[i] + index_offset.2)?
};
if i % 3 == 2 {
writeln!(w)?
} else {
Expand Down
5 changes: 2 additions & 3 deletions src/pile_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ impl<T: PartialEq + 'static> PileMap<T> {
}
}
impl<T: PartialEq> From<PileMap<T>> for Vec<T> {
fn from(val: PileMap<T>) -> Self {
val.pile

fn from(val: PileMap<T>) -> Self {
val.pile
}
}
53 changes: 35 additions & 18 deletions src/tmf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ pub(crate) enum SectionType {
NormalTriangleSegment = 4,
UvSegment = 5,
UvTriangleSegment = 6,
// MaterialInfo = 7,
// Materialtriangles = 8,
ColorSegment = 7,
ColorTriangleSegment = 8,
TangentSegment = 9,
TangentTriangleSegment = 10,
MaterialInfo = 11,
MaterialTriangleRanges = 12,
GroupInfo = 13,
GroupTriangleRanges = 14,
CustomIndexSegment = 15,
CustomFloatSegment = 16,
CustomUnit2Segment = 17,
CustomUnit3Segment = 18,
CustomVector2Segment = 19,
CustomVector3Segment = 20,
}
impl SectionType {
pub fn from_u16(input: u16) -> Self {
Expand Down Expand Up @@ -77,7 +89,7 @@ fn calc_shortest_edge(
) -> Result<FloatType> {
let shortest_edge = match vertex_triangles {
Some(vertex_triangles) => {
if vertex_triangles.is_empty(){
if vertex_triangles.is_empty() {
//TODO: handle 0 faced mesh as mesh with no faces!
return Ok(1.0);
}
Expand Down Expand Up @@ -148,21 +160,21 @@ fn save_vertices<W: Write>(
shortest_edge: FloatType,
) -> Result<()> {
if let Some(vertices) = vertices {
use crate::vertices::save_tmf_vertices;
save_tmf_vertices(
vertices,
p_info.vertex_precision,
curr_segment_data,
shortest_edge,
)?;
write_segment_header(
w,
SectionType::VertexSegment,
curr_segment_data.len(),
CompressionType::None,
)?;
w.write_all(curr_segment_data)?;
curr_segment_data.clear();
use crate::vertices::save_tmf_vertices;
save_tmf_vertices(
vertices,
p_info.vertex_precision,
curr_segment_data,
shortest_edge,
)?;
write_segment_header(
w,
SectionType::VertexSegment,
curr_segment_data.len(),
CompressionType::None,
)?;
w.write_all(curr_segment_data)?;
curr_segment_data.clear();
}
Ok(())
}
Expand Down Expand Up @@ -338,6 +350,11 @@ pub(crate) fn write_mesh<W: Write>(
}
None => (),
};
for data in &mesh.custom_data{
data.write(&mut curr_segment_data)?;
w.write_all(&curr_segment_data)?;
curr_segment_data.clear();
}
Ok(())
}
pub(crate) fn write_string<W: Write>(w: &mut W, s: &str) -> Result<()> {
Expand Down
22 changes: 11 additions & 11 deletions src/tmf_segment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Vector3,TMFMesh};
use crate::{TMFMesh, Vector3};
#[repr(u16)]
#[derive(Debug)]
pub(crate) enum SectionType {
Expand Down Expand Up @@ -42,21 +42,21 @@ impl CompressionType {
}
}
}
struct EncodedSegment{
seg_type:SectionType,
compresion_type:CompressionType,
seg_data:Vec<u8>,
struct EncodedSegment {
seg_type: SectionType,
compresion_type: CompressionType,
seg_data: Vec<u8>,
}
enum DecodedSegement{
enum DecodedSegement {
VertexSegment(Vec<Vector3>),
}
impl DecodedSegement{
fn encode(self)->EncodedSegment{
impl DecodedSegement {
fn encode(self) -> EncodedSegment {
todo!("Not working yet!");
}
fn apply(self,mesh:&mut TMFMesh){
match self{
DecodedSegement::VertexSegment(vertices)=>{
fn apply(self, mesh: &mut TMFMesh) {
match self {
DecodedSegement::VertexSegment(vertices) => {
/*match mesh.get_vertices(){
Some(vertices)=>
}*/
Expand Down

0 comments on commit d9a5be3

Please sign in to comment.