add block particles property
This commit is contained in:
parent
24af455bf0
commit
0eeb6b6eb2
@ -15,5 +15,21 @@
|
||||
"obstacle": false,
|
||||
"grounded": true,
|
||||
"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 "data/dv_util.hpp"
|
||||
#include "data/StructLayout.hpp"
|
||||
#include "presets/ParticlesPreset.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
using namespace data;
|
||||
@ -335,6 +336,11 @@ void ContentLoader::loadBlock(
|
||||
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) {
|
||||
def.tickInterval = 1;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "graphics/core/PostProcessing.hpp"
|
||||
#include "graphics/core/Viewport.hpp"
|
||||
#include "graphics/render/WorldRenderer.hpp"
|
||||
#include "graphics/render/Decorator.hpp"
|
||||
#include "graphics/ui/elements/Menu.hpp"
|
||||
#include "graphics/ui/GUI.hpp"
|
||||
#include "logic/LevelController.hpp"
|
||||
@ -29,20 +30,25 @@
|
||||
|
||||
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>())
|
||||
{
|
||||
Level* level = levelPtr.get();
|
||||
|
||||
auto& settings = engine->getSettings();
|
||||
auto assets = engine->getAssets();
|
||||
auto menu = engine->getGUI()->getMenu();
|
||||
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);
|
||||
|
||||
worldRenderer = std::make_unique<WorldRenderer>(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) {
|
||||
controller->getLevel()->chunks->saveAndClear();
|
||||
worldRenderer->clear();
|
||||
@ -156,6 +162,7 @@ void LevelScreen::update(float delta) {
|
||||
}
|
||||
controller->update(glm::min(delta, 0.2f), !inputLocked, hud->isPause());
|
||||
hud->update(hudVisible);
|
||||
decorator->update(delta, *camera);
|
||||
}
|
||||
|
||||
void LevelScreen::draw(float delta) {
|
||||
|
||||
@ -12,6 +12,7 @@ class WorldRenderer;
|
||||
class TextureAnimator;
|
||||
class PostProcessing;
|
||||
class ContentPackRuntime;
|
||||
class Decorator;
|
||||
class Level;
|
||||
|
||||
class LevelScreen : public Screen {
|
||||
@ -20,6 +21,7 @@ class LevelScreen : public Screen {
|
||||
std::unique_ptr<WorldRenderer> worldRenderer;
|
||||
std::unique_ptr<TextureAnimator> animator;
|
||||
std::unique_ptr<PostProcessing> postProcessing;
|
||||
std::unique_ptr<Decorator> decorator;
|
||||
std::unique_ptr<Hud> hud;
|
||||
|
||||
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
|
||||
bool lighting = true;
|
||||
/// @brief Max distance of actually spawning particles.
|
||||
float maxDistance = 32.0f;
|
||||
float maxDistance = 16.0f;
|
||||
/// @brief Particles spawn interval
|
||||
float spawnInterval = 0.1f;
|
||||
/// @brief Particle life time
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "core_defs.hpp"
|
||||
#include "data/StructLayout.hpp"
|
||||
#include "presets/ParticlesPreset.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
|
||||
std::string to_string(BlockModel model) {
|
||||
@ -142,6 +143,7 @@ void Block::cloneTo(Block& dst) {
|
||||
dst.inventorySize = inventorySize;
|
||||
dst.tickInterval = tickInterval;
|
||||
dst.overlayTexture = overlayTexture;
|
||||
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
||||
}
|
||||
|
||||
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
#include "maths/aabb.hpp"
|
||||
#include "typedefs.hpp"
|
||||
|
||||
struct ParticlesPreset;
|
||||
|
||||
namespace data {
|
||||
class StructLayout;
|
||||
}
|
||||
@ -199,6 +201,8 @@ public:
|
||||
|
||||
std::unique_ptr<data::StructLayout> dataStruct;
|
||||
|
||||
std::unique_ptr<ParticlesPreset> particles;
|
||||
|
||||
/// @brief Runtime indices (content indexing results)
|
||||
struct {
|
||||
/// @brief block runtime integer id
|
||||
|
||||
@ -60,6 +60,10 @@ public:
|
||||
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;
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user