【问题标题】:Accessing vector index using bitset使用 bitset 访问向量索引
【发布时间】:2015-01-31 21:57:40
【问题描述】:

我正在尝试编写我自己的实体组件系统,并且我想要一种快速(可能的时间恒定)而且内存高效的方式来访问实体的组件。

使用全局映射 (std::unordered_map) 将每个实体映射到包含其组件的排序向量:

Key        Value
---        -----
EntityA -> Sorted vector of components 
EntityB -> Sorted vector of components
[..]    -> [..]

每个实体都有一个位集,指示实体具有哪些组件,即。 :

|C0 |C1 |C2 |C3 |C4 |C5
 0   0   1   0   1   1

and on the map:
Key        Value
---        -----
EntityA -> [C2,C4,C5]

由于组件很少添加,我可以负担排序插入的成本,但我绝对想要快速访问。

现在我从 bitset 知道 C4 是第二个元素集(从左数),所以它应该在第二个向量索引处。

如何将它写入一个方法中,该方法将返回给定组件类型 ID 的实体的组件? 例如。

Component* getComponent(ComponentID id){ // component id of C5 should be 6 since it occupies the 6th position of the bitset
return [..];
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    假设我们的成员是:

    std::bitset<6> bits;
    std::vector<Component> comps;
    

    然后:

    Component* getComponent(int id) {
        // we need to find how many bits are set for ids < id
        // first, make sure this one is set:
        if (!bits[id]) return nullptr;
    
        // then, let's count
        int idx = 0;
        for (int i = 0; i < id; ++i) {
            if (bits[i]) ++idx;
        }
    
        // now, just return the right pointer
        return &comps[idx];
    }
    

    如果您想进行边界检查,您也可以使用std::bitset::test 代替索引运算符。

    一个更快的解决方案可能是这样的:

    Component* getComponent(int id) {
        if (!bits[id]) return nullptr;
    
        // flip id and get a mask
        // if we have C0 .. C5, and we pass in 4
        // we want the mask 0x111100
        unsigned long mask = (1 << (bits.size() - id)) - 1;
        mask = ~mask;
    
        // apply the mask to the bitset
        // so from 0x001011, we get 0x001000
        unsigned long new_bits = bits.to_ulong() & mask;
    
        // count how many bits are set there
        unsigned int popcnt = __builtin_popcount(new_bits);
    
        // and there we have it
        return &comps[popcnt];
    }
    

    【讨论】:

    • 使用掩码是否比简单地右移然后计数位更快?
    猜你喜欢
    • 2015-09-08
    • 2018-06-01
    • 2016-08-25
    • 2021-02-26
    • 2012-03-19
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    相关资源
    最近更新 更多