87 lines
2.4 KiB
C++
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;
|
|
};
|
|
} |