From 97ffc34e2497ed6069c5c1461e47dec9b7a70125 Mon Sep 17 00:00:00 2001 From: MarcEricMartel <74071476+MarcEricMartel@users.noreply.github.com> Date: Tue, 30 Nov 2021 19:55:11 -0500 Subject: [PATCH] =?UTF-8?q?=C3=87A=20SAVE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SQCSim2021/chunk.cpp | 58 ++-- SQCSim2021/chunk.h | 4 +- SQCSim2021/define.h | 3 +- SQCSim2021/engine.cpp | 250 ++++++++++++------ SQCSim2021/engine.h | 9 +- .../exemple_lecture_ecriture_fichier.cpp | 90 ------- SQCSim2021/media/chunks/60_66.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/60_67.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/60_68.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/61_55.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/61_56.chunk | 1 + SQCSim2021/media/chunks/61_68.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/64_72.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/66_57.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/70_49.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/70_50.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/80_36.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/86_31.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/88_31.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/89_29.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/chunks/89_31.chunk | Bin 0 -> 32768 bytes SQCSim2021/media/shaders/shader01.frag | 3 +- SQCSim2021/media/shaders/shader01.vert | 2 +- SQCSim2021/shader.h | 1 - SQCSim2021/world.cpp | 1 + SQCSim2021/world.h | 2 + 26 files changed, 221 insertions(+), 203 deletions(-) delete mode 100644 SQCSim2021/exemple_lecture_ecriture_fichier.cpp create mode 100644 SQCSim2021/media/chunks/60_66.chunk create mode 100644 SQCSim2021/media/chunks/60_67.chunk create mode 100644 SQCSim2021/media/chunks/60_68.chunk create mode 100644 SQCSim2021/media/chunks/61_55.chunk create mode 100644 SQCSim2021/media/chunks/61_56.chunk create mode 100644 SQCSim2021/media/chunks/61_68.chunk create mode 100644 SQCSim2021/media/chunks/64_72.chunk create mode 100644 SQCSim2021/media/chunks/66_57.chunk create mode 100644 SQCSim2021/media/chunks/70_49.chunk create mode 100644 SQCSim2021/media/chunks/70_50.chunk create mode 100644 SQCSim2021/media/chunks/80_36.chunk create mode 100644 SQCSim2021/media/chunks/86_31.chunk create mode 100644 SQCSim2021/media/chunks/88_31.chunk create mode 100644 SQCSim2021/media/chunks/89_29.chunk create mode 100644 SQCSim2021/media/chunks/89_31.chunk diff --git a/SQCSim2021/chunk.cpp b/SQCSim2021/chunk.cpp index e4bb929..45d57de 100644 --- a/SQCSim2021/chunk.cpp +++ b/SQCSim2021/chunk.cpp @@ -3,7 +3,32 @@ Chunk::Chunk(int x, int y) : m_posX(x), m_posY(y) { m_blocks.Reset(BTYPE_AIR); } -Chunk::~Chunk() { } +Chunk::Chunk(int x, int y, char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]) : m_posX(x), m_posY(y) { + 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) + m_blocks.Set(x, y, z, data[x + (z * CHUNK_SIZE_X) + (y * 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().c_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); @@ -39,9 +64,10 @@ void Chunk::CheckNeighbors(int x, int z, World* world) { world->ChunkAt(m_posX * CHUNK_SIZE_X, 1, (m_posY + 1) * CHUNK_SIZE_Z)->MakeDirty(); } -int Chunk::GetPosX() const { return m_posX; } - -int Chunk::GetPosY() const { return m_posY; } +void Chunk::GetPosition(int& x, int& y) const { + x = m_posX; + y = m_posY; +} void Chunk::Update(BlockInfo* blockinfo[BTYPE_LAST], World* world) { float u, v, s; @@ -88,10 +114,10 @@ void Chunk::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType b } if (y == 0 || GetBlock(x, y - 1, z) == BTYPE_AIR) { // -y - vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .8f, .8f, .8f, u, v); - vd[count++] = VertexBuffer::VertexData(x, y, z, .8f, .8f, .8f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z, .8f, .8f, .8f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, .8f, .8f, .8f, u + s, v); + 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 @@ -102,17 +128,17 @@ void Chunk::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType b } if (world->BlockAt(cx - 1, y, cy) == BTYPE_AIR) { // -x - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, .9f, .9f, .9f, u, v + s); - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z, .9f, .9f, .9f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x, y, z, .9f, .9f, .9f, u + s, v); - vd[count++] = VertexBuffer::VertexData(x, y, z + 1.f, .9f, .9f, .9f, u, v); + 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, 1.f, 1.f, 1.f, u, v); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y, z + 1.f, 1.f, 1.f, 1.f, u + s, v); - vd[count++] = VertexBuffer::VertexData(x + 1.f, y + 1.f, z + 1.f, 1.f, 1.f, 1.f, u + s, v + s); - vd[count++] = VertexBuffer::VertexData(x, y + 1.f, z + 1.f, 1.f, 1.f, 1.f, u, v + s); + 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 diff --git a/SQCSim2021/chunk.h b/SQCSim2021/chunk.h index 1bde671..e4d21b4 100644 --- a/SQCSim2021/chunk.h +++ b/SQCSim2021/chunk.h @@ -22,14 +22,14 @@ class Chunk { public: Chunk(int x, int y); + Chunk(int x, int y, char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]); ~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(int x, int z, World* world); - int GetPosX() const; - int GetPosY() const; + void GetPosition(int& x, int& y) const; void Update(BlockInfo* blockinfo[BTYPE_LAST], World* world); diff --git a/SQCSim2021/define.h b/SQCSim2021/define.h index ad3e097..d12d984 100644 --- a/SQCSim2021/define.h +++ b/SQCSim2021/define.h @@ -22,7 +22,7 @@ #define FRAMES_RENDER_CHUNKS 2 #define FRAMES_UPDATE_CHUNKS 2 -#define VIEW_DISTANCE 128 +#define VIEW_DISTANCE 512 #define MAX_SELECTION_DISTANCE 5 typedef uint8_t BlockType; @@ -31,5 +31,6 @@ enum BLOCK_TYPE { BTYPE_AIR, BTYPE_DIRT, BTYPE_GRASS, BTYPE_METAL, BTYPE_ICE, BT #define TEXTURE_PATH "../SQCSim2021/media/textures/" #define SHADER_PATH "../SQCSim2021/media/shaders/" #define AUDIO_PATH "../SQCSim2021/media/audio/" +#define CHUNK_PATH "../SQCSim2021/media/chunks/" #endif // DEFINE_H__ diff --git a/SQCSim2021/engine.cpp b/SQCSim2021/engine.cpp index 1bbfbf0..f683569 100644 --- a/SQCSim2021/engine.cpp +++ b/SQCSim2021/engine.cpp @@ -8,8 +8,7 @@ Engine::Engine() { } Engine::~Engine() { } -void Engine::Init() -{ +void Engine::Init() { GLenum glewErr = glewInit(); if (glewErr != GLEW_OK) { std::cerr << " ERREUR GLEW : " << glewGetErrorString(glewErr) << std::endl; @@ -18,17 +17,21 @@ void Engine::Init() glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glEnable(GL_TEXTURE_2D); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (float)Width() / (float)Height(), 0.0001f, 1000.0f); glEnable(GL_DEPTH_TEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glShadeModel(GL_SMOOTH); + //glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LINE_SMOOTH); glEnable(GL_CULL_FACE); + glDisable(GL_FRAMEBUFFER_SRGB); + + glEnable(GL_BLEND); + glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + // Light GLfloat light0Pos[4] = { 0.0f, CHUNK_SIZE_Y, 0.0f, 1.0f }; GLfloat light0Amb[4] = { 0.2f, 0.2f, 0.2f, 1.f }; @@ -41,11 +44,14 @@ void Engine::Init() glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diff); glLightfv(GL_LIGHT0, GL_SPECULAR, light0Spec); + // Init manifeste de chunks renderés. + m_renderManifest.reserve(3000); + // Objet de skybox avec sa propre texture et son propre shader! m_skybox.Init(0.00013f); // Objet de musique! - m_audio.ToggleMusicState(); + //m_audio.ToggleMusicState(); // Init Chunks m_world.GetChunks().Reset(nullptr); @@ -67,7 +73,7 @@ void Engine::LoadResource() { TextureAtlas::TextureIndex texGrassIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "grass.png"); TextureAtlas::TextureIndex texMetalIndex = m_textureAtlas.AddTexture(TEXTURE_PATH "metal.png"); - if (!m_textureAtlas.Generate(128, false)) { + if (!m_textureAtlas.Generate(512, false)) { std::cout << " Unable to generate texture atlas ..." << std::endl; abort(); } @@ -101,7 +107,7 @@ void Engine::DrawHud(float elapsedTime) { glDisable(GL_LIGHTING); glColor4f(1.f, 1.f, 1.f, 1.f); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glEnable(GL_BLEND); + //glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -119,6 +125,9 @@ void Engine::DrawHud(float elapsedTime) { ss << " Rendered Chunks : " << m_renderCount; PrintText(10, Height() - 35, ss.str()); ss.str(""); + ss << " Bad Hits on Chunks : " << m_badHitCount; + PrintText(10, Height() - 45, ss.str()); + ss.str(""); ss << " Velocity : " << m_player.GetVelocity(); // IMPORTANT : on utilise l ’ operateur << pour afficher la position PrintText(10, 10, ss.str()); ss.str(""); @@ -146,7 +155,9 @@ void Engine::DrawHud(float elapsedTime) { glVertex2i(0, crossSize); glEnd(); glEnable(GL_LIGHTING); - glDisable(GL_BLEND); + //glDisable(GL_BLEND); + //glBlendFuncSeparate(GL_SRC_COLOR, GL_ONE_MINUS_DST_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -198,25 +209,29 @@ void Engine::Render(float elapsedTime) { 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!). + glDisable(GL_LIGHT0); - m_skybox.Render(skybox); - - // Génération/Update de Chunks. + //m_skybox.Render(skybox); glEnable(GL_LIGHT0); + + if (m_mouseL) + ChangeBlockAtCursor(BTYPE_DIRT); + else if (m_mouseR) + ChangeBlockAtCursor(BTYPE_AIR); + + // Génération/Update des Chunks. m_textureAtlas.Bind(); int cx = m_player.GetPosition().x; int cy = m_player.GetPosition().z; static int frameGenerate = 0; static int frameUpdate = 0; int side = 0; - m_shader01.Use(); - m_renderCount = 0; if (frameGenerate > 0) --frameGenerate; if (frameUpdate > 0) --frameUpdate; if (!frameGenerate || !frameUpdate) - while (side * CHUNK_SIZE_X <= VIEW_DISTANCE) { + while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) { int tx = -side, ty = -side; for (; tx <= side; ++tx) @@ -231,77 +246,69 @@ void Engine::Render(float elapsedTime) { ++side; } - // Rendering de Chunks. - all.Use(); - if (m_renderer) { // Choix d'algorithme de rendu pour comparer. - Vector3f direct = m_player.GetDirection(); - Vector3f renderpos = m_player.GetPosition(); + // Rendering des Chunks. + m_shader01.Use(); + m_renderCount = 0; + m_badHitCount = 0; + Vector3f angle; + Vector3f cursor; + Vector3f direct = m_player.GetDirection(); + Vector3f pos = m_player.GetPosition() - direct; - direct.y = 0; - direct.Normalize(); + direct.y = 0; + direct.Normalize(); + pos.y = 1; + m_renderManifest.clear(); - Vector3f viewL = renderpos - direct * CHUNK_SIZE_X * 2, - viewR = viewL; + for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) { + // Configuration du radar. + angle.x = direct.z + direct.x; + angle.y = 0; + angle.z = direct.z - direct.x; + angle.Normalize(); - viewL.Dot(direct); - viewR.Dot(direct); + float sinus = .01745240643; // sin(1 degré) + float cosinus = .99984769515; // cos(1 degré) + int echantillons = 90; - for (int x = -3; x <= VIEW_DISTANCE / CHUNK_SIZE_X; ++x) { - int chunkxL = -1, chunkyL = -1, chunkxR = -1, chunkyR = -1; + for (int radar = 0; radar < echantillons; ++radar) { + float x = angle.x; + float z = angle.z; - if (m_world.ChunkAt(viewL)) { - chunkxL = m_world.ChunkAt(viewL)->GetPosX(); - chunkyL = m_world.ChunkAt(viewL)->GetPosY(); - } - if (m_world.ChunkAt(viewR)) { - chunkxR = m_world.ChunkAt(viewR)->GetPosX(); - chunkyR = m_world.ChunkAt(viewR)->GetPosY(); - } + angle.x = x * cosinus - z * sinus; + angle.z = z * cosinus + x * sinus; + angle.Normalize(); - if (chunkxL == chunkxR) { - ++chunkxR; - --chunkxL; - } - if (chunkyL == chunkyR) { - ++chunkyR; - --chunkyL; - } + cursor = pos - direct * CHUNK_SIZE_X * 2 + angle * dist; + if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = 1; - if (chunkxL >= 0 && chunkyL >= 0 && chunkxR >= 0 && chunkyR >= 0) - for (int rx = chunkxL; rx != chunkxR; chunkxL < chunkxR ? ++rx : --rx) - for (int ry = chunkyL; ry != chunkyR; chunkyL < chunkyR ? ++ry : --ry) { - all.ApplyTranslation(rx * CHUNK_SIZE_X, 0, ry * CHUNK_SIZE_Z); - all.Use(); - if (m_world.GetChunks().Get(rx, ry)) { - m_world.GetChunks().Get(rx, ry)->Render(); - ++m_renderCount; - } - all.ApplyTranslation(-rx * CHUNK_SIZE_X, 0, -ry * CHUNK_SIZE_Z); + bool valide = true; + + if (m_world.ChunkAt(cursor)) { + int chx, chy; + m_world.ChunkAt(cursor)->GetPosition(chx, chy); + for (int index = 0; index < m_renderManifest.size(); ++index) + if (m_renderManifest[index] == Vector3i(chx, 0, chy)) { + valide = false; + ++m_badHitCount; } - viewL.x += (direct.x + direct.z) * CHUNK_SIZE_X / 2; - viewL.z += (direct.z - direct.x) * CHUNK_SIZE_X / 2; - viewR.x += (direct.x - direct.z) * CHUNK_SIZE_X / 2; - viewR.z += (direct.z + direct.x) * CHUNK_SIZE_X / 2; - } - } - else { - for (int chx = 0; chx < WORLD_SIZE_X; chx++) - for (int chy = 0; chy < WORLD_SIZE_Y; chy++) { - all.ApplyTranslation(chx * CHUNK_SIZE_X, 0, chy * CHUNK_SIZE_Z); - all.Use(); - if (m_world.GetChunks().Get(chx, chy)) { + if (valide) { + all.ApplyTranslation(chx * CHUNK_SIZE_X, 0, chy * CHUNK_SIZE_Z); + all.Use(); + float dist = (pos - cursor).Length(); + float blend = ((float)VIEW_DISTANCE - dist * 2.f + 128.f) / (float)VIEW_DISTANCE; + glBlendColor(0.f,0.f,0.f,blend); m_world.GetChunks().Get(chx, chy)->Render(); + all.ApplyTranslation(-chx * CHUNK_SIZE_X, 0, -chy * CHUNK_SIZE_Z); + m_renderManifest.push_back(Vector3i(chx, 0, chy)); ++m_renderCount; } - all.ApplyTranslation(-chx * CHUNK_SIZE_X, 0, -chy * CHUNK_SIZE_Z); } + } } - m_shader01.Disable(); - if (m_mouseL) - GetBlockAtCursor(BTYPE_DIRT); - else if (m_mouseR) GetBlockAtCursor(BTYPE_AIR); + m_shader01.Disable(); if (m_wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -309,15 +316,19 @@ void Engine::Render(float elapsedTime) { if (m_wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (m_player.GetPosition().y < -20.f) - m_player = Player(Vector3f(CHUNK_SIZE_X * WORLD_SIZE_X / 2, CHUNK_SIZE_Y + 1.7f, CHUNK_SIZE_Z * WORLD_SIZE_X / 2)); // Respawn si le bonho- joueur tombe en bas du monde. + m_player = Player(Vector3f(CHUNK_SIZE_X * WORLD_SIZE_X / 2, CHUNK_SIZE_Y + 1.8f, CHUNK_SIZE_Z * WORLD_SIZE_X / 2)); // Respawn si le bonho- joueur tombe en bas du monde. } void Engine::KeyPressEvent(unsigned char key) { switch (key) { case 36: // ESC + for (int x = 0; x < WORLD_SIZE_X; ++x) // Les destructeurs de Chunks ont de la misère je les aide un peu! + for (int y = 0; y < WORLD_SIZE_Y; ++y) + if (m_world.GetChunks().Get(x,y)) + m_world.GetChunks().Get(x, y)->~Chunk(); + m_world.GetChunks().Reset(nullptr); // Hack cheap qui empêche d'avoir une exception en sortant du jeu Stop(); break; case 94: // F10 @@ -490,17 +501,80 @@ bool Engine::GenerateChunk(int chx, int chy) { if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && chx >= 0 && chy >= 0) if (!m_world.ChunkAt(chx, 1, chy)) { - m_world.GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z)); - Chunk* chunk = m_world.GetChunks().Get(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z); - for (int x = 0; x < CHUNK_SIZE_X; ++x) - for (int z = 0; z < CHUNK_SIZE_Z; ++z) - for (int y = 0; y < 32; ++y) - chunk->SetBlock(x, y, z, (chx + chy) % (BTYPE_LAST - 1) + 1, &m_world); + std::ostringstream pos; + pos << CHUNK_PATH << chx / CHUNK_SIZE_X << '_' << chy / CHUNK_SIZE_Z << ".chunk"; + std::ifstream input(pos.str().c_str(), std::fstream::binary); + + if (input.fail()) { + m_world.GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z)); + Chunk* chunk = m_world.GetChunks().Get(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z); + + for (int x = 0; x < CHUNK_SIZE_X; ++x) + for (int z = 0; z < CHUNK_SIZE_Z; ++z) { + Vector3f perlin; + perlin.z = x * CHUNK_SIZE_X + CHUNK_SIZE_X * chx; + perlin.y = 0; + perlin.x = z * CHUNK_SIZE_Z + CHUNK_SIZE_Z * chy; + perlin.Normalize(); + float height = m_perlin.Get(perlin.x, perlin.z) * 3 - 32; + for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) { + chunk->SetBlock(x, y, z, BTYPE_METAL, &m_world); + } + } + + for (int x = 0; x < CHUNK_SIZE_X; ++x) + for (int z = 0; z < CHUNK_SIZE_Z; ++z) { + Vector3f perlin; + perlin.x = x * CHUNK_SIZE_X + CHUNK_SIZE_X * chx; + perlin.y = 0; + perlin.z = z * CHUNK_SIZE_Z + CHUNK_SIZE_Z * chy; + perlin.Normalize(); + float height = m_perlin.Get(perlin.x, perlin.z) + 16; + for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) { + if (chunk->GetBlock(x, y, z) == BTYPE_AIR) + chunk->SetBlock(x, y, z, BTYPE_GRASS, &m_world); + } + } + + for (int x = 0; x < CHUNK_SIZE_X; ++x) + for (int z = 0; z < CHUNK_SIZE_Z; ++z) { + for (int y = 0; y <= 10; ++y) { + if (chunk->GetBlock(x, y, z) == BTYPE_AIR) + chunk->SetBlock(x, y, z, BTYPE_ICE, &m_world); + } + } + + for (int x = 0; x < CHUNK_SIZE_X; ++x) + for (int z = 0; z < CHUNK_SIZE_Z; ++z) { + for (int y = 0; y < CHUNK_SIZE_Y; ++y) { + Vector3f perlin; + perlin.x = x * CHUNK_SIZE_X + CHUNK_SIZE_X * chx; + perlin.y = (x + z) * CHUNK_SIZE_Y; + perlin.z = z * CHUNK_SIZE_Z + CHUNK_SIZE_Z * chy; + perlin.Normalize(); + float height = m_perlin.Get(perlin.x, perlin.y, perlin.z); + if (chunk->GetBlock(x, y, z) != BTYPE_AIR && height > 18) + chunk->SetBlock(x, y, z, BTYPE_DIRT, &m_world); + } + } + } + else { + input.seekg(0, std::ios_base::end); + int size = input.tellg(); + input.seekg(0, std::ios_base::beg); + + char* data = new char[size]; + input.read(data, size); + input.close(); + + m_world.GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, data)); + + delete[] data; + } std::cout << "Chunk generated: " << chx / CHUNK_SIZE_X << ", " << chy / CHUNK_SIZE_Z << std::endl; - return true; } return false; @@ -515,7 +589,7 @@ void Engine::UpdateWorld(int& generates, int& updates, int chx, int chy) { } } -void Engine::GetBlockAtCursor(BlockType blockType) { +void Engine::ChangeBlockAtCursor(BlockType blockType) { Vector3f currentPos = m_player.GetPosition(); Vector3f currentBlock = currentPos; Vector3f ray = m_player.GetDirection(); @@ -527,7 +601,7 @@ void Engine::GetBlockAtCursor(BlockType blockType) { currentBlock += ray / 10.f; BlockType bt = m_world.BlockAt(currentBlock); - + if (bt != BTYPE_AIR) found = true; } @@ -540,7 +614,7 @@ void Engine::GetBlockAtCursor(BlockType blockType) { BlockType bt = m_world.BlockAt(currentBlock); - if (bt == BTYPE_AIR) { + 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; @@ -551,12 +625,12 @@ void Engine::GetBlockAtCursor(BlockType blockType) { 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 (!(Bx == Px && + (By == PyA || + By == PyB || + By == PyC) && + Bz == Pz)) + found = true; } } } diff --git a/SQCSim2021/engine.h b/SQCSim2021/engine.h index 93df26d..8b90aa0 100644 --- a/SQCSim2021/engine.h +++ b/SQCSim2021/engine.h @@ -13,6 +13,7 @@ #include "blockinfo.h" #include "array2d.h" #include "world.h" +#include "perlin.h" class Engine : public OpenglContext { public: @@ -37,17 +38,19 @@ private: bool GenerateChunk(int chx, int chy); void UpdateWorld(int& generates, int& updates, int chx, int chy); - void GetBlockAtCursor(BlockType blocktype); + void ChangeBlockAtCursor(BlockType blocktype); bool m_wireframe = false; bool m_renderer = false; int m_renderCount = 0; + int m_badHitCount = 0; + std::vector m_renderManifest; BlockInfo* m_blockinfo[BTYPE_LAST]; TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST); World m_world = World(); - + Perlin m_perlin = Perlin(3,5.f,64.f,12345); Texture m_textureFloor; Texture m_textureSkybox; @@ -59,7 +62,7 @@ private: Shader m_shader01; Audio m_audio = Audio(AUDIO_PATH "music01.wav"); - Player m_player = Player(Vector3f(CHUNK_SIZE_X * WORLD_SIZE_X / 2, CHUNK_SIZE_Y + 1.7f, CHUNK_SIZE_Z * WORLD_SIZE_X / 2)); + Player m_player = Player(Vector3f(CHUNK_SIZE_X * WORLD_SIZE_X / 2, CHUNK_SIZE_Y + 1.8f, CHUNK_SIZE_Z * WORLD_SIZE_X / 2)); bool m_keyW = false; bool m_keyA = false; diff --git a/SQCSim2021/exemple_lecture_ecriture_fichier.cpp b/SQCSim2021/exemple_lecture_ecriture_fichier.cpp deleted file mode 100644 index 8c050c2..0000000 --- a/SQCSim2021/exemple_lecture_ecriture_fichier.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -void FichierTexte() -{ - std::ofstream sortie("fichier.txt"); // std::fstream::app - if(!sortie.is_open()) - { - std::cerr << "Erreur d'ouverture de fichier" << std::endl; - return; - } - - sortie << "Premiere ligne de plusieurs mots" << std::endl; - sortie << "Age: " << 6 << std::endl; - sortie.close(); - - - std::ifstream entree("fichier.txt"); - if(!entree.is_open()) - { - std::cerr << "Erreur d'ouverture de fichier" << std::endl; - return; - } - - std::string mot; - std::string line; - int age; - entree >> mot; - std::cout << mot << std::endl; - - std::getline(entree, line); - std::cout << line << std::endl; - - entree >> mot; - entree >> age; - std::cout << age << std::endl; - - - // TODO montrer eof.. -} - - -void FichierBinaire() -{ - srand(time(0)); - char data[1024]; - for(int i = 0; i < sizeof(data); ++i) - data[i] = rand() % 256; - - std::ofstream sortie("fichier.bin", std::fstream::binary); - sortie.write(data, sizeof(data)); - sortie.close(); - - - // Relire le fichier et comparer... - std::ifstream entree("fichier.bin", std::fstream::binary); - - // Obtenir la taille du fichier - entree.seekg(0, std::ios_base::end); - int size = entree.tellg(); - entree.seekg(0, std::ios_base::beg); - - char* data2 = new char[size]; - entree.read(data2, size); - entree.close(); - - // Comparaison - bool pareil = true; - for(int i = 0; i < size; ++i) - { - if(data[i] != data2[i]) - { - pareil = false; - break; - } - } - - std::cout << "Les donnees sont " << (pareil ? "pareilles" : "differentes") << std::endl; - - - delete [] data2; -} - -int main() -{ - FichierTexte(); - FichierBinaire(); - -} diff --git a/SQCSim2021/media/chunks/60_66.chunk b/SQCSim2021/media/chunks/60_66.chunk new file mode 100644 index 0000000000000000000000000000000000000000..df7588ec529aff3a331af614adae8ab693f650cd GIT binary patch literal 32768 zcmZP`1*0J_8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiTJLx2g*eN1Qq zOlSg3=mKc^Y0X7*9y6Nrn9-ew?p|zsWHUkX$Yw(L2o+F1LV$pW(G?<_4bn=Cdy&n6 z*bmYP!4N(|1r9#kTBtnSTHJhynFx7^5y*Uy3NRny6fg9>9grGb)AFcu< z3BoW1AT}671;A`D0TBQ*Ap}?e!i10@0SF69G9&DRh@kVCVD5uRQ$&JnM=>8PfNUg4 z0GSU81Qb3Kihht372O9iZWIq}2rvw+^~BiD$i&2mqK*-j%Y@2j7zLvtFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? v8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3^7Vh8{LliEPS literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/60_67.chunk b/SQCSim2021/media/chunks/60_67.chunk new file mode 100644 index 0000000000000000000000000000000000000000..d047ed20c8abd8397e3e98709184856776c07907 GIT binary patch literal 32768 zcmZP`1*0J_8UmvsFd71*Aut*OqaiRF0;3@?8Un*61enl#!h|k>CO_D@=*~y?4-=XI z6Pf^sk8Z|5`Wf9VXwGLwb3TZVq6OVQU_O!x2p=JU&ZpGx2$LZuVY(k84kKygAGkB1 z{)0OM&WEZ%@F4;a66QK)W(+>uB#4?p=YE8Tzz#%kAuh$sXJW>lo{$0oq91HDn1JvR z3ZQ(r0E`b4fb*dO2tGsri4PV)=7R)K_)zyE#31fR@F`${eTQrwL;%S|umBPttexWOO} zGc(9PP!@y&>4&f&B#4h}239_j03DOT`f+-LmWGz+j0T2U*K>{!~n1;It%mcd%#)8tI z_=GYM6v!MH28+TtaPtrXV0m)<2Q>n!AM7@e5P}a0RU|%G0GSUGK;c8;4_OGS|Bw}6 zXMM3?Bc2 z+y+vE&Y@8}9xi94IL94^lpe(kI9{qj)p~MnhmU1V%$(Gz3ONU^E0qLtr!n zMnhmU1V{)01~jz{XaXQU2*Z>yFd*}om_U4FEm-+T3c&J6MnL&+6)-+b0M3UBAovgg zBtBRGA0MOuSsvsJR6Ya5KWKuZ+|dvi4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 Zfzc2c4S~@R7!85Z5Eu=C(Gb8F0sy6iFf;%F literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/61_55.chunk b/SQCSim2021/media/chunks/61_55.chunk new file mode 100644 index 0000000000000000000000000000000000000000..2e8410a02cf0b38c0b9ed58bae27a78445495d96 GIT binary patch literal 32768 zcmZP?1*0J_8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFf2oWfdS21=zKKkVZ&vB0ho`_`Akd@5tuv^Q~-$& zR)Ne1383(q24DC>e1)5YdK0by=5Lq)$bT?4hz9XN{syr@7|cf!fbbClP(EA$#)k>O z`A`7_AL24(K1c})pNQ}Vxp63AkROrV3kd~;2q=CS5nOQoMdE__=w=|x4+l1~|3Usi z=YzyX5=QqwBf7vy3XD;|j)uT!2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk oz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2+%A90EzcL%K!iX literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/61_56.chunk b/SQCSim2021/media/chunks/61_56.chunk new file mode 100644 index 0000000..dae3115 --- /dev/null +++ b/SQCSim2021/media/chunks/61_56.chunk @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SQCSim2021/media/chunks/61_68.chunk b/SQCSim2021/media/chunks/61_68.chunk new file mode 100644 index 0000000000000000000000000000000000000000..e64f750ed9669173733bcc9065630ea308de4072 GIT binary patch literal 32768 zcmZP`1*0J_8UmvsFib;$3C&;Vd^G7H&qeni6Pf@My1)?gF`9Rn(Y=H2KPEH*5Fg!) zfeZq4w_xzm1kk+04Dt`M`$2qUEnq&90ECYufUKDYY;>D2;|tYNYWolBU$`@1e7FFr z^(6Dq&B62^stS<($d-Wk$SSb%kraUCkt~7o;VNK!m;js)6+rNz0?3YGW@bhg#o(g} z&^x~1?uWV?&WE}S!G{PS@xcPfe2@TAP=ZaQj(@;LfeEO6U^a+=@eBuD_lf|8*4gEAo$vUy+;B=eE@AcLS7A`0ce%|quy9S4_3gd$i! zh=6JVF(DWt0AYhkumG3^B|rjDCWJyVA0_~yVI)ES!4wjrK~{q?Od*(qY(G>0CJ*y5 zf)5E3BtBRGnGX^`;WJUq{iw#0#{>HiSu02YAAgYh2ifUFvIkXs5b5SoWuqZ58Umvs zFd71*Aut*Oq=o>)C>RZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 Sfzc2c4S~@R7!3guLjVAy6FB$) literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/64_72.chunk b/SQCSim2021/media/chunks/64_72.chunk new file mode 100644 index 0000000000000000000000000000000000000000..f7c3a222697b2e52be30cf8cd0d182b45de043e7 GIT binary patch literal 32768 zcmZP`Vt@(Fy-a8Vn0!H|cP_g7L40I0z|bi=WDcAScP&gmLIA1;E&%0&tOkqW;=>fc{Yj`2!+=q!cWG#HWUTs1<+6&LW!)@*uKibUw(#$nu~FMCDU0J)#*) zFD@+q!|fYX@dJ0&C}T7PMnhmU1V%$(Gz3ONU^E0qLtr!nXd42I#2U}QfT|LckE(!y z0aXQvkE{aBM-qVW5dt{)a0O6#xFv8tR0V>Mm&J%zcKAz1NO3@32V+OiT~~1Ro-R#0M)u z;Sb92gZKkRGJ#zU<3ZvZ!GrLTl|cOmR|4fj0)xWv0~rc44?@H2hwwmd1+f@G1QJG1 zl=%1{J4nHBk3lsdhXqIo>Y@}Y)+b<&4Gw-MwfWSgPRh6{n+3+KV&A0YseN7e)7!>xhwVFGYI zOaNijkYJ%Zo2>8~55Fc3ygpbez<-?W0`A{VYK12YC57vXiXJTMLC>C;)R=SXf{pFg{EK!H0+-^Fbo0{88R$2#kinXb6mkz-S1JhQMeDjE2By z2n?G8RafrB+R?ZytKdnM`)ZEb!7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c x4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4FP;1001zpE7AY} literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/86_31.chunk b/SQCSim2021/media/chunks/86_31.chunk new file mode 100644 index 0000000000000000000000000000000000000000..6b2f6b797fbf62362c20d79ed46d8e6ab99b8972 GIT binary patch literal 32768 zcmZP?T7VJNxs0fMMpQl{Dj&o}R*%j{HF|LJkloM3#DwZ!CRG1|xX9|!{fo{YoIXZ% z6|#Ru{XZK2sOe!e{iB2jD1#$q9}pK=9-WV*bkH)9-9MWDNAo{wdKk_Bj4Vi57nH$S zSXf{}ATA?_4;2FQk(3Vz6XrOWqu3FdyN5F>&Q@)RQ~ALK!ZelQ8* zBC7}UL3U7r85mG?Gk^e+5QxiwqzKA~3nBOrArwAcI7p6VVqyYYi6jK(4{G;AT}TZI z=6{4)knlk8hdYaLxO;Haf1@EV8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O zqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? q8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*Oqai?Q2mk<5W)}7U literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/88_31.chunk b/SQCSim2021/media/chunks/88_31.chunk new file mode 100644 index 0000000000000000000000000000000000000000..fad70c682f5f21fb085b71daedecb570ad9ddcc7 GIT binary patch literal 32768 zcmZP?+<+0yd1!n_R6ZjrpAnT0;v%UBbCLLHHVqCgy8F=hsQzU_^)HBvtRC!Pgtx$4 zWO;ijenH%0ZQRW;RE6#$%DB_d?b~Fhl%b!H2!G%M~SM@^pBE0 zKq(w4d_Y_zc`z4=kEC+&FwxzI#ve`pC{Z;6(?1Jx05CE#valdTKq;IB48V#&T#!6i zgazC>LQ6kjW%MN&7*OqFU_cRJ1o4rCV0@?$BN88~l0*vCcG7t$u4Q6k0$Yz{4499k z2+D`LAF3WE2-6Sa(}hNIEYyBv5vUX3LQwu7azDaFl(ImcL^A^tpJ;-k+|dvi4S~@R z7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R S7!85Z5Eu=C(GVC(Apigp?H9WM literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/89_29.chunk b/SQCSim2021/media/chunks/89_29.chunk new file mode 100644 index 0000000000000000000000000000000000000000..eafb86754f65b41f451e93f5e03a46fc149dade2 GIT binary patch literal 32768 zcmZR=4;WFU8BzI+sC-6LK8TB?9?V7XAzU~g%7yV^TqqyTh42wvFdvBv;v;hznV3+x zSoo+uMB{O?uaiM%T7s5wy!F(hxh>y(0 z;$IYLka~m@FIi-<|6nIE}ReL!uT*Qln>`Z_y{hTkHiJ>k-4M!e>DFSNDoLU z7Ly4|Pe`Jp?cg8oO&E+7YjEQjg_aUt;q_B5Ca zAEO7tBm5nk+Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ON zU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU z1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qb_f6f DVZtfM literal 0 HcmV?d00001 diff --git a/SQCSim2021/media/chunks/89_31.chunk b/SQCSim2021/media/chunks/89_31.chunk new file mode 100644 index 0000000000000000000000000000000000000000..369b6e8ec1af8d9f164b8cad38db88df0b7dcece GIT binary patch literal 32768 zcmZP?T!0bHIcR)FR6ZjrpAkPFB#opW%thj(**q{@boZd~QT@w=-@hPfWc^?dBfJIX zBFiJB29Aa99yI=_|52i5H2zW22Pj1&hYuPb#6?mM<|6Ttbq*LC-92dh(e#fJGo$Gr zC4GQWG;;W$@j+Z9^^00v+Wfw+udE{FiDMl%nrjJ^cIwP1U}?gO(R z1elNT5+jrk^(7+`pMik^ +#include class Chunk;