@@ -84,6 +84,12 @@ pub enum AquiferSampler {
8484 Aquifer ( WorldAquiferSampler ) ,
8585}
8686
87+ macro_rules! packed_position_index {
88+ ( $local_x: expr, $local_y: expr, $local_z: expr, $dim_y: expr, $dim_z: expr) => {
89+ ( $local_x * $dim_z + $local_z) * $dim_y + $local_y
90+ } ;
91+ }
92+
8793macro_rules! local_xz {
8894 ( $xz: expr) => {
8995 floor_div( $xz, 16 )
@@ -100,10 +106,10 @@ pub struct WorldAquiferSampler {
100106 random_deriver : RandomDeriver ,
101107 fluid_level : FluidLevelSampler ,
102108 start_x : i32 ,
103- size_x : u64 ,
104109 start_y : i8 ,
105110 start_z : i32 ,
106- size_z : u64 ,
111+ size_y : usize ,
112+ size_z : usize ,
107113 levels : Box < [ Option < FluidLevel > ] > ,
108114 packed_positions : Box < [ i64 ] > ,
109115}
@@ -135,19 +141,19 @@ impl WorldAquiferSampler {
135141 ) -> Self {
136142 let start_x = local_xz ! ( chunk_pos:: start_block_x( & chunk_pos) ) - 1 ;
137143 let end_x = local_xz ! ( chunk_pos:: end_block_x( & chunk_pos) ) + 1 ;
138- let size_x = ( end_x - start_x) as u64 + 1 ;
144+ let size_x = ( end_x - start_x) as usize + 1 ;
139145
140146 let start_y = local_y ! ( minimum_y) - 1 ;
141147 let end_y = local_y ! ( minimum_y as i32 + height as i32 ) + 1 ;
142- let size_y = ( end_y - start_y as i32 ) as u64 + 1 ;
148+ let size_y = ( end_y - start_y as i32 ) as usize + 1 ;
143149
144150 let start_z = local_xz ! ( chunk_pos:: start_block_z( & chunk_pos) ) - 1 ;
145151 let end_z = local_xz ! ( chunk_pos:: end_block_z( & chunk_pos) ) + 1 ;
146- let size_z = ( end_z - start_z) as u64 + 1 ;
152+ let size_z = ( end_z - start_z) as usize + 1 ;
147153
148154 let cache_size = size_x * size_y * size_z;
149155
150- let mut packed_positions = vec ! [ 0 ; cache_size as usize ] ;
156+ let mut packed_positions = vec ! [ 0 ; cache_size] ;
151157
152158 for offset_x in 0 ..size_x {
153159 for offset_y in 0 ..size_y {
@@ -161,7 +167,8 @@ impl WorldAquiferSampler {
161167 let rand_y = y * 12 + random. next_bounded_i32 ( 9 ) ;
162168 let rand_z = z * 16 + random. next_bounded_i32 ( 10 ) ;
163169
164- let index = ( offset_y * size_z + offset_z) * size_x + offset_x;
170+ let index =
171+ packed_position_index ! ( offset_x, offset_y, offset_z, size_y, size_z) ;
165172 packed_positions[ index as usize ] =
166173 block_pos:: packed ( & Vector3 :: new ( rand_x, rand_y, rand_z) ) ;
167174 }
@@ -172,22 +179,54 @@ impl WorldAquiferSampler {
172179 random_deriver,
173180 fluid_level,
174181 start_x,
175- size_x,
176182 start_y,
177183 start_z,
184+ size_y,
178185 size_z,
179186 levels : vec ! [ None ; cache_size as usize ] . into ( ) ,
180187 packed_positions : packed_positions. into ( ) ,
181188 }
182189 }
183190
184- #[ inline]
185- fn index ( & self , x : i32 , y : i32 , z : i32 ) -> usize {
186- let i = ( x - self . start_x ) as u64 ;
187- let j = ( y - self . start_y as i32 ) as u64 ;
188- let k = ( z - self . start_z ) as u64 ;
191+ fn packed_position_index ( & self , x : i32 , y : i32 , z : i32 ) -> usize {
192+ let local_x = ( x - self . start_x ) as usize ;
193+ let local_y = ( y - self . start_y as i32 ) as usize ;
194+ let local_z = ( z - self . start_z ) as usize ;
195+
196+ packed_position_index ! ( local_x, local_y, local_z, self . size_y, self . size_z)
197+ }
189198
190- ( ( j * self . size_z + k) * self . size_x + i) as usize
199+ fn random_positions_for_pos ( & self , x : i32 , y : i32 , z : i32 ) -> [ i64 ; 12 ] {
200+ // (x, y - 1, z) to (x + 1, y + 1, z + 1)
201+ // y values are contiguous in packed array:
202+ // ($local_x * $dim_z + $local_z) * $dim_y + $local_y
203+
204+ // (x, y - 1, z)
205+ let x_0_z_0 = self . packed_position_index ( x, y - 1 , z) ;
206+
207+ // (x, y - 1, z + 1)
208+ let x_0_z_1 = x_0_z_0 + self . size_y ;
209+
210+ // (x + 1, y - 1, z)
211+ let x_1_z_0 = x_0_z_0 + self . size_y * self . size_z ;
212+
213+ // (x + 1, y - 1, z + 1)
214+ let x_1_z_1 = x_1_z_0 + self . size_y ;
215+
216+ [
217+ self . packed_positions [ x_0_z_0] ,
218+ self . packed_positions [ x_0_z_1] ,
219+ self . packed_positions [ x_1_z_0] ,
220+ self . packed_positions [ x_1_z_1] ,
221+ self . packed_positions [ x_0_z_0 + 1 ] ,
222+ self . packed_positions [ x_0_z_1 + 1 ] ,
223+ self . packed_positions [ x_1_z_0 + 1 ] ,
224+ self . packed_positions [ x_1_z_1 + 1 ] ,
225+ self . packed_positions [ x_0_z_0 + 2 ] ,
226+ self . packed_positions [ x_0_z_1 + 2 ] ,
227+ self . packed_positions [ x_1_z_0 + 2 ] ,
228+ self . packed_positions [ x_1_z_1 + 2 ] ,
229+ ]
191230 }
192231
193232 #[ inline]
@@ -197,8 +236,10 @@ impl WorldAquiferSampler {
197236
198237 fn calculate_density (
199238 & mut self ,
239+ barrier_sample : & mut Option < f64 > ,
200240 pos : & impl NoisePos ,
201- barrier_sample : f64 ,
241+ router : & mut ChunkNoiseRouter ,
242+ sample_options : & ChunkNoiseFunctionSampleOptions ,
202243 level_1 : FluidLevel ,
203244 level_2 : FluidLevel ,
204245 ) -> f64 {
@@ -226,7 +267,7 @@ impl WorldAquiferSampler {
226267 } ;
227268
228269 let r = if ( -2f64 ..=2f64 ) . contains ( & q) {
229- barrier_sample
270+ * barrier_sample. get_or_insert_with ( || router . barrier_noise ( pos , sample_options ) )
230271 } else {
231272 0f64
232273 } ;
@@ -253,7 +294,7 @@ impl WorldAquiferSampler {
253294 let local_y = local_y ! ( y) ;
254295 let local_z = local_xz ! ( z) ;
255296
256- let index = self . index ( local_x, local_y, local_z) ;
297+ let index = self . packed_position_index ( local_x, local_y, local_z) ;
257298 if let Some ( level) = & self . levels [ index] {
258299 level. clone ( )
259300 } else {
@@ -445,55 +486,45 @@ impl WorldAquiferSampler {
445486 if density > 0f64 {
446487 None
447488 } else {
448- let i = pos. x ( ) ;
449- let j = pos. y ( ) ;
450- let k = pos. z ( ) ;
451-
452- let fluid_level = self . fluid_level . get_fluid_level ( i, j, k) ;
453- if fluid_level. get_block ( j) == & LAVA_BLOCK {
489+ let sample_x = pos. x ( ) ;
490+ let sample_y = pos. y ( ) ;
491+ let sample_z = pos. z ( ) ;
492+
493+ let fluid_level = self
494+ . fluid_level
495+ . get_fluid_level ( sample_x, sample_y, sample_z) ;
496+ if fluid_level. get_block ( sample_y) == & LAVA_BLOCK {
454497 Some ( LAVA_BLOCK . default_state )
455498 } else {
456- let scaled_x = floor_div ( i - 5 , 16 ) ;
457- let scaled_y = floor_div ( j + 1 , 12 ) ;
458- let scaled_z = floor_div ( k - 5 , 16 ) ;
499+ let scaled_x = local_xz ! ( sample_x - 5 ) ;
500+ let scaled_y = local_y ! ( sample_y + 1 ) ;
501+ let scaled_z = local_xz ! ( sample_z - 5 ) ;
459502
460503 // The 3 closest positions, closest to furthest
461504 let mut packed_block_and_hypots = [ ( 0 , i32:: MAX ) ; 3 ] ;
462- for offset_y in -1 ..=1 {
463- for offset_x in 0 ..=1 {
464- for offset_z in 0 ..=1 {
465- let x_pos = scaled_x + offset_x;
466- let y_pos = scaled_y + offset_y;
467- let z_pos = scaled_z + offset_z;
468- let index = self . index ( x_pos, y_pos, z_pos) ;
469-
470- let packed_random = self . packed_positions [ index] ;
505+ for packed_random in self . random_positions_for_pos ( scaled_x, scaled_y, scaled_z) {
506+ let unpacked_x = block_pos:: unpack_x ( packed_random) ;
507+ let unpacked_y = block_pos:: unpack_y ( packed_random) ;
508+ let unpacked_z = block_pos:: unpack_z ( packed_random) ;
471509
472- let unpacked_x = block_pos :: unpack_x ( packed_random ) ;
473- let unpacked_y = block_pos :: unpack_y ( packed_random ) ;
474- let unpacked_z = block_pos :: unpack_z ( packed_random ) ;
510+ let local_x = unpacked_x - sample_x ;
511+ let local_y = unpacked_y - sample_y ;
512+ let local_z = unpacked_z - sample_z ;
475513
476- let local_x = unpacked_x - i;
477- let local_y = unpacked_y - j;
478- let local_z = unpacked_z - k;
514+ let hypot_squared = local_x * local_x + local_y * local_y + local_z * local_z;
479515
480- let hypot_squared =
481- local_x * local_x + local_y * local_y + local_z * local_z;
482-
483- if packed_block_and_hypots[ 2 ] . 1 >= hypot_squared {
484- packed_block_and_hypots[ 2 ] = ( packed_random, hypot_squared) ;
485- }
516+ if packed_block_and_hypots[ 2 ] . 1 >= hypot_squared {
517+ packed_block_and_hypots[ 2 ] = ( packed_random, hypot_squared) ;
518+ }
486519
487- if packed_block_and_hypots[ 1 ] . 1 >= hypot_squared {
488- packed_block_and_hypots[ 2 ] = packed_block_and_hypots[ 1 ] ;
489- packed_block_and_hypots[ 1 ] = ( packed_random, hypot_squared) ;
490- }
520+ if packed_block_and_hypots[ 1 ] . 1 >= hypot_squared {
521+ packed_block_and_hypots[ 2 ] = packed_block_and_hypots[ 1 ] ;
522+ packed_block_and_hypots[ 1 ] = ( packed_random, hypot_squared) ;
523+ }
491524
492- if packed_block_and_hypots[ 0 ] . 1 >= hypot_squared {
493- packed_block_and_hypots[ 1 ] = packed_block_and_hypots[ 0 ] ;
494- packed_block_and_hypots[ 0 ] = ( packed_random, hypot_squared) ;
495- }
496- }
525+ if packed_block_and_hypots[ 0 ] . 1 >= hypot_squared {
526+ packed_block_and_hypots[ 1 ] = packed_block_and_hypots[ 0 ] ;
527+ packed_block_and_hypots[ 0 ] = ( packed_random, hypot_squared) ;
497528 }
498529 }
499530
@@ -505,7 +536,7 @@ impl WorldAquiferSampler {
505536 ) ;
506537 let d =
507538 Self :: max_distance ( packed_block_and_hypots[ 0 ] . 1 , packed_block_and_hypots[ 1 ] . 1 ) ;
508- let block_state = fluid_level2. get_block ( j ) ;
539+ let block_state = fluid_level2. get_block ( sample_y ) ;
509540
510541 if d <= 0f64 {
511542 // TODO: Handle fluid tick
@@ -514,22 +545,24 @@ impl WorldAquiferSampler {
514545 } else if block_state == & WATER_BLOCK
515546 && self
516547 . fluid_level
517- . get_fluid_level ( i , j - 1 , k )
518- . get_block ( j - 1 )
548+ . get_fluid_level ( sample_x , sample_y - 1 , sample_z )
549+ . get_block ( sample_y - 1 )
519550 == & LAVA_BLOCK
520551 {
521552 Some ( block_state. default_state )
522553 } else {
523- let barrier_sample = router . barrier_noise ( pos , sample_options ) ;
554+ let mut barrier_sample = None ;
524555 let fluid_level3 = self . get_water_level (
525556 packed_block_and_hypots[ 1 ] . 0 ,
526557 router,
527558 height_estimator,
528559 sample_options,
529560 ) ;
530561 let e = d * self . calculate_density (
562+ & mut barrier_sample,
531563 pos,
532- barrier_sample,
564+ router,
565+ sample_options,
533566 fluid_level2. clone ( ) ,
534567 fluid_level3. clone ( ) ,
535568 ) ;
@@ -551,8 +584,10 @@ impl WorldAquiferSampler {
551584 let g = d
552585 * f
553586 * self . calculate_density (
587+ & mut barrier_sample,
554588 pos,
555- barrier_sample,
589+ router,
590+ sample_options,
556591 fluid_level2,
557592 fluid_level4. clone ( ) ,
558593 ) ;
@@ -569,8 +604,10 @@ impl WorldAquiferSampler {
569604 let h = d
570605 * g
571606 * self . calculate_density (
607+ & mut barrier_sample,
572608 pos,
573- barrier_sample,
609+ router,
610+ sample_options,
574611 fluid_level3,
575612 fluid_level4,
576613 ) ;
@@ -1589,9 +1626,10 @@ mod test {
15891626 let level1 = FluidLevel :: new ( h1, & WATER_BLOCK ) ;
15901627 let level2 = FluidLevel :: new ( h2, & WATER_BLOCK ) ;
15911628 let pos = UnblendedNoisePos :: new ( x, y, z) ;
1592- let sample = router. barrier_noise ( & pos, & env) ;
1629+ let mut sample = None ;
1630+
15931631 assert_eq ! (
1594- aquifer. calculate_density( & pos, sample , level1, level2) ,
1632+ aquifer. calculate_density( & mut sample , & pos, & mut router , & env , level1, level2) ,
15951633 result
15961634 ) ;
15971635 }
0 commit comments