11use crate :: * ;
22use bevy:: math:: DVec3 ;
3- use rayon:: prelude:: * ;
3+
4+ const EXTRA_FLAGS : & [ ( & str , [ ( i32 , i32 ) ; 3 ] ) ] = & [
5+ (
6+ "mp_black_water_canal" ,
7+ [ ( 0 , 0 ) , ( 0 , Contents :: WINDOW_NO_COLLIDE as i32 ) , ( 0 , 0 ) ] ,
8+ ) ,
9+ (
10+ "mp_colony02" ,
11+ [ ( 0 , 0 ) , ( 0 , Contents :: WINDOW_NO_COLLIDE as i32 ) , ( 0 , 0 ) ] ,
12+ ) ,
13+ ] ;
14+ const SHOULD_CHECK_WINDOW_NO_COLLIDE : & [ ( & str , bool ) ] = & [
15+ ( "mp_angel_city" , true ) ,
16+ ( "mp_black_water_canal" , true ) ,
17+ ( "mp_grave" , true ) ,
18+ ( "mp_colony02" , true ) ,
19+ ( "mp_complex3" , true ) ,
20+ ( "mp_crashsite3" , true ) ,
21+ ( "mp_drydock" , true ) ,
22+ ( "mp_eden" , true ) ,
23+ ( "mp_thaw" , true ) ,
24+ ( "mp_forwardbase_kodai" , true ) ,
25+ ( "mp_glitch" , true ) ,
26+ ( "mp_homestead" , true ) ,
27+ ( "mp_relic02" , true ) ,
28+ ( "mp_rise" , true ) ,
29+ ( "mp_wargames" , true ) ,
30+ ( "mp_lobby" , true ) ,
31+ ( "mp_lf_deck" , true ) ,
32+ ( "mp_lf_meadow" , true ) ,
33+ ( "mp_lf_stacks" , true ) ,
34+ ( "mp_lf_township" , true ) ,
35+ ( "mp_lf_traffic" , true ) ,
36+ ( "mp_lf_uma" , true ) ,
37+ ( "mp_coliseum" , true ) ,
38+ ( "mp_coliseum_column" , true ) ,
39+ ] ;
440
541pub fn geoset_to_meshes (
642 BSPData {
@@ -17,7 +53,19 @@ pub fn geoset_to_meshes(
1753 props,
1854 model_data,
1955 } : BSPData ,
56+ map_name : & str ,
2057) -> Vec < Mesh > {
58+ let extra_flags = EXTRA_FLAGS
59+ . iter ( )
60+ . find_map ( |( name, rest) | ( * name == map_name) . then_some ( rest) )
61+ . copied ( )
62+ . unwrap_or_default ( ) ;
63+ let should_check_window_no_collide = SHOULD_CHECK_WINDOW_NO_COLLIDE
64+ . iter ( )
65+ . find_map ( |( name, rest) | ( * name == map_name) . then_some ( rest) )
66+ . copied ( )
67+ . unwrap_or_default ( ) ;
68+
2169 geo_sets
2270 . into_iter ( )
2371 . flat_map ( |geoset| {
@@ -30,26 +78,46 @@ pub fn geoset_to_meshes(
3078 . chain ( geoset. prim_count . eq ( & 1 ) . then_some ( geoset. prim_start ) )
3179 } )
3280 . filter_map ( |primative| {
33- let flag = Contents :: SOLID as i32 | Contents :: PLAYER_CLIP as i32 ;
34- let no_flag = Contents :: WINDOW_NO_COLLIDE as i32 ;
81+ let ty =
82+ PrimitiveType :: try_from ( ( primative >> 29 ) & 0x7 ) . expect ( "invalid primative type" ) ;
83+ let ( flag, no_flag) = match ty {
84+ PrimitiveType :: Brush => (
85+ Contents :: SOLID as i32 | Contents :: PLAYER_CLIP as i32 ,
86+ Contents :: WINDOW_NO_COLLIDE as i32 ,
87+ ) ,
88+ PrimitiveType :: Tricoll => (
89+ Contents :: SOLID as i32
90+ | Contents :: PLAYER_CLIP as i32
91+ | Contents :: BULLET_CLIP as i32 ,
92+ 0 ,
93+ ) ,
94+ PrimitiveType :: Prop => ( Contents :: SOLID as i32 | Contents :: PLAYER_CLIP as i32 , 0 ) ,
95+ } ;
96+
97+ let extra_flags = extra_flags
98+ . get ( ( ty as usize ) . saturating_sub ( 1 ) )
99+ . copied ( )
100+ . unwrap_or_default ( ) ;
101+ let ( flag, no_flag) = ( flag | extra_flags. 0 , no_flag | extra_flags. 1 ) ;
102+
35103 // if it doesn't contain any
36104 if unique_contents[ primative as usize & 0xFF ] & flag == 0
37105 || unique_contents[ primative as usize & 0xFF ] & no_flag != 0
38106 {
39107 None
40108 } else {
41109 Some ( (
42- PrimitiveType :: try_from ( ( primative >> 29 ) & 0x7 )
43- . expect ( "invalid primative type" ) ,
110+ ty,
44111 ( ( primative >> 8 ) & 0x1FFFFF ) as usize ,
45112 unique_contents[ primative as usize & 0xFF ] ,
113+ unique_contents[ primative as usize & 0xFF ] ,
46114 ) )
47115 }
48116 } )
49- . collect :: < std:: collections:: HashSet < ( PrimitiveType , usize , i32 ) > > ( )
117+ . collect :: < std:: collections:: HashSet < ( PrimitiveType , usize , i32 , i32 ) > > ( )
50118 // maybe this doesn't improve anything but it's cool
51119 . into_par_iter ( )
52- . filter_map ( |( ty, index, contents) | {
120+ . filter_map ( |( ty, index, contents, flags ) | {
53121 let mut pushing_vertices: Vec < Vec3 > = Vec :: new ( ) ;
54122 let mut indices = Vec :: new ( ) ;
55123
@@ -78,6 +146,25 @@ pub fn geoset_to_meshes(
78146 ) ?,
79147 }
80148
149+ // just check if the surface is not flat which means we have a huge wall here that is marked WINDOW_NO_COLLIDE therefore it needs to be gone
150+ if should_check_window_no_collide
151+ && flags & Contents :: WINDOW_NO_COLLIDE as i32 != 0
152+ && ( pushing_vertices
153+ . iter ( )
154+ . map ( |v| v. y as i64 )
155+ . max ( )
156+ . unwrap_or_default ( )
157+ - pushing_vertices
158+ . iter ( )
159+ . map ( |v| v. y as i64 )
160+ . min ( )
161+ . unwrap_or_default ( ) )
162+ . abs ( )
163+ > 200
164+ {
165+ return None ;
166+ }
167+
81168 Some (
82169 Mesh :: new (
83170 bevy:: render:: mesh:: PrimitiveTopology :: TriangleList ,
@@ -176,31 +263,34 @@ fn prop_to_mesh(
176263 if props. len ( ) <= index {
177264 return None ;
178265 }
266+
179267 let static_prop = props[ index] ;
180- let transform = Transform :: from_translation ( static_prop. origin )
268+ let transform = Transform :: from_translation ( static_prop. origin . xzy ( ) )
181269 . with_rotation ( Quat :: from_euler (
182270 EulerRot :: XYZ ,
183- static_prop. angles . x ,
184- static_prop. angles . y ,
185- static_prop. angles . z ,
271+ static_prop. angles . x . to_radians ( ) ,
272+ static_prop. angles . y . to_radians ( ) ,
273+ static_prop. angles . z . to_radians ( ) ,
186274 ) )
187275 . with_scale ( Vec3 :: splat ( static_prop. scale ) )
188- . compute_affine ( ) ;
276+ . compute_matrix ( ) ;
189277
190278 if let Some ( model_data) = model_data
191279 . get ( static_prop. model_index as usize )
192280 . and_then ( |o| o. as_ref ( ) )
193- // .filter(|_| static_prop.solid == 1)
281+ . cloned ( )
282+ // .or_else(|| Some(ico(Sphere::new(static_prop.scale * 3.), 3)))
283+ . filter ( |_| static_prop. solid == 6 )
284+ // figure what this actually is ^ rigth vphysics stuff I rember
194285 {
195286 indices. extend ( & model_data. 1 ) ;
196287 pushing_vertices. extend (
197288 model_data
198289 . 0
199290 . iter ( )
200291 . copied ( )
201- . map ( |vert| transform. transform_point3 ( vert) ) ,
292+ . map ( |vert| transform. mul_vec4 ( vert. extend ( 1. ) ) . xyz ( ) ) ,
202293 ) ;
203- println ! ( "phys model" ) ;
204294 } else {
205295 // println!("no phys model");
206296 }
@@ -267,3 +357,32 @@ fn calculate_intersection_point(planes: [&Vec4; 3]) -> Option<DVec3> {
267357
268358 Some ( DVec3 :: new ( d. dot ( u) , m3. dot ( v) , -m2. dot ( v) ) / denom)
269359}
360+
361+ // pub fn ico(sphere: Sphere, subdivisions: u32) -> (Vec<Vec3>, Vec<u32>) {
362+ // use hexasphere::shapes::IcoSphere;
363+ // let generated = IcoSphere::new(subdivisions as usize, |point| {
364+ // let inclination = ops::acos(point.y);
365+ // let azimuth = ops::atan2(point.z, point.x);
366+
367+ // let norm_inclination = inclination / PI;
368+ // let norm_azimuth = 0.5 - (azimuth / core::f32::consts::TAU);
369+
370+ // [norm_azimuth, norm_inclination]
371+ // });
372+
373+ // let raw_points = generated.raw_points();
374+
375+ // let points = raw_points
376+ // .iter()
377+ // .map(|&p| (p * sphere.radius).into())
378+ // .map(Vec3::from_array)
379+ // .collect::<Vec<Vec3>>();
380+
381+ // let mut indices = Vec::with_capacity(generated.indices_per_main_triangle() * 20);
382+
383+ // for i in 0..20 {
384+ // generated.get_indices(i, &mut indices);
385+ // }
386+
387+ // (points, indices)
388+ // }
0 commit comments