COLORED LIGHTING~

master
Nicole Collings 2020-05-12 17:16:11 -07:00
parent a9a13b73c6
commit 49b45d1b9e
30 changed files with 444 additions and 154 deletions

View File

@ -4,11 +4,12 @@ layout (location = 0) out vec4 gPosition;
layout (location = 1) out vec4 gNormal;
layout (location = 2) out vec4 gSpecular;
in vec2 texCoords;
in vec2 blendMaskCoords;
in vec3 blend;
in vec3 fragPos;
in vec3 normal;
in vec2 texCoords;
in vec2 blendMaskCoords;
in vec3 blend;
in vec3 fragPos;
in vec3 normal;
in vec3 light;
uniform float time;
@ -16,6 +17,7 @@ uniform sampler2D tex;
void main() {
float blendMaskMult = -1;
if (blendMaskCoords.x >= 0 && blendMaskCoords.y >= 0) blendMaskMult = texture(tex, blendMaskCoords).r;
vec4 spec = texture(tex, texCoords);
@ -24,7 +26,7 @@ void main() {
blendCol = (vec3(1, 1, 1) * (1 - blendMaskMult)) + (blendCol * blendMaskMult);
}
spec = vec4(spec.xyz * blendCol, spec.w);
spec = vec4(spec.xyz * blendCol * light, spec.a);
if (spec.a < 0.1) discard;

View File

@ -1,28 +1,31 @@
#version 330 core
#define TAU 6.28318530718
#define MAX_BLOCKLIGHT 31
#define MAX_SUNLIGHT 15
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
layout (location = 2) in vec3 aBlend;
layout (location = 3) in vec2 aBlendMaskCoords;
layout (location = 4) in float aNormal;
layout (location = 5) in float aShaderMod;
layout (location = 6) in vec3 aModValues;
layout (location = 5) in vec4 aLight;
layout (location = 6) in float aShaderMod;
layout (location = 7) in vec3 aModValues;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
uniform sampler2D swayTex;
uniform float time;
out vec2 texCoords;
out vec2 blendMaskCoords;
out vec3 blend;
out vec3 fragPos;
out vec3 normal;
out vec2 texCoords;
out vec2 blendMaskCoords;
out vec3 blend;
out vec3 fragPos;
out vec3 normal;
out vec3 light;
vec3 unpackFloat(float src) {
return vec3(fract(src) * 2.0f - 1.0f, fract(src * 256.f) * 2.0f - 1.0f, fract(src * 65536.f) * 2.0f - 1.0f);
@ -88,6 +91,12 @@ void main() {
}
}
float sunlightIntensity = aLight.w * clamp(sin(time * 10.5) + 0.25, 0, 1) / MAX_SUNLIGHT;
vec3 blockLightColor = (aLight.xyz / MAX_BLOCKLIGHT) * vec3(1 + sunlightIntensity / 4);
vec3 sunlightColor = clamp(sunlightIntensity * 1.25 * vec3(1, 0.8, 0.9), 0, 1);
vec3 resultantLight = vec3(max(sunlightColor.x, blockLightColor.x), max(sunlightColor.y, blockLightColor.y), max(sunlightColor.z, blockLightColor.z));
vec4 worldPos = model * pos;
fragPos = (view * worldPos).xyz;
@ -95,6 +104,6 @@ void main() {
blendMaskCoords = aBlendMaskCoords;
blend = aBlend;
normal = nml.xyz;
light = resultantLight;
gl_Position = projection * view * worldPos;
}

View File

@ -7,13 +7,13 @@
LocalDefinitionAtlas::LocalDefinitionAtlas(TextureAtlas& atlas) {
//Invalid Node
BlockModel invalidModel = BlockModel::createCube({atlas["_missing"]}, {}, {});
BlockDef* invalid = new BlockDef("invalid", 0, "Invalid (you broke the game!)", 1, invalidModel, invalidModel, true, {{}}, {{}});
BlockDef* invalid = new BlockDef("invalid", "Invalid (you broke the game!)", 1, invalidModel, invalidModel, true, {}, {{}}, {{}});
defs.push_back(invalid);
defTable.insert({"invalid", 0});
//Air Node
BlockModel nullModel {};
BlockDef* air = new BlockDef("air", 0, "Air", 1, nullModel, nullModel, false, {}, {});
BlockDef* air = new BlockDef("air", "Air", 1, nullModel, nullModel, false, {}, {}, {});
defs.push_back(air);
defTable.insert({"air", 1});
}

View File

@ -8,12 +8,12 @@ ServerDefinitionAtlas::ServerDefinitionAtlas() {
//Invalid Node
BlockModel invalidModel = BlockModel::createCube({}, {}, {});
BlockDef* invalid = new BlockDef("invalid", INVALID, "Invalid (you broke the game!)", 1, invalidModel, invalidModel, true, {{}}, {{}});
BlockDef* invalid = new BlockDef("invalid", "Invalid (you broke the game!)", 1, invalidModel, invalidModel, true, {}, {{}}, {{}}, INVALID);
registerDef(invalid);
//Air Node
BlockModel nullModel {};
BlockDef* air = new BlockDef("air", AIR, "Air (you broke the game!)", 1, nullModel, nullModel, false, {}, {});
BlockDef* air = new BlockDef("air", "Air (you broke the game!)", 1, nullModel, nullModel, false, {}, {}, {}, AIR);
registerDef(air);
}

View File

@ -4,20 +4,25 @@
#include "BlockDef.h"
BlockDef::BlockDef(const std::string &identifier, const std::string& name, unsigned short maxStackSize,
const BlockModel &model, const BlockModel& farModel, bool solid, const std::vector<SelectionBox>& sBoxes,
const std::vector<SelectionBox>& cBoxes) :
BlockDef(identifier, 0, name, maxStackSize, model, farModel, solid, sBoxes, cBoxes) {}
BlockDef::BlockDef(const std::string& identifier, unsigned int index, const std::string& name,
unsigned short maxStackSize, const BlockModel& model, const BlockModel& farModel, bool solid,
const std::vector<SelectionBox>& sBoxes, const std::vector<SelectionBox>& cBoxes) :
BlockDef::BlockDef(
const std::string& identifier,
const std::string& name,
unsigned short maxStackSize,
const BlockModel& model,
const BlockModel& farModel,
bool solid,
glm::ivec3 lightSource,
const std::vector<SelectionBox>& sBoxes,
const std::vector<SelectionBox>& cBoxes,
unsigned int index) :
ItemDef {identifier, name, index, maxStackSize, ItemDef::Type::BLOCK},
model(model),
farModel(farModel),
culls(model.culls),
solid(solid),
lightSource(lightSource),
sBoxes(sBoxes),
cBoxes(cBoxes) {}

View File

@ -15,21 +15,29 @@
class BlockDef : public ItemDef {
public:
BlockDef() = default;
BlockDef(const std::string& identifier, const std::string& name, unsigned short maxStackSize,
const BlockModel& model, const BlockModel& farModel, bool solid, const std::vector<SelectionBox>& sBoxes,
const std::vector<SelectionBox>& cBoxes);
BlockDef(const std::string& identifier, unsigned int index, const std::string& name,
unsigned short maxStackSize, const BlockModel& model, const BlockModel& farModel, bool solid,
const std::vector<SelectionBox>& sBoxes, const std::vector<SelectionBox>& cBoxes);
BlockDef(
const std::string& identifier,
const std::string& name,
unsigned short maxStackSize,
const BlockModel& model,
const BlockModel& farModel,
bool solid,
glm::ivec3 lightSource,
const std::vector<SelectionBox>& sBoxes,
const std::vector<SelectionBox>& cBoxes,
unsigned int index = 0
);
void createModel();
BlockModel model, farModel;
BlockModel model;
BlockModel farModel;
bool culls = false;
bool solid = false;
glm::ivec3 lightSource;
std::vector<SelectionBox> sBoxes;
std::vector<SelectionBox> cBoxes;

View File

@ -2,11 +2,9 @@
// Created by aurailus on 25/11/18.
//
#include "ChunkMesh.h"
#include <vector>
ChunkMesh::ChunkMesh(const ChunkMesh &o) {
throw "Copy constructor for ChunkMesh is not supported! Throwing.";
}
#include "ChunkMesh.h"
void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices) {
indCount = static_cast<GLsizei>(indices.size());
@ -21,6 +19,7 @@ void ChunkMesh::create(const std::vector<ChunkVertex>& vertices, const std::vect
createVertexAttrib(idx++, 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendColor));
createVertexAttrib(idx++, 2, GL_FLOAT, STRIDE_OFFSET_CHUNK(blendMaskCoords));
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(normal));
createVertexAttrib(idx++, 4, GL_FLOAT, STRIDE_OFFSET_CHUNK(light));
createVertexAttrib(idx++, 1, GL_FLOAT, STRIDE_OFFSET_CHUNK(shaderMod));
createVertexAttrib(idx , 3, GL_FLOAT, STRIDE_OFFSET_CHUNK(modValues));

View File

@ -4,14 +4,15 @@
#pragma once
#include <vector>
#include "Mesh.h"
#include "ChunkVertex.h"
class ChunkMesh : public Mesh {
public:
ChunkMesh() = default;
ChunkMesh(const ChunkMesh& o);
ChunkMesh(const ChunkMesh& o) { assert(false); };
void create(const std::vector<ChunkVertex>& vertices, const std::vector<unsigned int>& indices);
~ChunkMesh() = default;
};

View File

@ -4,8 +4,9 @@
#pragma once
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
struct ChunkVertex {
glm::vec3 position;
@ -13,6 +14,7 @@ struct ChunkVertex {
glm::vec3 blendColor;
glm::vec2 blendMaskCoords;
float normal;
glm::vec4 light;
float shaderMod;
glm::vec3 modValues;
};

View File

@ -64,21 +64,28 @@ ChunkMeshGenerator::ChunkMeshGenerator(ChunkMeshDetails* meshDetails, LocalDefin
}
}
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);
glm::ivec3 pos {};
pos = { off.x - 1, off.y, off.z };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XNEG)], biomeTint, getLightAt(pos));
pos = { off.x + 1, off.y, off.z };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::XPOS)], biomeTint, getLightAt(pos));
pos = { off.x, off.y - 1, off.z };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YNEG)], biomeTint, getLightAt(pos));
pos = { off.x, off.y + 1, off.z };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::YPOS)], biomeTint, getLightAt(pos));
pos = { off.x, off.y, off.z - 1 };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZNEG)], biomeTint, getLightAt(pos));
pos = { off.x, off.y, off.z + 1 };
if (!getBlockAt(pos).culls) addFaces(vis, model.parts[static_cast<int>(Dir::ZPOS)], biomeTint, getLightAt(pos));
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint);
addFaces(vis, model.parts[static_cast<int>(Dir::NO_CULL)], biomeTint, getLightAt(vis));
}
meshDetails->vertices.shrink_to_fit();
meshDetails->indices.shrink_to_fit();
}
BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
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}));
@ -91,7 +98,20 @@ BlockDef& ChunkMeshGenerator::getBlockAt(const glm::ivec3 &pos) {
return defs.blockFromId(chunk->getBlock(pos));
}
void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint) {
glm::vec4 ChunkMeshGenerator::getLightAt(const glm::ivec3& pos) {
if (pos.x == 16) return adjacent[0]->getLightVec(Space::Block::index(pos - glm::ivec3 {16, 0, 0}));
if (pos.x == -1) return adjacent[1]->getLightVec(Space::Block::index(pos + glm::ivec3 {16, 0, 0}));
if (pos.y == 16) return adjacent[2]->getLightVec(Space::Block::index(pos - glm::ivec3 {0, 16, 0}));
if (pos.y == -1) return adjacent[3]->getLightVec(Space::Block::index(pos + glm::ivec3 {0, 16, 0}));
if (pos.z == 16) return adjacent[4]->getLightVec(Space::Block::index(pos - glm::ivec3 {0, 0, 16}));
if (pos.z == -1) return adjacent[5]->getLightVec(Space::Block::index(pos + glm::ivec3 {0, 0, 16}));
return chunk->getLightVec(Space::Block::index(pos));
}
void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint, glm::vec4 light) {
for (const MeshPart& mp : meshParts) {
glm::vec3 modData = {};
@ -114,6 +134,7 @@ void ChunkMeshGenerator::addFaces(const glm::vec3 &offset, const std::vector<Mes
mp.blendInd ? tint : glm::vec3 {1, 1, 1},
mp.blendInd ? vertex.blendMask : glm::vec2 {-1, -1},
Util::packFloat(vertex.nml),
light,
static_cast<float>(mp.shaderMod),
modData
});

View File

@ -21,8 +21,10 @@ public:
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);
inline BlockDef& getBlockAt(const glm::ivec3& pos);
inline glm::vec4 getLightAt(const glm::ivec3& pos);
void addFaces(const glm::vec3 &offset, const std::vector<MeshPart> &meshParts, const glm::vec3& tint, glm::vec4 light);
LocalDefinitionAtlas& defs;
LocalBiomeAtlas& biomes;

View File

@ -265,6 +265,16 @@ namespace RegisterBlocks {
bool solid = blockTable.get_or("solid", true);
auto maxStack = blockTable.get_or("stack", 64);
glm::vec3 lightSource {};
if (blockTable.get<sol::optional<sol::table>>("light_source")) {
auto light = blockTable.get<sol::table>("light_source");
lightSource = { light[1], light[2], light[3] };
}
else if (blockTable.get_or<float>("light_source", -1) != -1) {
auto light = blockTable.get<float>("light_source");
lightSource = { light, light, light };
}
// Parse through selection boxes and collision boxes
auto selectionOpt = blockTable.get<sol::optional<sol::table>>("selection_box");
auto collisionOpt = blockTable.get<sol::optional<sol::table>>("collision_box");
@ -283,14 +293,15 @@ namespace RegisterBlocks {
std::pair<BlockModel, BlockModel> models = createBlockModel(blockTable, blockModels, atlas);
BlockDef *blockDef = new BlockDef(
identifier,
defs.size(),
*nameOpt,
maxStack,
models.first, models.second,
solid,
std::move(selectionBoxes),
std::move(collisionBoxes)
identifier,
*nameOpt,
maxStack,
models.first, models.second,
solid,
lightSource,
std::move(selectionBoxes),
std::move(collisionBoxes),
defs.size() // Index
);
// Create entity model

View File

@ -7,13 +7,14 @@
#include "ServerWorld.h"
#include "ServerGenStream.h"
#include "../conn/ClientList.h"
#include "../conn/ServerClient.h"
ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& clients) :
ServerWorld::ServerWorld(unsigned int seed, ServerGame& game, ClientList& clients) :
clientList(clients),
dimension(game),
seed(seed),
defs(defs) {
game(game) {
//Pregenerate chunk generation order
generateOrder.reserve(MB_GEN_H * 2 * MB_GEN_H * 2 * MB_GEN_V * 2);
@ -34,7 +35,7 @@ ServerWorld::ServerWorld(unsigned int seed, ServerGame& defs, ClientList& client
}
void ServerWorld::init() {
genStream = std::make_unique<ServerGenStream>(seed, defs);
genStream = std::make_unique<ServerGenStream>(seed, game);
}
void ServerWorld::update(double delta) {
@ -170,26 +171,21 @@ void ServerWorld::setBlock(glm::ivec3 pos, unsigned int block) {
auto oldBlock = getBlock(pos);
if (block == DefinitionAtlas::AIR) {
auto def = defs.defs.blockFromId(oldBlock);
auto def = game.defs.blockFromId(oldBlock);
if (def.callbacks.count(Callback::DESTRUCT)) {
def.callbacks[Callback::DESTRUCT](defs.parser.luaVec(pos));
def.callbacks[Callback::DESTRUCT](game.parser.luaVec(pos));
}
}
else {
auto def = defs.defs.blockFromId(block);
auto def = game.defs.blockFromId(block);
if (def.callbacks.count(Callback::CONSTRUCT)) {
def.callbacks[Callback::CONSTRUCT](defs.parser.luaVec(pos));
def.callbacks[Callback::CONSTRUCT](game.parser.luaVec(pos));
}
}
dimension.setBlock(pos, block);
Packet b(PacketType::BLOCK_SET);
b.data = Serializer()
.append(pos)
.append(block)
.data;
Packet b = Serializer().append(pos).append(block).packet(PacketType::BLOCK_SET);
auto chunkPos = Space::Chunk::world::fromBlock(pos);
for (auto &client : clientList.clients) {
@ -207,15 +203,15 @@ void ServerWorld::setBlock(glm::ivec3 pos, unsigned int block) {
}
if (block == DefinitionAtlas::AIR) {
auto def = defs.defs.blockFromId(oldBlock);
auto def = game.defs.blockFromId(oldBlock);
if (def.callbacks.count(Callback::AFTER_DESTRUCT)) {
def.callbacks[Callback::AFTER_DESTRUCT](defs.parser.luaVec(pos));
def.callbacks[Callback::AFTER_DESTRUCT](game.parser.luaVec(pos));
}
}
else {
auto def = defs.defs.blockFromId(block);
auto def = game.defs.blockFromId(block);
if (def.callbacks.count(Callback::AFTER_CONSTRUCT)) {
def.callbacks[Callback::AFTER_CONSTRUCT](defs.parser.luaVec(pos));
def.callbacks[Callback::AFTER_CONSTRUCT](game.parser.luaVec(pos));
}
}
}

View File

@ -1,15 +1,14 @@
//
// World subclass for the server.
// Handles blocks, entities, and clients.
// Created by aurailus on 05/03/19.
//
#pragma once
#include <unordered_set>
#include "../../game/scene/world/World.h"
#include "ServerGenStream.h"
#include "../conn/ClientList.h"
#include "../../def/ServerGame.h"
#include "../../game/scene/world/World.h"
#include "../../world/ServerDimension.h"
class ServerWorld : public World {
@ -17,7 +16,7 @@ public:
const static int MB_GEN_H = 2;
const static int MB_GEN_V = 2;
explicit ServerWorld(unsigned int seed, ServerGame& defs, ClientList& clients);
explicit ServerWorld(unsigned int seed, ServerGame& game, ClientList& clients);
void init();
void update(double delta) override;
@ -25,7 +24,7 @@ public:
unsigned int getBlock(glm::ivec3 pos) override;
void setBlock(glm::ivec3 pos, unsigned int block) override;
ServerDimension dimension {};
ServerDimension dimension;
private:
void changedChunks(ServerClient& client);
bool generateMapBlock(glm::ivec3 pos);
@ -39,7 +38,7 @@ private:
std::unique_ptr<ServerGenStream> genStream = nullptr;
unsigned int seed;
ServerGame& defs;
ServerGame& game;
ClientList& clientList;
unsigned int generatedChunks = 0;

View File

@ -41,17 +41,17 @@ namespace Space {
namespace Region {
namespace world {
// Get a Region engine position from a MapBlock's engine position.
// Get a Region engine position from a MapBlock's world position.
static inline glm::ivec3 fromMapBlock(const glm::ivec3& mapBlock) {
return sectionFromGlobal(mapBlock, REGION_SIZE);
}
// Get a Region engine position from a Chunk's engine position.
// Get a Region engine position from a Chunk's world position.
static inline glm::ivec3 fromChunk(const glm::ivec3 &chunk) {
return sectionFromGlobal(chunk, REGION_CHUNK_LENGTH);
}
// Get a Region engine position from a Block's engine position.
// Get a Region engine position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3 &chunk) {
return sectionFromGlobal(chunk, REGION_BLOCK_LENGTH);
}
@ -60,25 +60,25 @@ namespace Space {
namespace MapBlock {
namespace relative {
// Get a MapBlock's relative position in its Region from its engine position.
// Get a MapBlock's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_SIZE);
}
}
namespace world {
// Get a MapBlock engine position from a Chunk's engine position.
// Get a MapBlock engine position from a Chunk's world position.
static inline glm::ivec3 fromChunk(const glm::ivec3 &chunk) {
return sectionFromGlobal(chunk, MAPBLOCK_SIZE);
}
// Get a MapBlock engine position from a Block's engine position.
// Get a MapBlock engine position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3 &vec) {
return sectionFromGlobal(vec, MAPBLOCK_BLOCK_LENGTH);
}
}
// Get the index of a MapBlock within its Region from its local or engine position.
// Get the index of a MapBlock within its Region from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = MapBlock::relative::toRegion(vec);
unsigned int ind = static_cast<unsigned int>(local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z));
@ -88,25 +88,25 @@ namespace Space {
namespace Chunk {
namespace relative {
// Get a Chunk's relative position in its MapBlock from its engine position.
// Get a Chunk's relative position in its MapBlock from its world position.
static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_CHUNK_LENGTH);
}
// Get a Chunk's relative position in its Region from its engine position.
// Get a Chunk's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
return localFromGlobal(pos, REGION_CHUNK_LENGTH);
}
}
namespace world {
// Get a Chunk engine position from a Block's engine position.
// Get a Chunk engine position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3& pos) {
return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH);
}
}
// Get the index of a Chunk within its MapBlock from its local or engine position.
// Get the index of a Chunk within its MapBlock from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = Chunk::relative::toMapBlock(vec);
return static_cast<unsigned int>(local.x + MAPBLOCK_SIZE * (local.y + MAPBLOCK_SIZE * local.z));
@ -115,27 +115,39 @@ namespace Space {
namespace Block {
namespace relative {
// Get a Block's relative position to its Chunk from its engine position.
// Get a Block's relative position to its Chunk from its world position.
static inline glm::ivec3 toChunk(const glm::ivec3& pos) {
return localFromGlobal(pos, CHUNK_BLOCK_LENGTH);
}
// Get a Block's relative position to its MapBlock from its engine position.
// Get a Block's relative position to its MapBlock from its world position.
static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH);
}
// Get a Block's relative position in its Region from its engine position.
// Get a Block's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
return localFromGlobal(pos, REGION_BLOCK_LENGTH);
}
}
// Get the index of a Block within its Chunk from its local or engine position.
// Get the index of a Block within its Chunk from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = Block::relative::toChunk(vec);
return static_cast<unsigned int>(local.x + CHUNK_SIZE * (local.y + CHUNK_SIZE * local.z));
}
// Return a local vector of an index within it's chunk.
static inline glm::ivec3 fromIndex(unsigned int ind) {
glm::ivec3 vec {};
vec.z = ind / (CHUNK_SIZE * CHUNK_SIZE);
ind -= (static_cast<int>(vec.z) * CHUNK_SIZE * CHUNK_SIZE);
vec.y = ind / CHUNK_SIZE;
vec.x = ind % CHUNK_SIZE;
return vec;
}
}
}

View File

@ -147,6 +147,20 @@ template <> inline std::vector<unsigned short> Deserializer::read<std::vector<un
reinterpret_cast<const unsigned short*>(&data[ind + len * 2]));
}
template <> inline std::vector<char> Deserializer::read<std::vector<char>>() {
unsigned int len = read<unsigned int>();
return std::vector<char>(
reinterpret_cast<const char*>(&data[ind]),
reinterpret_cast<const char*>(&data[ind + len]));
}
template <> inline std::vector<unsigned char> Deserializer::read<std::vector<unsigned char>>() {
unsigned int len = read<unsigned int>();
return std::vector<unsigned char>(
reinterpret_cast<const unsigned char*>(&data[ind]),
reinterpret_cast<const unsigned char*>(&data[ind + len]));
}
template <> inline std::vector<float> Deserializer::read<std::vector<float>>() {
unsigned int len = read<unsigned int>();
return std::vector<float>(

View File

@ -132,6 +132,20 @@ template <> inline Serializer& Serializer::append<std::vector<unsigned short>>(c
return *this;
}
template <> inline Serializer& Serializer::append<std::vector<char>>(const std::vector<char>& elem) {
data.reserve(data.length() + elem.size() + 4);
append<unsigned int>(elem.size());
data += std::string { reinterpret_cast<const char*>(&elem[0]), elem.size() };
return *this;
}
template <> inline Serializer& Serializer::append<std::vector<unsigned char>>(const std::vector<unsigned char>& elem) {
data.reserve(data.length() + elem.size() + 4);
append<unsigned int>(elem.size());
data += std::string { reinterpret_cast<const char*>(&elem[0]), elem.size() };
return *this;
}
template <> inline Serializer& Serializer::append<std::vector<float>>(const std::vector<float>& elem) {
data.reserve(data.length() + elem.size() * 4 + 4);
append<unsigned int>(elem.size());

View File

@ -4,6 +4,8 @@
#include "Dimension.h"
Dimension::Dimension(DefinitionAtlas &defs) : defs(defs) {}
std::shared_ptr<Region> Dimension::getRegion(glm::ivec3 regionPosition) {
if (!regions.count(regionPosition)) return nullptr;
return regions[regionPosition];
@ -15,13 +17,13 @@ void Dimension::removeRegion(glm::ivec3 pos) {
std::shared_ptr<MapBlock> Dimension::getMapBlock(glm::ivec3 mapBlockPosition) {
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
if (region == nullptr) return nullptr;
if (!region) return nullptr;
return (*region)[Space::MapBlock::index(mapBlockPosition)];
}
void Dimension::removeMapBlock(glm::ivec3 pos) {
auto region = getRegion(Space::Region::world::fromMapBlock(pos));
if (region == nullptr) return;
if (!region) return;
auto ind = Space::MapBlock::index(pos);
region->remove(ind);
if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos));
@ -29,7 +31,7 @@ void Dimension::removeMapBlock(glm::ivec3 pos) {
std::shared_ptr<BlockChunk> Dimension::getChunk(glm::ivec3 chunkPosition) {
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
if (mapBlock == nullptr) return nullptr;
if (!mapBlock) return nullptr;
return (*mapBlock)[Space::Chunk::index(chunkPosition)];
}
@ -40,7 +42,7 @@ void Dimension::setChunk(std::shared_ptr<BlockChunk> chunk) {
void Dimension::removeChunk(glm::ivec3 pos){
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos));
if (mapBlock == nullptr) return;
if (!mapBlock) return;
auto ind = Space::Chunk::index(pos);
mapBlock->remove(ind);
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
@ -48,20 +50,27 @@ void Dimension::removeChunk(glm::ivec3 pos){
unsigned int Dimension::getBlock(glm::ivec3 pos) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (chunk != nullptr) return chunk->getBlock(Space::Block::relative::toChunk(pos));
if (chunk) return chunk->getBlock(Space::Block::relative::toChunk(pos));
return 0;
}
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (chunk == nullptr) return false;
if (!chunk) return false;
chunk->setBlock(Space::Block::relative::toChunk(pos), block);
glm::ivec3 oldLight = chunk->getBlockLight(Space::Block::index(pos));
glm::ivec3 newLight = defs.blockFromId(block).lightSource;
if (oldLight != newLight) {
if (abs(oldLight.x) + abs(oldLight.y) + abs(oldLight.z) != 0) removeLight(pos);
if (abs(newLight.x) + abs(newLight.y) + abs(newLight.z) != 0) addLight(pos, newLight);
}
return true;
}
std::shared_ptr<Region> Dimension::getOrCreateRegion(glm::ivec3 pos) {
if (regions[pos] != nullptr) return regions[pos];
if (regions[pos]) return regions[pos];
regions[pos] = std::make_shared<Region>(pos);
return regions[pos];
}
@ -74,3 +83,97 @@ std::shared_ptr<MapBlock> Dimension::getOrCreateMapBlock(glm::ivec3 mapBlockPosi
(*region).set(index, std::make_shared<MapBlock>(mapBlockPosition));
return (*region)[index];
}
// Returns true if the provided pos references a block within chunk, otherwise returns false.
bool Dimension::containsWorldPos(BlockChunk *chunk, glm::ivec3 pos) {
return chunk && Space::Chunk::world::fromBlock(pos) == chunk->pos;
}
// Get the BlockLight of a block. This function can be accelerated
// by providing a chunk that might contain the world position.
glm::ivec3 Dimension::getBlockLight(glm::ivec3 worldPos, BlockChunk *chunk) {
if (containsWorldPos(chunk, worldPos)) return chunk->getBlockLight(Space::Block::index(worldPos));
auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get();
return (oChunk ? oChunk->getBlockLight(Space::Block::index(worldPos)) : glm::ivec3 {});
}
void Dimension::addLight(glm::ivec3 pos, glm::ivec3 light) {
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
auto index = Space::Block::index(pos);
startChunk->setBlockLight(index, light);
lightAddQueue[0].emplace(index, startChunk.get());
lightAddQueue[1].emplace(index, startChunk.get());
lightAddQueue[2].emplace(index, startChunk.get());
propogateAddNodes(0);
propogateAddNodes(1);
propogateAddNodes(2);
}
void Dimension::removeLight(glm::ivec3 pos) {
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
glm::ivec3 val = startChunk->getBlockLight(Space::Block::index(pos));
startChunk->setBlockLight(Space::Block::index(pos), {});
lightRemoveQueue[0].emplace(Space::Block::index(pos), val.r, startChunk.get());
lightRemoveQueue[1].emplace(Space::Block::index(pos), val.g, startChunk.get());
lightRemoveQueue[2].emplace(Space::Block::index(pos), val.b, startChunk.get());
propogateRemoveNodes(0);
propogateRemoveNodes(1);
propogateRemoveNodes(2);
}
void Dimension::propogateAddNodes(unsigned char channel) {
while (!lightAddQueue[channel].empty()) {
LightAddNode& node = lightAddQueue[channel].front();
unsigned char lightLevel = node.chunk->getBlockLight(node.index, channel);
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
for (const auto& i : checks) {
glm::ivec3 check = worldPos + i;
if (!defs.blockFromId(getBlock(check)).solid && getBlockLight(check, node.chunk)[channel] + 2 <= lightLevel) {
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
chunk->setBlockLight(Space::Block::index(check), channel, lightLevel - 1);
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
}
}
lightAddQueue[channel].pop();
}
}
void Dimension::propogateRemoveNodes(unsigned char channel) {
while (!lightRemoveQueue[channel].empty()) {
LightRemoveNode& node = lightRemoveQueue[channel].front();
glm::ivec3 worldPos = node.chunk->pos * 16 + Space::Block::fromIndex(node.index);
const static std::array<glm::ivec3, 6> checks = { glm::ivec3 {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1} };
for (const auto& i : checks) {
glm::ivec3 check = worldPos + i;
unsigned char checkLight = getBlockLight(check, node.chunk)[channel];
if (checkLight != 0 && checkLight < node.value) {
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
auto blockLight = defs.blockFromId(chunk->getBlock(Space::Block::index(check))).lightSource[channel];
chunk->setBlockLight(Space::Block::index(check), channel, blockLight);
if (blockLight) lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
lightRemoveQueue[channel].emplace(Space::Block::index(check), checkLight, chunk);
}
else if (checkLight >= node.value) {
auto chunk = containsWorldPos(node.chunk, check) ? node.chunk : getChunk(Space::Chunk::world::fromBlock(check)).get();
if (!chunk) continue;
lightAddQueue[channel].emplace(Space::Block::index(check), chunk);
}
}
lightRemoveQueue[channel].pop();
}
propogateAddNodes(channel);
}

View File

@ -4,6 +4,8 @@
#pragma once
#include <queue>
#include <array>
#include <memory>
#include "../util/Vec.h"
@ -11,7 +13,7 @@
class Dimension {
public:
Dimension() = default;
Dimension(DefinitionAtlas& defs);
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition);
void removeRegion(glm::ivec3 pos);
@ -29,8 +31,34 @@ public:
protected:
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Region>, Vec::ivec3> block_region_map;
block_region_map regions;
DefinitionAtlas& defs;
private:
inline std::shared_ptr<Region> getOrCreateRegion(glm::ivec3 pos);
inline std::shared_ptr<MapBlock> getOrCreateMapBlock(glm::ivec3 mapBlockPosition);
static inline bool containsWorldPos(BlockChunk* chunk, glm::ivec3 pos);
inline glm::ivec3 getBlockLight(glm::ivec3 worldPos, BlockChunk* chunk = nullptr);
inline void addLight(glm::ivec3 pos, glm::ivec3 light);
inline void removeLight(glm::ivec3 pos);
void propogateAddNodes(unsigned char channel);
void propogateRemoveNodes(unsigned char channel);
struct LightAddNode {
LightAddNode(unsigned short index, BlockChunk* chunk) : index(index), chunk(chunk) {};
unsigned short index;
BlockChunk* chunk;
};
struct LightRemoveNode {
LightRemoveNode(unsigned short index, unsigned short value, BlockChunk* chunk) : index(index), value(value), chunk(chunk) {};
unsigned short index;
unsigned short value;
BlockChunk* chunk;
};
std::array<std::queue<LightAddNode>, 3> lightAddQueue;
std::array<std::queue<LightRemoveNode>, 3> lightRemoveQueue;
};

View File

@ -6,7 +6,9 @@
#include "../game/scene/world/graph/MeshChunk.h"
LocalDimension::LocalDimension(ClientGame &defs) : defs(defs), meshGenStream(std::make_unique<MeshGenStream>(defs, *this)) {}
LocalDimension::LocalDimension(ClientGame &game) : Dimension(game.defs),
meshGenStream(std::make_unique<MeshGenStream>(game, *this)),
game(game) {}
void LocalDimension::update(double delta, glm::vec3 playerPos) {
finishMeshes();
@ -182,7 +184,7 @@ void LocalDimension::serverEntityInfo(PacketView& p) {
luaEntity.setDisplayType(displayMode, displayArg1, displayArg2);
}
else {
auto entity = std::make_shared<ServerLocalLuaEntity>(id, defs, displayMode, displayArg1, displayArg2);
auto entity = std::make_shared<ServerLocalLuaEntity>(id, game, displayMode, displayArg1, displayArg2);
entity->entity->setPos(position);
entity->entity->setVisualOffset(visualOffset);
entity->entity->interpRotateX(rotation.x);

View File

@ -5,10 +5,11 @@
#pragma once
#include "Dimension.h"
#include "../lua/api/class/LocalLuaEntity.h"
#include "../lua/api/class/ServerLocalLuaEntity.h"
#include "../game/entity/engine/PlayerEntity.h"
#include "../game/scene/world/MeshGenStream.h"
#include "../game/entity/engine/PlayerEntity.h"
#include "../lua/api/class/ServerLocalLuaEntity.h"
#include "../game/scene/world/graph/ChunkRenderElem.h"
class MeshChunk;
@ -18,7 +19,7 @@ public:
const static int MB_STORE_H = 6;
const static int MB_STORE_V = 4;
explicit LocalDimension(ClientGame& defs);
explicit LocalDimension(ClientGame& game);
void update(double delta, glm::vec3 playerPos);
void setChunk(std::shared_ptr<BlockChunk> chunk) override;
@ -50,7 +51,7 @@ private:
void attemptMeshChunk(const std::shared_ptr<BlockChunk>& chunk, bool updateAdjacents = true);
bool getAdjacentExists(glm::vec3 pos, bool updateAdjacents);
ClientGame& defs;
ClientGame& game;
std::unique_ptr<MeshGenStream> meshGenStream = nullptr;
std::vector<glm::vec3> pendingMesh {};

View File

@ -2,10 +2,13 @@
// Created by aurailus on 01/10/19.
//
#include "ServerDimension.h"
#include "../def/gen/MapGen.h"
#include "../server/conn/ServerClient.h"
#include "../server/world/ServerWorld.h"
#include "ServerDimension.h"
ServerDimension::ServerDimension(ServerGame &game) : Dimension(game.defs), game(game) {}
void ServerDimension::update(const std::vector<std::shared_ptr<ServerClient>> &clients) {
for (const auto& region : regions) {
@ -79,4 +82,4 @@ const std::list<unsigned int> &ServerDimension::getRemovedEntities() const {
void ServerDimension::clearRemovedEntities() {
removedEntities.clear();
}
}

View File

@ -12,7 +12,7 @@ class ServerClient;
class ServerDimension : public Dimension {
public:
ServerDimension() = default;
ServerDimension(ServerGame& game);
void update(const std::vector<std::shared_ptr<ServerClient>>& clients);
@ -27,6 +27,8 @@ public:
const std::list<unsigned int>& getRemovedEntities() const;
void clearRemovedEntities();
private:
ServerGame& game;
typedef std::list<std::shared_ptr<ServerLuaEntity>>::iterator luaent_ref;
std::unordered_map<unsigned int, luaent_ref> luaEntityRefs {};

View File

@ -19,6 +19,7 @@ BlockChunk::BlockChunk(const std::vector<unsigned int>& blocks, const std::vecto
biomes(std::move(biomes)),
pos(pos),
generated(true) {
memset(light.data(), 0, sizeof(light));
calcNonAirBlocks();
}
@ -59,6 +60,16 @@ Packet BlockChunk::serialize() {
temp = Serializer().append(biomes).data;
s.append<std::string>(gzip::compress(temp.data(), temp.size()));
std::vector<unsigned char> lights {};
lights.resize(4096 * 3);
for (unsigned short i = 0; i < 4096; i++) {
lights[i * 3] = this->light[i].r;
lights[i * 3 + 1] = this->light[i].g;
lights[i * 3 + 2] = this->light[i].b;
}
temp = Serializer().append(lights).data;
s.append<std::string>(gzip::compress(temp.data(), temp.size()));
return s.packet(PacketType::CHUNK);
}
@ -78,6 +89,18 @@ void BlockChunk::deserialize(PacketView& packet) {
gzip = gzip::decompress(gzip.data(), gzip.length());
biomes = Deserializer(gzip).read<std::vector<unsigned short>>();
gzip = packet.d.read<std::string>();
if (!gzip::is_compressed(gzip.data(), gzip.length())) throw "Invalid Light GZip Data.";
gzip = gzip::decompress(gzip.data(), gzip.length());
auto lightsVec = Deserializer(gzip).read<std::vector<unsigned char>>();
for (unsigned int i = 0; i < 4096; i++) {
light[i].r = lightsVec[i * 3];
light[i].g = lightsVec[i * 3 + 1];
light[i].b = lightsVec[i * 3 + 2];
}
}
void BlockChunk::calcNonAirBlocks() {

View File

@ -35,10 +35,14 @@ public:
inline unsigned short getBiome(const glm::ivec3& pos) const;
inline void setSunlight(unsigned int ind, unsigned char val);
inline void setBlocklight(unsigned int ind, unsigned char val);
inline void setBlockLight(unsigned int ind, glm::ivec3 light);
inline void setBlockLight(unsigned int ind, unsigned char channel, unsigned char light);
inline int getSunlight(unsigned int ind);
inline int getBlocklight(unsigned int ind);
inline unsigned char getSunlight(unsigned int ind);
inline glm::ivec3 getBlockLight(unsigned int ind);
inline unsigned char getBlockLight(unsigned int ind, unsigned char channel);
inline glm::vec4 getLightVec(unsigned int ind);
const std::vector<unsigned int>& cGetBlocks() const;
const std::vector<unsigned short>& cGetBiomes() const;
@ -53,9 +57,16 @@ public:
glm::ivec3 pos;
private:
struct light_bits {
// 16 bits - 1 short
unsigned char r: 5;
unsigned char g: 5;
unsigned char b: 5, :1;
};
std::vector<unsigned int> blocks {};
std::vector<unsigned short> biomes {};
std::array<unsigned char, 4096> lighting {};
std::array <light_bits, 4096> light {};
bool empty = true;
bool partial = false;
@ -100,17 +111,34 @@ inline unsigned short BlockChunk::getBiome(const glm::ivec3& pos) const {
}
inline void BlockChunk::setSunlight(unsigned int ind, unsigned char val) {
lighting[ind] = (lighting[ind] & 0xF) | (val << 4);
}
inline void BlockChunk::setBlocklight(unsigned int ind, unsigned char val) {
lighting[ind] = (lighting[ind] & 0xF0) | val;
inline void BlockChunk::setBlockLight(unsigned int ind, glm::ivec3 l) {
light[ind].r = l.x;
light[ind].g = l.y;
light[ind].b = l.z;
}
inline int BlockChunk::getSunlight(unsigned int ind) {
return (lighting[ind] >> 4) & 0xF;
inline void BlockChunk::setBlockLight(unsigned int ind, unsigned char channel, unsigned char l){
channel == 0 ? light[ind].r = l :
channel == 1 ? light[ind].g = l :
light[ind].b = l;
}
inline int BlockChunk::getBlocklight(unsigned int ind) {
return (lighting[ind]) & 0xF;
inline unsigned char BlockChunk::getSunlight(unsigned int ind) {
return 15;
}
inline glm::ivec3 BlockChunk::getBlockLight(unsigned int ind) {
return { light[ind].r, light[ind].g, light[ind].b };
}
inline unsigned char BlockChunk::getBlockLight(unsigned int ind, unsigned char channel) {
return channel == 0 ? light[ind].r :
channel == 1 ? light[ind].g :
light[ind].b;
}
inline glm::vec4 BlockChunk::getLightVec(unsigned int ind) {
return glm::vec4 { light[ind].r, light[ind].g, light[ind].b, getSunlight(ind) };
}

View File

@ -6,5 +6,6 @@ zepha.register_block("zeus:default:cobblestone", {
hand = 14,
pick = 3
},
yields = "zeus:default:cobblestone"
yields = "zeus:default:cobblestone",
light_source = { 31, 16, 4 },
})

View File

@ -7,5 +7,6 @@ zepha.register_block("zeus:default:dirt", {
shovel = 1,
pick = 2
},
light_source = { 0, 15, 31 },
yields = "zeus:default:dirt"
})

View File

@ -1,28 +1,31 @@
local noise = {
heightmap = {
module = "add",
sources = {{
## Elevation
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.002,
octaves = 8
},
scale = 250,
bias = -32
}, {
## Features
module = "scale_bias",
source = {
module = "perlin",
frequency = 0.2,
octaves = 3,
},
scale = 6,
bias = 6
}}
module = "const"
}
## heightmap = {
## module = "add",
## sources = {{
## ## Elevation
## module = "scale_bias",
## source = {
## module = "perlin",
## frequency = 0.002,
## octaves = 8
## },
## scale = 250,
## bias = -32
## }, {
## ## Features
## module = "scale_bias",
## source = {
## module = "perlin",
## frequency = 0.2,
## octaves = 3,
## },
## scale = 6,
## bias = 6
## }}
## }
}
zepha.register_biome("zeus:mapgen:plains", {
@ -32,7 +35,7 @@ zepha.register_biome("zeus:mapgen:plains", {
roughness = 20/100,
},
blocks = {
top = "zeus:default:grass",
top = "zeus:default:stone",
soil = "zeus:default:dirt",
rock = "zeus:default:stone"
},