Indépendance!
This commit is contained in:
parent
ace555a93e
commit
033365c961
@ -138,6 +138,7 @@
|
||||
<ClInclude Include="opensimplex.h" />
|
||||
<ClInclude Include="player.h" />
|
||||
<ClInclude Include="netprotocol.h" />
|
||||
<ClInclude Include="transformation.h" />
|
||||
<ClInclude Include="vector3.h" />
|
||||
<ClInclude Include="world.h" />
|
||||
</ItemGroup>
|
||||
@ -148,6 +149,7 @@
|
||||
<ClCompile Include="netprotocol.cpp" />
|
||||
<ClCompile Include="opensimplex.cpp" />
|
||||
<ClCompile Include="player.cpp" />
|
||||
<ClCompile Include="transformation.cpp" />
|
||||
<ClCompile Include="world.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -51,6 +51,9 @@
|
||||
<ClInclude Include="netprotocol.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transformation.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="world.cpp">
|
||||
@ -74,5 +77,8 @@
|
||||
<ClCompile Include="netprotocol.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transformation.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -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; }
|
||||
|
||||
|
@ -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<BlockType> m_blocks = Array3d<BlockType>(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();
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,33 +1,43 @@
|
||||
#ifndef _PLAYER_H__
|
||||
#define _PLAYER_H__
|
||||
#include "vector3.h"
|
||||
#ifndef CLI_PLAYER_H__
|
||||
#define CLI_PLAYER_H__
|
||||
#include <cmath>
|
||||
#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__
|
||||
|
@ -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
|
||||
{
|
@ -2,9 +2,9 @@
|
||||
#define TRANSFORMATION_H__
|
||||
|
||||
#include <stack>
|
||||
#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;
|
||||
|
@ -6,6 +6,10 @@ World::~World() {}
|
||||
|
||||
Array2d<Chunk*>& 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<Chunk*> genThList[THREADS_GENERATE_CHUNKS];
|
||||
//std::future<void> 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(); }
|
@ -6,14 +6,12 @@
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#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<Chunk*>& 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<Chunk*> m_chunks = Array2d<Chunk*>(WORLD_SIZE_X, WORLD_SIZE_Y);
|
||||
std::vector<Chunk*> 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__
|
||||
|
||||
|
@ -20,37 +20,33 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="audio.h" />
|
||||
<ClInclude Include="chunk.h" />
|
||||
<ClInclude Include="connector.h" />
|
||||
<ClInclude Include="define.h" />
|
||||
<ClInclude Include="engine.h" />
|
||||
<ClInclude Include="mesh.h" />
|
||||
<ClInclude Include="openglcontext.h" />
|
||||
<ClInclude Include="player.h" />
|
||||
<ClInclude Include="shader.h" />
|
||||
<ClInclude Include="skybox.h" />
|
||||
<ClInclude Include="texture.h" />
|
||||
<ClInclude Include="textureatlas.h" />
|
||||
<ClInclude Include="tool.h" />
|
||||
<ClInclude Include="transformation.h" />
|
||||
<ClInclude Include="vertexbuffer.h" />
|
||||
<ClInclude Include="world.h" />
|
||||
<ClInclude Include="worldrenderer.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="audio.cpp" />
|
||||
<ClCompile Include="chunk.cpp" />
|
||||
<ClCompile Include="connector.cpp" />
|
||||
<ClCompile Include="engine.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="mesh.cpp" />
|
||||
<ClCompile Include="openglcontext.cpp" />
|
||||
<ClCompile Include="player.cpp" />
|
||||
<ClCompile Include="shader.cpp" />
|
||||
<ClCompile Include="skybox.cpp" />
|
||||
<ClCompile Include="texture.cpp" />
|
||||
<ClCompile Include="textureatlas.cpp" />
|
||||
<ClCompile Include="tool.cpp" />
|
||||
<ClCompile Include="transformation.cpp" />
|
||||
<ClCompile Include="vertexbuffer.cpp" />
|
||||
<ClCompile Include="world.cpp" />
|
||||
<ClCompile Include="worldrenderer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SQCSim-common\SQCSim-common.vcxproj">
|
||||
|
@ -11,9 +11,6 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="chunk.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="define.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
@ -23,12 +20,6 @@
|
||||
<ClInclude Include="texture.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transformation.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="player.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shader.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
@ -44,9 +35,6 @@
|
||||
<ClInclude Include="textureatlas.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="world.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="connector.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
@ -56,11 +44,14 @@
|
||||
<ClInclude Include="tool.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mesh.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="worldrenderer.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="chunk.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="engine.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
@ -73,12 +64,6 @@
|
||||
<ClCompile Include="texture.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transformation.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="player.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shader.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
@ -94,14 +79,17 @@
|
||||
<ClCompile Include="textureatlas.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="world.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="connector.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tool.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mesh.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="worldrenderer.cpp">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include <irrKlang.h>
|
||||
#include <ik_ISoundSource.h>
|
||||
#include "define.h"
|
||||
#include "../SQCSim-common/vector3.h"
|
||||
#include "define.h"
|
||||
|
||||
class Audio {
|
||||
private:
|
||||
|
@ -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; }
|
||||
|
@ -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<BlockType> m_blocks = Array3d<BlockType>(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__
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
120
SQCSim2021/mesh.cpp
Normal file
120
SQCSim2021/mesh.cpp
Normal file
@ -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;
|
||||
}
|
32
SQCSim2021/mesh.h
Normal file
32
SQCSim2021/mesh.h
Normal file
@ -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
|
@ -1,10 +1,9 @@
|
||||
#ifndef OPENGLCONTEXT_H__
|
||||
#define OPENGLCONTEXT_H__
|
||||
|
||||
#include "define.h"
|
||||
|
||||
#include <string>
|
||||
#include <SFML/Window.hpp>
|
||||
#include "define.h"
|
||||
|
||||
// Documentation de SFML: http://www.sfml-dev.org/documentation/index-fr.php
|
||||
class OpenglContext
|
||||
|
@ -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;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
#ifndef CLI_PLAYER_H__
|
||||
#define CLI_PLAYER_H__
|
||||
#include "../SQCSim-common/vector3.h"
|
||||
#include "transformation.h"
|
||||
#include "audio.h"
|
||||
#include <cmath>
|
||||
|
||||
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__
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef TEXTURE_H__
|
||||
#define TEXTURE_H__
|
||||
|
||||
#include "define.h"
|
||||
#include <IL/il.h>
|
||||
#include <string>
|
||||
#include <IL/il.h>
|
||||
#include "define.h"
|
||||
|
||||
class Texture
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef TEXTUREATLAS_H__
|
||||
#define TEXTUREATLAS_H__
|
||||
#include "define.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <IL/ilu.h>
|
||||
#include "define.h"
|
||||
|
||||
class TextureAtlas
|
||||
{
|
||||
|
@ -1,506 +0,0 @@
|
||||
#include "world.h"
|
||||
|
||||
World::World() {}
|
||||
|
||||
World::~World() {}
|
||||
|
||||
Array2d<Chunk*>& 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<unsigned int> 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<unsigned int>(chx,
|
||||
(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) < 0.f? 0:
|
||||
(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) * 1000,
|
||||
chy);
|
||||
}
|
||||
}
|
||||
}
|
||||
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<Chunk*> genThList[THREADS_GENERATE_CHUNKS];
|
||||
std::future<Chunk*> updateThList[THREADS_UPDATE_CHUNKS];
|
||||
std::future<void> 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(); }
|
@ -1,59 +0,0 @@
|
||||
#ifndef WORLD_H__
|
||||
#define WORLD_H__
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#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<Chunk*>& 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<Chunk*> m_chunks = Array2d<Chunk*>(WORLD_SIZE_X, WORLD_SIZE_Y);
|
||||
std::vector<Chunk*> 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__
|
||||
|
213
SQCSim2021/worldrenderer.cpp
Normal file
213
SQCSim2021/worldrenderer.cpp
Normal file
@ -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<unsigned int> 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<unsigned int>(chx,
|
||||
(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) < 0.f ? 0 :
|
||||
(VIEW_DISTANCE - (pos - cursor).Length() * 3.f + 256.f) * 1000,
|
||||
chy);
|
||||
}
|
||||
}
|
||||
}
|
||||
shader.Use();
|
||||
atlas.Bind();
|
||||
glStencilFunc(GL_EQUAL, 1, 0x00);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
unsigned int sx, sy, cx, cy;
|
||||
origin->GetScope(sx,sy);
|
||||
|
||||
for (int index = 0; index < rendercount; ++index) {
|
||||
int chx = (renderManifest[index].x - sx) * CHUNK_SIZE_X, chy = (renderManifest[index].z - sy) * CHUNK_SIZE_Z;
|
||||
|
||||
world.ApplyTranslation(chx, 0, chy);
|
||||
glLoadMatrixf(world.GetMatrix().GetInternalValues());
|
||||
float blcolor = renderManifest[index].y / (VIEW_DISTANCE / 50.f);
|
||||
glBlendColor(blcolor, blcolor, blcolor, 1.f);
|
||||
origin->ChunkAt(chx, 1, chy)->GetPosition(cx,cy);
|
||||
if (m_meshes.Get(cx - sx, cy - sy))
|
||||
m_meshes.Get(cx - sx, cy -sy)->Render();
|
||||
world.ApplyTranslation(-chx, 0, -chy);
|
||||
}
|
||||
shader.Disable();
|
||||
glStencilFunc(GL_GREATER, 1, 0xFF);
|
||||
};
|
||||
|
||||
void 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<Mesh*> updateThList[THREADS_UPDATE_CHUNKS];
|
||||
|
||||
unsigned int mx = 0 , my = 0, sx, sy;
|
||||
|
||||
origin->GetScope(sx, sy);
|
||||
|
||||
if (frameUpdate > 0) --frameUpdate;
|
||||
|
||||
if (!frameUpdate)
|
||||
while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) {
|
||||
int tx = -side, ty = -side;
|
||||
|
||||
for (; tx <= side; ++tx) {
|
||||
if (frameUpdate)
|
||||
break;
|
||||
unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
|
||||
if (origin->ChunkAt(chx, 1, chy) &&
|
||||
origin->ChunkAt(chx, 1, chy)->IsDirty()) {
|
||||
origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
|
||||
if (m_meshes.Get(mx - sx, my - sy))
|
||||
updateThList[threads++] =
|
||||
std::async(std::launch::async,
|
||||
[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
|
||||
mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
|
||||
else updateThList[threads++] = std::async(std::launch::async,
|
||||
[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
|
||||
if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
|
||||
}
|
||||
}
|
||||
for (; ty <= side; ++ty) {
|
||||
if (frameUpdate)
|
||||
break;
|
||||
unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
|
||||
if (origin->ChunkAt(chx, 1, chy) &&
|
||||
origin->ChunkAt(chx, 1, chy)->IsDirty()) {
|
||||
origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
|
||||
if (m_meshes.Get(mx - sx, my - sy))
|
||||
updateThList[threads++] =
|
||||
std::async(std::launch::async,
|
||||
[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
|
||||
mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
|
||||
else updateThList[threads++] = std::async(std::launch::async,
|
||||
[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
|
||||
if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
|
||||
}
|
||||
}
|
||||
for (; tx >= -side; --tx) {
|
||||
if (frameUpdate)
|
||||
break;
|
||||
unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
|
||||
if (origin->ChunkAt(chx, 1, chy) &&
|
||||
origin->ChunkAt(chx, 1, chy)->IsDirty()) {
|
||||
origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
|
||||
if (m_meshes.Get(mx - sx, my - sy))
|
||||
updateThList[threads++] =
|
||||
std::async(std::launch::async,
|
||||
[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
|
||||
mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
|
||||
else updateThList[threads++] = std::async(std::launch::async,
|
||||
[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
|
||||
if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
|
||||
}
|
||||
}
|
||||
for (; ty >= -side; --ty) {
|
||||
if (frameUpdate)
|
||||
break;
|
||||
unsigned int chx = cx + tx * CHUNK_SIZE_X, chy = cy + ty * CHUNK_SIZE_Z;
|
||||
if (origin->ChunkAt(chx, 1, chy) &&
|
||||
origin->ChunkAt(chx, 1, chy)->IsDirty()) {
|
||||
origin->ChunkAt(chx, 1, chy)->GetPosition(mx, my);
|
||||
if (m_meshes.Get(mx - sx, my - sy))
|
||||
updateThList[threads++] =
|
||||
std::async(std::launch::async,
|
||||
[](Mesh* mesh, BlockInfo* blockinfo[BTYPE_LAST], World* world) {
|
||||
mesh->Update(blockinfo, world); return mesh; }, m_meshes.Get(mx - sx, my - sy), blockinfo, origin);
|
||||
else updateThList[threads++] = std::async(std::launch::async,
|
||||
[](Chunk* chunk) { return new Mesh(chunk); }, origin->ChunkAt(chx, 1, chy));
|
||||
if (threads == THREADS_UPDATE_CHUNKS) frameUpdate = FRAMES_UPDATE_CHUNKS;
|
||||
}
|
||||
}
|
||||
if (frameUpdate)
|
||||
break;
|
||||
++side;
|
||||
}
|
||||
|
||||
if (threads > 0) {
|
||||
for (int i = 0; i < threads; ++i) {
|
||||
updateThList[i].wait();
|
||||
Mesh* mesh = updateThList[i].get();
|
||||
if (mesh->IsNew()) {
|
||||
unsigned int x, y;
|
||||
mesh->GetPosition(x, y, origin);
|
||||
m_meshes.Set(x, y, mesh);
|
||||
}
|
||||
mesh->FlushMeshToVBO();
|
||||
}
|
||||
}
|
||||
}
|
23
SQCSim2021/worldrenderer.h
Normal file
23
SQCSim2021/worldrenderer.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef WORLDRENDERER_H__
|
||||
#define WORLDRENDERER_H__
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#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<Mesh*> m_meshes = Array2d<Mesh*>(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
|
Loading…
Reference in New Issue
Block a user