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

84 lines
2.6 KiB
C++

#pragma once
#include <robin_hood.h>
#include "../../core/world/materials.hpp"
#include <cassert>
namespace world {
/// Universe unit
struct Voxel {
/// Packed value
/// swap(1) + material(12) + density(3)
uint16_t value;
using material_t = uint_fast16_t;
using density_t = uint_fast8_t;
constexpr static const density_t DENSITY_MAX = 0b0111;
Voxel(uint16_t value = 0): value(value) { }
Voxel(material_t material, density_t density, bool swap = false) {
assert(density <= DENSITY_MAX);
assert(material < (1 << 12));
value = (swap & 0b1000'0000'0000'0000) |
((material << 3) & 0b0111'1111'1111'1000) |
(density & DENSITY_MAX);
}
/// Material type
constexpr inline material_t material() const {
return (value & 0b0111'1111'1111'1000) >> 3;
}
/// Texture idx
constexpr inline uint16_t texture() const {
return materials::textures_map[material()];
}
/// Quantity of element
constexpr inline density_t density() const {
return value & DENSITY_MAX;
}
/// Quantity of element on [0, 1]
constexpr inline float density_ratio() const {
return density() * 1.f / world::Voxel::DENSITY_MAX;
}
/// Swap value
/// Use external metadata table
constexpr inline bool swap() const {
return value & 0b1000'0000'0000'0000;
}
/// Is solid
constexpr inline bool is_solid() const {
return density() > 0 && materials::solidity[material()];
}
/// Is visible matter
constexpr inline bool is_visible() const {
return !materials::invisibility[material()];
}
/// Contains matter
constexpr inline bool is_material() const {
return density() > 0 && is_visible();
}
/// Is full
constexpr inline bool is_full() const {
return density() == DENSITY_MAX && !materials::transparency[material()];
}
};
/// Stock of material
struct Item {
/// Quantity of material
unsigned long long Count;
/// Material type
/// @see world::materials
Voxel::material_t Material;
};
/// List of materials
struct ItemList: robin_hood::unordered_map<Voxel::material_t, unsigned long long> {
void add(const std::optional<Item>& item) {
if(item) {
(*this)[item.value().Material] += item.value().Count;
}
}
};
}