diff options
Diffstat (limited to 'world/src/mesh.rs')
-rw-r--r-- | world/src/mesh.rs | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/world/src/mesh.rs b/world/src/mesh.rs deleted file mode 100644 index ffc0f2f..0000000 --- a/world/src/mesh.rs +++ /dev/null @@ -1,431 +0,0 @@ -/* - wearechat - generic multiplayer game with voip - Copyright (C) 2025 metamuffin - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, version 3 of the License only. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <https://www.gnu.org/licenses/>. -*/ -use crate::{Args, TextureCache, load_texture, vrm::VrmInfo}; -use anyhow::Result; -use gltf::{Mesh, Node, buffer::Data}; -use log::{debug, info, warn}; -use std::{collections::BTreeMap, path::Path}; -use weareshared::{ - Affine3A, Vec3A, packets::Resource, resources::MeshPart, store::ResourceStore, vec2, vec3a, - vec4, -}; - -pub fn import_mesh( - mesh: Mesh, - trans: Affine3A, - buffers: &[Data], - store: &ResourceStore, - path_base: &Path, - node: &Node, - args: &Args, - texture_cache: &TextureCache, - joint_index_map: &BTreeMap<(usize, u16), u32>, - vrm: &VrmInfo, - head_bones: &[u32], -) -> Result<Vec<(usize, Affine3A, Resource<MeshPart>)>> { - let mut meshes = Vec::new(); - for p in mesh.primitives() { - let name = mesh.name().or(node.name()).map(|e| e.to_owned()); - if let Some(name) = &name { - info!("adding mesh {name:?}"); - } else { - info!("adding mesh"); - } - let reader = p.reader(|buf| Some(&buffers[buf.index()])); - - let mut num_vertex = 0; - let va_position = reader - .read_positions() - .map(|iter| { - let a = iter.map(|[x, y, z]| vec3a(x, y, z)).collect::<Vec<_>>(); - debug!("{} vertex positions", a.len()); - num_vertex = a.len(); - store.set(&a) - }) - .transpose()?; - - let va_normal = reader - .read_normals() - .map(|iter| { - let a = iter.map(|[x, y, z]| vec3a(x, y, z)).collect::<Vec<_>>(); - debug!("{} vertex normals", a.len()); - store.set(&a) - }) - .transpose()?; - - let va_tangent = reader - .read_tangents() - .map(|iter| { - // TODO dont ignore handedness - let a = iter - .map(|[x, y, z, h]| vec4(x, y, z, h)) - .collect::<Vec<_>>(); - debug!("{} vertex tangents", a.len()); - store.set(&a) - }) - .transpose()?; - - let mut many_head_bones = false; - let va_joint_index = reader - .read_joints(0) - .map(|iter| { - let si = node.skin().unwrap().index(); - let a = iter - .into_u16() - .map(|x| x.map(|x| joint_index_map[&(si, x)])) - .collect::<Vec<_>>(); - - let head_bone_count = a - .iter() - .flatten() - .filter(|b| head_bones.contains(*b)) - .count(); - many_head_bones |= head_bone_count > a.len() / 2; - debug!("{} vertex joint indecies", a.len()); - if many_head_bones { - debug!("many joints are head bones"); - } - if a.len() != num_vertex { - warn!("joint index count does not vertex count") - } - store.set(&a) - }) - .transpose()?; - - let va_joint_weight = reader - .read_weights(0) - .map(|iter| { - let a = iter.into_f32().collect::<Vec<_>>(); - debug!("{} vertex joint weights", a.len()); - if a.len() != num_vertex { - warn!("joint weight count does not vertex count") - } - store.set(&a) - }) - .transpose()?; - - let va_texcoord = reader - .read_tex_coords(0) - .map(|iter| { - let a = iter.into_f32().map(|[x, y]| vec2(x, y)).collect::<Vec<_>>(); - debug!("{} vertex texture coordinates", a.len()); - store.set(&a) - }) - .transpose()?; - - let va_albedo = reader - .read_colors(0) - .map(|iter| { - let a = iter - .into_rgb_f32() - .map(|[x, y, z]| vec3a(x, y, z)) - .collect::<Vec<_>>(); - debug!("{} vertex colors", a.len()); - store.set(&a) - }) - .transpose()?; - - let va_alpha = reader - .read_colors(0) - .map(|iter| { - let mut color_a = vec![]; - for p in iter.into_rgba_f32() { - color_a.push(p[3]); - } - let o = if color_a.iter().any(|x| *x != 1.) { - debug!("{} vertex transmissions", color_a.len()); - Some(store.set(&color_a)?) - } else { - debug!("vertex transmission pruned"); - None - }; - Ok::<_, anyhow::Error>(o) - }) - .transpose()? - .flatten(); - - let index = reader - .read_indices() - .unwrap() - .into_u32() - .array_chunks::<3>() - .collect::<Vec<_>>(); - - debug!("{} indecies", index.len() * 3); - let index = Some(store.set(&index)?); - - let mut tex_albedo = None; - let mut tex_alpha = None; - if let Some(tex) = p.material().pbr_metallic_roughness().base_color_texture() { - let r = load_texture( - "albedo", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?; - tex_albedo = Some(r.clone()); - tex_alpha = Some(r.clone()); - } - 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(), - args.webp, - texture_cache, - )?); - } - let mut tex_emission = None; - if let Some(tex) = p.material().emissive_texture() { - tex_emission = Some(load_texture( - "emission", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?); - } - let mut tex_transmission = None; - if let Some(tex) = p - .material() - .transmission() - .and_then(|t| t.transmission_texture()) - { - tex_transmission = Some(load_texture( - "transmission", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?); - } - let mut tex_thickness = None; - if let Some(tex) = p.material().volume().and_then(|t| t.thickness_texture()) { - tex_thickness = Some(load_texture( - "thickness", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?); - } - let mut tex_occlusion = None; - if let Some(tex) = p.material().occlusion_texture() { - tex_occlusion = Some(load_texture( - "occlusion", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?); - } - let mut tex_roughness = None; - let mut tex_metallic = None; - if let Some(tex) = p - .material() - .pbr_metallic_roughness() - .metallic_roughness_texture() - { - let r = load_texture( - "metallic+roughness", - store, - path_base, - buffers, - &tex.texture().source().source(), - args.webp, - texture_cache, - )?; - tex_roughness = Some(r.clone()); - tex_metallic = Some(r.clone()); - } - - let g_metallic = Some(p.material().pbr_metallic_roughness().metallic_factor()); - let g_roughness = Some(p.material().pbr_metallic_roughness().roughness_factor()); - - let base_color = p.material().pbr_metallic_roughness().base_color_factor(); - - let g_albedo = if base_color[0] != 1. || base_color[1] != 1. || base_color[2] != 1. { - debug!( - "albedo is r={},g={},b={}", - base_color[0], base_color[1], base_color[2] - ); - Some(Vec3A::new(base_color[0], base_color[1], base_color[2])) - } else { - debug!("albedo pruned"); - None - }; - let g_alpha = if base_color[3] != 1. { - debug!("alpha is {}", base_color[3]); - Some(base_color[3]) - } else { - debug!("alpha pruned"); - None - }; - - let emission = p.material().emissive_factor(); - let g_emission = if emission[0] != 0. || emission[1] != 0. || emission[2] != 0. { - debug!( - "emission is r={},g={},b={}", - base_color[0], base_color[1], base_color[2] - ); - Some(Vec3A::new(emission[0], emission[1], emission[2])) - } else { - debug!("emission pruned"); - None - }; - - let transmission = p - .material() - .transmission() - .map(|t| t.transmission_factor()) - .unwrap_or(0.); - - let g_transmission = if transmission != 0. { - debug!("transmission is {transmission}"); - Some(transmission) - } else { - debug!("transmission pruned"); - None - }; - - let g_dispersion = p - .material() - .extension_value("KHR_materials_dispersion") - .and_then(|e| e.get("dispersion")) - .and_then(|e| e.as_f64()) - .map(|e| e as f32); - if let Some(d) = g_dispersion { - debug!("dispersion is {d}"); - } - - // if node.name() == Some("fog") { - // eprintln!("{:#?}", p.material().volume().is_some()); - // eprintln!("{:#?}", p.material().ior()); - // eprintln!("{:#?}", p.material().transmission().is_some()); - // } - - let g_attenuation = p.material().volume().map(|v| { - let ref_dist = v.attenuation_distance(); - let att = Vec3A::from_array(v.attenuation_color().map( - // manually derived from attenuation coefficient formula. i hope this is correct. - |factor| -(factor.powf(1. / ref_dist)).ln(), - )); - debug!("attenuation is {att}"); - att - }); - let g_refractive_index = p.material().ior(); - if let Some(i) = g_refractive_index { - debug!("refractive index is {i}"); - } - let g_thickness = p.material().volume().map(|v| v.thickness_factor()); - - let g_unlit = bool_to_opt( - p.material() - .extension_value("KHR_materials_unlit") - .is_some(), - "unlit", - ); - - let g_double_sided = bool_to_opt(p.material().double_sided(), "double sided"); - - let hint_volume = bool_to_opt( - g_attenuation.is_some_and(|a| a.length() > 0.01), - "volume hint", - ); - - let hint_hide_first_person = bool_to_opt( - many_head_bones | vrm.hide_first_person.contains(&node.index()), - "hide first person hint", - ); - - let hint_mirror = bool_to_opt( - node.name().unwrap_or_default().ends_with("-mirror"), - "mirror hint", - ); - - let armature = node.skin().map(|_| 0); - - let mesh = MeshPart { - name, - index, - armature, - g_albedo, - g_alpha, - g_metallic, - g_roughness, - g_emission, - g_transmission, - g_attenuation, - g_thickness, - g_refractive_index, - g_dispersion, - g_unlit, - g_double_sided, - va_position, - va_normal, - va_tangent, - va_texcoord, - va_albedo, - va_alpha, - va_joint_index, - va_joint_weight, - tex_albedo, - tex_normal, - tex_roughness, - tex_metallic, - tex_alpha, - tex_emission, - tex_transmission, - tex_thickness, - tex_occlusion, - hint_hide_first_person, - hint_mirror, - hint_volume, - // not supported by gltf - hint_static: None, // TODO Set when instancing - va_transmission: None, - va_emission: None, - va_metallic: None, - va_roughness: None, - }; - meshes.push((node.index(), trans, store.set(&mesh)?)) - } - Ok(meshes) -} - -fn bool_to_opt(b: bool, log: &str) -> Option<()> { - if b { - debug!("{log}"); - Some(()) - } else { - None - } -} |