Test monde infini

This commit is contained in:
MarcEricMartel 2021-12-02 18:12:35 -05:00
parent 2ad6b7e2c6
commit 033f69465c
159 changed files with 332 additions and 327 deletions

View File

@ -22,7 +22,6 @@ Chunk::~Chunk() {
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();
@ -31,36 +30,36 @@ 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);
CheckNeighbors(x, z, world);
m_isDirty = true;
}
BlockType Chunk::GetBlock(int x, int y, int z) { return m_blocks.Get(x, y, z); }
void Chunk::CheckNeighbors(int x, int z, World* world) {
if (x == 0 && m_posX >= 0 &&
world->ChunkAt((m_posX - 1) * CHUNK_SIZE_X, 1, m_posY * CHUNK_SIZE_Z))
world->ChunkAt((m_posX - 1) * CHUNK_SIZE_X, 1, m_posY * CHUNK_SIZE_Z)->MakeDirty();
else if (x == CHUNK_SIZE_X - 1 && m_posX < WORLD_SIZE_X &&
world->ChunkAt((m_posX + 1) * CHUNK_SIZE_X, 1, m_posY * CHUNK_SIZE_Z))
world->ChunkAt((m_posX + 1) * CHUNK_SIZE_X, 1, m_posY * CHUNK_SIZE_Z)->MakeDirty();
int cx, cy;
if (z == 0 && m_posY >= 0 &&
world->ChunkAt(m_posX * CHUNK_SIZE_X, 1, (m_posY - 1) * CHUNK_SIZE_Z))
world->ChunkAt(m_posX * CHUNK_SIZE_X, 1, (m_posY - 1) * CHUNK_SIZE_Z)->MakeDirty();
else if (z == CHUNK_SIZE_X - 1 && m_posY < WORLD_SIZE_Y &&
world->ChunkAt(m_posX * CHUNK_SIZE_X, 1, (m_posY + 1) * CHUNK_SIZE_Z))
world->ChunkAt(m_posX * CHUNK_SIZE_X, 1, (m_posY + 1) * CHUNK_SIZE_Z)->MakeDirty();
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(int& x, int& y) const {
@ -103,7 +102,11 @@ void Chunk::Update(BlockInfo* blockinfo[BTYPE_LAST], World* world) {
void Chunk::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt,
int x, int y, int z, float u, float v, float s, World* world) {
int cx = x + m_posX * CHUNK_SIZE_X, cy = z + m_posY * CHUNK_SIZE_Z;
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);

View File

@ -23,7 +23,6 @@ void Engine::Init() {
glEnable(GL_DEPTH_TEST);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_CULL_FACE);
@ -32,26 +31,11 @@ void Engine::Init() {
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 };
GLfloat light0Diff[4] = { 1.f, 1.f, 1.f, 1.f };
GLfloat light0Spec[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0Amb);
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);
@ -64,7 +48,6 @@ void Engine::Init() {
void Engine::DeInit() { }
void Engine::LoadResource() {
LoadTexture(m_textureFloor, TEXTURE_PATH "grass.png");
LoadTexture(m_skybox.GetTexture(), TEXTURE_PATH "skybox.png");
LoadTexture(m_textureCrosshair, TEXTURE_PATH "cross.bmp");
LoadTexture(m_textureFont, TEXTURE_PATH "font.bmp");
@ -104,10 +87,8 @@ void Engine::UnloadResource() {}
void Engine::DrawHud(float elapsedTime) {
// Setter le blend function , tout ce qui sera noir sera transparent
glDisable(GL_LIGHTING);
glColor4f(1.f, 1.f, 1.f, 1.f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
//glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@ -154,9 +135,6 @@ void Engine::DrawHud(float elapsedTime) {
glTexCoord2f(0, 1);
glVertex2i(0, crossSize);
glEnd();
glEnable(GL_LIGHTING);
//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);
@ -210,105 +188,15 @@ 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);
if (m_isSkybox) m_skybox.Render(skybox);
glEnable(GL_LIGHT0);
if (m_mouseL)
ChangeBlockAtCursor(BTYPE_DIRT);
m_world.ChangeBlockAtCursor(BTYPE_DIRT, m_player, m_block);
else if (m_mouseR)
ChangeBlockAtCursor(BTYPE_AIR);
m_world.ChangeBlockAtCursor(BTYPE_AIR, m_player, m_block);
// 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;
if (frameGenerate > 0) --frameGenerate;
if (frameUpdate > 0) --frameUpdate;
if (!frameGenerate || !frameUpdate)
while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) {
int tx = -side, ty = -side;
for (; tx <= side; ++tx)
UpdateWorld(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z);
for (; ty <= side; ++ty)
UpdateWorld(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z);
for (; tx >= -side; --tx)
UpdateWorld(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z);
for (; ty >= -side; --ty)
UpdateWorld(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z);
++side;
}
// 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();
pos.y = 1;
m_renderManifest.clear();
for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
// Configuration du radar.
angle.x = direct.z + direct.x;
angle.y = 0;
angle.z = direct.z - direct.x;
angle.Normalize();
float sinus = .01745240643; // sin(1 degré)
float cosinus = .99984769515; // cos(1 degré)
int echantillons = 90;
for (int radar = 0; radar < echantillons; ++radar) {
float x = angle.x;
float z = angle.z;
angle.x = x * cosinus - z * sinus;
angle.z = z * cosinus + x * sinus;
angle.Normalize();
cursor = pos - direct * CHUNK_SIZE_X * 2 + angle * dist;
if (cursor.y >= 128.f || cursor.y >= 0.f) cursor.y = 1;
bool valide = true;
if (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;
}
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;
}
}
}
}
m_shader01.Disable();
m_world.Update(m_renderCount, m_badHitCount, m_player, all, m_shader01, m_textureAtlas, m_perlin, m_blockinfo);
if (m_wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@ -320,10 +208,10 @@ void Engine::Render(float elapsedTime) {
m_player = Player(Vector3f(0, CHUNK_SIZE_Y + 1.8f, 0)); // Respawn si le bonho- joueur tombe en bas du monde.
}
void Engine::KeyPressEvent(unsigned char key)
{
void Engine::KeyPressEvent(unsigned char key) {
switch (key) {
case 36: // ESC
m_world.CleanUpWorld(m_renderCount, true);
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))
@ -380,8 +268,7 @@ void Engine::KeyPressEvent(unsigned char key)
}
}
void Engine::KeyReleaseEvent(unsigned char key)
{
void Engine::KeyReleaseEvent(unsigned char key) {
switch (key) {
case 12:
m_audio.ToggleMusicState();
@ -422,8 +309,7 @@ void Engine::KeyReleaseEvent(unsigned char key)
}
}
void Engine::MouseMoveEvent(int x, int y)
{
void Engine::MouseMoveEvent(int x, int y) {
m_player.TurnLeftRight(x - (Width() / 2));
m_player.TurnTopBottom(y - (Height() / 2));
@ -482,8 +368,7 @@ void Engine::MouseReleaseEvent(const MOUSE_BUTTON& button, int x, int y) {
}
}
bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool stopOnError)
{
bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool stopOnError) {
texture.Load(filename);
if (!texture.IsValid())
{
@ -496,153 +381,3 @@ bool Engine::LoadTexture(Texture& texture, const std::string& filename, bool sto
return true;
}
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)) {
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;
}
void Engine::UpdateWorld(int& generates, int& updates, int chx, int chy) {
if (generates == 0 && GenerateChunk(chx, chy)) generates = FRAMES_RENDER_CHUNKS;
if (updates == 0 && m_world.ChunkAt(chx, 1, chy) &&
m_world.ChunkAt(chx, 1, chy)->IsDirty()) {
m_world.ChunkAt(chx, 1, chy)->Update(m_blockinfo, &m_world);
updates = FRAMES_UPDATE_CHUNKS;
}
}
void Engine::ChangeBlockAtCursor(BlockType blockType) {
Vector3f currentPos = m_player.GetPosition();
Vector3f currentBlock = currentPos;
Vector3f ray = m_player.GetDirection();
bool found = false;
if (m_block) return;
while ((currentPos - currentBlock).Length() <= MAX_SELECTION_DISTANCE && !found) {
currentBlock += ray / 10.f;
BlockType bt = m_world.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 = m_world.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;
m_world.ChunkAt(currentBlock)->SetBlock(bx, by, bz, blockType, &m_world);
m_world.ChunkAt(currentBlock)->MakeModified();
m_block = true;
}
}

View File

@ -35,31 +35,25 @@ private:
void DrawHud(float elapsedTime);
void PrintText(unsigned int x, unsigned int y, const std::string& t);
int GetFps(float elapsedTime) const;
bool GenerateChunk(int chx, int chy);
void UpdateWorld(int& generates, int& updates, int chx, int chy);
void ChangeBlockAtCursor(BlockType blocktype);
bool m_wireframe = false;
bool m_isSkybox = true;
int m_renderCount = 0;
int m_badHitCount = 0;
std::vector<Vector3i> m_renderManifest;
Shader m_shader01;
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;
World m_world = World();
Perlin m_perlin = Perlin(3,7.f,127.f,12345);
Texture m_textureSkybox;
Texture m_textureFont;
Texture m_textureCrosshair;
Texture m_textureCube1;
Skybox m_skybox;
Shader m_shader01;
Audio m_audio = Audio(AUDIO_PATH "music01.wav");
Player m_player = Player(Vector3f(0, CHUNK_SIZE_Y + 1.8f, 0));

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More