mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Add support for binary glTF (.glb) (#271)
Add support for binary glTF (.glb)
This commit is contained in:
parent
c9000deafa
commit
9aff0bcc2a
3 changed files with 27 additions and 9 deletions
BIN
assets/models/monkey/Monkey.glb
Normal file
BIN
assets/models/monkey/Monkey.glb
Normal file
Binary file not shown.
|
@ -5,7 +5,7 @@ use bevy_render::{
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bevy_asset::AssetLoader;
|
use bevy_asset::AssetLoader;
|
||||||
use gltf::{buffer::Source, iter, mesh::Mode};
|
use gltf::{buffer::Source, mesh::Mode};
|
||||||
use std::{fs, io, path::Path};
|
use std::{fs, io, path::Path};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ impl AssetLoader<Mesh> for GltfLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extensions(&self) -> &[&str] {
|
fn extensions(&self) -> &[&str] {
|
||||||
static EXTENSIONS: &[&str] = &["gltf"];
|
static EXTENSIONS: &[&str] = &["gltf", "glb"];
|
||||||
EXTENSIONS
|
EXTENSIONS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ pub enum GltfError {
|
||||||
Gltf(#[from] gltf::Error),
|
Gltf(#[from] gltf::Error),
|
||||||
#[error("Failed to load file.")]
|
#[error("Failed to load file.")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
#[error("Binary buffers not supported yet.")]
|
#[error("Binary blob is missing.")]
|
||||||
BinaryBuffersUnsupported,
|
MissingBlob,
|
||||||
#[error("Failed to decode base64 mesh data.")]
|
#[error("Failed to decode base64 mesh data.")]
|
||||||
Base64Decode(#[from] base64::DecodeError),
|
Base64Decode(#[from] base64::DecodeError),
|
||||||
#[error("Unsupported buffer format.")]
|
#[error("Unsupported buffer format.")]
|
||||||
|
@ -58,7 +58,7 @@ fn get_primitive_topology(mode: Mode) -> Result<PrimitiveTopology, GltfError> {
|
||||||
// TODO: this should return a scene
|
// TODO: this should return a scene
|
||||||
pub fn load_gltf(asset_path: &Path, bytes: Vec<u8>) -> Result<Mesh, GltfError> {
|
pub fn load_gltf(asset_path: &Path, bytes: Vec<u8>) -> Result<Mesh, GltfError> {
|
||||||
let gltf = gltf::Gltf::from_slice(&bytes)?;
|
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() {
|
for scene in gltf.scenes() {
|
||||||
if let Some(node) = scene.nodes().next() {
|
if let Some(node) = scene.nodes().next() {
|
||||||
return Ok(load_node(&buffer_data, &node, 1)?);
|
return Ok(load_node(&buffer_data, &node, 1)?);
|
||||||
|
@ -112,11 +112,11 @@ fn load_node(buffer_data: &[Vec<u8>], node: &gltf::Node, depth: i32) -> Result<M
|
||||||
panic!("failed to find mesh")
|
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,";
|
const OCTET_STREAM_URI: &str = "data:application/octet-stream;base64,";
|
||||||
|
|
||||||
let mut buffer_data = Vec::new();
|
let mut buffer_data = Vec::new();
|
||||||
for buffer in buffers {
|
for buffer in gltf.buffers() {
|
||||||
match buffer.source() {
|
match buffer.source() {
|
||||||
Source::Uri(uri) => {
|
Source::Uri(uri) => {
|
||||||
if uri.starts_with("data:") {
|
if uri.starts_with("data:") {
|
||||||
|
@ -131,7 +131,13 @@ fn load_buffers(buffers: iter::Buffers, asset_path: &Path) -> Result<Vec<Vec<u8>
|
||||||
buffer_data.push(buffer_bytes);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,24 @@ fn setup(
|
||||||
commands
|
commands
|
||||||
// mesh
|
// mesh
|
||||||
.spawn(PbrComponents {
|
.spawn(PbrComponents {
|
||||||
// load the mesh
|
// load a mesh from glTF
|
||||||
mesh: asset_server
|
mesh: asset_server
|
||||||
.load("assets/models/monkey/Monkey.gltf")
|
.load("assets/models/monkey/Monkey.gltf")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
// create a material for the mesh
|
// create a material for the mesh
|
||||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
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()
|
..Default::default()
|
||||||
})
|
})
|
||||||
// light
|
// light
|
||||||
|
|
Loading…
Add table
Reference in a new issue