2017-01-09 5 views
0

私のゲーム用のメッシュリストの空間グリッドを作成しようとすると、特定のグリッドの座標データに基づいてユニークなハッシュを作成しようとしています。グリッドデータを取得しようとしています:WorldName world_name; uint8_t stage_index; short int pos_x; short int pos_y; short int pos_z;とユニークなuint64_t hash_bitfieldを構築しようとしています。符号付きintが大きいビットフィールドの一部を壊します

私のグリッド座標が正である場合、私のuint64_t GenerateHash(...)はうまく動作します。 1にそのバイトの左ビットおきである負のフリップをPOS_Y

world: 1  -->> 0000 0001 
stage: 1  -->> 0000 0001 
pos_x: 23  -->> 0000 0000 0001 0111 
pos_y: -23  -->> 1111 1111 1110 1001 
pos_z: 23  -->> 0000 0000 0001 0111 

[ world ] [ stage ] [  pos_x  ] [  pos_y  ] [  pos_z  ] 
--byte7-- --byte6-- --byte5-- --byte4-- --byte3-- --byte2-- --byte1-- --byte0-- 
1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110 1001 0000 0000 0001 0111 <-- what I get 
0000 0001 0000 0001 0000 0000 0001 0111 0000 0000 0001 0111 0000 0000 0001 0111 <-- when y is positive 

What I expected:      vvvvvvvvvvvvvvvvvvv 
0000 0001 0000 0001 0000 0000 0001 0111 1111 1111 1110 1001 0000 0000 0001 0111 

注意:いずれかが負の場合しかし、私は、望ましくない効果を得ることができます。このようなことは、すべての数字が正の場合には起こりません。以下のコードでわかるように、私は手作業で符号ビットを反転させて、のビットをuint64_t(コメントブロック)にコピーしました。それもうまくいかなかった。 (POS_Yのビットフィールドはのみ16バイト2のビットとBYTE3に影響を与えている)の上に、私は、私の[予想される]ビットフィールドのように見えるuint64_tをを取得できますか

#include <iostream> 
#include <string> 
#include <sstream> 
#include <bitset> 
using namespace std; 

enum WorldName{ // These are collections of gameobj sectors 
    WORLD_TYPE1, 
    WORLD_TYPE2, 
    WORLD_TYPE3, 
    MAX_WORLDS 
}; 

uint64_t GenerateHash(WorldName world_name, uint8_t stage_index, short int pos_x, short int pos_y, short int pos_z){ 
    uint64_t world_name_t = world_name; 
    uint64_t stage_index_t = stage_index; 
    uint64_t pos_x_t = pos_x; 
    uint64_t pos_y_t = pos_y; 
    uint64_t pos_z_t = pos_z; 

    // Try to flip the sign manually (it doesn't help) 
    //uint64_t pos_x_t, pos_y_t, pos_z_t; 
    //if(pos_x < 0){ pos_x_t = ~(uint64_t(abs(pos_x))) + 1; } else { pos_x_t = pos_x; } 
    //if(pos_y < 0){ pos_y_t = ~(uint64_t(abs(pos_y))) + 1; } else { pos_y_t = pos_y; } 
    //if(pos_z < 0){ pos_z_t = ~(uint64_t(abs(pos_z))) + 1; } else { pos_z_t = pos_z; } 

    uint64_t hash_bitfield = 0x0; 
    hash_bitfield |= world_name_t << (8 * 7); 
    hash_bitfield |= stage_index_t << (8 * 6); 
    hash_bitfield |= pos_x_t << (8 * 4); 
    hash_bitfield |= pos_y_t << (8 * 2); 
    hash_bitfield |= pos_z_t; 

    return hash_bitfield; 
} 

void PrintBitString(std::string bitstr, std::string label="", bool print_ruler=true){ 
    std::string buffer; 
    int count = 0; 
    for(size_t i = 0; i < bitstr.size(); i++){ 
     buffer += bitstr[i]; 
     count++; 
     if(count >3){ buffer += ' '; count = 0; } 
    } 

    if(print_ruler){ 
     int num_of_bytes_to_draw = (bitstr.size()/8); 
     for(size_t k = num_of_bytes_to_draw; k > 0; --k){ 
      cout << "--byte" << k - 1 << "-- "; 
     } 
     cout << endl; 
    } 

    cout << buffer << endl; 
} 

int main() { 
    WorldName world_name = (WorldName) 1; // 4B 
    uint8_t stage_index = 1;  // 1B 
    short int pos_x = 23;  // 2B 
    short int pos_y = -23;  // 2B 
    short int pos_z = 23;  // 2B 

    std::bitset<8> world_name_bits(world_name); 
    std::bitset<8> stage_index_bits(stage_index); 
    std::bitset<16> pos_x_bits(pos_x); 
    std::bitset<16> pos_y_bits(pos_y); 
    std::bitset<16> pos_z_bits(pos_z); 
    cout << "world: " << world_name << "\t-->> " << world_name_bits << endl; 
    cout << "stage: " << (int)stage_index << "\t-->> " << stage_index_bits << endl; 
    cout << "pos_x: " << pos_x << "\t-->> " << pos_x_bits << endl; 
    cout << "pos_y: " << pos_y << "\t-->> " << pos_y_bits << endl; 
    cout << "pos_z: " << pos_z << "\t-->> " << pos_z_bits << endl << endl; 

    uint64_t my_hash = GenerateHash(world_name, stage_index, pos_x, pos_y, pos_z); 
    uint64_t my_hash_abs = GenerateHash(world_name, stage_index, pos_x, abs(pos_y), pos_z); 

    cout << "[ world ] [ stage ] [  pos_x  ] [  pos_y  ] [  pos_z  ]" << endl; 
    std::bitset<64> bits(my_hash); 
    std::bitset<64> bits_abs(my_hash_abs); 
    PrintBitString(bits.to_string()); 
    PrintBitString(bits_abs.to_string(),"",false); 
    cout << endl; 

    system("PAUSE"); 
} 

?ご協力いただきありがとうございます!

答えて

0

あなたはpos_x_t

uint_64_t pos_x_t = (unsigned short) pos_x; 

それとも、

uint_64_t pos_x_t = uint_64_t(pos_x) & 0xFFFF; 

それともhash_bitfield

に格納する際に適切なマスクを使用して値をマスクすることが可能にそれらを割り当てる前 unsigned shortpos_xなどの変数をキャストすることができ
hash_bitfield |= (pos_x_t & 0xFFFF) << (8 * 4); 

マスキングはシフトの後に行うこともできますが、シフトされたマスクを使用する必要があります。

+0

'unsigned short'は' uint16_t'を意味します –

+0

これはトリックでした。私はそれを考えなかったのは恥ずかしいです。ありがとう。 uint64_t pos_x_t = uint16_t(pos_x); uint64_t pos_y_t = uint16_t(pos_y); uint64_t pos_z_t = uint16_t(pos_z); – truthastup

関連する問題