render: process GltfScenes and Node local transforms

This commit is contained in:
SeanOMik 2024-03-08 00:21:28 -05:00 committed by SeanOMik
parent c1b5ca768f
commit fba925512b
13 changed files with 248 additions and 198 deletions

3
Cargo.lock generated
View File

@ -1845,7 +1845,9 @@ dependencies = [
"gltf",
"image",
"infer",
"instant",
"lyra-ecs",
"lyra-math",
"mime",
"notify",
"notify-debouncer-full",
@ -3101,7 +3103,6 @@ dependencies = [
"async-std",
"fps_counter",
"lyra-engine",
"lyra-scripting",
"tracing",
]

View File

@ -6,8 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lyra-engine = { path = "../../", version = "0.0.1", features = ["lua_scripting"] }
lyra-scripting = { path = "../../lyra-scripting", features = ["lua", "teal"] }
lyra-engine = { path = "../../", version = "0.0.1" }
#lyra-engine = { path = "../../", version = "0.0.1", features = ["lua_scripting"] }
#lyra-scripting = { path = "../../lyra-scripting", features = ["lua", "teal"] }
#lyra-ecs = { path = "../../lyra-ecs"}
anyhow = "1.0.75"
async-std = "1.12.0"

View File

@ -0,0 +1,2 @@
Sponza*
Textures

View File

@ -0,0 +1 @@
To keep the size of this repository down, the Sponza scene is omitted from this repo. The files were downloaded from https://github.com/toji/sponza-optimized

View File

@ -1,7 +1,7 @@
use std::ptr::NonNull;
use lyra_engine::{math::{self, Vec3}, math::Transform, input::{KeyCode, ActionHandler, Action, ActionKind, LayoutId, ActionMapping, ActionSource, ActionMappingId, InputActionPlugin, MouseInput, MouseAxis, CommonActionLabel}, game::Game, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct, ecs::{system::{Criteria, CriteriaSchedule, BatchedSystem, IntoSystem}, World, Component}, DeltaTime, scene::{ModelComponent, CameraComponent}, lua::{LuaScriptingPlugin, LuaScript}, Script, ScriptList};
use lyra_engine::assets::{ResourceManager, Model};
use lyra_engine::{assets::gltf::Gltf, ecs::{system::{BatchedSystem, Criteria, CriteriaSchedule, IntoSystem}, Component, World}, game::Game, input::{Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource, InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput}, math::{self, Transform, Vec3}, render::light::{directional::DirectionalLight, PointLight, SpotLight}, scene::{CameraComponent, MeshComponent}, DeltaTime};
use lyra_engine::assets::ResourceManager;
mod free_fly_camera;
use free_fly_camera::{FreeFlyCameraPlugin, FreeFlyCamera};
@ -16,6 +16,13 @@ pub enum ActionLabel {
LookRoll,
}
const ACTLBL_MOVE_UP_DOWN: &str = "MoveUpDown";
const ACTLBL_MOVE_LEFT_RIGHT: &str = "MoveLeftRight";
const ACTLBL_MOVE_FORWARD_BACKWARD: &str = "MoveForwardBackward";
const ACTLBL_LOOK_LEFT_RIGHT: &str = "LookLeftRight";
const ACTLBL_LOOK_UP_DOWN: &str = "LookUpDown";
const ACTLBL_LOOK_ROLL: &str = "LookRoll";
struct FixedTimestep {
max_tps: u32,
fixed_time: f32,
@ -86,30 +93,45 @@ async fn main() {
//let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
//let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
//let cube_model = resman.request::<Model>("assets/cube-texture-bin.glb").unwrap();
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
let crate_model = resman.request::<Model>("assets/crate/crate.gltf").unwrap();
//let sponza_model = resman.request::<Model>("assets/sponza/Sponza.gltf").unwrap();
let cube_gltf = resman.request::<Gltf>("assets/texture-sep/texture-sep.gltf").unwrap();
let crate_gltf = resman.request::<Gltf>("assets/crate/crate.gltf").unwrap();
let separate_gltf = resman.request::<Gltf>("assets/pos-testing/separate-nodes-two-cubes.glb").unwrap();
drop(resman);
/* world.spawn((
ModelComponent(antique_camera_model),
Transform::from_xyz(0.0, -5.0, -10.0),
)); */
let cube_mesh = &cube_gltf.data_ref()
.unwrap().meshes[0];
let crate_mesh = &crate_gltf.data_ref()
.unwrap().meshes[0];
/* world.spawn((
ModelComponent(sponza_model),
let separate_scene = &separate_gltf.data_ref()
.unwrap().scenes[0];
/* let sponza_model = resman.request::<Gltf>("assets/sponza/Sponza.gltf").unwrap();
drop(resman);
let sponza_scene = &sponza_model.data_ref()
.unwrap().scenes[0];
world.spawn((
sponza_scene.clone(),
Transform::from_xyz(0.0, 0.0, 0.0),
)); */
{
let cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0);
world.spawn((
separate_scene.clone(),
Transform::from_xyz(0.0, -5.0, -10.0),
));
/* {
let cube_tran = Transform::from_xyz(-5.9026427, -1.8953488, -10.0);
//cube_tran.rotate_y(math::Angle::Degrees(180.0));
world.spawn((
cube_tran,
ModelComponent(crate_model.clone()),
crate_mesh.clone(),
CubeFlag,
));
}
} */
{
let mut light_tran = Transform::from_xyz(1.5, 2.5, 0.0);
@ -124,11 +146,11 @@ async fn main() {
specular: 1.3,
},
light_tran,
ModelComponent(cube_model.clone()),
cube_mesh.clone(),
));
}
{
/* {
let mut light_tran = Transform::from_xyz(-3.5, 0.2, -4.5);
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
world.spawn((
@ -146,10 +168,32 @@ async fn main() {
specular: 1.0,
},
Transform::from(light_tran),
ModelComponent(cube_model.clone()),
cube_mesh.clone(),
));
}
{
let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5);
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
world.spawn((
PointLight {
color: Vec3::new(0.0, 0.0, 1.0),
intensity: 3.3,
constant: 1.0,
linear: 0.09,
quadratic: 0.032,
ambient: 0.2,
diffuse: 1.0,
specular: 1.3,
},
Transform::from(light_tran),
cube_mesh.clone(),
));
} */
/* {
let mut light_tran = Transform::from_xyz(-5.0, 2.5, -9.5);
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
@ -172,28 +216,6 @@ async fn main() {
));
} */
{
let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5);
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
world.spawn((
PointLight {
color: Vec3::new(0.0, 0.0, 1.0),
intensity: 3.3,
constant: 1.0,
linear: 0.09,
quadratic: 0.032,
ambient: 0.2,
diffuse: 1.0,
specular: 1.3,
},
Transform::from(light_tran),
ModelComponent(cube_model),
));
}
let mut camera = CameraComponent::new_3d();
camera.transform.translation += math::Vec3::new(0.0, 0.0, 5.5);
world.spawn(( camera, FreeFlyCamera::default() ));
@ -211,7 +233,7 @@ async fn main() {
Ok(())
};
let fps_plugin = move |game: &mut Game| {
let _fps_plugin = move |game: &mut Game| {
let world = game.world_mut();
world.add_resource(fps_counter::FPSCounter::new());
};
@ -246,54 +268,54 @@ async fn main() {
};
let action_handler_plugin = |game: &mut Game| {
/* let action_handler = ActionHandler::builder()
let action_handler = ActionHandler::builder()
.add_layout(LayoutId::from(0))
.add_action(CommonActionLabel::MoveForwardBackward, Action::new(ActionKind::Axis))
.add_action(CommonActionLabel::MoveLeftRight, Action::new(ActionKind::Axis))
.add_action(CommonActionLabel::MoveUpDown, Action::new(ActionKind::Axis))
.add_action(CommonActionLabel::LookLeftRight, Action::new(ActionKind::Axis))
.add_action(CommonActionLabel::LookUpDown, Action::new(ActionKind::Axis))
.add_action(CommonActionLabel::LookRoll, Action::new(ActionKind::Axis))
.add_action(ACTLBL_MOVE_FORWARD_BACKWARD, Action::new(ActionKind::Axis))
.add_action(ACTLBL_MOVE_LEFT_RIGHT, Action::new(ActionKind::Axis))
.add_action(ACTLBL_MOVE_UP_DOWN, Action::new(ActionKind::Axis))
.add_action(ACTLBL_LOOK_LEFT_RIGHT, Action::new(ActionKind::Axis))
.add_action(ACTLBL_LOOK_UP_DOWN, Action::new(ActionKind::Axis))
.add_action(ACTLBL_LOOK_ROLL, Action::new(ActionKind::Axis))
.add_mapping(ActionMapping::builder(LayoutId::from(0), ActionMappingId::from(0))
.bind(CommonActionLabel::MoveForwardBackward, &[
.bind(ACTLBL_MOVE_FORWARD_BACKWARD, &[
ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0),
ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0)
])
.bind(CommonActionLabel::MoveLeftRight, &[
.bind(ACTLBL_MOVE_LEFT_RIGHT, &[
ActionSource::Keyboard(KeyCode::A).into_binding_modifier(-1.0),
ActionSource::Keyboard(KeyCode::D).into_binding_modifier(1.0)
])
.bind(CommonActionLabel::MoveUpDown, &[
.bind(ACTLBL_MOVE_UP_DOWN, &[
ActionSource::Keyboard(KeyCode::C).into_binding_modifier(1.0),
ActionSource::Keyboard(KeyCode::Z).into_binding_modifier(-1.0)
])
.bind(CommonActionLabel::LookLeftRight, &[
.bind(ACTLBL_LOOK_LEFT_RIGHT, &[
ActionSource::Mouse(MouseInput::Axis(MouseAxis::X)).into_binding(),
ActionSource::Keyboard(KeyCode::Left).into_binding_modifier(-1.0),
ActionSource::Keyboard(KeyCode::Right).into_binding_modifier(1.0),
//ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickX)).into_binding(),
])
.bind(CommonActionLabel::LookUpDown, &[
.bind(ACTLBL_LOOK_UP_DOWN, &[
ActionSource::Mouse(MouseInput::Axis(MouseAxis::Y)).into_binding(),
ActionSource::Keyboard(KeyCode::Up).into_binding_modifier(-1.0),
ActionSource::Keyboard(KeyCode::Down).into_binding_modifier(1.0),
//ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickY)).into_binding(),
])
.bind(CommonActionLabel::LookRoll, &[
.bind(ACTLBL_LOOK_ROLL, &[
ActionSource::Keyboard(KeyCode::E).into_binding_modifier(-1.0),
ActionSource::Keyboard(KeyCode::Q).into_binding_modifier(1.0),
])
.finish()
);
).finish();
let world = game.world_mut();
world.add_resource(action_handler); */
world.add_resource(action_handler);
game.with_plugin(InputActionPlugin);
};
let script_test_plugin = |game: &mut Game| {
/* let script_test_plugin = |game: &mut Game| {
game.with_plugin(LuaScriptingPlugin);
let world = game.world_mut();
@ -306,13 +328,13 @@ async fn main() {
let scripts = ScriptList::new(vec![script]);
world.spawn((scripts,));
};
}; */
Game::initialize().await
.with_plugin(lyra_engine::DefaultPlugins)
.with_startup_system(setup_sys.into_system())
.with_plugin(action_handler_plugin)
.with_plugin(script_test_plugin)
//.with_plugin(script_test_plugin)
//.with_plugin(fps_plugin)
.with_plugin(jiggle_plugin)
.with_plugin(FreeFlyCameraPlugin)

View File

@ -10,11 +10,11 @@ pub struct MaterialSpecular {
}
impl MaterialSpecular {
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::Specular) -> Self {
let tex = value.texture.as_ref().map(|t| t.data_ref())
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Specular) -> Self {
let tex = value.texture.as_ref().and_then(|t| t.data_ref())
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
let color_tex = value.color_texture.as_ref().map(|t| t.data_ref())
let color_tex = value.color_texture.as_ref().and_then(|t| t.data_ref())
.map(|i| RenderTexture::from_image(device, queue, bg_layout, &i.image, None).unwrap());
Self {
@ -38,8 +38,8 @@ pub struct Material {
}
impl Material {
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::Material) -> Self {
let diffuse_texture = value.base_color_texture.as_ref().map(|t| t.data_ref())
pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc<wgpu::BindGroupLayout>, value: &lyra_resource::gltf::Material) -> Self {
let diffuse_texture = value.base_color_texture.as_ref().and_then(|t| t.data_ref())
.map(|i| RenderTexture::from_image(device, queue, bg_layout.clone(), &i.image, None).unwrap());
let specular = value.specular.as_ref().map(|s| MaterialSpecular::from_resource(device, queue, bg_layout.clone(), s));

View File

@ -5,10 +5,13 @@ use std::borrow::Cow;
use glam::Vec3;
use instant::Instant;
use itertools::izip;
use lyra_ecs::Entity;
use lyra_ecs::query::filter::{Has, Or};
use lyra_ecs::{Entity, Tick};
use lyra_ecs::query::{Entities, TickOf};
use lyra_ecs::World;
use tracing::{debug, warn};
use lyra_resource::gltf::GltfScene;
use tracing::{debug, debug_span, warn};
use uuid::Uuid;
use wgpu::{BindGroupLayout, Limits};
use wgpu::util::DeviceExt;
use winit::window::Window;
@ -16,7 +19,7 @@ use winit::window::Window;
use crate::math::Transform;
use crate::render::material::MaterialUniform;
use crate::render::render_buffer::BufferWrapperBuilder;
use crate::scene::{ModelComponent, CameraComponent};
use crate::scene::CameraComponent;
use super::camera::{RenderCamera, CameraUniform};
use super::desc_buf_lay::DescVertexBufferLayout;
@ -28,7 +31,10 @@ use super::transform_buffer_storage::TransformBuffers;
use super::vertex::Vertex;
use super::{render_pipeline::FullRenderPipeline, render_buffer::BufferStorage, render_job::RenderJob};
use lyra_resource::Mesh;
use lyra_resource::{gltf::Mesh, ResHandle};
type MeshHandle = ResHandle<Mesh>;
type SceneHandle = ResHandle<GltfScene>;
pub trait Renderer {
fn prepare(&mut self, main_world: &mut World);
@ -265,16 +271,19 @@ impl BasicRenderer {
s
}
fn update_mesh_buffers(&mut self, _entity: Entity, mesh: &Mesh) {
if let Some(buffers) = self.mesh_buffers.get_mut(&mesh.uuid) {
/// Checks if the mesh buffers in the GPU need to be updated.
fn check_mesh_buffers(&mut self, _entity: Entity, meshh: &ResHandle<Mesh>) {
let mesh_uuid = meshh.uuid();
if let (Some(mesh), Some(buffers)) = (meshh.data_ref(), self.mesh_buffers.get_mut(&mesh_uuid)) {
// check if the buffer sizes dont match. If they dont, completely remake the buffers
let vertices = mesh.position().unwrap();
if buffers.buffer_vertex.count() != vertices.len() {
debug!("Recreating buffers for mesh {}", mesh.uuid.to_string());
let (vert, idx) = self.create_vertex_index_buffers(mesh);
debug!("Recreating buffers for mesh {}", mesh_uuid.to_string());
let (vert, idx) = self.create_vertex_index_buffers(&mesh);
// have to re-get buffers because of borrow checker
let buffers = self.mesh_buffers.get_mut(&mesh.uuid).unwrap();
let buffers = self.mesh_buffers.get_mut(&mesh_uuid).unwrap();
buffers.buffer_indices = idx;
buffers.buffer_vertex = vert;
@ -292,8 +301,8 @@ impl BasicRenderer {
if let Some(index_buffer) = buffers.buffer_indices.as_ref() {
let aligned_indices = match mesh.indices.as_ref().unwrap() {
// U16 indices need to be aligned to u32, for wpgu, which are 4-bytes in size.
lyra_resource::MeshIndices::U16(v) => bytemuck::pod_align_to::<u16, u32>(v).1,
lyra_resource::MeshIndices::U32(v) => bytemuck::pod_align_to::<u32, u32>(v).1,
lyra_resource::gltf::MeshIndices::U16(v) => bytemuck::pod_align_to::<u16, u32>(v).1,
lyra_resource::gltf::MeshIndices::U32(v) => bytemuck::pod_align_to::<u32, u32>(v).1,
};
let index_buffer = index_buffer.1.buffer();
@ -327,8 +336,8 @@ impl BasicRenderer {
let indices = match mesh.indices.as_ref() {
Some(indices) => {
let (idx_type, len, contents) = match indices {
lyra_resource::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(v)),
lyra_resource::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(v)),
lyra_resource::gltf::MeshIndices::U16(v) => (wgpu::IndexFormat::Uint16, v.len(), bytemuck::cast_slice(v)),
lyra_resource::gltf::MeshIndices::U32(v) => (wgpu::IndexFormat::Uint32, v.len(), bytemuck::cast_slice(v)),
};
let index_buffer = self.device.create_buffer_init(
@ -354,7 +363,11 @@ impl BasicRenderer {
fn create_mesh_buffers(&mut self, mesh: &Mesh) -> MeshBufferStorage {
let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh);
let material = Material::from_resource(&self.device, &self.queue, self.bgl_texture.clone(), &mesh.material());
let material = mesh.material.as_ref()
.expect("Material resource not loaded yet")
.data_ref()
.unwrap();
let material = Material::from_resource(&self.device, &self.queue, self.bgl_texture.clone(), &material);
let uni = MaterialUniform::from(&material);
self.queue.write_buffer(&self.material_buffer.inner_buf, 0, bytemuck::bytes_of(&uni));
debug!("Wrote material to buffer");
@ -367,7 +380,7 @@ impl BasicRenderer {
}
/// Processes the mesh for the renderer, storing and creating buffers as needed. Returns true if a new mesh was processed.
fn process_mesh(&mut self, entity: Entity, transform: Transform, mesh: &Mesh) -> bool {
fn process_mesh(&mut self, entity: Entity, transform: Transform, mesh: &Mesh, mesh_uuid: Uuid) -> bool {
if self.transform_buffers.should_expand() {
self.transform_buffers.expand_buffers(&self.device);
}
@ -376,15 +389,48 @@ impl BasicRenderer {
entity, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) ));
#[allow(clippy::map_entry)]
if !self.mesh_buffers.contains_key(&mesh.uuid) {
if !self.mesh_buffers.contains_key(&mesh_uuid) {
// create the mesh's buffers
let buffers = self.create_mesh_buffers(mesh);
self.mesh_buffers.insert(mesh.uuid, buffers);
self.entity_meshes.insert(entity, mesh.uuid);
self.mesh_buffers.insert(mesh_uuid, buffers);
self.entity_meshes.insert(entity, mesh_uuid);
true
} else { false }
}
fn interpolate_transforms(&mut self, now: Instant, last_epoch: Tick, entity: Entity, transform: &Transform, transform_epoch: Tick) -> Transform {
let cached = match self.entity_last_transforms.get_mut(&entity) {
Some(last) if transform_epoch == last_epoch => {
last.from_transform = last.to_transform;
last.to_transform = *transform;
last.last_updated_at = Some(last.cached_at);
last.cached_at = now;
last.clone()
},
Some(last) => last.clone(),
None => {
let cached = CachedTransform {
last_updated_at: None,
cached_at: now,
from_transform: *transform,
to_transform: *transform,
};
self.entity_last_transforms.insert(entity, cached.clone());
cached
}
};
let fixed_time = match cached.last_updated_at {
Some(last_updated_at) => cached.cached_at - last_updated_at,
None => now - cached.cached_at
}.as_secs_f32();
let accumulator = (now - cached.cached_at).as_secs_f32();
let alpha = accumulator / fixed_time;
cached.from_transform.lerp(cached.to_transform, alpha)
}
}
impl Renderer for BasicRenderer {
@ -395,57 +441,71 @@ impl Renderer for BasicRenderer {
let now_inst = Instant::now();
for (entity, model, model_epoch, transform, transform_epoch) in main_world.view_iter::<(Entities, &ModelComponent, TickOf<ModelComponent>, &Transform, TickOf<Transform>)>() {
let view = main_world.filtered_view_iter::<(Entities, &Transform, TickOf<Transform>), Or<Has<MeshHandle>, Has<SceneHandle>>>();
for (entity, transform, transform_epoch) in view {
alive_entities.insert(entity);
let cached = match self.entity_last_transforms.get_mut(&entity) {
Some(last) if transform_epoch == last_epoch => {
last.from_transform = last.to_transform;
last.to_transform = *transform;
last.last_updated_at = Some(last.cached_at);
last.cached_at = now_inst;
let mesh_view = main_world.view_one::<(&MeshHandle, TickOf<MeshHandle>)>(entity);
if let Some((mesh_han, mesh_epoch)) = mesh_view.get() {
let interop_pos = self.interpolate_transforms(now_inst, last_epoch, entity, &transform, transform_epoch);
last.clone()
},
Some(last) => last.clone(),
None => {
let cached = CachedTransform {
last_updated_at: None,
cached_at: now_inst,
from_transform: *transform,
to_transform: *transform,
};
self.entity_last_transforms.insert(entity, cached.clone());
cached
if let Some(mesh) = mesh_han.data_ref() {
// if process mesh did not just create a new mesh, and the epoch
// shows that the scene has changed, verify that the mesh buffers
// dont need to be resent to the gpu.
if !self.process_mesh(entity, interop_pos, &*mesh, mesh_han.uuid())
&& mesh_epoch == last_epoch {
self.check_mesh_buffers(entity, &mesh_han);
}
let material = mesh.material.as_ref().unwrap()
.data_ref().unwrap();
let shader = material.shader_uuid.unwrap_or(0);
let job = RenderJob::new(entity, shader, mesh_han.uuid(), interop_pos);
self.render_jobs.push_back(job);
}
};
//debug!("Transform: {:?}, comp: {:?}", cached.to_transform.translation, transform.transform.translation);
}
let fixed_time = match cached.last_updated_at {
Some(last_updated_at) => cached.cached_at - last_updated_at,
None => now_inst - cached.cached_at
}.as_secs_f32();
let accumulator = (now_inst - cached.cached_at).as_secs_f32();
let alpha = accumulator / fixed_time;
let scene_view = main_world.view_one::<(&SceneHandle, TickOf<SceneHandle>)>(entity);
if let Some((scene_han, scene_epoch)) = scene_view.get() {
// TODO: Rendering scenes
let transform_val = cached.from_transform.lerp(cached.to_transform, alpha);
let scene_scope = debug_span!("scene", uuid = scene_han.uuid().to_string());
let _enter = scene_scope.enter();
let model = model.data_ref();
for mesh in model.meshes.iter() {
if !self.process_mesh(entity, transform_val, mesh) && model_epoch == last_epoch {
self.update_mesh_buffers(entity, mesh);
if let Some(scene) = scene_han.data_ref() {
let interop_pos = self.interpolate_transforms(now_inst, last_epoch, entity, &transform, transform_epoch);
let meshes = scene.collect_world_meshes();
for (mesh_han, mesh_pos) in meshes.into_iter() {
if let Some(mesh) = mesh_han.data_ref() {
let mesh_interp = interop_pos + mesh_pos;
let mesh_scope = debug_span!("mesh", uuid = mesh_han.uuid().to_string());
let _enter = mesh_scope.enter();
debug!("mesh at {:?}", mesh_interp.translation);
// if process mesh did not just create a new mesh, and the epoch
// shows that the scene has changed, verify that the mesh buffers
// dont need to be resent to the gpu.
if !self.process_mesh(entity, mesh_interp, &*mesh, mesh_han.uuid())
&& scene_epoch == last_epoch {
self.check_mesh_buffers(entity, &mesh_han);
debug!("updating mesh buffers");
}
let material = mesh.material.as_ref().unwrap()
.data_ref().unwrap();
let shader = material.shader_uuid.unwrap_or(0);
let job = RenderJob::new(entity, shader, mesh_han.uuid(), interop_pos);
self.render_jobs.push_back(job);
}
}
}
let shader = mesh.material().shader_uuid.unwrap_or(0);
let job = RenderJob::new(entity, shader, mesh.uuid, transform_val);
self.render_jobs.push_back(job);
}
}
/* for (entity, mesh, mesh_epoch, transform) in main_world.query::<(Entities, &MeshComponent, EpochOf<MeshComponent>, &TransformComponent)>().iter() {
debug!("TODO: Process MeshComponents"); // TODO: Process MeshComponents
} */
// collect dead entities
self.transform_buffers.tick();

View File

@ -5,25 +5,6 @@ use lyra_resource::{ResHandle, Texture};
use super::render_buffer::BindGroupPair;
/* #[derive(Clone)]
pub struct Texture {
texture_id: u32,
pub img: image::DynamicImage,
}
impl Texture {
pub fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
let img = image::load_from_memory(bytes)?;
Ok(Self {
texture_id: 0,
img,
})
}
} */
#[allow(dead_code)]
pub struct RenderTexture {
pub inner_texture: wgpu::Texture,
@ -153,8 +134,12 @@ impl RenderTexture {
})
}
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &Arc<ResHandle<Texture>>) {
let texture = &texture.data_ref().image;
/// Updates the texture on the gpu with the provided texture.
///
/// # Panics
/// Panics if `texture` is not loaded
pub fn update_texture(&mut self, _device: &wgpu::Device, queue: &wgpu::Queue, texture: &ResHandle<Texture>) {
let texture = &texture.data_ref().unwrap().image;
let rgba = texture.to_rgba8();
let dimensions = texture.dimensions();
let size = wgpu::Extent3d {

View File

@ -1,15 +1,37 @@
use lyra_ecs::Component;
use lyra_resource::Mesh;
use lyra_reflect::Reflect;
use lyra_resource::{gltf::Mesh, ResHandle};
#[derive(Clone, Component)]
#[derive(Clone, Component, Reflect)]
pub struct MeshComponent {
pub mesh: Mesh,
#[reflect(skip)]
pub mesh: ResHandle<Mesh>,
}
impl MeshComponent {
pub fn new(mesh: Mesh) -> Self {
impl From<ResHandle<Mesh>> for MeshComponent {
fn from(value: ResHandle<Mesh>) -> Self {
Self {
mesh,
mesh: value
}
}
}
impl std::ops::Deref for MeshComponent {
type Target = ResHandle<Mesh>;
fn deref(&self) -> &Self::Target {
&self.mesh
}
}
impl std::ops::DerefMut for MeshComponent {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.mesh
}
}
impl MeshComponent {
pub fn new(mesh: ResHandle<Mesh>) -> Self {
Self::from(mesh)
}
}

View File

@ -1,9 +1,6 @@
pub mod mesh;
pub use mesh::*;
pub mod model;
pub use model::*;
pub mod camera;
pub use camera::*;

View File

@ -1,41 +0,0 @@
use lyra_ecs::Component;
use lyra_reflect::Reflect;
use lyra_resource::ResHandle;
use crate::assets::Model;
#[derive(Clone, Component, Reflect)]
pub struct ModelComponent(#[reflect(skip)] pub ResHandle<Model>);
impl From<ResHandle<Model>> for ModelComponent {
fn from(value: ResHandle<Model>) -> Self {
ModelComponent(value)
}
}
/* impl From<ResHandle<Model> for ModelComponent {
} */
impl std::ops::Deref for ModelComponent {
type Target = ResHandle<Model>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for ModelComponent {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
/* impl ModelComponent {
pub fn new(model, material: Material) -> Self {
Self {
mesh,
material
}
}
} */