Various shit.
parent
4febca7ef8
commit
a59e1d2a82
|
@ -1,8 +1,8 @@
|
|||
-- Register base models (if not on main menu)
|
||||
if zepha.register_blockmodel then runfile(_PATH .. "models/_index") end
|
||||
|
||||
-- Load Libraries
|
||||
runfile(_PATH .. "dump")
|
||||
runfile(_PATH .. "math")
|
||||
runfile(_PATH .. "vector")
|
||||
runfile(_PATH .. "gui")
|
||||
runfile(_PATH .. "gui")
|
||||
|
||||
-- Register base models (if not on main menu)
|
||||
if zepha.register_blockmodel then runfile(_PATH .. "models/_index") end
|
|
@ -10,9 +10,9 @@ set(ZEPHA_SRC
|
|||
game/graph/Camera.cpp
|
||||
game/graph/Camera.h
|
||||
game/graph/Texture.cpp
|
||||
game/graph/Texture.h
|
||||
game/scene/world/graph/MeshGenerator.cpp
|
||||
game/scene/world/graph/MeshGenerator.h
|
||||
game/graph/Texture.h
|
||||
game/scene/world/graph/ChunkMeshGenerator.cpp
|
||||
game/scene/world/graph/ChunkMeshGenerator.h
|
||||
util/Timer.cpp
|
||||
util/Timer.h
|
||||
def/LocalDefinitionAtlas.cpp
|
||||
|
@ -81,9 +81,9 @@ set(ZEPHA_SRC
|
|||
game/graph/frustum/FrustumAABB.cpp
|
||||
game/graph/frustum/FrustumAABB.h
|
||||
server/world/ServerWorld.cpp
|
||||
server/world/ServerWorld.h
|
||||
server/world/WorldGenStream.cpp
|
||||
server/world/WorldGenStream.h
|
||||
server/world/ServerWorld.h
|
||||
server/world/ServerGenStream.cpp
|
||||
server/world/ServerGenStream.h
|
||||
game/scene/world/WorldInterpolationStream.cpp
|
||||
game/scene/world/WorldInterpolationStream.h
|
||||
util/Space.h
|
||||
|
@ -143,8 +143,8 @@ set(ZEPHA_SRC
|
|||
game/scene/ConnectScene.h
|
||||
util/net/Address.h
|
||||
game/scene/net/ServerConnection.cpp
|
||||
game/scene/net/ServerConnection.h
|
||||
game/scene/world/MeshDetails.h
|
||||
game/scene/net/ServerConnection.h
|
||||
game/scene/world/ChunkMeshDetails.h
|
||||
game/hud/components/GuiComponent.cpp
|
||||
game/hud/components/GuiComponent.h
|
||||
game/hud/components/basic/GuiContainer.cpp
|
||||
|
@ -320,6 +320,6 @@ set(ZEPHA_SRC
|
|||
game/inventory/InventoryList.h
|
||||
lua/api/modules/time.h
|
||||
util/net/PacketView.cpp
|
||||
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h)
|
||||
util/net/PacketView.h lua/api/modules/create_structure.h util/Any.h game/scene/world/graph/MeshFarMap.cpp game/scene/world/graph/MeshFarMap.h def/gen/MapGenProps.cpp def/gen/MapGenProps.h def/gen/FarMapGen.cpp def/gen/FarMapGen.h def/gen/FarMapJob.h game/scene/world/graph/FarMeshGenerator.cpp game/scene/world/graph/FarMeshGenerator.h game/scene/world/FarMapMeshDetails.h)
|
||||
|
||||
add_library (Zepha_Core ${ZEPHA_SRC})
|
|
@ -4,10 +4,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "LocalDefinitionAtlas.h"
|
||||
#include "gen/LocalBiomeAtlas.h"
|
||||
#include "gen/MapGenProps.h"
|
||||
#include "model/ModelStore.h"
|
||||
#include "gen/LocalBiomeAtlas.h"
|
||||
#include "texture/TextureAtlas.h"
|
||||
#include "LocalDefinitionAtlas.h"
|
||||
#include "../lua/parser/LocalLuaParser.h"
|
||||
|
||||
class ClientGame {
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
#include "ServerGame.h"
|
||||
#include "../server/conn/ClientList.h"
|
||||
|
||||
ServerGame::ServerGame(const std::string& subgame) :
|
||||
subgamePath("subgames/" + subgame + "/") {
|
||||
ServerGame::ServerGame(const std::string& subgame, unsigned int seed) :
|
||||
subgamePath("subgames/" + subgame + "/"),
|
||||
biomes(seed) {
|
||||
|
||||
if (subgame.empty()) {
|
||||
std::cout << Log::err << "No subgame specified." << Log::endl;
|
||||
|
|
|
@ -15,7 +15,7 @@ class ClientList;
|
|||
|
||||
class ServerGame {
|
||||
public:
|
||||
ServerGame(const std::string& subgame);
|
||||
ServerGame(const std::string& subgame, unsigned int seed);
|
||||
void init(ServerWorld& world);
|
||||
void update(double delta, ClientList& clients);
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-05.
|
||||
//
|
||||
|
||||
#include "FarMapGen.h"
|
||||
|
||||
FarMapGen::FarMapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props) :
|
||||
seed(seed),
|
||||
defs(defs),
|
||||
props(props),
|
||||
biomes(biomes) {}
|
||||
|
||||
MeshFarMap FarMapGen::generateFarMap(glm::ivec3 mbPos, unsigned short downScale) {
|
||||
auto job = new FarMapJob();
|
||||
job->downScale = downScale;
|
||||
|
||||
buildDensityMap(job, mbPos);
|
||||
|
||||
delete job;
|
||||
}
|
||||
|
||||
void FarMapGen::buildDensityMap(FarMapJob *job, glm::ivec3 mbPos) {
|
||||
job->temperature = {}; job->humidity = {}; job->roughness = {};
|
||||
|
||||
job->temperature.fill([&](glm::ivec3 pos) {
|
||||
return props->temperature.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
|
||||
job->humidity.fill([&](glm::ivec3 pos) {
|
||||
return props->humidity.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
|
||||
job->roughness.fill([&](glm::ivec3 pos) {
|
||||
return props->roughness.GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f); }, 4);
|
||||
|
||||
NoiseSample volume = {}, heightmap = {};
|
||||
|
||||
volume.fill([&](glm::ivec3 pos) {
|
||||
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
|
||||
return biome.volume[biome.volume.size() - 1]->GetValue(mbPos.x * 4 + pos.x / 4.f, mbPos.y * 4 + pos.y / 4.f, mbPos.z * 4 + pos.z / 4.f);
|
||||
}, {4, 4});
|
||||
|
||||
heightmap.fill([&](glm::ivec3 pos) {
|
||||
auto& biome = biomes.getBiomeAt(job->temperature.get(pos), job->humidity.get(pos), job->roughness.get(pos));
|
||||
return biome.heightmap[biome.heightmap.size() - 1]->GetValue(mbPos.x * 4 + pos.x / 4.f, 0, mbPos.z * 4 + pos.z / 4.f);
|
||||
}, 4);
|
||||
|
||||
int sampleWid = 64 / job->downScale;
|
||||
float factor = (job->downScale == 2 ? 0.5f : job->downScale == 4 ? 1 : 2);
|
||||
|
||||
glm::ivec3 lp;
|
||||
for (int m = 0; m < pow(sampleWid, 3); m++) {
|
||||
Vec::indAssignVec(m, lp, sampleWid);
|
||||
|
||||
job->density[m] = (volume.get(glm::vec3(lp) * factor) + heightmap.get(glm::vec3(lp) * factor)) - (static_cast<float>(lp.y) * factor + mbPos.y * 64);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-05.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FarMapJob.h"
|
||||
#include "BiomeAtlas.h"
|
||||
#include "NoiseSample.h"
|
||||
#include "MapGenProps.h"
|
||||
#include "../../util/Vec.h"
|
||||
#include "../DefinitionAtlas.h"
|
||||
#include "../../game/scene/world/graph/MeshFarMap.h"
|
||||
|
||||
class FarMapGen {
|
||||
FarMapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props);
|
||||
|
||||
MeshFarMap generateFarMap(glm::ivec3 mbPos, unsigned short downScale);
|
||||
private:
|
||||
// Build the density map for a job.
|
||||
void buildDensityMap(FarMapJob* job, glm::ivec3 mbPos);
|
||||
|
||||
// Build the elevation map for a job.
|
||||
void buildElevationMap(FarMapJob& job);
|
||||
|
||||
// Generate blocks and structures on a chunk, respectively. generateStructures can create partials.
|
||||
// void generateBlocks(chunk_partial& chunk);
|
||||
// void generateStructures(chunk_partials_map& chunks, chunk_partial& chunk);
|
||||
|
||||
unsigned int seed = 0;
|
||||
|
||||
DefinitionAtlas& defs;
|
||||
BiomeAtlas& biomes;
|
||||
|
||||
std::shared_ptr<MapGenProps> props;
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-05.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <glm/vec3.hpp>
|
||||
#include "NoiseSample.h"
|
||||
|
||||
struct FarMapJob {
|
||||
std::vector<float> density {};
|
||||
std::vector<float> depth {};
|
||||
|
||||
unsigned short downScale;
|
||||
|
||||
NoiseSample temperature, humidity, roughness;
|
||||
};
|
|
@ -8,41 +8,11 @@
|
|||
#include <random>
|
||||
#include <cmath>
|
||||
|
||||
MapGen::MapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes) :
|
||||
MapGen::MapGen(unsigned int seed, DefinitionAtlas& defs, BiomeAtlas& biomes, std::shared_ptr<MapGenProps> props) :
|
||||
seed(seed),
|
||||
defs(defs),
|
||||
biomes(biomes) {
|
||||
|
||||
temperatureBase.SetSeed(seed);
|
||||
temperatureBase.SetFrequency(0.02);
|
||||
temperatureBase.SetOctaveCount(4);
|
||||
temperatureTurbulence.SetSourceModule(0, temperatureBase);
|
||||
temperatureTurbulence.SetRoughness(4);
|
||||
temperatureTurbulence.SetFrequency(0.2);
|
||||
temperature.SetSourceModule(0, temperatureTurbulence);
|
||||
temperature.SetScale(0.35);
|
||||
temperature.SetBias(0.25);
|
||||
|
||||
humidityBase.SetSeed(seed + 5);
|
||||
humidityBase.SetFrequency(0.02);
|
||||
humidityBase.SetOctaveCount(4);
|
||||
humidityTurbulence.SetSourceModule(0, humidityBase);
|
||||
humidityTurbulence.SetRoughness(4);
|
||||
humidityTurbulence.SetFrequency(0.2);
|
||||
humidity.SetSourceModule(0, humidityTurbulence);
|
||||
humidity.SetScale(0.5);
|
||||
humidity.SetBias(0.5);
|
||||
|
||||
roughnessBase.SetSeed(seed + 10);
|
||||
roughnessBase.SetFrequency(0.02);
|
||||
roughnessBase.SetOctaveCount(4);
|
||||
roughnessTurbulence.SetSourceModule(0, roughnessBase);
|
||||
roughnessTurbulence.SetRoughness(4);
|
||||
roughnessTurbulence.SetFrequency(0.2);
|
||||
roughness.SetSourceModule(0, roughnessTurbulence);
|
||||
roughness.SetScale(0.5);
|
||||
roughness.SetBias(0.5);
|
||||
}
|
||||
props(props),
|
||||
biomes(biomes) {}
|
||||
|
||||
MapGen::chunk_partials_map MapGen::generateMapBlock(glm::ivec3 mbPos) {
|
||||
chunk_partials_map chunks {};
|
||||
|
@ -84,11 +54,11 @@ void MapGen::buildDensityMap(MapGenJob* job, glm::ivec3 worldPos) {
|
|||
job->temperature = {}; job->humidity = {}; job->roughness = {};
|
||||
|
||||
job->temperature.fill([&](glm::ivec3 pos) {
|
||||
return temperature.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
return props->temperature.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
job->humidity.fill([&](glm::ivec3 pos) {
|
||||
return humidity.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
return props->humidity.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
job->roughness.fill([&](glm::ivec3 pos) {
|
||||
return roughness.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
return props->roughness.GetValue(worldPos.x + pos.x / 16.f, 0, worldPos.z + pos.z / 16.f); }, 4);
|
||||
|
||||
NoiseSample volume = {}, heightmap = {};
|
||||
|
||||
|
|
|
@ -5,17 +5,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "MapGenJob.h"
|
||||
#include "MapGenProps.h"
|
||||
#include "../../util/Vec.h"
|
||||
#include "../../world/chunk/BlockChunk.h"
|
||||
|
||||
using namespace noise;
|
||||
|
||||
class MapGen {
|
||||
public:
|
||||
typedef std::pair<MapGenJob*, BlockChunk*> chunk_partial;
|
||||
typedef std::unordered_map<glm::ivec3, chunk_partial, Vec::ivec3> chunk_partials_map;
|
||||
|
||||
MapGen(unsigned int seed, DefinitionAtlas& atlas, BiomeAtlas& biome);
|
||||
MapGen(unsigned int seed, DefinitionAtlas& atlas, BiomeAtlas& biome, std::shared_ptr<MapGenProps> props);
|
||||
chunk_partials_map generateMapBlock(glm::ivec3 mbPos);
|
||||
|
||||
// Combine two chunk partials, or a chunk and a chunk partial.
|
||||
|
@ -43,15 +42,5 @@ private:
|
|||
DefinitionAtlas& defs;
|
||||
BiomeAtlas& biomes;
|
||||
|
||||
module::Perlin temperatureBase;
|
||||
module::Turbulence temperatureTurbulence;
|
||||
module::ScaleBias temperature;
|
||||
|
||||
module::Perlin humidityBase;
|
||||
module::Turbulence humidityTurbulence;
|
||||
module::ScaleBias humidity;
|
||||
|
||||
module::Perlin roughnessBase;
|
||||
module::Turbulence roughnessTurbulence;
|
||||
module::ScaleBias roughness;
|
||||
std::shared_ptr<MapGenProps> props;
|
||||
};
|
|
@ -5,13 +5,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <glm/vec3.hpp>
|
||||
#include "NoiseSample.h"
|
||||
#include "../../util/Space.h"
|
||||
|
||||
struct MapGenJob {
|
||||
class MapGenJob {
|
||||
public:
|
||||
std::array<float, 4096> density {};
|
||||
std::array<float, 4096> depth {};
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-05.
|
||||
//
|
||||
|
||||
#include "MapGenProps.h"
|
||||
|
||||
MapGenProps::MapGenProps(unsigned int seed) : seed(seed) {
|
||||
temperatureBase.SetSeed(seed);
|
||||
temperatureBase.SetFrequency(0.02);
|
||||
temperatureBase.SetOctaveCount(4);
|
||||
temperatureTurbulence.SetSourceModule(0, temperatureBase);
|
||||
temperatureTurbulence.SetRoughness(4);
|
||||
temperatureTurbulence.SetFrequency(0.2);
|
||||
temperature.SetSourceModule(0, temperatureTurbulence);
|
||||
temperature.SetScale(0.35);
|
||||
temperature.SetBias(0.25);
|
||||
|
||||
humidityBase.SetSeed(seed + 5);
|
||||
humidityBase.SetFrequency(0.02);
|
||||
humidityBase.SetOctaveCount(4);
|
||||
humidityTurbulence.SetSourceModule(0, humidityBase);
|
||||
humidityTurbulence.SetRoughness(4);
|
||||
humidityTurbulence.SetFrequency(0.2);
|
||||
humidity.SetSourceModule(0, humidityTurbulence);
|
||||
humidity.SetScale(0.5);
|
||||
humidity.SetBias(0.5);
|
||||
|
||||
roughnessBase.SetSeed(seed + 10);
|
||||
roughnessBase.SetFrequency(0.02);
|
||||
roughnessBase.SetOctaveCount(4);
|
||||
roughnessTurbulence.SetSourceModule(0, roughnessBase);
|
||||
roughnessTurbulence.SetRoughness(4);
|
||||
roughnessTurbulence.SetFrequency(0.2);
|
||||
roughness.SetSourceModule(0, roughnessTurbulence);
|
||||
roughness.SetScale(0.5);
|
||||
roughness.SetBias(0.5);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-05.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <noise/noise.h>
|
||||
|
||||
using namespace noise;
|
||||
|
||||
class MapGenProps {
|
||||
public:
|
||||
MapGenProps(unsigned int seed);
|
||||
|
||||
unsigned int seed;
|
||||
|
||||
module::Perlin temperatureBase;
|
||||
module::Turbulence temperatureTurbulence;
|
||||
module::ScaleBias temperature;
|
||||
|
||||
module::Perlin humidityBase;
|
||||
module::Turbulence humidityTurbulence;
|
||||
module::ScaleBias humidity;
|
||||
|
||||
module::Perlin roughnessBase;
|
||||
module::Turbulence roughnessTurbulence;
|
||||
module::ScaleBias roughness;
|
||||
};
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include "ServerBiomeAtlas.h"
|
||||
|
||||
ServerBiomeAtlas::ServerBiomeAtlas() {
|
||||
ServerBiomeAtlas::ServerBiomeAtlas(unsigned int seed) :
|
||||
seed(seed) {
|
||||
//Invalid Biome
|
||||
BiomeDef* invalid = new BiomeDef("invalid", INVALID, -1, -1, -1, 0, 0, 0, {}, {}, {}, {});
|
||||
registerBiome(invalid);
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
class ServerBiomeAtlas : public BiomeAtlas {
|
||||
public:
|
||||
ServerBiomeAtlas();
|
||||
ServerBiomeAtlas(unsigned int seed);
|
||||
void registerBiome(BiomeDef* def) override;
|
||||
|
||||
unsigned int seed;
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
ServerConnection connection {};
|
||||
ClientGame defs;
|
||||
|
||||
unsigned int seed = 0;
|
||||
|
||||
std::string desiredState = "this";
|
||||
|
||||
double fps = 0;
|
||||
|
|
|
@ -142,5 +142,5 @@ void GuiInventoryList::drawContents() {
|
|||
}
|
||||
|
||||
GuiInventoryList::~GuiInventoryList() {
|
||||
list->setGuiCallback(nullptr);
|
||||
if (list != nullptr) list->setGuiCallback(nullptr);
|
||||
}
|
|
@ -51,6 +51,27 @@ void ConnectScene::update() {
|
|||
handleConnecting();
|
||||
break;
|
||||
|
||||
case State::PROPERTIES: {
|
||||
components.get<GuiRect>("loadBar")->setScale({state.renderer.window.getSize().x * 0.1, 32});
|
||||
|
||||
ENetEvent e;
|
||||
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
|
||||
PacketView p(e.packet);
|
||||
|
||||
if (p.type == PacketType::SERVER_INFO) {
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
statusText->setText(statusText->getText() + "Received server properties.\n");
|
||||
|
||||
state.seed = p.d.read<unsigned int>();
|
||||
|
||||
connectState = State::IDENTIFIER_LIST;
|
||||
Packet resp(PacketType::BLOCK_IDENTIFIER_LIST);
|
||||
resp.sendTo(connection.getPeer(), PacketChannel::CONNECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case State::IDENTIFIER_LIST: {
|
||||
components.get<GuiRect>("loadBar")->setScale({state.renderer.window.getSize().x * 0.2, 32});
|
||||
|
||||
|
@ -161,7 +182,7 @@ void ConnectScene::update() {
|
|||
}
|
||||
|
||||
void ConnectScene::handleConnecting() {
|
||||
Packet resp(PacketType::BLOCK_IDENTIFIER_LIST);
|
||||
Packet resp(PacketType::SERVER_INFO);
|
||||
auto statusText = components.get<GuiText>("statusText");
|
||||
|
||||
switch (connection.getConnectionStatus()) {
|
||||
|
@ -189,7 +210,7 @@ void ConnectScene::handleConnecting() {
|
|||
break;
|
||||
|
||||
case ServerConnection::State::CONNECTED:
|
||||
connectState = State::IDENTIFIER_LIST;
|
||||
connectState = State::PROPERTIES;
|
||||
statusText->setText(statusText->getText() + " Connected!~\n");
|
||||
|
||||
resp.sendTo(connection.getPeer(), PacketChannel::CONNECT);
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
enum class State {
|
||||
CONNECTING,
|
||||
FAILED_CONNECT,
|
||||
PROPERTIES,
|
||||
IDENTIFIER_LIST,
|
||||
MODS,
|
||||
MEDIA,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <glm/vec3.hpp>
|
||||
#include "../../graph/meshtypes/ChunkMesh.h"
|
||||
|
||||
struct MeshDetails {
|
||||
struct ChunkMeshDetails {
|
||||
std::vector<ChunkVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-06.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
struct FarMapMeshDetails {
|
||||
// std::vector<FarMapVertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
glm::vec3 pos {0, 0, 0};
|
||||
};
|
|
@ -38,7 +38,7 @@ void LocalWorld::update(double delta) {
|
|||
}
|
||||
|
||||
void LocalWorld::loadChunkPacket(std::unique_ptr<PacketView> p) {
|
||||
worldGenStream->pushBack(std::move(p));
|
||||
worldGenStream->queuePacket(std::move(p));
|
||||
}
|
||||
|
||||
void LocalWorld::commitChunk(std::shared_ptr<BlockChunk> c) {
|
||||
|
@ -162,7 +162,7 @@ void LocalWorld::finishChunks() {
|
|||
auto finishedChunks = worldGenStream->update();
|
||||
|
||||
lastGenUpdates = 0;
|
||||
for (const auto &chunk : finishedChunks) {
|
||||
for (const auto &chunk : *finishedChunks) {
|
||||
commitChunk(chunk);
|
||||
lastGenUpdates++;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "../../../world/LocalDimension.h"
|
||||
|
||||
MeshGenStream::MeshGenStream(ClientGame &defs, LocalDimension &dimension) :
|
||||
defs(defs),
|
||||
MeshGenStream::MeshGenStream(ClientGame& game, LocalDimension &dimension) :
|
||||
game(game),
|
||||
dimension(dimension) {
|
||||
|
||||
queuedTasks.reserve(static_cast<unsigned long>(TOTAL_QUEUE_SIZE));
|
||||
|
@ -28,18 +28,14 @@ MeshGenStream::MeshGenStream(ClientGame &defs, LocalDimension &dimension) :
|
|||
noiseSampler[2].fill([&](glm::ivec3 pos) -> float { return offsetTurbulence.GetValue(pos.x, pos.y, pos.z + 8); }, {16, 16});
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) {
|
||||
threads.emplace_back(defs, noiseSampler);
|
||||
}
|
||||
for (int i = 0; i < THREADS; i++) threads.emplace_back(game, noiseSampler);
|
||||
}
|
||||
|
||||
MeshGenStream::Thread::Thread(ClientGame &defs, std::array<NoiseSample, 3>& offsetSamplers) :
|
||||
defs(defs), offsetSamplers(offsetSamplers) {
|
||||
thread = std::thread(MeshGenStream::threadFunction, this);
|
||||
}
|
||||
game(defs), offsetSamplers(offsetSamplers), thread(MeshGenStream::threadFunction, this) {}
|
||||
|
||||
std::vector<MeshDetails*> MeshGenStream::update() {
|
||||
std::vector<MeshDetails*> finishedChunks;
|
||||
std::vector<ChunkMeshDetails*> MeshGenStream::update() {
|
||||
std::vector<ChunkMeshDetails*> finishedChunks;
|
||||
|
||||
for (Thread& t : threads) {
|
||||
for (Unit& u : t.tasks) {
|
||||
|
@ -48,7 +44,7 @@ std::vector<MeshDetails*> MeshGenStream::update() {
|
|||
if (u.thisChunk != nullptr) {
|
||||
u.thisChunk = nullptr;
|
||||
finishedChunks.push_back(u.meshDetails);
|
||||
u.meshDetails = new MeshDetails();
|
||||
u.meshDetails = new ChunkMeshDetails();
|
||||
}
|
||||
|
||||
if (!queuedTasks.empty()) {
|
||||
|
@ -83,12 +79,11 @@ void MeshGenStream::threadFunction(MeshGenStream::Thread *thread) {
|
|||
while (thread->keepAlive) {
|
||||
bool hasNoTasks = true;
|
||||
|
||||
for (Unit& u : thread->tasks) {
|
||||
for (auto i = 0; i < thread->tasks.size(); i++) {
|
||||
auto& u = thread->tasks[i];
|
||||
if (!u.busy) continue;
|
||||
|
||||
// bool hi = glm::distance(glm::vec3{0, 0, 0}, glm::vec3(u.thisChunk->pos)) < 8;
|
||||
|
||||
MeshGenerator m(u.meshDetails, thread->defs, u.thisChunk, u.adjacentChunks, thread->offsetSamplers, true);
|
||||
ChunkMeshGenerator m(u.meshDetails, thread->game.defs, thread->game.biomes, u.thisChunk, u.adjacentChunks, thread->offsetSamplers);
|
||||
hasNoTasks = false;
|
||||
u.busy = false;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include <glm/vec3.hpp>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include "MeshDetails.h"
|
||||
#include "graph/MeshGenerator.h"
|
||||
#include "ChunkMeshDetails.h"
|
||||
#include "graph/ChunkMeshGenerator.h"
|
||||
#include "../../../world/chunk/BlockChunk.h"
|
||||
#include "../../../def/LocalDefinitionAtlas.h"
|
||||
#include "../../../util/Vec.h"
|
||||
|
@ -23,7 +23,7 @@ public:
|
|||
static const int THREADS = 2;
|
||||
static const int TOTAL_QUEUE_SIZE = THREADS * THREAD_QUEUE_SIZE;
|
||||
|
||||
explicit MeshGenStream(ClientGame& defs, LocalDimension& dimension);
|
||||
explicit MeshGenStream(ClientGame& game, LocalDimension& dimension);
|
||||
~MeshGenStream();
|
||||
|
||||
bool spaceInQueue();
|
||||
|
@ -34,13 +34,13 @@ public:
|
|||
|
||||
//Will return a vector of MeshDetails pointers containing finished meshes.
|
||||
//Frees up the threads and starts new tasks.
|
||||
std::vector<MeshDetails*> update();
|
||||
std::vector<ChunkMeshDetails*> update();
|
||||
|
||||
struct Unit {
|
||||
std::shared_ptr<BlockChunk> thisChunk = nullptr;
|
||||
std::array<std::shared_ptr<BlockChunk>, 6> adjacentChunks {};
|
||||
|
||||
MeshDetails* meshDetails = new MeshDetails();
|
||||
ChunkMeshDetails* meshDetails = new ChunkMeshDetails();
|
||||
|
||||
bool busy = false;
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ public:
|
|||
struct Thread {
|
||||
explicit Thread(ClientGame &defs, std::array<NoiseSample, 3>& offsetSampler);
|
||||
|
||||
ClientGame &defs;
|
||||
ClientGame &game;
|
||||
std::array<NoiseSample, 3>& offsetSamplers;
|
||||
|
||||
std::thread thread {};
|
||||
|
@ -62,7 +62,7 @@ private:
|
|||
static void threadFunction(Thread* thread);
|
||||
|
||||
LocalDimension& dimension;
|
||||
ClientGame& defs;
|
||||
ClientGame& game;
|
||||
|
||||
std::array<NoiseSample, 3> noiseSampler;
|
||||
std::vector<glm::vec3> queuedTasks;
|
||||
|
|
|
@ -4,40 +4,66 @@
|
|||
|
||||
#include "WorldInterpolationStream.h"
|
||||
|
||||
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, ClientGame& defs) {
|
||||
// gen(seed, defs.defs) {
|
||||
queuedTasks.reserve(1024);
|
||||
#include "../../../def/ClientGame.h"
|
||||
|
||||
WorldInterpolationStream::WorldInterpolationStream(unsigned int seed, ClientGame& game) :
|
||||
props(std::make_shared<MapGenProps>(seed)),
|
||||
gen(seed, game.defs, game.biomes, props) {
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) {
|
||||
// threads.emplace_back(&gen);
|
||||
threads.emplace_back();
|
||||
for (int i = 0; i < THREADS; i++) threads.emplace_back(&gen);
|
||||
}
|
||||
|
||||
void WorldInterpolationStream::queuePacket(std::unique_ptr<PacketView> p) {
|
||||
queuedPacketTasks.push_back(std::move(p));
|
||||
}
|
||||
|
||||
bool WorldInterpolationStream::queuePosition(glm::vec3 pos){
|
||||
if (!queuedInterpMap.count(pos)) {
|
||||
queuedInterpTasks.push_back(pos);
|
||||
queuedInterpMap.insert(pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WorldInterpolationStream::pushBack(std::unique_ptr<PacketView> p) {
|
||||
queuedTasks.push_back(std::move(p));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<BlockChunk>> WorldInterpolationStream::update() {
|
||||
std::vector<std::shared_ptr<BlockChunk>> finishedChunks;
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> WorldInterpolationStream::update() {
|
||||
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
|
||||
auto finishedMapBlocks = std::make_unique<std::vector<std::shared_ptr<MeshFarMap>>>();
|
||||
|
||||
for (auto& t : threads) {
|
||||
for (auto& u : t.tasks) {
|
||||
if (!u.unlocked) continue;
|
||||
if (u.locked) continue;
|
||||
|
||||
if (u.chunk != nullptr) {
|
||||
finishedChunks.push_back(std::shared_ptr<BlockChunk>(u.chunk));
|
||||
finishedChunks->push_back(u.chunk);
|
||||
u.chunk = nullptr;
|
||||
u.job = JobType::EMPTY;
|
||||
}
|
||||
else if (u.mapblock != nullptr) {
|
||||
finishedMapBlocks->push_back(u.mapblock);
|
||||
u.mapblock = nullptr;
|
||||
u.job = JobType::EMPTY;
|
||||
}
|
||||
|
||||
if (!queuedTasks.empty()) {
|
||||
auto it = queuedTasks.begin();
|
||||
u.packet = std::move(*it);
|
||||
queuedTasks.erase(it);
|
||||
//Lock it to allow the thread to edit it.
|
||||
u.unlocked = false;
|
||||
if (!queuedPacketTasks.empty()) {
|
||||
auto it = queuedPacketTasks.begin();
|
||||
auto packet = std::move(*it);
|
||||
queuedPacketTasks.erase(it);
|
||||
|
||||
u.job = JobType::PACKET;
|
||||
u.packet = std::move(packet);
|
||||
u.locked = true;
|
||||
}
|
||||
else if (!queuedInterpTasks.empty()) {
|
||||
auto it = queuedInterpTasks.begin();
|
||||
glm::vec3 pos = *it;
|
||||
queuedInterpTasks.erase(it);
|
||||
queuedInterpMap.erase(pos);
|
||||
|
||||
u.job = JobType::FARMAP;
|
||||
u.mapBlockPos = pos;
|
||||
u.locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,41 +71,36 @@ std::vector<std::shared_ptr<BlockChunk>> WorldInterpolationStream::update() {
|
|||
return finishedChunks;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
WorldInterpolationStream::Thread::Thread() {
|
||||
//WorldInterpolationStream::Thread::Thread(MapGen *gen) : gen(gen) {
|
||||
WorldInterpolationStream::Thread::Thread(MapGen *gen) : gen(gen) {
|
||||
thread = std::thread(WorldInterpolationStream::threadFunction, this);
|
||||
thread.detach();
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
void WorldInterpolationStream::threadFunction(WorldInterpolationStream::Thread *thread) {
|
||||
while (!thread->kill) {
|
||||
|
||||
while (thread->keepAlive) {
|
||||
|
||||
bool noJobs = true;
|
||||
|
||||
for (Unit& u : thread->tasks) {
|
||||
if (!u.unlocked) {
|
||||
noJobs = false;
|
||||
|
||||
u.chunk = new BlockChunk;
|
||||
u.chunk->deserialize(*u.packet);
|
||||
|
||||
u.unlocked = true;
|
||||
break;
|
||||
bool empty = true;
|
||||
for (Job& u : thread->tasks) {
|
||||
if (u.locked) {
|
||||
if (u.job == JobType::PACKET) {
|
||||
empty = false;
|
||||
u.chunk = std::make_shared<BlockChunk>();
|
||||
u.chunk->deserialize(*u.packet);
|
||||
u.locked = false;
|
||||
break;
|
||||
}
|
||||
else if (u.job == JobType::FARMAP) {
|
||||
std::cout << "Farmap no exist yet" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (noJobs) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
WorldInterpolationStream::~WorldInterpolationStream() {
|
||||
for (auto& t : threads) {
|
||||
t.keepAlive = false;
|
||||
t.kill = true;
|
||||
t.thread.join();
|
||||
}
|
||||
}
|
|
@ -4,50 +4,69 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "../../../def/ClientGame.h"
|
||||
#include "graph/MeshFarMap.h"
|
||||
#include "../../../def/gen/MapGen.h"
|
||||
#include "../../../world/chunk/BlockChunk.h"
|
||||
|
||||
class ClientGame;
|
||||
|
||||
class WorldInterpolationStream {
|
||||
public:
|
||||
static const int THREAD_QUEUE_SIZE = 128;
|
||||
static const int THREADS = 2;
|
||||
static const int THREADS = 4;
|
||||
static const int THREAD_QUEUE_SIZE = 32;
|
||||
|
||||
WorldInterpolationStream(unsigned int seed, ClientGame& defs);
|
||||
WorldInterpolationStream(unsigned int seed, ClientGame& game);
|
||||
~WorldInterpolationStream();
|
||||
|
||||
//Add `p` to the pre-thread queue.
|
||||
bool pushBack(std::unique_ptr<PacketView> p);
|
||||
// Queue parsing of packet `p`.
|
||||
void queuePacket(std::unique_ptr<PacketView> p);
|
||||
// Queue interpolation of Mapblock at `pos`.
|
||||
bool queuePosition(glm::vec3 pos);
|
||||
// Returns a vector of BlockChunks that have finished processing,
|
||||
// and gives the threads new data to work with.
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
|
||||
|
||||
//Will return a vector of BlockChunk pointers containing finished chunks.
|
||||
//Frees up the threads and starts new tasks.
|
||||
std::vector<std::shared_ptr<BlockChunk>> update();
|
||||
private:
|
||||
enum class JobType {
|
||||
EMPTY,
|
||||
PACKET,
|
||||
FARMAP
|
||||
};
|
||||
|
||||
struct Unit {
|
||||
std::unique_ptr<PacketView> packet;
|
||||
BlockChunk* chunk = nullptr;
|
||||
struct Job {
|
||||
bool locked = false;
|
||||
JobType job = JobType::EMPTY;
|
||||
|
||||
std::unique_ptr<PacketView> packet = nullptr;
|
||||
std::shared_ptr<BlockChunk> chunk = nullptr;
|
||||
|
||||
std::shared_ptr<MeshFarMap> mapblock = nullptr;
|
||||
glm::vec3 mapBlockPos = {0, 0, 0};
|
||||
|
||||
bool unlocked = true;
|
||||
};
|
||||
|
||||
struct Thread {
|
||||
// explicit Thread(MapGen* gen);
|
||||
explicit Thread();
|
||||
|
||||
// MapGen* gen;
|
||||
|
||||
explicit Thread(MapGen* gen);
|
||||
std::thread thread;
|
||||
bool keepAlive = true;
|
||||
bool kill = false;
|
||||
|
||||
std::vector<Unit> tasks = std::vector<Unit>(THREAD_QUEUE_SIZE);
|
||||
MapGen* gen;
|
||||
std::vector<Job> tasks = std::vector<Job>(THREAD_QUEUE_SIZE);
|
||||
};
|
||||
|
||||
std::vector<Thread> threads;
|
||||
private:
|
||||
// Function that occurs on the threads.
|
||||
static void threadFunction(Thread* thread);
|
||||
|
||||
// MapGen gen;
|
||||
std::vector<std::unique_ptr<PacketView>> queuedTasks;
|
||||
std::shared_ptr<MapGenProps> props;
|
||||
MapGen gen;
|
||||
|
||||
std::vector<Thread> threads;
|
||||
std::list<std::unique_ptr<PacketView>> queuedPacketTasks;
|
||||
std::unordered_set<glm::vec3, Vec::vec3> queuedInterpMap;
|
||||
std::list<glm::vec3> queuedInterpTasks;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Created by aurailus on 01/12/18.
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <glm/gtx/normal.hpp>
|
||||
|
||||
#include "ChunkMeshGenerator.h"
|
||||
|
||||
#include "../ChunkMeshDetails.h"
|
||||
#include "../../../../util/Vec.h"
|
||||
#include "../../../../world/chunk/BlockChunk.h"
|
||||
|
||||
ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent, std::array<NoiseSample, 3>& blockOffsets) :
|
||||
|
||||
defs(defs),
|
||||
chunk(chunk),
|
||||
biomes(biomes),
|
||||
adjacent(adjacent),
|
||||
meshDetails(meshDetails) {
|
||||
|
||||
meshDetails->vertices.reserve(5000);
|
||||
meshDetails->indices.reserve(7000);
|
||||
|
||||
const auto& blockData = chunk->cGetBlocks();
|
||||
const auto& biomeData = chunk->cGetBiomes();
|
||||
|
||||
unsigned short blockArrayPos = 0;
|
||||
unsigned int cBlock = blockData[blockArrayPos + 1];
|
||||
unsigned short biomeArrayPos = 0;
|
||||
unsigned short cBiome = biomeData[biomeArrayPos + 1];
|
||||
|
||||
glm::ivec3 off;
|
||||
for (unsigned short i = 0; i < 4096; i++) {
|
||||
if (blockArrayPos + 2 < blockData.size() && i >= blockData[blockArrayPos + 2]) {
|
||||
blockArrayPos += 2;
|
||||
cBlock = blockData[blockArrayPos + 1];
|
||||
}
|
||||
if (biomeArrayPos + 2 < biomeData.size() && i >= biomeData[biomeArrayPos + 2]) {
|
||||
biomeArrayPos += 2;
|
||||
cBiome = biomeData[biomeArrayPos + 1];
|
||||
}
|
||||
|
||||
BlockModel& model = defs.blockFromId(cBlock).model;
|
||||
glm::vec3 biomeTint = biomes.biomeFromId(cBiome).biomeTint;
|
||||
|
||||
if (!model.visible) continue;
|
||||
|
||||
Vec::indAssignVec(i, off);
|
||||
glm::vec3 vis = off;
|
||||
|
||||
for (auto& mod : model.meshMods) {
|
||||
switch (mod.first) {
|
||||
default: break;
|
||||
|
||||
case MeshMod::OFFSET_X:
|
||||
vis.x += blockOffsets[0].get(off) * mod.second; break;
|
||||
case MeshMod::OFFSET_Y:
|
||||
vis.y += blockOffsets[1].get(off) * mod.second; break;
|
||||
case MeshMod::OFFSET_Z:
|
||||
vis.z += blockOffsets[2].get(off) * mod.second; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!getBlockAt({off.x - 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
|
||||
if (!getBlockAt({off.x + 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
|
||||
if (!getBlockAt({off.x, off.y - 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
|
||||
if (!getBlockAt({off.x, off.y + 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
|
||||
if (!getBlockAt({off.x, off.y, off.z - 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
|
||||
if (!getBlockAt({off.x, off.y, off.z + 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
|
||||
|
||||
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
|
||||
}
|
||||
|
||||
meshDetails->vertices.shrink_to_fit();
|
||||
meshDetails->indices.shrink_to_fit();
|
||||
}
|
||||
|
||||
BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
|
||||
if (pos.x == 16) return defs.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
|
||||
if (pos.x == -1) return defs.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
|
||||
|
||||
if (pos.y == 16) return defs.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
|
||||
if (pos.y == -1) return defs.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
|
||||
|
||||
if (pos.z == 16) return defs.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
|
||||
if (pos.z == -1) return defs.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
|
||||
|
||||
return defs.blockFromId(chunk->getBlock(pos));
|
||||
}
|
||||
|
||||
void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
|
||||
for (const MeshPart& mp : meshParts) {
|
||||
glm::vec3 modData = {};
|
||||
|
||||
switch (mp.shaderMod) {
|
||||
default: break;
|
||||
|
||||
case ShaderMod::ROTATE_X:
|
||||
case ShaderMod::ROTATE_Y:
|
||||
case ShaderMod::ROTATE_Z:
|
||||
case ShaderMod::SWAY_ATTACHED:
|
||||
case ShaderMod::SWAY_FULL_BLOCK:
|
||||
modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
|
||||
break;
|
||||
}
|
||||
|
||||
for (const BlockModelVertex &vertex : mp.vertices) {
|
||||
meshDetails->vertices.push_back({
|
||||
vertex.pos + offset,
|
||||
vertex.tex,
|
||||
(mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
|
||||
(mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
|
||||
Util::packFloat(vertex.nml),
|
||||
static_cast<float>(mp.shaderMod),
|
||||
modData
|
||||
});
|
||||
}
|
||||
|
||||
for (unsigned int index : mp.indices) {
|
||||
meshDetails->indices.push_back(indOffset + index);
|
||||
}
|
||||
|
||||
indOffset += mp.vertices.size();
|
||||
}
|
||||
}
|
|
@ -2,37 +2,33 @@
|
|||
// Created by aurailus on 01/12/18.
|
||||
//
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
|
||||
|
||||
#pragma once
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#include "../../../../def/ClientGame.h"
|
||||
#include "../../../../def/gen/NoiseSample.h"
|
||||
|
||||
class MeshDetails;
|
||||
class ChunkMeshDetails;
|
||||
class BlockChunk;
|
||||
|
||||
class MeshGenerator {
|
||||
class ChunkMeshGenerator {
|
||||
public:
|
||||
MeshGenerator(MeshDetails* meshDetails, ClientGame& defs,
|
||||
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent,
|
||||
std::array<NoiseSample, 3>& blockOffsets, bool hi);
|
||||
ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
std::shared_ptr<BlockChunk> chunk, std::array<std::shared_ptr<BlockChunk>, 6> adjacent, std::array<NoiseSample, 3>& blockOffsets);
|
||||
private:
|
||||
BlockDef& getBlockAt(const glm::ivec3 &pos);
|
||||
void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint);
|
||||
|
||||
unsigned int indOffset = 0;
|
||||
LocalDefinitionAtlas& defs;
|
||||
LocalBiomeAtlas& biomes;
|
||||
|
||||
ClientGame& defs;
|
||||
LocalDefinitionAtlas& atlas;
|
||||
MeshDetails* meshDetails;
|
||||
unsigned int indOffset = 0;
|
||||
ChunkMeshDetails* meshDetails;
|
||||
|
||||
std::shared_ptr<BlockChunk> chunk;
|
||||
std::array<std::shared_ptr<BlockChunk>, 6> adjacent;
|
||||
|
||||
};
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
};
|
|
@ -0,0 +1,126 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-06.
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <glm/gtx/normal.hpp>
|
||||
|
||||
#include "FarMeshGenerator.h"
|
||||
|
||||
#include "../FarMapMeshDetails.h"
|
||||
#include "../../../../util/Vec.h"
|
||||
#include "../../../../world/chunk/BlockChunk.h"
|
||||
|
||||
//FarMeshGenerator::FarMeshGenerator(LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
// std::vector<unsigned int>& blocks, unsigned int width) :
|
||||
//
|
||||
// defs(defs),
|
||||
// width(width),
|
||||
// blocks(blocks),
|
||||
// biomes(biomes) {
|
||||
//
|
||||
// meshDetails->vertices.reserve(5000);
|
||||
// meshDetails->indices.reserve(7000);
|
||||
//
|
||||
// const auto& blockData = chunk->cGetBlocks();
|
||||
// const auto& biomeData = chunk->cGetBiomes();
|
||||
//
|
||||
// unsigned short blockArrayPos = 0;
|
||||
// unsigned int cBlock = blockData[blockArrayPos + 1];
|
||||
// unsigned short biomeArrayPos = 0;
|
||||
// unsigned short cBiome = biomeData[biomeArrayPos + 1];
|
||||
//
|
||||
// glm::ivec3 off;
|
||||
// for (unsigned short i = 0; i < 4096; i++) {
|
||||
// if (blockArrayPos + 2 < blockData.size() && i >= blockData[blockArrayPos + 2]) {
|
||||
// blockArrayPos += 2;
|
||||
// cBlock = blockData[blockArrayPos + 1];
|
||||
// }
|
||||
// if (biomeArrayPos + 2 < biomeData.size() && i >= biomeData[biomeArrayPos + 2]) {
|
||||
// biomeArrayPos += 2;
|
||||
// cBiome = biomeData[biomeArrayPos + 1];
|
||||
// }
|
||||
//
|
||||
// BlockModel& model = defs.blockFromId(cBlock).model;
|
||||
// glm::vec3 biomeTint = biomes.biomeFromId(cBiome).biomeTint;
|
||||
//
|
||||
// if (!model.visible) continue;
|
||||
//
|
||||
// Vec::indAssignVec(i, off);
|
||||
// glm::vec3 vis = off;
|
||||
//
|
||||
// for (auto& mod : model.meshMods) {
|
||||
// switch (mod.first) {
|
||||
// default: break;
|
||||
//
|
||||
// case MeshMod::OFFSET_X:
|
||||
// vis.x += blockOffsets[0].get(off) * mod.second; break;
|
||||
// case MeshMod::OFFSET_Y:
|
||||
// vis.y += blockOffsets[1].get(off) * mod.second; break;
|
||||
// case MeshMod::OFFSET_Z:
|
||||
// vis.z += blockOffsets[2].get(off) * mod.second; break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!getBlockAt({off.x - 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
|
||||
// if (!getBlockAt({off.x + 1, off.y, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
|
||||
// if (!getBlockAt({off.x, off.y - 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
|
||||
// if (!getBlockAt({off.x, off.y + 1, off.z}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
|
||||
// if (!getBlockAt({off.x, off.y, off.z - 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
|
||||
// if (!getBlockAt({off.x, off.y, off.z + 1}).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
|
||||
//
|
||||
// addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
|
||||
// }
|
||||
//
|
||||
// meshDetails->vertices.shrink_to_fit();
|
||||
// meshDetails->indices.shrink_to_fit();
|
||||
//}
|
||||
//
|
||||
//BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
|
||||
// if (pos.x == 16) return defs.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
|
||||
// if (pos.x == -1) return defs.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
|
||||
//
|
||||
// if (pos.y == 16) return defs.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
|
||||
// if (pos.y == -1) return defs.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
|
||||
//
|
||||
// if (pos.z == 16) return defs.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
|
||||
// if (pos.z == -1) return defs.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
|
||||
//
|
||||
// return defs.blockFromId(chunk->getBlock(pos));
|
||||
//}
|
||||
//
|
||||
//void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
|
||||
// for (const MeshPart& mp : meshParts) {
|
||||
// glm::vec3 modData = {};
|
||||
//
|
||||
// switch (mp.shaderMod) {
|
||||
// default: break;
|
||||
//
|
||||
// case ShaderMod::ROTATE_X:
|
||||
// case ShaderMod::ROTATE_Y:
|
||||
// case ShaderMod::ROTATE_Z:
|
||||
// case ShaderMod::SWAY_ATTACHED:
|
||||
// case ShaderMod::SWAY_FULL_BLOCK:
|
||||
// modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// for (const BlockModelVertex &vertex : mp.vertices) {
|
||||
// meshDetails->vertices.push_back({
|
||||
// vertex.pos + offset,
|
||||
// vertex.tex,
|
||||
// (mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
|
||||
// (mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
|
||||
// Util::packFloat(vertex.nml),
|
||||
// static_cast<float>(mp.shaderMod),
|
||||
// modData
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// for (unsigned int index : mp.indices) {
|
||||
// meshDetails->indices.push_back(indOffset + index);
|
||||
// }
|
||||
//
|
||||
// indOffset += mp.vertices.size();
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Created by aurailus on 2020-04-06.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#include "../../../../def/ClientGame.h"
|
||||
#include "../../../../def/gen/NoiseSample.h"
|
||||
|
||||
class FarMapMeshDetails;
|
||||
|
||||
//class FarMeshGenerator {
|
||||
//public:
|
||||
// FarMeshGenerator(LocalDefinitionAtlas& defs, LocalBiomeAtlas& biomes,
|
||||
// std::vector<unsigned int>& blocks, unsigned int width);
|
||||
//private:
|
||||
// BlockDef& getBlockAt(const glm::ivec3 &pos);
|
||||
// void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint);
|
||||
//
|
||||
// LocalDefinitionAtlas& defs;
|
||||
// LocalBiomeAtlas& biomes;
|
||||
//
|
||||
// unsigned int indOffset = 0;
|
||||
// FarMapMeshDetails* meshDetails;
|
||||
//
|
||||
// unsigned int width;
|
||||
// std::vector<unsigned int>& blocks;
|
||||
//};
|
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// Created by aurailus on 2020-03-26.
|
||||
//
|
||||
|
||||
#include "MeshFarMap.h"
|
|
@ -0,0 +1,9 @@
|
|||
//
|
||||
// Created by aurailus on 2020-03-26.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
class MeshFarMap {
|
||||
|
||||
};
|
|
@ -1,152 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 01/12/18.
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <glm/gtx/normal.hpp>
|
||||
|
||||
#include "MeshGenerator.h"
|
||||
|
||||
#include "../MeshDetails.h"
|
||||
#include "../../../../util/Vec.h"
|
||||
#include "../../../../util/Timer.h"
|
||||
#include "../../../../world/chunk/BlockChunk.h"
|
||||
|
||||
MeshGenerator::MeshGenerator(MeshDetails* meshDetails, ClientGame& defs, std::shared_ptr<BlockChunk> chunk,
|
||||
std::array<std::shared_ptr<BlockChunk>, 6> adjacent,
|
||||
std::array<NoiseSample, 3>& blockOffsets, bool hi) :
|
||||
|
||||
defs(defs),
|
||||
chunk(chunk),
|
||||
atlas(defs.defs),
|
||||
adjacent(adjacent),
|
||||
meshDetails(meshDetails) {
|
||||
|
||||
meshDetails->vertices.reserve(5000);
|
||||
meshDetails->indices.reserve(7000);
|
||||
|
||||
Timer t("ChunkMesh Generation");
|
||||
|
||||
glm::ivec3 off;
|
||||
glm::vec3 vis;
|
||||
glm::vec3 check;
|
||||
|
||||
const auto& blocks = chunk->cGetBlocks();
|
||||
const auto& biomes = chunk->cGetBiomes();
|
||||
|
||||
unsigned short blockArrayPos = 0;
|
||||
unsigned int cBlock = blocks[blockArrayPos + 1];
|
||||
unsigned short biomeArrayPos = 0;
|
||||
unsigned short cBiome = biomes[biomeArrayPos + 1];
|
||||
|
||||
for (unsigned short i = 0; i < 4096; i++) {
|
||||
if (blockArrayPos + 2 < blocks.size() && i >= blocks[blockArrayPos + 2]) {
|
||||
blockArrayPos += 2;
|
||||
cBlock = blocks[blockArrayPos + 1];
|
||||
}
|
||||
if (biomeArrayPos + 2 < biomes.size() && i >= biomes[biomeArrayPos + 2]) {
|
||||
biomeArrayPos += 2;
|
||||
cBiome = biomes[biomeArrayPos + 1];
|
||||
}
|
||||
|
||||
BlockModel& model = hi ? atlas.blockFromId(cBlock).model : atlas.blockFromId(cBlock).farModel;
|
||||
glm::vec3 biomeTint = defs.biomes.biomeFromId(cBiome).biomeTint;
|
||||
|
||||
if (model.visible) {
|
||||
Vec::indAssignVec(i, off);
|
||||
|
||||
vis = off;
|
||||
|
||||
for (auto& mod : model.meshMods) {
|
||||
switch (mod.first) {
|
||||
default: break;
|
||||
|
||||
case MeshMod::OFFSET_X: {
|
||||
vis.x += blockOffsets[0].get(off) * mod.second;
|
||||
break;
|
||||
}
|
||||
case MeshMod::OFFSET_Y: {
|
||||
vis.y += blockOffsets[1].get(off) * mod.second;
|
||||
break;
|
||||
}
|
||||
case MeshMod::OFFSET_Z: {
|
||||
vis.z += blockOffsets[2].get(off) * mod.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model.visible) {
|
||||
check = off; check.x -= 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint);
|
||||
check = off; check.x += 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint);
|
||||
check = off; check.y -= 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint);
|
||||
check = off; check.y += 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint);
|
||||
check = off; check.z -= 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint);
|
||||
check = off; check.z += 1;
|
||||
if (!getBlockAt(check).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint);
|
||||
|
||||
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meshDetails->vertices.shrink_to_fit();
|
||||
meshDetails->indices.shrink_to_fit();
|
||||
}
|
||||
|
||||
BlockDef& MeshGenerator::getBlockAt(const glm::ivec3 &pos) {
|
||||
if (pos.x < 0 || pos.x >= 16 || pos.y < 0 || pos.y >= 16 || pos.z < 0 || pos.z >= 16) {
|
||||
if (pos.x == 16) return atlas.blockFromId(adjacent[0]->getBlock(pos - glm::ivec3 {16, 0, 0}));
|
||||
if (pos.x == -1) return atlas.blockFromId(adjacent[1]->getBlock(pos + glm::ivec3 {16, 0, 0}));
|
||||
|
||||
if (pos.y == 16) return atlas.blockFromId(adjacent[2]->getBlock(pos - glm::ivec3 {0, 16, 0}));
|
||||
if (pos.y == -1) return atlas.blockFromId(adjacent[3]->getBlock(pos + glm::ivec3 {0, 16, 0}));
|
||||
|
||||
if (pos.z == 16) return atlas.blockFromId(adjacent[4]->getBlock(pos - glm::ivec3 {0, 0, 16}));
|
||||
if (pos.z == -1) return atlas.blockFromId(adjacent[5]->getBlock(pos + glm::ivec3 {0, 0, 16}));
|
||||
}
|
||||
|
||||
return atlas.blockFromId(chunk->getBlock(pos));
|
||||
}
|
||||
|
||||
void MeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
|
||||
for (const MeshPart& mp : meshParts) {
|
||||
glm::vec3 modData = {};
|
||||
|
||||
switch (mp.shaderMod) {
|
||||
default: break;
|
||||
|
||||
case ShaderMod::ROTATE_X:
|
||||
case ShaderMod::ROTATE_Y:
|
||||
case ShaderMod::ROTATE_Z:
|
||||
case ShaderMod::SWAY_ATTACHED:
|
||||
case ShaderMod::SWAY_FULL_BLOCK: {
|
||||
modData = {Util::packFloat((offset - 8.f) / 8.f), mp.modValue, 0};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const BlockModelVertex &vertex : mp.vertices) {
|
||||
meshDetails->vertices.push_back({
|
||||
vertex.pos + offset,
|
||||
vertex.tex,
|
||||
(mp.blendInd ? tint : glm::vec3 {1, 1, 1}),
|
||||
(mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1}),
|
||||
Util::packFloat(vertex.nml),
|
||||
static_cast<float>(mp.shaderMod),
|
||||
modData
|
||||
});
|
||||
}
|
||||
|
||||
for (unsigned int index : mp.indices) {
|
||||
meshDetails->indices.push_back(indOffset + index);
|
||||
}
|
||||
|
||||
indOffset += mp.vertices.size();
|
||||
}
|
||||
}
|
|
@ -11,13 +11,14 @@
|
|||
#include "../util/net/PacketView.h"
|
||||
|
||||
Server::Server(unsigned short port, const std::string& subgame) :
|
||||
seed(27),
|
||||
port(port),
|
||||
config(defs),
|
||||
defs(subgame),
|
||||
defs(subgame, seed),
|
||||
clientList(defs),
|
||||
handler(port, 32),
|
||||
refs(defs.defs, &clientList),
|
||||
world(10, defs, clientList) {
|
||||
world(seed, defs, clientList) {
|
||||
|
||||
defs.init(world);
|
||||
world.init();
|
||||
|
|
|
@ -27,6 +27,9 @@ public:
|
|||
private:
|
||||
bool alive = true;
|
||||
|
||||
unsigned int seed = 0;
|
||||
unsigned short port = 0;
|
||||
|
||||
ServerGame defs;
|
||||
ServerWorld world;
|
||||
NetHandler handler;
|
||||
|
@ -38,7 +41,5 @@ private:
|
|||
|
||||
double elapsedSeconds = 0;
|
||||
double deltaTime = 0;
|
||||
|
||||
unsigned short port = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,17 +8,17 @@
|
|||
#include "../../util/net/PacketView.h"
|
||||
#include "../../util/net/Serializer.h"
|
||||
|
||||
ServerConfig::ServerConfig(ServerGame &defs) : defs(defs) {}
|
||||
ServerConfig::ServerConfig(ServerGame &defs) : game(defs) {}
|
||||
|
||||
void ServerConfig::init() {
|
||||
blockIdentifierList.reserve(static_cast<unsigned long>(defs.defs.size()));
|
||||
for (unsigned int i = 0; i < defs.defs.size(); i++) {
|
||||
blockIdentifierList.push_back(defs.defs.fromId(i).identifier);
|
||||
blockIdentifierList.reserve(static_cast<unsigned long>(game.defs.size()));
|
||||
for (unsigned int i = 0; i < game.defs.size(); i++) {
|
||||
blockIdentifierList.push_back(game.defs.fromId(i).identifier);
|
||||
}
|
||||
|
||||
biomeIdentifierList.reserve(static_cast<unsigned long>(defs.biomes.size()));
|
||||
for (unsigned int i = 0; i < defs.biomes.size(); i++) {
|
||||
biomeIdentifierList.push_back(defs.biomes.biomeFromId(i).identifier);
|
||||
biomeIdentifierList.reserve(static_cast<unsigned long>(game.biomes.size()));
|
||||
for (unsigned int i = 0; i < game.biomes.size(); i++) {
|
||||
biomeIdentifierList.push_back(game.biomes.biomeFromId(i).identifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,14 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
|
|||
return true;
|
||||
}
|
||||
|
||||
case PacketType::SERVER_INFO: {
|
||||
Serializer()
|
||||
.append(game.biomes.seed)
|
||||
.packet(PacketType::SERVER_INFO)
|
||||
.sendTo(client.peer, PacketChannel::CONNECT);
|
||||
break;
|
||||
}
|
||||
|
||||
case PacketType::BLOCK_IDENTIFIER_LIST: {
|
||||
Serializer()
|
||||
.append(blockIdentifierList)
|
||||
|
@ -46,7 +54,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
|
|||
}
|
||||
|
||||
case PacketType::MODS: {
|
||||
defs.parser.sendModsPacket(client.peer);
|
||||
game.parser.sendModsPacket(client.peer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -56,7 +64,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
|
|||
|
||||
Serializer s {};
|
||||
|
||||
for (ServerTexture& texture : defs.assets.textures) {
|
||||
for (ServerTexture& texture : game.assets.textures) {
|
||||
if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
|
||||
s.append(static_cast<int>(AssetType::END));
|
||||
Packet p(PacketType::MEDIA);
|
||||
|
@ -77,7 +85,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
|
|||
packetSize += texture.data.length() + 20;
|
||||
}
|
||||
|
||||
for (SerializedModel& model : defs.assets.models) {
|
||||
for (SerializedModel& model : game.assets.models) {
|
||||
if (packetSize + 16 + model.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
|
||||
s.append(static_cast<int>(AssetType::END));
|
||||
Packet p(PacketType::MEDIA);
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
//Bool: Create player
|
||||
bool handlePacket(ServerClient &client, PacketView& p);
|
||||
private:
|
||||
ServerGame& defs;
|
||||
ServerGame& game;
|
||||
std::vector<std::string> blockIdentifierList {};
|
||||
std::vector<std::string> biomeIdentifierList {};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// Created by aurailus on 06/03/19.
|
||||
//
|
||||
|
||||
#include "ServerGenStream.h"
|
||||
|
||||
#include "../../def/ServerGame.h"
|
||||
|
||||
ServerGenStream::ServerGenStream(unsigned int seed, ServerGame& game) :
|
||||
props(std::make_shared<MapGenProps>(seed)),
|
||||
gen(seed, game.defs, game.biomes, props) {
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) threads.emplace_back(&gen);
|
||||
}
|
||||
|
||||
bool ServerGenStream::queue(glm::vec3 pos) {
|
||||
if (!queuedMap.count(pos)) {
|
||||
queuedTasks.push_back(pos);
|
||||
queuedMap.insert(pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> ServerGenStream::update() {
|
||||
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
|
||||
|
||||
for (auto& t : threads) {
|
||||
for (auto& u : t.tasks) {
|
||||
if (u.locked) continue;
|
||||
|
||||
if (!u.chunks.empty()) {
|
||||
for (auto chunk : u.chunks)
|
||||
finishedChunks->push_back(std::shared_ptr<BlockChunk>(chunk.second.second));
|
||||
u.chunks.clear();
|
||||
}
|
||||
|
||||
if (!queuedTasks.empty()) {
|
||||
auto it = queuedTasks.begin();
|
||||
glm::vec3 pos = *it;
|
||||
queuedTasks.erase(it);
|
||||
queuedMap.erase(pos);
|
||||
|
||||
u.pos = pos;
|
||||
u.locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finishedChunks;
|
||||
}
|
||||
|
||||
ServerGenStream::Thread::Thread(MapGen *gen) : gen(gen) {
|
||||
thread = std::thread(ServerGenStream::threadFunction, this);
|
||||
thread.detach();
|
||||
}
|
||||
|
||||
void ServerGenStream::threadFunction(ServerGenStream::Thread *thread) {
|
||||
while (!thread->kill) {
|
||||
|
||||
bool empty = true;
|
||||
for (Job& u : thread->tasks) {
|
||||
if (u.locked) {
|
||||
empty = false;
|
||||
u.chunks = thread->gen->generateMapBlock(u.pos);
|
||||
u.locked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
ServerGenStream::~ServerGenStream() {
|
||||
for (auto& t : threads) {
|
||||
t.kill = true;
|
||||
t.thread.join();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Created by aurailus on 06/03/19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "../../def/gen/MapGen.h"
|
||||
|
||||
class ServerGame;
|
||||
|
||||
class ServerGenStream {
|
||||
public:
|
||||
static const int THREADS = 4;
|
||||
static const int THREAD_QUEUE_SIZE = 6;
|
||||
|
||||
explicit ServerGenStream(unsigned int seed, ServerGame& game);
|
||||
~ServerGenStream();
|
||||
|
||||
// Add the MapBlock position `pos` to the generation queue.
|
||||
bool queue(glm::vec3 pos);
|
||||
// Returns a vector of BlockChunks that have finished generating,
|
||||
// and gives the threads new data to work with.
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
|
||||
|
||||
private:
|
||||
struct Job {
|
||||
bool locked = false;
|
||||
|
||||
glm::ivec3 pos {};
|
||||
MapGen::chunk_partials_map chunks {};
|
||||
};
|
||||
|
||||
struct Thread {
|
||||
explicit Thread(MapGen* gen);
|
||||
std::thread thread;
|
||||
bool kill = false;
|
||||
|
||||
MapGen* gen;
|
||||
std::vector<Job> tasks = std::vector<Job>(THREAD_QUEUE_SIZE);
|
||||
};
|
||||
|
||||
// Function that occurs on the threads.
|
||||
static void threadFunction(Thread* thread);
|
||||
|
||||
std::shared_ptr<MapGenProps> props;
|
||||
MapGen gen;
|
||||
|
||||
std::vector<Thread> threads;
|
||||
std::list<glm::vec3> queuedTasks;
|
||||
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
|
||||
};
|
|
@ -2,17 +2,14 @@
|
|||
// Created by aurailus on 05/03/19.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <glm/glm.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "WorldGenStream.h"
|
||||
#include "../conn/ServerClient.h"
|
||||
#include "../../world/chunk/BlockChunk.h"
|
||||
#include "../../util/Vec.h"
|
||||
|
||||
#include "ServerWorld.h"
|
||||
|
||||
#include "ServerGenStream.h"
|
||||
#include "../conn/ServerClient.h"
|
||||
|
||||
ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& clients) :
|
||||
clientList(clients),
|
||||
seed(seed),
|
||||
|
@ -37,23 +34,12 @@ ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& client
|
|||
}
|
||||
|
||||
void ServerWorld::init() {
|
||||
genStream = std::make_unique<WorldGenStream>(seed, defs);
|
||||
genStream = std::make_unique<ServerGenStream>(seed, defs);
|
||||
}
|
||||
|
||||
void ServerWorld::update(double delta) {
|
||||
dimension.update(clientList.clients);
|
||||
|
||||
while (!generateQueueList.empty()) {
|
||||
auto it = generateQueueList.begin();
|
||||
glm::vec3 pos = *it;
|
||||
|
||||
if (genStream->tryToQueue(pos)) {
|
||||
generateQueueList.erase(it);
|
||||
generateQueueMap.erase(pos);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
auto finished = genStream->update();
|
||||
generatedChunks = static_cast<int>(finished->size());
|
||||
|
||||
|
@ -147,11 +133,9 @@ void ServerWorld::changedChunks(ServerClient& client) {
|
|||
}
|
||||
|
||||
bool ServerWorld::generateMapBlock(glm::ivec3 pos) {
|
||||
if(!generateQueueMap.count(pos) && (!dimension.getMapBlock(pos) || !dimension.getMapBlock(pos)->generated)) {
|
||||
generateQueueMap.insert(pos);
|
||||
generateQueueList.push_back(pos);
|
||||
return true;
|
||||
}
|
||||
if(!dimension.getMapBlock(pos) || !dimension.getMapBlock(pos)->generated)
|
||||
return genStream->queue(pos);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "WorldGenStream.h"
|
||||
#include "ServerGenStream.h"
|
||||
#include "../conn/ClientList.h"
|
||||
#include "../../def/ServerGame.h"
|
||||
#include "../../game/scene/world/World.h"
|
||||
|
@ -36,10 +36,7 @@ private:
|
|||
|
||||
static bool isInBounds(glm::ivec3 pos, std::pair<glm::ivec3, glm::ivec3>& bounds);
|
||||
|
||||
std::unique_ptr<WorldGenStream> genStream = nullptr;
|
||||
|
||||
std::unordered_set<glm::vec3, Vec::vec3> generateQueueMap;
|
||||
std::vector<glm::vec3> generateQueueList;
|
||||
std::unique_ptr<ServerGenStream> genStream = nullptr;
|
||||
|
||||
unsigned int seed;
|
||||
ServerGame& defs;
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 06/03/19.
|
||||
//
|
||||
|
||||
#include "WorldGenStream.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
|
||||
WorldGenStream::WorldGenStream(unsigned int seed, ServerGame& atlas) : gen(seed, atlas.defs, atlas.biomes) {
|
||||
queuedTasks.reserve((unsigned long) TOTAL_QUEUE_SIZE);
|
||||
|
||||
threads.reserve(THREADS);
|
||||
for (int i = 0; i < THREADS; i++) {
|
||||
threads.emplace_back(&gen);
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldGenStream::tryToQueue(glm::vec3 pos) {
|
||||
unsigned long sizeOfQueue = queuedTasks.size();
|
||||
|
||||
if (sizeOfQueue < TOTAL_QUEUE_SIZE && !queuedMap.count(pos)) {
|
||||
queuedTasks.push_back(pos);
|
||||
queuedMap.insert(pos);
|
||||
}
|
||||
|
||||
return sizeOfQueue + 1 < TOTAL_QUEUE_SIZE;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> WorldGenStream::update() {
|
||||
auto finishedChunks = std::make_unique<std::vector<std::shared_ptr<BlockChunk>>>();
|
||||
|
||||
for (auto& t : threads) {
|
||||
for (auto& u : t.tasks) {
|
||||
if (!u.unlocked) continue;
|
||||
|
||||
if (!u.chunks.empty()) {
|
||||
for (auto chunk : u.chunks) {
|
||||
finishedChunks->push_back(std::shared_ptr<BlockChunk>(chunk.second.second));
|
||||
}
|
||||
u.chunks.clear();
|
||||
}
|
||||
|
||||
if (!queuedTasks.empty()) {
|
||||
auto it = queuedTasks.begin();
|
||||
glm::vec3 pos = *it;
|
||||
queuedTasks.erase(it);
|
||||
queuedMap.erase(pos);
|
||||
|
||||
u.pos = pos;
|
||||
//Lock it in to allow the thread to edit it.
|
||||
u.unlocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finishedChunks;
|
||||
}
|
||||
|
||||
WorldGenStream::Thread::Thread(MapGen *gen) {
|
||||
this->gen = gen;
|
||||
|
||||
thread = std::thread(WorldGenStream::threadFunction, this);
|
||||
thread.detach();
|
||||
}
|
||||
|
||||
void WorldGenStream::threadFunction(WorldGenStream::Thread *thread) {
|
||||
while (thread->keepAlive) {
|
||||
|
||||
bool empty = true;
|
||||
for (Unit& u : thread->tasks) {
|
||||
if (!u.unlocked) {
|
||||
empty = false;
|
||||
u.chunks = thread->gen->generateMapBlock(u.pos);
|
||||
u.unlocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorldGenStream::~WorldGenStream() {
|
||||
for (auto& t : threads) {
|
||||
t.keepAlive = false;
|
||||
t.thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// Created by aurailus on 06/03/19.
|
||||
//
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include "../../util/Vec.h"
|
||||
#include "../../def/gen/MapGen.h"
|
||||
#include "../../world/chunk/BlockChunk.h"
|
||||
#include "../../def/ServerGame.h"
|
||||
|
||||
class WorldGenStream {
|
||||
public:
|
||||
static const int THREAD_QUEUE_SIZE = 6;
|
||||
static const int THREADS = 4;
|
||||
static const int TOTAL_QUEUE_SIZE = THREADS * THREAD_QUEUE_SIZE;
|
||||
|
||||
explicit WorldGenStream(unsigned int seed, ServerGame& defs);
|
||||
~WorldGenStream();
|
||||
|
||||
//Attempt to add `pos` to the pre-thread queue.
|
||||
//Will return a boolean stating if there is more space left in the queue.
|
||||
bool tryToQueue(glm::vec3 pos);
|
||||
|
||||
//Will return a vector of BlockChunk pointers containing finished chunks.
|
||||
//Frees up the threads and starts new units.
|
||||
std::unique_ptr<std::vector<std::shared_ptr<BlockChunk>>> update();
|
||||
|
||||
struct Unit {
|
||||
glm::ivec3 pos {};
|
||||
MapGen::chunk_partials_map chunks {};
|
||||
|
||||
bool unlocked = true;
|
||||
};
|
||||
|
||||
struct Thread {
|
||||
explicit Thread(MapGen* gen);
|
||||
|
||||
MapGen* gen;
|
||||
|
||||
std::thread thread;
|
||||
bool keepAlive = true;
|
||||
|
||||
std::vector<Unit> tasks = std::vector<Unit>(THREAD_QUEUE_SIZE);
|
||||
};
|
||||
|
||||
std::vector<Thread> threads;
|
||||
private:
|
||||
static void threadFunction(Thread* thread);
|
||||
|
||||
MapGen gen;
|
||||
std::vector<glm::vec3> queuedTasks;
|
||||
std::unordered_set<glm::vec3, Vec::vec3> queuedMap;
|
||||
};
|
||||
|
||||
#pragma clang diagnostic pop
|
|
@ -29,11 +29,11 @@ namespace Vec {
|
|||
glm::ivec3 {0, 0, 1}, glm::ivec3 {0, 0, -1}
|
||||
};
|
||||
|
||||
static inline void indAssignVec(int ind, glm::ivec3& vec) {
|
||||
vec.z = ind / (16 * 16);
|
||||
ind -= ((int)vec.z * 16 * 16);
|
||||
vec.y = ind / 16;
|
||||
vec.x = ind % 16;
|
||||
static inline void indAssignVec(int ind, glm::ivec3& vec, unsigned int wid = 16) {
|
||||
vec.z = ind / (wid * wid);
|
||||
ind -= ((int)vec.z * wid * wid);
|
||||
vec.y = ind / wid;
|
||||
vec.x = ind % wid;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ void LocalDimension::finishMeshes() {
|
|||
lastMeshUpdates = 0;
|
||||
auto finishedMeshes = meshGenStream->update();
|
||||
|
||||
for (MeshDetails* meshDetails : finishedMeshes) {
|
||||
for (ChunkMeshDetails* meshDetails : finishedMeshes) {
|
||||
|
||||
if (!meshDetails->vertices.empty()) {
|
||||
auto meshChunk = std::make_shared<MeshChunk>();
|
||||
|
|
|
@ -17,6 +17,6 @@ zepha.register_entity("zeus:default:test", {
|
|||
}
|
||||
})
|
||||
|
||||
if (zepha.server) {
|
||||
local entity = zepha.add_entity("zeus:default:test", V(0, 0, 0))
|
||||
}
|
||||
##if (zepha.server) {
|
||||
## local entity = zepha.add_entity("zeus:default:test", V(0, 0, 0))
|
||||
##}
|
|
@ -1,7 +1,7 @@
|
|||
zepha.register_item("zeus:materials:flint", {
|
||||
name = "Flint",
|
||||
textures = {
|
||||
"zeus:materials:flint_outlined",
|
||||
"zeus:materials:flint",
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
zepha.register_item("zeus:materials:plant_fibre", {
|
||||
name = "Plant Fibre",
|
||||
textures = {
|
||||
"zeus:materials:plant_fibre_outlined"
|
||||
"zeus:materials:plant_fibre"
|
||||
},
|
||||
groups = {
|
||||
organic = 1,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
zepha.register_item("zeus:materials:plant_twine", {
|
||||
name = "Plant Twine",
|
||||
textures = {
|
||||
"zeus:materials:plant_twine_outlined"
|
||||
"zeus:materials:plant_twine"
|
||||
},
|
||||
groups = {
|
||||
rope = 1,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
zepha.register_item("zeus:materials:rock", {
|
||||
name = "Rock",
|
||||
textures = {
|
||||
"zeus:materials:rock_outlined"
|
||||
"zeus:materials:rock"
|
||||
},
|
||||
groups = {
|
||||
rock = 1,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
zepha.register_item("zeus:materials:stick", {
|
||||
name = "Stick",
|
||||
textures = {
|
||||
"zeus:materials:stick_outlined",
|
||||
"zeus:materials:stick",
|
||||
## "zeus:materials:stick_1_outlined",
|
||||
## "zeus:materials:stick_2_outlined",
|
||||
## "zeus:materials:stick_3_outlined"
|
||||
|
|
Loading…
Reference in New Issue