Split lighting functionality and block functionality
parent
f8da40b229
commit
0bfe269308
|
@ -228,8 +228,8 @@ set(ZEPHA_SRC
|
||||||
def/gen/ServerBiomeAtlas.h
|
def/gen/ServerBiomeAtlas.h
|
||||||
def/gen/LocalBiomeAtlas.cpp
|
def/gen/LocalBiomeAtlas.cpp
|
||||||
def/gen/LocalBiomeAtlas.h
|
def/gen/LocalBiomeAtlas.h
|
||||||
world/Dimension.cpp
|
world/DimensionBase.cpp
|
||||||
world/Dimension.h
|
world/DimensionBase.h
|
||||||
def/texture/RawTexData.h
|
def/texture/RawTexData.h
|
||||||
game/hud/components/compound/GuiImageButton.cpp
|
game/hud/components/compound/GuiImageButton.cpp
|
||||||
game/hud/components/compound/GuiImageButton.h
|
game/hud/components/compound/GuiImageButton.h
|
||||||
|
@ -333,6 +333,6 @@ set(ZEPHA_SRC
|
||||||
game/scene/world/graph/FarMeshGenerator.h
|
game/scene/world/graph/FarMeshGenerator.h
|
||||||
game/scene/world/FarMapMeshDetails.h
|
game/scene/world/FarMapMeshDetails.h
|
||||||
lua/api/class/LuaGuiElement.cpp
|
lua/api/class/LuaGuiElement.cpp
|
||||||
lua/api/class/LuaGuiElement.h)
|
lua/api/class/LuaGuiElement.h world/Dimension.cpp world/Dimension.h)
|
||||||
|
|
||||||
add_library (Zepha_Core ${ZEPHA_SRC})
|
add_library (Zepha_Core ${ZEPHA_SRC})
|
|
@ -1,133 +1,28 @@
|
||||||
//
|
//
|
||||||
// Created by aurailus on 2019-11-20.
|
// Created by aurailus on 2020-05-26.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Dimension.h"
|
#include "Dimension.h"
|
||||||
|
|
||||||
Dimension::Dimension(DefinitionAtlas &defs) : defs(defs) {}
|
void Dimension::calculateEdgeLight(glm::ivec3 mbPos) {
|
||||||
|
for (auto i = 0; i < 64; i++) {
|
||||||
|
glm::ivec3 l = Space::Chunk::fromIndex(i);
|
||||||
|
glm::ivec3 chunkPos = mbPos * 4 + l;
|
||||||
|
|
||||||
std::shared_ptr<Region> Dimension::getRegion(glm::ivec3 regionPosition) {
|
auto edges = std::array<bool, 6> { l.x == 0, l.y == 0, l.z == 0,
|
||||||
if (!regions.count(regionPosition)) return nullptr;
|
l.x == Space::MAPBLOCK_SIZE, l.y == Space::MAPBLOCK_SIZE, l.z == Space::MAPBLOCK_SIZE};
|
||||||
return regions[regionPosition];
|
|
||||||
|
if (edges[1]) {
|
||||||
|
for (unsigned int j = 0; j < 64; j++) {
|
||||||
|
for (unsigned int k = 0; k < 64; k++) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dimension::removeRegion(glm::ivec3 pos) {
|
void Dimension::reflowSunlightAroundSolid(glm::ivec3 pos) {
|
||||||
regions.erase(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<MapBlock> Dimension::getMapBlock(glm::ivec3 mapBlockPosition) {
|
|
||||||
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
|
|
||||||
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) return;
|
|
||||||
auto ind = Space::MapBlock::index(pos);
|
|
||||||
region->remove(ind);
|
|
||||||
if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<BlockChunk> Dimension::getChunk(glm::ivec3 chunkPosition) {
|
|
||||||
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
|
|
||||||
if (!mapBlock) return nullptr;
|
|
||||||
return (*mapBlock)[Space::Chunk::index(chunkPosition)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dimension::setChunk(std::shared_ptr<BlockChunk> chunk) {
|
|
||||||
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->pos));
|
|
||||||
(*mapBlock).set(Space::Chunk::index(chunk->pos), chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dimension::removeChunk(glm::ivec3 pos){
|
|
||||||
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos));
|
|
||||||
if (!mapBlock) return;
|
|
||||||
auto ind = Space::Chunk::index(pos);
|
|
||||||
mapBlock->remove(ind);
|
|
||||||
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Dimension::getBlock(glm::ivec3 pos) {
|
|
||||||
auto chunk = getChunk(Space::Chunk::world::fromBlock(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) return false;
|
|
||||||
|
|
||||||
chunk->setBlock(Space::Block::relative::toChunk(pos), block);
|
|
||||||
|
|
||||||
// Remove light when placing solid blocks.
|
|
||||||
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
|
||||||
if (!def.lightPropagates && oldLight.x + oldLight.y + oldLight.z != 0) removeLight(pos);
|
|
||||||
|
|
||||||
// Add light when placing light emitting blocks.
|
|
||||||
glm::ivec3 newLight = def.lightSource;
|
|
||||||
if (newLight.x > oldLight.x || newLight.y > oldLight.y || newLight.z > oldLight.z) addLight(pos, newLight);
|
|
||||||
|
|
||||||
// Reflow light when a transparent block is placed.
|
|
||||||
if (def.lightPropagates) reflowLight(pos);
|
|
||||||
|
|
||||||
// Block sunlight when a solid block is placed.
|
|
||||||
if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) blockSunlight(pos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Region> Dimension::getOrCreateRegion(glm::ivec3 pos) {
|
|
||||||
if (regions[pos]) return regions[pos];
|
|
||||||
regions[pos] = std::make_shared<Region>(pos);
|
|
||||||
return regions[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<MapBlock> Dimension::getOrCreateMapBlock(glm::ivec3 mapBlockPosition) {
|
|
||||||
auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
|
|
||||||
unsigned int index = Space::MapBlock::index(mapBlockPosition);
|
|
||||||
|
|
||||||
if ((*region)[index] != nullptr) return (*region)[index];
|
|
||||||
(*region).set(index, std::make_shared<MapBlock>(mapBlockPosition));
|
|
||||||
return (*region)[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Light related functions.
|
|
||||||
//
|
|
||||||
|
|
||||||
void Dimension::createSunlight(glm::ivec3 pos) {
|
|
||||||
// auto chunk = getChunk(pos);
|
|
||||||
// auto top = getChunk(pos + glm::ivec3 {0, 1, 0});
|
|
||||||
// if (top) {
|
|
||||||
// for (unsigned int i = 0; i < 256; i++) {
|
|
||||||
// unsigned int ind = Space::Block::index(glm::ivec3 {i / 16, 0, i % 16});
|
|
||||||
// auto light = top->getSunlight(ind);
|
|
||||||
// if (light != 0) {
|
|
||||||
// lightAddQueue[SUNLIGHT_CHANNEL].emplace(ind, top.get());
|
|
||||||
// if (light == 15) for (int j = 15; j >= 0; j--) {
|
|
||||||
// unsigned int ind = Space::Block::index({i / 16, j, i % 16});
|
|
||||||
// if (!defs.blockFromId(chunk->getBlock(ind)).solid) {
|
|
||||||
// chunk->setSunlight(ind, 15);
|
|
||||||
// lightAddQueue[SUNLIGHT_CHANNEL].emplace(ind, chunk.get());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// for (unsigned int i = 0; i < 256; i++) {
|
|
||||||
// for (unsigned int j = 15; j >= 0; j--) {
|
|
||||||
// auto index = Space::Block::index(glm::ivec3{i / 16, j, i % 16});
|
|
||||||
// if (defs.blockFromId(chunk->getBlock(index)).solid) continue;
|
|
||||||
// chunk->setSunlight(index, 15);
|
|
||||||
// lightAddQueue[SUNLIGHT_CHANNEL].emplace(index, chunk.get());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dimension::blockSunlight(glm::ivec3 pos) {
|
|
||||||
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
auto ind = Space::Block::index(pos);
|
auto ind = Space::Block::index(pos);
|
||||||
unsigned int light = startChunk->getSunlight(ind);
|
unsigned int light = startChunk->getSunlight(ind);
|
||||||
|
@ -136,41 +31,68 @@ void Dimension::blockSunlight(glm::ivec3 pos) {
|
||||||
propogateRemoveNodes();
|
propogateRemoveNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the provided pos references a block within chunk, otherwise returns false.
|
|
||||||
bool Dimension::containsWorldPos(BlockChunk *chunk, glm::ivec3 pos) {
|
bool Dimension::containsWorldPos(BlockChunk *chunk, glm::ivec3 pos) {
|
||||||
return chunk && Space::Chunk::world::fromBlock(pos) == chunk->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::ivec4 Dimension::getLight(glm::ivec3 worldPos, BlockChunk *chunk) {
|
glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, BlockChunk *chunk) {
|
||||||
if (containsWorldPos(chunk, worldPos)) return chunk->getLight(Space::Block::index(worldPos));
|
if (containsWorldPos(chunk, worldPos)) return chunk->getLight(Space::Block::index(worldPos));
|
||||||
auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get();
|
auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get();
|
||||||
return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : glm::ivec4 {});
|
return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : glm::ivec4 {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dimension::addLight(glm::ivec3 pos, glm::ivec3 light) {
|
void Dimension::addBlockLight(glm::ivec3 pos, glm::ivec3 light) {
|
||||||
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
auto index = Space::Block::index(pos);
|
auto ind = Space::Block::index(pos);
|
||||||
|
|
||||||
startChunk->setBlockLight(index, light);
|
startChunk->setBlockLight(ind, light);
|
||||||
lightAddQueue[0].emplace(index, startChunk.get());
|
lightAddQueue[0].emplace(ind, startChunk.get());
|
||||||
lightAddQueue[1].emplace(index, startChunk.get());
|
lightAddQueue[1].emplace(ind, startChunk.get());
|
||||||
lightAddQueue[2].emplace(index, startChunk.get());
|
lightAddQueue[2].emplace(ind, startChunk.get());
|
||||||
propogateAddNodes();
|
propogateAddNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dimension::removeLight(glm::ivec3 pos) {
|
void Dimension::removeBlockLight(glm::ivec3 pos) {
|
||||||
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
glm::ivec4 val = startChunk->getLight(Space::Block::index(pos));
|
auto ind = Space::Block::index(pos);
|
||||||
|
|
||||||
|
glm::ivec4 val = startChunk->getLight(ind);
|
||||||
|
|
||||||
startChunk->setBlockLight(Space::Block::index(pos), {});
|
startChunk->setBlockLight(Space::Block::index(pos), {});
|
||||||
lightRemoveQueue[0].emplace(Space::Block::index(pos), val.x, startChunk.get());
|
lightRemoveQueue[0].emplace(ind, val.x, startChunk.get());
|
||||||
lightRemoveQueue[1].emplace(Space::Block::index(pos), val.y, startChunk.get());
|
lightRemoveQueue[1].emplace(ind, val.y, startChunk.get());
|
||||||
lightRemoveQueue[2].emplace(Space::Block::index(pos), val.z, startChunk.get());
|
lightRemoveQueue[2].emplace(ind, val.z, startChunk.get());
|
||||||
propogateRemoveNodes();
|
propogateRemoveNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dimension::reflowLightAroundTransparent(glm::ivec3 pos) {
|
||||||
|
glm::ivec4 placeLight {};
|
||||||
|
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} };
|
||||||
|
|
||||||
|
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
|
auto ind = Space::Block::index(pos);
|
||||||
|
if (!chunk) return;
|
||||||
|
|
||||||
|
for (const auto& i : checks) {
|
||||||
|
glm::ivec3 check = pos + i;
|
||||||
|
auto adjLight = getLight(check, chunk.get());
|
||||||
|
placeLight.x = fmax(placeLight.x, adjLight.x - 1);
|
||||||
|
placeLight.y = fmax(placeLight.y, adjLight.y - 1);
|
||||||
|
placeLight.z = fmax(placeLight.z, adjLight.z - 1);
|
||||||
|
placeLight.w = fmax(placeLight.w, adjLight.w - (i.y == 1 ? 0 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk->setBlockLight(ind, {placeLight.x, placeLight.y, placeLight.z});
|
||||||
|
chunk->setSunlight(ind, placeLight.w);
|
||||||
|
|
||||||
|
lightAddQueue[0].emplace(ind, chunk.get());
|
||||||
|
lightAddQueue[1].emplace(ind, chunk.get());
|
||||||
|
lightAddQueue[2].emplace(ind, chunk.get());
|
||||||
|
lightAddQueue[3].emplace(ind, chunk.get());
|
||||||
|
|
||||||
|
propogateAddNodes();
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
|
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
|
||||||
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
|
||||||
|
|
||||||
|
@ -249,7 +171,25 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
|
||||||
return chunksUpdated;
|
return chunksUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dimension::propogateLight() {
|
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
|
||||||
propogateRemoveNodes();
|
if (!DimensionBase::setBlock(pos, block)) return false;
|
||||||
propogateAddNodes();
|
|
||||||
|
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
|
auto &def = defs.blockFromId(block);
|
||||||
|
|
||||||
|
// Remove light when placing solid blocks.
|
||||||
|
glm::ivec4 oldLight = chunk->getLight(Space::Block::index(pos));
|
||||||
|
if (!def.lightPropagates && oldLight.x + oldLight.y + oldLight.z != 0) removeBlockLight(pos);
|
||||||
|
|
||||||
|
// Add light when placing light emitting blocks.
|
||||||
|
glm::ivec3 newLight = def.lightSource;
|
||||||
|
if (newLight.x > oldLight.x || newLight.y > oldLight.y || newLight.z > oldLight.z) addBlockLight(pos, newLight);
|
||||||
|
|
||||||
|
// Reflow light when a transparent block is placed.
|
||||||
|
if (def.lightPropagates) reflowLightAroundTransparent(pos);
|
||||||
|
|
||||||
|
// Block sunlight when a solid block is placed.
|
||||||
|
if (!def.lightPropagates && getLight(pos, chunk.get()).w != 0) reflowSunlightAroundSolid(pos);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +1,52 @@
|
||||||
//
|
//
|
||||||
// Created by aurailus on 2019-11-20.
|
// DimensionBase subclass that handles block light and sunlight.
|
||||||
|
// This class was split from DimensionBase to help differentiate
|
||||||
|
// lighting functions from basic world manipulation.
|
||||||
|
// Created by aurailus on 2020-05-26.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <array>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "../util/Vec.h"
|
#include "DimensionBase.h"
|
||||||
#include "region/Region.h"
|
|
||||||
|
|
||||||
class Dimension {
|
class Dimension : public DimensionBase {
|
||||||
public:
|
public:
|
||||||
Dimension(DefinitionAtlas& defs);
|
Dimension(DefinitionAtlas& defs) : DimensionBase(defs) {}
|
||||||
|
|
||||||
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition);
|
// Override setBlock to update lighting.
|
||||||
void removeRegion(glm::ivec3 pos);
|
bool setBlock(glm::ivec3 pos, unsigned int block) override;
|
||||||
|
|
||||||
std::shared_ptr<MapBlock> getMapBlock(glm::ivec3 mapBlockPosition);
|
// Calculate light propogation around MapBlock edges,
|
||||||
virtual void removeMapBlock(glm::ivec3 pos);
|
// Called after a new mapblock is inserted into the dimension.
|
||||||
|
void calculateEdgeLight(glm::ivec3 mbPos);
|
||||||
|
|
||||||
std::shared_ptr<BlockChunk> getChunk(glm::ivec3 chunkPosition);
|
|
||||||
virtual void setChunk(std::shared_ptr<BlockChunk> chunk);
|
|
||||||
virtual void removeChunk(glm::ivec3 pos);
|
|
||||||
|
|
||||||
unsigned int getBlock(glm::ivec3 pos);
|
|
||||||
virtual bool setBlock(glm::ivec3 pos, unsigned int block);
|
|
||||||
|
|
||||||
void createSunlight(glm::ivec3 pos);
|
|
||||||
void propogateLight();
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Region>, Vec::ivec3> block_region_map;
|
|
||||||
block_region_map regions;
|
|
||||||
DefinitionAtlas& defs;
|
|
||||||
|
|
||||||
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateAddNodes();
|
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateAddNodes();
|
||||||
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateRemoveNodes();
|
virtual std::unordered_set<glm::ivec3, Vec::ivec3> propogateRemoveNodes();
|
||||||
private:
|
|
||||||
inline std::shared_ptr<Region> getOrCreateRegion(glm::ivec3 pos);
|
|
||||||
inline std::shared_ptr<MapBlock> getOrCreateMapBlock(glm::ivec3 mapBlockPosition);
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Helper methods to speed up light propagation.
|
||||||
static inline bool containsWorldPos(BlockChunk* chunk, glm::ivec3 pos);
|
static inline bool containsWorldPos(BlockChunk* chunk, glm::ivec3 pos);
|
||||||
inline glm::ivec4 getLight(glm::ivec3 worldPos, BlockChunk* chunk = nullptr);
|
inline glm::ivec4 getLight(glm::ivec3 worldPos, BlockChunk* chunk = nullptr);
|
||||||
|
|
||||||
inline void addLight(glm::ivec3 pos, glm::ivec3 light);
|
// Add and remove block light sources.
|
||||||
inline void removeLight(glm::ivec3 pos);
|
inline void addBlockLight(glm::ivec3 pos, glm::ivec3 light);
|
||||||
|
inline void removeBlockLight(glm::ivec3 pos);
|
||||||
|
|
||||||
|
// Special methods to recalculate lights after world manipulation.
|
||||||
|
inline void reflowLightAroundTransparent(glm::ivec3 pos);
|
||||||
|
inline void reflowSunlightAroundSolid(glm::ivec3 pos);
|
||||||
|
|
||||||
struct LightAddNode {
|
struct LightAddNode {
|
||||||
LightAddNode(unsigned short index, BlockChunk* chunk) : index(index), chunk(chunk) {};
|
LightAddNode(unsigned short index, BlockChunk* chunk) : index(index), chunk(chunk) {};
|
||||||
unsigned short index;
|
unsigned short index; BlockChunk* chunk;
|
||||||
BlockChunk* chunk;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightRemoveNode {
|
struct LightRemoveNode {
|
||||||
LightRemoveNode(unsigned short index, unsigned short value, BlockChunk* chunk) : index(index), value(value), chunk(chunk) {};
|
LightRemoveNode(unsigned short index, unsigned short value, BlockChunk* chunk) : index(index), value(value), chunk(chunk) {};
|
||||||
unsigned short index;
|
unsigned short index, value; BlockChunk* chunk;
|
||||||
unsigned short value;
|
|
||||||
BlockChunk* chunk;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr unsigned char SUNLIGHT_CHANNEL = 3;
|
static constexpr unsigned char SUNLIGHT_CHANNEL = 3;
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
//
|
||||||
|
// Created by aurailus on 2019-11-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "DimensionBase.h"
|
||||||
|
|
||||||
|
DimensionBase::DimensionBase(DefinitionAtlas &defs) : defs(defs) {}
|
||||||
|
|
||||||
|
std::shared_ptr<Region> DimensionBase::getRegion(glm::ivec3 regionPosition) {
|
||||||
|
if (!regions.count(regionPosition)) return nullptr;
|
||||||
|
return regions[regionPosition];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimensionBase::removeRegion(glm::ivec3 pos) {
|
||||||
|
regions.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MapBlock> DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) {
|
||||||
|
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
|
||||||
|
if (!region) return nullptr;
|
||||||
|
return (*region)[Space::MapBlock::index(mapBlockPosition)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimensionBase::removeMapBlock(glm::ivec3 pos) {
|
||||||
|
auto region = getRegion(Space::Region::world::fromMapBlock(pos));
|
||||||
|
if (!region) return;
|
||||||
|
auto ind = Space::MapBlock::index(pos);
|
||||||
|
region->remove(ind);
|
||||||
|
if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockChunk> DimensionBase::getChunk(glm::ivec3 chunkPosition) {
|
||||||
|
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
|
||||||
|
if (!mapBlock) return nullptr;
|
||||||
|
return (*mapBlock)[Space::Chunk::index(chunkPosition)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimensionBase::setChunk(std::shared_ptr<BlockChunk> chunk) {
|
||||||
|
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->pos));
|
||||||
|
(*mapBlock).set(Space::Chunk::index(chunk->pos), chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimensionBase::removeChunk(glm::ivec3 pos){
|
||||||
|
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos));
|
||||||
|
if (!mapBlock) return;
|
||||||
|
auto ind = Space::Chunk::index(pos);
|
||||||
|
mapBlock->remove(ind);
|
||||||
|
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int DimensionBase::getBlock(glm::ivec3 pos) {
|
||||||
|
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
|
if (chunk) return chunk->getBlock(Space::Block::relative::toChunk(pos));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) {
|
||||||
|
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
|
||||||
|
if (!chunk) return false;
|
||||||
|
|
||||||
|
auto &def = defs.blockFromId(block);
|
||||||
|
chunk->setBlock(Space::Block::relative::toChunk(pos), block);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Region> DimensionBase::getOrCreateRegion(glm::ivec3 pos) {
|
||||||
|
if (regions[pos]) return regions[pos];
|
||||||
|
regions[pos] = std::make_shared<Region>(pos);
|
||||||
|
return regions[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<MapBlock> DimensionBase::getOrCreateMapBlock(glm::ivec3 mapBlockPosition) {
|
||||||
|
auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
|
||||||
|
unsigned int index = Space::MapBlock::index(mapBlockPosition);
|
||||||
|
|
||||||
|
if ((*region)[index] != nullptr) return (*region)[index];
|
||||||
|
(*region).set(index, std::make_shared<MapBlock>(mapBlockPosition));
|
||||||
|
return (*region)[index];
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// The base superclass for both dimensions. Handles chunk storage and manipulation.
|
||||||
|
// Does not include lighting mechanics, which are contained in subclass Dimension.
|
||||||
|
// Created by aurailus on 2019-11-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "../util/Vec.h"
|
||||||
|
#include "region/Region.h"
|
||||||
|
|
||||||
|
class DimensionBase {
|
||||||
|
public:
|
||||||
|
DimensionBase(DefinitionAtlas& defs);
|
||||||
|
|
||||||
|
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition);
|
||||||
|
void removeRegion(glm::ivec3 pos);
|
||||||
|
|
||||||
|
std::shared_ptr<MapBlock> getMapBlock(glm::ivec3 mapBlockPosition);
|
||||||
|
virtual void removeMapBlock(glm::ivec3 pos);
|
||||||
|
|
||||||
|
std::shared_ptr<BlockChunk> getChunk(glm::ivec3 chunkPosition);
|
||||||
|
virtual void setChunk(std::shared_ptr<BlockChunk> chunk);
|
||||||
|
virtual void removeChunk(glm::ivec3 pos);
|
||||||
|
|
||||||
|
unsigned int getBlock(glm::ivec3 pos);
|
||||||
|
virtual bool setBlock(glm::ivec3 pos, unsigned int block);
|
||||||
|
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);
|
||||||
|
};
|
|
@ -20,7 +20,6 @@ void LocalDimension::update(double delta, glm::vec3 playerPos) {
|
||||||
|
|
||||||
auto clientMapBlock = Space::MapBlock::world::fromBlock(playerPos);
|
auto clientMapBlock = Space::MapBlock::world::fromBlock(playerPos);
|
||||||
|
|
||||||
|
|
||||||
for (auto it = regions.cbegin(); it != regions.cend();) {
|
for (auto it = regions.cbegin(); it != regions.cend();) {
|
||||||
bool remove = false;
|
bool remove = false;
|
||||||
for (unsigned short m = 0; m < 64; m++) {
|
for (unsigned short m = 0; m < 64; m++) {
|
||||||
|
@ -34,7 +33,6 @@ void LocalDimension::update(double delta, glm::vec3 playerPos) {
|
||||||
for (unsigned short c = 0; c < 64; c++) {
|
for (unsigned short c = 0; c < 64; c++) {
|
||||||
auto chunk = mapBlock->operator[](c);
|
auto chunk = mapBlock->operator[](c);
|
||||||
if (!chunk) continue;
|
if (!chunk) continue;
|
||||||
|
|
||||||
removeMeshChunk(chunk->pos);
|
removeMeshChunk(chunk->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,27 +46,6 @@ void LocalDimension::update(double delta, glm::vec3 playerPos) {
|
||||||
}
|
}
|
||||||
if (!remove) it++;
|
if (!remove) it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (const auto& region : regions) {
|
|
||||||
// for (unsigned short i = 0; i < 64; i++) {
|
|
||||||
// auto mapBlock = region.second->operator[](i);
|
|
||||||
// if (mapBlock == nullptr) continue;
|
|
||||||
//
|
|
||||||
// if (abs(clientMapBlock.x - mapBlock->pos.x) > LocalDimension::MB_STORE_H + 1
|
|
||||||
// || abs(clientMapBlock.y - mapBlock->pos.y) > LocalDimension::MB_STORE_V + 1
|
|
||||||
// || abs(clientMapBlock.z - mapBlock->pos.z) > LocalDimension::MB_STORE_H + 1) {
|
|
||||||
//
|
|
||||||
// for (unsigned short j = 0; j < 64; j++) {
|
|
||||||
// auto chunk = mapBlock->operator[](j);
|
|
||||||
// if (chunk == nullptr) continue;
|
|
||||||
// removeMeshChunk(chunk->pos);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// removeMapBlock(mapBlock->pos);
|
|
||||||
// if (region.second->count == 0) break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalDimension::finishMeshes() {
|
void LocalDimension::finishMeshes() {
|
||||||
|
|
Loading…
Reference in New Issue