+13
-12
Cargo.lock
+13
-12
Cargo.lock
···
2428
2428
"simd-adler32",
2429
2429
]
2430
2430
2431
+
[[package]]
2432
+
name = "felix-assets"
2433
+
version = "0.1.0"
2434
+
dependencies = [
2435
+
"anyhow",
2436
+
"bevy",
2437
+
"flate2",
2438
+
"unity-asset",
2439
+
"unity-asset-binary",
2440
+
"unity-asset-decode",
2441
+
]
2442
+
2431
2443
[[package]]
2432
2444
name = "felix-audio"
2433
2445
version = "0.1.0"
···
2451
2463
"bevy_mod_xr",
2452
2464
"cpal 0.16.0",
2453
2465
"dotenvy",
2466
+
"felix-assets",
2454
2467
"felix-audio",
2455
-
"felix-loader",
2456
2468
"felix-net",
2457
2469
"openxr",
2458
2470
"tokio",
2459
2471
]
2460
2472
2461
-
[[package]]
2462
-
name = "felix-loader"
2463
-
version = "0.1.0"
2464
-
dependencies = [
2465
-
"anyhow",
2466
-
"bevy",
2467
-
"unity-asset",
2468
-
"unity-asset-binary",
2469
-
"unity-asset-decode",
2470
-
]
2471
-
2472
2473
[[package]]
2473
2474
name = "felix-net"
2474
2475
version = "0.1.0"
+1
-1
Cargo.toml
+1
-1
Cargo.toml
+2
-1
loader/Cargo.toml
assets/Cargo.toml
+2
-1
loader/Cargo.toml
assets/Cargo.toml
+87
assets/src/buffer.rs
+87
assets/src/buffer.rs
···
1
+
use std::io::Read;
2
+
3
+
use bevy::math::{Quat, Vec3};
4
+
5
+
pub struct StreamedBuffer{
6
+
stream: Box<dyn Read>
7
+
}
8
+
9
+
impl StreamedBuffer{
10
+
pub fn new( stream: impl Read + 'static ) -> Self{
11
+
Self {
12
+
stream: Box::new(stream)
13
+
}
14
+
}
15
+
16
+
pub fn get_u8(&mut self) -> u8{
17
+
let mut b = [0u8; 1];
18
+
self.stream.read(&mut b).unwrap();
19
+
20
+
b[0]
21
+
}
22
+
23
+
pub fn get_u8s(&mut self, count: usize) -> Vec<u8>{
24
+
let mut b = vec![0u8; count];
25
+
self.stream.read(&mut b).unwrap();
26
+
27
+
b
28
+
}
29
+
30
+
pub fn get_i16(&mut self) -> i16{
31
+
let b = self.get_u8s(2);
32
+
i16::from_le_bytes([ b[0], b[1] ])
33
+
}
34
+
35
+
pub fn get_i32(&mut self) -> i32{
36
+
let b = self.get_u8s(4);
37
+
i32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
38
+
}
39
+
40
+
pub fn get_i64(&mut self) -> i64{
41
+
let b = self.get_u8s(8);
42
+
i64::from_le_bytes([ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] ])
43
+
}
44
+
45
+
pub fn get_u16(&mut self) -> u16{
46
+
let b = self.get_u8s(2);
47
+
u16::from_le_bytes([ b[0], b[1] ])
48
+
}
49
+
50
+
pub fn get_u32(&mut self) -> u32{
51
+
let b = self.get_u8s(4);
52
+
u32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
53
+
}
54
+
55
+
pub fn get_u64(&mut self) -> u64{
56
+
let b = self.get_u8s(8);
57
+
u64::from_le_bytes([ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] ])
58
+
}
59
+
60
+
pub fn get_str(&mut self) -> String{
61
+
let length = self.get_u32();
62
+
let b = self.get_u8s(length as usize);
63
+
64
+
let string = str::from_utf8(&b).unwrap();
65
+
string.to_owned()
66
+
}
67
+
68
+
69
+
pub fn get_vec3(&mut self) -> Vec3{
70
+
Vec3 { x: self.get_f32(), y: self.get_f32(), z: self.get_f32() }
71
+
}
72
+
73
+
pub fn get_quat(&mut self) -> Quat{
74
+
Quat::from_xyzw(self.get_f32(), self.get_f32(), self.get_f32(), self.get_f32())
75
+
}
76
+
77
+
78
+
pub fn get_f32(&mut self) -> f32{
79
+
let b = self.get_u8s(4);
80
+
f32::from_le_bytes([ b[0], b[1], b[2], b[3] ])
81
+
}
82
+
83
+
pub fn get_f64(&mut self) -> f64{
84
+
let b = self.get_u8s(8);
85
+
f64::from_le_bytes([ b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] ])
86
+
}
87
+
}
+52
assets/src/felix/mod.rs
+52
assets/src/felix/mod.rs
···
1
+
use std::fs::File;
2
+
3
+
use bevy::{asset::RenderAssetUsages, mesh::{Indices, PrimitiveTopology}, prelude::*, transform::components::Transform};
4
+
use flate2::read::GzDecoder;
5
+
6
+
use crate::{BevyObject, buffer::StreamedBuffer};
7
+
8
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
9
+
let mut objs = vec![];
10
+
11
+
let decoder = GzDecoder::new(File::open(path).unwrap());
12
+
let mut buf = StreamedBuffer::new(decoder);
13
+
14
+
let obj_count = buf.get_u32();
15
+
16
+
for _ in 0..obj_count{
17
+
let name = buf.get_str();
18
+
let transform = Transform {
19
+
translation: buf.get_vec3(),
20
+
rotation: buf.get_quat(),
21
+
scale: buf.get_vec3()
22
+
};
23
+
24
+
let mut vertices = vec![];
25
+
let mut normals = vec![];
26
+
let mut triangles = vec![];
27
+
28
+
let vertex_count = buf.get_u32();
29
+
for _ in 0..vertex_count{
30
+
vertices.push(buf.get_vec3());
31
+
normals.push(buf.get_vec3());
32
+
}
33
+
34
+
let triangle_count = buf.get_u32();
35
+
for _ in 0..triangle_count{
36
+
triangles.push(buf.get_u32());
37
+
triangles.push(buf.get_u32());
38
+
triangles.push(buf.get_u32());
39
+
}
40
+
41
+
objs.push(BevyObject {
42
+
name,
43
+
transform,
44
+
mesh: Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
45
+
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
46
+
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
47
+
.with_inserted_indices(Indices::U32(triangles))
48
+
});
49
+
}
50
+
51
+
Ok(objs)
52
+
}
+16
assets/src/lib.rs
+16
assets/src/lib.rs
···
1
+
use bevy::{mesh::Mesh, transform::components::Transform};
2
+
3
+
mod unity;
4
+
mod felix;
5
+
mod buffer;
6
+
7
+
#[derive(Debug)]
8
+
pub struct BevyObject{
9
+
pub name: String,
10
+
pub transform: Transform,
11
+
pub mesh: Mesh,
12
+
}
13
+
14
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
15
+
felix::load(path)
16
+
}
loader/src/unity/component/mesh_renderer.rs
assets/src/unity/component/mesh_renderer.rs
loader/src/unity/component/mesh_renderer.rs
assets/src/unity/component/mesh_renderer.rs
loader/src/unity/component/mod.rs
assets/src/unity/component/mod.rs
loader/src/unity/component/mod.rs
assets/src/unity/component/mod.rs
+1
-1
loader/src/unity/component/transform.rs
assets/src/unity/component/transform.rs
+1
-1
loader/src/unity/component/transform.rs
assets/src/unity/component/transform.rs
···
1
1
use bevy::transform::components::Transform;
2
2
use unity_asset_binary::object::UnityObject;
3
3
4
-
use crate::util::unity_value::{unity_value_to_quat, unity_value_to_vec3};
4
+
use crate::unity::unity_value::{unity_value_to_quat, unity_value_to_vec3};
5
5
6
6
pub fn into_bevy_transform(value: UnityObject) -> Transform {
7
7
let position = value.get("m_LocalPosition").unwrap();
+24
-7
loader/src/unity/mod.rs
assets/src/unity/mod.rs
+24
-7
loader/src/unity/mod.rs
assets/src/unity/mod.rs
···
1
+
// NOTE: Very WIP, Does not work!!
2
+
1
3
use anyhow::bail;
2
4
use bevy::{prelude::*, transform::components::Transform};
3
5
use unity_asset::environment::{Environment, EnvironmentObjectRef};
4
6
use unity_asset_binary::unity_version::UnityVersion;
5
7
use unity_asset_decode::mesh::MeshParser;
6
8
7
-
use crate::{unity::component::{Component, mesh_renderer::MeshRenderer, transform::into_bevy_transform}, util};
9
+
use crate::{BevyObject, unity::{component::{Component, mesh_renderer::MeshRenderer, transform::into_bevy_transform}, unity_value::try_unity_mesh_to_bevy}};
8
10
9
11
mod component;
12
+
mod unity_value;
10
13
11
14
#[derive(Debug)]
12
-
pub struct GameObject{
15
+
pub struct UnityGameObject{
13
16
pub name: String,
14
17
pub active: bool,
15
18
···
18
21
pub mesh_filter: Option<Mesh>,
19
22
}
20
23
21
-
pub fn load( path: &'static str ) -> anyhow::Result<Vec<GameObject>>{
24
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<BevyObject>>{
22
25
let mesh_parser = MeshParser::new(UnityVersion::parse_version("2020.3.12f1").unwrap());
23
26
24
27
let mut env = Environment::new();
···
60
63
let mesh = env.find_binary_object(path_id).unwrap();
61
64
let mesh_obj = mesh.read().unwrap();
62
65
63
-
if let Some(mesh) = util::unity_value::try_unity_mesh_to_bevy(mesh_obj, &mesh_parser){
66
+
if let Some(mesh) = try_unity_mesh_to_bevy(mesh_obj, &mesh_parser){
64
67
mesh_filter = Some(mesh);
65
68
} else{
66
69
println!("[WARN] Failed to load mesh for: {}", go.name);
···
73
76
74
77
if transform.is_none(){ bail!("Cannot find transform for object {}", go.name); }
75
78
76
-
let gameobject = GameObject {
79
+
let gameobject = UnityGameObject {
77
80
name: go.name,
78
81
active: go.active,
79
82
···
83
86
};
84
87
85
88
gameobjects.push(gameobject);
86
-
// break;
89
+
break;
87
90
}
88
91
},
89
92
_ => {}
90
93
}
91
94
}
92
95
93
-
Ok(gameobjects)
96
+
let mut objs = vec![];
97
+
98
+
for go in gameobjects{
99
+
if go.active{
100
+
if let Some(mesh) = go.mesh_filter{
101
+
objs.push(BevyObject {
102
+
name: go.name,
103
+
transform: go.transform,
104
+
mesh: mesh
105
+
});
106
+
}
107
+
}
108
+
}
109
+
110
+
Ok(objs)
94
111
}
+76
-64
loader/src/util/unity_value.rs
assets/src/unity/unity_value.rs
+76
-64
loader/src/util/unity_value.rs
assets/src/unity/unity_value.rs
···
1
-
use std::{fs::File, io::Write};
1
+
use std::{fs::File, io::Write, mem};
2
2
3
3
use bevy::{asset::RenderAssetUsages, math::{Quat, Vec3}, mesh::{Indices, PrimitiveTopology}, prelude::*};
4
4
use unity_asset::UnityValue;
···
26
26
)
27
27
}
28
28
29
-
fn get_channel_dtype( format: u8 ) -> String{
30
-
match format{
31
-
0 => "f", // kVertexFormatFloat
32
-
// 1 => "e", // kVertexFormatFloat16
33
-
2 => "B", // kVertexFormatUNorm8
34
-
3 => "b", // kVertexFormatSNorm8
35
-
4 => "H", // kVertexFormatUNorm16
36
-
5 => "h", // kVertexFormatSNorm16
37
-
6 => "B", // kVertexFormatUInt8
38
-
7 => "b", // kVertexFormatSInt8
39
-
8 => "H", // kVertexFormatUInt16
40
-
9 => "h", // kVertexFormatSInt16
41
-
10 => "I", // kVertexFormatUInt32
42
-
11 => "i", // kVertexFormatSInt32
43
-
44
-
_ => ""
45
-
}.into()
46
-
}
47
-
48
29
fn get_channel_component_size( format: u8 ) -> usize{
49
30
match format{
50
31
0 => 4, // kVertexFormatFloat
51
-
// 1 => 2, // kVertexFormatFloat16
32
+
1 => 2, // kVertexFormatFloat16
52
33
2 => 1, // kVertexFormatUNorm8
53
34
3 => 1, // kVertexFormatSNorm8
54
35
4 => 2, // kVertexFormatUNorm16
···
66
47
67
48
enum UnityDataTypeArray{
68
49
kVertexFormatFloat(Vec<Vec<f32>>),
69
-
// kVertexFormatFloat16(Vec<Vec<f16>>),
50
+
kVertexFormatFloat16(Vec<Vec<f32>>),
70
51
kVertexFormatUNorm8(Vec<Vec<u8>>),
71
52
kVertexFormatSNorm8(Vec<Vec<i8>>),
72
53
kVertexFormatUNorm16(Vec<Vec<u16>>),
···
121
102
UnityDataTypeArray::kVertexFormatFloat(decoded)
122
103
},
123
104
105
+
1 => {
106
+
let mut decoded: Vec<Vec<_>> = vec![];
107
+
let item_size = get_channel_component_size(component_dtype);
108
+
let vec_size = item_size * dimension;
109
+
110
+
for i in 0..( bytes.len() / vec_size ){
111
+
let indx = i * vec_size;
112
+
let mut vec = vec![0.0; dimension];
113
+
114
+
for j in 0..dimension{
115
+
vec[j] = f32::from_le_bytes([
116
+
bytes[indx + (j * item_size)],
117
+
bytes[indx + (j * item_size) + 1],
118
+
0, 0
119
+
]);
120
+
}
121
+
decoded.push(vec);
122
+
}
123
+
124
+
UnityDataTypeArray::kVertexFormatFloat16(decoded)
125
+
},
126
+
124
127
2 => {
125
128
let mut decoded: Vec<Vec<u8>> = vec![];
126
129
let item_size = get_channel_component_size(component_dtype);
···
334
337
let mesh = mesh_parser.parse_from_unity_object(&mesh_obj).unwrap().mesh;
335
338
let vertex_data = mesh.vertex_data;
336
339
340
+
dbg!(&vertex_data.channels);
341
+
337
342
let mut streams = vec![];
338
-
let stream_count = 1 + vertex_data.channels.iter().map(|x| x.stream).max()?;
343
+
let stream_count = 1 + vertex_data.channels.iter().map(|x| x.stream).max()? as usize;
339
344
340
345
let mut offset = 0;
341
346
···
345
350
346
351
let mut i = 0;
347
352
for channel in &vertex_data.channels{
348
-
if channel.stream == s && channel.dimension > 0{
353
+
if channel.stream == s as u8 && channel.dimension > 0{
349
354
chn_mask |= 1 << i;
350
355
351
356
let component_size = get_channel_component_size(channel.format);
352
-
stride += (channel.dimension & 0xF) as usize * component_size;
357
+
stride += channel.dimension as usize * component_size;
353
358
}
354
359
355
-
streams.push(StreamInfo {
356
-
channel_mask: chn_mask,
357
-
offset,
358
-
stride
359
-
});
360
-
361
-
offset += vertex_data.vertex_count as usize * stride;
362
-
offset = ( offset + ( 16 - 1 ) ) & !(16 - 1);
363
-
364
360
i += 1;
365
361
}
362
+
363
+
streams.push(StreamInfo {
364
+
channel_mask: chn_mask,
365
+
offset,
366
+
stride
367
+
});
368
+
369
+
offset += vertex_data.vertex_count as usize * stride;
370
+
offset = ( offset + ( 16 - 1 ) ) & !(16 - 1);
366
371
}
367
372
368
373
let mut i = 0;
···
371
376
372
377
if stream.channel_mask >> i & 1 == 1{
373
378
let component_byte_size = get_channel_component_size(channel.format);
374
-
let channel_dimension = (channel.dimension & 0xF) as usize;
379
+
dbg!(&component_byte_size, &channel.format);
380
+
let channel_dimension = channel.dimension as usize;
375
381
376
382
let mut bytes =
377
383
vec![0; vertex_data.vertex_count as usize * channel_dimension * component_byte_size];
378
384
379
-
dbg!(vertex_data.vertex_count);
380
-
381
-
let vertex_base_offset = stream.offset + channel.offset as usize;
382
385
for v in 0..vertex_data.vertex_count{
383
-
let vertex_offset = vertex_base_offset + stream.stride * v as usize;
386
+
let vertex_offset = stream.offset + channel.offset as usize + stream.stride * v as usize;
384
387
385
388
for d in 0..channel_dimension{
386
-
let vertex_data_src = vertex_offset + component_byte_size * d as usize;
387
-
let component_data_src = component_byte_size * ( v as usize * channel_dimension + d as usize );
389
+
let component_offset = vertex_offset + component_byte_size * d as usize;
390
+
let dst_offset = component_byte_size * (v as usize * channel.dimension as usize + d as usize);
388
391
389
-
let buff = vertex_data.data_size[vertex_data_src..vertex_data_src + component_byte_size].to_vec();
390
-
bytes.splice(component_data_src..component_data_src + component_byte_size, buff);
392
+
let slice = &vertex_data.data_size[component_offset..component_offset + component_byte_size];
393
+
bytes[dst_offset..dst_offset + component_byte_size].clone_from_slice(slice);
391
394
}
392
395
}
393
396
···
409
412
let mut triangles = vec![];
410
413
if mesh.index_buffer.len() > 0{
411
414
for submesh in mesh.sub_meshes{
412
-
let first_index = submesh.first_byte / 4;
413
-
let triangle_count = submesh.index_count / 6;
414
-
415
-
for i in 0..triangle_count{
416
-
let indx = i * 6;
417
-
418
-
triangles.push(u16::from_le_bytes([
419
-
mesh.index_buffer[(first_index + indx) as usize],
420
-
mesh.index_buffer[(first_index + indx + 1) as usize]
421
-
]));
422
-
423
-
triangles.push(u16::from_le_bytes([
424
-
mesh.index_buffer[(first_index + indx + 2) as usize],
425
-
mesh.index_buffer[(first_index + indx + 3) as usize]
426
-
]));
427
-
428
-
triangles.push(u16::from_le_bytes([
429
-
mesh.index_buffer[(first_index + indx + 4) as usize],
430
-
mesh.index_buffer[(first_index + indx + 5) as usize]
431
-
]));
415
+
let first_index = submesh.first_byte / 2;
416
+
417
+
match submesh.topology{
418
+
0 => {
419
+
// for i in (0..submesh.index_count).step_by(3){
420
+
// triangles.push(mesh.index_buffer[(first_index + i) as usize] as u16);
421
+
// triangles.push(mesh.index_buffer[(first_index + i + 1) as usize] as u16);
422
+
// triangles.push(mesh.index_buffer[(first_index + i + 2) as usize] as u16);
423
+
// }
424
+
425
+
for i in (0..submesh.index_count).step_by(6){
426
+
triangles.push(u16::from_le_bytes([
427
+
mesh.index_buffer[(first_index + i) as usize],
428
+
mesh.index_buffer[(first_index + i + 1) as usize]
429
+
]));
430
+
431
+
triangles.push(u16::from_le_bytes([
432
+
mesh.index_buffer[(first_index + i + 2) as usize],
433
+
mesh.index_buffer[(first_index + i + 3) as usize]
434
+
]));
435
+
436
+
triangles.push(u16::from_le_bytes([
437
+
mesh.index_buffer[(first_index + i + 4) as usize],
438
+
mesh.index_buffer[(first_index + i + 5) as usize]
439
+
]));
440
+
}
441
+
},
442
+
// TODO: Implement other topologys
443
+
_ => {}
432
444
}
433
445
}
434
446
} else{
···
446
458
447
459
for i in 0..(triangles.len() / 3){
448
460
let indx = i * 3;
449
-
writeln!(file, "f {} {} {}", triangles[indx], triangles[indx + 1], triangles[indx + 2]).unwrap();
461
+
writeln!(file, "f {} {} {}", triangles[indx] + 1, triangles[indx + 1] + 1, triangles[indx + 2] + 1).unwrap();
450
462
}
451
463
452
464
Some(Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
+1
-1
client/Cargo.toml
+1
-1
client/Cargo.toml
···
10
10
dotenvy = "0.15.7"
11
11
felix-net = { path = '../net' }
12
12
felix-audio = { path = '../audio' }
13
-
felix-loader = { path = '../loader' }
13
+
felix-assets = { path = '../assets' }
14
14
tokio = { version = "1.48.0", features = ["full"] }
15
15
bevy_mod_openxr = "0.4.0"
16
16
openxr = "0.19.0"
+6
-8
client/src/setup.rs
+6
-8
client/src/setup.rs
···
45
45
FelixAudioListener
46
46
));
47
47
48
-
let gos = felix_loader::load("bundle").unwrap();
48
+
let gos = felix_assets::load("test.flx").unwrap();
49
49
for go in gos{
50
-
if let Some(mesh) = go.mesh_filter{
51
-
commands.spawn((
52
-
Mesh3d(meshes.add(mesh)),
53
-
MeshMaterial3d(materials.add(Color::WHITE)),
54
-
go.transform
55
-
));
56
-
}
50
+
commands.spawn((
51
+
Mesh3d(meshes.add(go.mesh)),
52
+
MeshMaterial3d(materials.add(Color::WHITE)),
53
+
go.transform
54
+
));
57
55
}
58
56
}
-8
loader/src/lib.rs
-8
loader/src/lib.rs
-1
loader/src/util/mod.rs
-1
loader/src/util/mod.rs
···
1
-
pub mod unity_value;