1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use crate::io::*; use std::path::Path; use crate::{CPUMesh, CPUMaterial}; pub struct ThreeD { } impl ThreeD { pub fn parse<P: AsRef<Path>>(loaded: &Loaded, path: P) -> Result<(Vec<CPUMesh>, Vec<CPUMaterial>), Error> { let bytes = Loader::get(loaded, path.as_ref())?; let mut decoded = bincode::deserialize::<ThreeDMesh>(bytes) .or_else(|_| Self::parse_version1(bytes))?; if decoded.meshes.len() == 0 { decoded = Self::parse_version1(bytes)?; } if decoded.magic_number != 61 { Err(bincode::Error::new(bincode::ErrorKind::Custom("Corrupt file!".to_string())))?; } if decoded.meshes.len() == 0 { Err(bincode::Error::new(bincode::ErrorKind::Custom("No mesh data in file!".to_string())))?; } let mut cpu_meshes = Vec::new(); for mesh in decoded.meshes { cpu_meshes.push(CPUMesh { name: mesh.name, material_name: mesh.material_name, positions: mesh.positions, indices: mesh.indices, normals: mesh.normals, uvs: mesh.uvs }); } let mut cpu_materials = Vec::new(); for material in decoded.materials { cpu_materials.push(CPUMaterial { name: material.name, color: material.color, diffuse_intensity: material.diffuse_intensity, specular_intensity: material.specular_intensity, specular_power: material.specular_power, texture_image: if let Some(filename) = material.texture_path { let texture_path = path.as_ref().parent().unwrap_or(&Path::new("./")).join(filename); Some(Loader::get_image(loaded, &texture_path)?) } else {None} }); } Ok((cpu_meshes, cpu_materials)) } fn parse_version1(bytes: &[u8]) -> Result<ThreeDMesh, bincode::Error> { bincode::deserialize::<ThreeDMeshV1>(bytes).map(|m| ThreeDMesh { magic_number: m.magic_number, version: 2, meshes: vec![ThreeDMeshSubMesh { indices: if m.indices.len() > 0 { Some(m.indices) } else {None}, positions: m.positions, normals: if m.normals.len() > 0 { Some(m.normals) } else {None}, ..Default::default() }], materials: vec![] }) } pub fn serialize(filename: &str, cpu_meshes: Vec<CPUMesh>, cpu_materials: Vec<CPUMaterial>) -> Result<Vec<u8>, Error> { let mut meshes = Vec::new(); for cpu_mesh in cpu_meshes { meshes.push(ThreeDMeshSubMesh { name: cpu_mesh.name, material_name: cpu_mesh.material_name, indices: cpu_mesh.indices, positions: cpu_mesh.positions, normals: cpu_mesh.normals, uvs: cpu_mesh.uvs }); } let mut materials = Vec::new(); for cpu_material in cpu_materials { let texture_path = cpu_material.texture_image.as_ref().map(|_| format!("{}_{}.png", filename, cpu_material.name)); materials.push(ThreeDMaterial { name: cpu_material.name, texture_path, color: cpu_material.color, diffuse_intensity: cpu_material.diffuse_intensity, specular_intensity: cpu_material.specular_intensity, specular_power: cpu_material.specular_power }); } Ok(bincode::serialize::<ThreeDMesh>(&ThreeDMesh { magic_number: 61, version: 2, meshes, materials })?) } } #[derive(serde::Serialize, serde::Deserialize, Debug)] struct ThreeDMesh { pub magic_number: u8, pub version: u8, pub meshes: Vec<ThreeDMeshSubMesh>, pub materials: Vec<ThreeDMaterial> } #[derive(serde::Serialize, serde::Deserialize, Debug, Default)] struct ThreeDMeshSubMesh { pub name: String, pub material_name: Option<String>, pub indices: Option<Vec<u32>>, pub positions: Vec<f32>, pub normals: Option<Vec<f32>>, pub uvs: Option<Vec<f32>>, } #[derive(serde::Serialize, serde::Deserialize, Debug, Default)] struct ThreeDMaterial { pub name: String, pub texture_path: Option<String>, pub color: Option<(f32, f32, f32, f32)>, pub diffuse_intensity: Option<f32>, pub specular_intensity: Option<f32>, pub specular_power: Option<f32> } #[derive(serde::Serialize, serde::Deserialize, Debug)] struct ThreeDMeshV1 { pub magic_number: u8, pub version: u8, pub indices: Vec<u32>, pub positions: Vec<f32>, pub normals: Vec<f32> }