块加载和排序
Chunks loading and sort
我正在克隆minecraft,我有两个块加载问题。
第一:确定要加载的块。
我发现了一种方法,它很难看,但对我来说效果很快
- 定义三维数组(数组)(大小:MAX_CHUNKS_X、MAX_CHUKS_Y、MAX_CHUNKS_Z)
- 用FALSE填充三维数组
- 从块列表中传递时,检查块是否在视觉范围内
- 如果内部集合数组[chunk_x][chunk_y][chunk_6z]=true
- 通过列表后开始低音阵列
- 对于所有数组[chunk_x][chunk_y][chunk_6z]==false在chunk_xchunk_y chunk_z处添加到LoadingList块
另一种方法可以减少丑陋并保持快速?
代码:
ChunksRenderList.clear();
CChunk* Chunk = NULL;
s32 RootChunk_X_Location = (floor(RenderCenter.x) / CHUNK_SIZE);
s32 RootChunk_Y_Location = (floor(RenderCenter.y) / CHUNK_SIZE);
s32 RootChunk_Z_Location = (floor(RenderCenter.z) / CHUNK_SIZE);
if(RenderCenter.x < 0)
RootChunk_X_Location--;
if(RenderCenter.y < 0)
RootChunk_Y_Location--;
if(RenderCenter.z < 0)
RootChunk_Z_Location--;
core::vector3s RootChunkLocation(RootChunk_X_Location,RootChunk_Y_Location,RootChunk_Z_Location);
u32 XZ_ArraySide = (RenderDistance_XZ*2)+1;
u32 Y_ArraySide = (RenderDistance_Y*2)+1;
char array[XZ_ArraySide][Y_ArraySide][XZ_ArraySide];
memset(array,0,(XZ_ArraySide*XZ_ArraySide*Y_ArraySide));
for(auto it = Chunks.begin(); it != Chunks.end(); it++)
{
Chunk = (it->second);
if(Chunk->Locked)
continue;
if(Chunk->KeepAliveCounter <= 0)
{
ChunksUnloadList.push_back(Chunk);
continue;
}
else
{
Chunk->KeepAliveCounter -= WORLD_UPDATE_PERIOD;
Chunk->DistanceToCamera = RenderCenter.distance_to(Chunk->ChunkAbsolutePosition);
}
if(Chunk->ChunkPosition.x >= (RootChunk_X_Location - (s32)RenderDistance_XZ) && Chunk->ChunkPosition.x <= (RootChunk_X_Location + (s32)RenderDistance_XZ))
if(Chunk->ChunkPosition.y >= (RootChunk_Y_Location - (s32)RenderDistance_Y) && Chunk->ChunkPosition.y <= (RootChunk_Y_Location + (s32)RenderDistance_Y))
if(Chunk->ChunkPosition.z >= (RootChunk_Z_Location - (s32)RenderDistance_XZ) && Chunk->ChunkPosition.z <= (RootChunk_Z_Location + (s32)RenderDistance_XZ))
{
s32 PositionInMatrix_X = Chunk->ChunkPosition.x - (RootChunk_X_Location - (s32)RenderDistance_XZ);
s32 PositionInMatrix_Y = Chunk->ChunkPosition.y - (RootChunk_Y_Location - (s32)RenderDistance_Y);
s32 PositionInMatrix_Z = Chunk->ChunkPosition.z - (RootChunk_Z_Location - (s32)RenderDistance_XZ);
array[PositionInMatrix_X][PositionInMatrix_Y][PositionInMatrix_Z] = true;
Chunk->KeepAliveCounter = CHUNK_LIVE_TIME;
}
if(not Chunk->NeightboarsUpdated)
{
ChunksNeightboarUpdateList.push_back(Chunk);
}
if(not Chunk->ChunkUpdated)
{
ChunksRebuildList.push_back(Chunk);
}
if(not Chunk->Locked and Chunk->VisibleBlocks > 0)
{
ChunksRenderList.push_back(Chunk);
}
}
for(u32 y = 0; y < Y_ArraySide; y++)
for(u32 x = 0; x < XZ_ArraySide; x++)
for(u32 z = 0; z < XZ_ArraySide; z++)
{
s32 ChunkPosition_X = (s32)x + (RootChunk_X_Location - (s32)RenderDistance_XZ);
s32 ChunkPosition_Y = (s32)y + (RootChunk_Y_Location - (s32)RenderDistance_Y);
s32 ChunkPosition_Z = (s32)z + (RootChunk_Z_Location - (s32)RenderDistance_XZ);
if(array[x][y][z] == 0)
{
SPendingToLoad ToLoad;
ToLoad.Position.set(ChunkPosition_X,ChunkPosition_Y,ChunkPosition_Z);
ToLoad.DistanceToCamera = ToLoad.Position.distance_to_sqr(RootChunkLocation);
ChunksLoadList.push_back(ToLoad);
}
}
第二:如何对ChunksLoadList进行排序以使其像这张图片上的左边一样生效https://www.dropbox.com/s/owjfaaekcj2m23w/58f2e4c8.png?dl=0红色=最接近ChunksLoadList.begin()Blue=告别ChunksLoadList.begin()
我尝试使用
ChunksLoadList.sort([&RootChunkLocation](SPendingToLoad& i,SPendingToLoad& j)
{
return i.DistanceToCamera < j.DistanceToCamera;
}
);
但它的方法是在大的视野范围内放慢速度。。。我必须如何重写代码才能获得快速加载效果?
对不起,我的英语很糟糕,我希望你能理解我…
让我们先来看看距离排序问题,如果您的ChunksLoadList
是std::list,而不是std::vector或std::array(C++11),那么您已经输掉了性能竞赛!Bjarne Stroustrup:为什么你应该避免链表密切关注图表!!!
如果在你把它改成std::vector后它仍然太慢,你可以试试"我刚刚发明的这个方法(TM)"!
最好的排序算法类似
O(C+K*N log log N)最快?
具有可怕的C常数准备时间,每个元素可怕的K和非常好的N log log N
对于N->无穷大,这将是O(N log log N)
但是对于这个问题,有一个更好的算法
整体填充,然后是插入排序,整体填充在O(N)中生成一个几乎排序的列表,插入排序从O(N。。。
O(C+K*N)
有一个可怕的恒定准备时间,每个元素都很糟糕,但只有N倍
维基百科的变体
Flood-fill (node, target-color, replacement-color):
If target-color is equal to replacement-color, return.
Set Q to the empty queue. [must be std::vector or std::array or this will fail]
Add camera node to the end of Q.
While Q is not empty:
Set n equal to the *first* element of Q.
Remove *first* element from Q.
If the color of n is equal to target-color:
Add n to the distance list as the next closed (this will be nearly correct)
Set the color of n to replacement-color and mark "n" as processed.
Add adjacent nodes to end of Q if they has not been processed yet. (x/y/z +1/-1)
Return.
队列元素为x、y、z
使用std::出列
距离列表也必须是随机访问包含,从大小(viewdistance*2+1)^3开始完全分配,这可能很大
如果视图距离100是201^3=~8000000个体素,你真的想要这个吗?如果你需要一些信息,你必须有一些指针或索引,至少4个字节,这会破坏大多数系统的缓存。
作为洪水填充,它是无效的,但作为距离的近似值。
如果你的要求得到满足,你可以到此为止
如果您需要总排序,然后在几乎排序的列表O(N)上运行插入排序,但您还需要计算相机距离。
潜在的进一步优化:
- 不透明体素不会添加同样不透明的邻居
- 空气(完全透明)不会添加到相机列表中,但需要在那里填充,以防出现飞行岛
- std::原子加载和存储都需要吗
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 为什么加载SDF会导致Mobilizer创建闭环错误
- C++atioglxx.pdb未加载错误glBufferData OpenGL
- 如何使用tinyxml2从XML加载父实体和子实体
- 如何在C++中使用pybind11加载一个pickle python列表
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- Python ctypes:不会按预期加载 dll
- 为什么会出现 gettnig 运行时错误:加载类型为"_Bit_type"(stl_bvector.h) 的空指针?
- 我的程序有一个保存配置文件的GUI,如何双击此配置文件以直接加载带有配置数据的GUI?
- 保存/加载大量短数组到二进制文件
- 使用 SDL2 和SDL_image C++加载图像
- 在ARM上加载并存储重新排序
- 是否可以在条件之前对加载或存储进行重新排序?
- GCC 在加载过程中使用“memory_order_seq_cst”重新排序.这是允许的吗
- 是否可以在 C++11 中使用后续顺序一致加载对存储版本进行重新排序
- 块加载和排序