Initial commit: Final state of the master project
This commit is contained in:
170
Research/scene/Material/BitsMaterial.h
Normal file
170
Research/scene/Material/BitsMaterial.h
Normal file
@@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../core/BitHelper.h"
|
||||
#include "../../core/Defines.h"
|
||||
#include <cmath>
|
||||
|
||||
template <unsigned N>
|
||||
class BitsMaterial
|
||||
{
|
||||
public:
|
||||
const static size_t BYTECOUNT = N / 8 + ((N % 8) == 0 ? 0 : 1); // Calculate the space needed to store the required number of bits
|
||||
const static unsigned8 BITS = N;
|
||||
private:
|
||||
unsigned8 mValue[BYTECOUNT];
|
||||
|
||||
static size_t GrabBits(size_t value, unsigned8 startBit, unsigned8 length) {
|
||||
return ((BitHelper::GetLSMask<size_t>(startBit, startBit + length)) & value) >> startBit;
|
||||
}
|
||||
static size_t GrabBits(size_t value, unsigned8 startBit) { return GrabBits(value, startBit, N); }
|
||||
|
||||
inline void Init(size_t value)
|
||||
{
|
||||
for (unsigned8 i = 0; i < BYTECOUNT; i++)
|
||||
mValue[BYTECOUNT - i - 1] = (unsigned8)GrabBits(value, i * 8, 8);
|
||||
}
|
||||
public:
|
||||
BitsMaterial() { mValue[0] = 0; }
|
||||
BitsMaterial(size_t value) { Init(value); }
|
||||
// Grab some bits from the number and store them in this material
|
||||
BitsMaterial(unsigned value, unsigned8 startBit) { Init(GrabBits(value, startBit)); }
|
||||
~BitsMaterial() {}
|
||||
|
||||
bool Empty() { return mValue == 0; }
|
||||
|
||||
glm::u16vec3 GetProperties() const {
|
||||
unsigned32 value = (unsigned32)GetValue();
|
||||
return glm::u16vec3(GrabBits(value, 21, 11), GrabBits(value, 10, 11), GrabBits(value, 0, 10));
|
||||
}
|
||||
void SetProperties(glm::u16vec3 material)
|
||||
{
|
||||
unsigned32 value = (((unsigned32)material.x) << 21) | (((unsigned32)material.y & BitHelper::GetLSMask<unsigned32>(0, 11)) << 10) | (((unsigned32)material.z) & BitHelper::GetLSMask<unsigned32>(0, 10));
|
||||
Init(value);
|
||||
}
|
||||
|
||||
size_t GetValue() const {
|
||||
size_t value = 0;
|
||||
for (unsigned8 i = 0; i < BYTECOUNT; i++)
|
||||
value |= mValue[i] << ((BYTECOUNT - i - 1) >> 3); // Get the value, shift it to the correct position, and add it to the GetValue() result
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string GetTypeSuffix() const {
|
||||
return "b" + std::to_string(N);
|
||||
}
|
||||
|
||||
static float Distance(BitsMaterial a, BitsMaterial b)
|
||||
{
|
||||
size_t maxValue = BitHelper::Exp2(N);
|
||||
return (float)std::abs((float)b.GetValue() - (float)a.GetValue()) / (float)maxValue;
|
||||
}
|
||||
|
||||
static BitsMaterial Average(const std::vector<BitsMaterial>& values)
|
||||
{
|
||||
size_t sum = 0;
|
||||
for (auto value : values) sum += value.GetValue();
|
||||
sum /= values.size();
|
||||
return BitsMaterial(sum);
|
||||
}
|
||||
|
||||
static BitsMaterial WeightedAverage(const std::vector<BitsMaterial>& values, std::vector<float> weights)
|
||||
{
|
||||
float sum = 0;
|
||||
for (size_t i = 0; i < values.size(); i++) sum += (float)values[i].GetValue() * weights[i];
|
||||
sum /= (float)CollectionHelper::Sum(weights);
|
||||
return BitsMaterial((size_t)sum);
|
||||
}
|
||||
|
||||
|
||||
void SetLS(size_t index, bool value)
|
||||
{
|
||||
size_t byte = index >> 8;
|
||||
unsigned8 mask = BitHelper::GetLSSingleBitMask<unsigned8>(index & 0x07);
|
||||
// Clear the bit
|
||||
mValue[byte] &= ~mask;
|
||||
// Set the bit
|
||||
if (value) mValue[byte] |= mask;
|
||||
}
|
||||
|
||||
bool GetLS(size_t index)
|
||||
{
|
||||
size_t byte = index >> 8;
|
||||
size_t bit = index % 8;
|
||||
return BitHelper::GetLS(mValue[byte], (unsigned8)bit);
|
||||
}
|
||||
|
||||
void SetHS(size_t index, bool value)
|
||||
{
|
||||
SetLS(N - index - 1, value);
|
||||
}
|
||||
|
||||
bool GetHS(size_t index)
|
||||
{
|
||||
return GetLS(N - index - 1);
|
||||
}
|
||||
|
||||
std::vector<unsigned8> Serialize() const {
|
||||
std::vector<unsigned8> res(BYTECOUNT);
|
||||
for (size_t i = 0; i < BYTECOUNT; i++) res[i] = mValue[i];
|
||||
return res;
|
||||
}
|
||||
|
||||
void Deserialize(std::vector<unsigned8> value) {
|
||||
assert(value.size() == BYTECOUNT);
|
||||
for (size_t i = 0; i < BYTECOUNT; i++) mValue[i] = value[i];
|
||||
}
|
||||
|
||||
void Serialize(std::ostream& stream) const {
|
||||
stream.write((char*)&mValue[0], BYTECOUNT);
|
||||
}
|
||||
void Deserialize(std::istream& stream) {
|
||||
stream.read((char*)&mValue[0], BYTECOUNT);
|
||||
}
|
||||
|
||||
bool operator==(const BitsMaterial<N>& other) const {
|
||||
for (unsigned i = 0; i < BYTECOUNT; i++)
|
||||
if (mValue[i] != other.mValue[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator<(const BitsMaterial<N>& other) const
|
||||
{
|
||||
for (unsigned8 i = 0; i < BYTECOUNT; i++)
|
||||
if (mValue[i] != other.mValue[i]) return mValue[i] < other.mValue[i];
|
||||
return false; // If they are equal, return false
|
||||
}
|
||||
|
||||
operator unsigned() const
|
||||
{
|
||||
return (unsigned32)GetValue();
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<unsigned N> struct hash <BitsMaterial<N>>
|
||||
{
|
||||
size_t operator()(BitsMaterial<N> const& value) const
|
||||
{
|
||||
// Check if a perfect hash is possible
|
||||
if (N < (sizeof(size_t) * 8))
|
||||
{
|
||||
return value.GetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: make a hash for all bytes
|
||||
return value.GetValue();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<unsigned N>
|
||||
struct BitsMaterialComparer
|
||||
{
|
||||
bool operator()(const BitsMaterial<N>& a, const BitsMaterial<N>& b)
|
||||
{
|
||||
return a.GetValue() < b.GetValue();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user