Loading textures from gltf blob and gltf.bin's, fix loading multiple meshses in a single model
This commit is contained in:
parent
fd9f4bee2a
commit
7ae59c0415
|
@ -1294,6 +1294,7 @@ dependencies = [
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"uuid",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
@ -1552,7 +1553,7 @@ checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand",
|
"rand 0.4.6",
|
||||||
"rustc-serialize",
|
"rustc-serialize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1867,6 +1868,12 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-easy"
|
name = "proc-easy"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -1934,6 +1941,27 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1949,6 +1977,15 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "range-alloc"
|
name = "range-alloc"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -2483,11 +2520,12 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.4.1"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -36,3 +36,4 @@ aligned-vec = "0.5.0"
|
||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
stopwatch = "0.0.7"
|
stopwatch = "0.0.7"
|
||||||
petgraph = "0.6.4"
|
petgraph = "0.6.4"
|
||||||
|
uuid = { version = "1.5.0", features = ["v4", "fast-rng"] }
|
|
@ -1333,6 +1333,7 @@ dependencies = [
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"uuid",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
@ -1581,7 +1582,7 @@ checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand",
|
"rand 0.4.6",
|
||||||
"rustc-serialize",
|
"rustc-serialize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1877,6 +1878,12 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-easy"
|
name = "proc-easy"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -1944,6 +1951,27 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1959,6 +1987,15 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "range-alloc"
|
name = "range-alloc"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -2508,11 +2545,12 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.4.1"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,137 @@
|
||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v3.6.6",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"Cube"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"doubleSided":true,
|
||||||
|
"name":"Material",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0,
|
||||||
|
"roughnessFactor":0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Cube",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"TEXCOORD_0":1,
|
||||||
|
"NORMAL":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"uvgrid",
|
||||||
|
"uri":"uvgrid.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"max":[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-1,
|
||||||
|
-1,
|
||||||
|
-1
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":24,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":36,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":192,
|
||||||
|
"byteOffset":288,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":288,
|
||||||
|
"byteOffset":480,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":72,
|
||||||
|
"byteOffset":768,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9729,
|
||||||
|
"minFilter":9987
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":840,
|
||||||
|
"uri":"texture-sep.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
|
@ -75,35 +75,18 @@ async fn main() {
|
||||||
|
|
||||||
let mut resman = world.get_resource_mut::<ResourceManager>().unwrap();
|
let mut resman = world.get_resource_mut::<ResourceManager>().unwrap();
|
||||||
let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
let diffuse_texture = resman.request::<Texture>("assets/happy-tree.png").unwrap();
|
||||||
//let cube_model = resman.request::<Model>("assets/cube-embedded.gltf").unwrap();
|
let antique_camera_model = resman.request::<Model>("assets/AntiqueCamera.glb").unwrap();
|
||||||
let cube_model = resman.request::<Model>("assets/cube-texture-embedded.gltf").unwrap();
|
let cube_model = resman.request::<Model>("assets/texture-sep/texture-sep.gltf").unwrap();
|
||||||
drop(resman);
|
drop(resman);
|
||||||
|
|
||||||
/* world.spawn((MeshComponent::new(
|
/* world.spawn((
|
||||||
Mesh {
|
ModelComponent(cube_model.clone()),
|
||||||
vertices: VERTICES.to_vec(),
|
TransformComponent::from(Transform::from_xyz(3.0, 0.5, -2.2)),
|
||||||
indices: Some(INDICES.to_vec())
|
|
||||||
}, Material {
|
|
||||||
shader_id: 0,
|
|
||||||
texture: diffuse_texture.clone()
|
|
||||||
}),
|
|
||||||
TransformComponent::from(Transform::from_xyz(0.005, 0.0, -2.0)),
|
|
||||||
));
|
|
||||||
|
|
||||||
world.spawn((MeshComponent::new(
|
|
||||||
Mesh {
|
|
||||||
vertices: VERTICES.to_vec(),
|
|
||||||
indices: Some(INDICES.to_vec())
|
|
||||||
}, Material {
|
|
||||||
shader_id: 0,
|
|
||||||
texture: diffuse_texture
|
|
||||||
}),
|
|
||||||
TransformComponent::from(Transform::from_xyz(0.005, 0.7, -0.5)),
|
|
||||||
)); */
|
)); */
|
||||||
|
|
||||||
world.spawn((
|
world.spawn((
|
||||||
ModelComponent(cube_model),
|
ModelComponent(antique_camera_model),
|
||||||
TransformComponent::from(Transform::from_xyz(0.005, 0.5, -2.2)),
|
TransformComponent::from(Transform::from_xyz(0.0, -5.0, -10.0)),
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut camera = CameraComponent::new_3d();
|
let mut camera = CameraComponent::new_3d();
|
||||||
|
@ -115,7 +98,6 @@ async fn main() {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
//world.insert_resource(fps_counter::FPSCounter::new());
|
|
||||||
let fps_system = |world: &mut World| -> anyhow::Result<()> {
|
let fps_system = |world: &mut World| -> anyhow::Result<()> {
|
||||||
let mut counter: RefMut<fps_counter::FPSCounter> = world.get_resource_mut().unwrap();
|
let mut counter: RefMut<fps_counter::FPSCounter> = world.get_resource_mut().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,17 @@ impl From<ModelLoaderError> for LoaderError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct GltfLoadContext<'a> {
|
||||||
|
pub resource_manager: &'a mut ResourceManager,
|
||||||
|
pub gltf: &'a gltf::Gltf,
|
||||||
|
/// Path to the gltf
|
||||||
|
pub gltf_path: &'a str,
|
||||||
|
/// The path to the directory that the gltf is contained in.
|
||||||
|
pub gltf_parent_path: &'a str,
|
||||||
|
/// List of buffers in the gltf
|
||||||
|
pub buffers: &'a Vec<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ModelLoader;
|
pub struct ModelLoader;
|
||||||
|
|
||||||
|
@ -59,7 +70,10 @@ impl ModelLoader {
|
||||||
|
|
||||||
// read the positions
|
// read the positions
|
||||||
if let Some(pos) = reader.read_positions() {
|
if let Some(pos) = reader.read_positions() {
|
||||||
debug!("Mesh mode is {:?}", prim.mode());
|
if prim.mode() != gltf::mesh::Mode::Triangles {
|
||||||
|
todo!("Load position primitives that aren't triangles"); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
let pos: Vec<glam::Vec3> = pos.map(|t| t.into()).collect();
|
let pos: Vec<glam::Vec3> = pos.map(|t| t.into()).collect();
|
||||||
new_mesh.add_attribute(MeshVertexAttribute::Position, VertexAttributeData::Vec3(pos));
|
new_mesh.add_attribute(MeshVertexAttribute::Position, VertexAttributeData::Vec3(pos));
|
||||||
}
|
}
|
||||||
|
@ -114,7 +128,7 @@ impl ModelLoader {
|
||||||
impl ResourceLoader for ModelLoader {
|
impl ResourceLoader for ModelLoader {
|
||||||
fn extensions(&self) -> &[&str] {
|
fn extensions(&self) -> &[&str] {
|
||||||
&[
|
&[
|
||||||
"gltf"
|
"gltf", "glb"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,11 +146,27 @@ impl ResourceLoader for ModelLoader {
|
||||||
parent_path.pop();
|
parent_path.pop();
|
||||||
let parent_path = parent_path.display().to_string();
|
let parent_path = parent_path.display().to_string();
|
||||||
|
|
||||||
|
/* let (document, buffers, images) = gltf::import(&path)?;
|
||||||
|
let buffers: Vec<Vec<u8>> = buffers.into_iter().map(|b| b.0).collect();
|
||||||
|
|
||||||
|
let scene = document.scenes().next().unwrap();
|
||||||
|
|
||||||
|
let materials: Vec<Material> = document.materials()
|
||||||
|
.map(|mat| Material::from_gltf(resource_manager, &parent_path, mat)).collect();
|
||||||
|
|
||||||
|
let meshes: Vec<Mesh> = scene.nodes()
|
||||||
|
.map(|node| self.process_node(&buffers, &materials, node))
|
||||||
|
.flatten().collect(); */
|
||||||
|
|
||||||
let gltf = gltf::Gltf::open(path)?;
|
let gltf = gltf::Gltf::open(path)?;
|
||||||
|
|
||||||
|
let mut use_bin = false;
|
||||||
let buffers: Vec<Vec<u8>> = gltf.buffers().map(|b| match b.source() {
|
let buffers: Vec<Vec<u8>> = gltf.buffers().map(|b| match b.source() {
|
||||||
gltf::buffer::Source::Bin => gltf.blob.as_deref().map(|v| v.to_vec())
|
gltf::buffer::Source::Bin => {
|
||||||
.ok_or(ModelLoaderError::MissingBin(path.to_string())),
|
use_bin = true;
|
||||||
|
gltf.blob.as_deref().map(|v| v.to_vec())
|
||||||
|
.ok_or(ModelLoaderError::MissingBin(path.to_string()))
|
||||||
|
},
|
||||||
gltf::buffer::Source::Uri(uri) => util::gltf_read_buffer_uri(&parent_path, uri)
|
gltf::buffer::Source::Uri(uri) => util::gltf_read_buffer_uri(&parent_path, uri)
|
||||||
.map_err(|e| ModelLoaderError::UriDecodingError(e)),
|
.map_err(|e| ModelLoaderError::UriDecodingError(e)),
|
||||||
}).flatten().collect();
|
}).flatten().collect();
|
||||||
|
@ -144,13 +174,21 @@ impl ResourceLoader for ModelLoader {
|
||||||
// TODO: Read in multiple scenes
|
// TODO: Read in multiple scenes
|
||||||
let scene = gltf.scenes().next().unwrap();
|
let scene = gltf.scenes().next().unwrap();
|
||||||
|
|
||||||
// Load the materials
|
let mut context = GltfLoadContext {
|
||||||
|
resource_manager,
|
||||||
|
gltf: &gltf,
|
||||||
|
gltf_path: path,
|
||||||
|
gltf_parent_path: &parent_path,
|
||||||
|
buffers: &buffers,
|
||||||
|
};
|
||||||
|
|
||||||
let materials: Vec<Material> = gltf.materials()
|
let materials: Vec<Material> = gltf.materials()
|
||||||
.map(|mat| Material::from_gltf(resource_manager, &parent_path, mat)).collect();
|
.map(|mat| Material::from_gltf(&mut context, mat)).collect();
|
||||||
|
|
||||||
let meshes: Vec<Mesh> = scene.nodes()
|
let meshes: Vec<Mesh> = scene.nodes()
|
||||||
.map(|node| self.process_node(&buffers, &materials, node))
|
.map(|node| self.process_node(&buffers, &materials, node))
|
||||||
.flatten().collect();
|
.flatten().collect();
|
||||||
|
debug!("Loaded {} meshes, and {} materials from '{}'", meshes.len(), materials.len(), path);
|
||||||
|
|
||||||
Ok(Arc::new(Resource::with_data(path, Model::new(meshes))))
|
Ok(Arc::new(Resource::with_data(path, Model::new(meshes))))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{fs::File, io::{BufReader, Read}, collections::hash_map::DefaultHasher, hash::{Hash, Hasher}};
|
use std::{fs::File, io::{BufReader, Read}, collections::hash_map::DefaultHasher, hash::{Hash, Hasher}};
|
||||||
|
|
||||||
use crate::{Texture, ResHandle, ResourceManager, util};
|
use crate::{Texture, ResHandle, ResourceManager, util, loader::model::GltfLoadContext};
|
||||||
|
|
||||||
/// PBR metallic roughness
|
/// PBR metallic roughness
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
|
@ -159,10 +159,11 @@ impl Material {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_source(resource_manager: &mut ResourceManager, gltf_rel_path: &str, src: gltf::image::Source) -> Result<Vec<u8>, util::UriReadError> {
|
fn read_source(context: &mut GltfLoadContext, src: gltf::image::Source) -> Result<Vec<u8>, util::UriReadError> {
|
||||||
|
let gltf_rel_path = context.gltf_parent_path;
|
||||||
// TODO: Don't copy sources
|
// TODO: Don't copy sources
|
||||||
match src {
|
match src {
|
||||||
gltf::image::Source::View { view, mime_type } => {
|
gltf::image::Source::View { view, mime_type: _ } => {
|
||||||
let buf = view.buffer();
|
let buf = view.buffer();
|
||||||
let src = buf.source();
|
let src = buf.source();
|
||||||
|
|
||||||
|
@ -170,7 +171,12 @@ impl Material {
|
||||||
let len = view.length();
|
let len = view.length();
|
||||||
|
|
||||||
match src {
|
match src {
|
||||||
gltf::buffer::Source::Bin => todo!("Read material source from gltf Bin"),
|
gltf::buffer::Source::Bin => {
|
||||||
|
let mut b = context.gltf.blob.clone().unwrap();
|
||||||
|
b.drain(0..offset);
|
||||||
|
b.truncate(len);
|
||||||
|
Ok(b)
|
||||||
|
},
|
||||||
gltf::buffer::Source::Uri(uri) => {
|
gltf::buffer::Source::Uri(uri) => {
|
||||||
util::gltf_read_buffer_uri(gltf_rel_path, uri)
|
util::gltf_read_buffer_uri(gltf_rel_path, uri)
|
||||||
.map(|mut buf| {
|
.map(|mut buf| {
|
||||||
|
@ -181,23 +187,23 @@ impl Material {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gltf::image::Source::Uri { uri, mime_type } => {
|
gltf::image::Source::Uri { uri, mime_type: _ } => {
|
||||||
util::gltf_read_buffer_uri(gltf_rel_path, uri)
|
util::gltf_read_buffer_uri(gltf_rel_path, uri)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_texture(resource_manager: &mut ResourceManager, gltf_rel_path: &str, texture_info: gltf::texture::Info<'_>) -> ResHandle<Texture> {
|
fn load_texture(context: &mut GltfLoadContext, texture_info: gltf::texture::Info<'_>) -> ResHandle<Texture> {
|
||||||
// TODO: texture_info.tex_coord()
|
// TODO: texture_info.tex_coord()
|
||||||
let tex = texture_info.texture();
|
let tex = texture_info.texture();
|
||||||
let img = tex.source();
|
let img = tex.source();
|
||||||
let src = img.source();
|
let src = img.source();
|
||||||
|
|
||||||
let buf = Material::read_source(resource_manager, gltf_rel_path, src).unwrap();
|
let buf = Material::read_source(context, src).unwrap();
|
||||||
let buflen = buf.len();
|
let buflen = buf.len();
|
||||||
let mime_type = infer::get(&buf).expect("Failed to get file type").mime_type();
|
let mime_type = infer::get(&buf).expect("Failed to get file type").mime_type();
|
||||||
|
|
||||||
resource_manager.load_bytes::<Texture>(&uuid::Uuid::new_v4().to_string(), mime_type,
|
context.resource_manager.load_bytes::<Texture>(&uuid::Uuid::new_v4().to_string(), mime_type,
|
||||||
buf, 0, buflen).unwrap()
|
buf, 0, buflen).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,21 +211,17 @@ impl Material {
|
||||||
///
|
///
|
||||||
/// `gltf_rel_path`: The relative path of the gltf file,
|
/// `gltf_rel_path`: The relative path of the gltf file,
|
||||||
/// e.g. gltf model path is "resource/models/player.gltf", the relative path would be "resource/models/"
|
/// e.g. gltf model path is "resource/models/player.gltf", the relative path would be "resource/models/"
|
||||||
pub fn from_gltf(resource_manager: &mut ResourceManager, gltf_rel_path: &str, gltf_mat: gltf::Material) -> Self {
|
pub(crate) fn from_gltf(context: &mut GltfLoadContext, gltf_mat: gltf::Material) -> Self {
|
||||||
let pbr_rough = gltf_mat.pbr_metallic_roughness();
|
let pbr_rough = gltf_mat.pbr_metallic_roughness();
|
||||||
let base_color = pbr_rough.base_color_factor().into();
|
let base_color = pbr_rough.base_color_factor().into();
|
||||||
let metallic = pbr_rough.metallic_factor();
|
let metallic = pbr_rough.metallic_factor();
|
||||||
let roughness = pbr_rough.roughness_factor();
|
let roughness = pbr_rough.roughness_factor();
|
||||||
|
|
||||||
let base_color_texture = pbr_rough.base_color_texture()
|
let base_color_texture = pbr_rough.base_color_texture()
|
||||||
.map(|info| Material::load_texture(resource_manager, gltf_rel_path, info));
|
.map(|info| Material::load_texture(context, info));
|
||||||
|
|
||||||
let metallic_roughness_texture = pbr_rough.metallic_roughness_texture()
|
let metallic_roughness_texture = pbr_rough.metallic_roughness_texture()
|
||||||
.map(|info| Material::load_texture(resource_manager, gltf_rel_path, info));
|
.map(|info| Material::load_texture(context, info));
|
||||||
|
|
||||||
/* let base_color_texture = if let Some(base_tex_info) = pbr_rough.base_color_texture() {
|
|
||||||
Some(Material::load_texture(resource_manager, gltf_rel_path, base_tex_info))
|
|
||||||
} else { None }; */
|
|
||||||
|
|
||||||
Material {
|
Material {
|
||||||
name: gltf_mat.name()
|
name: gltf_mat.name()
|
||||||
|
|
|
@ -77,13 +77,25 @@ pub enum MeshVertexAttribute {
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, edict::Component)]
|
#[derive(Clone, edict::Component)]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
|
pub uuid: uuid::Uuid,
|
||||||
pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>,
|
pub attributes: HashMap<MeshVertexAttribute, VertexAttributeData>,
|
||||||
pub indices: Option<MeshIndices>,
|
pub indices: Option<MeshIndices>,
|
||||||
material: Option<Material>,
|
material: Option<Material>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Mesh {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
uuid: uuid::Uuid::new_v4(),
|
||||||
|
attributes: Default::default(),
|
||||||
|
indices: Default::default(),
|
||||||
|
material: Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn add_attribute(&mut self, attribute: MeshVertexAttribute, data: VertexAttributeData) {
|
pub fn add_attribute(&mut self, attribute: MeshVertexAttribute, data: VertexAttributeData) {
|
||||||
self.attributes.insert(attribute, data);
|
self.attributes.insert(attribute, data);
|
||||||
|
|
|
@ -19,20 +19,23 @@ pub enum UriReadError {
|
||||||
///
|
///
|
||||||
/// * `containing_path`: The path of the containing folder of the buffers "parent",
|
/// * `containing_path`: The path of the containing folder of the buffers "parent",
|
||||||
/// the parent being where this buffer is defined in,
|
/// the parent being where this buffer is defined in,
|
||||||
/// i.e. parent="resources/models/player.gltf", containing="reousrce/models"
|
/// i.e. parent="resources/models/player.gltf", containing="resource/models"
|
||||||
pub(crate) fn gltf_read_buffer_uri(containing_path: &str, uri: &str) -> Result<Vec<u8>, UriReadError> {
|
pub(crate) fn gltf_read_buffer_uri(containing_path: &str, uri: &str) -> Result<Vec<u8>, UriReadError> {
|
||||||
let uri = uri.strip_prefix("data").ok_or(UriReadError::None)?;
|
if let Some((mime, data)) = uri.strip_prefix("data")
|
||||||
let (mime, data) = uri.split_once(",").ok_or(UriReadError::None)?;
|
.and_then(|uri| uri.split_once(",")) {
|
||||||
|
let (_mime, is_base64) = match mime.strip_suffix(";base64") {
|
||||||
|
Some(mime) => (mime, true),
|
||||||
|
None => (mime, false),
|
||||||
|
};
|
||||||
|
|
||||||
let (_mime, is_base64) = match mime.strip_suffix(";base64") {
|
if is_base64 {
|
||||||
Some(mime) => (mime, true),
|
base64::engine::general_purpose::STANDARD.decode(data)
|
||||||
None => (mime, false),
|
.map_err(|e| UriReadError::Base64Decode(e))
|
||||||
};
|
} else {
|
||||||
|
Ok(data.as_bytes().to_vec())
|
||||||
if is_base64 {
|
}
|
||||||
base64::engine::general_purpose::STANDARD.decode(data).map_err(|e| UriReadError::Base64Decode(e))
|
|
||||||
} else {
|
} else {
|
||||||
let full_path = format!("{containing_path}/{data}");
|
let full_path = format!("{containing_path}/{uri}");
|
||||||
std::fs::read(&full_path).map_err(|e| UriReadError::IoError(e))
|
std::fs::read(&full_path).map_err(|e| UriReadError::IoError(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1 @@
|
||||||
|
nightly
|
|
@ -297,7 +297,7 @@ impl Game {
|
||||||
.with(fmt::layer().with_writer(stdout_layer))
|
.with(fmt::layer().with_writer(stdout_layer))
|
||||||
.with(filter::Targets::new()
|
.with(filter::Targets::new()
|
||||||
.with_target("lyra_engine", Level::TRACE)
|
.with_target("lyra_engine", Level::TRACE)
|
||||||
.with_target("wgpu_core", Level::INFO)
|
.with_target("wgpu_core", Level::WARN)
|
||||||
.with_default(Level::DEBUG))
|
.with_default(Level::DEBUG))
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![feature(hash_extract_if)]
|
||||||
|
|
||||||
pub mod game;
|
pub mod game;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod input_event;
|
pub mod input_event;
|
||||||
|
|
|
@ -2,48 +2,23 @@ use edict::EntityId;
|
||||||
|
|
||||||
use crate::math::Transform;
|
use crate::math::Transform;
|
||||||
|
|
||||||
//use super::mesh::Mesh;
|
|
||||||
use lyra_resource::Mesh;
|
|
||||||
|
|
||||||
pub struct RenderJob {
|
pub struct RenderJob {
|
||||||
mesh: Mesh,
|
pub entity: EntityId,
|
||||||
entity: EntityId,
|
pub shader_id: u64,
|
||||||
|
pub mesh_buffer_id: uuid::Uuid,
|
||||||
|
|
||||||
transform: Transform,
|
pub transform: Transform,
|
||||||
last_transform: Option<Transform>, // TODO: render interpolation
|
pub last_transform: Option<Transform>, // TODO: render interpolation
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderJob {
|
impl RenderJob {
|
||||||
pub fn new(mesh: Mesh, entity: EntityId, transform: Transform, last_transform: Option<Transform>) -> Self {
|
pub fn new(entity: EntityId, shader_id: u64, mesh_buffer_id: uuid::Uuid, transform: Transform, last_transform: Option<Transform>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mesh,
|
|
||||||
entity,
|
entity,
|
||||||
|
shader_id,
|
||||||
|
mesh_buffer_id,
|
||||||
transform,
|
transform,
|
||||||
last_transform,
|
last_transform,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mesh(&self)-> &Mesh {
|
|
||||||
&self.mesh
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn entity(&self)-> EntityId {
|
|
||||||
self.entity
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transform(&self)-> &Transform {
|
|
||||||
&self.transform
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_transform(&mut self, transform: Transform){
|
|
||||||
self.transform = transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last_transform(&self)-> Option<&Transform> {
|
|
||||||
self.last_transform.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_last_transform(&mut self, last_transform: Transform){
|
|
||||||
self.last_transform = Some(last_transform);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ use crate::ecs::components::camera::CameraComponent;
|
||||||
use crate::ecs::components::mesh::MeshComponent;
|
use crate::ecs::components::mesh::MeshComponent;
|
||||||
use crate::ecs::components::model::ModelComponent;
|
use crate::ecs::components::model::ModelComponent;
|
||||||
use crate::ecs::components::transform::TransformComponent;
|
use crate::ecs::components::transform::TransformComponent;
|
||||||
|
use crate::math::Transform;
|
||||||
|
|
||||||
use super::camera::RenderCamera;
|
use super::camera::RenderCamera;
|
||||||
use super::desc_buf_lay::DescVertexBufferLayout;
|
use super::desc_buf_lay::DescVertexBufferLayout;
|
||||||
|
@ -68,13 +69,15 @@ struct TransformBuffers {
|
||||||
|
|
||||||
impl TransformBuffers {
|
impl TransformBuffers {
|
||||||
/// Update an entity's buffer with the new transform. Will panic if the entity isn't stored
|
/// Update an entity's buffer with the new transform. Will panic if the entity isn't stored
|
||||||
fn update_entity(&mut self, queue: &wgpu::Queue, limits: &Limits, entity: EntityId, transform: glam::Mat4) {
|
fn update_entity(&mut self, queue: &wgpu::Queue, limits: &Limits, entity: EntityId, transform: glam::Mat4) -> TransformBufferIndices {
|
||||||
let indices = self.not_updated.remove(&entity)
|
let indices = self.not_updated.remove(&entity)
|
||||||
|
.or_else(|| self.just_updated.remove(&entity))
|
||||||
.expect("Use 'insert_entity' for new entities");
|
.expect("Use 'insert_entity' for new entities");
|
||||||
self.just_updated.insert(entity, indices);
|
self.just_updated.insert(entity, indices);
|
||||||
|
|
||||||
let (_, buffer, _) = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
|
let (_, buffer, _) = self.buffer_bindgroups.get(indices.buffer_index).unwrap();
|
||||||
queue.write_buffer(buffer, indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as u64, bytemuck::bytes_of(&transform));
|
queue.write_buffer(buffer, indices.transform_index as u64 * limits.min_uniform_buffer_offset_alignment as u64, bytemuck::bytes_of(&transform));
|
||||||
|
indices
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a new entity into the buffer, returns where it was stored.
|
/// Insert a new entity into the buffer, returns where it was stored.
|
||||||
|
@ -104,6 +107,22 @@ impl TransformBuffers {
|
||||||
indices
|
indices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update or insert an entities transform
|
||||||
|
fn update_or_insert<TFn>(&mut self, queue: &wgpu::Queue, limits: &Limits, entity: EntityId, transform_fn: TFn) -> TransformBufferIndices
|
||||||
|
where TFn: Fn() -> glam::Mat4
|
||||||
|
{
|
||||||
|
if self.contains(entity) {
|
||||||
|
self.update_entity(queue, limits, entity, transform_fn())
|
||||||
|
} else {
|
||||||
|
self.insert_entity(queue, limits, entity, transform_fn())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the entity's transform is stored (does not mean its up-to-date).
|
||||||
|
fn contains(&self, entity: EntityId) -> bool {
|
||||||
|
self.not_updated.contains_key(&entity) || self.just_updated.contains_key(&entity)
|
||||||
|
}
|
||||||
|
|
||||||
/// Collect the dead entities, mark entities and not updated for next updates.
|
/// Collect the dead entities, mark entities and not updated for next updates.
|
||||||
fn tick(&mut self) {
|
fn tick(&mut self) {
|
||||||
// take the dead entities, these were ones that were not updated this tick
|
// take the dead entities, these were ones that were not updated this tick
|
||||||
|
@ -111,7 +130,6 @@ impl TransformBuffers {
|
||||||
.map(|t| t.clone()).collect();
|
.map(|t| t.clone()).collect();
|
||||||
self.dead_indices = dead;
|
self.dead_indices = dead;
|
||||||
|
|
||||||
// swap just_updated into not_updated
|
|
||||||
self.not_updated = self.just_updated.clone();
|
self.not_updated = self.just_updated.clone();
|
||||||
self.just_updated.clear();
|
self.just_updated.clear();
|
||||||
}
|
}
|
||||||
|
@ -143,7 +161,8 @@ pub struct BasicRenderer {
|
||||||
pub render_pipelines: HashMap<u64, Arc<FullRenderPipeline>>,
|
pub render_pipelines: HashMap<u64, Arc<FullRenderPipeline>>,
|
||||||
pub render_jobs: VecDeque<RenderJob>,
|
pub render_jobs: VecDeque<RenderJob>,
|
||||||
|
|
||||||
buffer_storage: HashMap<EntityId, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
mesh_buffers: HashMap<uuid::Uuid, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||||
|
entity_meshes: HashMap<EntityId, uuid::Uuid>,
|
||||||
|
|
||||||
transform_buffers: TransformBuffers,
|
transform_buffers: TransformBuffers,
|
||||||
transform_bind_group_layout: BindGroupLayout,
|
transform_bind_group_layout: BindGroupLayout,
|
||||||
|
@ -205,7 +224,7 @@ impl BasicRenderer {
|
||||||
false => surface_caps.present_modes[0]
|
false => surface_caps.present_modes[0]
|
||||||
}; */
|
}; */
|
||||||
|
|
||||||
println!("present mode: {:?}", present_mode);
|
debug!("present mode: {:?}", present_mode);
|
||||||
|
|
||||||
let surface_format = surface_caps.formats.iter()
|
let surface_format = surface_caps.formats.iter()
|
||||||
.copied()
|
.copied()
|
||||||
|
@ -380,7 +399,8 @@ impl BasicRenderer {
|
||||||
},
|
},
|
||||||
render_pipelines: HashMap::new(),
|
render_pipelines: HashMap::new(),
|
||||||
render_jobs: VecDeque::new(),
|
render_jobs: VecDeque::new(),
|
||||||
buffer_storage: HashMap::new(),
|
mesh_buffers: HashMap::new(),
|
||||||
|
entity_meshes: HashMap::new(),
|
||||||
|
|
||||||
render_limits,
|
render_limits,
|
||||||
transform_buffers,
|
transform_buffers,
|
||||||
|
@ -405,17 +425,16 @@ impl BasicRenderer {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) {
|
fn update_mesh_buffers(&mut self, _entity: EntityId, mesh: &Mesh) {
|
||||||
if let Some(buffers) = self.buffer_storage.get_mut(&entity) {
|
if let Some(buffers) = self.mesh_buffers.get_mut(&mesh.uuid) {
|
||||||
// check if the buffer sizes dont match. If they dont, completely remake the buffers
|
// check if the buffer sizes dont match. If they dont, completely remake the buffers
|
||||||
let vertices = mesh.position().unwrap();
|
let vertices = mesh.position().unwrap();
|
||||||
if buffers.buffer_vertex.count() != vertices.len() {
|
if buffers.buffer_vertex.count() != vertices.len() {
|
||||||
drop(buffers);
|
debug!("Recreating buffers for mesh {}", mesh.uuid.to_string());
|
||||||
debug!("Recreating buffers for mesh");
|
|
||||||
let (vert, idx) = self.create_vertex_index_buffers(mesh);
|
let (vert, idx) = self.create_vertex_index_buffers(mesh);
|
||||||
|
|
||||||
// have to re-get buffers because of borrow checker
|
// have to re-get buffers because of borrow checker
|
||||||
let buffers = self.buffer_storage.get_mut(&entity).unwrap();
|
let buffers = self.mesh_buffers.get_mut(&mesh.uuid).unwrap();
|
||||||
buffers.buffer_indices = idx;
|
buffers.buffer_indices = idx;
|
||||||
buffers.buffer_vertex = vert;
|
buffers.buffer_vertex = vert;
|
||||||
|
|
||||||
|
@ -448,13 +467,11 @@ impl BasicRenderer {
|
||||||
let tex_coords: Vec<glam::Vec2> = mesh.tex_coords().cloned()
|
let tex_coords: Vec<glam::Vec2> = mesh.tex_coords().cloned()
|
||||||
.unwrap_or_else(|| vec![glam::Vec2::new(0.0, 0.0); positions.len()]);
|
.unwrap_or_else(|| vec![glam::Vec2::new(0.0, 0.0); positions.len()]);
|
||||||
|
|
||||||
debug!("Pos count: {}, tex coords count: {}", positions.len(), tex_coords.len());
|
|
||||||
assert!(positions.len() == tex_coords.len());
|
assert!(positions.len() == tex_coords.len());
|
||||||
|
|
||||||
let vertex_inputs: Vec<Vertex> = std::iter::zip(positions, tex_coords.into_iter())
|
let vertex_inputs: Vec<Vertex> = std::iter::zip(positions, tex_coords.into_iter())
|
||||||
.map(|(v, t)| Vertex::new(v.clone(), t))
|
.map(|(v, t)| Vertex::new(v.clone(), t))
|
||||||
.collect();
|
.collect();
|
||||||
println!("Vertex inputs: {:?}", vertex_inputs.as_slice());
|
|
||||||
|
|
||||||
let vertex_buffer = self.device.create_buffer_init(
|
let vertex_buffer = self.device.create_buffer_init(
|
||||||
&wgpu::util::BufferInitDescriptor {
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
@ -565,6 +582,28 @@ impl BasicRenderer {
|
||||||
buffers.next_indices = indices;
|
buffers.next_indices = indices;
|
||||||
indices
|
indices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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: EntityId, transform: Transform, mesh: &Mesh) -> bool {
|
||||||
|
let indices = self.transform_buffers.update_or_insert(&self.queue, &self.render_limits,
|
||||||
|
entity, || transform.calculate_mat4());
|
||||||
|
|
||||||
|
if self.mesh_buffers.contains_key(&mesh.uuid) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
// check if the transform buffers need to be expanded
|
||||||
|
if self.transform_buffers.should_expand() {
|
||||||
|
self.expand_transform_buffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the mesh's buffers
|
||||||
|
let buffers = self.create_mesh_buffers(mesh, indices);
|
||||||
|
self.mesh_buffers.insert(mesh.uuid, buffers);
|
||||||
|
self.entity_meshes.insert(entity, mesh.uuid);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer for BasicRenderer {
|
impl Renderer for BasicRenderer {
|
||||||
|
@ -574,37 +613,20 @@ impl Renderer for BasicRenderer {
|
||||||
let mut alive_entities = HashSet::new();
|
let mut alive_entities = HashSet::new();
|
||||||
|
|
||||||
for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &ModelComponent, EpochOf<ModelComponent>, &TransformComponent)>().iter() {
|
for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &ModelComponent, EpochOf<ModelComponent>, &TransformComponent)>().iter() {
|
||||||
let model = model.data.as_ref().unwrap().as_ref();
|
|
||||||
let model_mesh = model.meshes.first().unwrap();
|
|
||||||
|
|
||||||
// Create the render job and push it to the queue
|
|
||||||
let job = RenderJob::new(model_mesh.clone(), entity, transform.transform, None);
|
|
||||||
self.render_jobs.push_back(job);
|
|
||||||
|
|
||||||
alive_entities.insert(entity);
|
alive_entities.insert(entity);
|
||||||
|
|
||||||
if self.buffer_storage.get(&entity).is_none() {
|
let model = model.data.as_ref().unwrap().as_ref();
|
||||||
// check if the transform buffers need to be expanded
|
|
||||||
if self.transform_buffers.should_expand() {
|
for mesh in model.meshes.iter() {
|
||||||
self.expand_transform_buffers();
|
if !self.process_mesh(entity, transform.transform, mesh) {
|
||||||
|
if model_epoch == last_epoch {
|
||||||
|
self.update_mesh_buffers(entity, mesh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert transform into buffers
|
let shader = mesh.material().shader_uuid.unwrap_or(0);
|
||||||
let indices = self.transform_buffers.insert_entity(&self.queue, &self.render_limits,
|
let job = RenderJob::new(entity, shader, mesh.uuid, transform.transform, None);
|
||||||
entity, transform.transform.calculate_mat4());
|
self.render_jobs.push_back(job);
|
||||||
|
|
||||||
// create the mesh's buffers
|
|
||||||
let buffers = self.create_mesh_buffers(model_mesh, indices);
|
|
||||||
self.buffer_storage.insert(entity, buffers);
|
|
||||||
} else {
|
|
||||||
// update entity transforms
|
|
||||||
self.transform_buffers.update_entity(&self.queue, &self.render_limits,
|
|
||||||
entity, transform.transform.calculate_mat4());
|
|
||||||
|
|
||||||
// if the model was updated, update its buffers
|
|
||||||
if model_epoch == last_epoch {
|
|
||||||
self.update_mesh_buffers(entity, model_mesh);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,8 +639,12 @@ impl Renderer for BasicRenderer {
|
||||||
|
|
||||||
// when buffer storage length does not match the amount of iterated entities,
|
// when buffer storage length does not match the amount of iterated entities,
|
||||||
// remove all dead entities, and their buffers, if they weren't iterated over
|
// remove all dead entities, and their buffers, if they weren't iterated over
|
||||||
if self.buffer_storage.len() != alive_entities.len() {
|
if self.mesh_buffers.len() != alive_entities.len() {
|
||||||
self.buffer_storage.retain(|e, _| alive_entities.contains(e));
|
let removed_entities: Vec<uuid::Uuid> = self.entity_meshes
|
||||||
|
.extract_if(|e, _| !alive_entities.contains(e))
|
||||||
|
.map(|(_, v)| v)
|
||||||
|
.collect();
|
||||||
|
self.mesh_buffers.retain(|u, _| !removed_entities.contains(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(camera) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() {
|
if let Some(camera) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() {
|
||||||
|
@ -663,13 +689,12 @@ impl Renderer for BasicRenderer {
|
||||||
|
|
||||||
// Pop off jobs from the queue as they're being processed
|
// Pop off jobs from the queue as they're being processed
|
||||||
while let Some(job) = self.render_jobs.pop_front() {
|
while let Some(job) = self.render_jobs.pop_front() {
|
||||||
if let Some(pipeline) = self.render_pipelines.get(&job.mesh().material().shader_uuid.unwrap_or(0)) {
|
if let Some(pipeline) = self.render_pipelines.get(&job.shader_id) {
|
||||||
// specify to use this pipeline
|
// specify to use this pipeline
|
||||||
render_pass.set_pipeline(pipeline.get_wgpu_pipeline());
|
render_pass.set_pipeline(pipeline.get_wgpu_pipeline());
|
||||||
|
|
||||||
// get the mesh (containing vertices) and the buffers from storage
|
// get the mesh (containing vertices) and the buffers from storage
|
||||||
let mesh = job.mesh();
|
let buffers = self.mesh_buffers.get(&job.mesh_buffer_id).unwrap();
|
||||||
let buffers = self.buffer_storage.get(&job.entity()).unwrap();
|
|
||||||
|
|
||||||
// Bind the optional texture
|
// Bind the optional texture
|
||||||
if let Some(tex) = buffers.texture_bindgroup.as_ref() {
|
if let Some(tex) = buffers.texture_bindgroup.as_ref() {
|
||||||
|
@ -695,13 +720,11 @@ impl Renderer for BasicRenderer {
|
||||||
render_pass.set_index_buffer(indices.buffer().slice(..), idx_type.clone());
|
render_pass.set_index_buffer(indices.buffer().slice(..), idx_type.clone());
|
||||||
render_pass.draw_indexed(0..indices_len, 0, 0..1);
|
render_pass.draw_indexed(0..indices_len, 0, 0..1);
|
||||||
} else {
|
} else {
|
||||||
let vertices = mesh.position().unwrap();
|
let vertex_count = buffers.buffer_vertex.count();
|
||||||
|
|
||||||
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
|
render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..));
|
||||||
render_pass.draw(0..vertices.len() as u32, 0..1);
|
render_pass.draw(0..vertex_count as u32, 0..1);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
warn!("Failure to find RenderPipeline with shader id of '{}'!", job.mesh().material().shader_uuid.unwrap_or(0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue