/* 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 . */ use crate::mesh::node_transform_to_affine; use anyhow::{Result, anyhow}; use gltf::{Gltf, Node, buffer::Data, json::Value}; use log::info; use weareshared::{ resources::{CollisionPart, Prefab}, store::ResourceStore, vec3a, }; pub fn import_physics( gltf: &Gltf, node: &Node, prefab: &mut Prefab, store: &ResourceStore, buffers: &[Data], ) -> Result<()> { if let Some(physics) = node .extensions() .map(|e| e.get("KHR_physics_rigid_bodies")) .flatten() { info!("--- COLLISION ---"); if let Some(collider) = physics.get("collider") { if let Some(geometry) = collider.get("geometry") { if geometry.get("convexHull") == Some(&Value::Bool(true)) { let node = geometry .get("node") .map(|n| n.as_u64()) .flatten() .ok_or(anyhow!("convexHull node missing"))?; let node = gltf .nodes() .nth(node as usize) .ok_or(anyhow!("convexHull node reference invalid"))?; let mesh = node.mesh().ok_or(anyhow!("convexHull node has no mesh"))?; for p in mesh.primitives() { let reader = p.reader(|buf| Some(&buffers[buf.index()])); let index = reader .read_indices() .ok_or(anyhow!("convexHull no index buffer"))? .into_u32() .map(|e| e as u16) .array_chunks::<3>() .collect::>(); let position = reader .read_positions() .ok_or(anyhow!("convexHull no positions"))? .map(|[x, y, z]| vec3a(x, y, z)) .collect::>(); info!( "convex hull has {} indecies and {} positions", index.len(), position.len() ); prefab.collision.push(( node_transform_to_affine(&node), store.set(&CollisionPart { sh_mesh: Some((store.set(&index)?, store.set(&position)?)), ..Default::default() })?, )); } } } } } Ok(()) }