bevy
bevy copied to clipboard
2D GLTF scene support
What problem does this solve or what need does it fill?
I'm using blender to create a 2D scene using the "2D Animation" mode. When using an OrthographicCamera to view a scene loaded from a GLTF file all of the Meshes and Materials are 3D and are not rendered. Conversion into a 2D scene is fairly cumbersome.
What solution would you like?
I'd like a "Scene2dBundle" that best effort can display a gltf in an Orthographic view.
Scene2dBundle{
scene: my_gltf.scenes[0].clone(),
..default()
}
What alternative(s) have you considered?
Currently, I am iterating over the nodes in the Gltf as follows:
for gltf_node in my_gltf.nodes.iter() {
if let Some(node) = gltf_nodes.get(gltf_node) {
if let Some(mesh_handle) = &node.mesh {
if let Some(mesh) = gltfs_meshes.get(mesh_handle) {
for primative in mesh.primitives.iter() {
let color_mat = if let Some(mat) = &primative.material {
if let Some(standard_mat) = standard_materials.get(mat) {
materials.add(ColorMaterial::from(standard_mat.base_color))
}
else {
materials.add(ColorMaterial::from(Color::rgb(3.2, 2.3, 0.4)))
}
}
else {
materials.add(ColorMaterial::from(Color::rgb(3.2, 2.3, 0.4)))
};
commands.spawn((MaterialMesh2dBundle{
mesh: primative.mesh.clone().into(),
material: color_mat,
transform: Transform{
translation: node.transform.translation * 150.0, // + 0.1 * Vec3::Z * (ix as f32),
rotation: Quat::from_axis_angle(Vec3::X,std::f32::consts::PI / 2.0),
scale: 150.0 * Vec3::ONE,
},
..Default::default()
}, SplashElement));
}
}
}
}
}
Additional context
Any other information you would like to add such as related previous work, screenshots, benchmarks, etc.
An example 2D gltf from a Blender 2D Animation(no cameras exported and material left out due to being binary).
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.0.44",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"name":"Scene",
"nodes":[
0
]
}
],
"nodes":[
{
"mesh":0,
"name":"Circle",
"rotation":[
0.7071068286895752,
0,
0,
0.7071068286895752
]
}
],
"animations":[
{
"channels":[
{
"sampler":0,
"target":{
"node":0,
"path":"translation"
}
},
{
"sampler":1,
"target":{
"node":0,
"path":"rotation"
}
},
{
"sampler":2,
"target":{
"node":0,
"path":"scale"
}
}
],
"name":"CircleAction",
"samplers":[
{
"input":4,
"interpolation":"LINEAR",
"output":5
},
{
"input":4,
"interpolation":"LINEAR",
"output":6
},
{
"input":4,
"interpolation":"LINEAR",
"output":7
}
]
}
],
"materials":[
{
"doubleSided":true,
"name":"Material",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.05711526423692703,
0.7999998927116394,
0.027054570615291595,
1
],
"metallicFactor":0,
"roughnessFactor":0.5
}
}
],
"meshes":[
{
"name":"Circle",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":32,
"max":[
1,
0,
1
],
"min":[
-1,
0,
-1
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":32,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":32,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":90,
"type":"SCALAR"
},
{
"bufferView":4,
"componentType":5126,
"count":1,
"max":[
0.041666666666666664
],
"min":[
0.041666666666666664
],
"type":"SCALAR"
},
{
"bufferView":5,
"componentType":5126,
"count":1,
"type":"VEC3"
},
{
"bufferView":6,
"componentType":5126,
"count":1,
"type":"VEC4"
},
{
"bufferView":7,
"componentType":5126,
"count":1,
"type":"VEC3"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":384,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":384,
"byteOffset":384,
"target":34962
},
{
"buffer":0,
"byteLength":256,
"byteOffset":768,
"target":34962
},
{
"buffer":0,
"byteLength":180,
"byteOffset":1024,
"target":34963
},
{
"buffer":0,
"byteLength":4,
"byteOffset":1204
},
{
"buffer":0,
"byteLength":12,
"byteOffset":1208
},
{
"buffer":0,
"byteLength":16,
"byteOffset":1220
},
{
"buffer":0,
"byteLength":12,
"byteOffset":1236
}
],
"buffers":[
{
"byteLength":1248,
"uri":"circle.bin"
}
]
}