From da044d773d078f17d0432e5a8839f960ff6a71dc Mon Sep 17 00:00:00 2001 From: furiouzz Date: Tue, 3 Nov 2020 00:30:51 +0100 Subject: [PATCH] [gltf] Support camera and fix hierarchy --- crates/bevy_gltf/src/loader.rs | 121 ++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 5406ee6e8343e9..906caf503a30ef 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -4,9 +4,12 @@ use bevy_ecs::{bevy_utils::BoxedFuture, World, WorldBuilderSource}; use bevy_math::Mat4; use bevy_pbr::prelude::{PbrComponents, StandardMaterial}; use bevy_render::{ + camera::{Camera, CameraProjection, OrthographicProjection, PerspectiveProjection}, + entity::{Camera2dComponents, Camera3dComponents}, mesh::{Indices, Mesh, VertexAttributeValues}, pipeline::PrimitiveTopology, prelude::{Color, Texture}, + render_graph::base, texture::{AddressMode, FilterMode, SamplerDescriptor, TextureFormat}, }; use bevy_scene::Scene; @@ -20,7 +23,7 @@ use gltf::{ Primitive, }; use image::{GenericImageView, ImageFormat}; -use std::path::Path; +use std::{borrow::Cow, path::Path}; use thiserror::Error; /// An error that occurs when loading a GLTF file @@ -90,21 +93,21 @@ async fn load_gltf<'a, 'b>( .read_positions() .map(|v| VertexAttributeValues::Float3(v.collect())) { - mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, vertex_attribute); + mesh.set_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_POSITION), vertex_attribute); } if let Some(vertex_attribute) = reader .read_normals() .map(|v| VertexAttributeValues::Float3(v.collect())) { - mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, vertex_attribute); + mesh.set_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_NORMAL), vertex_attribute); } if let Some(vertex_attribute) = reader .read_tex_coords(0) .map(|v| VertexAttributeValues::Float2(v.into_f32().collect())) { - mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, vertex_attribute); + mesh.set_attribute(Cow::Borrowed(Mesh::ATTRIBUTE_UV_0), vertex_attribute); } if let Some(indices) = reader.read_indices() { @@ -211,42 +214,94 @@ fn load_node( ) -> Result<(), GltfError> { let transform = node.transform(); let mut gltf_error = None; - world_builder - .spawn(( + + // create camera node + let world_builder = if let Some(camera) = node.camera() { + match camera.projection() { + gltf::camera::Projection::Orthographic(orthographic) => { + let xmag = orthographic.xmag(); + let ymag = orthographic.ymag(); + let mut projection: OrthographicProjection = Default::default(); + projection.left = -xmag; + projection.right = xmag; + projection.top = ymag; + projection.bottom = -ymag; + projection.far = orthographic.zfar(); + projection.near = orthographic.znear(); + projection.get_projection_matrix(); + world_builder.spawn(Camera2dComponents { + camera: Camera { + name: Some(base::camera::CAMERA2D.to_owned()), + projection_matrix: projection.get_projection_matrix(), + ..Default::default() + }, + transform: Transform::from_matrix(Mat4::from_cols_array_2d( + &transform.matrix(), + )), + orthographic_projection: projection, + ..Default::default() + }) + } + gltf::camera::Projection::Perspective(perspective) => { + let mut projection: PerspectiveProjection = Default::default(); + projection.fov = perspective.yfov(); + projection.near = perspective.znear(); + if let Some(zfar) = perspective.zfar() { + projection.far = zfar; + } + if let Some(aspect_ratio) = perspective.aspect_ratio() { + projection.aspect_ratio = aspect_ratio; + } + world_builder.spawn(Camera3dComponents { + camera: Camera { + name: Some(base::camera::CAMERA3D.to_owned()), + projection_matrix: projection.get_projection_matrix(), + ..Default::default() + }, + transform: Transform::from_matrix(Mat4::from_cols_array_2d( + &transform.matrix(), + )), + perspective_projection: projection, + ..Default::default() + }) + } + } + } + // or create empty node + else { + world_builder.spawn(( Transform::from_matrix(Mat4::from_cols_array_2d(&transform.matrix())), GlobalTransform::default(), )) - .with_children(|parent| { - if let Some(mesh) = node.mesh() { - for primitive in mesh.primitives() { - let primitive_label = primitive_label(&mesh, &primitive); - let mesh_asset_path = - AssetPath::new_ref(load_context.path(), Some(&primitive_label)); - let material = primitive.material(); - let material_label = material_label(&material); - let material_asset_path = - AssetPath::new_ref(load_context.path(), Some(&material_label)); - parent.spawn(PbrComponents { - mesh: load_context.get_handle(mesh_asset_path), - material: load_context.get_handle(material_asset_path), - ..Default::default() - }); - } + }; + + world_builder.with_children(|parent| { + if let Some(mesh) = node.mesh() { + // append primitives + for primitive in mesh.primitives() { + let primitive_label = primitive_label(&mesh, &primitive); + let mesh_asset_path = + AssetPath::new_ref(load_context.path(), Some(&primitive_label)); + let material = primitive.material(); + let material_label = material_label(&material); + let material_asset_path = + AssetPath::new_ref(load_context.path(), Some(&material_label)); + parent.spawn(PbrComponents { + mesh: load_context.get_handle(mesh_asset_path), + material: load_context.get_handle(material_asset_path), + ..Default::default() + }); } + } - if parent.current_entity().is_none() { + // append other nodes + for child in node.children() { + if let Err(err) = load_node(&child, parent, load_context, buffer_data) { + gltf_error = Some(err); return; } - - parent.with_children(|parent| { - for child in node.children() { - if let Err(err) = load_node(&child, parent, load_context, buffer_data) { - gltf_error = Some(err); - return; - } - } - }); - }); + } + }); if let Some(err) = gltf_error { Err(err) } else {