From 0a0abfe7b093d91447fb7070820a0e6d56d6c22d Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 7 Jan 2025 16:50:44 +0100 Subject: normal texture --- world/src/main.rs | 174 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 124 insertions(+), 50 deletions(-) (limited to 'world') diff --git a/world/src/main.rs b/world/src/main.rs index b68b287..517f1e9 100644 --- a/world/src/main.rs +++ b/world/src/main.rs @@ -1,18 +1,20 @@ #![feature(iter_array_chunks)] -use anyhow::Result; +use anyhow::{Result, bail}; use clap::Parser; -use log::info; +use gltf::image::Source; +use log::{info, warn}; use rand::random; use std::{ - io::Write, + fs::File, + io::{Read, Write}, net::{SocketAddr, TcpStream}, - path::PathBuf, + path::{Path, PathBuf}, thread::{self, sleep}, time::Duration, }; use weareshared::{ Affine3A, Vec3A, - packets::{Data, Object, Packet, ReadWrite}, + packets::{Data, Object, Packet, ReadWrite, Resource}, resources::{AttributeArray, IndexArray, Part, Prefab}, store::ResourceStore, vec3a, @@ -37,35 +39,71 @@ fn main() -> Result<()> { Packet::Connect(random()).write(&mut sock)?; - let (gltf, buffers, _) = gltf::import(args.scene)?; + let (gltf, buffers, _) = gltf::import(&args.scene)?; + let path_base = args.scene.parent().unwrap(); let mut prefab = Prefab::default(); for node in gltf.nodes() { if let Some(mesh) = node.mesh() { for p in mesh.primitives() { let reader = p.reader(|buf| Some(&buffers[buf.index()])); - let mut pos_x = vec![]; - let mut pos_y = vec![]; - let mut pos_z = vec![]; - let mut norm_x = vec![]; - let mut norm_y = vec![]; - let mut norm_z = vec![]; - let mut uv_x = vec![]; - let mut uv_y = vec![]; - for p in reader.read_positions().unwrap() { - pos_x.push(p[0]); - pos_y.push(p[1]); - pos_z.push(p[2]); - } - for p in reader.read_normals().unwrap() { - norm_x.push(p[0]); - norm_y.push(p[1]); - norm_z.push(p[2]); - } - for p in reader.read_tex_coords(0).unwrap().into_f32() { - uv_x.push(p[0]); - uv_y.push(p[1]); - } + + let va_position = reader + .read_positions() + .map(|iter| { + let mut pos_x = vec![]; + let mut pos_y = vec![]; + let mut pos_z = vec![]; + for p in iter { + pos_x.push(p[0]); + pos_y.push(p[1]); + pos_z.push(p[2]); + } + info!("vertex positions"); + Ok::<_, anyhow::Error>([ + store.set(&AttributeArray(pos_x).write_alloc())?, + store.set(&AttributeArray(pos_y).write_alloc())?, + store.set(&AttributeArray(pos_z).write_alloc())?, + ]) + }) + .transpose()?; + + let va_normal = reader + .read_normals() + .map(|iter| { + let mut normal_x = vec![]; + let mut normal_y = vec![]; + let mut normal_z = vec![]; + for p in iter { + normal_x.push(p[0]); + normal_y.push(p[1]); + normal_z.push(p[2]); + } + info!("vertex normals"); + Ok::<_, anyhow::Error>([ + store.set(&AttributeArray(normal_x).write_alloc())?, + store.set(&AttributeArray(normal_y).write_alloc())?, + store.set(&AttributeArray(normal_z).write_alloc())?, + ]) + }) + .transpose()?; + let va_texcoord = reader + .read_tex_coords(0) + .map(|iter| { + let mut texcoord_u = vec![]; + let mut texcoord_v = vec![]; + for p in iter.into_f32() { + texcoord_u.push(p[0]); + texcoord_v.push(p[1]); + } + info!("vertex texture coordinates"); + Ok::<_, anyhow::Error>([ + store.set(&AttributeArray(texcoord_u).write_alloc())?, + store.set(&AttributeArray(texcoord_v).write_alloc())?, + ]) + }) + .transpose()?; + let index = reader .read_indices() .unwrap() @@ -73,36 +111,42 @@ fn main() -> Result<()> { .map(|e| e as u16) .array_chunks::<3>() .collect::>(); + let index = Some(store.set(&IndexArray(index).write_alloc())?); let mut tex_albedo = None; if let Some(tex) = p.material().pbr_metallic_roughness().base_color_texture() { - let s = tex.texture().source().source(); - if let gltf::image::Source::View { view, mime_type } = s { - info!("albedo texture is of type {mime_type:?}"); - let buf = &buffers[view.buffer().index()].0 - [view.offset()..view.offset() + view.length()]; - tex_albedo = Some(store.set(buf)?); - } + tex_albedo = Some(load_texture( + "albedo", + &store, + path_base, + &buffers, + &tex.texture().source().source(), + )?); + } + let mut tex_normal = None; + if let Some(tex) = p.material().normal_texture() { + tex_normal = Some(load_texture( + "normal", + &store, + path_base, + &buffers, + &tex.texture().source().source(), + )?); } + let g_metallic = Some(p.material().pbr_metallic_roughness().metallic_factor()); + let g_roughness = Some(p.material().pbr_metallic_roughness().roughness_factor()); + let part = store.set( &Part { - va_position: Some([ - store.set(&AttributeArray(pos_x).write_alloc())?, - store.set(&AttributeArray(pos_y).write_alloc())?, - store.set(&AttributeArray(pos_z).write_alloc())?, - ]), - va_normal: Some([ - store.set(&AttributeArray(norm_x).write_alloc())?, - store.set(&AttributeArray(norm_y).write_alloc())?, - store.set(&AttributeArray(norm_z).write_alloc())?, - ]), - va_texcoord: Some([ - store.set(&AttributeArray(uv_x).write_alloc())?, - store.set(&AttributeArray(uv_y).write_alloc())?, - ]), + g_metallic, + g_roughness, + va_position, + va_normal, + va_texcoord, tex_albedo, - index: Some(store.set(&IndexArray(index).write_alloc())?), + tex_normal, + index, ..Part::default() } .write_alloc(), @@ -160,3 +204,33 @@ fn main() -> Result<()> { } Ok(()) } + +fn load_texture( + name: &str, + store: &ResourceStore, + path: &Path, + buffers: &[gltf::buffer::Data], + source: &Source, +) -> Result { + match source { + gltf::image::Source::View { view, mime_type } => { + info!("{name} texture is embedded and of type {mime_type:?}"); + let buf = + &buffers[view.buffer().index()].0[view.offset()..view.offset() + view.length()]; + return Ok(store.set(buf)?); + } + gltf::image::Source::Uri { + uri, + mime_type: Some(mime_type), + } => { + info!("{name} texture is at {uri:?} and of type {mime_type:?}"); + let path = path.join(uri); + let mut buf = Vec::new(); + File::open(path)?.read_to_end(&mut buf)?; + return Ok(store.set(&buf)?); + } + _ => { + bail!("texture is external and has no mime type") + } + } +} -- cgit v1.2.3-70-g09d2