Skip to content

Commit

Permalink
Add support for binary glTF (.glb) (#271)
Browse files Browse the repository at this point in the history
Add support for binary glTF (.glb)
  • Loading branch information
eliaspekkala authored Aug 25, 2020
1 parent c9000de commit 9aff0bc
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
Binary file added assets/models/monkey/Monkey.glb
Binary file not shown.
22 changes: 14 additions & 8 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy_render::{

use anyhow::Result;
use bevy_asset::AssetLoader;
use gltf::{buffer::Source, iter, mesh::Mode};
use gltf::{buffer::Source, mesh::Mode};
use std::{fs, io, path::Path};
use thiserror::Error;

Expand All @@ -22,7 +22,7 @@ impl AssetLoader<Mesh> for GltfLoader {
}

fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["gltf"];
static EXTENSIONS: &[&str] = &["gltf", "glb"];
EXTENSIONS
}
}
Expand All @@ -36,8 +36,8 @@ pub enum GltfError {
Gltf(#[from] gltf::Error),
#[error("Failed to load file.")]
Io(#[from] io::Error),
#[error("Binary buffers not supported yet.")]
BinaryBuffersUnsupported,
#[error("Binary blob is missing.")]
MissingBlob,
#[error("Failed to decode base64 mesh data.")]
Base64Decode(#[from] base64::DecodeError),
#[error("Unsupported buffer format.")]
Expand All @@ -58,7 +58,7 @@ fn get_primitive_topology(mode: Mode) -> Result<PrimitiveTopology, GltfError> {
// TODO: this should return a scene
pub fn load_gltf(asset_path: &Path, bytes: Vec<u8>) -> Result<Mesh, GltfError> {
let gltf = gltf::Gltf::from_slice(&bytes)?;
let buffer_data = load_buffers(gltf.buffers(), asset_path)?;
let buffer_data = load_buffers(&gltf, asset_path)?;
for scene in gltf.scenes() {
if let Some(node) = scene.nodes().next() {
return Ok(load_node(&buffer_data, &node, 1)?);
Expand Down Expand Up @@ -112,11 +112,11 @@ fn load_node(buffer_data: &[Vec<u8>], node: &gltf::Node, depth: i32) -> Result<M
panic!("failed to find mesh")
}

fn load_buffers(buffers: iter::Buffers, asset_path: &Path) -> Result<Vec<Vec<u8>>, GltfError> {
fn load_buffers(gltf: &gltf::Gltf, asset_path: &Path) -> Result<Vec<Vec<u8>>, GltfError> {
const OCTET_STREAM_URI: &str = "data:application/octet-stream;base64,";

let mut buffer_data = Vec::new();
for buffer in buffers {
for buffer in gltf.buffers() {
match buffer.source() {
Source::Uri(uri) => {
if uri.starts_with("data:") {
Expand All @@ -131,7 +131,13 @@ fn load_buffers(buffers: iter::Buffers, asset_path: &Path) -> Result<Vec<Vec<u8>
buffer_data.push(buffer_bytes);
}
}
Source::Bin => return Err(GltfError::BinaryBuffersUnsupported),
Source::Bin => {
if let Some(blob) = gltf.blob.as_deref() {
buffer_data.push(blob.into());
} else {
return Err(GltfError::MissingBlob);
}
}
}
}

Expand Down
14 changes: 13 additions & 1 deletion examples/3d/load_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,24 @@ fn setup(
commands
// mesh
.spawn(PbrComponents {
// load the mesh
// load a mesh from glTF
mesh: asset_server
.load("assets/models/monkey/Monkey.gltf")
.unwrap(),
// create a material for the mesh
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
translation: Translation::new(-1.5, 0.0, 0.0),
..Default::default()
})
// mesh
.spawn(PbrComponents {
// load a mesh from binary glTF
mesh: asset_server
.load("assets/models/monkey/Monkey.glb")
.unwrap(),
// create a material for the mesh
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
translation: Translation::new(1.5, 0.0, 0.0),
..Default::default()
})
// light
Expand Down

0 comments on commit 9aff0bc

Please sign in to comment.