// Chunk Creation void ChunkManager::CreateNewChunk(int x, int y, int z) { ChunkCoordKeys coordKeys; coordKeys.x = x; coordKeys.y = y; coordKeys.z = z; // Create a new chunk at this grid position Chunk* pNewChunk = new Chunk(m_pRenderer, this, m_pVoxSettings); pNewChunk->SetPlayer(m_pPlayer); pNewChunk->SetSceneryManager(m_pSceneryManager); float xPos = x * (Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f); float yPos = y * (Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f); float zPos = z * (Chunk::CHUNK_SIZE * Chunk::BLOCK_RENDER_SIZE*2.0f); pNewChunk->SetPosition(vec3(xPos, yPos, zPos)); pNewChunk->SetGrid(coordKeys.x, coordKeys.y, coordKeys.z); m_ChunkMapMutexLock.lock(); m_chunksMap[coordKeys] = pNewChunk; m_ChunkMapMutexLock.unlock(); pNewChunk->Setup(); pNewChunk->SetNeedsRebuild(false, true); pNewChunk->RebuildMesh(); pNewChunk->CompleteMesh(); pNewChunk->SetCreated(true); UpdateChunkNeighbours(pNewChunk, x, y, z); }
void ChunkManager::Update() { ChunkList unloadList; 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()) { unloadList.push_back(chunk); } else if (chunk->IsRebuildComplete()) { chunk->CompleteMesh(); } } m_chunkMapMutex.unlock(); int numUnloadChunks = 0; const static int MAX_NUM_CHUNKS_UNLOAD = 1; for (unsigned int i = 0; i < unloadList.size() && numUnloadChunks < MAX_NUM_CHUNKS_UNLOAD; ++i) { Chunk* chunk = unloadList[i]; UnloadChunk(chunk); } }
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; }