summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-01-10 20:06:01 +0100
committermetamuffin <metamuffin@disroot.org>2025-01-10 20:06:01 +0100
commit3ac853862b5965c1ebfb10b12fb35cf5c671232f (patch)
tree4aaa6684d21ec7eb4dbae00878111989131aedba
parent2746fce8d943325f34b188a67b7039453d8484d1 (diff)
downloadweareserver-3ac853862b5965c1ebfb10b12fb35cf5c671232f.tar
weareserver-3ac853862b5965c1ebfb10b12fb35cf5c671232f.tar.bz2
weareserver-3ac853862b5965c1ebfb10b12fb35cf5c671232f.tar.zst
physics extension and fixes
-rw-r--r--client/src/shader.wgsl23
-rw-r--r--doc/resources.md14
-rw-r--r--server/src/main.rs2
-rw-r--r--shared/src/helper.rs140
-rw-r--r--shared/src/lib.rs4
-rw-r--r--shared/src/resources.rs154
-rw-r--r--world/src/main.rs8
-rw-r--r--world/src/mesh.rs95
-rw-r--r--world/src/physics.rs73
9 files changed, 330 insertions, 183 deletions
diff --git a/client/src/shader.wgsl b/client/src/shader.wgsl
index eb5530c..3f93223 100644
--- a/client/src/shader.wgsl
+++ b/client/src/shader.wgsl
@@ -14,19 +14,14 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
struct VertexIn {
- @location(0) x: f32,
- @location(1) y: f32,
- @location(2) z: f32,
- @location(3) nx: f32,
- @location(4) ny: f32,
- @location(5) nz: f32,
- @location(6) u: f32,
- @location(7) v: f32,
+ @location(0) position: vec3<f32>,
+ @location(1) normal: vec3<f32>,
+ @location(2) texcoord: vec2<f32>,
}
struct VertexOut {
@builtin(position) clip: vec4<f32>,
@location(0) normal: vec3<f32>,
- @location(1) uv: vec2<f32>,
+ @location(1) texcoord: vec2<f32>,
}
@group(0) @binding(0) var tex_albedo: texture_2d<f32>;
@@ -35,15 +30,11 @@ var<push_constant> project: mat4x4<f32>;
@vertex
fn vs_main(vi: VertexIn) -> VertexOut {
- var clip = project * vec4(vi.x, vi.y, vi.z, 1.);
- let vo = VertexOut(
- clip,
- vec3(vi.nx, vi.ny, vi.nz),
- vec2(vi.u, vi.v),
- );
+ var clip = project * vec4(vi.position, 1.);
+ let vo = VertexOut(clip, vi.normal, vi.texcoord);
return vo;
}
@fragment
fn fs_main(vo: VertexOut) -> @location(0) vec4<f32> {
- return textureSample(tex_albedo, tex_albedo_sampler, vo.uv);
+ return textureSample(tex_albedo, tex_albedo_sampler, vo.texcoord);
}
diff --git a/doc/resources.md b/doc/resources.md
index 86f874a..d3d33eb 100644
--- a/doc/resources.md
+++ b/doc/resources.md
@@ -22,7 +22,7 @@
| Key | Value Type | |
| ------------- | -------------------------------------- | --------- |
| `mesh` | `Matrix3`, `Vec3`, `Res<MeshPart>` | Multi key |
-| `collider` | `Matrix3`, `Vec3`, `Res<ColliderPart>` | Multi key |
+| `collision` | `Matrix3`, `Vec3`, `Res<ColliderPart>` | Multi key |
| `light` | `Vec3`, `Res<LightPart>` | Multi key |
| `environment` | `Res<EnvironmentPart>` | |
@@ -51,12 +51,12 @@ white except normals are zero.
| `va_position` | `Res<[Vec3]>` | |
| `va_normal` | `Res<[Vec3]>` | |
| `va_texcoord` | `Res<[Vec2]>` | |
-| `va_roughness` | `Res<Float>` | |
-| `va_metallic` | `Res<Float>` | |
+| `va_roughness` | `Res<[Float]>` | |
+| `va_metallic` | `Res<[Float]>` | |
| `va_albedo` | `Res<[Vec3]>` | |
-| `va_alpha` | `Res<Float>` | |
-| `va_transmission` | `Res<Float>` | |
-| `va_emission` | `Res<Float>` | |
+| `va_alpha` | `Res<[Float]>` | |
+| `va_transmission` | `Res<[Float]>` | |
+| `va_emission` | `Res<[Vec3]>` | |
| `tex_normal` | `Res<Texture>` | Use color channels |
| `tex_roughness` | `Res<Texture>` | Use green channel |
| `tex_metallic` | `Res<Texture>` | Use blue channel |
@@ -107,7 +107,7 @@ white except normals are zero.
WebP
-## ColliderPart
+## CollisionPart
Only one key for shape should be set.
diff --git a/server/src/main.rs b/server/src/main.rs
index a599efa..bb99edd 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -28,7 +28,7 @@ use std::{
use weareshared::{
packets::{Data, Packet, Resource},
resources::{Prefab, PrefabIndex},
- store::{ResourceStore, sha256},
+ store::ResourceStore,
tree::SceneTree,
};
diff --git a/shared/src/helper.rs b/shared/src/helper.rs
index 706e36b..61e149f 100644
--- a/shared/src/helper.rs
+++ b/shared/src/helper.rs
@@ -16,6 +16,7 @@
*/
use crate::packets::{Data, Object, Resource};
use anyhow::Result;
+use glam::{Affine3A, Vec2, Vec3A};
use std::{
io::{Read, Write},
marker::PhantomData,
@@ -65,6 +66,81 @@ impl ReadWrite for Vec<u8> {
Ok(buf)
}
}
+impl ReadWrite for Vec<Vec3A> {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for e in self {
+ e.write(w)?;
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut buf = Vec::new();
+ r.read_to_end(&mut buf)?;
+ Ok(buf
+ .into_iter()
+ .array_chunks::<4>()
+ .map(f32::from_be_bytes)
+ .array_chunks::<3>()
+ .map(Vec3A::from_array)
+ .collect())
+ }
+}
+impl ReadWrite for Vec<Vec2> {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for e in self {
+ e.write(w)?;
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut buf = Vec::new();
+ r.read_to_end(&mut buf)?;
+ Ok(buf
+ .into_iter()
+ .array_chunks::<4>()
+ .map(f32::from_be_bytes)
+ .array_chunks::<2>()
+ .map(Vec2::from_array)
+ .collect())
+ }
+}
+impl ReadWrite for Vec<[u16; 3]> {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for e in self {
+ w.write_all(&e[0].to_be_bytes())?;
+ w.write_all(&e[1].to_be_bytes())?;
+ w.write_all(&e[2].to_be_bytes())?;
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut buf = Vec::new();
+ r.read_to_end(&mut buf)?;
+ Ok(buf
+ .into_iter()
+ .array_chunks::<2>()
+ .map(u16::from_be_bytes)
+ .array_chunks::<3>()
+ .collect())
+ }
+}
+impl ReadWrite for Vec<f32> {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for e in self {
+ e.write(w)?;
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut buf = Vec::new();
+ r.read_to_end(&mut buf)?;
+ Ok(buf
+ .into_iter()
+ .array_chunks::<4>()
+ .map(f32::from_be_bytes)
+ .collect())
+ }
+}
impl ReadWrite for String {
fn write(&self, w: &mut dyn Write) -> Result<()> {
w.write_all(self.as_bytes())?;
@@ -134,3 +210,67 @@ impl ReadWrite for () {
Ok(())
}
}
+impl ReadWrite for Vec2 {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.x.write(w)?;
+ self.y.write(w)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok(Self::new(f32::read(r)?, f32::read(r)?))
+ }
+}
+impl ReadWrite for Vec3A {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.x.write(w)?;
+ self.y.write(w)?;
+ self.z.write(w)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok(Self::new(f32::read(r)?, f32::read(r)?, f32::read(r)?))
+ }
+}
+impl ReadWrite for Affine3A {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ for v in self.to_cols_array() {
+ v.write(w)?
+ }
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok(Self::from_cols_array(&[(); 12].try_map(|()| f32::read(r))?))
+ }
+}
+impl<A: ReadWrite, B: ReadWrite> ReadWrite for (A, B) {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.0.write(w)?;
+ self.1.write(w)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok((A::read(r)?, B::read(r)?))
+ }
+}
+impl<A: ReadWrite, B: ReadWrite, C: ReadWrite> ReadWrite for (A, B, C) {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ self.0.write(w)?;
+ self.1.write(w)?;
+ self.2.write(w)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ Ok((A::read(r)?, B::read(r)?, C::read(r)?))
+ }
+}
+impl ReadWrite for u8 {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ w.write_all(&[*self])?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut buf = [0u8; 1];
+ r.read_exact(&mut buf)?;
+ Ok(buf[0])
+ }
+}
diff --git a/shared/src/lib.rs b/shared/src/lib.rs
index 951683c..11ed2ce 100644
--- a/shared/src/lib.rs
+++ b/shared/src/lib.rs
@@ -16,10 +16,10 @@
*/
#![feature(iter_array_chunks, array_try_map)]
+pub mod helper;
pub mod packets;
pub mod resources;
pub mod store;
pub mod tree;
-pub mod helper;
-pub use glam::{Affine3A, Mat3A, Vec3A, vec3a};
+pub use glam::{Affine3A, Mat3A, Vec2, Vec3A, vec2, vec3a};
diff --git a/shared/src/resources.rs b/shared/src/resources.rs
index 772a140..f422611 100644
--- a/shared/src/resources.rs
+++ b/shared/src/resources.rs
@@ -16,7 +16,7 @@
*/
use crate::{helper::ReadWrite, packets::Resource};
use anyhow::Result;
-use glam::{Affine3A, Vec3A};
+use glam::{Affine3A, Vec2, Vec3A};
use log::warn;
use std::{
collections::BTreeMap,
@@ -27,6 +27,7 @@ use std::{
pub struct Prefab {
pub name: Option<String>,
pub mesh: Vec<(Affine3A, Resource<MeshPart>)>,
+ pub collision: Vec<(Affine3A, Resource<CollisionPart>)>,
pub light: Vec<(Vec3A, Resource<LightPart>)>,
pub environment: Option<Resource<EnvironmentPart>>,
}
@@ -46,7 +47,7 @@ pub struct EnvironmentPart {
#[derive(Debug, Default, Clone)]
pub struct MeshPart {
pub name: Option<String>,
- pub index: Option<Resource<IndexArray>>,
+ pub index: Option<Resource<Vec<[u16; 3]>>>,
pub g_metallic: Option<f32>,
pub g_roughness: Option<f32>,
pub g_albedo: Option<Vec3A>,
@@ -58,15 +59,15 @@ pub struct MeshPart {
pub g_attenuation: Option<Vec3A>,
pub g_dispersion: Option<f32>,
pub g_unlit: Option<()>,
- pub va_position: Option<[Resource<AttributeArray>; 3]>,
- pub va_normal: Option<[Resource<AttributeArray>; 3]>,
- pub va_texcoord: Option<[Resource<AttributeArray>; 2]>,
- pub va_roughness: Option<Resource<AttributeArray>>,
- pub va_metallic: Option<Resource<AttributeArray>>,
- pub va_albedo: Option<[Resource<AttributeArray>; 3]>,
- pub va_transmission: Option<Resource<AttributeArray>>,
- pub va_alpha: Option<Resource<AttributeArray>>,
- pub va_emission: Option<[Resource<AttributeArray>; 3]>,
+ pub va_position: Option<Resource<Vec<Vec3A>>>,
+ pub va_normal: Option<Resource<Vec<Vec3A>>>,
+ pub va_texcoord: Option<Resource<Vec<Vec2>>>,
+ pub va_roughness: Option<Resource<Vec<f32>>>,
+ pub va_metallic: Option<Resource<Vec<f32>>>,
+ pub va_albedo: Option<Resource<Vec<Vec3A>>>,
+ pub va_transmission: Option<Resource<Vec<f32>>>,
+ pub va_alpha: Option<Resource<Vec<f32>>>,
+ pub va_emission: Option<Resource<Vec<Vec3A>>>,
pub tex_normal: Option<Resource<Image>>,
pub tex_roughness: Option<Resource<Image>>,
pub tex_metallic: Option<Resource<Image>>,
@@ -79,12 +80,20 @@ pub struct MeshPart {
}
#[derive(Debug, Default, Clone)]
-pub struct PrefabIndex(pub BTreeMap<String, Resource<Prefab>>);
+pub struct CollisionPart {
+ pub restitution_coeff: Option<f32>,
+ pub friction_kinetic: Option<f32>,
+ pub friction_static: Option<f32>,
+ pub sh_box: Option<Vec3A>,
+ pub sh_sphere: Option<f32>,
+ pub sh_cylinder: Option<(f32, f32, f32)>,
+ pub sh_capsule: Option<(f32, f32, f32)>,
+ pub sh_convex_hull: Option<Resource>,
+ pub sh_mesh: Option<(Resource<Vec<[u16; 3]>>, Resource<Vec<Vec3A>>)>,
+}
#[derive(Debug, Default, Clone)]
-pub struct AttributeArray(pub Vec<f32>);
-#[derive(Debug, Default, Clone)]
-pub struct IndexArray(pub Vec<[u16; 3]>);
+pub struct PrefabIndex(pub BTreeMap<String, Resource<Prefab>>);
#[derive(Debug, Clone)]
pub struct Image(pub Vec<u8>);
@@ -109,12 +118,48 @@ impl ReadWrite for PrefabIndex {
}
}
+impl ReadWrite for CollisionPart {
+ fn write(&self, w: &mut dyn Write) -> Result<()> {
+ write_kv_opt(w, b"restitution_coeff", &self.restitution_coeff)?;
+ write_kv_opt(w, b"friction_kinetic", &self.friction_kinetic)?;
+ write_kv_opt(w, b"friction_static", &self.friction_static)?;
+ write_kv_opt(w, b"sh_box", &self.sh_box)?;
+ write_kv_opt(w, b"sh_sphere", &self.sh_sphere)?;
+ write_kv_opt(w, b"sh_cylinder", &self.sh_cylinder)?;
+ write_kv_opt(w, b"sh_capsule", &self.sh_capsule)?;
+ write_kv_opt(w, b"sh_convex_hull", &self.sh_convex_hull)?;
+ write_kv_opt(w, b"sh_mesh", &self.sh_mesh)?;
+ Ok(())
+ }
+ fn read(r: &mut dyn Read) -> Result<Self> {
+ let mut s = Self::default();
+ read_kv_iter(r, |k, v| match k {
+ b"restitution_coeff" => Ok(s.restitution_coeff = Some(read_slice(v)?)),
+ b"friction_kinetic" => Ok(s.friction_kinetic = Some(read_slice(v)?)),
+ b"friction_static" => Ok(s.friction_static = Some(read_slice(v)?)),
+ b"sh_box" => Ok(s.sh_box = Some(read_slice(v)?)),
+ b"sh_sphere" => Ok(s.sh_sphere = Some(read_slice(v)?)),
+ b"sh_cylinder" => Ok(s.sh_cylinder = Some(read_slice(v)?)),
+ b"sh_capsule" => Ok(s.sh_capsule = Some(read_slice(v)?)),
+ b"sh_convex_hull" => Ok(s.sh_convex_hull = Some(read_slice(v)?)),
+ b"sh_mesh" => Ok(s.sh_mesh = Some(read_slice(v)?)),
+ x => Ok(warn!(
+ "unknown prefab key: {:?}",
+ String::from_utf8_lossy(x)
+ )),
+ })?;
+ Ok(s)
+ }
+}
impl ReadWrite for Prefab {
fn write(&self, w: &mut dyn Write) -> Result<()> {
write_kv_opt(w, b"name", &self.name)?;
for x in &self.mesh {
write_kv_opt(w, b"mesh", &Some(x.clone()))?;
}
+ for x in &self.collision {
+ write_kv_opt(w, b"collision", &Some(x.clone()))?;
+ }
for x in &self.light {
write_kv_opt(w, b"light", &Some(x.clone()))?;
}
@@ -126,6 +171,7 @@ impl ReadWrite for Prefab {
read_kv_iter(r, |k, v| match k {
b"name" => Ok(s.name = Some(read_slice(v)?)),
b"mesh" => Ok(s.mesh.push(read_slice(v)?)),
+ b"collision" => Ok(s.collision.push(read_slice(v)?)),
b"light" => Ok(s.light.push(read_slice(v)?)),
b"environment" => Ok(s.environment = Some(read_slice(v)?)),
x => Ok(warn!(
@@ -284,84 +330,6 @@ fn write_kv(w: &mut dyn Write, key: &[u8], value: &[u8]) -> Result<()> {
Ok(())
}
-impl ReadWrite for u8 {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- w.write_all(&[*self])?;
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- let mut buf = [0u8; 1];
- r.read_exact(&mut buf)?;
- Ok(buf[0])
- }
-}
-
-impl ReadWrite for Vec3A {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- self.x.write(w)?;
- self.y.write(w)?;
- self.z.write(w)?;
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- Ok(Self::new(f32::read(r)?, f32::read(r)?, f32::read(r)?))
- }
-}
-impl ReadWrite for Affine3A {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- for v in self.to_cols_array() {
- v.write(w)?
- }
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- Ok(Self::from_cols_array(&[(); 12].try_map(|()| f32::read(r))?))
- }
-}
-impl ReadWrite for IndexArray {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- for x in self.0.clone() {
- w.write_all(x.map(|x| x.to_be_bytes()).as_flattened())?;
- }
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self(Vec::new());
- let mut g = Vec::new();
- r.read_to_end(&mut g)?;
- for x in g.iter().array_chunks::<2>().array_chunks::<3>() {
- s.0.push(x.map(|x| u16::from_be_bytes(x.map(|x| *x))))
- }
- Ok(s)
- }
-}
-impl ReadWrite for AttributeArray {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- for x in self.0.clone() {
- w.write_all(&x.to_be_bytes())?;
- }
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- let mut s = Self(Vec::new());
- let mut g = Vec::new();
- r.read_to_end(&mut g)?;
- for x in g.iter().array_chunks::<4>() {
- s.0.push(f32::from_be_bytes(x.map(|x| *x)))
- }
- Ok(s)
- }
-}
-impl<A: ReadWrite, B: ReadWrite> ReadWrite for (A, B) {
- fn write(&self, w: &mut dyn Write) -> Result<()> {
- self.0.write(w)?;
- self.1.write(w)?;
- Ok(())
- }
- fn read(r: &mut dyn Read) -> Result<Self> {
- Ok((A::read(r)?, B::read(r)?))
- }
-}
impl ReadWrite for Image {
fn write(&self, w: &mut dyn Write) -> Result<()> {
self.0.write(w)
diff --git a/world/src/main.rs b/world/src/main.rs
index 5dbfd06..c90ff0c 100644
--- a/world/src/main.rs
+++ b/world/src/main.rs
@@ -16,6 +16,7 @@
*/
#![feature(iter_array_chunks)]
pub mod mesh;
+pub mod physics;
use anyhow::{Result, bail};
use clap::Parser;
@@ -23,6 +24,7 @@ use gltf::{Gltf, image::Source, import_buffers};
use image::{ImageReader, codecs::webp::WebPEncoder};
use log::info;
use mesh::import_mesh;
+use physics::import_physics;
use rand::random;
use std::{
fs::File,
@@ -93,6 +95,7 @@ fn main() -> Result<()> {
for node in gltf.nodes() {
if let Some(mesh) = node.mesh() {
+ info!("--- MESH ---");
import_mesh(
mesh,
&buffers,
@@ -105,7 +108,11 @@ fn main() -> Result<()> {
}
let (position, _, _) = node.transform().decomposed();
if let Some(light) = node.light() {
+ info!("--- LIGHT ---");
let emission = Some(Vec3A::from_array(light.color()) * light.intensity());
+ if let Some(e) = emission {
+ info!("emission is {e}");
+ }
prefab.light.push((
Vec3A::from_array(position),
store.set(&LightPart {
@@ -114,6 +121,7 @@ fn main() -> Result<()> {
})?,
));
}
+ import_physics(&gltf, &node, &mut prefab, &store, &buffers)?;
}
if let Some(skybox) = args.skybox {
diff --git a/world/src/mesh.rs b/world/src/mesh.rs
index c621753..67f86ad 100644
--- a/world/src/mesh.rs
+++ b/world/src/mesh.rs
@@ -21,8 +21,9 @@ use log::{debug, info};
use std::path::Path;
use weareshared::{
Affine3A, Vec3A,
- resources::{AttributeArray, IndexArray, MeshPart, Prefab},
+ resources::{MeshPart, Prefab},
store::ResourceStore,
+ vec2, vec3a,
};
pub fn import_mesh(
@@ -40,77 +41,39 @@ pub fn import_mesh(
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", pos_x.len());
- Ok::<_, anyhow::Error>([
- store.set(&AttributeArray(pos_x))?,
- store.set(&AttributeArray(pos_y))?,
- store.set(&AttributeArray(pos_z))?,
- ])
+ let a = iter.map(|[x, y, z]| vec3a(x, y, z)).collect::<Vec<_>>();
+ info!("{} vertex positions", a.len());
+ Ok::<_, anyhow::Error>(store.set(&a)?)
})
.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", normal_x.len());
- Ok::<_, anyhow::Error>([
- store.set(&AttributeArray(normal_x))?,
- store.set(&AttributeArray(normal_y))?,
- store.set(&AttributeArray(normal_z))?,
- ])
+ let a = iter.map(|[x, y, z]| vec3a(x, y, z)).collect::<Vec<_>>();
+ info!("{} vertex normals", a.len());
+ Ok::<_, anyhow::Error>(store.set(&a)?)
})
.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", texcoord_u.len());
- Ok::<_, anyhow::Error>([
- store.set(&AttributeArray(texcoord_u))?,
- store.set(&AttributeArray(texcoord_v))?,
- ])
+ let a = iter.into_f32().map(|[x, y]| vec2(x, y)).collect::<Vec<_>>();
+ info!("{} vertex texture coordinates", a.len());
+ Ok::<_, anyhow::Error>(store.set(&a)?)
})
.transpose()?;
let va_albedo = reader
.read_colors(0)
.map(|iter| {
- let mut color_r = vec![];
- let mut color_g = vec![];
- let mut color_b = vec![];
- for p in iter.into_rgb_f32() {
- color_r.push(p[0]);
- color_g.push(p[1]);
- color_b.push(p[2]);
- }
- info!("{} vertex colors", color_r.len());
- Ok::<_, anyhow::Error>([
- store.set(&AttributeArray(color_r))?,
- store.set(&AttributeArray(color_g))?,
- store.set(&AttributeArray(color_b))?,
- ])
+ let a = iter
+ .into_rgb_f32()
+ .map(|[x, y, z]| vec3a(x, y, z))
+ .collect::<Vec<_>>();
+ info!("{} vertex colors", a.len());
+ Ok::<_, anyhow::Error>(store.set(&a)?)
})
.transpose()?;
@@ -123,7 +86,7 @@ pub fn import_mesh(
}
let o = if color_a.iter().any(|x| *x != 1.) {
info!("{} vertex transmissions", color_a.len());
- Some(store.set(&AttributeArray(color_a))?)
+ Some(store.set(&color_a)?)
} else {
debug!("vertex transmission pruned");
None
@@ -141,7 +104,7 @@ pub fn import_mesh(
.array_chunks::<3>()
.collect::<Vec<_>>();
info!("{} indecies", index.len() * 3);
- let index = Some(store.set(&IndexArray(index))?);
+ let index = Some(store.set(&index)?);
let mut tex_albedo = None;
let mut tex_alpha = None;
@@ -370,13 +333,17 @@ pub fn import_mesh(
va_metallic: None,
va_roughness: None,
})?;
- let mat = node.transform().matrix();
- let aff = Affine3A::from_cols_array_2d(&[
- [mat[0][0], mat[0][1], mat[0][2]],
- [mat[1][0], mat[1][1], mat[1][2]],
- [mat[2][0], mat[2][1], mat[2][2]],
- [mat[3][0], mat[3][1], mat[3][2]],
- ]);
- prefab.mesh.push((aff, mesh))
+
+ prefab.mesh.push((node_transform_to_affine(node), mesh))
})
}
+
+pub fn node_transform_to_affine(node: &Node) -> Affine3A {
+ let mat = node.transform().matrix();
+ Affine3A::from_cols_array_2d(&[
+ [mat[0][0], mat[0][1], mat[0][2]],
+ [mat[1][0], mat[1][1], mat[1][2]],
+ [mat[2][0], mat[2][1], mat[2][2]],
+ [mat[3][0], mat[3][1], mat[3][2]],
+ ])
+}
diff --git a/world/src/physics.rs b/world/src/physics.rs
new file mode 100644
index 0000000..82bb28f
--- /dev/null
+++ b/world/src/physics.rs
@@ -0,0 +1,73 @@
+use anyhow::{Result, anyhow};
+use gltf::{Gltf, Node, buffer::Data, json::Value};
+use log::info;
+use weareshared::{
+ resources::{CollisionPart, Prefab},
+ store::ResourceStore,
+ vec3a,
+};
+
+use crate::mesh::node_transform_to_affine;
+
+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::<Vec<_>>();
+ let position = reader
+ .read_positions()
+ .ok_or(anyhow!("convexHull no positions"))?
+ .map(|[x, y, z]| vec3a(x, y, z))
+ .collect::<Vec<_>>();
+
+ 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(())
+}