Multi-mesh objects + full scene tree

This commit is contained in:
mars 2022-05-30 00:22:49 -06:00
parent 3437d4d40f
commit 45cd80d239
5 changed files with 34 additions and 30 deletions

View File

@ -29,7 +29,7 @@ pub fn load_stl(path: std::path::PathBuf) -> model::Model {
objects: vec![model::Object {
name,
transform: Default::default(),
mesh: Some(model::Mesh { vertices, indices }),
meshes: vec![model::Mesh { vertices, indices }],
children: vec![],
}],
}
@ -88,14 +88,14 @@ impl<'a> GltfLoader<'a> {
let mut object = model::Object {
name: node.name().map(str::to_string),
transform,
mesh: None,
meshes: vec![],
children: vec![],
};
if let Some(mesh) = node.mesh() {
assert_eq!(1, mesh.primitives().len());
let primitive = mesh.primitives().next().unwrap();
object.mesh = Some(self.load_primitive_mesh(primitive));
for primitive in mesh.primitives() {
object.meshes.push(self.load_primitive_mesh(primitive));
}
}
for child in node.children() {

View File

@ -126,13 +126,15 @@ impl Application {
for object in self.objects.iter_mut() {
object.flush_dirty(|object| {
let transform = object.transform.to_mat4();
self.render_state
.world
.entry_mut(object.entity)
.unwrap()
.get_component_mut::<cyborg::scene::Transform>()
.unwrap()
.transform = transform;
for entity in object.entities.iter() {
self.render_state
.world
.entry_mut(*entity)
.unwrap()
.get_component_mut::<cyborg::scene::Transform>()
.unwrap()
.transform = transform;
}
});
}
}

View File

@ -6,7 +6,7 @@ pub struct Model {
pub struct Object {
pub name: Option<String>,
pub transform: Transform,
pub mesh: Option<Mesh>,
pub meshes: Vec<Mesh>,
pub children: Vec<Object>,
}

View File

@ -272,19 +272,19 @@ impl RenderState {
}
pub fn load_object(&mut self, object: &model::Object) -> ObjectWidget {
let mesh = object.mesh.as_ref().map(|mesh| cyborg::scene::Mesh {
mesh: self.load_mesh(mesh),
});
let transform = cyborg::scene::Transform {
transform: object.transform.to_mat4(),
};
let entity = if let Some(mesh) = mesh {
self.world.push((mesh, transform))
} else {
self.world.push((transform, ()))
};
let mut entities = Vec::new();
for mesh in object.meshes.iter() {
let mesh = cyborg::scene::Mesh {
mesh: self.load_mesh(mesh),
};
let entity = self.world.push((mesh, transform.clone()));
entities.push(entity);
}
let mut children = Vec::new();
for child in object.children.iter() {
@ -294,7 +294,7 @@ impl RenderState {
ObjectWidget {
name: object.name.clone(),
transform: object.transform.clone(),
entity,
entities,
children,
dirty: false,
children_dirty: false,

View File

@ -197,9 +197,11 @@ impl UserInterface {
egui::SidePanel::left("objects_panel")
.resizable(true)
.show(ctx, |ui| {
for (index, object) in objects.iter_mut().enumerate() {
object.ui(index, ui);
}
egui::ScrollArea::vertical().show(ui, |ui| {
for (index, object) in objects.iter_mut().enumerate() {
object.ui(index, ui);
}
});
});
egui::CentralPanel::default().show(ctx, |ui| {
@ -220,7 +222,7 @@ impl UserInterface {
let extensions: &[&str] = match kind {
ImportKind::Stl => &["stl"],
ImportKind::Gltf => &["gltf", "glb"],
ImportKind::Gltf => &["gltf", "glb", "vrm"],
};
let file_sender = self.file_sender.to_owned();
@ -319,7 +321,7 @@ impl egui::Widget for &mut ViewportWidget {
pub struct ObjectWidget {
pub name: Option<String>,
pub transform: crate::model::Transform,
pub entity: legion::Entity,
pub entities: Vec<legion::Entity>,
pub children: Vec<ObjectWidget>,
pub dirty: bool,
pub children_dirty: bool,
@ -335,7 +337,7 @@ impl ObjectWidget {
for (index, child) in self.children.iter_mut().enumerate() {
child.ui(index, ui);
if child.dirty {
if child.dirty || child.children_dirty {
self.children_dirty = true;
}
}
@ -412,7 +414,7 @@ impl ObjectWidget {
pub fn flush_dirty(&mut self, mut f: impl FnMut(&mut Self)) {
let mut stack = vec![self];
if let Some(parent) = stack.pop() {
while let Some(parent) = stack.pop() {
if parent.dirty {
parent.dirty = false;
f(parent);