Skip to content

Commit

Permalink
Added Obj compression
Browse files Browse the repository at this point in the history
  • Loading branch information
AHL00 committed Oct 20, 2024
1 parent 512978a commit 3a02f78
Show file tree
Hide file tree
Showing 10 changed files with 375,124 additions and 404 deletions.
34 changes: 19 additions & 15 deletions cobalt_asset_manager/src/pages/import_assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,30 +324,34 @@ impl ImportAssets {
Message::ImportAssetsMessage(ImportAssetsMessage::ImportAsset),
);

let compression_toggle =
widget::Checkbox::new("Compression", self.pack.compression.is_some()).on_toggle(
|compression| {
let mut new_pack_info = self.pack.clone();
let compression_toggle = widget::Checkbox::new(
format!("Compression ({})", PackInfo::COMPRESSION_ALGO),
self.pack.compression.is_some(),
)
.on_toggle(|compression| {
let mut new_pack_info = self.pack.clone();

if compression {
new_pack_info.compression = Some(4);
} else {
new_pack_info.compression = None;
}
if compression {
new_pack_info.compression = Some(0);
} else {
new_pack_info.compression = None;
}

Message::ImportAssetsMessage(ImportAssetsMessage::SetPackInfo(new_pack_info))
},
);
Message::ImportAssetsMessage(ImportAssetsMessage::SetPackInfo(new_pack_info))
});

let pack_settings = if let Some(compression) = self.pack.compression {
let compression_level_label =
widget::Text::new(format!("Compression Level: {}", compression));
let compression_input =
widget::Slider::new(0..=9, self.pack.compression.unwrap(), |level| {
let compression_input = widget::Slider::new(
PackInfo::MIN_COMPRESSION_LEVEL..=PackInfo::MAX_COMPRESSION_LEVEL,
self.pack.compression.unwrap(),
|level| {
let mut new_pack_info = self.pack.clone();
new_pack_info.compression = Some(level);
Message::ImportAssetsMessage(ImportAssetsMessage::SetPackInfo(new_pack_info))
});
},
);

widget::column![
compression_toggle,
Expand Down
17 changes: 9 additions & 8 deletions cobalt_assets/src/manifest.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Asset packing system
// Main manifest file is `manifest.toml`

use bytes::Bytes;
use cobalt_graphics::texture::TextureType;
use hashbrown::HashMap;
use path_clean::PathClean;

Expand All @@ -11,10 +6,9 @@ use crate::asset::{AssetImportError, AssetImporter};
use super::{
asset::{AssetFileSystemType, AssetID},
exports::AssetTrait,
server::AssetLoadError,
};
use std::{
io::{self, Read},
io::{self},
path::PathBuf,
};

Expand All @@ -26,6 +20,13 @@ pub struct PackInfo {
pub compression: Option<u32>,
}

impl PackInfo {
pub const MAX_COMPRESSION_LEVEL: u32 = 22;
pub const MIN_COMPRESSION_LEVEL: u32 = 0;
pub const DEFAULT_COMPRESSION_LEVEL: u32 = 3;
pub const COMPRESSION_ALGO: &'static str = "zstd";
}

#[derive(serde::Deserialize, serde::Serialize, Clone, Debug)]
pub struct AssetInfo {
pub asset_id: AssetID,
Expand Down Expand Up @@ -204,7 +205,7 @@ pub fn pack_asset<A: AssetTrait, T: AssetImporter<A>>(
let extra = T::import(abs_input, &asset_info, assets_dir)
.map_err(|e| AssetPackError::ImportError(e))?;

asset_info.extra = extra;
asset_info.extra = extra;

manifest.assets.push(asset_info);

Expand Down
1 change: 1 addition & 0 deletions cobalt_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ bytes = { version = "1.7.2", features = ["serde"] }
toml = "0.8.15"
ron = "0.8.1"
bincode = "1.3.3"
zstd = "0.13.2"

cobalt_ecs = { path = "../cobalt_ecs" }

Expand Down
42 changes: 30 additions & 12 deletions cobalt_core/src/asset_types/mesh.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use cobalt_assets::{asset::{AssetReadError, AssetTrait}, server::AssetLoadError};
use std::io::{BufReader, Read};

use cobalt_assets::{
asset::{AssetReadError, AssetTrait},
server::AssetLoadError,
};
use cobalt_graphics::vertex::UvNormalVertex;
use wgpu::util::DeviceExt;

Expand Down Expand Up @@ -29,26 +34,39 @@ impl AssetTrait for Mesh {
) -> Result<Self, AssetReadError> {
let abs_path = assets_dir.join(&asset_info.relative_path);

let buffer = std::fs::read(&abs_path)?;
let data = if let Some(_) = asset_info.pack.compression {
let reader = BufReader::new(std::fs::File::open(&abs_path)?);

let mut decoder = zstd::Decoder::new(reader).map_err(|e| AssetReadError::Io(e))?;

let mut decoded = Vec::new();
decoder
.read_to_end(&mut decoded)
.map_err(|e| AssetReadError::Io(e))?;

decoded
} else {
std::fs::read(&abs_path)?
};

let mesh_buffer: MeshAssetBuffer =
bincode::deserialize(&buffer).map_err(|e| AssetReadError::DeserializeError(e))?;
bincode::deserialize(&data).map_err(|e| AssetReadError::DeserializeError(e))?;

let index_buffer = graphics.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
let index_buffer = graphics
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&mesh_buffer.index_buffer),
usage: wgpu::BufferUsages::INDEX,
},
);
});

let vertex_buffer = graphics.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
let vertex_buffer = graphics
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(&mesh_buffer.vertex_buffer),
usage: wgpu::BufferUsages::VERTEX,
},
);
});

Ok(Mesh {
index_buffer,
Expand All @@ -58,4 +76,4 @@ impl AssetTrait for Mesh {
has_uv: mesh_buffer.has_uv,
})
}
}
}
48 changes: 23 additions & 25 deletions cobalt_core/src/importers/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,13 @@ impl AssetImporter<Mesh> for ObjImporter {

let model = &mut models[0];

// Check if normals and texcoords are present
if model.mesh.normals.len() == 0 {
log::warn!(
"Mesh \"{}\" does not contain normals. Normals will be generated.",
asset_info.name
);

let normals = generate_normals(&model.mesh.positions, &model.mesh.indices);

model.mesh.normals = normals;
}

// Always recompute normals, as the normals in the .obj file
// may not be correct.
let normals = generate_normals(&model.mesh.positions, &model.mesh.indices);

model.mesh.normals = normals;

// Check if texcoords are present
if model.mesh.texcoords.len() == 0 {
log::warn!("Mesh \"{}\" does not contain texture coordinates. There will be issues if rendering with textures.", asset_info.name);
}
Expand Down Expand Up @@ -200,7 +195,15 @@ impl AssetImporter<Mesh> for ObjImporter {
has_uv: model.mesh.texcoords.len() > 0,
};

let ser_bytes = bincode::serialize(&mesh_buffer)?;
let ser_bytes = if let Some(compression) = asset_info.pack.compression {
let mut encoder = zstd::Encoder::new(Vec::new(), compression as i32)?;

encoder.write_all(&bincode::serialize(&mesh_buffer)?)?;

encoder.finish()?
} else {
bincode::serialize(&mesh_buffer)?
};

// Write the mesh buffer to the target file
let target_path = assets_dir.join(&asset_info.relative_path);
Expand Down Expand Up @@ -239,16 +242,8 @@ fn generate_normals(positions: &[f32], indices: &[u32]) -> Vec<f32> {
positions[i2 * 3 + 2],
];

let e1 = [
v1[0] - v0[0],
v1[1] - v0[1],
v1[2] - v0[2],
];
let e2 = [
v2[0] - v0[0],
v2[1] - v0[1],
v2[2] - v0[2],
];
let e1 = [v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]];
let e2 = [v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]];

let normal = [
e1[1] * e2[2] - e1[2] * e2[1],
Expand All @@ -264,12 +259,15 @@ fn generate_normals(positions: &[f32], indices: &[u32]) -> Vec<f32> {
}

for i in (0..normals.len()).step_by(3) {
let len = (normals[i] * normals[i] + normals[i + 1] * normals[i + 1] + normals[i + 2] * normals[i + 2]).sqrt();
let len = (normals[i] * normals[i]
+ normals[i + 1] * normals[i + 1]
+ normals[i + 2] * normals[i + 2])
.sqrt();

normals[i] /= len;
normals[i + 1] /= len;
normals[i + 2] /= len;
}

normals
}
}
Binary file added examples/test_scene/assets/dragon.asset
Binary file not shown.
15 changes: 15 additions & 0 deletions examples/test_scene/assets/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,18 @@ secs_since_epoch = 1729405470
nanos_since_epoch = 529254513

[assets.extra]

[[assets]]
asset_id = "6de96971-4f43-4995-a51c-2f4d1b268f7e"
relative_path = "dragon.asset"
name = "dragon"
type_name = "Mesh"

[assets.pack]
compression = 3

[assets.timestamp]
secs_since_epoch = 1729407915
nanos_since_epoch = 685122023

[assets.extra]
Loading

0 comments on commit 3a02f78

Please sign in to comment.