add block particles property
This commit is contained in:
parent
24af455bf0
commit
0eeb6b6eb2
@ -15,5 +15,21 @@
|
|||||||
"obstacle": false,
|
"obstacle": false,
|
||||||
"grounded": true,
|
"grounded": true,
|
||||||
"rotation": "pipe",
|
"rotation": "pipe",
|
||||||
"material": "base:wood"
|
"material": "base:wood",
|
||||||
|
"particles": {
|
||||||
|
"lifetime": 2.0,
|
||||||
|
"spawn_interval": 0.3,
|
||||||
|
"acceleration": [0, 0, 0],
|
||||||
|
"velocity": [0, 0.3, 0],
|
||||||
|
"explosion": [0, 0, 0],
|
||||||
|
"size": [0.2, 0.2, 0.2],
|
||||||
|
"spawn_shape": "ball",
|
||||||
|
"spawn_spread": [0.05, 0.05, 0.05],
|
||||||
|
"lighting": false,
|
||||||
|
"frames": [
|
||||||
|
"particles:fire_0",
|
||||||
|
"particles:smoke_0",
|
||||||
|
"particles:smoke_1"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
function on_placed(x, y, z)
|
|
||||||
particles.emit({x + 0.5, y + 0.4, z + 0.5}, -1, {
|
|
||||||
lifetime=2.0,
|
|
||||||
spawn_interval=0.3,
|
|
||||||
acceleration={0, 0, 0},
|
|
||||||
velocity={0, 0.3, 0},
|
|
||||||
explosion={0, 0, 0},
|
|
||||||
size={0.2, 0.2, 0.2},
|
|
||||||
spawn_shape="ball",
|
|
||||||
spawn_spread={0.05, 0.05, 0.05},
|
|
||||||
lighting=false,
|
|
||||||
frames={
|
|
||||||
"particles:fire_0",
|
|
||||||
"particles:smoke_0",
|
|
||||||
"particles:smoke_1"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
@ -22,6 +22,7 @@
|
|||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "data/dv_util.hpp"
|
#include "data/dv_util.hpp"
|
||||||
#include "data/StructLayout.hpp"
|
#include "data/StructLayout.hpp"
|
||||||
|
#include "presets/ParticlesPreset.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace data;
|
using namespace data;
|
||||||
@ -335,6 +336,11 @@ void ContentLoader::loadBlock(
|
|||||||
perform_user_block_fields(def.name, *def.dataStruct);
|
perform_user_block_fields(def.name, *def.dataStruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.has("particles")) {
|
||||||
|
def.particles = std::make_unique<ParticlesPreset>();
|
||||||
|
def.particles->deserialize(root["particles"]);
|
||||||
|
}
|
||||||
|
|
||||||
if (def.tickInterval == 0) {
|
if (def.tickInterval == 0) {
|
||||||
def.tickInterval = 1;
|
def.tickInterval = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "graphics/core/PostProcessing.hpp"
|
#include "graphics/core/PostProcessing.hpp"
|
||||||
#include "graphics/core/Viewport.hpp"
|
#include "graphics/core/Viewport.hpp"
|
||||||
#include "graphics/render/WorldRenderer.hpp"
|
#include "graphics/render/WorldRenderer.hpp"
|
||||||
|
#include "graphics/render/Decorator.hpp"
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
#include "graphics/ui/elements/Menu.hpp"
|
||||||
#include "graphics/ui/GUI.hpp"
|
#include "graphics/ui/GUI.hpp"
|
||||||
#include "logic/LevelController.hpp"
|
#include "logic/LevelController.hpp"
|
||||||
@ -29,20 +30,25 @@
|
|||||||
|
|
||||||
static debug::Logger logger("level-screen");
|
static debug::Logger logger("level-screen");
|
||||||
|
|
||||||
LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> level)
|
LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> levelPtr)
|
||||||
: Screen(engine), postProcessing(std::make_unique<PostProcessing>())
|
: Screen(engine), postProcessing(std::make_unique<PostProcessing>())
|
||||||
{
|
{
|
||||||
|
Level* level = levelPtr.get();
|
||||||
|
|
||||||
auto& settings = engine->getSettings();
|
auto& settings = engine->getSettings();
|
||||||
auto assets = engine->getAssets();
|
auto assets = engine->getAssets();
|
||||||
auto menu = engine->getGUI()->getMenu();
|
auto menu = engine->getGUI()->getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
|
|
||||||
controller = std::make_unique<LevelController>(engine, std::move(level));
|
controller = std::make_unique<LevelController>(engine, std::move(levelPtr));
|
||||||
frontend = std::make_unique<LevelFrontend>(controller->getPlayer(), controller.get(), assets);
|
frontend = std::make_unique<LevelFrontend>(controller->getPlayer(), controller.get(), assets);
|
||||||
|
|
||||||
worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer());
|
worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer());
|
||||||
hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer());
|
hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer());
|
||||||
|
|
||||||
|
decorator =
|
||||||
|
std::make_unique<Decorator>(*level, *worldRenderer->particles, *assets);
|
||||||
|
|
||||||
keepAlive(settings.graphics.backlight.observe([=](bool) {
|
keepAlive(settings.graphics.backlight.observe([=](bool) {
|
||||||
controller->getLevel()->chunks->saveAndClear();
|
controller->getLevel()->chunks->saveAndClear();
|
||||||
worldRenderer->clear();
|
worldRenderer->clear();
|
||||||
@ -156,6 +162,7 @@ void LevelScreen::update(float delta) {
|
|||||||
}
|
}
|
||||||
controller->update(glm::min(delta, 0.2f), !inputLocked, hud->isPause());
|
controller->update(glm::min(delta, 0.2f), !inputLocked, hud->isPause());
|
||||||
hud->update(hudVisible);
|
hud->update(hudVisible);
|
||||||
|
decorator->update(delta, *camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelScreen::draw(float delta) {
|
void LevelScreen::draw(float delta) {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ class WorldRenderer;
|
|||||||
class TextureAnimator;
|
class TextureAnimator;
|
||||||
class PostProcessing;
|
class PostProcessing;
|
||||||
class ContentPackRuntime;
|
class ContentPackRuntime;
|
||||||
|
class Decorator;
|
||||||
class Level;
|
class Level;
|
||||||
|
|
||||||
class LevelScreen : public Screen {
|
class LevelScreen : public Screen {
|
||||||
@ -20,6 +21,7 @@ class LevelScreen : public Screen {
|
|||||||
std::unique_ptr<WorldRenderer> worldRenderer;
|
std::unique_ptr<WorldRenderer> worldRenderer;
|
||||||
std::unique_ptr<TextureAnimator> animator;
|
std::unique_ptr<TextureAnimator> animator;
|
||||||
std::unique_ptr<PostProcessing> postProcessing;
|
std::unique_ptr<PostProcessing> postProcessing;
|
||||||
|
std::unique_ptr<Decorator> decorator;
|
||||||
std::unique_ptr<Hud> hud;
|
std::unique_ptr<Hud> hud;
|
||||||
|
|
||||||
void saveWorldPreview();
|
void saveWorldPreview();
|
||||||
|
|||||||
103
src/graphics/render/Decorator.cpp
Normal file
103
src/graphics/render/Decorator.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "Decorator.hpp"
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
|
#include "ParticlesRenderer.hpp"
|
||||||
|
#include "assets/assets_util.hpp"
|
||||||
|
#include "content/Content.hpp"
|
||||||
|
#include "voxels/Chunks.hpp"
|
||||||
|
#include "voxels/Block.hpp"
|
||||||
|
#include "world/Level.hpp"
|
||||||
|
#include "window/Camera.hpp"
|
||||||
|
|
||||||
|
/// @brief Not greather than 64 for this BIG_PRIME value
|
||||||
|
inline constexpr int UPDATE_AREA_DIAMETER = 32;
|
||||||
|
/// @brief Number of blocks in the volume
|
||||||
|
inline constexpr int UPDATE_BLOCKS =
|
||||||
|
UPDATE_AREA_DIAMETER * UPDATE_AREA_DIAMETER * UPDATE_AREA_DIAMETER;
|
||||||
|
/// @brief Number of update iterations
|
||||||
|
inline constexpr int ITERATIONS = 512;
|
||||||
|
/// @brief Big prime number used for pseudo-random 3d array iteration
|
||||||
|
inline constexpr int BIG_PRIME = 666667;
|
||||||
|
|
||||||
|
Decorator::Decorator(
|
||||||
|
const Level& level, ParticlesRenderer& particles, const Assets& assets
|
||||||
|
)
|
||||||
|
: level(level), particles(particles), assets(assets) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decorator::update(
|
||||||
|
float delta, const glm::ivec3& areaStart, const glm::ivec3& areaCenter
|
||||||
|
) {
|
||||||
|
int index = currentIndex;
|
||||||
|
currentIndex = (currentIndex + BIG_PRIME) % UPDATE_BLOCKS;
|
||||||
|
|
||||||
|
const auto& chunks = *level.chunks;
|
||||||
|
const auto& indices = *level.content->getIndices();
|
||||||
|
|
||||||
|
int lx = index % UPDATE_AREA_DIAMETER;
|
||||||
|
int lz = (index / UPDATE_AREA_DIAMETER) % UPDATE_AREA_DIAMETER;
|
||||||
|
int ly = (index / UPDATE_AREA_DIAMETER / UPDATE_AREA_DIAMETER);
|
||||||
|
|
||||||
|
auto pos = areaStart + glm::ivec3(lx, ly, lz);
|
||||||
|
|
||||||
|
if (auto vox = chunks.get(pos)) {
|
||||||
|
const auto& def = indices.blocks.require(vox->id);
|
||||||
|
if (def.particles) {
|
||||||
|
const auto& found = blockEmitters.find(pos);
|
||||||
|
if (found == blockEmitters.end()) {
|
||||||
|
auto treg = util::get_texture_region(
|
||||||
|
assets, def.particles->texture, ""
|
||||||
|
);
|
||||||
|
blockEmitters[pos] = particles.add(std::make_unique<Emitter>(
|
||||||
|
level,
|
||||||
|
glm::vec3{pos.x + 0.5, pos.y + 0.5, pos.z + 0.5},
|
||||||
|
*def.particles,
|
||||||
|
treg.texture,
|
||||||
|
treg.region,
|
||||||
|
-1
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decorator::update(float delta, const Camera& camera) {
|
||||||
|
glm::ivec3 pos = camera.position;
|
||||||
|
pos -= glm::ivec3(UPDATE_AREA_DIAMETER / 2);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++) {
|
||||||
|
update(delta, pos, camera.position);
|
||||||
|
}
|
||||||
|
const auto& chunks = *level.chunks;
|
||||||
|
const auto& indices = *level.content->getIndices();
|
||||||
|
auto iter = blockEmitters.begin();
|
||||||
|
while (iter != blockEmitters.end()) {
|
||||||
|
auto emitter = particles.getEmitter(iter->second);
|
||||||
|
if (emitter == nullptr) {
|
||||||
|
iter = blockEmitters.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove = false;
|
||||||
|
if (auto vox = chunks.get(iter->first)) {
|
||||||
|
const auto& def = indices.blocks.require(vox->id);
|
||||||
|
if (def.particles == nullptr) {
|
||||||
|
remove = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iter = blockEmitters.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (util::distance2(iter->first, glm::ivec3(camera.position)) >
|
||||||
|
UPDATE_AREA_DIAMETER * UPDATE_AREA_DIAMETER) {
|
||||||
|
remove = true;
|
||||||
|
}
|
||||||
|
if (remove) {
|
||||||
|
emitter->stop();
|
||||||
|
iter = blockEmitters.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/graphics/render/Decorator.hpp
Normal file
31
src/graphics/render/Decorator.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/gtx/hash.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class Level;
|
||||||
|
class Chunks;
|
||||||
|
class Camera;
|
||||||
|
class Assets;
|
||||||
|
class ParticlesRenderer;
|
||||||
|
|
||||||
|
class Decorator {
|
||||||
|
const Level& level;
|
||||||
|
const Assets& assets;
|
||||||
|
ParticlesRenderer& particles;
|
||||||
|
std::unordered_map<glm::ivec3, uint64_t> blockEmitters;
|
||||||
|
int currentIndex = 0;
|
||||||
|
|
||||||
|
void update(
|
||||||
|
float delta, const glm::ivec3& areaStart, const glm::ivec3& areaCenter
|
||||||
|
);
|
||||||
|
public:
|
||||||
|
Decorator(
|
||||||
|
const Level& level, ParticlesRenderer& particles, const Assets& assets
|
||||||
|
);
|
||||||
|
|
||||||
|
void update(float delta, const Camera& camera);
|
||||||
|
};
|
||||||
@ -25,7 +25,7 @@ struct ParticlesPreset : public Serializable {
|
|||||||
/// @brief Apply lighting
|
/// @brief Apply lighting
|
||||||
bool lighting = true;
|
bool lighting = true;
|
||||||
/// @brief Max distance of actually spawning particles.
|
/// @brief Max distance of actually spawning particles.
|
||||||
float maxDistance = 32.0f;
|
float maxDistance = 16.0f;
|
||||||
/// @brief Particles spawn interval
|
/// @brief Particles spawn interval
|
||||||
float spawnInterval = 0.1f;
|
float spawnInterval = 0.1f;
|
||||||
/// @brief Particle life time
|
/// @brief Particle life time
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "core_defs.hpp"
|
#include "core_defs.hpp"
|
||||||
#include "data/StructLayout.hpp"
|
#include "data/StructLayout.hpp"
|
||||||
|
#include "presets/ParticlesPreset.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
|
|
||||||
std::string to_string(BlockModel model) {
|
std::string to_string(BlockModel model) {
|
||||||
@ -142,6 +143,7 @@ void Block::cloneTo(Block& dst) {
|
|||||||
dst.inventorySize = inventorySize;
|
dst.inventorySize = inventorySize;
|
||||||
dst.tickInterval = tickInterval;
|
dst.tickInterval = tickInterval;
|
||||||
dst.overlayTexture = overlayTexture;
|
dst.overlayTexture = overlayTexture;
|
||||||
|
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
||||||
|
|||||||
@ -10,6 +10,8 @@
|
|||||||
#include "maths/aabb.hpp"
|
#include "maths/aabb.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
|
struct ParticlesPreset;
|
||||||
|
|
||||||
namespace data {
|
namespace data {
|
||||||
class StructLayout;
|
class StructLayout;
|
||||||
}
|
}
|
||||||
@ -199,6 +201,8 @@ public:
|
|||||||
|
|
||||||
std::unique_ptr<data::StructLayout> dataStruct;
|
std::unique_ptr<data::StructLayout> dataStruct;
|
||||||
|
|
||||||
|
std::unique_ptr<ParticlesPreset> particles;
|
||||||
|
|
||||||
/// @brief Runtime indices (content indexing results)
|
/// @brief Runtime indices (content indexing results)
|
||||||
struct {
|
struct {
|
||||||
/// @brief block runtime integer id
|
/// @brief block runtime integer id
|
||||||
|
|||||||
@ -60,6 +60,10 @@ public:
|
|||||||
return get(pos.x, pos.y, pos.z);
|
return get(pos.x, pos.y, pos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const voxel* get(glm::ivec3 pos) const {
|
||||||
|
return get(pos.x, pos.y, pos.z);
|
||||||
|
}
|
||||||
|
|
||||||
light_t getLight(int32_t x, int32_t y, int32_t z) const;
|
light_t getLight(int32_t x, int32_t y, int32_t z) const;
|
||||||
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const;
|
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const;
|
||||||
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
|
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user