278 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "renderer.h"
 | ||
| #include <iostream>
 | ||
| #include <cstring>
 | ||
| 
 | ||
| #include <thread>
 | ||
| #include <queue>
 | ||
| 
 | ||
| Renderer::Renderer() {
 | ||
| 	m_meshes.Reset(nullptr);
 | ||
| }
 | ||
| 
 | ||
| Renderer::~Renderer() {
 | ||
| }
 | ||
| 
 | ||
| void Renderer::RemoveChunk(int nbReduit)
 | ||
| {
 | ||
| 	for (int x = 0; x < WORLD_SIZE_X; ++x)
 | ||
| 		for (int y = 0; y < WORLD_SIZE_Y; ++y)
 | ||
| 		{
 | ||
| 			Mesh* chk = nullptr;
 | ||
| 			if (x < nbReduit)
 | ||
| 				chk = m_meshes.Remove(x, y);
 | ||
| 			if (y < nbReduit)
 | ||
| 				chk = m_meshes.Remove(x, y);
 | ||
| 			if (y > WORLD_SIZE_Y - nbReduit)
 | ||
| 				chk = m_meshes.Remove(x, y);
 | ||
| 			if (x > WORLD_SIZE_X - nbReduit)
 | ||
| 				chk = m_meshes.Remove(x, y);
 | ||
| 
 | ||
| 			// TODO: MakeDirty() les voisins pour qu'ils se redessinent.
 | ||
| 
 | ||
| 			if (!chk)
 | ||
| 				continue;
 | ||
| 
 | ||
| 			delete chk;
 | ||
| 		}
 | ||
| 
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| void Renderer::RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation world, Shader& shader, TextureAtlas& atlas) const {
 | ||
| 	rendercount = 0;
 | ||
| 	Vector3f angle;
 | ||
| 	Vector3f cursor;
 | ||
| 	Vector3f direct = player_dir;
 | ||
| 	Vector3f pos = player_pos - direct;
 | ||
| 
 | ||
| 	direct.y = 0;
 | ||
| 	direct.Normalize();
 | ||
| 	pos.y = 1;
 | ||
| 
 | ||
| 	static Vector3<unsigned int> renderManifest[VIEW_DISTANCE * 8]; // Nombre de Chunks maximal <20> <20>tre rendus.
 | ||
| 
 | ||
| 	//for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
 | ||
| 	for (int dist = 0; dist <= VIEW_DISTANCE; dist += CHUNK_SIZE_X) {
 | ||
| 		// Configuration du radar.
 | ||
| 		float sinus, cosinus;
 | ||
| 		int echantillons;
 | ||
| 
 | ||
| 		if (dist > VIEW_DISTANCE * .1f) {
 | ||
| 			sinus = .00872653549f; // sin(1/2 degr<67>)
 | ||
| 			cosinus = .99996192306; // cos(1/2 degr<67>)
 | ||
| 			echantillons = 180;
 | ||
| 		}
 | ||
| 		//else {//if (dist > VIEW_DISTANCE * .3f) {
 | ||
| 		//	sinus = .01151891831f; // sin(2/3 degr<67>)
 | ||
| 		//	cosinus = .99993365506; // cos(2/3 degr<67>)
 | ||
| 		//	echantillons = 120;
 | ||
| 		//}
 | ||
| 		//else if (dist > VIEW_DISTANCE * .2f) {
 | ||
| 		//	sinus = .01745240643; // sin(1 degr<67>)
 | ||
| 		//	cosinus = .99984769515; // cos(1 degr<67>)
 | ||
| 		//	echantillons = 90;
 | ||
| 		//}
 | ||
| 		//else if (dist > VIEW_DISTANCE * .1f) {
 | ||
| 		//	sinus = .0261769483;
 | ||
| 		//	cosinus = .99965732497;
 | ||
| 		//	echantillons = 60;
 | ||
| 		//}
 | ||
| 		else {
 | ||
| 			sinus = .0348994967;
 | ||
| 			cosinus = .99939082701;
 | ||
| 			echantillons = 45;
 | ||
| 		}
 | ||
| 
 | ||
| 		angle.x = direct.z + direct.x;
 | ||
| 		angle.z = direct.z - direct.x;
 | ||
| 		angle.y = 0;
 | ||
| 		angle.Normalize();
 | ||
| 
 | ||
| 		for (int radar = 0; radar < echantillons; ++radar) {
 | ||
| 			float x = angle.x;
 | ||
| 
 | ||
| 			angle.x = angle.x * cosinus - angle.z * sinus;
 | ||
| 			angle.z = angle.z * cosinus + x * sinus;
 | ||
| 			angle.Normalize();
 | ||
| 
 | ||
| 			cursor = pos - direct * CHUNK_SIZE_X * 4 + angle * dist;
 | ||
| 			if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = CHUNK_SIZE_Y / 4.f;
 | ||
| 
 | ||
| 
 | ||
| 			if (origin->ChunkAt(cursor)) {
 | ||
| 				bool valide = true;
 | ||
| 				unsigned int chx, chy;
 | ||
| 				origin->ChunkAt(cursor)->GetPosition(chx, chy);
 | ||
| 				for (int index = 0; index < rendercount; ++index) // Permet de v<>rifier seulement contre celles ajout<75>es dans la frame, et ne pas avoir <20> refaire l'array <20> chaque frame.
 | ||
| 					if (renderManifest[index].x == chx && renderManifest[index].z == chy)
 | ||
| 						valide = false;
 | ||
| 
 | ||
| 				if (valide) renderManifest[rendercount++] = Vector3<unsigned int>(chx,
 | ||
| 					(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) < 0.f ? 0 :
 | ||
| 					(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) * 1000,
 | ||
| 					chy);
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 	shader.Use();
 | ||
| 	atlas.Bind();
 | ||
| 	glStencilFunc(GL_EQUAL, 1, 0x00);
 | ||
| 	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
 | ||
| 
 | ||
| 	unsigned int sx, sy, cx, cy;
 | ||
| 	origin->GetScope(sx,sy);
 | ||
| 
 | ||
| 	for (int index = 0; index < rendercount; ++index) {
 | ||
| 		int chx = (renderManifest[index].x - sx) * CHUNK_SIZE_X, chy = (renderManifest[index].z - sy) * CHUNK_SIZE_Z;
 | ||
| 
 | ||
| 		world.ApplyTranslation(chx, 0, chy);
 | ||
| 		glLoadMatrixf(world.GetMatrix().GetInternalValues());
 | ||
| 		float blcolor = renderManifest[index].y / (VIEW_DISTANCE / 50.f);
 | ||
| 		glBlendColor(blcolor, blcolor, blcolor, 1.f);
 | ||
| 		origin->ChunkAt(chx, 1, chy)->GetPosition(cx,cy);
 | ||
| 		if (m_meshes.Get(cx - sx, cy - sy))
 | ||
| 			m_meshes.Get(cx - sx, cy -sy)->Render();
 | ||
| 		world.ApplyTranslation(-chx, 0, -chy);
 | ||
| 	}
 | ||
| 	shader.Disable();
 | ||
| 	glStencilFunc(GL_GREATER, 1, 0xFF);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| void Renderer::UpdateMesh(World* origin, const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]) {
 | ||
| 	int cx = player.x;
 | ||
| 	int cy = player.z;
 | ||
| 	static int frameUpdate = 2;
 | ||
| 	int side = 0;
 | ||
| 	int threads = 0;
 | ||
| 	std::future<Mesh*> updateThList[THREADS_UPDATE_CHUNKS];
 | ||
| 
 | ||
| 	unsigned int mx = 0 , my = 0, sx, sy;
 | ||
| 
 | ||
| 	origin->GetScope(sx, sy);
 | ||
| 
 | ||
| 	if (frameUpdate > 0) --frameUpdate;
 | ||
| 
 | ||
| 	if (!frameUpdate)
 | ||
| 		while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) {
 | ||
| 			int tx = -side, ty = -side;
 | ||
| 
 | ||
| 			for (; tx <= side; ++tx) {
 | ||
| 				if (frameUpdate)
 | ||
| 					break;
 | ||
| 				unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
 | ||
| 				if (origin->ChunkAt(chx, 1, chy) &&
 | ||
| 					origin->ChunkAt(chx, 1, chy)->IsDirty()) {
 | ||
| 					origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
 | ||
| 					if (m_meshes.Get(mx - sx, my - sy))
 | ||
| 						updateThList[threads++] =
 | ||
| 						std::async(std::launch::async,
 | ||
| 							[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
 | ||
| 								mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
 | ||
| 					else updateThList[threads++] = std::async(std::launch::async,
 | ||
| 						[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
 | ||
| 					if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
 | ||
| 				}
 | ||
| 			}
 | ||
| 			for (; ty <= side; ++ty) {
 | ||
| 				if (frameUpdate)
 | ||
| 					break;
 | ||
| 				unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
 | ||
| 				if (origin->ChunkAt(chx, 1, chy) &&
 | ||
| 					origin->ChunkAt(chx, 1, chy)->IsDirty()) {
 | ||
| 					origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
 | ||
| 					if (m_meshes.Get(mx - sx, my - sy))
 | ||
| 						updateThList[threads++] =
 | ||
| 						std::async(std::launch::async,
 | ||
| 							[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
 | ||
| 								mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
 | ||
| 					else updateThList[threads++] = std::async(std::launch::async,
 | ||
| 						[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
 | ||
| 					if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
 | ||
| 				}
 | ||
| 			}
 | ||
| 			for (; tx >= -side; --tx) {
 | ||
| 				if (frameUpdate)
 | ||
| 					break;
 | ||
| 				unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
 | ||
| 				if (origin->ChunkAt(chx, 1, chy) &&
 | ||
| 					origin->ChunkAt(chx, 1, chy)->IsDirty()) {
 | ||
| 					origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
 | ||
| 					if (m_meshes.Get(mx - sx, my - sy))
 | ||
| 						updateThList[threads++] =
 | ||
| 						std::async(std::launch::async,
 | ||
| 							[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
 | ||
| 								mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
 | ||
| 					else updateThList[threads++] = std::async(std::launch::async,
 | ||
| 						[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
 | ||
| 					if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
 | ||
| 				}
 | ||
| 			}
 | ||
| 			for (; ty >= -side; --ty) {
 | ||
| 				if (frameUpdate)
 | ||
| 					break;
 | ||
| 				unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
 | ||
| 				if (origin->ChunkAt(chx, 1, chy) &&
 | ||
| 					origin->ChunkAt(chx, 1, chy)->IsDirty()) {
 | ||
| 					origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
 | ||
| 					if (m_meshes.Get(mx - sx, my - sy))
 | ||
| 						updateThList[threads++] =
 | ||
| 						std::async(std::launch::async,
 | ||
| 							[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
 | ||
| 								mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
 | ||
| 					else updateThList[threads++] = std::async(std::launch::async,
 | ||
| 						[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
 | ||
| 					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();
 | ||
| 			Mesh* mesh = updateThList[i].get();
 | ||
| 			if (mesh->IsNew()) {
 | ||
| 				unsigned int x, y;
 | ||
| 				mesh->GetPosition(x, y, origin);
 | ||
| 				m_meshes.Set(x, y, mesh);
 | ||
| 			}
 | ||
| 			mesh->FlushMeshToVBO();
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| void Renderer::RenderBillboard(const Vector3f pos, TextureAtlas textureAtlas, TextureAtlas::TextureIndex idx, Shader& shader, Transformation tran)
 | ||
| {
 | ||
| 	//float x = pos.x;
 | ||
| 	//float y = pos.y;
 | ||
| 	//float z = pos.z;
 | ||
| 	//float width = 1.0f;
 | ||
| 	//float height = 1.0f;
 | ||
| 
 | ||
| 	//float u, v, w, h;
 | ||
| 	//shader.Use();
 | ||
| 	//textureAtlas.Bind();
 | ||
| 	//textureAtlas.TextureIndexToCoord(idx, u, v, w, h);
 | ||
| 
 | ||
| 	//glLoadMatrixf(tran.GetMatrix().GetInternalValues());
 | ||
| 	//glBegin(GL_QUADS);
 | ||
| 	//glTexCoord2f(u, v); glVertex3f(x - width / 2., y - height, z); //glVertex3f(v4.x, v4.y, v4.z);//glVertex3f(0, 50, 0);
 | ||
| 	//glTexCoord2f(u + w, v); glVertex3f(x + width / 2., y - height, z); //glVertex3f(v3.x, v3.y, v3.z); //glVertex3f(50,50, 0);
 | ||
| 	//glTexCoord2f(u + w, v + h); glVertex3f(x + width / 2., y, z); //glVertex3f(v2.x, v2.y, v2.z); //glVertex3f(50, 0, 0);
 | ||
| 	//glTexCoord2f(u, v + h); glVertex3f(x - width / 2., y, z); //glVertex3f(v1.x, v1.y, v1.z);// glVertex3f(0, 0, 0);
 | ||
| 	//glEnd();
 | ||
| 	//shader.Disable();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| void Renderer::RenderPlayer(Player* player, Transformation tran) const {
 | ||
| }
 | ||
| 
 | ||
| void Renderer::RenderPlayer(RemotePlayer* rplayer, const Vector3f& player_pos, const Vector3f& player_dir) const {
 | ||
| }
 | ||
| 
 |