84 lines
2.6 KiB
C++
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;
|
|
}
|
|
}
|
|
};
|
|
}
|