Compare commits

..

10 Commits

Author SHA1 Message Date
MarcEricMartel
5c30cdf26d ++Performance; 2022-04-06 23:07:24 -04:00
MarcEricMartel
16a67035d0 Changements pour v143 et autres corrections. 2022-04-02 15:26:55 -04:00
MarcEricMartel
a226d95923 ! 2021-12-18 15:36:21 -05:00
MarcEricMartel
ae8f87b047 Ajustements dans renderer. 2021-12-18 15:34:47 -05:00
MarcEricMartel
5f50f5f87e Monde de max de UINT_MAX * UINT_MAX 2021-12-18 15:24:57 -05:00
MarcEricMartel
5dc05167de Le DeleteChunk est maintenant en multi-thread et peux enfin keep up avec le reste! 2021-12-15 21:00:06 -05:00
MarcEricMartel
2ec9170fe3 Corrections dans le générateur pour le MakeDirty au bout du monde 2021-12-14 17:16:14 -05:00
MarcEricMartel
cdc926bb39 Rétrécissement de la zone de trigger de tapis roulant, assemblage ur VS2022 2021-12-13 23:56:20 -05:00
MarcEricMartel
e8a9cbb96e Séparation Chunk::Update et VertexBuffer::SetMeshData, Cleanup 2021-12-13 23:24:12 -05:00
MarcEricMartel
7eb9f44d41 Génération de Chunks en multithreads 2021-12-12 23:31:38 -05:00
64 changed files with 3008 additions and 541 deletions

1
.gitignore vendored
View File

@ -367,3 +367,4 @@ FodyWeavers.xsd
/SQCSim2021/Release
/SQCSim2021/media/chunks
/x64/Release/SQCSim2021.exe
/SQCSim2021/x64/Release/SQCSim2021.tlog

View File

@ -29,7 +29,7 @@
<ClInclude Include="engine.h" />
<ClInclude Include="matrix4.h" />
<ClInclude Include="openglcontext.h" />
<ClInclude Include="perlin.h" />
<ClInclude Include="opensimplex.h" />
<ClInclude Include="player.h" />
<ClInclude Include="shader.h" />
<ClInclude Include="skybox.h" />
@ -49,7 +49,7 @@
<ClCompile Include="engine.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="openglcontext.cpp" />
<ClCompile Include="perlin.cpp" />
<ClCompile Include="opensimplex.cpp" />
<ClCompile Include="player.cpp" />
<ClCompile Include="shader.cpp" />
<ClCompile Include="skybox.cpp" />
@ -72,13 +72,13 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@ -117,8 +117,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)\external\irrKlang-1.6.0\include$(MSBuildProjectDirectory)$(MSBuildProjectDirectory);external\devil178\include;external\sfml23\include;$(IncludePath)</IncludePath>
<LibraryPath>external\devil178\lib;external\sfml23\lib;$(LibraryPath);D:\Repos\SQCSim2021\SQCSim2021\external\irrKlang-1.6.0\lib\Win32-visualStudio</LibraryPath>
<IncludePath>external\irrKlang-64bit-1.6.0\include;external\devil180\include;external\sfml251\include;external\glew210\include;$(IncludePath)</IncludePath>
<LibraryPath>external\devil180\lib\x64\Release;external\glew210\lib\Release\x64;external\sfml251\lib;$(LibraryPath);external\irrKlang-64bit-1.6.0\lib\Winx64-visualStudio</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>

View File

@ -68,10 +68,10 @@
<ClInclude Include="world.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="perlin.h">
<ClInclude Include="bullet.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="bullet.h">
<ClInclude Include="opensimplex.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
</ItemGroup>
@ -121,10 +121,10 @@
<ClCompile Include="world.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="perlin.cpp">
<ClCompile Include="bullet.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="bullet.cpp">
<ClCompile Include="opensimplex.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
</ItemGroup>

View File

@ -1,13 +1,81 @@
#include "chunk.h"
#include "world.h"
Chunk::Chunk(int x, int y) : m_posX(x), m_posY(y) { m_blocks.Reset(BTYPE_AIR); }
Chunk::Chunk(unsigned int x, unsigned int y) : 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);
Chunk::Chunk(int x, int y, char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]) : m_posX(x), m_posY(y) {
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z)
for (int y = 0; y < CHUNK_SIZE_Y; ++y)
m_blocks.Set(x, y, z, data[x + (z * CHUNK_SIZE_X) + (y * CHUNK_SIZE_Z * CHUNK_SIZE_X)]);
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) / 1024.;
ynoiz = (double)(iz + y * CHUNK_SIZE_Z) / 1024.;
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() {
@ -36,14 +104,14 @@ void Chunk::RemoveBlock(int x, int y, int z, World* world) {
void Chunk::SetBlock(int x, int y, int z, BlockType type, World* world) {
m_blocks.Set(x, y, z, type);
CheckNeighbors(x, z, world);
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(int x, int z, World* world) {
int cx, cy;
void Chunk::CheckNeighbors(unsigned int x, unsigned int z, World* world) {
unsigned int cx, cy;
world->GetScope(cx, cy);
@ -62,36 +130,44 @@ void Chunk::CheckNeighbors(int x, int z, World* world) {
world->ChunkAt((m_posX - cx) * CHUNK_SIZE_X, 1, (m_posY - cy + 1) * CHUNK_SIZE_Z)->MakeDirty();
}
void Chunk::GetPosition(int& x, int& y) const { x = m_posX; y = m_posY; }
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);
VertexBuffer::VertexData* vd = new VertexBuffer::VertexData[maxVertexCount];
int count = 0;
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 (count > USHRT_MAX)
if (m_vcount > USHRT_MAX)
break;
BlockType bt = GetBlock(x, y, z);
if (bt != BTYPE_AIR) {
blockinfo[bt]->GetTexture(u, v, s);
AddBlockToMesh(vd, count, bt, x, y, z, u, v, s, world);
AddBlockToMesh(m_vd, m_vcount, bt, x, y, z, u, v, s, world);
}
}
}
}
if (count > USHRT_MAX) {
count = USHRT_MAX;
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_vertexBuffer.SetMeshData(vd, count);
delete[] vd;
}
m_isDirty = false;
}
@ -99,8 +175,7 @@ void Chunk::Update(BlockInfo* blockinfo[BTYPE_LAST], World* world) {
void Chunk::AddBlockToMesh(VertexBuffer::VertexData* vd, int& count, BlockType bt,
int x, int y, int z, float u, float v, float s, World* world) {
static Perlin perlin = Perlin(2, 4.f, 1.f, 362436);
int cex, cey;
unsigned int cex, cey;
world->GetScope(cex, cey);

View File

@ -5,6 +5,7 @@
#include "array2d.h"
#include "vertexbuffer.h"
#include "blockinfo.h"
#include "opensimplex.h"
class World;
@ -15,23 +16,29 @@ class Chunk {
bool m_isDirty = true;
bool m_isModified = false;
int m_posX; // Position du chunk dans l'array constituant le monde.
int m_posY;
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(int x, int y);
Chunk(int x, int y, char data[CHUNK_SIZE_X * CHUNK_SIZE_Y * CHUNK_SIZE_Z]);
Chunk(unsigned int x, unsigned int y);
~Chunk();
void RemoveBlock(int x, int y, int z, World* world);
void SetBlock(int x, int y, int z, BlockType type, World* world);
BlockType GetBlock(int x, int y, int z);
void CheckNeighbors(int x, int z, World* world);
void GetPosition(int& x, int& y) const;
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;

View File

@ -16,6 +16,7 @@
#define CHUNK_SIZE_Y 128
#define CHUNK_SIZE_Z 16
#define MAX_SELECTION_DISTANCE 5
#define SEED 12345
#ifdef _DEBUG
#define WORLD_SIZE_X 64
@ -25,19 +26,27 @@
#define FRAMES_UPDATE_CHUNKS 4
#define FRAMES_DELETE_CHUNKS 4
#define THREADS_GENERATE_CHUNKS 1
#define THREADS_UPDATE_CHUNKS 1
#define THREADS_DELETE_CHUNKS 1
#define VIEW_DISTANCE 256
#define TEXTURE_SIZE 128
#define MAX_BULLETS 64
#endif
#ifdef NDEBUG
#define WORLD_SIZE_X 128
#define WORLD_SIZE_Y 128
#define WORLD_SIZE_X 64
#define WORLD_SIZE_Y 64
#define FRAMES_RENDER_CHUNKS 1
#define FRAMES_UPDATE_CHUNKS 1
#define FRAMES_DELETE_CHUNKS 1
#define THREADS_GENERATE_CHUNKS 12
#define THREADS_UPDATE_CHUNKS 5
#define THREADS_DELETE_CHUNKS 2
#define VIEW_DISTANCE 1024
#define TEXTURE_SIZE 512
#define MAX_BULLETS 512

View File

@ -43,7 +43,7 @@ void Engine::Init() {
m_skybox.Init(0.2f);
// Objet de musique!
m_audio.ToggleMusicState();
//m_audio.ToggleMusicState();
// Array pour les balles.
for (int x = 0; x < MAX_BULLETS; ++x)
@ -120,6 +120,9 @@ void Engine::DrawHud(float elapsedTime, BlockType bloc) {
ss << " Rendered Chunks : " << m_renderCount;
PrintText(10, Height() - 35, ss.str());
ss.str("");
ss << " To-Be-Deleted Chunks : " << m_world.GettbDeleted();
PrintText(10, Height() - 45, ss.str());
ss.str("");
ss << " Velocity : " << m_player.GetVelocity(); // IMPORTANT : on utilise l operateur << pour afficher la position
PrintText(10, 10, ss.str());
ss.str("");
@ -182,17 +185,18 @@ void Engine::PrintText(unsigned int x, unsigned int y, const std::string& t) {
int Engine::GetFps(float elapsedTime) const { return 1 / elapsedTime; }
void Engine::Render(float elapsedTime) {
static float gameTime = elapsedTime;
//static float gameTime = elapsedTime;
static float pollTime = 0;
static float bulletTime = 0;
static BlockType bloc = 1;
if (elapsedTime > 0.1f) return;
gameTime += elapsedTime;
//gameTime += elapsedTime;
pollTime += elapsedTime;
Transformation all;
Transformation skybox;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Transformations initiales
@ -202,9 +206,13 @@ void Engine::Render(float elapsedTime) {
if (bulletTime > 0.f) bulletTime -= elapsedTime;
if (bulletTime < 0.f) bulletTime = 0.f;
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);
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);
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;
}
m_player.ApplyTransformation(all);
m_player.ApplyTransformation(skybox, false); // Version d'ApplyTransformation qui ne tient compte que de la rotation
@ -249,7 +257,7 @@ void Engine::Render(float elapsedTime) {
m_bullets[x] = nullptr;
}
m_world.Update(m_renderCount, m_bullets, m_player, all, m_shader01, m_textureAtlas, m_perlin, m_blockinfo);
m_world.Update(m_renderCount, m_bullets, m_player, all, m_shader01, m_textureAtlas, m_blockinfo);
if (m_isSkybox) m_skybox.Render(skybox);
@ -280,37 +288,37 @@ void Engine::KeyPressEvent(unsigned char key) {
break;
case 22: // W
if (!m_keyW) {
std::cout << "W " << std::endl;
// std::cout << "W " << std::endl;
m_keyW = true;
}
break;
case 0: // A
if (!m_keyA) {
std::cout << "A " << std::endl;
//std::cout << "A " << std::endl;
m_keyA = true;
}
break;
case 18: // S
if (!m_keyS) {
std::cout << "S " << std::endl;
//std::cout << "S " << std::endl;
m_keyS = true;
}
break;
case 3: // D
if (!m_keyD) {
std::cout << "D " << std::endl;
//std::cout << "D " << std::endl;
m_keyD = true;
}
break;
case 38: // Left Shift
if (!m_keylshift) {
std::cout << "Dash!" << std::endl;
//std::cout << "Dash!" << std::endl;
m_keylshift = true;
}
break;
case 57: // Space
if (!m_keySpace) {
std::cout << "Jump! " << std::endl;
//std::cout << "Jump! " << std::endl;
m_keySpace = true;
}
break;
@ -344,26 +352,26 @@ void Engine::KeyReleaseEvent(unsigned char key) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case 22: // W
std::cout << "rW " << std::endl;
//std::cout << "rW " << std::endl;
m_keyW = false;
break;
case 0: // A
std::cout << "rA " << std::endl;
//std::cout << "rA " << std::endl;
m_keyA = false;
break;
case 18: // S
std::cout << "rS " << std::endl;
//std::cout << "rS " << std::endl;
m_keyS = false;
break;
case 3: // D
std::cout << "rD " << std::endl;
//std::cout << "rD " << std::endl;
m_keyD = false;
break;
case 38: // Left Shift
std::cout << "rLS " << std::endl;
//std::cout << "rLS " << std::endl;
m_keylshift = false;
case 57: // Espace
std::cout << "rSpace " << std::endl;
//std::cout << "rSpace " << std::endl;
m_keySpace = false;
break;
}

View File

@ -13,7 +13,6 @@
#include "blockinfo.h"
#include "array2d.h"
#include "world.h"
#include "perlin.h"
#include "bullet.h"
class Engine : public OpenglContext {
@ -47,7 +46,6 @@ private:
TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST);
World m_world = World();
Perlin m_perlin = Perlin(8,45.f,7.f,12345);
Texture m_textureSkybox;
Texture m_textureFont;

View File

@ -4,6 +4,6 @@
int main() {
Engine engine;
engine.SetMaxFps(60);
engine.SetMaxFps(10000);
engine.Start("Syndicat Quebecois de la Construction Simulator 2021", 1920, 1080, true);
}

2542
SQCSim2021/opensimplex.cpp Normal file

File diff suppressed because it is too large Load Diff

51
SQCSim2021/opensimplex.h Normal file
View File

@ -0,0 +1,51 @@
/**
Open Simple Noise for C++
Port to C++ from https://gist.github.com/KdotJPG/b1270127455a94ac5d19
by Rickard Lundberg, 2019.
*/
#ifndef _OPENSIMPLEX_H__
#define _OPENSIMPLEX_H__
#include <cstdint>
#include <array>
namespace OpenSimplexNoise
{
class Noise
{
public:
Noise();
Noise(int64_t seed);
//2D Open Simplex Noise.
double eval(const double x, const double y) const;
//3D Open Simplex Noise.
double eval(double x, double y, double z) const;
//4D Open Simplex Noise.
double eval(double x, double y, double z, double w) const;
private:
const double m_stretch2d;
const double m_squish2d;
const double m_stretch3d;
const double m_squish3d;
const double m_stretch4d;
const double m_squish4d;
const double m_norm2d;
const double m_norm3d;
const double m_norm4d;
const long m_defaultSeed;
std::array<short, 256> m_perm;
std::array<short, 256> m_permGradIndex3d;
std::array<char, 16> m_gradients2d;
std::array<char, 72> m_gradients3d;
std::array<char, 256> m_gradients4d;
double extrapolate(int xsb, int ysb, double dx, double dy) const;
double extrapolate(int xsb, int ysb, int zsb, double dx, double dy, double dz) const;
double extrapolate(int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw) const;
};
}
#endif // _OPENSIMPLEX_H__

View File

@ -1,262 +0,0 @@
/* coherent noise function over 1, 2 or 3 dimensions */
/* (copyright Ken Perlin) */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "perlin.h"
#define B SAMPLE_SIZE
#define BM (SAMPLE_SIZE-1)
#define N 0x1000
#define NP 12 /* 2^N */
#define NM 0xfff
#define s_curve(t) ( t * t * (3.0f - 2.0f * t) )
#define lerp(t, a, b) ( a + t * (b - a) )
#define setup(i,b0,b1,r0,r1)\
t = vec[i] + N;\
b0 = ((int)t) & BM;\
b1 = (b0+1) & BM;\
r0 = t - (int)t;\
r1 = r0 - 1.0f;
float Perlin::noise1(float arg)
{
int bx0, bx1;
float rx0, rx1, sx, t, u, v, vec[1];
vec[0] = arg;
if (mStart)
{
srand(mSeed);
mStart = false;
init();
}
setup(0, bx0,bx1, rx0,rx1);
sx = s_curve(rx0);
u = rx0 * g1[ p[ bx0 ] ];
v = rx1 * g1[ p[ bx1 ] ];
return lerp(sx, u, v);
}
float Perlin::noise2(float vec[2])
{
int bx0, bx1, by0, by1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
int i, j;
if (mStart)
{
srand(mSeed);
mStart = false;
init();
}
setup(0,bx0,bx1,rx0,rx1);
setup(1,by0,by1,ry0,ry1);
i = p[bx0];
j = p[bx1];
b00 = p[i + by0];
b10 = p[j + by0];
b01 = p[i + by1];
b11 = p[j + by1];
sx = s_curve(rx0);
sy = s_curve(ry0);
#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
q = g2[b00];
u = at2(rx0,ry0);
q = g2[b10];
v = at2(rx1,ry0);
a = lerp(sx, u, v);
q = g2[b01];
u = at2(rx0,ry1);
q = g2[b11];
v = at2(rx1,ry1);
b = lerp(sx, u, v);
return lerp(sy, a, b);
}
float Perlin::noise3(float vec[3])
{
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
int i, j;
if (mStart)
{
srand(mSeed);
mStart = false;
init();
}
setup(0, bx0,bx1, rx0,rx1);
setup(1, by0,by1, ry0,ry1);
setup(2, bz0,bz1, rz0,rz1);
i = p[ bx0 ];
j = p[ bx1 ];
b00 = p[ i + by0 ];
b10 = p[ j + by0 ];
b01 = p[ i + by1 ];
b11 = p[ j + by1 ];
t = s_curve(rx0);
sy = s_curve(ry0);
sz = s_curve(rz0);
#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
a = lerp(t, u, v);
q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
b = lerp(t, u, v);
c = lerp(sy, a, b);
q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
a = lerp(t, u, v);
q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
b = lerp(t, u, v);
d = lerp(sy, a, b);
return lerp(sz, c, d);
}
void Perlin::normalize2(float v[2])
{
float s;
s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
s = 1.0f/s;
v[0] = v[0] * s;
v[1] = v[1] * s;
}
void Perlin::normalize3(float v[3])
{
float s;
s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
s = 1.0f/s;
v[0] = v[0] * s;
v[1] = v[1] * s;
v[2] = v[2] * s;
}
void Perlin::init(void)
{
int i, j, k;
for (i = 0 ; i < B ; i++)
{
p[i] = i;
g1[i] = (float)((rand() % (B + B)) - B) / B;
for (j = 0 ; j < 2 ; j++)
g2[i][j] = (float)((rand() % (B + B)) - B) / B;
normalize2(g2[i]);
for (j = 0 ; j < 3 ; j++)
g3[i][j] = (float)((rand() % (B + B)) - B) / B;
normalize3(g3[i]);
}
while (--i)
{
k = p[i];
p[i] = p[j = rand() % B];
p[j] = k;
}
for (i = 0 ; i < B + 2 ; i++)
{
p[B + i] = p[i];
g1[B + i] = g1[i];
for (j = 0 ; j < 2 ; j++)
g2[B + i][j] = g2[i][j];
for (j = 0 ; j < 3 ; j++)
g3[B + i][j] = g3[i][j];
}
}
float Perlin::perlin_noise_2D(float vec[2])
{
int terms = mOctaves;
//float freq = mFrequency;
float result = 0.0f;
float amp = mAmplitude;
vec[0]*=mFrequency;
vec[1]*=mFrequency;
for( int i=0; i<terms; i++ )
{
result += noise2(vec)*amp;
vec[0] *= 2.0f;
vec[1] *= 2.0f;
amp*=0.5f;
}
return result;
}
float Perlin::perlin_noise_3D(float vec[3])
{
int terms = mOctaves;
//float freq = mFrequency;
float result = 0.0f;
float amp = mAmplitude;
vec[0]*=mFrequency;
vec[1]*=mFrequency;
vec[2]*=mFrequency;
for( int i=0; i<terms; i++ )
{
result += noise3(vec)*amp;
vec[0] *= 2.0f;
vec[1] *= 2.0f;
vec[2] *= 2.0f;
amp*=0.5f;
}
return result;
}
Perlin::Perlin(int octaves,float freq,float amp,int seed)
{
mOctaves = octaves;
mFrequency = freq;
mAmplitude = amp;
mSeed = seed;
mStart = true;
}

View File

@ -1,60 +0,0 @@
//http://www.flipcode.com/archives/Perlin_Noise_Class.shtml
#ifndef PERLIN_H_
#define PERLIN_H_
#include <stdlib.h>
#define SAMPLE_SIZE 1024
class Perlin
{
public:
Perlin(int octaves,float freq,float amp,int seed);
float Get(float x,float y)
{
float vec[2];
vec[0] = x;
vec[1] = y;
return perlin_noise_2D(vec);
};
float Get(float x,float y, float z)
{
float vec[3];
vec[0] = x;
vec[1] = y;
vec[2] = z;
return perlin_noise_3D(vec);
};
private:
void init_perlin(int n,float p);
float perlin_noise_2D(float vec[2]);
float perlin_noise_3D(float vec[3]);
float noise1(float arg);
float noise2(float vec[2]);
float noise3(float vec[3]);
void normalize2(float v[2]);
void normalize3(float v[3]);
void init(void);
int mOctaves;
float mFrequency;
float mAmplitude;
int mSeed;
int p[SAMPLE_SIZE + SAMPLE_SIZE + 2];
float g3[SAMPLE_SIZE + SAMPLE_SIZE + 2][3];
float g2[SAMPLE_SIZE + SAMPLE_SIZE + 2][2];
float g1[SAMPLE_SIZE + SAMPLE_SIZE + 2];
bool mStart;
};
#endif

View File

@ -64,25 +64,25 @@ Vector3f Player::GetInput(bool front, bool back, bool left, bool right, bool jum
return delta;
}
void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime, Audio* audio) {
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);
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);
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);
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) {
@ -100,17 +100,17 @@ void Player::ApplyPhysics(Vector3f input, World world, float elapsedTime, Audio*
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);
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) {
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);
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) {
input.z = m_velocity.z = 0;
m_velocity.x *= .5f;

View File

@ -13,7 +13,7 @@ public:
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 ApplyPhysics(Vector3f input, World* world, float elapsedTime, Audio* audio);
void ApplyTransformation(Transformation& transformation, bool rel = true) const;
Vector3f GetPosition() const;

View File

@ -20,7 +20,7 @@ void VertexBuffer::SetMeshData(VertexData* vd, int vertexCount) {
assert(vertexCount <= USHRT_MAX);
if(vertexCount == 0)
return;
if(!m_isValid) {
glGenBuffers(1, &m_vertexVboId);
glGenBuffers(1, &m_indexVboId);
@ -74,3 +74,10 @@ int VertexBuffer::Count() const {
return m_vertexCount;
}
void VertexBuffer::Flush() {
if (m_isValid) {
glDeleteBuffers(1, &m_vertexVboId);
glDeleteBuffers(1, &m_indexVboId);
}
m_isValid = false;
}

View File

@ -2,6 +2,7 @@
#define VERTEXBUFFER_H__
#include "define.h"
#include <mutex>
class VertexBuffer
{
@ -30,9 +31,12 @@ class VertexBuffer
int Count() const;
void Flush();
private:
// static std::mutex m_opgl;
bool m_isValid;
int m_vertexCount;
GLuint m_vertexVboId;

View File

@ -41,44 +41,56 @@ BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const
void World::TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]) {
int x = 0, y = 0;
if (player.GetPosition().x > (WORLD_SIZE_X * CHUNK_SIZE_X) * .66f) ++x;
else if (player.GetPosition().x < (WORLD_SIZE_X * CHUNK_SIZE_X) * .33f) --x;
if (player.GetPosition().z > (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .66f) ++y;
else if (player.GetPosition().z < (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .33f) --y;
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)
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)
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)
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)
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));
}
@ -97,125 +109,40 @@ void World::CleanUpWorld(int& deleteframes, bool clear = false) {
}
}
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(int& x, int& y) {
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, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
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);
UpdateWorld(player, perlin, blockinfo);
shader.Disable();
glStencilFunc(GL_GREATER, 1, 0xFF);
}
bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z &&
chx >= 0 && chy >= 0)
if (!ChunkAt(chx, 1, chy)) {
for (int index = 0; index < m_tbDeleted.size(); ++index) { // Vérifie l'existence d'un chunk dans le buffer de suppression avec sa position.
int x, y;
if (m_tbDeleted.at(index)) {
m_tbDeleted.at(index)->GetPosition(x, y);
if (chx / CHUNK_SIZE_X + m_center[0] == x &&
chy / CHUNK_SIZE_Z + m_center[1] == y) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index)));
return true;
}
}
}
std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position.
pos << CHUNK_PATH << chx / CHUNK_SIZE_X + m_center[0] << '_' << chy / CHUNK_SIZE_Z + m_center[1] << ".chunk";
std::ifstream input(pos.str(), std::fstream::binary);
if (input.fail()) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]));
Chunk* chunk = GetChunks().Get(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z);
for (int x = 0; x < CHUNK_SIZE_X; ++x) // Montagnes
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
float xnoiz, ynoiz;
xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
float height = (perlin.Get(xnoiz, ynoiz)) * 20.f + 5.f;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y)
chunk->SetBlock(x, y, z, BTYPE_METAL, this);
}
for (int x = 0; x < CHUNK_SIZE_X; ++x) // Collines
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
float xnoiz, ynoiz;
xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
float height = perlin.Get(xnoiz, ynoiz) * 5.f + 24.f;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_GRASS, this);
}
}
for (int x = 0; x < CHUNK_SIZE_X; ++x) // "Lacs"
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
for (int y = 0; y < 13; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_ICE, this);
}
}
for (int x = 0; x < CHUNK_SIZE_X; ++x) // "Arbres"
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
float xnoiz, ynoiz;
xnoiz = (double)(z * CHUNK_SIZE_Y + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
ynoiz = (double)(x * CHUNK_SIZE_Y + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
bool tree = (int)(abs(perlin.Get(xnoiz, ynoiz)) * 17933.f) % CHUNK_SIZE_Y > 126 ? true: false;
for (int y = 0; y < CHUNK_SIZE_Y - 10; ++y)
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
if (chunk->GetBlock(x, y - 1, z) == BTYPE_GRASS)
if (tree) {
for (int i = 0; i < (int)(abs(perlin.Get(xnoiz, ynoiz))) % 3 + 1; ++i)
chunk->SetBlock(x, y + i, z, BTYPE_DIRT, this);
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();
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, new Chunk(chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1], data));
}
return true;
}
return false;
}
void World::UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
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;
}
if (generates == 0 && GenerateChunk(chx, chy, perlin)) generates = FRAMES_RENDER_CHUNKS;
}
void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block) {
@ -276,12 +203,12 @@ void World::ChangeBlockAtCursor(BlockType blockType, Player& player, bool& block
}
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;
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();
ChunkAt(pos)->SetBlock(bx, by, bz, blockType, this);
ChunkAt(pos)->MakeModified();
}
void World::RenderWorld(int& rendercount, Player& player, Transformation& world, Shader& shader) {
@ -296,7 +223,7 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world,
direct.Normalize();
pos.y = 1;
static Vector3f renderManifest[VIEW_DISTANCE * 4]; // Nombre de Chunks maximal à être rendus.
static Vector3<unsigned int> renderManifest[VIEW_DISTANCE * 4]; // 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) {
@ -314,7 +241,7 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world,
cosinus = .99993365506; // cos(2/3 degré)
echantillons = 120;
}
else if (dist > VIEW_DISTANCE * .3f) {
else if (dist > VIEW_DISTANCE * .3f) {
sinus = .01745240643; // sin(1 degré)
cosinus = .99984769515; // cos(1 degré)
echantillons = 90;
@ -345,16 +272,19 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world,
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;
bool valide = true;
if (ChunkAt(cursor)) {
int chx, chy;
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)
if (renderManifest[index].x == chx && renderManifest[index].z == chy)
valide = false;
if (valide) renderManifest[rendercount++] = Vector3f(chx, (VIEW_DISTANCE - (pos - cursor).Length() * 2.f + 128) / (float)VIEW_DISTANCE, chy);
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);
}
}
}
@ -363,40 +293,183 @@ void World::RenderWorld(int& rendercount, Player& player, Transformation& world,
world.ApplyTranslation(chx, 0, chy);
world.Use();
glBlendColor(renderManifest[index].y, renderManifest[index].y, renderManifest[index].y, 1.f);
float blcolor = renderManifest[index].y / (VIEW_DISTANCE * 1000.f);
glBlendColor(blcolor, blcolor, blcolor, 1.f);
ChunkAt(chx, 1, chy)->Render();
world.ApplyTranslation(-chx, 0, -chy);
}
shader.Disable();
};
void World::UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
void World::UpdateWorld(Player& player, BlockInfo* blockinfo[BTYPE_LAST]) {
int cx = player.GetPosition().x;
int cy = player.GetPosition().z;
static int frameGenerate = 0;
static int frameUpdate = 0;
static int frameDelete = 0;
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 || !frameUpdate)
while (side * CHUNK_SIZE_X <= VIEW_DISTANCE * 2) {
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)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; ty <= side; ++ty)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; tx >= -side; --tx)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
for (; ty >= -side; --ty)
UpdateChunk(frameGenerate, frameUpdate, cx + tx * CHUNK_SIZE_X, cy + ty * CHUNK_SIZE_Z, perlin, blockinfo);
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) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]);
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) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]);
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) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]);
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) { return new Chunk(x, y); }, chx / CHUNK_SIZE_X + m_center[0], chy / CHUNK_SIZE_Z + m_center[1]);
if (threads == THREADS_GENERATE_CHUNKS) frameGenerate = FRAMES_RENDER_CHUNKS;
}
if (frameGenerate)
break;
++side;
}
CleanUpWorld(frameDelete);
}
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;
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(); }

View File

@ -1,18 +1,19 @@
#ifndef WORLD_H__
#define WORLD_H__
#include <fstream>
#include <string>
#include <vector>
#include <future>
#include <thread>
#include "define.h"
#include "chunk.h"
#include "array2d.h"
#include "vector3.h"
#include "player.h"
#include "transformation.h"
#include "perlin.h"
#include "shader.h"
#include "bullet.h"
#include "textureatlas.h"
#include <fstream>
#include <string>
#include <vector>
class Chunk;
class Player;
@ -31,23 +32,23 @@ public:
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, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void Update(int& rendercount, Bullet* bullets[MAX_BULLETS], Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, BlockInfo* blockinfo[BTYPE_LAST]);
void GetScope(int& x, int& y);
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;
int m_center[2] = { INT16_MAX / 2 - WORLD_SIZE_X / 2, INT16_MAX / 2 - WORLD_SIZE_Y / 2 };
unsigned int m_center[2] = { UINT16_MAX / 2 - WORLD_SIZE_X, UINT16_MAX / 2 - WORLD_SIZE_Y };
bool GenerateChunk(int x, int y, Perlin& perlin);
void UpdateChunk(int& generates, int& updates, int chx, int chy, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
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, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void UpdateWorld(Player& player, BlockInfo* blockinfo[BTYPE_LAST]);
void TransposeWorld(Player& player, Bullet* bullets[MAX_BULLETS]);
};

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>D:\Repos\SQCSim2021\x64\Debug\SQCSim2021.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>

View File

@ -0,0 +1,2 @@
PlatformToolSet=ClangCL:VCToolArchitecture=Native64Bit:VCToolsVersion=14.31.31103:TargetPlatformVersion=10.0.22000.0:
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64|13.0.0|Debug|x64|D:\Repos\SQCSim2021\|

View File

@ -1,2 +1,2 @@
PlatformToolSet=ClangCL:VCToolArchitecture=Native32Bit:VCToolsVersion=14.29.30133:VCServicingVersionATL=14.29.30136:VCServicingVersionCrtHeaders=14.29.30136:TargetPlatformVersion=10.0.19041.0:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64|12.0.0|Release|x64|D:\Repos\SQCSim2021\|
PlatformToolSet=ClangCL:VCToolArchitecture=Native64Bit:VCToolsVersion=14.31.31103:TargetPlatformVersion=10.0.22000.0:
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64|13.0.0|Release|x64|D:\Repos\SQCSim2021\|

BIN
x64/Debug/DevIL.dll Normal file

Binary file not shown.

BIN
x64/Debug/ILU.dll Normal file

Binary file not shown.

BIN
x64/Debug/ILUT.dll Normal file

Binary file not shown.

BIN
x64/Debug/SQCSim2021.exe Normal file

Binary file not shown.

BIN
x64/Debug/glew32.dll Normal file

Binary file not shown.

BIN
x64/Debug/irrKlang.dll Normal file

Binary file not shown.

BIN
x64/Debug/openal32.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.