#pragma once #include "../Defines.h" #include #include #include "../MathHelper.h" template class TransferFunction { public: struct Node { unsigned32 value; float opacity; T material; Node(unsigned32 value, float opacity, T mat) : value(value), opacity(opacity), material(mat) {} Node(unsigned32 value) : value(value), opacity(0), material(T()) {} }; struct NodeCompare { bool operator()(const Node& a, const Node& b) { return a.value < b.value; } }; TransferFunction() { } ~TransferFunction() { mFunction.clear(); } void AddNode(unsigned32 value, float opacity, T mat) { Node node(value, opacity, mat); auto pos = LowerBound(node); if (pos != mFunction.end() && pos->value == value) mFunction[pos - mFunction.begin()] = node; else mFunction.insert(pos, node); } template void Evaluate(unsigned32 value, float& outOpacity, T& outMat, Interpolator interpolator) const { Node node(value); // Set default values outOpacity = 1.f; outMat = T(); // Find the current node auto pos = LowerBound(node); if (pos == mFunction.end()) return; Node after = *pos; if (pos == mFunction.begin()) { outOpacity = after.opacity; outMat = after.material; return; } pos--; Node before = *pos; float t = float(value - before.value) / float(after.value - before.value); outMat = interpolator(before.material, after.material, t); outOpacity = MathHelper::lerp(t, before.opacity, after.opacity); } private: typename std::vector::const_iterator LowerBound(const Node& node) const { return std::lower_bound(mFunction.begin(), mFunction.end(), node, NodeCompare()); } std::vector mFunction; };