Génération de Chunks en multithreads
This commit is contained in:
		| @@ -113,109 +113,19 @@ void World::Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& playe | ||||
| 	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | ||||
| 	atlas.Bind(); | ||||
| 	RenderWorld(rendercount, player, world, shader); | ||||
| 	TransposeWorld(player, bullets); | ||||
| 	UpdateWorld(player, perlin, blockinfo); | ||||
| 	TransposeWorld(player, bullets); | ||||
| 	shader.Disable(); | ||||
| 	glStencilFunc(GL_GREATER, 1, 0xFF); | ||||
| } | ||||
|  | ||||
| bool World::GenerateChunk(int chx, int chy, Perlin& perlin) { | ||||
| 	if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && | ||||
| 		chx >= 0 && chy >= 0) | ||||
| 		if (!ChunkAt(chx, 1, chy)) { | ||||
|  | ||||
| 			for (int index = 0; index < m_tbDeleted.size(); ++index) { // V<>rifie l'existence d'un chunk dans le buffer de suppression avec sa position. | ||||
| 				int x, y; | ||||
|  | ||||
| 				if (m_tbDeleted.at(index)) { | ||||
| 					m_tbDeleted.at(index)->GetPosition(x, y); | ||||
| 					if (chx / CHUNK_SIZE_X + m_center[0] == x && | ||||
| 						chy / CHUNK_SIZE_Z + m_center[1] == y) { | ||||
| 						GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index))); | ||||
| 						return true; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			std::ostringstream pos; // V<>rifie l'existence d'un fichier .chunk avec sa position. | ||||
| 			pos << CHUNK_PATH << chx / CHUNK_SIZE_X + m_center[0] << '_' << chy / CHUNK_SIZE_Z + m_center[1] << ".chunk"; | ||||
| 			std::ifstream input(pos.str(), std::fstream::binary); | ||||
|  | ||||
| 			if (input.fail()) { | ||||
| 				GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1])); | ||||
| 				Chunk* chunk = GetChunks().Get(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z); | ||||
|  | ||||
| 				for (int x = 0; x < CHUNK_SIZE_X; ++x) // Montagnes | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						float xnoiz, ynoiz; | ||||
| 						xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX; | ||||
| 						ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX; | ||||
| 						float height = (perlin.Get(xnoiz, ynoiz)) * 20.f + 5.f; | ||||
| 						for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) | ||||
| 							chunk->SetBlock(x, y, z, BTYPE_METAL, this); | ||||
| 					} | ||||
|  | ||||
| 				for (int x = 0; x < CHUNK_SIZE_X; ++x) // Collines | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						float xnoiz, ynoiz; | ||||
| 						xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX; | ||||
| 						ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX; | ||||
| 						float height = perlin.Get(xnoiz, ynoiz) * 5.f + 24.f; | ||||
| 						for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) { | ||||
| 							if (chunk->GetBlock(x, y, z) == BTYPE_AIR) | ||||
| 								chunk->SetBlock(x, y, z, BTYPE_GRASS, this); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 				for (int x = 0; x < CHUNK_SIZE_X; ++x) // "Lacs" | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						for (int y = 0; y < 13; ++y) { | ||||
| 							if (chunk->GetBlock(x, y, z) == BTYPE_AIR) | ||||
| 								chunk->SetBlock(x, y, z, BTYPE_ICE, this); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 				for (int x = 0; x < CHUNK_SIZE_X; ++x) // "Arbres" | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						float xnoiz, ynoiz; | ||||
| 						xnoiz = (double)(z * CHUNK_SIZE_Y + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX; | ||||
| 						ynoiz = (double)(x * CHUNK_SIZE_Y + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX; | ||||
| 						bool tree = (int)(abs(perlin.Get(xnoiz, ynoiz)) * 17933.f) % CHUNK_SIZE_Y > 126 ? true: false; | ||||
| 						 | ||||
| 						for (int y = 0; y < CHUNK_SIZE_Y - 10; ++y)  | ||||
| 							if (chunk->GetBlock(x, y, z) == BTYPE_AIR)  | ||||
| 								if (chunk->GetBlock(x, y - 1, z) == BTYPE_GRASS) | ||||
| 									if (tree) { | ||||
| 										for (int i = 0; i < (int)(abs(perlin.Get(xnoiz, ynoiz))) % 3 + 1; ++i) | ||||
| 											chunk->SetBlock(x, y + i, z, BTYPE_DIRT, this); | ||||
| 										break; | ||||
| 									} | ||||
| 					} | ||||
| 			} | ||||
| 			else { | ||||
| 				input.seekg(0, std::ios_base::end); | ||||
| 				int size = input.tellg(); | ||||
| 				input.seekg(0, std::ios_base::beg); | ||||
|  | ||||
| 				char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; | ||||
| 				input.read(data, size); | ||||
| 				input.close(); | ||||
|  | ||||
| 				GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1], data)); | ||||
|  | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void World::UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) { | ||||
| void World::UpdateChunk(int& updates, int chx, int chy, BlockInfo* blockinfo[BTYPE_LAST]) { | ||||
| 	if (updates == 0 && ChunkAt(chx, 1, chy) && | ||||
| 		ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 		ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 		updates = FRAMES_UPDATE_CHUNKS; | ||||
| 	} | ||||
| 	if (generates == 0 && GenerateChunk(chx, chy, perlin)) generates = FRAMES_RENDER_CHUNKS; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) { | ||||
| @@ -377,26 +287,152 @@ void World::UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTY | ||||
| 	static int frameUpdate = 0; | ||||
| 	static int frameDelete = 0; | ||||
| 	int side = 0; | ||||
| 	int threads = 0; | ||||
| 	std::future<Chunk*> genThList[THREADS_GENERATE_CHUNKS]; | ||||
| 	//std::future<Chunk*> updateThList[THREADS_UPDATE_CHUNKS]; | ||||
|  | ||||
| 	if (frameGenerate > 0) --frameGenerate; | ||||
| 	if (frameUpdate > 0) --frameUpdate; | ||||
| 	if (frameDelete > 0) --frameDelete; | ||||
|  | ||||
| 	if (!frameGenerate || !frameUpdate) | ||||
| 	if (!frameGenerate) | ||||
| 		while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) { | ||||
| 			int tx = -side, ty = -side; | ||||
| 			int chx = 0; | ||||
| 			int chy = 0; | ||||
|  | ||||
| 			for (; tx <= side; ++tx) | ||||
| 				UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo); | ||||
| 			for (; ty <= side; ++ty) | ||||
| 				UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo); | ||||
| 			for (; tx >= -side; --tx) | ||||
| 				UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo); | ||||
| 			for (; ty >= -side; --ty) | ||||
| 				UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo); | ||||
|  | ||||
| 			for (; tx <= side; ++tx) { | ||||
| 				if (frameGenerate) | ||||
| 					break; | ||||
| 				chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && | ||||
| 					chx >= 0 && chy >= 0 && !ChunkAt(chx, 1, chy)) | ||||
| 					genThList[threads++] = std::async(std::launch::async, [](int x, int y) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]); | ||||
| 				if (threads == THREADS_GENERATE_CHUNKS) frameGenerate = FRAMES_RENDER_CHUNKS; | ||||
| 			} | ||||
| 			for (; ty <= side; ++ty) { | ||||
| 				if (frameGenerate) | ||||
| 					break; | ||||
| 				chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && | ||||
| 					chx >= 0 && chy >= 0 && !ChunkAt(chx, 1, chy)) | ||||
| 					genThList[threads++] = std::async(std::launch::async, [](int x, int y) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]); | ||||
| 				if (threads == THREADS_GENERATE_CHUNKS) frameGenerate = FRAMES_RENDER_CHUNKS; | ||||
| 			} | ||||
| 			for (; tx >= -side; --tx) { | ||||
| 				if (frameGenerate) | ||||
| 					break; | ||||
| 				chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && | ||||
| 					chx >= 0 && chy >= 0 && !ChunkAt(chx, 1, chy)) | ||||
| 					genThList[threads++] = std::async(std::launch::async, [](int x, int y) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]); | ||||
| 				if (threads == THREADS_GENERATE_CHUNKS) frameGenerate = FRAMES_RENDER_CHUNKS; | ||||
| 			} | ||||
| 			for (; ty >= -side; --ty) { | ||||
| 				if (frameGenerate) | ||||
| 					break; | ||||
| 				chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && | ||||
| 					chx >= 0 && chy >= 0 && !ChunkAt(chx, 1, chy)) | ||||
| 					genThList[threads++] = std::async(std::launch::async, [](int x, int y) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]); | ||||
| 				if (threads == THREADS_GENERATE_CHUNKS) frameGenerate = FRAMES_RENDER_CHUNKS; | ||||
| 			} | ||||
| 			if (frameGenerate) | ||||
| 				break; | ||||
| 			++side; | ||||
| 		} | ||||
|  | ||||
| 	if (threads > 0) { | ||||
| 		for (int i = 0; i < threads; ++i) | ||||
| 			genThList[i].wait(); | ||||
| 		 | ||||
| 		for (int i = 0; i < threads; ++i) { | ||||
| 			int x, y; | ||||
| 			Chunk* chunk = genThList[i].get(); | ||||
| 			chunk->GetPosition(x,y); | ||||
| 			m_chunks.Set(x - m_center[0], y - m_center[1], chunk); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	side = 0; | ||||
| 	threads = 0; | ||||
|  | ||||
| 	if (!frameUpdate) | ||||
| 		while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) { | ||||
| 			int tx = -side, ty = -side; | ||||
|  | ||||
| 			for (; tx <= side; ++tx) { | ||||
| 				if (frameUpdate) | ||||
| 					break; | ||||
| 				int chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				int chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (ChunkAt(chx, 1, chy) && | ||||
| 					ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 					ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 					if (threads++ == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS; | ||||
| 				} | ||||
| 			}	 | ||||
| 			for (; ty <= side; ++ty) { | ||||
| 				if (frameUpdate) | ||||
| 					break; | ||||
| 				int chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				int chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (ChunkAt(chx, 1, chy) && | ||||
| 					ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 					ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 					if (threads++ == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS; | ||||
| 				} | ||||
| 			}	 | ||||
| 			for (; tx >= -side; --tx) { | ||||
| 				if (frameUpdate) | ||||
| 					break; | ||||
| 				int chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				int chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (ChunkAt(chx, 1, chy) && | ||||
| 					ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 					ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 					if (threads++ == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS; | ||||
| 				} | ||||
| 			}	 | ||||
| 			for (; ty >= -side; --ty) { | ||||
| 				if (frameUpdate) | ||||
| 					break; | ||||
| 				int chx = cx + tx * CHUNK_SIZE_X; | ||||
| 				int chy = cy + ty * CHUNK_SIZE_Z; | ||||
| 				if (ChunkAt(chx, 1, chy) && | ||||
| 					ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 					ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 					if (threads++ == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS; | ||||
| 				} | ||||
| 				/*if (ChunkAt(chx, 1, chy) && // Version multithread d'UpdateChunks qui ne fonctionne pas. | ||||
| 					ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 					updateThList[threads++] = | ||||
| 						std::async(std::launch::async, | ||||
| 							[](Chunk* chunk, BlockInfo* blockinfo[BTYPE_LAST], World* world) { | ||||
| 								chunk->Update(blockinfo, world); return chunk; }, ChunkAt(chx, 1, chy), blockinfo, this); | ||||
| 					if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS; | ||||
| 				}*/ | ||||
| 			}		 | ||||
| 			if (frameUpdate) | ||||
| 				break; | ||||
| 			++side; | ||||
| 		} | ||||
|  | ||||
| 	/*if (threads > 0) { | ||||
| 		for (int i = 0; i < threads; ++i) | ||||
| 			updateThList[i].wait(); | ||||
|  | ||||
| 		for (int i = 0; i < threads; ++i) { | ||||
| 			int x, y; | ||||
| 			Chunk* chunk = updateThList[i].get(); | ||||
| 			chunk->GetPosition(x, y); | ||||
| 			m_chunks.Set(x - m_center[0], y - m_center[1], chunk); | ||||
| 		} | ||||
| 	}*/ | ||||
|  | ||||
| 	CleanUpWorld(frameDelete); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user