diff --git a/SQCSim-common/SQCSim-common.vcxproj b/SQCSim-common/SQCSim-common.vcxproj index 15265fb..991cd1d 100644 --- a/SQCSim-common/SQCSim-common.vcxproj +++ b/SQCSim-common/SQCSim-common.vcxproj @@ -138,6 +138,7 @@ + @@ -148,6 +149,7 @@ + diff --git a/SQCSim-common/SQCSim-common.vcxproj.filters b/SQCSim-common/SQCSim-common.vcxproj.filters index a98dd18..26c6c05 100644 --- a/SQCSim-common/SQCSim-common.vcxproj.filters +++ b/SQCSim-common/SQCSim-common.vcxproj.filters @@ -51,6 +51,9 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + @@ -74,5 +77,8 @@ Fichiers sources + + Fichiers sources + \ No newline at end of file diff --git a/SQCSim-common/chunk.cpp b/SQCSim-common/chunk.cpp index 7bfc690..cb93218 100644 --- a/SQCSim-common/chunk.cpp +++ b/SQCSim-common/chunk.cpp @@ -1,13 +1,13 @@ #include "chunk.h" #include "world.h" -Chunk::Chunk(unsigned int x, unsigned int y) : m_posX(x), m_posY(y) { +Chunk::Chunk(unsigned int x, unsigned int y, int64_t seed) : m_posX(x), m_posY(y) { //std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position. //pos << CHUNK_PATH << x << '_' << y << ".chunk"; //std::ifstream input(pos.str(), std::fstream::binary); //if (input.fail()) { - OpenSimplexNoise::Noise simplex = OpenSimplexNoise::Noise(SEED); + OpenSimplexNoise::Noise simplex = OpenSimplexNoise::Noise(seed); m_blocks.Reset(BTYPE_AIR); for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // Montagnes @@ -98,14 +98,45 @@ Chunk::~Chunk() { void Chunk::RemoveBlock(int x, int y, int z, World* world) { m_blocks.Set(x, y, z, BTYPE_AIR); + CheckNeighbors(x, y, world); + m_isDirty = true; } void Chunk::SetBlock(int x, int y, int z, BlockType type, World* world) { m_blocks.Set(x, y, z, type); + if (world) CheckNeighbors(x, z, world); // Si nullptr, ne pas vérifier les chunks voisines. + m_isDirty = true; } BlockType Chunk::GetBlock(int x, int y, int z) { return m_blocks.Get(x, y, z); } +void Chunk::CheckNeighbors(unsigned int x, unsigned int z, World* world) { + unsigned int cx, cy; + + world->GetScope(cx, cy); + + if (x == 0 && m_posX - cx >= 0 && + world->ChunkAt((m_posX - cx - 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)) + world->ChunkAt((m_posX - cx - 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)->MakeDirty(); + else if (x == CHUNK_SIZE_X - 1 && m_posX - cx < WORLD_SIZE_X && + world->ChunkAt((m_posX - cx + 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)) + world->ChunkAt((m_posX - cx + 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)->MakeDirty(); + + if (z == 0 && m_posY - cy >= 0 && + world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy - 1) * CHUNK_SIZE_Z)) + world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy - 1) * CHUNK_SIZE_Z)->MakeDirty(); + else if (z == CHUNK_SIZE_X - 1 && m_posY - cy < WORLD_SIZE_Y && + world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy + 1) * CHUNK_SIZE_Z)) + world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy + 1) * CHUNK_SIZE_Z)->MakeDirty(); +} + void Chunk::GetPosition(unsigned int& x, unsigned int& y) const { x = m_posX; y = m_posY; } +bool Chunk::IsDirty() const { return m_isDirty; } + +void Chunk::MakeDirty() { m_isDirty = true; } + +void Chunk::MakeClean() { m_isDirty = false; } + void Chunk::MakeModified() { m_isModified = true; } + diff --git a/SQCSim-common/chunk.h b/SQCSim-common/chunk.h index ec015ba..ea4a949 100644 --- a/SQCSim-common/chunk.h +++ b/SQCSim-common/chunk.h @@ -1,30 +1,35 @@ #ifndef CHUNK_H__ #define CHUNK_H__ #include "define.h" -#include "array3d.h" #include "array2d.h" +#include "array3d.h" #include "blockinfo.h" #include "opensimplex.h" class World; class Chunk { - protected: + private: Array3d m_blocks = Array3d(CHUNK_SIZE_X, CHUNK_SIZE_Y, CHUNK_SIZE_Z); + bool m_isDirty = true; bool m_isModified = false; unsigned int m_posX; // Position du chunk dans l'array constituant le monde. unsigned int m_posY; public: - Chunk(unsigned int x, unsigned int y); + Chunk(unsigned int x, unsigned int y, int64_t seed); ~Chunk(); void RemoveBlock(int x, int y, int z, World* world); void SetBlock(int x, int y, int z, BlockType type, World* world); BlockType GetBlock(int x, int y, int z); + void CheckNeighbors(unsigned int x, unsigned int z, World* world); void GetPosition(unsigned int& x, unsigned int& y) const; + bool IsDirty() const; + void MakeDirty(); + void MakeClean(); void MakeModified(); }; diff --git a/SQCSim-common/define.h b/SQCSim-common/define.h index 0342359..f02d719 100644 --- a/SQCSim-common/define.h +++ b/SQCSim-common/define.h @@ -17,7 +17,15 @@ #define WORLD_SIZE_X 64 #define WORLD_SIZE_Y 64 -#define VIEW_DISTANCE 512 +#define FRAMES_RENDER_CHUNKS 1 +#define FRAMES_UPDATE_CHUNKS 1 +#define FRAMES_DELETE_CHUNKS 1 + +#define THREADS_GENERATE_CHUNKS 8 +#define THREADS_UPDATE_CHUNKS 3 +#define THREADS_DELETE_CHUNKS 3 + +#define VIEW_DISTANCE 512 // Si les chunks arrêtent de s'afficher pendant une game et qu'il y a un access violation quand tu quitte, il faut augmenter ce chiffre. #define TEXTURE_SIZE 512 #define MAX_BULLETS 512 diff --git a/SQCSim-common/player.cpp b/SQCSim-common/player.cpp index b42968a..2043dd9 100644 --- a/SQCSim-common/player.cpp +++ b/SQCSim-common/player.cpp @@ -4,6 +4,8 @@ Player::Player(const Vector3f& position, float rotX, float rotY) : m_position(position), m_rotX(rotX), m_rotY(rotY) { m_velocity = Vector3f(0, 0, 0); m_airborne = true; + m_hp = 0.75f; //TODO: Remettre à 1.0f + m_username = "Zelda Bee-Bop"; } void Player::TurnLeftRight(float value) { @@ -64,7 +66,8 @@ Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jum return delta; } -void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { +Player::Sound Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { + Player::Sound snd = Player::Sound::NOSOUND; static float timing = 0.f; /* Gestion de collisions */ BlockType bt1, bt2, bt3; @@ -85,6 +88,7 @@ void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { if (bt3 != BTYPE_AIR) { m_velocity.y = 0; if (timing == 0.f) { + if (m_airborne) snd = Player::Sound::FALL; timing = .3f; } m_airborne = false; @@ -137,10 +141,10 @@ void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { m_velocity.x += input.x * 2.f * elapsedTime; m_velocity.z += input.z * 2.f * elapsedTime; - if (input.x == 0.f) + if (input.x == 0.f) m_velocity.x *= .8f; - - if (input.z == 0.f) + + if (input.z == 0.f) m_velocity.z *= .8f; } else { @@ -160,6 +164,30 @@ void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime) { m_velocity.y = vy; m_position += m_velocity; + + static float bobbingtime = 0; // Gestion de la caméra + static bool leftright = false; + static bool isStep = false; + if (bobbingtime <= 360.f) + bobbingtime += elapsedTime * 20.f; else bobbingtime = 0; + + if ((sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) < -.2f && !m_airborne) { + if (!isStep) { + snd = Player::Sound::STEP; + } + isStep = true; + } + else isStep = false; + m_POV = m_position.y; + m_POV += m_airborne ? 0 : (sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) * .2f; + + return snd; +} + +void Player::ApplyTransformation(Transformation& transformation, bool rel) const { + transformation.ApplyRotation(-m_rotX, 1, 0, 0); + transformation.ApplyRotation(-m_rotY, 0, 1, 0); + if (rel) transformation.ApplyTranslation(-GetPOV()); } 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); } @@ -170,6 +198,10 @@ Vector3f Player::GetPOV() const { return Vector3f(GetPosition().x, m_POV, GetPos Vector3f Player::GetDirection() const { return m_direction; } +std::string Player::GetUsername() const { return m_username; } + +float Player::GetHP() const { return m_hp; } + void Player::Teleport(int& x, int& z) { m_position.x -= x * CHUNK_SIZE_X; m_position.z -= z * CHUNK_SIZE_Z; diff --git a/SQCSim-common/player.h b/SQCSim-common/player.h index f889b68..3856ced 100644 --- a/SQCSim-common/player.h +++ b/SQCSim-common/player.h @@ -1,33 +1,43 @@ -#ifndef _PLAYER_H__ -#define _PLAYER_H__ -#include "vector3.h" +#ifndef CLI_PLAYER_H__ +#define CLI_PLAYER_H__ #include +#include "transformation.h" +#include "vector3.h" -class World; +class World; class Player { public: + enum Sound { NOSOUND, STEP, FALL }; + Player(const Vector3f& position, float rotX = 0, float rotY = 0); void TurnLeftRight(float value); void TurnTopBottom(float value); Vector3f GetInput(bool front, bool back, bool left, bool right, bool jump, bool dash, float elapsedTime); - void ApplyPhysics(Vector3f input, World* world, float elapsedTime); + Sound ApplyPhysics(Vector3f input, World* world, float elapsedTime); + void ApplyTransformation(Transformation& transformation, bool rel = true) const; Vector3f GetPosition() const; Vector3f GetDirection() const; Vector3f GetVelocity() const; Vector3f GetPOV() const; + std::string GetUsername() const; + float GetHP() const; void Teleport(int& x, int& z); -protected: +private: Vector3f m_position; Vector3f m_velocity; Vector3f m_direction; + std::string m_username; + float m_rotX = 0; float m_rotY = 0; float m_POV; + float m_hp; + bool m_airborne; }; #endif //_PLAYER_H__ diff --git a/SQCSim2021/transformation.cpp b/SQCSim-common/transformation.cpp similarity index 91% rename from SQCSim2021/transformation.cpp rename to SQCSim-common/transformation.cpp index 7629f52..c4169a3 100644 --- a/SQCSim2021/transformation.cpp +++ b/SQCSim-common/transformation.cpp @@ -51,10 +51,10 @@ void Transformation::ApplyScale(const Vector3f& v) ApplyScale(v.x, v.y, v.z); } -void Transformation::Use() const -{ - glLoadMatrixf(m_stack.top().GetInternalValues()); -} +//void Transformation::Use() const +//{ +// glLoadMatrixf(m_stack.top().GetInternalValues()); +//} const Matrix4f& Transformation::GetMatrix() const { diff --git a/SQCSim2021/transformation.h b/SQCSim-common/transformation.h similarity index 87% rename from SQCSim2021/transformation.h rename to SQCSim-common/transformation.h index 72e0690..f6ac105 100644 --- a/SQCSim2021/transformation.h +++ b/SQCSim-common/transformation.h @@ -2,9 +2,9 @@ #define TRANSFORMATION_H__ #include -#include "../SQCSim-common/matrix4.h" -#include "../SQCSim-common/vector3.h" #include "define.h" +#include "matrix4.h" +#include "vector3.h" class Transformation { @@ -25,7 +25,7 @@ class Transformation void ApplyScale(float x, float y, float z); void ApplyScale(const Vector3f& v); - void Use() const; + //void Use() const; const Matrix4f& GetMatrix() const; diff --git a/SQCSim-common/world.cpp b/SQCSim-common/world.cpp index 6b4ccf6..4d7c292 100644 --- a/SQCSim-common/world.cpp +++ b/SQCSim-common/world.cpp @@ -6,6 +6,10 @@ World::~World() {} Array2d& World::GetChunks() { return m_chunks; } +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; @@ -38,23 +42,112 @@ BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const return BlockAt(pos.x, pos.y, pos.z, defaultBlockType); } +void World::TransposeWorld(Vector3f& player, Bullet* bullets[MAX_BULLETS]) { + int x = 0, y = 0; + + if (player.x > (WORLD_SIZE_X * CHUNK_SIZE_X) * .6f) ++x; + else if (player.x < (WORLD_SIZE_X * CHUNK_SIZE_X) * .4f) --x; + if (player.z > (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .6f) ++y; + else if (player.z < (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .4f) --y; + + if (!x && !y) return; + + if (x > 0) { + for (int ax = 0; ax < WORLD_SIZE_X; ++ax) + for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) + if (ax - x >= 0) { + m_chunks.Set(ax - x, ay, + m_chunks.Remove(ax, ay)); + if (ax == WORLD_SIZE_X - 1 && m_chunks.Get(ax - x, ay)) + m_chunks.Get(ax - x, ay)->MakeDirty(); + } + else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); + } + else if (x < 0) { + for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax) + for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay) + if (ax - x < WORLD_SIZE_X) { + m_chunks.Set(ax - x, ay, + m_chunks.Remove(ax, ay)); + if (ax == 0 && m_chunks.Get(ax - x, ay)) + m_chunks.Get(ax - x, ay)->MakeDirty(); + } + else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); + } + + if (y > 0) { + for (int ax = 0; ax < WORLD_SIZE_X; ++ax) + for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) + if (ay - y >= 0) { + m_chunks.Set(ax, ay - y, + m_chunks.Remove(ax, ay)); + if (ay == WORLD_SIZE_Y - 1 && m_chunks.Get(ax, ay - y)) + m_chunks.Get(ax, ay - y)->MakeDirty(); + } + else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); + } + else if (y < 0) { + for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax) + for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay) + if (ay - y < WORLD_SIZE_Y) { + m_chunks.Set(ax, ay - y, + m_chunks.Remove(ax, ay)); + if (ay == 0 && m_chunks.Get(ax, ay - y)) + m_chunks.Get(ax, ay - y)->MakeDirty(); + } + else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); + } + + m_center[0] += x; m_center[1] += y; + player.x -= x * CHUNK_SIZE_X; + player.z -= y * CHUNK_SIZE_Z; + + for (int index = 0; index < MAX_BULLETS; ++index) + if (bullets[index]) bullets[index]->Transpose(x, y); +} + +void World::CleanUpWorld(int& deleteframes, bool clear = false) { + if (clear) { + while (m_tbDeleted.size() > 0) { + delete m_tbDeleted.back(); + m_tbDeleted.pop_back(); + } + } + if (!m_tbDeleted.empty() && !deleteframes) { + int deleted = 0; + while (deleted < THREADS_DELETE_CHUNKS) { + + + } + delete m_tbDeleted.back(); + m_tbDeleted.pop_back(); + deleteframes = FRAMES_DELETE_CHUNKS; + } +} + void World::GetScope(unsigned int& x, unsigned int& y) { x = m_center[0]; y = m_center[1]; } -void World::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) { - int bx = (int)pos.x % CHUNK_SIZE_X; - int by = (int)pos.y % CHUNK_SIZE_Y; - int bz = (int)pos.z % CHUNK_SIZE_Z; - - ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this); +void World::Update(Bullet* bullets[MAX_BULLETS], Vector3f& player_pos, BlockInfo* blockinfo[BTYPE_LAST]) { + UpdateWorld(player_pos, blockinfo); + //TransposeWorld(player_pos, bullets); } +// +//void World::UpdateChunk(int& updates, unsigned int chx, unsigned 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; +// } +// +//} -void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) { - Vector3f currentPos = player.GetPosition(); +void World::ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block) { + Vector3f currentPos = player_pos; Vector3f currentBlock = currentPos; - Vector3f ray = player.GetDirection(); + Vector3f ray = player_dir; bool found = false; if (block) return; @@ -76,7 +169,7 @@ void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block BlockType bt = BlockAt(currentBlock); - if (bt == BTYPE_AIR) { // V?rification pour ?tre s?r que le bloc ? changer n'est pas dans le joueur. + if (bt == BTYPE_AIR) { // Vérification pour être sûr que le bloc à changer n'est pas dans le joueur. int Bx = (int)currentBlock.x; int By = (int)currentBlock.y; int Bz = (int)currentBlock.z; @@ -107,3 +200,211 @@ void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block block = true; } } + +void World::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) { + int bx = (int)pos.x % CHUNK_SIZE_X; + int by = (int)pos.y % CHUNK_SIZE_Y; + int bz = (int)pos.z % CHUNK_SIZE_Z; + + ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this); + ChunkAt(pos)->MakeModified(); +} + +void World::UpdateWorld(const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]) { + int cx = player.x; + int cy = player.z; + static int frameGenerate = 1; + static int frameUpdate = 2; + static int frameDelete = 3; + int side = 0; + int threads = 0; + std::future genThList[THREADS_GENERATE_CHUNKS]; + //std::future delThList[THREADS_DELETE_CHUNKS]; + + if (frameGenerate > 0) --frameGenerate; + if (frameUpdate > 0) --frameUpdate; + if (frameDelete > 0) --frameDelete; + + if (!frameGenerate) + while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2 + CHUNK_SIZE_X) { + int tx = -side, ty = -side; + int chx = 0; + int chy = 0; + + 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, + [](unsigned int x, unsigned int y, uint64_t seed) { + return new Chunk(x, y, seed); }, + chx / CHUNK_SIZE_X + m_center[0], + chy / CHUNK_SIZE_Z + m_center[1], + m_seed); + 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, + [](unsigned int x, unsigned int y, uint64_t seed) { + return new Chunk(x, y, seed); }, + chx / CHUNK_SIZE_X + m_center[0], + chy / CHUNK_SIZE_Z + m_center[1], + m_seed); + 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, + [](unsigned int x, unsigned int y, uint64_t seed) { + return new Chunk(x, y, seed); }, + chx / CHUNK_SIZE_X + m_center[0], + chy / CHUNK_SIZE_Z + m_center[1], + m_seed); + 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, + [](unsigned int x, unsigned int y, uint64_t seed) { + return new Chunk(x, y, seed); }, + chx / CHUNK_SIZE_X + m_center[0], + chy / CHUNK_SIZE_Z + m_center[1], + m_seed); + 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) { + unsigned 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; + // unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; + // if (ChunkAt(chx, 1, chy) && + // 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; + // } + // } + // for (; ty <= side; ++ty) { + // if (frameUpdate) + // break; + // unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; + // if (ChunkAt(chx, 1, chy) && + // 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; + // } + // } + // for (; tx >= -side; --tx) { + // if (frameUpdate) + // break; + // unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; + // if (ChunkAt(chx, 1, chy) && + // 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; + // } + // } + // for (; ty >= -side; --ty) { + // if (frameUpdate) + // break; + // unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; + // if (ChunkAt(chx, 1, chy) && + // 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(); + // Chunk* chunk = updateThList[i].get(); + // chunk->FlushMeshToVBO(); + // } + //} + + threads = 0; + + //int del = THREADS_DELETE_CHUNKS; + //while (!m_tbDeleted.empty() && del--) { // Moins rapide que le bout en dessous, mais -beaucoup- plus stable. + // m_tbDeleted.back()->FlushVBO(); + // m_tbDeleted.back()->~Chunk(); + // m_tbDeleted.pop_back(); + //} + + /*while (!m_tbDeleted.empty() && !frameDelete) { + if (m_tbDeleted.back()) { + m_tbDeleted.back()->FlushVBO(); + delThList[threads] = + std::async(std::launch::async, + [](Chunk* chunk) { delete chunk; }, m_tbDeleted.back()); + m_tbDeleted.pop_back(); + if (++threads > THREADS_DELETE_CHUNKS) frameDelete = FRAMES_DELETE_CHUNKS; + } + else m_tbDeleted.pop_back(); + }*/ + + /*for (int x = 0; x < threads; ++x) { + delThList[x].wait(); + delThList[x].get(); + }*/ +} + +int World::GettbDeleted() const { return m_tbDeleted.size(); } \ No newline at end of file diff --git a/SQCSim-common/world.h b/SQCSim-common/world.h index dd9967a..69937aa 100644 --- a/SQCSim-common/world.h +++ b/SQCSim-common/world.h @@ -6,14 +6,12 @@ #include #include #include "define.h" -#include "chunk.h" -#include "array2d.h" #include "vector3.h" -#include "player.h" +#include "array2d.h" #include "bullet.h" +#include "chunk.h" class Chunk; -class Player; class Bullet; class World { @@ -23,23 +21,33 @@ public: Array2d& GetChunks(); + void SetSeed(uint64_t seed); + Chunk* ChunkAt(float x, float y, float z) const; Chunk* ChunkAt(const Vector3f& pos) const; BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const; BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const; + void Update(Bullet* bullets[MAX_BULLETS], Vector3f& player_pos, BlockInfo* blockinfo[BTYPE_LAST]); + void GetScope(unsigned int& x, unsigned int& y); - void ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block); + void ChangeBlockAtCursor(BlockType blockType, const Vector3f& player_pos, const Vector3f& player_dir, bool& block); void ChangeBlockAtPosition(BlockType blockType, Vector3f pos); - + void CleanUpWorld(int& deleteframes, bool clear); + int GettbDeleted() const; private: Array2d m_chunks = Array2d(WORLD_SIZE_X, WORLD_SIZE_Y); std::vector m_tbDeleted; + uint64_t m_seed = 0; unsigned int m_center[2] = { UINT16_MAX / 2 - WORLD_SIZE_X, UINT16_MAX / 2 - WORLD_SIZE_Y }; + void UpdateChunk(int& updates, unsigned int chx, unsigned int chy, BlockInfo* blockinfo[BTYPE_LAST]); + void UpdateWorld(const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]); + void TransposeWorld(Vector3f& player, Bullet* bullets[MAX_BULLETS]); + }; #endif // WORLD_H__ diff --git a/SQCSim2021/SQCSim2021.vcxproj b/SQCSim2021/SQCSim2021.vcxproj index 02c2b51..8fb814c 100644 --- a/SQCSim2021/SQCSim2021.vcxproj +++ b/SQCSim2021/SQCSim2021.vcxproj @@ -20,37 +20,33 @@ - + - - - + - + - - - + diff --git a/SQCSim2021/SQCSim2021.vcxproj.filters b/SQCSim2021/SQCSim2021.vcxproj.filters index 0e371d0..3bf0928 100644 --- a/SQCSim2021/SQCSim2021.vcxproj.filters +++ b/SQCSim2021/SQCSim2021.vcxproj.filters @@ -11,9 +11,6 @@ - - Fichiers d%27en-tête - Fichiers d%27en-tête @@ -23,12 +20,6 @@ Fichiers d%27en-tête - - Fichiers d%27en-tête - - - Fichiers d%27en-tête - Fichiers d%27en-tête @@ -44,9 +35,6 @@ Fichiers d%27en-tête - - Fichiers d%27en-tête - Fichiers d%27en-tête @@ -56,11 +44,14 @@ Fichiers d%27en-tête + + Fichiers d%27en-tête + + + Fichiers d%27en-tête + - - Fichiers sources - Fichiers sources @@ -73,12 +64,6 @@ Fichiers sources - - Fichiers sources - - - Fichiers sources - Fichiers sources @@ -94,14 +79,17 @@ Fichiers sources - - Fichiers sources - Fichiers sources Fichiers sources + + Fichiers sources + + + Fichiers sources + \ No newline at end of file diff --git a/SQCSim2021/audio.h b/SQCSim2021/audio.h index 315bfae..b0ff044 100644 --- a/SQCSim2021/audio.h +++ b/SQCSim2021/audio.h @@ -3,8 +3,8 @@ #include #include -#include "define.h" #include "../SQCSim-common/vector3.h" +#include "define.h" class Audio { private: diff --git a/SQCSim2021/chunk.cpp b/SQCSim2021/chunk.cpp deleted file mode 100644 index 5d78859..0000000 --- a/SQCSim2021/chunk.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "chunk.h" -#include "world.h" - -Chunk::Chunk(unsigned int x, unsigned int y, int64_t seed) : m_posX(x), m_posY(y) { - //std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position. - //pos << CHUNK_PATH << x << '_' << y << ".chunk"; - //std::ifstream input(pos.str(), std::fstream::binary); - - //if (input.fail()) { - OpenSimplexNoise::Noise simplex = OpenSimplexNoise::Noise(seed); - m_blocks.Reset(BTYPE_AIR); - - for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // Montagnes - for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { - float xnoiz, ynoiz; - xnoiz = (double)(ix + x * CHUNK_SIZE_X) / 4096.; - ynoiz = (double)(iz + y * CHUNK_SIZE_Z) / 4096.; - double height = 0; - for (int x = 0; x < 39; ++x) { - height += simplex.eval(xnoiz, ynoiz); - height *= .79; - xnoiz *= 1.139; - ynoiz *= 1.139; - } - height = height * 2000. * simplex.eval((double)(ix + x * CHUNK_SIZE_X) / 512., (double)(iz + y * CHUNK_SIZE_Z) / 512.); - height /= (CHUNK_SIZE_Y / 1.9); - height += 15.; - for (int iy = 0; iy <= (int)height % CHUNK_SIZE_Y; ++iy) - SetBlock(ix, iy, iz, BTYPE_METAL, nullptr); - } - for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // Collines - for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { - float xnoiz, ynoiz; - xnoiz = (double)(ix + x * CHUNK_SIZE_X) / 512.; - ynoiz = (double)(iz + y * CHUNK_SIZE_Z) / 512.; - float height = simplex.eval(xnoiz, ynoiz) * 50.f;// +1.f; - for (int iy = 0; iy <= (int)height % CHUNK_SIZE_Y; ++iy) { - if (GetBlock(ix, iy, iz) == BTYPE_AIR) - SetBlock(ix, iy, iz, BTYPE_GRASS, nullptr); - } - } - for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // "Lacs" - for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { - for (int iy = 0; iy < 13; ++iy) { - if (GetBlock(ix, iy, iz) == BTYPE_AIR) - SetBlock(ix, iy, iz, BTYPE_ICE, nullptr); - } - } - //for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) // "Arbres" - // for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) { - // float xnoiz, ynoiz; - // xnoiz = (double)(iz * CHUNK_SIZE_Y + x * CHUNK_SIZE_X) / 256.; - // ynoiz = (double)(ix * CHUNK_SIZE_Y + y * CHUNK_SIZE_Z) / 256.; - // bool tree = (int)(abs(simplex.eval(xnoiz, ynoiz)) * 17933.f) % CHUNK_SIZE_Y > 126 ? true : false; - // for (int iy = 0; iy < CHUNK_SIZE_Y - 10; ++iy) - // if (GetBlock(ix, iy, iz) == BTYPE_AIR) - // if (GetBlock(ix, iy - 1, iz) == BTYPE_GRASS) - // if (tree) { - // for (int i = 0; i < (int)(abs(simplex.eval(xnoiz, ynoiz) * 4)) % 42 + 1; ++i) - // SetBlock(ix, iy + i, iz, BTYPE_DIRT, nullptr); - // 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(); - - for (int ix = 0; ix < CHUNK_SIZE_X; ++ix) - for (int iz = 0; iz < CHUNK_SIZE_Z; ++iz) - for (int iy = 0; iy < CHUNK_SIZE_Y; ++iy) - m_blocks.Set(ix, iy, iz, data[ix + (iz * CHUNK_SIZE_X) + (iy * CHUNK_SIZE_Z * CHUNK_SIZE_X)]); - }*/ -} - -Chunk::~Chunk() { - /*if (m_isModified) { - char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]; - - 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) - data[x + (z * CHUNK_SIZE_X) + (y * CHUNK_SIZE_Z * CHUNK_SIZE_X)] = (char)GetBlock(x, y, z); - - std::ostringstream pos; - pos << CHUNK_PATH << m_posX << '_' << m_posY << ".chunk"; - - std::ofstream output(pos.str(), std::fstream::binary); - output.write(data, sizeof(data)); - output.close(); - }*/ -} - -void Chunk::RemoveBlock(int x, int y, int z, World* world) { - m_blocks.Set(x, y, z, BTYPE_AIR); - CheckNeighbors(x, y, world); - m_isDirty = true; -} - -void Chunk::SetBlock(int x, int y, int z, BlockType type, World* world) { - m_blocks.Set(x, y, z, type); - if (world) CheckNeighbors(x, z, world); // Si nullptr, ne pas vérifier les chunks voisines. - m_isDirty = true; -} - -BlockType Chunk::GetBlock(int x, int y, int z) { return m_blocks.Get(x, y, z); } - -void Chunk::CheckNeighbors(unsigned int x, unsigned int z, World* world) { - unsigned int cx, cy; - - world->GetScope(cx, cy); - - if (x == 0 && m_posX - cx >= 0 && - world->ChunkAt((m_posX - cx - 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)) - world->ChunkAt((m_posX - cx - 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)->MakeDirty(); - else if (x == CHUNK_SIZE_X - 1 && m_posX - cx < WORLD_SIZE_X && - world->ChunkAt((m_posX - cx + 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)) - world->ChunkAt((m_posX - cx + 1) * CHUNK_SIZE_X, 1, (m_posY - cy) * CHUNK_SIZE_Z)->MakeDirty(); - - if (z == 0 && m_posY - cy >= 0 && - world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy - 1) * CHUNK_SIZE_Z)) - world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy - 1) * CHUNK_SIZE_Z)->MakeDirty(); - else if (z == CHUNK_SIZE_X - 1 && m_posY - cy < WORLD_SIZE_Y && - world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy + 1) * CHUNK_SIZE_Z)) - world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy + 1) * CHUNK_SIZE_Z)->MakeDirty(); -} - -void Chunk::GetPosition(unsigned int& x, unsigned int& y) const { x = m_posX; y = m_posY; } - -void Chunk::FlushMeshToVBO() { - m_vertexBuffer.SetMeshData(m_vd, m_vcount); - m_vcount = 0; - delete[] m_vd; -} - -void Chunk::FlushVBO() { - m_vertexBuffer.Flush(); -} - -void Chunk::Update(BlockInfo* blockinfo[BTYPE_LAST], World* world) { - float u, v, s; - // Update mesh - if (m_isDirty) { - int maxVertexCount = (CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z) * (6 * 4); - m_vd = new VertexBuffer::VertexData[maxVertexCount]; - m_vcount = 0; - 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) { - if (m_vcount > USHRT_MAX) - break; - - BlockType bt = GetBlock(x, y, z); - - if (bt != BTYPE_AIR) { - blockinfo[bt]->GetTexture(u, v, s); - AddBlockToMesh(m_vd, m_vcount, bt, x, y, z, u, v, s, world); - } - } - } - } - if (m_vcount > USHRT_MAX) { - m_vcount = USHRT_MAX; - std::cout << "[ Chunk :: Update ] Chunk data truncaned , too much vertices to have a 16 bit index " << std::endl; - } - } - m_isDirty = false; -} - -void Chunk::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt, - int x, int y, int z, float u, float v, float s, World* world) { - - unsigned int cex, cey; - - world->GetScope(cex, cey); - - int cx = x + (m_posX - cex) * CHUNK_SIZE_X, cy = z + (m_posY - cey) * CHUNK_SIZE_Z; - - if (y == CHUNK_SIZE_Y - 1 || GetBlock(x, y + 1, z) == BTYPE_AIR) { // y - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, .8f, .8f, .8f, u, v); - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .8f, .8f, .8f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .8f, .8f, .8f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, .8f, .8f, .8f, u + s, v); - } - - if (y == 0 || GetBlock(x, y - 1, z) == BTYPE_AIR) { // -y - vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .2f, .2f, .2f, u, v); - vd[count++] = VertexBuffer::VertexData(x, y, z, .2f, .2f, .2f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, .2f, .2f, .2f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .2f, .2f, .2f, u + s, v); - } - - if (world->BlockAt(cx + 1, y, cy) == BTYPE_AIR) { // x - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, .9f, .9f, .9f, u, v); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, .9f, .9f, .9f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .9f, .9f, .9f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .9f, .9f, .9f, u + s, v); - } - - if (world->BlockAt(cx - 1, y, cy) == BTYPE_AIR) { // -x - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .5f, .5f, .5f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, .5f, .5f, .5f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x, y, z, .5f, .5f, .5f, u + s, v); - vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .5f, .5f, .5f, u, v); - } - - if (world->BlockAt(cx, y, cy + 1) == BTYPE_AIR) { // z - vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .4f, .4f, .4f, u, v); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .4f, .4f, .4f, u + s, v); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .4f, .4f, .4f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .4f, .4f, .4f, u, v + s); - } - - if (world->BlockAt(cx, y, cy - 1) == BTYPE_AIR) { // -z - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, 1.f, 1.f, 1.f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, 1.f, 1.f, 1.f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z , 1.f, 1.f, 1.f, u + s, v); - vd[count++] = VertexBuffer::VertexData(x, y, z , 1.f, 1.f, 1.f, u, v); - } -} - -void Chunk::Render() const { m_vertexBuffer.Render(); } - -bool Chunk::IsDirty() const { return m_isDirty; } - -void Chunk::MakeDirty() { m_isDirty = true; } - -void Chunk::MakeModified() { m_isModified = true; } - diff --git a/SQCSim2021/chunk.h b/SQCSim2021/chunk.h deleted file mode 100644 index 995b3f6..0000000 --- a/SQCSim2021/chunk.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef CHUNK_H__ -#define CHUNK_H__ -#include "define.h" -#include "../SQCSim-common/array2d.h" -#include "../SQCSim-common/array3d.h" -#include "../SQCSim-common/blockinfo.h" -#include "../SQCSim-common/opensimplex.h" -#include "vertexbuffer.h" - -class World; - -class Chunk { - private: - Array3d m_blocks = Array3d(CHUNK_SIZE_X, CHUNK_SIZE_Y, CHUNK_SIZE_Z); - VertexBuffer m_vertexBuffer; - bool m_isDirty = true; - bool m_isModified = false; - - unsigned int m_posX; // Position du chunk dans l'array constituant le monde. - unsigned int m_posY; - - VertexBuffer::VertexData* m_vd; - int m_vcount; - - void AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt, int x, int y, int z, float u, float v, float s, World* world); - - public: - Chunk(unsigned int x, unsigned int y, int64_t seed); - ~Chunk(); - - void RemoveBlock(int x, int y, int z, World* world); - void SetBlock(int x, int y, int z, BlockType type, World* world); - BlockType GetBlock(int x, int y, int z); - void CheckNeighbors(unsigned int x, unsigned int z, World* world); - void GetPosition(unsigned int& x, unsigned int& y) const; - - - void Update(BlockInfo* blockinfo[BTYPE_LAST], World* world); - void FlushMeshToVBO(); - - void FlushVBO(); - - void Render() const; - bool IsDirty() const; - void MakeDirty(); - void MakeModified(); -}; - -#endif // CHUNK_H__ diff --git a/SQCSim2021/define.h b/SQCSim2021/define.h index ceeb08c..8d51188 100644 --- a/SQCSim2021/define.h +++ b/SQCSim2021/define.h @@ -18,14 +18,6 @@ #define SRV_ADDR "127.0.0.1" #define COUNTDOWN 300 -#define FRAMES_RENDER_CHUNKS 1 -#define FRAMES_UPDATE_CHUNKS 1 -#define FRAMES_DELETE_CHUNKS 1 - -#define THREADS_GENERATE_CHUNKS 8 -#define THREADS_UPDATE_CHUNKS 3 -#define THREADS_DELETE_CHUNKS 3 - #define BASE_WIDTH 640 #define BASE_HEIGHT 480 diff --git a/SQCSim2021/engine.cpp b/SQCSim2021/engine.cpp index 6599890..5c670b3 100644 --- a/SQCSim2021/engine.cpp +++ b/SQCSim2021/engine.cpp @@ -17,11 +17,11 @@ void Engine::Init() { abort(); } - //glDisable(GL_FRAMEBUFFER_SRGB); - //glEnable(GL_DEPTH_TEST); - //glEnable(GL_STENCIL_TEST); - //glEnable(GL_POINT_SMOOTH); - //glEnable(GL_BLEND); + glDisable(GL_FRAMEBUFFER_SRGB); + glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); + glEnable(GL_POINT_SMOOTH); + glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); @@ -31,10 +31,10 @@ void Engine::Init() { gluPerspective(45.0f, (float)Width() / (float)Height(), 0.1f, VIEW_DISTANCE); glShadeModel(GL_SMOOTH); - //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - //glDisable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendEquation(GL_FUNC_SUBTRACT); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_SUBTRACT); // // Objet de skybox avec sa propre texture et son propre shader! m_skybox.Init(0.2f); @@ -330,6 +330,7 @@ int Engine::GetCountdown(float elapsedTime) { void Engine::Render(float elapsedTime) { //static float gameTime = elapsedTime; + static irrklang::ISound* step; // Pour les sons de pas. static float pollTime = 0; static float bulletTime = 0; static BlockType bloc = 1; @@ -341,6 +342,7 @@ void Engine::Render(float elapsedTime) { Transformation all; Transformation skybox; + Vector3f vstep; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Transformations initiales @@ -350,8 +352,22 @@ void Engine::Render(float elapsedTime) { if (bulletTime > 0.f) bulletTime -= elapsedTime; if (bulletTime < 0.f) bulletTime = 0.f; + static bool leftright = false; if (pollTime >= .005f) { - m_player.ApplyPhysics(m_player.GetInput(m_keyW, m_keyS, m_keyA, m_keyD, m_keySpace, (bloc == BTYPE_LAST && bulletTime <= 0.f && m_mouseL), elapsedTime), &m_world, elapsedTime, &m_audio); + Player::Sound snd = m_player.ApplyPhysics(m_player.GetInput(m_keyW, m_keyS, m_keyA, m_keyD, m_keySpace, (bloc == BTYPE_LAST && bulletTime <= 0.f && m_mouseL), elapsedTime), &m_world, elapsedTime); + switch (snd) { + case Player::Sound::STEP: + if (leftright) + vstep = Vector3f(m_player.GetPosition().x + m_player.GetDirection().z, m_player.GetPosition().y - 1.7f, m_player.GetPosition().z + m_player.GetDirection().x); + else vstep = Vector3f(m_player.GetPosition().x - m_player.GetDirection().z, m_player.GetPosition().y - 1.7f, m_player.GetPosition().z - m_player.GetDirection().x); + m_audio.Create3DAudioObj(step, AUDIO_PATH "step.wav", vstep, m_player.GetVelocity(), .8f); + leftright = !leftright; + break; + case Player::Sound::FALL: + m_audio.Create3DAudioObj(step, AUDIO_PATH "hit.wav", m_player.GetPosition(), m_player.GetVelocity(), 1.f); + break; + default: break; + } m_audio.Update3DAudio(m_player.GetPOV(), m_player.GetDirection(), m_player.GetVelocity()); // Ajustement du positionnement 3D avec les coordonnées du joueur et // son vecteur de vélocité (pour l'effet Doppler) pollTime = 0; @@ -370,7 +386,7 @@ void Engine::Render(float elapsedTime) { if (m_mouseL) { if (bloc != BTYPE_LAST) - m_world.ChangeBlockAtCursor(bloc, m_player, m_block); + m_world.ChangeBlockAtCursor(bloc, m_player.GetPosition(), m_player.GetDirection(), m_block); else if (bulletTime <= 0.f) { for (int x = 0; x < MAX_BULLETS; ++x) // Ajouter une balle dans l'array (aussi connu sous le nom de "faire pow pow"). if (!m_bullets[x]) { @@ -392,7 +408,7 @@ void Engine::Render(float elapsedTime) { } } else if (m_mouseR) - m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player, m_block); + m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player.GetPosition(), m_player.GetDirection(), m_block); for (int x = 0; x < MAX_BULLETS; ++x) // Array de bullets en jeu. if (m_bullets[x]) @@ -401,7 +417,9 @@ void Engine::Render(float elapsedTime) { m_bullets[x] = nullptr; } - m_world.Update(m_renderCount, m_bullets, m_player, all, m_shader01, m_textureAtlas, m_blockinfo); + m_wrenderer.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_wrenderer.UpdateWorld(&m_world, m_player.GetPosition(), m_blockinfo); if (m_isSkybox) m_skybox.Render(skybox); diff --git a/SQCSim2021/engine.h b/SQCSim2021/engine.h index 8c525b6..e2a291f 100644 --- a/SQCSim2021/engine.h +++ b/SQCSim2021/engine.h @@ -6,18 +6,19 @@ #include "../SQCSim-common/array2d.h" #include "../SQCSim-common/blockinfo.h" #include "../SQCSim-common/bullet.h" +#include "../SQCSim-common/chunk.h" +#include "../SQCSim-common/world.h" +#include "../SQCSim-common/transformation.h" +#include "../SQCSim-common/player.h" #include "define.h" #include "openglcontext.h" #include "texture.h" -#include "transformation.h" #include "shader.h" -#include "player.h" -#include "chunk.h" #include "skybox.h" #include "audio.h" #include "textureatlas.h" -#include "world.h" #include "connector.h" +#include "worldrenderer.h" class Engine : public OpenglContext { public: @@ -55,6 +56,7 @@ private: TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST); World m_world = World(); + WorldRenderer m_wrenderer = WorldRenderer(); Texture m_textureSkybox; Texture m_textureFont; diff --git a/SQCSim2021/mesh.cpp b/SQCSim2021/mesh.cpp new file mode 100644 index 0000000..c6f6b9b --- /dev/null +++ b/SQCSim2021/mesh.cpp @@ -0,0 +1,120 @@ +#include "mesh.h" + +Mesh::Mesh(Chunk* chunk): m_chunk(chunk) {} + +Mesh::~Mesh() { + FlushVBO(); +} + +void Mesh::FlushMeshToVBO() { + m_vertexBuffer.SetMeshData(m_vd, m_vcount); + m_vcount = 0; + delete[] m_vd; +} + +void Mesh::FlushVBO() { + m_vertexBuffer.Flush(); +} + +void Mesh::Update(BlockInfo* blockinfo[BTYPE_LAST], World* world) { + float u, v, s; + // Update mesh + if (m_chunk->IsDirty()) { + int maxVertexCount = (CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z) * (6 * 4); + m_vd = new VertexBuffer::VertexData[maxVertexCount]; + m_vcount = 0; + 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) { + if (m_vcount > USHRT_MAX) + break; + + BlockType bt = m_chunk->GetBlock(x, y, z); + + if (bt != BTYPE_AIR) { + blockinfo[bt]->GetTexture(u, v, s); + AddBlockToMesh(m_vd, m_vcount, bt, x, y, z, u, v, s, world); + } + } + } + } + if (m_vcount > USHRT_MAX) { + m_vcount = USHRT_MAX; + std::cout << "[ Chunk :: Update ] Chunk data truncaned , too much vertices to have a 16 bit index " << std::endl; + } + } + m_chunk->MakeClean(); +} + +void Mesh::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt, + int x, int y, int z, float u, float v, float s, World* world) { + + unsigned int cex, cey, cpx, cpy; + + m_chunk->GetPosition(cpx, cpy); + + world->GetScope(cex, cey); + + int cx = x + (cpx - cex) * CHUNK_SIZE_X, cy = z + (cpy - cey) * CHUNK_SIZE_Z; + + if (y == CHUNK_SIZE_Y - 1 || m_chunk->GetBlock(x, y + 1, z) == BTYPE_AIR) { // y + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, .8f, .8f, .8f, u, v); + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .8f, .8f, .8f, u, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .8f, .8f, .8f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, .8f, .8f, .8f, u + s, v); + } + + if (y == 0 || m_chunk->GetBlock(x, y - 1, z) == BTYPE_AIR) { // -y + vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .2f, .2f, .2f, u, v); + vd[count++] = VertexBuffer::VertexData(x, y, z, .2f, .2f, .2f, u, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, .2f, .2f, .2f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .2f, .2f, .2f, u + s, v); + } + + if (world->BlockAt(cx + 1, y, cy) == BTYPE_AIR) { // x + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, .9f, .9f, .9f, u, v); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, .9f, .9f, .9f, u, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .9f, .9f, .9f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .9f, .9f, .9f, u + s, v); + } + + if (world->BlockAt(cx - 1, y, cy) == BTYPE_AIR) { // -x + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .5f, .5f, .5f, u, v + s); + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, .5f, .5f, .5f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x, y, z, .5f, .5f, .5f, u + s, v); + vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .5f, .5f, .5f, u, v); + } + + if (world->BlockAt(cx, y, cy + 1) == BTYPE_AIR) { // z + vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .4f, .4f, .4f, u, v); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .4f, .4f, .4f, u + s, v); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, .4f, .4f, .4f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .4f, .4f, .4f, u, v + s); + } + + if (world->BlockAt(cx, y, cy - 1) == BTYPE_AIR) { // -z + vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, 1.f, 1.f, 1.f, u, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z, 1.f, 1.f, 1.f, u + s, v + s); + vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, 1.f, 1.f, 1.f, u + s, v); + vd[count++] = VertexBuffer::VertexData(x, y, z, 1.f, 1.f, 1.f, u, v); + } +} + +void Mesh::Render() const { m_vertexBuffer.Render(); } + +bool Mesh::IsDirty() const { return m_chunk->IsDirty(); } + +bool Mesh::IsNew() { + bool bl = m_new; + if (m_new) + m_new = false; + return bl; +} + +void Mesh::GetPosition(unsigned int& x, unsigned int& y, World* world) const { + unsigned int sx, sy; + world->GetScope(sx, sy); + m_chunk->GetPosition(x, y); + x -= sx; + y -= sy; +} diff --git a/SQCSim2021/mesh.h b/SQCSim2021/mesh.h new file mode 100644 index 0000000..0a070ff --- /dev/null +++ b/SQCSim2021/mesh.h @@ -0,0 +1,32 @@ +#ifndef MESH_H__ +#define MESH_H__ + +#include "../SQCSim-common/chunk.h" +#include "../SQCSim-common/world.h" +#include "define.h" +#include "vertexbuffer.h" + +class Mesh { +private: + VertexBuffer m_vertexBuffer; + VertexBuffer::VertexData* m_vd = nullptr; + int m_vcount = 0; + bool m_new = true; + 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); + +public: + Mesh(Chunk* chunk); + ~Mesh(); + + void FlushMeshToVBO(); + void FlushVBO(); + void Update(BlockInfo* blockinfo[BTYPE_LAST], World* world); + void Render() const; + + bool IsDirty() const; + bool IsNew(); + void GetPosition(unsigned int& x, unsigned int& y, World* world) const; +}; +#endif \ No newline at end of file diff --git a/SQCSim2021/openglcontext.h b/SQCSim2021/openglcontext.h index 5b116f4..b82c683 100644 --- a/SQCSim2021/openglcontext.h +++ b/SQCSim2021/openglcontext.h @@ -1,10 +1,9 @@ #ifndef OPENGLCONTEXT_H__ #define OPENGLCONTEXT_H__ -#include "define.h" - #include #include +#include "define.h" // Documentation de SFML: http://www.sfml-dev.org/documentation/index-fr.php class OpenglContext diff --git a/SQCSim2021/player.cpp b/SQCSim2021/player.cpp deleted file mode 100644 index f5313c7..0000000 --- a/SQCSim2021/player.cpp +++ /dev/null @@ -1,209 +0,0 @@ -#include "player.h" -#include "world.h" - -Player::Player(const Vector3f& position, float rotX, float rotY) : m_position(position), m_rotX(rotX), m_rotY(rotY) { - m_velocity = Vector3f(0, 0, 0); - m_airborne = true; - m_hp = 0.75f; //TODO: Remettre à 1.0f - m_username = "Zelda Bee-Bop"; -} - -void Player::TurnLeftRight(float value) { - m_rotY += value; - if (m_rotY > 360) m_rotY = 0; - else if (m_rotY < -360) m_rotY = 0; -} - -void Player::TurnTopBottom(float value) { - m_rotX += value; - if (m_rotX > 80) m_rotX = 80; - else if (m_rotX < -80) m_rotX = -80; -} - -Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jump, bool shoot, float elapsedTime) { - - Vector3f delta = Vector3f(0, 0, 0); - - float yrotrad = (m_rotY / 57.2957795056f); // 180/Pi = 57.295... - float xrotrad = (m_rotX / 57.2957795056f); - - m_direction = Vector3f(cos(xrotrad) * sin(yrotrad), - -sin(xrotrad), - cos(xrotrad) * -cos(yrotrad)); - - m_direction.Normalize(); - - if (front) { - delta.x += float(sin(yrotrad)) * elapsedTime * 10.f; - delta.z += float(-cos(yrotrad)) * elapsedTime * 10.f; - } - else if (back) { - delta.x += float(-sin(yrotrad)) * elapsedTime * 10.f; - delta.z += float(cos(yrotrad)) * elapsedTime * 10.f; - } - - if (left) { - delta.x += float(-cos(yrotrad)) * elapsedTime * 10.f; - delta.z += float(-sin(yrotrad)) * elapsedTime * 10.f; - } - else if (right) { - delta.x += float(cos(yrotrad)) * elapsedTime * 10.f; - delta.z += float(sin(yrotrad)) * elapsedTime * 10.f; - } - - delta.Normalize(); - delta.x *= .6f; - delta.z *= .6f; - - if ((jump || shoot ) && !m_airborne) { - delta.y += jump? .32f: shoot? .1f : 0.f; - m_airborne = true; - } - - if (shoot) // Recoil! - TurnTopBottom(-1); - - return delta; -} - -void Player::ApplyPhysics(Vector3f input, World* world, float elapsedTime, Audio* audio) { - static irrklang::ISound* step; // Pour les sons de pas. - static float timing = 0.f; - /* Gestion de collisions */ - BlockType bt1, bt2, bt3; - - bt1 = world->BlockAt(GetPosition().x, GetPosition().y + input.y, GetPosition().z); - bt2 = world->BlockAt(GetPosition().x, GetPosition().y + input.y - 0.9f, GetPosition().z); - bt3 = world->BlockAt(GetPosition().x, GetPosition().y + input.y - 1.7f, GetPosition().z); - if ((bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) && m_position.y < 129.7f) { - bt1 = world->BlockAt(GetPosition().x, GetPosition().y + .3f, GetPosition().z); - if (bt1 == BTYPE_AIR) m_position.y = (int)m_position.y + .7f; - m_velocity.y = input.y = 0; - m_airborne = false; - } - else { - if (abs(m_velocity.y) < 1.1f) m_velocity.y += input.y - 1.1f * elapsedTime; - bt3 = world->BlockAt(GetPosition().x, GetPosition().y + m_velocity.y - 1.7f, GetPosition().z); - bt1 = world->BlockAt(GetPosition().x, GetPosition().y + .3f, GetPosition().z); - if (bt3 != BTYPE_AIR) { - m_velocity.y = 0; - if (timing == 0.f) { - if (m_airborne) audio->Create3DAudioObj(step, AUDIO_PATH "hit.wav", GetPosition(), GetVelocity(), 1.f); - timing = .3f; - } - m_airborne = false; - } - else if (bt1 != BTYPE_AIR) { - m_velocity.y = -.1f; - } - else m_airborne = true; - } - - if (timing > 0.f) timing -= elapsedTime; - if (timing < 0.f) timing = 0.f; - - bt1 = world->BlockAt(GetPosition().x + input.x, GetPosition().y, GetPosition().z); - bt2 = world->BlockAt(GetPosition().x + input.x, GetPosition().y - 0.9f, GetPosition().z); - bt3 = world->BlockAt(GetPosition().x + input.x, GetPosition().y - 1.7f, GetPosition().z); - if (bt1 == BTYPE_AIR && bt2 != BTYPE_AIR && bt3 != BTYPE_AIR) { - if (input.x > 0) - input.x = m_velocity.x = 0.5f; - else - input.x = m_velocity.x = -0.5f; - m_velocity.y = 0.3; - m_velocity.z *= .5f; - } else if (bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) { - input.x = m_velocity.x = 0; - m_velocity.z *= .5f; - } - - bt1 = world->BlockAt(GetPosition().x, GetPosition().y, GetPosition().z + input.z); - bt2 = world->BlockAt(GetPosition().x, GetPosition().y - 0.9f, GetPosition().z + input.z); - bt3 = world->BlockAt(GetPosition().x, GetPosition().y - 1.7f, GetPosition().z + input.z); - if (bt1 == BTYPE_AIR && bt2 != BTYPE_AIR && bt3 != BTYPE_AIR) { - if (input.z > 0) - input.z = m_velocity.z = 0.5f; - else - input.z = m_velocity.z = -0.5f; - m_velocity.y = 0.3; - m_velocity.x *= .5f; - } else if (bt1 != BTYPE_AIR || bt2 != BTYPE_AIR || bt3 != BTYPE_AIR) { - input.z = m_velocity.z = 0; - m_velocity.x *= .5f; - } - - /* Fin gestion de collisions */ - /* Gestion de la friction */ - - if (!m_airborne) { - m_velocity.x += input.x * 2.f * elapsedTime; - m_velocity.z += input.z * 2.f * elapsedTime; - - if (input.x == 0.f) - m_velocity.x *= .8f; - - if (input.z == 0.f) - m_velocity.z *= .8f; - } - else { - m_velocity.x += input.x * .4f * elapsedTime; // Techniquement contre les lois de la physique, mais c'est beaucoup moins chiant pour grimper sur les blocs. - m_velocity.z += input.z * .4f * elapsedTime; - m_velocity.x *= .99f; - m_velocity.z *= .99f; - } - - /* Fin gestion de la friction */ - - float vy = m_velocity.y; - m_velocity.y = 1.f; // Padding pour limiter le x et z lors du Normalize(). - if (m_velocity.Length() >= 1.f) m_velocity.Normalize(); // Limiteur de vitesse en x/z. - m_velocity.y = 0; - if (m_velocity.Length() < .005f) m_velocity.Zero(); // Threshold en x/z. - m_velocity.y = vy; - - m_position += m_velocity; - - static float bobbingtime = 0; // Gestion de la caméra - static bool leftright = false; - static bool isStep = false; - if (bobbingtime <= 360.f) - bobbingtime += elapsedTime * 20.f; else bobbingtime = 0; - - if ((sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) < -.2f && !m_airborne) { - Vector3f vstep; - if (leftright) - vstep = Vector3f(GetPosition().x + GetDirection().z, GetPosition().y - 1.7f, GetPosition().z + GetDirection().x); - else vstep = Vector3f(GetPosition().x - GetDirection().z, GetPosition().y - 1.7f, GetPosition().z - GetDirection().x); - if (!isStep) { - audio->Create3DAudioObj(step, AUDIO_PATH "step.wav", vstep, GetVelocity(), .8f); - leftright = !leftright; - } - isStep = true; - } - else isStep = false; - m_POV = m_position.y; - m_POV += m_airborne ? 0 : (sin(bobbingtime) - 0.5f) * (abs(m_velocity.x) + abs(m_velocity.z)) * .2f; -} - -void Player::ApplyTransformation(Transformation& transformation, bool rel) const { - transformation.ApplyRotation(-m_rotX, 1, 0, 0); - transformation.ApplyRotation(-m_rotY, 0, 1, 0); - if (rel) transformation.ApplyTranslation(-GetPOV()); -} - -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; } - -Vector3f Player::GetPOV() const { return Vector3f(GetPosition().x, m_POV, GetPosition().z); } - -Vector3f Player::GetDirection() const { return m_direction; } - -std::string Player::GetUsername() const { return m_username; } - -float Player::GetHP() const { return m_hp; } - -void Player::Teleport(int& x, int& z) { - m_position.x -= x * CHUNK_SIZE_X; - m_position.z -= z * CHUNK_SIZE_Z; -} diff --git a/SQCSim2021/player.h b/SQCSim2021/player.h deleted file mode 100644 index d8f46f3..0000000 --- a/SQCSim2021/player.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef CLI_PLAYER_H__ -#define CLI_PLAYER_H__ -#include "../SQCSim-common/vector3.h" -#include "transformation.h" -#include "audio.h" -#include - -class World; - -class Player { -public: - Player(const Vector3f& position, float rotX = 0, float rotY = 0); - void TurnLeftRight(float value); - void TurnTopBottom(float value); - Vector3f GetInput(bool front, bool back, bool left, bool right, bool jump, bool dash, float elapsedTime); - void ApplyPhysics(Vector3f input, World* world, float elapsedTime, Audio* audio); - void ApplyTransformation(Transformation& transformation, bool rel = true) const; - - Vector3f GetPosition() const; - Vector3f GetDirection() const; - Vector3f GetVelocity() const; - Vector3f GetPOV() const; - std::string GetUsername() const; - float GetHP() const; - void Teleport(int& x, int& z); - -private: - Vector3f m_position; - Vector3f m_velocity; - Vector3f m_direction; - - std::string m_username; - - float m_rotX = 0; - float m_rotY = 0; - float m_POV; - - float m_hp; - - bool m_airborne; -}; -#endif //_PLAYER_H__ - diff --git a/SQCSim2021/skybox.cpp b/SQCSim2021/skybox.cpp index 947535c..a024ae7 100644 --- a/SQCSim2021/skybox.cpp +++ b/SQCSim2021/skybox.cpp @@ -45,7 +45,7 @@ void Skybox::Init(float size){ void Skybox::Render(Transformation tran) const { glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); - tran.Use(); + glLoadMatrixf(tran.GetMatrix().GetInternalValues()); m_texture.Bind(); m_shader.Use(); m_vertexBuffer.Render(); diff --git a/SQCSim2021/skybox.h b/SQCSim2021/skybox.h index a596416..6df8aab 100644 --- a/SQCSim2021/skybox.h +++ b/SQCSim2021/skybox.h @@ -1,10 +1,10 @@ #ifndef SKYBOX_H__ #define SKYBOX_H__ +#include "../SQCSim-common/transformation.h" #include "define.h" #include "vertexbuffer.h" #include "texture.h" -#include "transformation.h" #include "shader.h" class Skybox { diff --git a/SQCSim2021/texture.h b/SQCSim2021/texture.h index 1a37395..fa549fd 100644 --- a/SQCSim2021/texture.h +++ b/SQCSim2021/texture.h @@ -1,9 +1,9 @@ #ifndef TEXTURE_H__ #define TEXTURE_H__ -#include "define.h" -#include #include +#include +#include "define.h" class Texture { diff --git a/SQCSim2021/textureatlas.h b/SQCSim2021/textureatlas.h index 1d717e1..fab0665 100644 --- a/SQCSim2021/textureatlas.h +++ b/SQCSim2021/textureatlas.h @@ -1,9 +1,9 @@ #ifndef TEXTUREATLAS_H__ #define TEXTUREATLAS_H__ -#include "define.h" #include #include #include +#include "define.h" class TextureAtlas { diff --git a/SQCSim2021/world.cpp b/SQCSim2021/world.cpp deleted file mode 100644 index dc5e5b6..0000000 --- a/SQCSim2021/world.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#include "world.h" - -World::World() {} - -World::~World() {} - -Array2d& World::GetChunks() { return m_chunks; } - -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; - - if (x < 0 || y < 0 || z < 0 || - x >= WORLD_SIZE_X * CHUNK_SIZE_X || - z >= CHUNK_SIZE_Z * WORLD_SIZE_Y || - y > CHUNK_SIZE_Y) - return 0; - - return m_chunks.Get(cx, cz); -} - -Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); } - -BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const { - Chunk* c = ChunkAt(x, y, z); - - if (!c) - return defaultBlockType; - - int bx = (int)x % CHUNK_SIZE_X; - int by = (int)y % CHUNK_SIZE_Y; - int bz = (int)z % CHUNK_SIZE_Z; - - return c->GetBlock(bx, by, bz); -} - -BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const { - return BlockAt(pos.x, pos.y, pos.z, defaultBlockType); -} - -void World::TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]) { - int x = 0, y = 0; - - if (player.GetPosition().x > (WORLD_SIZE_X * CHUNK_SIZE_X) * .6f) ++x; - else if (player.GetPosition().x < (WORLD_SIZE_X * CHUNK_SIZE_X) * .4f) --x; - if (player.GetPosition().z > (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .6f) ++y; - else if (player.GetPosition().z < (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .4f) --y; - - if (!x && !y) return; - - if (x > 0) { - for (int ax = 0; ax < WORLD_SIZE_X; ++ax) - for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) - if (ax - x >= 0) { - m_chunks.Set(ax - x, ay, - m_chunks.Remove(ax, ay)); - if (ax == WORLD_SIZE_X - 1 && m_chunks.Get(ax - x, ay)) - m_chunks.Get(ax - x, ay)->MakeDirty(); - } - else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); - } - else if (x < 0) { - for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax) - for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay) - if (ax - x < WORLD_SIZE_X) { - m_chunks.Set(ax - x, ay, - m_chunks.Remove(ax, ay)); - if (ax == 0 && m_chunks.Get(ax - x, ay)) - m_chunks.Get(ax - x, ay)->MakeDirty(); - } - else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); - } - - if (y > 0) { - for (int ax = 0; ax < WORLD_SIZE_X; ++ax) - for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) - if (ay - y >= 0) { - m_chunks.Set(ax, ay - y, - m_chunks.Remove(ax, ay)); - if (ay == WORLD_SIZE_Y - 1 && m_chunks.Get(ax, ay - y)) - m_chunks.Get(ax, ay - y)->MakeDirty(); - } - else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); - } - else if (y < 0) { - for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax) - for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay) - if (ay - y < WORLD_SIZE_Y) { - m_chunks.Set(ax, ay - y, - m_chunks.Remove(ax, ay)); - if (ay == 0 && m_chunks.Get(ax, ay - y)) - m_chunks.Get(ax, ay - y)->MakeDirty(); - } - else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay)); - } - - m_center[0] += x; m_center[1] += y; - player.Teleport(x, y); - - for (int index = 0; index < MAX_BULLETS; ++index) - if (bullets[index]) bullets[index]->Transpose(x, y); -} - -void World::CleanUpWorld(int& deleteframes, bool clear = false) { - if (clear) { - while (m_tbDeleted.size() > 0) { - delete m_tbDeleted.back(); - m_tbDeleted.pop_back(); - } - } - if (!m_tbDeleted.empty() && !deleteframes) { - int deleted = 0; - while (deleted < THREADS_DELETE_CHUNKS) { - - - } - delete m_tbDeleted.back(); - m_tbDeleted.pop_back(); - deleteframes = FRAMES_DELETE_CHUNKS; - } -} - -void World::GetScope(unsigned int& x, unsigned int& y) { - x = m_center[0]; - y = m_center[1]; -} - -void World::Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, BlockInfo* blockinfo[BTYPE_LAST]) { - glStencilFunc(GL_EQUAL, 1, 0x00); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - atlas.Bind(); - RenderWorld(rendercount, player, world, shader); - UpdateWorld(player, blockinfo); - //TransposeWorld(player, bullets); - shader.Disable(); - glStencilFunc(GL_GREATER, 1, 0xFF); -} - -void World::UpdateChunk(int& updates, unsigned int chx, unsigned 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; - } - -} - -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 être sûr que le bloc à 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::ChangeBlockAtPosition(BlockType blockType, Vector3f pos) { - int bx = (int)pos.x % CHUNK_SIZE_X; - int by = (int)pos.y % CHUNK_SIZE_Y; - int bz = (int)pos.z % CHUNK_SIZE_Z; - - ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this); - ChunkAt(pos)->MakeModified(); -} - -void World::RenderWorld(int& rendercount, Player& player, Transformation& world, Shader& shader) { - shader.Use(); - rendercount = 0; - Vector3f angle; - Vector3f cursor; - Vector3f direct = player.GetDirection(); - Vector3f pos = player.GetPosition() - direct; - - direct.y = 0; - direct.Normalize(); - pos.y = 1; - - static Vector3 renderManifest[VIEW_DISTANCE * 8]; // Nombre de Chunks maximal à ê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é) - cosinus = .99996192306; // cos(1/2 degré) - echantillons = 180; - } - //else if (dist > VIEW_DISTANCE * .3f) { - // sinus = .01151891831f; // sin(2/3 degré) - // cosinus = .99993365506; // cos(2/3 degré) - // echantillons = 120; - //} - //else if (dist > VIEW_DISTANCE * .2f) { - // sinus = .01745240643; // sin(1 degré) - // cosinus = .99984769515; // cos(1 degré) - // 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 * 2 + angle * dist; - if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = CHUNK_SIZE_Y / 2.f; - - - if (ChunkAt(cursor)) { - bool valide = true; - unsigned int chx, chy; - ChunkAt(cursor)->GetPosition(chx, chy); - for (int index = 0; index < rendercount; ++index) // Permet de vérifier seulement contre celles ajoutées dans la frame, et ne pas avoir à refaire l'array à chaque frame. - if (renderManifest[index].x == chx && renderManifest[index].z == chy) - valide = false; - - if (valide) renderManifest[rendercount++] = Vector3(chx, - (VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) < 0.f? 0: - (VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) * 1000, - chy); - } - } - } - for (int index = 0; index < rendercount; ++index) { - int chx = (renderManifest[index].x - m_center[0]) * CHUNK_SIZE_X, chy = (renderManifest[index].z - m_center[1]) * CHUNK_SIZE_Z; - - world.ApplyTranslation(chx, 0, chy); - world.Use(); - float blcolor = renderManifest[index].y / (VIEW_DISTANCE / 50.f); - glBlendColor(blcolor, blcolor, blcolor, 1.f); - ChunkAt(chx, 1, chy)->Render(); - world.ApplyTranslation(-chx, 0, -chy); - } - shader.Disable(); -}; - -void World::UpdateWorld(Player& player, BlockInfo* blockinfo[BTYPE_LAST]) { - int cx = player.GetPosition().x; - int cy = player.GetPosition().z; - static int frameGenerate = 1; - static int frameUpdate = 2; - static int frameDelete = 3; - int side = 0; - int threads = 0; - std::future genThList[THREADS_GENERATE_CHUNKS]; - std::future updateThList[THREADS_UPDATE_CHUNKS]; - std::future delThList[THREADS_DELETE_CHUNKS]; - - if (frameGenerate > 0) --frameGenerate; - if (frameUpdate > 0) --frameUpdate; - if (frameDelete > 0) --frameDelete; - - if (!frameGenerate) - while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2 + CHUNK_SIZE_X) { - int tx = -side, ty = -side; - int chx = 0; - int chy = 0; - - 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, - [](unsigned int x, unsigned int y, uint64_t seed) { - return new Chunk(x, y, seed); }, - chx / CHUNK_SIZE_X + m_center[0], - chy / CHUNK_SIZE_Z + m_center[1], - m_seed); - 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, - [](unsigned int x, unsigned int y, uint64_t seed) { - return new Chunk(x, y, seed); }, - chx / CHUNK_SIZE_X + m_center[0], - chy / CHUNK_SIZE_Z + m_center[1], - m_seed); - 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, - [](unsigned int x, unsigned int y, uint64_t seed) { - return new Chunk(x, y, seed); }, - chx / CHUNK_SIZE_X + m_center[0], - chy / CHUNK_SIZE_Z + m_center[1], - m_seed); - 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, - [](unsigned int x, unsigned int y, uint64_t seed) { - return new Chunk(x, y, seed); }, - chx / CHUNK_SIZE_X + m_center[0], - chy / CHUNK_SIZE_Z + m_center[1], - m_seed); - 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) { - unsigned 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; - unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; - if (ChunkAt(chx, 1, chy) && - 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; - } - } - for (; ty <= side; ++ty) { - if (frameUpdate) - break; - unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; - if (ChunkAt(chx, 1, chy) && - 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; - } - } - for (; tx >= -side; --tx) { - if (frameUpdate) - break; - unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; - if (ChunkAt(chx, 1, chy) && - 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; - } - } - for (; ty >= -side; --ty) { - if (frameUpdate) - break; - unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z; - if (ChunkAt(chx, 1, chy) && - 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(); - Chunk* chunk = updateThList[i].get(); - chunk->FlushMeshToVBO(); - } - } - - threads = 0; - - int del = THREADS_DELETE_CHUNKS; - while (!m_tbDeleted.empty() && del--) { // Moins rapide que le bout en dessous, mais -beaucoup- plus stable. - m_tbDeleted.back()->FlushVBO(); - m_tbDeleted.back()->~Chunk(); - m_tbDeleted.pop_back(); - } - - /*while (!m_tbDeleted.empty() && !frameDelete) { - if (m_tbDeleted.back()) { - m_tbDeleted.back()->FlushVBO(); - delThList[threads] = - std::async(std::launch::async, - [](Chunk* chunk) { delete chunk; }, m_tbDeleted.back()); - m_tbDeleted.pop_back(); - if (++threads > THREADS_DELETE_CHUNKS) frameDelete = FRAMES_DELETE_CHUNKS; - } - else m_tbDeleted.pop_back(); - }*/ - - for (int x = 0; x < threads; ++x) { - delThList[x].wait(); - delThList[x].get(); - } -} - -int World::GettbDeleted() const { return m_tbDeleted.size(); } \ No newline at end of file diff --git a/SQCSim2021/world.h b/SQCSim2021/world.h deleted file mode 100644 index 0b88748..0000000 --- a/SQCSim2021/world.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef WORLD_H__ -#define WORLD_H__ -#include -#include -#include -#include -#include -#include "../SQCSim-common/vector3.h" -#include "../SQCSim-common/array2d.h" -#include "../SQCSim-common/bullet.h" -#include "define.h" -#include "player.h" -#include "chunk.h" -#include "transformation.h" -#include "shader.h" -#include "textureatlas.h" - -class Chunk; -class Player; -class Bullet; - -class World { -public: - World(); - ~World(); - - Array2d& GetChunks(); - - void SetSeed(uint64_t seed); - - Chunk* ChunkAt(float x, float y, float z) const; - Chunk* ChunkAt(const Vector3f& pos) const; - - BlockType BlockAt(float x, float y, float z, BlockType defaultBlockType = BTYPE_AIR) const; - BlockType BlockAt(const Vector3f& pos, BlockType defaultBlockType = BTYPE_AIR) const; - - void Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, BlockInfo* blockinfo[BTYPE_LAST]); - - void GetScope(unsigned int& x, unsigned int& y); - - void ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block); - void ChangeBlockAtPosition(BlockType blockType, Vector3f pos); - void CleanUpWorld(int& deleteframes, bool clear); - int GettbDeleted() const; -private: - Array2d m_chunks = Array2d(WORLD_SIZE_X, WORLD_SIZE_Y); - std::vector m_tbDeleted; - uint64_t m_seed = 0; - - unsigned int m_center[2] = { UINT16_MAX / 2 - WORLD_SIZE_X, UINT16_MAX / 2 - WORLD_SIZE_Y }; - - void UpdateChunk(int& updates, unsigned int chx, unsigned int chy, BlockInfo* blockinfo[BTYPE_LAST]); - void RenderWorld(int& rendercount, Player& player, Transformation& world, Shader& shader); - void UpdateWorld(Player& player, BlockInfo* blockinfo[BTYPE_LAST]); - void TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]); - -}; -#endif // WORLD_H__ - diff --git a/SQCSim2021/worldrenderer.cpp b/SQCSim2021/worldrenderer.cpp new file mode 100644 index 0000000..dcf6d45 --- /dev/null +++ b/SQCSim2021/worldrenderer.cpp @@ -0,0 +1,213 @@ +#include "worldrenderer.h" + +WorldRenderer::WorldRenderer() { + m_meshes.Reset(nullptr); +} + +WorldRenderer::~WorldRenderer() { +} + +void WorldRenderer::RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation& world, Shader& shader, TextureAtlas& atlas) { + 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 renderManifest[VIEW_DISTANCE * 8]; // Nombre de Chunks maximal à ê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é) + cosinus = .99996192306; // cos(1/2 degré) + echantillons = 180; + } + //else {//if (dist > VIEW_DISTANCE * .3f) { + // sinus = .01151891831f; // sin(2/3 degré) + // cosinus = .99993365506; // cos(2/3 degré) + // echantillons = 120; + //} + //else if (dist > VIEW_DISTANCE * .2f) { + // sinus = .01745240643; // sin(1 degré) + // cosinus = .99984769515; // cos(1 degré) + // 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ées dans la frame, et ne pas avoir à refaire l'array à chaque frame. + if (renderManifest[index].x == chx && renderManifest[index].z == chy) + valide = false; + + if (valide) renderManifest[rendercount++] = Vector3(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 WorldRenderer::UpdateWorld(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 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(); + } + } +} diff --git a/SQCSim2021/worldrenderer.h b/SQCSim2021/worldrenderer.h new file mode 100644 index 0000000..46e6624 --- /dev/null +++ b/SQCSim2021/worldrenderer.h @@ -0,0 +1,23 @@ +#ifndef WORLDRENDERER_H__ +#define WORLDRENDERER_H__ +#include +#include +#include "../SQCSim-common/world.h" +#include "../SQCSim-common/transformation.h" +#include "define.h" +#include "mesh.h" +#include "textureatlas.h" +#include "shader.h" + +class WorldRenderer { +private: + Array2d m_meshes = Array2d(WORLD_SIZE_X, WORLD_SIZE_Y); + +public: + WorldRenderer(); + ~WorldRenderer(); + + void RenderWorld(World* origin, int& rendercount, const Vector3f& player_pos, const Vector3f& player_dir, Transformation& world, Shader& shader, TextureAtlas& atlas); + void UpdateWorld(World* origin, const Vector3f& player, BlockInfo* blockinfo[BTYPE_LAST]); +}; +#endif \ No newline at end of file