public void DecompressVoxelData( byte[] data, ushort[] result )
		{
			BitStream stream;
			ushort DataBytes;
			DataBytes = BitConverter.ToUInt16( data, 0 );
			if( DataBytes > 20 )
			{
				MemoryStream initial_stream = new MemoryStream( data );
				initial_stream.Seek( 2, SeekOrigin.Begin );
				byte[] uncompressed_data = new byte[DataBytes];
				GZipStream gz_stream = new GZipStream( initial_stream, CompressionMode.Decompress );
				gz_stream.Read( uncompressed_data, 0, DataBytes );
				stream = new BitStream( uncompressed_data );
			}
			else
			{
				stream = new BitStream( data );
				stream.Seek( 16 ); // seek by bit position
			}
			List<ushort> types = new List<ushort>();

			byte bits;
			uint TypeCount;
			stream.Read( 8, out bits );
			stream.Read( bits, out TypeCount );
			TypeCount++; // always at least one.
			int n;
			for( n = 0; n < TypeCount; n++ )
			{
				ushort val;
				stream.Read( 16, out val );
				types.Add( val );
			}

			int outpos = 0;
			do
			{
				ushort vox;
				uint val;
				uint count;
				stream.Read( 1, out val );
				if( val == 0 )
				{
					stream.Read( bits, out val );
					vox = types[(int)val];
					result[outpos++] = vox;
				}
				else
				{
					uint count_tmp;
					stream.Read( 6, out count_tmp );
					count = count_tmp & 0x1F;
					if( ( count_tmp & 0x20 ) != 0 )
					{
						count <<= 5;
						stream.Read( 6, out count_tmp );
						count |= count_tmp & 0x1F;
						if( ( count_tmp & 0x20 ) != 0 )
						{
							count <<= 5;
							stream.Read( 6, out count_tmp );
							count |= count_tmp & 0x1F;
						}
					}
					count += 2;
					//stream.Read( 16, out count );
					//Log.log( "Read count {0}", count );
					stream.Read( bits, out val );
					vox = types[(int)val];
					for( n = 0; n < count; n++ )
						result[outpos++] = vox;
				}

			} while( outpos < 32768 );

		}
		void WriteCubes( BitStream stream, int bits, uint count, uint index )
		{
			// 1 count 2 bits = 3   vs 9
			// 1 count 3 bits = 4   vs 10
			// 1 count  4 bits  = 5     vs 11
			// 1 count  5 bits  = 6     vs 12
			// 1 count  6 bits  = 7     vs 13
			// 1 count  7 bits  = 8     vs 14

			// 2 count 2 bits = 6   vs 9
			// 2 count 3 bits = 8   vs 10
			// 2 count  4 bits  = 10    vs 11
			// 2 count  5 bits  = 12    vs 12
			// 2 count  6 bits  = 14    vs 13
			// 2 count  7 bits  = 16    vs 14

			// 3 count 2 bits = 9   vs 9
			// 3 count 3 bits = 12  vs 10
			// 3 count  4 bits  = 15    vs 11
			// 3 count  5 bits  = 18    vs 12
			// 3 count  6 bits  = 21    vs 13
			// 3 count  7 bits  = 24    vs 14


			if( ( (bits +1) * count ) <= ( 7 + bits ) )
			{
				for( int n = 0; n < count; n++ )
				{
					stream.Write( 0, 1 );
					stream.Write( index, bits );
				}
			}
			else
			{
				stream.Write( 1, 1 );
				//Log.log( "Write count {0}", count );
				/*
				if( ( count & 0x8000 ) != 0 )
				{
					stream.Write( ( ( count >> 15 ) & 0x1F ) | 0x20, 7 );
					stream.Write( ( ( count >> 10 ) & 0x1F ) | 0x20, 7 );
					stream.Write( ( ( count >> 5 ) & 0x1F ) | 0x20, 7 );
					stream.Write( ( ( count  ) & 0x1F ), 7 );
				}
				else */
				count -= 2; // always at least 1, and then this value always starts at atleast 2; and very small delta sets can be 3, but typically 2.
				if( ( count & 0xFC00 ) != 0 )
				{
					stream.Write( ( ( count >> 10 ) & 0x1F ) | 0x20, 6 );
					stream.Write( ( ( count >> 5 ) & 0x1F ) | 0x20, 6 );
					stream.Write( ( ( count ) & 0x1F ), 6 );
				}
				else if( ( count & 0xFFE0 ) != 0 )
				{
					stream.Write( ( ( count >> 5 ) & 0x1F ) | 0x20, 6 );
					stream.Write( ( ( count ) & 0x1F ) , 6 );
				}
				else
				{
					stream.Write( ( ( count ) & 0x1F ), 6 );
				}
				//stream.Write( count, 16 );
				stream.Write( index, bits );
			}

		}
		public void CompressVoxelData( ushort[] data, out byte[] result, out int bytes_used )
		{
			BitStream stream = new BitStream();
			int len = data.Length;
			int n;
			List<ushort> types = new List<ushort>();
			for( n = 0; n < len; n++ )
			{
				if( !types.Contains( data[n] ) )
					types.Add( data[n] );
			}
			int bits = BitStream.GetMinBitsNeededForValue( types.Count - 1 ); // 4 is 0,1,2,3; needs only 2 bits...
			//bits = (bits + 7 ) & 0xf8;
			stream.Seek( 16 ); // seek bit count
			stream.Write( (byte)bits, 8 );
			stream.Write( (uint)types.Count-1, bits );
			foreach( ushort type in types )
				stream.Write( type, 16 );
			ushort prior_cube = 0xFFFF, cube;
			uint index = 0;
			int count = 0;
            for( n = 0; n < len; n++ )
			{
				cube = data[n];
				if( prior_cube != cube )
				{
					if( count > 0 )
						WriteCubes( stream, bits, (uint)count, index );
					index = (uint)types.IndexOf( cube );
					prior_cube = cube;
					count = 1;
				}
				else
					count++;
			}
			WriteCubes( stream, bits, (uint)count, index );

			stream.GetBytes( out result, out bytes_used );
			result[0] = (byte)(( bytes_used ) & 0xFF);
			result[1] = (byte)( ( bytes_used ) >> 8);
			if( bytes_used < 20 )
				return;

			MemoryStream final_stream = new MemoryStream();
			final_stream.Seek( 2, SeekOrigin.Begin );
			//DeflateStream gz_stream = new DeflateStream( final_stream, CompressionMode.Compress );
			//GZipStream gz_stream = new GZipStream( final_stream, CompressionMode.Compress );
			GZipStream gz_stream = new GZipStream( final_stream, CompressionLevel.Fastest );
			//for( n = 2; n < bytes_used; n++ )
			//	gz_stream.WriteByte( result[n] );
			gz_stream.Write( result, 2, bytes_used - 2 );
			gz_stream.Close();
			result = final_stream.ToArray();//.GetBuffer();
			Log.log( "Compressed another {0}%", (float)( 100.0f * (float)( bytes_used - result.Length ) / ( bytes_used - 2 ) ) );
			// store old length so we know how much to request decompressing.
			result[0] = (byte)( ( bytes_used ) & 0xFF );
			result[1] = (byte)( ( bytes_used ) >> 8 );
			bytes_used = result.Length;// (int)final_stream.Length;
			gz_stream.Dispose();
		}