Voxels sort optimization
This commit is contained in:
parent
003ba2b290
commit
93da247ccc
@ -103,7 +103,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
ZElement *voxels;
|
||||
};
|
||||
|
||||
template<class sprite_data_t>
|
||||
class VoxelDrawerImpl : public RendererApi::VoxelDrawer {
|
||||
public:
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t _width;
|
||||
@ -116,15 +115,15 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
|
||||
VoxelDrawerImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height, pixel_trace_metadata *pixels_metadata, ZElementAllocationBuffer *pixel_trace_elements_allocator);
|
||||
|
||||
[[nodiscard]] RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width() const final {
|
||||
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width() const final {
|
||||
return this->_width;
|
||||
}
|
||||
|
||||
[[nodiscard]] RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
|
||||
[[nodiscard]] inline RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height() const final {
|
||||
return this->_height;
|
||||
}
|
||||
|
||||
pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
||||
inline pixel_trace_metadata *at(std::uint_fast16_t x, std::uint_fast16_t y) {
|
||||
return &(this->pixels_metadata[y * this->_width + x]);
|
||||
}
|
||||
|
||||
@ -136,12 +135,15 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
pixel_trace_metadata *buffer;
|
||||
std::size_t size;
|
||||
} pixel_metadata_cache;
|
||||
std::vector<ZElement *> sorter;
|
||||
ZElementAllocationBuffer pixel_trace_elements_allocator;
|
||||
|
||||
public:
|
||||
DefaultVoxelDrawerCache();
|
||||
|
||||
private:
|
||||
static ZElement *sort_zelements_desc(DefaultVoxelDrawerCache::ZElement *start) noexcept;
|
||||
|
||||
public:
|
||||
template<class sprite_data_t>
|
||||
void render(
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w,
|
||||
@ -157,19 +159,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
~DefaultVoxelDrawerCache();
|
||||
};
|
||||
|
||||
template<class sprite_data_t>
|
||||
DefaultVoxelDrawerCache::VoxelDrawerImpl<sprite_data_t>::VoxelDrawerImpl(
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
|
||||
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
|
||||
DefaultVoxelDrawerCache::ZElementAllocationBuffer *pixel_trace_elements_allocator
|
||||
): _width{width},
|
||||
_height{height},
|
||||
pixels_metadata{pixels_metadata},
|
||||
pixel_trace_elements_allocator{pixel_trace_elements_allocator},
|
||||
current_artist{nullptr} {}
|
||||
|
||||
|
||||
template<class... args_t>
|
||||
DefaultVoxelDrawerCache::ZElement *DefaultVoxelDrawerCache::ZElementAllocationBuffer::alloc_elem(args_t... args) {
|
||||
auto cell = this->next_unallocated;
|
||||
@ -184,27 +173,6 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
return new(&(cell->allocated)) ZElement{args...};
|
||||
}
|
||||
|
||||
template<class sprite_data_t>
|
||||
void DefaultVoxelDrawerCache::VoxelDrawerImpl<sprite_data_t>::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
|
||||
if (x < 0 || this->_width <= x) return;
|
||||
if (y < 0 || this->_height <= y) return;
|
||||
if (z < 0) return;
|
||||
auto p = this->at(x, y);
|
||||
if (z <= p->nearest_z) {
|
||||
p->nearest_z = z;
|
||||
#if 1
|
||||
if (c.alpha == 255) {
|
||||
ZElement *e;
|
||||
while (p->voxels != nullptr) {
|
||||
e = p->voxels;
|
||||
p->voxels = e->next;
|
||||
this->pixel_trace_elements_allocator->free_elem(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p->voxels = this->pixel_trace_elements_allocator->alloc_elem(p->voxels, z, c, this->current_artist);
|
||||
}
|
||||
|
||||
template<class sprite_data_t>
|
||||
void DefaultVoxelDrawerCache::render(
|
||||
@ -226,7 +194,7 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
}
|
||||
|
||||
this->pixel_trace_elements_allocator.reset_allocations();
|
||||
VoxelDrawerImpl<sprite_data_t> painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
|
||||
VoxelDrawerImpl painter{w, h, this->pixel_metadata_cache.buffer, &this->pixel_trace_elements_allocator};
|
||||
|
||||
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
||||
new(&this->pixel_metadata_cache.buffer[i]) pixel_trace_metadata{};
|
||||
@ -241,19 +209,14 @@ namespace BGTU::ComputerGraphicsLabWork {
|
||||
std::uint_fast16_t x = 0;
|
||||
|
||||
for (std::int_fast64_t i = w * h - 1; i >= 0; i--) {
|
||||
this->sorter.clear();
|
||||
for (ZElement *e = this->pixel_metadata_cache.buffer[i].voxels; e != nullptr; e = e->next) {
|
||||
this->sorter.push_back(e);
|
||||
this->pixel_metadata_cache.buffer[i].voxels = sort_zelements_desc(this->pixel_metadata_cache.buffer[i].voxels);
|
||||
RendererApi::Color cc = bg;
|
||||
RendererApi::SpriteMetadata *owner = nullptr;
|
||||
for (auto p = this->pixel_metadata_cache.buffer[i].voxels; p != nullptr; p = p->next) {
|
||||
cc = apply_transparent_color(cc, p->color);
|
||||
owner = p->owner;
|
||||
}
|
||||
std::sort(this->sorter.begin(), this->sorter.end(), [](ZElement *l, ZElement *r) { return l->z > r->z; });
|
||||
RendererApi::Color p = bg;
|
||||
for (auto a: this->sorter) {
|
||||
p = apply_transparent_color(p, a->color);
|
||||
}
|
||||
if (this->sorter.empty())
|
||||
frame->set_pixel(x, y, p, nullptr);
|
||||
else
|
||||
frame->set_pixel(x, y, p, this->sorter[this->sorter.size() - 1]->owner);
|
||||
frame->set_pixel(x, y, cc, owner);
|
||||
|
||||
if (++x >= w) {
|
||||
y++;
|
||||
|
@ -40,7 +40,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
this->release_resources();
|
||||
}
|
||||
|
||||
DefaultVoxelDrawerCache::DefaultVoxelDrawerCache() : pixel_trace_elements_allocator{}, pixel_metadata_cache{.buffer = nullptr, .size = 0}, sorter{} {}
|
||||
DefaultVoxelDrawerCache::DefaultVoxelDrawerCache() : pixel_trace_elements_allocator{}, pixel_metadata_cache{.buffer = nullptr, .size = 0} {}
|
||||
|
||||
DefaultVoxelDrawerCache::~DefaultVoxelDrawerCache() {
|
||||
if (this->pixel_metadata_cache.buffer != nullptr) {
|
||||
@ -50,4 +50,106 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
|
||||
this->pixel_metadata_cache.size = 0;
|
||||
}
|
||||
|
||||
DefaultVoxelDrawerCache::ZElement* DefaultVoxelDrawerCache::sort_zelements_desc(DefaultVoxelDrawerCache::ZElement *start) noexcept {
|
||||
for (std::size_t frame_size = 1; 0 < frame_size && frame_size < std::numeric_limits<std::size_t>::max() / 4; frame_size *= 2) {
|
||||
ZElement **before_left = &start;
|
||||
|
||||
while (true) {
|
||||
ZElement **union_ptr = before_left;
|
||||
ZElement *left_ptr = *before_left;
|
||||
ZElement *right_ptr;
|
||||
std::size_t left_counter = frame_size;
|
||||
std::size_t right_counter = frame_size;
|
||||
|
||||
if (left_ptr == nullptr)
|
||||
goto ROUND_DONE;
|
||||
|
||||
right_ptr = left_ptr;
|
||||
while (left_counter-- > 0) {
|
||||
right_ptr = right_ptr->next;
|
||||
if (right_ptr == nullptr)
|
||||
goto ROUND_DONE;
|
||||
}
|
||||
left_counter = frame_size;
|
||||
|
||||
while (left_counter > 0 && right_counter > 0) {
|
||||
if (left_ptr->z >= right_ptr->z) {
|
||||
*union_ptr = left_ptr;
|
||||
left_ptr = left_ptr->next;
|
||||
union_ptr = &((*union_ptr)->next);
|
||||
if (left_counter-- == 0)
|
||||
goto RIGHT_TAIL;
|
||||
} else {
|
||||
*union_ptr = right_ptr;
|
||||
right_ptr = right_ptr->next;
|
||||
union_ptr = &((*union_ptr)->next);
|
||||
if (right_counter-- == 0)
|
||||
goto LEFT_TAIL;
|
||||
|
||||
if (right_ptr == nullptr) {
|
||||
goto LEFT_TAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (right_counter == 0) {
|
||||
LEFT_TAIL:
|
||||
while (right_counter-- > 1)
|
||||
left_ptr = left_ptr->next;
|
||||
left_ptr->next = right_ptr;
|
||||
before_left = &(left_ptr->next);
|
||||
}
|
||||
if (left_counter == 0) {
|
||||
RIGHT_TAIL:
|
||||
*union_ptr = right_ptr;
|
||||
while (right_counter-- > 1) {
|
||||
right_ptr = right_ptr->next;
|
||||
if (right_ptr == nullptr) {
|
||||
goto ROUND_DONE;
|
||||
}
|
||||
}
|
||||
before_left = &(right_ptr->next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ROUND_DONE:
|
||||
if (before_left == &start)
|
||||
break;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
DefaultVoxelDrawerCache::VoxelDrawerImpl::VoxelDrawerImpl(
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t width,
|
||||
RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t height,
|
||||
DefaultVoxelDrawerCache::pixel_trace_metadata *pixels_metadata,
|
||||
DefaultVoxelDrawerCache::ZElementAllocationBuffer *pixel_trace_elements_allocator
|
||||
) : _width{width},
|
||||
_height{height},
|
||||
pixels_metadata{pixels_metadata},
|
||||
pixel_trace_elements_allocator{pixel_trace_elements_allocator},
|
||||
current_artist{nullptr} {}
|
||||
|
||||
|
||||
void DefaultVoxelDrawerCache::VoxelDrawerImpl::add_voxel(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y, double z, RendererApi::Color::Transparent c) {
|
||||
if (x < 0 || this->_width <= x) return;
|
||||
if (y < 0 || this->_height <= y) return;
|
||||
if (z < 0) return;
|
||||
auto p = this->at(x, y);
|
||||
if (z <= p->nearest_z) {
|
||||
p->nearest_z = z;
|
||||
#if 1
|
||||
if (c.alpha == 255) {
|
||||
ZElement *e;
|
||||
while (p->voxels != nullptr) {
|
||||
e = p->voxels;
|
||||
p->voxels = e->next;
|
||||
this->pixel_trace_elements_allocator->free_elem(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p->voxels = this->pixel_trace_elements_allocator->alloc_elem(p->voxels, z, c, this->current_artist);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user