+229
Cargo.lock
+229
Cargo.lock
···
104
104
]
105
105
106
106
[[package]]
107
+
name = "alloc-no-stdlib"
108
+
version = "2.0.4"
109
+
source = "registry+https://github.com/rust-lang/crates.io-index"
110
+
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
111
+
112
+
[[package]]
113
+
name = "alloc-stdlib"
114
+
version = "0.2.2"
115
+
source = "registry+https://github.com/rust-lang/crates.io-index"
116
+
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
117
+
dependencies = [
118
+
"alloc-no-stdlib",
119
+
]
120
+
121
+
[[package]]
107
122
name = "alsa"
108
123
version = "0.9.1"
109
124
source = "registry+https://github.com/rust-lang/crates.io-index"
···
181
196
dependencies = [
182
197
"num-traits",
183
198
]
199
+
200
+
[[package]]
201
+
name = "array-init"
202
+
version = "2.1.0"
203
+
source = "registry+https://github.com/rust-lang/crates.io-index"
204
+
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
184
205
185
206
[[package]]
186
207
name = "arrayref"
···
1597
1618
]
1598
1619
1599
1620
[[package]]
1621
+
name = "binrw"
1622
+
version = "0.15.0"
1623
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1624
+
checksum = "81419ff39e6ed10a92a7f125290859776ced35d9a08a665ae40b23e7ca702f30"
1625
+
dependencies = [
1626
+
"array-init",
1627
+
"binrw_derive",
1628
+
"bytemuck",
1629
+
]
1630
+
1631
+
[[package]]
1632
+
name = "binrw_derive"
1633
+
version = "0.15.0"
1634
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1635
+
checksum = "376404e55ec40d0d6f8b4b7df3f87b87954bd987f0cf9a7207ea3b6ea5c9add4"
1636
+
dependencies = [
1637
+
"either",
1638
+
"owo-colors",
1639
+
"proc-macro2",
1640
+
"quote",
1641
+
"syn",
1642
+
]
1643
+
1644
+
[[package]]
1600
1645
name = "bit-set"
1601
1646
version = "0.8.0"
1602
1647
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1678
1723
]
1679
1724
1680
1725
[[package]]
1726
+
name = "brotli"
1727
+
version = "3.5.0"
1728
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1729
+
checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
1730
+
dependencies = [
1731
+
"alloc-no-stdlib",
1732
+
"alloc-stdlib",
1733
+
"brotli-decompressor",
1734
+
]
1735
+
1736
+
[[package]]
1737
+
name = "brotli-decompressor"
1738
+
version = "2.5.1"
1739
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1740
+
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
1741
+
dependencies = [
1742
+
"alloc-no-stdlib",
1743
+
"alloc-stdlib",
1744
+
]
1745
+
1746
+
[[package]]
1681
1747
name = "bumpalo"
1682
1748
version = "3.19.1"
1683
1749
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2060
2126
]
2061
2127
2062
2128
[[package]]
2129
+
name = "crc"
2130
+
version = "3.4.0"
2131
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2132
+
checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
2133
+
dependencies = [
2134
+
"crc-catalog",
2135
+
]
2136
+
2137
+
[[package]]
2138
+
name = "crc-catalog"
2139
+
version = "2.4.0"
2140
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2141
+
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
2142
+
2143
+
[[package]]
2063
2144
name = "crc32fast"
2064
2145
version = "1.5.0"
2065
2146
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2371
2452
"cpal 0.16.0",
2372
2453
"dotenvy",
2373
2454
"felix-audio",
2455
+
"felix-loader",
2374
2456
"felix-net",
2375
2457
"openxr",
2376
2458
"tokio",
2377
2459
]
2378
2460
2379
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
+
[[package]]
2380
2473
name = "felix-net"
2381
2474
version = "0.1.0"
2382
2475
dependencies = [
···
3130
3223
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
3131
3224
3132
3225
[[package]]
3226
+
name = "lz4_flex"
3227
+
version = "0.12.0"
3228
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3229
+
checksum = "ab6473172471198271ff72e9379150e9dfd70d8e533e0752a27e515b48dd375e"
3230
+
dependencies = [
3231
+
"twox-hash",
3232
+
]
3233
+
3234
+
[[package]]
3235
+
name = "lzma-rs"
3236
+
version = "0.3.0"
3237
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3238
+
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
3239
+
dependencies = [
3240
+
"byteorder",
3241
+
"crc",
3242
+
]
3243
+
3244
+
[[package]]
3133
3245
name = "mach2"
3134
3246
version = "0.4.3"
3135
3247
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3403
3515
]
3404
3516
3405
3517
[[package]]
3518
+
name = "num_cpus"
3519
+
version = "1.17.0"
3520
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3521
+
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
3522
+
dependencies = [
3523
+
"hermit-abi",
3524
+
"libc",
3525
+
]
3526
+
3527
+
[[package]]
3406
3528
name = "num_enum"
3407
3529
version = "0.7.5"
3408
3530
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3819
3941
dependencies = [
3820
3942
"ttf-parser 0.25.1",
3821
3943
]
3944
+
3945
+
[[package]]
3946
+
name = "owo-colors"
3947
+
version = "4.2.3"
3948
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3949
+
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
3822
3950
3823
3951
[[package]]
3824
3952
name = "parking"
···
4400
4528
]
4401
4529
4402
4530
[[package]]
4531
+
name = "serde_bytes"
4532
+
version = "0.11.19"
4533
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4534
+
checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
4535
+
dependencies = [
4536
+
"serde",
4537
+
"serde_core",
4538
+
]
4539
+
4540
+
[[package]]
4403
4541
name = "serde_core"
4404
4542
version = "1.0.228"
4405
4543
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4433
4571
]
4434
4572
4435
4573
[[package]]
4574
+
name = "serde_yaml"
4575
+
version = "0.9.34+deprecated"
4576
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4577
+
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
4578
+
dependencies = [
4579
+
"indexmap",
4580
+
"itoa",
4581
+
"ryu",
4582
+
"serde",
4583
+
"unsafe-libyaml",
4584
+
]
4585
+
4586
+
[[package]]
4436
4587
name = "sharded-slab"
4437
4588
version = "0.1.7"
4438
4589
source = "registry+https://github.com/rust-lang/crates.io-index"
···
5110
5261
version = "0.2.6"
5111
5262
source = "registry+https://github.com/rust-lang/crates.io-index"
5112
5263
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
5264
+
5265
+
[[package]]
5266
+
name = "unity-asset"
5267
+
version = "0.2.0"
5268
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5269
+
checksum = "6705b95fda449527055ff77fe5cff49f774dde7335ed92bc3d048fc74066ebaf"
5270
+
dependencies = [
5271
+
"unity-asset-binary",
5272
+
"unity-asset-core",
5273
+
"unity-asset-yaml",
5274
+
]
5275
+
5276
+
[[package]]
5277
+
name = "unity-asset-binary"
5278
+
version = "0.2.0"
5279
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5280
+
checksum = "d739d1414c1732be1035417f83b1e60f234c7d5eb8abda0ee70d178a58137cb7"
5281
+
dependencies = [
5282
+
"binrw",
5283
+
"brotli",
5284
+
"byteorder",
5285
+
"flate2",
5286
+
"indexmap",
5287
+
"lz4_flex",
5288
+
"lzma-rs",
5289
+
"memmap2",
5290
+
"num_cpus",
5291
+
"once_cell",
5292
+
"regex",
5293
+
"serde",
5294
+
"serde_json",
5295
+
"thiserror 2.0.17",
5296
+
"unity-asset-core",
5297
+
]
5298
+
5299
+
[[package]]
5300
+
name = "unity-asset-core"
5301
+
version = "0.2.0"
5302
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5303
+
checksum = "12903fd47e122b5e7e335fc9cb5540bb35ab0ffe5bb57a7741a8c7be8d361361"
5304
+
dependencies = [
5305
+
"indexmap",
5306
+
"lazy_static",
5307
+
"serde",
5308
+
"serde_bytes",
5309
+
"thiserror 2.0.17",
5310
+
]
5311
+
5312
+
[[package]]
5313
+
name = "unity-asset-decode"
5314
+
version = "0.2.0"
5315
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5316
+
checksum = "9ea6e630cdefde54a88ca4fbae54cf3d3e5ba527fac96b085562da3b3834b77b"
5317
+
dependencies = [
5318
+
"indexmap",
5319
+
"serde",
5320
+
"unity-asset-binary",
5321
+
"unity-asset-core",
5322
+
]
5323
+
5324
+
[[package]]
5325
+
name = "unity-asset-yaml"
5326
+
version = "0.2.0"
5327
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5328
+
checksum = "b991e340c27b1578e657defee9f57de867d853b8f40448fb079d0ee3a5ebc77e"
5329
+
dependencies = [
5330
+
"indexmap",
5331
+
"serde",
5332
+
"serde_yaml",
5333
+
"thiserror 2.0.17",
5334
+
"unity-asset-core",
5335
+
]
5336
+
5337
+
[[package]]
5338
+
name = "unsafe-libyaml"
5339
+
version = "0.2.11"
5340
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5341
+
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
5113
5342
5114
5343
[[package]]
5115
5344
name = "uuid"
+4
-1
Cargo.toml
+4
-1
Cargo.toml
+1
-6
audio/src/source/static_source.rs
+1
-6
audio/src/source/static_source.rs
···
1
1
use std::{sync::{Arc, Mutex}, thread};
2
2
3
3
use bevy::transform::components::Transform;
4
-
use kira::{Decibels, Easing, Mapping, Mix, Tween, Value, effect::{filter::FilterBuilder, reverb::ReverbBuilder}, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
4
+
use kira::{Decibels, Easing, Mapping, Tween, Value, effect::{filter::FilterBuilder}, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
5
5
6
6
use crate::{FelixAudioComponent, source::AudioSource};
7
7
···
52
52
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
53
53
input_range: ( 0.0, 20.0 ),
54
54
output_range: ( 18000.0, 2000.0 ),
55
-
easing: Easing::Linear
56
-
})))
57
-
.with_effect(ReverbBuilder::new().mix(Value::FromListenerDistance(Mapping {
58
-
input_range: ( 0.0, 100.0 ),
59
-
output_range: ( Mix::DRY, Mix::WET ),
60
55
easing: Easing::Linear
61
56
})))
62
57
.with_send(&send_track, Value::FromListenerDistance(Mapping {
+1
-6
audio/src/source/stream_source.rs
+1
-6
audio/src/source/stream_source.rs
···
1
1
use bevy::transform::components::Transform;
2
-
use kira::{Decibels, Easing, Mapping, Mix, Tween, Value, effect::{filter::FilterBuilder, reverb::ReverbBuilder}, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
2
+
use kira::{Decibels, Easing, Mapping, Tween, Value, effect::{filter::FilterBuilder}, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}};
3
3
4
4
use crate::{FelixAudioComponent, source::{AudioSource, stream_source::sound_data::StreamAudioSourceSoundData}};
5
5
···
44
44
.with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping {
45
45
input_range: ( 0.0, 20.0 ),
46
46
output_range: ( 18000.0, 2000.0 ),
47
-
easing: Easing::Linear
48
-
})))
49
-
.with_effect(ReverbBuilder::new().mix(Value::FromListenerDistance(Mapping {
50
-
input_range: ( 0.0, 100.0 ),
51
-
output_range: ( Mix::DRY, Mix::WET ),
52
47
easing: Easing::Linear
53
48
})))
54
49
.with_send(&send_track, Value::FromListenerDistance(Mapping {
+1
-1
audio/src/voice/decoder.rs
+1
-1
audio/src/voice/decoder.rs
···
26
26
27
27
let mut total = 0.0;
28
28
for sample in buffer{ total += sample.powi(2) }
29
-
*set_rms.write().unwrap() = ( total / buffer.len() as f32 ).sqrt();
29
+
*set_rms.write().unwrap() = 20.0 * ( total / buffer.len() as f32 ).sqrt().log10();
30
30
31
31
let mut voice = queue.lock().unwrap();
32
32
for sample in buffer{ voice.push_back(sample); }
+34
-22
audio/src/voice/microphone.rs
+34
-22
audio/src/voice/microphone.rs
···
1
-
use std::{env, net::{ToSocketAddrs, UdpSocket}, sync::{Arc, Mutex, RwLock}};
1
+
use std::{env, net::{SocketAddr, UdpSocket}, sync::{Arc, Mutex, RwLock}};
2
2
3
3
use bevy::ecs::component::Component;
4
4
use cpal::{BufferSize, SampleRate, Stream, StreamConfig, traits::{DeviceTrait, HostTrait, StreamTrait}};
···
10
10
#[derive(Component)]
11
11
pub struct VoiceChatMicrophone{
12
12
stream: Option<Stream>,
13
-
udp: Option<UdpSocket>,
13
+
addr: SocketAddr,
14
+
udp: UdpSocket,
14
15
muted: Arc<Mutex<bool>>,
15
-
last_rms: Arc<RwLock<isize>>
16
+
last_rms: Arc<RwLock<f32>>,
17
+
gate_level: Arc<RwLock<f32>>
16
18
}
17
19
18
20
impl VoiceChatMicrophone{
19
-
pub fn new( socket: UdpSocket ) -> Self{
21
+
pub fn new( addr: SocketAddr, socket: UdpSocket ) -> Self{
20
22
Self {
21
23
stream: None,
22
-
udp: Some(socket),
24
+
addr,
25
+
udp: socket,
23
26
muted: Arc::new(Mutex::new(false)), // TODO: Default to muted
24
-
last_rms: Arc::new(RwLock::new(0))
27
+
last_rms: Arc::new(RwLock::new(0.0)),
28
+
gate_level: Arc::new(RwLock::new(-65.0))
25
29
}
26
30
}
27
31
···
58
62
let mut buffer = [0; MONO_20MS];
59
63
60
64
let muted = self.muted.clone();
61
-
let udp = self.udp.take().unwrap();
62
65
63
-
let addr = env::var("HOST")?.to_socket_addrs()?.nth(0).unwrap();
66
+
let udp = self.udp.try_clone().unwrap();
67
+
let addr = self.addr.clone();
64
68
65
69
for conf in mic.supported_input_configs().unwrap(){
66
70
println!("{} {:?} {} {:?}", conf.channels(), conf.buffer_size(), conf.sample_format(), conf.with_max_sample_rate());
67
71
}
68
72
69
73
let set_rms = self.last_rms.clone();
74
+
let gate_level = self.gate_level.clone();
70
75
71
76
let stream = mic.build_input_stream(
72
77
&StreamConfig {
···
81
86
buffer_indx = 0;
82
87
} else{
83
88
for i in 0..data.len(){
84
-
if i % 2 == 0{ continue; }
89
+
if i % 2 == 1{ continue; }
85
90
86
91
buffer[buffer_indx] = data[i];
87
92
buffer_indx += 1;
···
89
94
if buffer_indx >= MONO_20MS{
90
95
buffer_indx = 0;
91
96
92
-
let mut total = 0;
93
-
for sample in buffer{ total += (sample as isize).pow(2) }
94
-
*set_rms.write().unwrap() = ( total / buffer.len() as isize ).isqrt();
97
+
let mut total = 0.0;
98
+
for sample in buffer{ total += (sample as f32).powi(2) }
95
99
96
-
let len = encoder.encode(&buffer, &mut output).unwrap();
97
-
let buf_to_send = output[0..len].to_vec();
100
+
let rms = 20.0 * ( ( total / buffer.len() as f32 ).sqrt() / i16::MAX as f32 ).log10();
101
+
*set_rms.write().unwrap() = rms;
98
102
99
-
let packet = PlayerVoicePacket {
100
-
id: "".into(), // NOTE: I know this kinda seems stupid but it's easier for me to get the player id on the server so imma just make the server fill this in.
101
-
packet: buf_to_send
102
-
};
103
+
if rms > *gate_level.read().unwrap(){
104
+
let len = encoder.encode(&buffer, &mut output).unwrap();
105
+
let buf_to_send = output[0..len].to_vec();
103
106
104
-
let packet: Vec<u8> = packet.to_buf().into();
105
-
udp.send_to(&packet, addr).unwrap();
107
+
let packet = PlayerVoicePacket {
108
+
id: "".into(), // NOTE: I know this kinda seems stupid but it's easier for me to get the player id on the server so imma just make the server fill this in.
109
+
packet: buf_to_send
110
+
};
111
+
112
+
let packet: Vec<u8> = packet.to_buf().into();
113
+
udp.send_to(&packet, addr).unwrap();
114
+
}
106
115
}
107
116
}
108
117
}
···
117
126
Ok(())
118
127
}
119
128
120
-
pub fn get_rms_of_last_packet( &self ) -> f32{
121
-
*self.last_rms.read().unwrap() as f32 / i16::MAX as f32
129
+
pub fn get_rms_of_last_packet( &self ) -> ( f32, bool ){
130
+
let rms = *self.last_rms.read().unwrap();
131
+
let gate = *self.gate_level.read().unwrap();
132
+
133
+
( rms, rms > gate )
122
134
}
123
135
}
+3
-3
audio/src/voice/mod.rs
+3
-3
audio/src/voice/mod.rs
···
1
-
use std::net::UdpSocket;
1
+
use std::net::{SocketAddr, UdpSocket};
2
2
3
3
use crate::voice::microphone::VoiceChatMicrophone;
4
4
5
5
pub mod decoder;
6
6
pub mod microphone;
7
7
8
-
pub fn init_microphone( socket: UdpSocket ) -> anyhow::Result<VoiceChatMicrophone>{
9
-
let mut handle = VoiceChatMicrophone::new(socket);
8
+
pub fn init_microphone( addr: SocketAddr, socket: UdpSocket ) -> anyhow::Result<VoiceChatMicrophone>{
9
+
let mut handle = VoiceChatMicrophone::new(addr, socket);
10
10
handle.start_stream()?;
11
11
12
12
Ok(handle)
+1
client/Cargo.toml
+1
client/Cargo.toml
+11
-6
client/src/components/debug_camera.rs
+11
-6
client/src/components/debug_camera.rs
···
78
78
79
79
let mut remote_rms = "".to_owned();
80
80
for id in net_manager.get_remote_player_voice_ids(){
81
-
remote_rms += format!("{}: {:.4}\n", id, net_manager.get_remote_player_voice_rms(&id)).as_str();
81
+
remote_rms += format!(
82
+
"{}: {:.4}db\n",
83
+
id,
84
+
net_manager.get_remote_player_voice_rms(&id)
85
+
).as_str();
82
86
}
83
87
84
-
let rms = if let Ok(mic) = voice.single(){
88
+
let ( rms, mic_open ) = if let Ok(mic) = voice.single(){
85
89
mic.get_rms_of_last_packet()
86
90
} else{
87
-
-1.0
91
+
( -1.0, false )
88
92
};
89
93
90
94
let ( mut text, _ ) = debug_text.single_mut().unwrap();
91
95
text.0 = format!(
92
-
"Microphone RMS: {:.4}
93
-
{}Position: {:.2} {:.2} {:.2}
94
-
Rotation: {:.2} {:.2} {:.2} {:.2}
96
+
"Microphone RMS: {:.4}db Open: {}
97
+
{}Position: X: {:.2} Y: {:.2} Z: {:.2}
98
+
Rotation: X: {:.2} Y: {:.2} Z: {:.2} W: {:.2}
95
99
XR State: {:#?}",
96
100
rms,
101
+
mic_open,
97
102
98
103
remote_rms,
99
104
+6
-2
client/src/main.rs
+6
-2
client/src/main.rs
···
1
+
use std::{env, net::ToSocketAddrs};
2
+
1
3
use bevy::{app::{App, FixedUpdate, Startup, Update}, ecs::system::Commands, prelude::*, render::pipelined_rendering::PipelinedRenderingPlugin};
2
4
use bevy_mod_openxr::{add_xr_plugins, resources::OxrSessionConfig};
3
5
use bevy_mod_xr::session::{XrSessionCreated, XrSessionPlugin};
···
33
35
.add_systems(XrSessionCreated, || { println!("[INFO] Started VR") })
34
36
.add_systems(Startup, setup)
35
37
.add_systems(Startup, move | mut commands: Commands |{
36
-
let ( comp, voice ) = net::handle_net().expect("Network Module Failed");
38
+
let addr = env::var("HOST").unwrap().to_socket_addrs().unwrap().nth(0).unwrap();
39
+
40
+
let ( comp, voice ) = net::handle_net(addr.clone()).expect("Network Module Failed");
37
41
commands.spawn(comp);
38
42
39
-
match voice::init_microphone(voice){
43
+
match voice::init_microphone(addr, voice){
40
44
Ok(voice) => { commands.spawn(voice); },
41
45
Err(err) => println!("[WARN] Failed to start microphone: {}", err)
42
46
}
+1
-1
client/src/net/connection.rs
+1
-1
client/src/net/connection.rs
+2
-4
client/src/net/mod.rs
+2
-4
client/src/net/mod.rs
···
1
-
use std::{env, net::{TcpStream, ToSocketAddrs, UdpSocket}};
1
+
use std::net::{SocketAddr, TcpStream, UdpSocket};
2
2
3
3
use bevy::prelude::*;
4
4
use felix_net::packet::PacketTypes;
···
14
14
RecvPacket(PacketTypes)
15
15
}
16
16
17
-
pub fn handle_net() -> anyhow::Result<( Connection, UdpSocket )>{
18
-
let addr = env::var("HOST")?.to_socket_addrs()?.nth(0).unwrap();
19
-
17
+
pub fn handle_net( addr: SocketAddr ) -> anyhow::Result<( Connection, UdpSocket )>{
20
18
let tcp = TcpStream::connect(addr)?;
21
19
let udp = UdpSocket::bind("0.0.0.0:0")?;
22
20
+31
-20
client/src/setup.rs
+31
-20
client/src/setup.rs
···
14
14
15
15
// TODO: UI and Menus
16
16
17
-
commands.spawn((
18
-
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
19
-
MeshMaterial3d(materials.add(Color::WHITE)),
20
-
Transform::from_xyz(5.0, 0.0, 0.0),
21
-
));
17
+
// commands.spawn((
18
+
// Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
19
+
// MeshMaterial3d(materials.add(Color::WHITE)),
20
+
// Transform::from_xyz(5.0, 0.0, 0.0),
21
+
// ));
22
22
23
-
commands.spawn((
24
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
25
-
MeshMaterial3d(materials.add(Color::WHITE)),
26
-
Transform::from_xyz(-5.0, 0.0, 0.0)
27
-
));
23
+
// commands.spawn((
24
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
25
+
// MeshMaterial3d(materials.add(Color::WHITE)),
26
+
// Transform::from_xyz(-5.0, 0.0, 0.0)
27
+
// ));
28
28
29
-
commands.spawn((
30
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
31
-
MeshMaterial3d(materials.add(Color::WHITE)),
32
-
Transform::from_xyz(0.0, 0.0, 5.0)
33
-
));
29
+
// commands.spawn((
30
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
31
+
// MeshMaterial3d(materials.add(Color::WHITE)),
32
+
// Transform::from_xyz(0.0, 0.0, 5.0)
33
+
// ));
34
34
35
-
commands.spawn((
36
-
Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
37
-
MeshMaterial3d(materials.add(Color::WHITE)),
38
-
Transform::from_xyz(0.0, 0.0, -5.0)
39
-
));
35
+
// commands.spawn((
36
+
// Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))),
37
+
// MeshMaterial3d(materials.add(Color::WHITE)),
38
+
// Transform::from_xyz(0.0, 0.0, -5.0)
39
+
// ));
40
40
41
41
commands.spawn((
42
42
DebugCamera::default(), // TODO: Build a proper player controller
···
44
44
Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
45
45
FelixAudioListener
46
46
));
47
+
48
+
let gos = felix_loader::load("bundle").unwrap();
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
+
}
57
+
}
47
58
}
+11
loader/Cargo.toml
+11
loader/Cargo.toml
+8
loader/src/lib.rs
+8
loader/src/lib.rs
+22
loader/src/unity/component/mesh_renderer.rs
+22
loader/src/unity/component/mesh_renderer.rs
···
1
+
use unity_asset_binary::object::UnityObject;
2
+
3
+
use crate::unity::component::Component;
4
+
5
+
#[derive(Debug)]
6
+
pub struct MeshRenderer{
7
+
8
+
}
9
+
10
+
impl Component for MeshRenderer{
11
+
12
+
}
13
+
14
+
impl From<UnityObject> for MeshRenderer{
15
+
fn from(value: UnityObject) -> Self {
16
+
// dbg!(value.property_names());
17
+
18
+
Self {
19
+
20
+
}
21
+
}
22
+
}
+6
loader/src/unity/component/mod.rs
+6
loader/src/unity/component/mod.rs
+16
loader/src/unity/component/transform.rs
+16
loader/src/unity/component/transform.rs
···
1
+
use bevy::transform::components::Transform;
2
+
use unity_asset_binary::object::UnityObject;
3
+
4
+
use crate::util::unity_value::{unity_value_to_quat, unity_value_to_vec3};
5
+
6
+
pub fn into_bevy_transform(value: UnityObject) -> Transform {
7
+
let position = value.get("m_LocalPosition").unwrap();
8
+
let rotation = value.get("m_LocalRotation").unwrap();
9
+
let scale = value.get("m_LocalScale").unwrap();
10
+
11
+
Transform {
12
+
translation: unity_value_to_vec3(position),
13
+
rotation: unity_value_to_quat(rotation),
14
+
scale: unity_value_to_vec3(scale)
15
+
}
16
+
}
+94
loader/src/unity/mod.rs
+94
loader/src/unity/mod.rs
···
1
+
use anyhow::bail;
2
+
use bevy::{prelude::*, transform::components::Transform};
3
+
use unity_asset::environment::{Environment, EnvironmentObjectRef};
4
+
use unity_asset_binary::unity_version::UnityVersion;
5
+
use unity_asset_decode::mesh::MeshParser;
6
+
7
+
use crate::{unity::component::{Component, mesh_renderer::MeshRenderer, transform::into_bevy_transform}, util};
8
+
9
+
mod component;
10
+
11
+
#[derive(Debug)]
12
+
pub struct GameObject{
13
+
pub name: String,
14
+
pub active: bool,
15
+
16
+
pub transform: Transform,
17
+
pub mesh_renderer: Option<MeshRenderer>,
18
+
pub mesh_filter: Option<Mesh>,
19
+
}
20
+
21
+
pub fn load( path: &'static str ) -> anyhow::Result<Vec<GameObject>>{
22
+
let mesh_parser = MeshParser::new(UnityVersion::parse_version("2020.3.12f1").unwrap());
23
+
24
+
let mut env = Environment::new();
25
+
env.load(path)?;
26
+
27
+
let mut gameobjects = vec![];
28
+
29
+
for obj in env.objects(){
30
+
match obj{
31
+
EnvironmentObjectRef::Binary(v) => {
32
+
if v.object.class_id() == 1{
33
+
let obj = v.object.read()?;
34
+
let go = obj.as_gameobject().unwrap();
35
+
36
+
let mut components: Vec<Box<dyn Component>> = vec![];
37
+
38
+
let mut transform = None;
39
+
let mut mesh_renderer = None;
40
+
let mut mesh_filter = None;
41
+
42
+
let comps = obj.get("m_Component").unwrap().as_array().unwrap();
43
+
44
+
for comp in comps{
45
+
let obj = comp.as_object().unwrap().get("component").unwrap();
46
+
let path_id = obj.as_object().unwrap().get("m_PathID").unwrap().as_i64().unwrap();
47
+
48
+
let comp = env.find_binary_object(path_id).unwrap();
49
+
let comp = comp.read().unwrap();
50
+
51
+
match comp.class_id(){
52
+
4 => transform = Some(into_bevy_transform(comp)), // Normal Transform
53
+
224 => transform = Some(into_bevy_transform(comp)), // Rect Transform (gonna just treat it as normal)
54
+
55
+
23 => mesh_renderer = Some(MeshRenderer::from(comp)),
56
+
33 => {
57
+
let mesh = comp.get("m_Mesh").unwrap();
58
+
let path_id = mesh.as_object().unwrap().get("m_PathID").unwrap().as_i64().unwrap();
59
+
60
+
let mesh = env.find_binary_object(path_id).unwrap();
61
+
let mesh_obj = mesh.read().unwrap();
62
+
63
+
if let Some(mesh) = util::unity_value::try_unity_mesh_to_bevy(mesh_obj, &mesh_parser){
64
+
mesh_filter = Some(mesh);
65
+
} else{
66
+
println!("[WARN] Failed to load mesh for: {}", go.name);
67
+
}
68
+
},
69
+
70
+
_ => {}
71
+
}
72
+
}
73
+
74
+
if transform.is_none(){ bail!("Cannot find transform for object {}", go.name); }
75
+
76
+
let gameobject = GameObject {
77
+
name: go.name,
78
+
active: go.active,
79
+
80
+
transform: transform.unwrap(),
81
+
mesh_renderer,
82
+
mesh_filter
83
+
};
84
+
85
+
gameobjects.push(gameobject);
86
+
// break;
87
+
}
88
+
},
89
+
_ => {}
90
+
}
91
+
}
92
+
93
+
Ok(gameobjects)
94
+
}
+1
loader/src/util/mod.rs
+1
loader/src/util/mod.rs
···
1
+
pub mod unity_value;
+455
loader/src/util/unity_value.rs
+455
loader/src/util/unity_value.rs
···
1
+
use std::{fs::File, io::Write};
2
+
3
+
use bevy::{asset::RenderAssetUsages, math::{Quat, Vec3}, mesh::{Indices, PrimitiveTopology}, prelude::*};
4
+
use unity_asset::UnityValue;
5
+
use unity_asset_binary::object::UnityObject;
6
+
use unity_asset_decode::mesh::MeshParser;
7
+
8
+
pub fn unity_value_to_vec3( val: &UnityValue ) -> Vec3{
9
+
let obj = val.as_object().unwrap();
10
+
11
+
Vec3 {
12
+
x: obj.get("x").unwrap().as_f64().unwrap() as f32,
13
+
y: obj.get("y").unwrap().as_f64().unwrap() as f32,
14
+
z: obj.get("z").unwrap().as_f64().unwrap() as f32
15
+
}
16
+
}
17
+
18
+
pub fn unity_value_to_quat( val: &UnityValue ) -> Quat{
19
+
let obj = val.as_object().unwrap();
20
+
21
+
Quat::from_xyzw(
22
+
obj.get("x").unwrap().as_f64().unwrap() as f32,
23
+
obj.get("y").unwrap().as_f64().unwrap() as f32,
24
+
obj.get("z").unwrap().as_f64().unwrap() as f32,
25
+
obj.get("w").unwrap().as_f64().unwrap() as f32
26
+
)
27
+
}
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
+
fn get_channel_component_size( format: u8 ) -> usize{
49
+
match format{
50
+
0 => 4, // kVertexFormatFloat
51
+
// 1 => 2, // kVertexFormatFloat16
52
+
2 => 1, // kVertexFormatUNorm8
53
+
3 => 1, // kVertexFormatSNorm8
54
+
4 => 2, // kVertexFormatUNorm16
55
+
5 => 2, // kVertexFormatSNorm16
56
+
6 => 1, // kVertexFormatUInt8
57
+
7 => 1, // kVertexFormatSInt8
58
+
8 => 2, // kVertexFormatUInt16
59
+
9 => 2, // kVertexFormatSInt16
60
+
10 => 4, // kVertexFormatUInt32
61
+
11 => 4, // kVertexFormatSInt32
62
+
63
+
_ => 0
64
+
}
65
+
}
66
+
67
+
enum UnityDataTypeArray{
68
+
kVertexFormatFloat(Vec<Vec<f32>>),
69
+
// kVertexFormatFloat16(Vec<Vec<f16>>),
70
+
kVertexFormatUNorm8(Vec<Vec<u8>>),
71
+
kVertexFormatSNorm8(Vec<Vec<i8>>),
72
+
kVertexFormatUNorm16(Vec<Vec<u16>>),
73
+
kVertexFormatSNorm16(Vec<Vec<i16>>),
74
+
kVertexFormatUInt8(Vec<Vec<u8>>),
75
+
kVertexFormatSInt8(Vec<Vec<i8>>),
76
+
kVertexFormatUInt16(Vec<Vec<u16>>),
77
+
kVertexFormatSInt16(Vec<Vec<i16>>),
78
+
kVertexFormatUInt32(Vec<Vec<u32>>),
79
+
kVertexFormatSInt32(Vec<Vec<i32>>),
80
+
Unknown
81
+
}
82
+
83
+
impl UnityDataTypeArray{
84
+
pub fn as_vec3_array( &self ) -> Vec<Vec3>{
85
+
if let Self::kVertexFormatFloat(array) = self{
86
+
let mut vecs = vec![];
87
+
88
+
for val in array{
89
+
vecs.push(Vec3 { x: val[0], y: val[1], z: val[2] });
90
+
}
91
+
92
+
vecs
93
+
} else{
94
+
panic!("Not a float array");
95
+
}
96
+
}
97
+
}
98
+
99
+
fn unpack_struct( dimension: usize, component_dtype: u8, bytes: Vec<u8> ) -> UnityDataTypeArray{
100
+
match component_dtype{
101
+
0 => {
102
+
let mut decoded: Vec<Vec<_>> = vec![];
103
+
let item_size = get_channel_component_size(component_dtype);
104
+
let vec_size = item_size * dimension;
105
+
106
+
for i in 0..( bytes.len() / vec_size ){
107
+
let indx = i * vec_size;
108
+
let mut vec = vec![0.0; dimension];
109
+
110
+
for j in 0..dimension{
111
+
vec[j] = f32::from_le_bytes([
112
+
bytes[indx + (j * item_size)],
113
+
bytes[indx + (j * item_size) + 1],
114
+
bytes[indx + (j * item_size) + 2],
115
+
bytes[indx + (j * item_size) + 3]
116
+
]);
117
+
}
118
+
decoded.push(vec);
119
+
}
120
+
121
+
UnityDataTypeArray::kVertexFormatFloat(decoded)
122
+
},
123
+
124
+
2 => {
125
+
let mut decoded: Vec<Vec<u8>> = vec![];
126
+
let item_size = get_channel_component_size(component_dtype);
127
+
let vec_size = item_size * dimension;
128
+
129
+
for i in 0..( bytes.len() / vec_size ){
130
+
let indx = i * vec_size;
131
+
let mut vec = vec![0; vec_size];
132
+
133
+
for j in 0..vec_size{ vec[j] = u8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
134
+
decoded.push(vec);
135
+
}
136
+
137
+
UnityDataTypeArray::kVertexFormatUNorm8(decoded)
138
+
},
139
+
140
+
3 => {
141
+
let mut decoded: Vec<Vec<_>> = vec![];
142
+
let item_size = get_channel_component_size(component_dtype);
143
+
let vec_size = item_size * dimension;
144
+
145
+
for i in 0..( bytes.len() / vec_size ){
146
+
let indx = i * vec_size;
147
+
let mut vec = vec![0; vec_size];
148
+
149
+
for j in 0..vec_size{ vec[j] = i8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
150
+
decoded.push(vec);
151
+
}
152
+
153
+
UnityDataTypeArray::kVertexFormatSNorm8(decoded)
154
+
},
155
+
156
+
4 => {
157
+
let mut decoded: Vec<Vec<_>> = vec![];
158
+
let item_size = get_channel_component_size(component_dtype);
159
+
let vec_size = item_size * dimension;
160
+
161
+
for i in 0..( bytes.len() / vec_size ){
162
+
let indx = i * vec_size;
163
+
let mut vec = vec![0; vec_size];
164
+
165
+
for j in 0..vec_size{
166
+
vec[j] = u16::from_le_bytes([
167
+
bytes[indx + (j * item_size)],
168
+
bytes[indx + (j * item_size) + 1]
169
+
]);
170
+
}
171
+
decoded.push(vec);
172
+
}
173
+
174
+
UnityDataTypeArray::kVertexFormatUNorm16(decoded)
175
+
},
176
+
177
+
5 => {
178
+
let mut decoded: Vec<Vec<_>> = vec![];
179
+
let item_size = get_channel_component_size(component_dtype);
180
+
let vec_size = item_size * dimension;
181
+
182
+
for i in 0..( bytes.len() / vec_size ){
183
+
let indx = i * vec_size;
184
+
let mut vec = vec![0; vec_size];
185
+
186
+
for j in 0..vec_size{
187
+
vec[j] = i16::from_le_bytes([
188
+
bytes[indx + (j * item_size)],
189
+
bytes[indx + (j * item_size) + 1]
190
+
]);
191
+
}
192
+
decoded.push(vec);
193
+
}
194
+
195
+
UnityDataTypeArray::kVertexFormatSNorm16(decoded)
196
+
},
197
+
198
+
6 => {
199
+
let mut decoded: Vec<Vec<u8>> = vec![];
200
+
let item_size = get_channel_component_size(component_dtype);
201
+
let vec_size = item_size * dimension;
202
+
203
+
for i in 0..( bytes.len() / vec_size ){
204
+
let indx = i * vec_size;
205
+
let mut vec = vec![0; vec_size];
206
+
207
+
for j in 0..vec_size{ vec[j] = u8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
208
+
decoded.push(vec);
209
+
}
210
+
211
+
UnityDataTypeArray::kVertexFormatUInt8(decoded)
212
+
},
213
+
214
+
7 => {
215
+
let mut decoded: Vec<Vec<_>> = vec![];
216
+
let item_size = get_channel_component_size(component_dtype);
217
+
let vec_size = item_size * dimension;
218
+
219
+
for i in 0..( bytes.len() / vec_size ){
220
+
let indx = i * vec_size;
221
+
let mut vec = vec![0; vec_size];
222
+
223
+
for j in 0..vec_size{ vec[j] = i8::from_le_bytes([ bytes[indx + (j * item_size)] ]); }
224
+
decoded.push(vec);
225
+
}
226
+
227
+
UnityDataTypeArray::kVertexFormatSInt8(decoded)
228
+
},
229
+
230
+
8 => {
231
+
let mut decoded: Vec<Vec<_>> = vec![];
232
+
let item_size = get_channel_component_size(component_dtype);
233
+
let vec_size = item_size * dimension;
234
+
235
+
for i in 0..( bytes.len() / vec_size ){
236
+
let indx = i * vec_size;
237
+
let mut vec = vec![0; vec_size];
238
+
239
+
for j in 0..vec_size{
240
+
vec[j] = u16::from_le_bytes([
241
+
bytes[indx + (j * item_size)],
242
+
bytes[indx + (j * item_size) + 1]
243
+
]);
244
+
}
245
+
decoded.push(vec);
246
+
}
247
+
248
+
UnityDataTypeArray::kVertexFormatUInt16(decoded)
249
+
},
250
+
251
+
9 => {
252
+
let mut decoded: Vec<Vec<_>> = vec![];
253
+
let item_size = get_channel_component_size(component_dtype);
254
+
let vec_size = item_size * dimension;
255
+
256
+
for i in 0..( bytes.len() / vec_size ){
257
+
let indx = i * vec_size;
258
+
let mut vec = vec![0; vec_size];
259
+
260
+
for j in 0..vec_size{
261
+
vec[j] = i16::from_le_bytes([
262
+
bytes[indx + (j * item_size)],
263
+
bytes[indx + (j * item_size) + 1]
264
+
]);
265
+
}
266
+
decoded.push(vec);
267
+
}
268
+
269
+
UnityDataTypeArray::kVertexFormatSInt16(decoded)
270
+
},
271
+
272
+
10 => {
273
+
let mut decoded: Vec<Vec<_>> = vec![];
274
+
let item_size = get_channel_component_size(component_dtype);
275
+
let vec_size = item_size * dimension;
276
+
277
+
for i in 0..( bytes.len() / vec_size ){
278
+
let indx = i * vec_size;
279
+
let mut vec = vec![0; vec_size];
280
+
281
+
for j in 0..vec_size{
282
+
vec[j] = u32::from_le_bytes([
283
+
bytes[indx + (j * item_size)],
284
+
bytes[indx + (j * item_size) + 1],
285
+
bytes[indx + (j * item_size) + 2],
286
+
bytes[indx + (j * item_size) + 3]
287
+
]);
288
+
}
289
+
decoded.push(vec);
290
+
}
291
+
292
+
UnityDataTypeArray::kVertexFormatUInt32(decoded)
293
+
},
294
+
295
+
11 => {
296
+
let mut decoded: Vec<Vec<_>> = vec![];
297
+
let item_size = get_channel_component_size(component_dtype);
298
+
let vec_size = item_size * dimension;
299
+
300
+
for i in 0..( bytes.len() / vec_size ){
301
+
let indx = i * vec_size;
302
+
let mut vec = vec![0; vec_size];
303
+
304
+
for j in 0..vec_size{
305
+
vec[j] = i32::from_le_bytes([
306
+
bytes[indx + (j * item_size)],
307
+
bytes[indx + (j * item_size) + 1],
308
+
bytes[indx + (j * item_size) + 2],
309
+
bytes[indx + (j * item_size) + 3]
310
+
]);
311
+
}
312
+
decoded.push(vec);
313
+
}
314
+
315
+
UnityDataTypeArray::kVertexFormatSInt32(decoded)
316
+
},
317
+
318
+
_ => { UnityDataTypeArray::Unknown }
319
+
}
320
+
}
321
+
322
+
struct StreamInfo{
323
+
channel_mask: usize,
324
+
offset: usize,
325
+
stride: usize
326
+
}
327
+
328
+
pub fn try_unity_mesh_to_bevy( mesh_obj: UnityObject, mesh_parser: &MeshParser ) -> Option<Mesh>{
329
+
let mut vertices = None;
330
+
let mut normals = None;
331
+
let mut tangents = None;
332
+
let mut uv0 = None;
333
+
334
+
let mesh = mesh_parser.parse_from_unity_object(&mesh_obj).unwrap().mesh;
335
+
let vertex_data = mesh.vertex_data;
336
+
337
+
let mut streams = vec![];
338
+
let stream_count = 1 + vertex_data.channels.iter().map(|x| x.stream).max()?;
339
+
340
+
let mut offset = 0;
341
+
342
+
for s in 0..stream_count{
343
+
let mut chn_mask = 0;
344
+
let mut stride = 0;
345
+
346
+
let mut i = 0;
347
+
for channel in &vertex_data.channels{
348
+
if channel.stream == s && channel.dimension > 0{
349
+
chn_mask |= 1 << i;
350
+
351
+
let component_size = get_channel_component_size(channel.format);
352
+
stride += (channel.dimension & 0xF) as usize * component_size;
353
+
}
354
+
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
+
i += 1;
365
+
}
366
+
}
367
+
368
+
let mut i = 0;
369
+
for channel in vertex_data.channels{
370
+
let stream = &streams[channel.stream as usize];
371
+
372
+
if stream.channel_mask >> i & 1 == 1{
373
+
let component_byte_size = get_channel_component_size(channel.format);
374
+
let channel_dimension = (channel.dimension & 0xF) as usize;
375
+
376
+
let mut bytes =
377
+
vec![0; vertex_data.vertex_count as usize * channel_dimension * component_byte_size];
378
+
379
+
dbg!(vertex_data.vertex_count);
380
+
381
+
let vertex_base_offset = stream.offset + channel.offset as usize;
382
+
for v in 0..vertex_data.vertex_count{
383
+
let vertex_offset = vertex_base_offset + stream.stride * v as usize;
384
+
385
+
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 );
388
+
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);
391
+
}
392
+
}
393
+
394
+
let component_data = unpack_struct(channel_dimension, channel.format, bytes);
395
+
396
+
match i{
397
+
0 => vertices = Some(component_data),
398
+
1 => normals = Some(component_data),
399
+
2 => tangents = Some(component_data),
400
+
4 => uv0 = Some(component_data),
401
+
402
+
_ => {}
403
+
}
404
+
}
405
+
406
+
i += 1;
407
+
}
408
+
409
+
let mut triangles = vec![];
410
+
if mesh.index_buffer.len() > 0{
411
+
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
+
]));
432
+
}
433
+
}
434
+
} else{
435
+
return None;
436
+
}
437
+
438
+
if vertices.is_none(){ panic!("Cannot parse vertices") }
439
+
let vertices = vertices.unwrap().as_vec3_array();
440
+
441
+
let mut file = File::create("test.obj").unwrap();
442
+
443
+
for vec in &vertices{
444
+
writeln!(file, "v {} {} {}", vec.x, vec.y, vec.z).unwrap();
445
+
}
446
+
447
+
for i in 0..(triangles.len() / 3){
448
+
let indx = i * 3;
449
+
writeln!(file, "f {} {} {}", triangles[indx], triangles[indx + 1], triangles[indx + 2]).unwrap();
450
+
}
451
+
452
+
Some(Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD)
453
+
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
454
+
.with_inserted_indices(Indices::U16(triangles)))
455
+
}