@@ -10,15 +10,13 @@ mod config;
1010pub use self :: config:: { LevelConfig , TerrainConfig } ;
1111
1212pub type TerrainType = u8 ;
13- pub const NUM_TERRAINS : usize = 8 ;
1413
1514pub type Altitude = u8 ;
1615pub type Delta = Altitude ;
1716pub const DOUBLE_LEVEL : u8 = 1 << 6 ;
1817pub const DELTA_SHIFT0 : u8 = 2 + 3 ;
1918pub const DELTA_SHIFT1 : u8 = 0 + 3 ;
2019pub const DELTA_MASK : u8 = 0x3 ;
21- pub const TERRAIN_SHIFT : u8 = 3 ;
2220pub const HEIGHT_SCALE : u32 = 128 ;
2321
2422pub struct Level {
@@ -28,11 +26,36 @@ pub struct Level {
2826 pub height : Vec < u8 > ,
2927 pub meta : Vec < u8 > ,
3028 pub palette : [ [ u8 ; 4 ] ; 0x100 ] ,
31- pub terrains : [ TerrainConfig ; NUM_TERRAINS ] ,
29+ pub terrains : Box < [ TerrainConfig ] > ,
3230}
3331
3432pub struct Point ( pub Altitude , pub TerrainType ) ;
3533
34+ pub struct TerrainBits {
35+ pub shift : u8 ,
36+ pub mask : TerrainType ,
37+ }
38+
39+ impl TerrainBits {
40+ pub fn new ( count : u8 ) -> Self {
41+ match count {
42+ 8 => TerrainBits {
43+ shift : 3 ,
44+ mask : 0x7 ,
45+ } ,
46+ 16 => TerrainBits {
47+ shift : 2 ,
48+ mask : 0xF ,
49+ } ,
50+ other => panic ! ( "Unexpected terrain count {}!" , other) ,
51+ }
52+ }
53+
54+ pub fn read ( & self , meta : u8 ) -> TerrainType {
55+ ( meta >> self . shift ) & self . mask
56+ }
57+ }
58+
3659pub enum Texel {
3760 Single ( Point ) ,
3861 Dual {
@@ -65,24 +88,12 @@ impl Level {
6588 height : vec ! [ 0 , 0 ] ,
6689 meta : vec ! [ 0 , 0 ] ,
6790 palette : [ [ 0xFF ; 4 ] ; 0x100 ] ,
68- // not pretty, I know
69- terrains : [
70- tc. clone ( ) ,
71- tc. clone ( ) ,
72- tc. clone ( ) ,
73- tc. clone ( ) ,
74- tc. clone ( ) ,
75- tc. clone ( ) ,
76- tc. clone ( ) ,
77- tc. clone ( ) ,
78- ] ,
91+ terrains : ( 0 ..8 ) . map ( |_| tc. clone ( ) ) . collect ( ) ,
7992 }
8093 }
8194
8295 pub fn get ( & self , mut coord : ( i32 , i32 ) ) -> Texel {
83- fn get_terrain ( meta : u8 ) -> TerrainType {
84- ( meta >> TERRAIN_SHIFT ) & ( NUM_TERRAINS as u8 - 1 )
85- }
96+ let bits = TerrainBits :: new ( self . terrains . len ( ) as u8 ) ;
8697 while coord. 0 < 0 {
8798 coord. 0 += self . size . 0 ;
8899 }
@@ -97,12 +108,12 @@ impl Level {
97108 let d0 = ( meta0 & DELTA_MASK ) << DELTA_SHIFT0 ;
98109 let d1 = ( meta1 & DELTA_MASK ) << DELTA_SHIFT1 ;
99110 Texel :: Dual {
100- low : Point ( self . height [ i & !1 ] , get_terrain ( meta0) ) ,
101- high : Point ( self . height [ i | 1 ] , get_terrain ( meta1) ) ,
111+ low : Point ( self . height [ i & !1 ] , bits . read ( meta0) ) ,
112+ high : Point ( self . height [ i | 1 ] , bits . read ( meta1) ) ,
102113 delta : d0 + d1,
103114 }
104115 } else {
105- Texel :: Single ( Point ( self . height [ i] , get_terrain ( meta) ) )
116+ Texel :: Single ( Point ( self . height [ i] , bits . read ( meta) ) )
106117 }
107118 }
108119
@@ -281,7 +292,7 @@ impl LevelData {
281292 } ) ;
282293 }
283294
284- pub fn import ( data : & [ u8 ] , size : ( i32 , i32 ) ) -> Self {
295+ pub fn import ( data : & [ u8 ] , size : ( i32 , i32 ) , terrain_shift : u8 ) -> Self {
285296 let total = ( size. 0 * size. 1 ) as usize ;
286297 assert_eq ! ( data. len( ) , total * 4 ) ;
287298 let mut level = LevelData {
@@ -300,15 +311,15 @@ impl LevelData {
300311 // average between two texels
301312 let mat = avg ( color[ 3 ] , color[ 7 ] ) ;
302313 level. meta [ i + 0 ] =
303- DOUBLE_LEVEL | ( ( mat & 0xF ) << TERRAIN_SHIFT ) | ( delta >> 2 ) ;
314+ DOUBLE_LEVEL | ( ( mat & 0xF ) << terrain_shift ) | ( delta >> 2 ) ;
304315 level. meta [ i + 1 ] =
305- DOUBLE_LEVEL | ( ( mat >> 4 ) << TERRAIN_SHIFT ) | ( delta & DELTA_MASK ) ;
316+ DOUBLE_LEVEL | ( ( mat >> 4 ) << terrain_shift ) | ( delta & DELTA_MASK ) ;
306317 level. height [ i + 0 ] = avg ( color[ 0 ] , color[ 4 ] ) ;
307318 level. height [ i + 1 ] = avg ( color[ 1 ] , color[ 5 ] ) ;
308319 } else {
309320 // average between low and high
310- level. meta [ i + 0 ] = ( color[ 3 ] & 0xF ) << TERRAIN_SHIFT ;
311- level. meta [ i + 1 ] = ( color[ 7 ] & 0xF ) << TERRAIN_SHIFT ;
321+ level. meta [ i + 0 ] = ( color[ 3 ] & 0xF ) << terrain_shift ;
322+ level. meta [ i + 1 ] = ( color[ 7 ] & 0xF ) << terrain_shift ;
312323 level. height [ i + 0 ] = avg ( color[ 0 ] , color[ 1 ] ) ;
313324 level. height [ i + 1 ] = avg ( color[ 4 ] , color[ 5 ] ) ;
314325 }
0 commit comments