Test monde infini
This commit is contained in:
		| @@ -79,10 +79,11 @@ void World::TransposeWorld(Player& player) { | ||||
|     player.Transpose(x, y); | ||||
| } | ||||
|  | ||||
| void World::CleanUpWorld(int& frames) { | ||||
|     if (!m_tbDeleted.empty() && !frames) { | ||||
| void World::CleanUpWorld(int& deleteframes, bool clear = false) { | ||||
| 	if (clear) m_tbDeleted.clear(); | ||||
|     if (!m_tbDeleted.empty() && !deleteframes) { | ||||
|         m_tbDeleted.pop_back(); | ||||
|         frames = FRAMES_DELETE_CHUNKS; | ||||
|         deleteframes = FRAMES_DELETE_CHUNKS; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -97,3 +98,270 @@ Chunk* World::RetrieveChunk(int x, int y) { | ||||
|  | ||||
|     return nullptr; | ||||
| } | ||||
|  | ||||
| void World::GetScope(int& x, int& y) { | ||||
| 	x = m_center[0]; | ||||
| 	y = m_center[1]; | ||||
| } | ||||
|  | ||||
| void World::Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) { | ||||
| 	atlas.Bind(); | ||||
| 	TransposeWorld(player); | ||||
| 	RenderWorld(rendercount, badhitcount, player, world, shader); | ||||
| 	UpdateWorld(player, perlin, blockinfo); | ||||
| 	shader.Disable(); | ||||
| } | ||||
|  | ||||
| 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; | ||||
| 				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().c_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) | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						Vector3f noise; | ||||
| 						noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]); | ||||
| 						noise.y = 0; | ||||
| 						noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]); | ||||
| 						noise.Normalize(); | ||||
| 						float height = perlin.Get(noise.x, noise.z) * 3 - 32; | ||||
| 						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) | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						Vector3f noise; | ||||
| 						noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]); | ||||
| 						noise.y = 0; | ||||
| 						noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]); | ||||
| 						noise.Normalize(); | ||||
| 						float height = perlin.Get(noise.x, noise.z) + 16; | ||||
| 						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) | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						for (int y = 0; y <= 10; ++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) | ||||
| 					for (int z = 0; z < CHUNK_SIZE_Z; ++z) { | ||||
| 						for (int y = 0; y < CHUNK_SIZE_Y; ++y) { | ||||
| 							Vector3f noise; | ||||
| 							noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]); | ||||
| 							noise.y = (x + z) * CHUNK_SIZE_Y + m_center[0]; | ||||
| 							noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]); | ||||
| 							noise.Normalize(); | ||||
| 							float height = perlin.Get(noise.x, noise.y, noise.z); | ||||
| 							if (chunk->GetBlock(x, y, z) != BTYPE_AIR && height > 18) | ||||
| 								chunk->SetBlock(x, y, z, BTYPE_DIRT, this); | ||||
| 						} | ||||
| 					} | ||||
| 			} | ||||
| 			else { | ||||
| 				input.seekg(0, std::ios_base::end); | ||||
| 				int size = input.tellg(); | ||||
| 				input.seekg(0, std::ios_base::beg); | ||||
|  | ||||
| 				char* data = new char[size]; | ||||
| 				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)); | ||||
|  | ||||
| 				delete[] data; | ||||
| 			} | ||||
| 			std::cout << "Chunk generated: " << chx / CHUNK_SIZE_X + m_center[0] << ", " << chy / CHUNK_SIZE_Z + m_center[1] << std::endl; | ||||
|  | ||||
| 			return true; | ||||
| 		} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| void World::UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) { | ||||
| 	if (generates == 0 && GenerateChunk(chx, chy, perlin)) generates = FRAMES_RENDER_CHUNKS; | ||||
| 	if (updates == 0 && ChunkAt(chx, 1, chy) && | ||||
| 		ChunkAt(chx, 1, chy)->IsDirty()) { | ||||
| 		ChunkAt(chx, 1, chy)->Update(blockinfo, this); | ||||
| 		updates = FRAMES_UPDATE_CHUNKS; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) { | ||||
| 	Vector3f currentPos = player.GetPosition(); | ||||
| 	Vector3f currentBlock = currentPos; | ||||
| 	Vector3f ray = player.GetDirection(); | ||||
| 	bool found = false; | ||||
|  | ||||
| 	if (block) return; | ||||
|  | ||||
| 	while ((currentPos - currentBlock).Length() <= MAX_SELECTION_DISTANCE && !found) { | ||||
| 		currentBlock += ray / 10.f; | ||||
|  | ||||
| 		BlockType bt = BlockAt(currentBlock); | ||||
|  | ||||
| 		if (bt != BTYPE_AIR) | ||||
| 			found = true; | ||||
| 	} | ||||
|  | ||||
| 	if (found) | ||||
| 		if (blockType != BTYPE_AIR) { | ||||
| 			found = false; | ||||
| 			while ((currentPos - currentBlock).Length() >= 1.7f && !found) { | ||||
| 				currentBlock -= ray / 10.f; | ||||
|  | ||||
| 				BlockType bt = BlockAt(currentBlock); | ||||
|  | ||||
| 				if (bt == BTYPE_AIR) { // V<>rification pour <20>tre s<>r que le bloc <20> changer n'est pas dans le joueur. | ||||
| 					int Bx = (int)currentBlock.x; | ||||
| 					int By = (int)currentBlock.y; | ||||
| 					int Bz = (int)currentBlock.z; | ||||
|  | ||||
| 					int Px = (int)currentPos.x; | ||||
| 					int PyA = (int)currentPos.y; | ||||
| 					int PyB = (int)(currentPos.y - .9f); | ||||
| 					int PyC = (int)(currentPos.y - 1.7f); | ||||
| 					int Pz = (int)currentPos.z; | ||||
|  | ||||
| 					if (!(Bx == Px && | ||||
| 						(By == PyA || | ||||
| 							By == PyB || | ||||
| 							By == PyC) && | ||||
| 						Bz == Pz)) | ||||
| 						found = true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	if (found && (int)currentBlock.y < CHUNK_SIZE_Y) { | ||||
| 		int bx = (int)currentBlock.x % CHUNK_SIZE_X; | ||||
| 		int by = (int)currentBlock.y % CHUNK_SIZE_Y; | ||||
| 		int bz = (int)currentBlock.z % CHUNK_SIZE_Z; | ||||
|  | ||||
| 		ChunkAt(currentBlock)->SetBlock(bx, by, bz, blockType, this); | ||||
| 		ChunkAt(currentBlock)->MakeModified(); | ||||
| 		block = true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader) { | ||||
| 	shader.Use(); | ||||
| 	rendercount = 0; | ||||
| 	badhitcount = 0; | ||||
| 	static std::vector<Vector3i> renderManifest; | ||||
| 	Vector3f angle; | ||||
| 	Vector3f cursor; | ||||
| 	Vector3f direct = player.GetDirection(); | ||||
| 	Vector3f pos = player.GetPosition() - direct; | ||||
|  | ||||
| 	direct.y = 0; | ||||
| 	direct.Normalize(); | ||||
| 	pos.y = 1; | ||||
| 	renderManifest.clear(); | ||||
|  | ||||
| 	for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) { | ||||
| 		// Configuration du radar. | ||||
| 		angle.x = direct.z + direct.x; | ||||
| 		angle.y = 0; | ||||
| 		angle.z = direct.z - direct.x; | ||||
| 		angle.Normalize(); | ||||
|  | ||||
| 		float sinus = .01745240643; // sin(1 degr<67>) | ||||
| 		float cosinus = .99984769515; // cos(1 degr<67>) | ||||
| 		int echantillons = 90; | ||||
|  | ||||
| 		for (int radar = 0; radar < echantillons; ++radar) { | ||||
| 			float x = angle.x; | ||||
| 			float z = angle.z; | ||||
|  | ||||
| 			angle.x = x * cosinus - z * sinus; | ||||
| 			angle.z = z * cosinus + x * sinus; | ||||
| 			angle.Normalize(); | ||||
|  | ||||
| 			cursor = pos - direct * CHUNK_SIZE_X * 2 + angle * dist; | ||||
| 			if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = 1; | ||||
|  | ||||
| 			bool valide = true; | ||||
|  | ||||
| 			if (ChunkAt(cursor)) { | ||||
| 				int chx, chy; | ||||
| 				ChunkAt(cursor)->GetPosition(chx, chy); | ||||
| 				for (int index = 0; index < renderManifest.size(); ++index) | ||||
| 					if (renderManifest[index] == Vector3i(chx, 0, chy)) { | ||||
| 						valide = false; | ||||
| 						++badhitcount; | ||||
| 					} | ||||
|  | ||||
| 				if (valide) { | ||||
| 					world.ApplyTranslation((chx - m_center[0]) * CHUNK_SIZE_X, 0, (chy - m_center[1]) * CHUNK_SIZE_Z); | ||||
| 					world.Use(); | ||||
| 					float dist = (pos - cursor).Length(); | ||||
| 					float blend = ((float)VIEW_DISTANCE - dist * 2.f + 128.f) / (float)VIEW_DISTANCE; | ||||
| 					glBlendColor(0.f, 0.f, 0.f, blend); | ||||
| 					ChunkAt(cursor)->Render(); | ||||
| 					world.ApplyTranslation(-(chx - m_center[0]) * CHUNK_SIZE_X, 0, -(chy - m_center[1]) * CHUNK_SIZE_Z); | ||||
| 					renderManifest.push_back(Vector3i(chx, 0, chy)); | ||||
| 					++rendercount; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	shader.Disable(); | ||||
| }; | ||||
|  | ||||
| void World::UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) { | ||||
| 	int cx = player.GetPosition().x; | ||||
| 	int cy = player.GetPosition().z; | ||||
| 	static int frameGenerate = 0; | ||||
| 	static int frameUpdate = 0; | ||||
| 	static int frameDelete = 0; | ||||
| 	int side = 0; | ||||
|  | ||||
| 	if (frameGenerate > 0) --frameGenerate; | ||||
| 	if (frameUpdate > 0) --frameUpdate; | ||||
| 	if (frameDelete > 0) --frameDelete; | ||||
|  | ||||
| 	if (!frameGenerate || !frameUpdate) | ||||
| 		while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) { | ||||
| 			int tx = -side, ty = -side; | ||||
|  | ||||
| 			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); | ||||
|  | ||||
| 			++side; | ||||
| 		} | ||||
|  | ||||
| 	CleanUpWorld(frameDelete); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user