2015-05-13 6 views
0

В моей системе вокселов используется динамический динамический массив, распределенный во время выполнения для каждого фрагмента, однако создание миллионов кубов на кусок невозможно, поэтому мне нужно оптимизировать.Проверяйте соседние вокселы эффективно в 3D-массиве размера n

Первой оптимизацией, которую я намерен реализовать, является, конечно, не генерация данных ячейки для оккультированных вокселов, это хорошая идея на бумаге, но я не знаю, как это сделать.

Все мои попытки оказались сложными для отладки проблем с распределением памяти, и поэтому я должен бросить полотенце и попросить более знающих людей, поскольку я нахожусь в убытке.

Моя нынешняя инкарнация это как таковой

int8_t x = 0, y= 0, z = 0; 
const int MAX = CHUNKSIZE-1; 
const int MIN = 0; 


int8_t sPosX = (x - 1 < MIN) ? x : x-1; 
int8_t sPosY = (y - 1 < MIN) ? y : y-1; 
int8_t sPosZ = (z - 1 < MIN) ? z : z-1; 

int8_t ePosX = (x + 1 > MAX) ? x : x+1; 
int8_t ePosY = (y + 1 > MAX) ? y : y+1; 
int8_t ePosZ = (z + 1 > MAX) ? z : z+1; 
int8_t a=sPosX, b=sPosY, c=sPosZ; 
int8_t add = 0; 


BlockType BT = BT_grass; 
scene::SMesh* mesh = new scene::SMesh(); 
for(x = 0; x <= MAX; x++) 
{ 
    for(y = 0; y <= MAX; y++) 
    { 
     for(z = 0; z <= MAX; z++) 
     { 
      cm = b_blocks[x][y][z].material; 
      //b_blocks[x][y][z].setFlags(0xFE, BT); 
      if(!b_blocks[x][x][z].isActive()) 
      { 
       continue; 
      } 
      else 
      { 
       if(sPosX == MIN) 
       { 
        createCube(x,y,z,c,mesh,cm); 
       } 

       else 
       { 
        if(a<=ePosX) 
        { 
         if(b<=ePosY) 
         { 
          if(c<=ePosZ) 
          { 
           printf("x %d, y %d, z %d\n", x, y, z); 
           if(!b_blocks[x][y][z].isActive()) 
           { 
            add = 1; 
           } 
          } 
         } 
        } 
        if(add == 1) 
        { 
         createCube(x,y,z,c,mesh,cm); 
         add = 0; 
        } 
       } 
      } 
     } 
    } 
} 

КРП (sPosX == MIN) хак я реализовывал не на сегментации генерации кусок (в противном случае она возвращает ошибку сегментации с нарушением доступа к памяти о создании . блок [CHUNKSIZE] [CHUNKSIZE] [CHUNKSIZE], что не очень приятно Этот хак неосторожно убеждается, что все кубы генерируются однако и столь же непривлекательный

Конспективные вопросы здесь заключается в следующем:. что часть моей логики нарушена? (предположительно, все это) и как правильно быстро проверить соседние блоки, которые не вызывают ошибку за пределами границ? (Я попытался с помощью кодирования вручную исключений для каждого последнего угла дела, но это оказалось неосновательный и был порядков медленнее и склонны к segfaulting)

+0

У меня есть мир voxel с открытым исходным кодом, реализованный в C++; Я сделал это, создав класс ['BlockIterator'] (https://github.com/programmerjake/voxels-0.7/blob/master/include/util/block_iterator.h), который обрабатывает перевод с глобальных позиций на куски/фрагменты локальных позиции. также вот определение для [блок-кусок] (https://github.com/programmerjake/voxels-0.7/blob/master/include/util/basic_block_chunk.h#L41) – programmerjake

+0

После сглаживания 1370 нечетных строк я не вижу как это должно мне помочь (в основном потому, что у меня нет времени для углубленного изучения кода и фактически расшифровки всех этих строк относительно друг друга, и если бы у меня было такое время, я бы загрузил источник на что-то вроде minetest и начать читать это). – LordHexahedron

ответ

1

Я хотел бы использовать что-то вроде:

class BlockChunk final 
{ 
public: 
    static constexpr int sizeXShift = 4, sizeYshift = 8, sizeZshift = 4; 
    static constexpr int sizeX = 1 << sizeXShift; // 2 ** sizeXShift 
    static constexpr int sizeY = 1 << sizeYShift; 
    static constexpr int sizeZ = 1 << sizeZShift; 
    static constexpr int sizeXRelativeMask = sizeX - 1; // mask to get position mod sizeX (faster than % because negative inputs to % return negative answers which need more adjusting whereas masking always returns the positive answer) 
    static constexpr int sizeYRelativeMask = sizeY - 1; 
    static constexpr int sizeZRelativeMask = sizeZ - 1; 
    static constexpr int sizeXChunkBaseMask = ~sizeXRelativeMask; // mask to get position - relativePosition (aka chunk base position) 
    static constexpr int sizeYChunkBaseMask = ~sizeYRelativeMask; 
    static constexpr int sizeZChunkBaseMask = ~sizeZRelativeMask; 
private: 
    Block blocks[sizeX][sizeY][sizeZ]; 
public: 
    const PositionI basePosition; 
    BlockChunk(PositionI basePosition) 
     : basePosition(basePosition) 
    { 
    } 
    Block &at(PositionI relative) 
    { 
     assert(relative.x >= 0 && relative.x < sizeX); 
     assert(relative.y >= 0 && relative.y < sizeY); 
     assert(relative.z >= 0 && relative.z < sizeZ); // these asserts are important for finding out-of-bounds bugs 
     return blocks[relative.x][relative.y][relative.z]; 
    } 
    static PositionI getRelativePosition(PositionI p) 
    { 
     p.x &= sizeXRelativeMask; 
     p.y &= sizeYRelativeMask; 
     p.z &= sizeZRelativeMask; 
     return p; 
    } 
    static PositionI getChunkBasePosition(PositionI p) 
    { 
     p.x &= sizeXChunkBaseMask; 
     p.y &= sizeYChunkBaseMask; 
     p.z &= sizeZChunkBaseMask; 
     return p; 
    } 
}; 

class BlockIterator; 

class BlockWorldBase 
{ 
    friend class BlockIterator; 
private: 
    std::unordered_map<PositionI, std::shared_ptr<BlockChunk>> chunks; 
    BlockChunk *getOrMakeChunk(PositionI chunkBasePosition) 
    { 
     std::shared_ptr<BlockChunk> &chunk = chunks[chunkBasePosition]; 
     if(chunk == nullptr) 
      chunk = std::make_shared<BlockChunk>(chunkBasePosition); 
     return chunk.get(); 
    } 
}; 

class BlockWorld; 

class BlockIterator final 
{ 
    friend class BlockWorld; 
private: 
    BlockChunk *chunk; 
    BlockWorldBase *world; 
    PositionI chunkBasePosition, relativePosition; 
    void updateChunk() 
    { 
     chunk = world->getOrMakeChunk(chunkBasePosition); 
    } 
    BlockIterator(BlockWorldBase *world, PositionI position) 
     : chunk(), 
     world(world), 
     chunkBasePosition(BlockChunk::getChunkBasePosition(position)), 
     relativePosition(BlockChunk::getRelativePosition(position)) 
    { 
     updateChunk(); 
    } 
public: 
    PositionI getPosition() const 
    { 
     return relativePosition + chunkBasePosition; 
    } 
    Block &get() 
    { 
     return chunk->at(relativePosition); 
    } 
    BlockIterator &operator +=(PositionI deltaPosition) // move to point to a new block 
    { 
     PositionI newRelativePosition = relativePosition + deltaPosition; 
     if(BlockChunk::getRelativePosition(newRelativePosition) != newRelativePosition) // if the new position is outside of this chunk 
     { 
      relativePosition = BlockChunk::getRelativePosition(newRelativePosition); 
      chunkBasePosition += BlockChunk::getChunkBasePosition(newRelativePosition); 
      updateChunk(); 
     } 
     else 
     { 
      relativePosition = newRelativePosition; 
     } 
    } 
    friend BlockIterator operator +(PositionI p, BlockIterator bi) 
    { 
     bi += p; 
     return bi; 
    } 
    friend BlockIterator operator +(BlockIterator bi, PositionI p) 
    { 
     bi += p; 
     return bi; 
    } 
}; 

class BlockWorld final : public BlockWorldBase 
{ 
public: 
    BlockIterator getIterator(PositionI p) 
    { 
     return BlockIterator(this, p); 
    } 
}; 

Если оставить утверждает и получить доступ через BlockIterator вы не должны когда-либо SEG-вины

void drawBlock(Renderer &renderer, BlockIterator bi) 
{ 
    BlockIterator nxBlockIterator = bi + PositionI(-1, 0, 0); 
    BlockIterator pxBlockIterator = bi + PositionI(1, 0, 0); 
    BlockIterator nyBlockIterator = bi + PositionI(0, -1, 0); 
    BlockIterator pyBlockIterator = bi + PositionI(0, 1, 0); 
    BlockIterator nzBlockIterator = bi + PositionI(0, 0, -1); 
    BlockIterator pzBlockIterator = bi + PositionI(0, 0, 1); 
    if(nxBlockIterator.get().isPXFaceBlocked()) 
     bi.get().renderNXFace(renderer, bi); 
    if(pxBlockIterator.get().isNXFaceBlocked()) 
     bi.get().renderPXFace(renderer, bi); 
    if(nyBlockIterator.get().isPYFaceBlocked()) 
     bi.get().renderNYFace(renderer, bi); 
    if(pyBlockIterator.get().isNYFaceBlocked()) 
     bi.get().renderPYFace(renderer, bi); 
    if(nzBlockIterator.get().isPZFaceBlocked()) 
     bi.get().renderNZFace(renderer, bi); 
    if(pzBlockIterator.get().isNZFaceBlocked()) 
     bi.get().renderPZFace(renderer, bi); 
    bi.get().renderCenter(renderer, bi); 
} 
0

вы не показывают, как переменная b_blocks объявлена ​​или инициализирована, но при условии, что вы получаете ошибку сегментации, то, скорее всего вы объявили это как меньший размер ваш CHUNK_SIZE.