void ChunkManager::UpdatingChunksThread() { while (m_updateThreadActive) { while (m_pPlayer == NULL) { #ifdef _WIN32 Sleep(100); #else usleep(100000); #endif } while (m_stepLockEnabled == true && m_updateStepLock == true) { #ifdef _WIN32 Sleep(100); #else usleep(100000); #endif } ChunkList updateChunkList; ChunkCoordKeysList addChunkList; ChunkList rebuildChunkList; ChunkList unloadChunkList; m_ChunkMapMutexLock.lock(); typedef map<ChunkCoordKeys, Chunk*>::iterator it_type; for (it_type iterator = m_chunksMap.begin(); iterator != m_chunksMap.end(); iterator++) { Chunk* pChunk = iterator->second; updateChunkList.push_back(pChunk); } m_ChunkMapMutexLock.unlock(); // Updating chunks int numAddedChunks = 0; int MAX_NUM_CHUNKS_ADD = 10; sort(updateChunkList.begin(), updateChunkList.end(), Chunk::ClosestToCamera); for (unsigned int i = 0; i < (int)updateChunkList.size(); i++) { Chunk* pChunk = updateChunkList[i]; if (pChunk != NULL) { pChunk->Update(0.01f); int gridX = pChunk->GetGridX(); int gridY = pChunk->GetGridY(); int gridZ = pChunk->GetGridZ(); float xPos = gridX * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = gridY * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = gridZ * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue > m_loaderRadius) { unloadChunkList.push_back(pChunk); } else { if (numAddedChunks < MAX_NUM_CHUNKS_ADD) { // Check neighbours if (pChunk->GetNumNeighbours() < 6 && (pChunk->IsEmpty() == false) || (gridY == 0)) { if (pChunk->GetxMinus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX - 1; coordKey.y = gridY; coordKey.z = gridZ; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } if (pChunk->GetxPlus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX + 1; coordKey.y = gridY; coordKey.z = gridZ; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } if (pChunk->GetyMinus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX; coordKey.y = gridY - 1; coordKey.z = gridZ; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } if (pChunk->GetyPlus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX; coordKey.y = gridY + 1; coordKey.z = gridZ; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } if (pChunk->GetzMinus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX; coordKey.y = gridY; coordKey.z = gridZ - 1; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } if (pChunk->GetzPlus() == NULL) { ChunkCoordKeys coordKey; coordKey.x = gridX; coordKey.y = gridY; coordKey.z = gridZ + 1; float xPos = coordKey.x * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float yPos = coordKey.y * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; float zPos = coordKey.z * Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f; vec3 chunkCenter = vec3(xPos, yPos, zPos) + vec3(Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE, Chunk::CHUNK_SIZE*Chunk::BLOCK_RENDER_SIZE); vec3 distanceVec = chunkCenter - m_pPlayer->GetCenter(); float lengthValue = length(distanceVec); if (lengthValue <= m_loaderRadius) { addChunkList.push_back(coordKey); numAddedChunks++; } } } } } } } updateChunkList.clear(); // Adding chunks for (unsigned int i = 0; i < (int)addChunkList.size(); i++) { ChunkCoordKeys coordKey = addChunkList[i]; Chunk* pChunk = GetChunk(coordKey.x, coordKey.y, coordKey.z); if (pChunk == NULL) { CreateNewChunk(coordKey.x, coordKey.y, coordKey.z); } else { UpdateChunkNeighbours(pChunk, coordKey.x, coordKey.y, coordKey.z); } } addChunkList.clear(); // Unloading chunks for (unsigned int i = 0; i < (int)unloadChunkList.size(); i++) { Chunk* pChunk = unloadChunkList[i]; UnloadChunk(pChunk); } unloadChunkList.clear(); // Check for rebuild chunks m_ChunkMapMutexLock.lock(); for (it_type iterator = m_chunksMap.begin(); iterator != m_chunksMap.end(); iterator++) { Chunk* pChunk = iterator->second; if (pChunk != NULL) { if (pChunk->NeedsRebuild()) { rebuildChunkList.push_back(pChunk); } } } m_ChunkMapMutexLock.unlock(); // Rebuilding chunks int numRebuildChunks = 0; int MAX_NUM_CHUNKS_REBUILD = 30; for (unsigned int i = 0; i < (int)rebuildChunkList.size() && numRebuildChunks < MAX_NUM_CHUNKS_REBUILD; i++) { Chunk* pChunk = rebuildChunkList[i]; pChunk->SwitchToCachedMesh(); pChunk->RebuildMesh(); pChunk->CompleteMesh(); pChunk->UndoCachedMesh(); numRebuildChunks++; } rebuildChunkList.clear(); if (m_stepLockEnabled == true && m_updateStepLock == false) { m_updateStepLock = true; } #ifdef _WIN32 Sleep(10); #else usleep(10000); #endif } m_updateThreadFinished = true; }
void ChunkManager::UpdateChunksThread() { while (m_updateThreadActive) { while (m_stepLockEnabled && m_updateStepLock) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } ChunkList updateList; ChunkList rebuildList; ChunkCoordKeyList addKeyList; // STEP 1: PUT ALL CREATED CHUNKS IN `UPDATE LIST` m_chunkMapMutex.lock(); std::map<ChunkCoordKey, Chunk*>::iterator it; for (it = m_chunkMap.begin(); it != m_chunkMap.end(); ++it) { Chunk* chunk = it->second; if (!chunk->IsUnloading()) { updateList.push_back(chunk); } } m_chunkMapMutex.unlock(); // STEP 2: FIND CHUNKS TO ADD (OR UNLOAD IF THEY'RE TOO FAR) int numAddedChunks = 0; const int MAX_NUM_CHUNKS_ADD = 10; std::sort(updateList.begin(), updateList.end(), Chunk::ClosestToCamera); for (unsigned int i = 0; i < updateList.size(); ++i) { Chunk* chunk = updateList[i]; if (chunk) { glm::vec3 chunkCenter = chunk->GetCenter(); glm::vec3 cameraPos = m_renderer->GetCamera().GetPosition(); float cameraDistance = glm::length(chunkCenter - cameraPos); if (cameraDistance > m_loadRadius) { chunk->SetUnloading(); } else if (numAddedChunks < MAX_NUM_CHUNKS_ADD) { ChunkCoordKeyList missing = chunk->GetMissingNeighbors(); if (!chunk->IsEmpty()) { for (ChunkCoordKey key : missing) { if (std::find(addKeyList.begin(), addKeyList.end(), key) == addKeyList.end()) { // Here we are calculating the distance of each // neighbor chunk to decide if we should add it glm::vec3 chunkCenter = Chunk::GetWorldCenter(key.x, key.y, key.z); float cameraDistance = glm::length(chunkCenter - cameraPos); if (cameraDistance <= m_loadRadius && key.y == 0) { addKeyList.push_back(key); ++numAddedChunks; } } } } } } } updateList.clear(); // STEP 3: ADD CHUNKS for (unsigned int i = 0; i < addKeyList.size(); ++i) { ChunkCoordKey key = addKeyList[i]; CreateNewChunk(key.x, key.y, key.z); } addKeyList.clear(); // STEP 4: CHECK FOR REBUILD CHUNKS m_chunkMapMutex.lock(); for (it = m_chunkMap.begin(); it != m_chunkMap.end(); ++it) { Chunk* chunk = it->second; if (!chunk->IsUnloading() && chunk->NeedsRebuild()) { rebuildList.push_back(chunk); } } m_chunkMapMutex.unlock(); // STEP 5: REBUILD CHUNKS int numRebuildChunks = 0; const int MAX_NUM_CHUNKS_REBUILD = 30; for (unsigned int i = 0; i < rebuildList.size() && numRebuildChunks < MAX_NUM_CHUNKS_REBUILD; ++i) { Chunk* chunk = rebuildList[i]; chunk->RebuildMesh(); ++numRebuildChunks; } rebuildList.clear(); if (m_stepLockEnabled && !m_updateStepLock) { m_updateStepLock = true; } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } m_updateThreadFinished = true; }