1
0
Fork 0
Univerxel/src/core/world/iterators.hpp

87 lines
2.4 KiB
C++

#pragma once
#include "position.h"
#include "actions.hpp"
namespace world::iterator {
using pair = std::pair<glm::ivec3, float>;
class Abstract {
public:
virtual bool next(pair&) = 0;
protected:
static constexpr uint32_t Diam(uint16_t radius) { return radius * 2 + 1; }
};
/// From -radius to radius
std::unique_ptr<Abstract> Get(action::Shape, uint16_t radius);
template<typename Chunk, typename area_map, typename CB>
void Apply(area_map &areas, action::FillShape fill, const CB& callback) {
if(const auto it = areas.find(fill.pos.first); it != areas.end()) {
auto &chunks = it->second->setChunks();
auto iterator = Get(fill.shape, fill.radius);
pair point;
typename std::shared_ptr<Chunk> ck = nullptr;
chunk_pos ck_pos = chunk_pos(INT32_MAX);
while (iterator->next(point)) {
const voxel_pos offset = point.first;
const auto split = glm::splitIdx(fill.pos.second + offset);
if (split.first != ck_pos && chunks.inRange(split.first)) {
if(auto it = chunks.find(split.first); it != chunks.end()) {
ck = std::dynamic_pointer_cast<Chunk>(it->second);
ck_pos = split.first;
}
}
if (split.first == ck_pos) {
auto prev = ck->get(split.second);
const auto next = prev.filled(fill.val, point.second);
if (prev.value != next.value) {
callback(ck, ck_pos, split.second, prev, next, glm::length2(offset) / fill.radius * .05f);
}
}
}
}
}
class Cube final: public Abstract {
public:
bool next(pair&) override;
Cube(uint16_t radius): radius(radius), pos(-radius, -radius, -radius) { }
private:
const uint16_t radius;
glm::ivec3 pos;
};
/// Interger sphere
class RawSphere final: public Abstract {
public:
bool next(pair&) override;
RawSphere(uint16_t radius): radius(radius), pos(-radius-1, 0, 0), dy(0), dz(0) { }
private:
const uint16_t radius;
glm::ivec3 pos;
int dy;
int dz;
};
/// Anti-aliased sphere
class SmoothSphere final: public Abstract {
public:
bool next(pair&) override;
SmoothSphere(uint16_t radius): radius(radius), pos(-radius-1, 0, 0), dy(0), dz(0) { }
private:
const uint16_t radius;
glm::ivec3 pos;
double dy;
double dz;
};
}