Initial commit: Final state of the master project
This commit is contained in:
169
Research/scene/Material/MaterialPair.h
Normal file
169
Research/scene/Material/MaterialPair.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
#include "Color.h"
|
||||
#include "../../core/ColorHelper.h"
|
||||
#include "../../inc/glm/glm.hpp"
|
||||
#include "../../core/Hashers.h"
|
||||
#include "../../core/Comparers.h"
|
||||
#include "../../core/CollectionHelper.h"
|
||||
#include "../../core/Serializer.h"
|
||||
#include "../../core/BitHelper.h"
|
||||
|
||||
template<typename U, typename V>
|
||||
class MaterialPair
|
||||
{
|
||||
private:
|
||||
U mFirst;
|
||||
V mSecond;
|
||||
public:
|
||||
static const unsigned8 BITS = U::BITS + V::BITS;
|
||||
static const unsigned8 CHANNELSPERPIXEL = BITS % 32 == 0 ? 4 : 3;
|
||||
|
||||
MaterialPair() : mFirst(U()), mSecond(V()) {}
|
||||
MaterialPair(U first, V second) : mFirst(first), mSecond(second) {}
|
||||
MaterialPair(std::pair<U, V> pair) : mFirst(pair.first), mSecond(pair.second) {}
|
||||
template<typename UC, typename VC>
|
||||
MaterialPair(UC first, VC second) : MaterialPair(U(first), V(second)) {}
|
||||
|
||||
const U& GetFirst() const { return mFirst; }
|
||||
void SetFirst(U value) { mFirst = value; }
|
||||
const V& GetSecond() const { return mSecond; }
|
||||
void SetSecond(V value) { mSecond = value; }
|
||||
|
||||
static MaterialPair Average(const std::vector<MaterialPair>& values)
|
||||
{
|
||||
std::vector<U> firsts(values.size());
|
||||
std::vector<V> seconds(values.size());
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
{
|
||||
firsts[i] = values[i].GetFirst();
|
||||
seconds[i] = values[i].GetSecond();
|
||||
}
|
||||
return MaterialPair(U::Average(first), V::Average(seconds));
|
||||
}
|
||||
static MaterialPair WeightedAverage(const std::vector<MaterialPair>& values, const std::vector<float>& weights)
|
||||
{
|
||||
std::vector<U> firsts(values.size());
|
||||
std::vector<V> seconds(values.size());
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
{
|
||||
firsts[i] = values[i].GetFirst();
|
||||
seconds[i] = values[i].GetSecond();
|
||||
}
|
||||
return MaterialPair(U::WeightedAverage(firsts, weights), V::WeightedAverage(seconds, weights));
|
||||
}
|
||||
|
||||
static float Distance(const MaterialPair& a, const MaterialPair& b)
|
||||
{
|
||||
return (U::Distance(a.GetFirst(), a.GetSecond()) + V::Distance(a.GetSecond(), b.GetSecond())) * 0.5f;
|
||||
}
|
||||
|
||||
std::string GetTypeSuffix() const { return GetFirst().GetTypeSuffix() + GetSecond().GetTypeSuffix(); }
|
||||
|
||||
std::vector<unsigned8> Serialize() const {
|
||||
std::vector<unsigned8> firstSerialized = GetFirst().Serialize();
|
||||
std::vector<unsigned8> secondSerialized = GetSecond().Serialize();
|
||||
firstSerialized.insert(firstSerialized.end(), secondSerialized.begin(), secondSerialized.end());
|
||||
return firstSerialized;
|
||||
};
|
||||
|
||||
void Deserialize(const std::vector<unsigned8>& value)
|
||||
{
|
||||
mFirst.Deserialize(std::vector<unsigned8>(value.begin(), value.begin() + sizeof(mFirst)));
|
||||
mSecond.Deserialize(std::vector<unsigned8>(value.begin() + sizeof(mFirst), value.end()));
|
||||
}
|
||||
|
||||
bool operator==(const MaterialPair& v) const { return v.mFirst == mFirst && v.mSecond == mSecond; }
|
||||
bool operator!=(const MaterialPair& n) const { return !(n == *this); }
|
||||
|
||||
//// Assignment operator, used for easy access to different kinds of materials
|
||||
//ColorAndValue& operator=(const unsigned& source)
|
||||
//{
|
||||
// mValue = source & 0x3FF;
|
||||
// glm::u8vec3 color;
|
||||
// color.r = (source >> (10 + 14 - 1)) & 0xFE;
|
||||
// color.g = (source >> (10 + 7 - 1)) & 0xFE;
|
||||
// color.b = (source >> (10 - 1)) & 0xFE;
|
||||
// mColor = Color(color);
|
||||
//}
|
||||
//operator unsigned() const
|
||||
//{
|
||||
// // Value is stored in the 10 lowest siginificant bits
|
||||
// unsigned32 res = (unsigned32)mValue;
|
||||
// // Colors are stored in the 21 highest significant bits (7 bits per channel, doesn't fit otherwise...)
|
||||
// res |= ((unsigned32)mColor.GetR() & 0xFE) << (10 + 14 - 1);
|
||||
// res |= ((unsigned32)mColor.GetG() & 0xFE) << (10 + 7 - 1);
|
||||
// res |= ((unsigned32)mColor.GetB() & 0xFE) << (10 - 1);
|
||||
// return res;
|
||||
//}
|
||||
};
|
||||
|
||||
template<typename U, typename V>
|
||||
struct NearestFinder<MaterialPair<U, V>>
|
||||
{
|
||||
MaterialPair<U, V> operator()(const MaterialPair<U, V>& source, const std::vector<MaterialPair<U, V>>& values)
|
||||
{
|
||||
std::vector<float> distances(values.size());
|
||||
// Distances are defined as the sum.
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
distances[i] = U::Distance(source.GetFirst(), values[i].GetFirst()) + V::Distance(source.GetSecond(), values[i].GetSecond());
|
||||
auto minIt = std::min_element(distances.begin(), distances.end());
|
||||
size_t minIndex = std::distance(distances.begin(), minIt);
|
||||
return values[minIndex];
|
||||
}
|
||||
};
|
||||
template<typename U, typename V>
|
||||
struct ParallelNearestFinder<MaterialPair<U, V>>
|
||||
{
|
||||
MaterialPair<U, V> operator()(const MaterialPair<U, V>& source, const std::vector<MaterialPair<U, V>>& values)
|
||||
{
|
||||
std::vector<float> distances(values.size());
|
||||
// Distances are defined as the sum.
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
distances[i] = U::Distance(source.GetFirst(), values[i].GetFirst()) + V::Distance(source.GetSecond(), values[i].GetSecond());
|
||||
auto minIt = std::min_element(distances.begin(), distances.end());
|
||||
size_t minIndex = std::distance(distances.begin(), minIt);
|
||||
return values[minIndex];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace std {
|
||||
template<typename U, typename V>
|
||||
struct hash<MaterialPair<U, V>> {
|
||||
size_t operator()(const MaterialPair<U, V> &value) const {
|
||||
#ifdef ENVIRONMENT64
|
||||
size_t cHash = std::hash<U>()(value.GetFirst());
|
||||
size_t nHash = std::hash<V>()(value.GetSecond());
|
||||
return cHash | BitHelper::CircularShiftLeft<size_t>(nHash, V::BITS);
|
||||
#else
|
||||
return (unsigned32)value;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename U, typename UCompare, typename V, typename VCompare>
|
||||
struct MaterialPairCompare
|
||||
{
|
||||
bool operator()(const MaterialPair<U, V>& a, const MaterialPair<U, V>& b) const
|
||||
{
|
||||
if (a.GetFirst() != b.GetFirst()) return UCompare()(a.GetFirst(), b.GetFirst());
|
||||
return VCompare()(a.GetSecond(), b.GetSecond());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename U, typename V>
|
||||
struct Serializer<MaterialPair<U, V>>
|
||||
{
|
||||
static void Serialize(const MaterialPair<U, V>& value, std::ostream& out)
|
||||
{
|
||||
Serializer<U>::Serialize(value.GetFirst(), out);
|
||||
Serializer<V>::Serialize(value.GetSecond(), out);
|
||||
}
|
||||
|
||||
static void Deserialize(MaterialPair<U, V>& value, std::istream& in)
|
||||
{
|
||||
U first; Serializer<U>::Deserialize(first, in); value.SetFirst(first);
|
||||
V second; Serializer<V>::Deserialize(second, in); value.SetSecond(second);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user