Merge branch 'SQC-15_paquets' into SQC-15_animation

This commit is contained in:
Claudel-D-Roy 2023-11-15 11:35:03 -05:00
commit dc0d2d8148
19 changed files with 395 additions and 160 deletions

View File

@ -1024,6 +1024,82 @@ std::vector<char*> netprot::recvPacks(SOCKET sock, Buffer* buf, Buffer* outbuf)
}
}
std::vector<char*> netprot::recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* outbuf) {
std::vector<char*> lsPck;
int len = buf->tmp ? buf->tmp - buf->ptr : 0,
end = 0;
char* cursor = buf->tmp ? buf->tmp : nullptr,
* next = buf->tmp ? buf->tmp + 1 : buf->ptr,
* last = buf->tmp ? buf->tmp : buf->ptr;
bool ended = true;
struct pollfd fds[1];
sockaddr_in sockad = from;
addrlen_t socklen = sizeof(sockad);
fds[0].fd = sock;
fds[0].events = POLLIN;
while (true) {
if (!poll(fds, 1, 0)) {
if (ended)
buf->tmp = nullptr;
return lsPck;
}
int bytes = recvfrom(sock, &buf->ptr[len], buf->len - len, 0, (sockaddr*)&sockad, &socklen);
if (bytes <= 0) { // si recv() retourne -1 ou 0; ça veut dire qu'il y a plus rien a lire qui n'a pas déjà été traité.
if (ended)
buf->tmp = nullptr;
return lsPck;
}
len += bytes;
end = len;
ended = false;
while (true) {
int cmp = 0;
if (cursor)
end -= (cursor - buf->ptr);
if (end < 0)
break;
cursor = (char*)memchr(next, '\r', end);
if (cursor) {
next = cursor;
cursor--;
cmp = memcmp(cursor, Footer, sizeof(uint32_t));
if (cmp == 0) {
if (!outbuf) {
lsPck.push_back(last);
cursor += sizeof(uint32_t);
last = cursor;
next = cursor + 1;
}
else {
memcpy(&outbuf->ptr[cursor - last], last, cursor - last);
lsPck.push_back(&outbuf->ptr[cursor - last]);
cursor += sizeof(uint32_t);
last = cursor;
next = cursor + 1;
}
}
}
else {
if (!outbuf)
buf->tmp = last;
cursor = &buf->ptr[len];
next = cursor + 1;
break;
};
}
}
}
template <>
void netprot::sendPack<netprot::Packet>(SOCKET sock, Packet* pack, Buffer* buf) {
switch (pack->type) {

View File

@ -177,6 +177,7 @@ namespace netprot {
template <class T> void sendPackTo(SOCKET sock, T* pack, Buffer* buf, sockaddr_in* sockad);
std::vector<char*> recvPacks(SOCKET sock, Buffer* buf, Buffer* oufbuf = nullptr);
std::vector<char*> recvPacksFrom(SOCKET sock, Buffer* buf, sockaddr_in from, Buffer* oufbuf = nullptr);
/* Templates */

View File

@ -192,6 +192,8 @@ void Player::ApplyTransformation(Transformation& transformation, bool rel) const
if (rel) transformation.ApplyTranslation(-GetPOV());
}
void Player::SetDirection(Vector3f dir) { m_direction = dir; }
Vector3f Player::GetPosition() const { return Vector3f(m_position.x + CHUNK_SIZE_X * WORLD_SIZE_X / 2, m_position.y, m_position.z + CHUNK_SIZE_Z * WORLD_SIZE_Y / 2); }
Vector3f Player::GetVelocity() const { return m_velocity; }

View File

@ -21,6 +21,7 @@ public:
Sound ApplyPhysics(Vector3f input, World* world, float elapsedTime);
void ApplyTransformation(Transformation& transformation, bool rel = true) const;
void SetDirection(Vector3f dir);
Vector3f GetPosition() const;
Vector3f GetDirection() const;
Vector3f GetVelocity() const;

View File

@ -16,6 +16,9 @@ void World::SetSeed(uint64_t seed) {
m_seed = seed;
}
Chunk* World::ChunkAt(float x, float y, float z) const {
int cx = (int)x / CHUNK_SIZE_X;
int cz = (int)z / CHUNK_SIZE_Z;
@ -31,6 +34,32 @@ Chunk* World::ChunkAt(float x, float y, float z) const {
Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); }
void World::RemoveChunk(int nbReduit)
{
for (int x = 0; x < WORLD_SIZE_X; ++x)
for (int y = 0; y < WORLD_SIZE_Y; ++y)
{
Chunk* chk = nullptr;
if (x < nbReduit)
chk = m_chunks.Remove(x, y);
if (y < nbReduit)
chk = m_chunks.Remove(x, y);
if (y > WORLD_SIZE_Y - nbReduit)
chk = m_chunks.Remove(x, y);
if (x > WORLD_SIZE_X - nbReduit)
chk = m_chunks.Remove(x, y);
// TODO: MakeDirty() les voisins pour qu'ils se redessinent.
if (!chk)
continue;
m_tbDeleted.emplace_back(chk);
}
}
BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const {
Chunk* c = ChunkAt(x, y, z);

View File

@ -28,6 +28,8 @@ public:
Chunk* ChunkAt(float x, float y, float z) const;
Chunk* ChunkAt(const Vector3f& pos) const;
void RemoveChunk(int nbReduit);
BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const;
BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const;

View File

@ -47,6 +47,70 @@ PlayerInfo* Connection::getInfo() const { return (PlayerInfo*)&m_playinfo; }
sockaddr_in* Connection::getAddr() const { return (sockaddr_in*)&m_addr; }
void Connection::getPacks(SOCKET sock) {
std::vector<char*> lsPck;
Input in;
while (true) {
lsPck = recvPacksFrom(sock, &m_buf, m_addr);
for (auto& pck : lsPck) {
uint32_t bsize = m_buf.len - (pck - m_buf.ptr);
switch (netprot::getType(pck, 1)) {
using enum netprot::PACKET_TYPE;
case INPUT:
if (Deserialize(&in, pck, &bsize))
m_input_manifest[in.timestamp] = in;
break;
default: break;
}
}
lsPck.clear();
}
}
void Connection::sendPacks(SOCKET sock, std::unordered_map<uint64_t, Connection*> conns) {
while (m_last_out < m_output_manifest.size()) {
Output out = m_output_manifest.at(m_last_out++);
for (auto& [key, conn] : conns) {
if (m_playinfo.id == conn->GetHash(true))
continue;
sendPackTo<Output>(sock, &out, &m_bufout, conn->getAddr());
}
}
}
void Connection::Run(World* world) {
Input in, last;
Output out;
float el;
if (m_input_manifest.size() < 2)
return;
while (m_last_in < m_input_manifest.size()) {
in = m_input_manifest.at(m_last_in + 1);
last = m_input_manifest.at(m_last_in);
el = (float)(in.timestamp - last.timestamp) / 1000.;
player.get()->SetDirection(in.direction);
player.get()->ApplyPhysics(player.get()->GetInput(in.keys.forward,
in.keys.backward,
in.keys.left,
in.keys.right,
in.keys.jump, false, el), world, el);
out.position = player.get()->GetPosition();
out.direction = in.direction;
out.timestamp = in.timestamp;
out.id = m_playinfo.id;
m_output_manifest[out.timestamp] = out;
++m_last_in;
}
}
void Connection::CleanInputManifest(Timestamp time) {
auto wat = m_input_manifest.find(time);

View File

@ -6,6 +6,7 @@
#include "../SQCSim-common/player.h"
#include "../SQCSim-common/vector3.h"
#include "../SQCSim-common/netprotocol.h"
#include "../SQCSim-common/world.h"
#include "define.h"
using namespace netprot;
@ -32,6 +33,11 @@ public:
PlayerInfo* getInfo() const;
sockaddr_in* getAddr() const;
void getPacks(SOCKET sock);
void sendPacks(SOCKET sock, std::unordered_map<uint64_t, Connection*> conns);
void Run(World* world);
void CleanInputManifest(Timestamp time);
private:
std::unordered_map<Timestamp, Input> m_input_manifest;
@ -43,5 +49,11 @@ private:
LoginInfo m_loginfo;
PlayerInfo m_playinfo;
Timestamp m_startsync;
uint64_t m_last_in = 0,
m_last_out = 0;
Buffer m_buf,
m_bufout;
};
#endif

View File

@ -155,7 +155,7 @@ int Server::Ready() {
play.tid = log->tid;
sendPack<GameInfo>(sock, &m_game, &m_buf);
std::unique_ptr<Connection> conn = std::make_unique<Connection>(sock, sockad, *log, play);
Connection* conn = new Connection(sock, sockad, *log, play);
for (auto& [key, player] : m_players) {
sendPack<PlayerInfo>(player->getSock(), &play, &m_buf); // Envoyer les infos de joueur distant aux joueurs d<>j<EFBFBD> connect<63>s
@ -175,13 +175,16 @@ int Server::Ready() {
}
void Server::Run() {
bool endgame = false;
Input in;
sockaddr_in sockad;
addrlen_t socklen = sizeof(sockad);
Log("Debut de la partie...", false, false);
m_world = std::make_unique<World>();
int players = m_players.size();
m_world = new World();
m_world->SetSeed(m_game.seed);
m_world->GetChunks().Reset(nullptr);
m_world->BuildWorld();
@ -198,32 +201,41 @@ void Server::Run() {
sendPack<Sync>(conn->getSock(), &sync, &m_buf);
}
while (true) {
if (recvfrom(m_sock_udp, m_buf.ptr, m_buf.len, 0, (sockaddr*)&sockad, &socklen) > 0) {
Packet pck = getPack(&m_buf);
switch (pck.type) {
using enum netprot::PACKET_TYPE;
case ERR: std::puts("ERROR!"); break;
case INPUT: std::puts("INPUT!"); break;
case OUTPUT: std::puts("OUTPUT!"); break;
case SYNC: std::puts("SYNC!"); break;
case TEAMINF: std::puts("TEAMINF!"); break;
case SELFINF: std::puts("SELFINF!"); break;
case PLAYINF: std::puts("PLAYINF!"); break;
case LOGINF: std::puts("LOGINF!"); break;
case CHUNKMOD: std::puts("CHUNKMOD!"); break;
case PLAYERMOD: std::puts("PLAYERMOD!"); break;
case PICKUPMOD: std::puts("PICKUPMOD!"); break;
case GAMEINFO: std::puts("GAMEINFO!"); break;
case ENDINFO: std::puts("ENDINFO!"); break;
case CHAT: std::puts("CHAT!"); break;
case ERRLOG: std::puts("ERRLOG!"); break;
case LAST_PACK: [[falltrough]];
default: std::puts("wtf?!"); break;
}
netprot::emptyPack(pck);
}
while (!endgame) {
for (auto& [key, conn] : m_players) {
conn->getPacks(m_sock_udp);
conn->Run(m_world);
conn->sendPacks(m_sock_udp, m_players);
}
}
//while (true) {
// if (recvfrom(m_sock_udp, m_buf.ptr, m_buf.len, 0, (sockaddr*)&sockad, &socklen) > 0) {
// Packet pck = getPack(&m_buf);
// switch (pck.type) {
// using enum netprot::PACKET_TYPE;
// case ERR: std::puts("ERROR!"); break;
// case INPUT: std::puts("INPUT!"); break;
// case OUTPUT: std::puts("OUTPUT!"); break;
// case SYNC: std::puts("SYNC!"); break;
// case TEAMINF: std::puts("TEAMINF!"); break;
// case SELFINF: std::puts("SELFINF!"); break;
// case PLAYINF: std::puts("PLAYINF!"); break;
// case LOGINF: std::puts("LOGINF!"); break;
// case CHUNKMOD: std::puts("CHUNKMOD!"); break;
// case PLAYERMOD: std::puts("PLAYERMOD!"); break;
// case PICKUPMOD: std::puts("PICKUPMOD!"); break;
// case GAMEINFO: std::puts("GAMEINFO!"); break;
// case ENDINFO: std::puts("ENDINFO!"); break;
// case CHAT: std::puts("CHAT!"); break;
// case ERRLOG: std::puts("ERRLOG!"); break;
// case LAST_PACK: [[falltrough]];
// default: std::puts("wtf?!"); break;
// }
// netprot::emptyPack(pck);
// }
//}
}
inline std::string Server::LogTimestamp() {

View File

@ -36,12 +36,12 @@ private:
Buffer m_buf;
std::unordered_map<uint64_t, std::unique_ptr<Connection>> m_players;
std::unordered_map<uint64_t, Connection*> m_players;
std::unordered_map<Timestamp, Chat> m_chatlog;
std::vector<uint64_t> m_ids;
GameInfo m_game;
std::unique_ptr<World> m_world = nullptr;
World* m_world = nullptr;
const bool m_manual_setup = SRV_MANUAL_SETUP;
std::string LogTimestamp();

View File

@ -276,9 +276,46 @@ void Engine::DrawMenu()
ShowCursor();
}
void Engine::Init() {
void Engine::DrawPause()
{
static const int sTitle = 400;
static const int sButton = 225;
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, Width(), 0, Height(), -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
PauseBGTexture.Bind();
glLoadIdentity();
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2i(0, 0);
glTexCoord2f(1, 0);
glVertex2i(800, 0);
glTexCoord2f(1, 1);
glVertex2i(800, 600);
glTexCoord2f(0, 1);
glVertex2i(0, 600);
glEnd();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
ShowCursor();
}
void Engine::Init() {
GLenum glewErr = glewInit();
if (glewErr != GLEW_OK) {
@ -307,6 +344,10 @@ void Engine::Init() {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_SUBTRACT);
if (m_istarted)
return;
else m_istarted = true;
//
// Objet de skybox avec sa propre texture et son propre shader!
m_skybox.Init(0.2f);
@ -396,15 +437,12 @@ void Engine::LoadResource() {
LoadTexture(MenuTitleTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png");
LoadTexture(MenuBGTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png");
LoadTexture(PauseBGTexture, TEXTURE_PATH "BrouillonbackgroundMenu.png");
LoadTexture(SplachScreenTexture, TEXTURE_PATH "sc2.png");
LoadTexture(MenuQuitTexture, MENU_ITEM_PATH "BasicQuit.png");
LoadTexture(MenuOptionsTexture, MENU_ITEM_PATH "test.png");
LoadTexture(MenuStartTexture, MENU_ITEM_PATH "BasicPlay.png");
TextureAtlas::TextureIndex texDirtIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal3.png");
TextureAtlas::TextureIndex texIceIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal2.png");
TextureAtlas::TextureIndex texGrassIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "grass.png");
@ -895,7 +933,13 @@ void Engine::DrawHud(float elapsedTime, BlockType bloc) {
glPushMatrix();
int timer = GetCountdown(elapsedTime);
for (int i = 1; i < WORLD_SIZE_X; i++)
{
if (timer <= COUNTDOWN - m_timerReductionChunk * i) {
m_world.RemoveChunk(m_nbReductionChunk * i);
m_renderer.RemoveChunk(m_nbReductionChunk * i);
}
}
if (m_keyK) {
SystemNotification(m_messageNotification);
m_keyK = false;
@ -960,12 +1004,13 @@ void Engine::PrintText(float x, float y, const std::string& t, float charSizeMul
}
}
int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; }
int Engine::GetCountdown(float elapsedTime) {
if (m_resetcountdown)
{
m_nbReductionChunk = 4;
m_timerReductionChunk = 30;
m_countdown = m_time + COUNTDOWN;
m_resetcountdown = false;
}
@ -1001,7 +1046,6 @@ void Engine::Render(float elapsedTime) {
Transformation all;
Transformation skybox;
Transformation remotePlayer;
Vector3f vstep;
// Transformations initiales
@ -1032,16 +1076,15 @@ void Engine::Render(float elapsedTime) {
pollTime = 0;
}
RenderRemotePlayers(m_remotePlayer, pollTime);
m_player.ApplyTransformation(all);
m_player.ApplyTransformation(skybox, false); // Version d'ApplyTransformation qui ne tient compte que de la rotation
// (donc l'objet ne bouge pas relativement au joueur, ce qui est pratique pour une skybox!).
//m_remotePlayer.ApplyTransformation(all);
if (m_mouseWU) bloc++;
else if (m_mouseWD) bloc--;
@ -1097,16 +1140,15 @@ void Engine::Render(float elapsedTime) {
}
}
m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas);
if (m_isSkybox) m_renderer.RenderWorld(&m_world, m_renderCount, m_player.GetPosition(), m_player.GetDirection(), all, m_shader01, m_textureAtlas);
m_world.Update(m_bullets, m_player.GetPosition(), m_blockinfo);
m_renderer.UpdateMesh(&m_world, m_player.GetPosition(), m_blockinfo);
m_remotePlayer.Render(m_textureAtlas, m_shader01, elapsedTime);
if (m_isSkybox) m_skybox.Render(skybox);
DrawHud(elapsedTime, bloc);
DisplayPovGun();
if (m_isSkybox) DrawHud(elapsedTime, bloc);
if (m_isSkybox) DisplayPovGun();
ProcessNotificationQueue();
if (m_damage)
{
@ -1122,14 +1164,26 @@ void Engine::Render(float elapsedTime) {
fell = false;
}
if (m_networkgame) {
if (m_networkgame) { // Pour se gerer le paquet.
using namespace std::chrono;
using namespace netprot;
Timestamp tstamp = duration_cast<milliseconds>(high_resolution_clock::now() - m_startTime).count();
Input input;
Sync sync;
uint64_t id = m_conn.getId();
static std::vector<char*> lsPck;
input.sid = m_conn.getId();
if (false) { // TODO: Faire un checkup pour chaque ~1000ms.
sync.sid = id;
sync.timestamp = tstamp;
sync.position = m_player.GetPosition();
sync.hp = m_player.GetHP();
// TODO: Garrocher ca quelque-part.
}
input.sid = id;
input.direction = m_player.GetDirection();
input.timestamp = duration_cast<milliseconds>(high_resolution_clock::now() - m_startTime).count();
input.timestamp = tstamp;
input.keys.forward = m_keyW;
input.keys.backward = m_keyS;
input.keys.left = m_keyA;
@ -1138,13 +1192,38 @@ void Engine::Render(float elapsedTime) {
input.keys.block = m_mouseR;
input.keys.shoot = m_mouseL;
sendPackTo<Input>(m_conn.m_sock_udp, &input, &m_buf, &m_conn.m_srvsockaddr);
// TODO: Faire la gestion de la réception de paquets.
sendPackTo<Input>(m_conn.m_sock_udp, &input, &m_bufout, &m_conn.m_srvsockaddr);
lsPck = recvPacks(m_conn.m_sock_udp, &m_buf);
char* prevptr = nullptr;
for (auto& pck : lsPck) { // We could make a few threads out of this.
Sync sync;
Output out;
if (!prevptr)
prevptr = m_buf.ptr;
uint32_t bsize = m_buf.len - (pck - prevptr);
prevptr = pck;
switch (getType(pck, 1)) {
using enum PACKET_TYPE;
case SYNC:
if (Deserialize(&sync, pck, &bsize)) {
if (sync.sid != m_conn.getId())
break;
// TODO: Vérifier si les positions concordent au sync local.
}
break;
case OUTPUT:
if (Deserialize(&out, pck, &bsize)) {
RemotePlayer* r = (RemotePlayer*)m_players[out.id];
r->Feed(out);
}
break;
default:
break;
}
}
lsPck.clear();
}
}
else if (m_gamestate == GameState::MAIN_MENU || m_gamestate == GameState::OPTIONS)
{
@ -1155,11 +1234,12 @@ void Engine::Render(float elapsedTime) {
DrawMenu();
}
}
else if (m_gamestate == GameState::PAUSE)
{
DrawPause();
}
else if (m_gamestate == GameState::QUIT)
Stop();
}
void Engine::KeyPressEvent(unsigned char key) {
@ -1185,7 +1265,14 @@ void Engine::KeyPressEvent(unsigned char key) {
}
break;
case 36: // ESC - Quitter
m_gamestate = GameState::MAIN_MENU;
if (m_gamestate == GameState::PLAY)
{
m_gamestate = GameState::PAUSE;
}
else if (m_gamestate == GameState::PAUSE)
{
m_gamestate = GameState::PLAY;
}
//Stop();
break;
case 57: // Space - Sauter
@ -1420,7 +1507,3 @@ bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool use
return true;
}
void Engine::RenderRemotePlayers(RemotePlayer& remoteplayer, float elapsedTime)
{
remoteplayer.Render(m_textureAtlas, m_shader01, elapsedTime);
}

View File

@ -29,6 +29,7 @@ public:
Engine();
virtual ~Engine();
virtual void DrawMenu();
virtual void DrawPause();
virtual void DrawSplachScreen();
virtual void Init();
virtual void DeInit();
@ -94,17 +95,18 @@ private:
Bullet* m_bullets[MAX_BULLETS];
std::unordered_map<uint64_t, Player*> m_players;
netprot::Buffer m_buf;
netprot::Buffer m_buf, m_bufout;
std::chrono::high_resolution_clock::time_point m_startTime;
//Menu
enum class GameState: uint8_t { MAIN_MENU, OPTIONS, QUIT, NEWG, PLAY };
enum class GameState: uint8_t { MAIN_MENU, OPTIONS, QUIT, NEWG, PLAY, PAUSE };
GameState m_gamestate = GameState::MAIN_MENU;
Texture MenuTitleTexture;
Texture MenuBGTexture;
Texture MenuStartTexture;
Texture MenuQuitTexture;
Texture MenuOptionsTexture;
Texture PauseBGTexture;
Texture SplachScreenTexture;
@ -118,6 +120,8 @@ private:
int m_renderCount = 0;
int m_countdown = COUNTDOWN;
int m_nbReductionChunk = 4;
int m_timerReductionChunk = 30;
bool m_damage = false;

View File

@ -9,7 +9,7 @@ Mesh::~Mesh() {
void Mesh::FlushMeshToVBO() {
m_vertexBuffer.SetMeshData(m_vd, m_vcount);
m_vcount = 0;
//delete[] m_vd;
delete[] m_vd;
}
void Mesh::FlushVBO() {

View File

@ -15,7 +15,7 @@ private:
Chunk* m_chunk; // NE PAS DÉTRUIRE ICI.
void AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt, int x, int y, int z, float u, float v, float s, World* world);
void RemoveChunk(int nbReduit);
public:
Mesh(Chunk* chunk);
~Mesh();

View File

@ -52,6 +52,8 @@ protected:
void HideCursor();
void ShowCrossCursor() const;
bool m_istarted = false;
private:
void InitWindow(int width, int height);
MOUSE_BUTTON ConvertMouseButton(sf::Mouse::Button button) const;

View File

@ -71,101 +71,20 @@ void RemotePlayer::Feed(const netprot::Output out) {
void RemotePlayer::Render(TextureAtlas& atlas, Shader& shader, float elapsedTime)
{
m_texture_front.Bind();
shader.Use();
//m_texture_front.Bind();
//float x = current.position.x;
//float y = current.position.y;
//float z = current.position.z;
float x = 128.0f;
float y = 21.0f;
float z = 128.0f;
float quadSize = 300.0f;
float u, v, w, h;
atlas.Bind();
atlas.TextureIndexToCoord(0, u, v, w, h);
glBegin(GL_QUADS);
glNormal3f(0, 0, 1);
// Face avant
glTexCoord2f(0, 0);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2);
// Face arričre
glTexCoord2f(0, 0);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2);
// Face droite
glTexCoord2f(0, 0);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2);
// Face gauche
glTexCoord2f(0, 0);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2);
// Face supérieure
glTexCoord2f(0, 0);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z + quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x + quadSize / 2, y + quadSize / 2, z - quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x - quadSize / 2, y + quadSize / 2, z - quadSize / 2);
// Face inférieure
glTexCoord2f(0, 0);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 0);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z - quadSize / 2);
glTexCoord2f(1, 1);
glVertex3f(x + quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(0, 1);
glVertex3f(x - quadSize / 2, y - quadSize / 2, z + quadSize / 2);
glTexCoord2f(u, v); glVertex3f(0, 50., 0);
glTexCoord2f(u+w, v); glVertex3f(50., 50., 0);
glTexCoord2f(u+w, v+h); glVertex3f(50., 0, 0);
glTexCoord2f(u, v+h); glVertex3f(0, 0, 0);
glEnd();
shader.Disable();
}
bool RemotePlayer::LoadTexture(Texture& texture, const std::string& filename, bool useMipmaps, bool stopOnError)

View File

@ -7,6 +7,32 @@ Renderer::Renderer() {
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;

View File

@ -21,6 +21,8 @@ public:
Renderer();
~Renderer();
void RemoveChunk(int nbReduit);
void UpdateMesh(World* origin, const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]);
void RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation& world, Shader& shader, TextureAtlas& atlas) const;