Add easing function, move gradient to a separate header
This commit is contained in:
parent
1e4fb66a89
commit
d421fc8c65
3 changed files with 79 additions and 63 deletions
|
|
@ -7,7 +7,7 @@
|
||||||
#include <psemek/geom/homogeneous.hpp>
|
#include <psemek/geom/homogeneous.hpp>
|
||||||
#include <psemek/geom/constants.hpp>
|
#include <psemek/geom/constants.hpp>
|
||||||
#include <psemek/geom/math.hpp>
|
#include <psemek/geom/math.hpp>
|
||||||
#include <psemek/geom/easing.hpp>
|
#include <psemek/geom/gradient.hpp>
|
||||||
#include <psemek/gfx/gl.hpp>
|
#include <psemek/gfx/gl.hpp>
|
||||||
#include <psemek/gfx/mesh.hpp>
|
#include <psemek/gfx/mesh.hpp>
|
||||||
#include <psemek/gfx/renderer/simple.hpp>
|
#include <psemek/gfx/renderer/simple.hpp>
|
||||||
|
|
@ -164,7 +164,7 @@ struct cloud_app
|
||||||
|
|
||||||
float step;
|
float step;
|
||||||
|
|
||||||
float max_density = 8.f;
|
float max_density = 6.f;
|
||||||
geom::interval<float> harmonic_range;
|
geom::interval<float> harmonic_range;
|
||||||
|
|
||||||
util::clock<std::chrono::duration<float>> clock;
|
util::clock<std::chrono::duration<float>> clock;
|
||||||
|
|
@ -241,7 +241,7 @@ struct cloud_app
|
||||||
|
|
||||||
pcg::fractal<pcg::perlin<float, 3>> perlin(std::move(grad), std::move(weights));
|
pcg::fractal<pcg::perlin<float, 3>> perlin(std::move(grad), std::move(weights));
|
||||||
|
|
||||||
geom::gradient<float> g(geom::vector<float, 2>{0.2f, 0.f}, geom::easing::cubic, geom::vector{0.4f, max_density});
|
geom::gradient<float> g(std::make_pair(0.2f, 0.f), geom::easing_type::cubic, std::pair{0.4f, max_density});
|
||||||
|
|
||||||
util::array<std::uint8_t, 3> cloud_data({cloud_size[0], cloud_size[1], cloud_size[2]});
|
util::array<std::uint8_t, 3> cloud_data({cloud_size[0], cloud_size[1], cloud_size[2]});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/geom/vector.hpp>
|
|
||||||
#include <psemek/util/assert.hpp>
|
#include <psemek/util/assert.hpp>
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace psemek::geom
|
namespace psemek::geom
|
||||||
{
|
{
|
||||||
|
|
||||||
enum class easing
|
enum class easing_type
|
||||||
{
|
{
|
||||||
nearest,
|
nearest,
|
||||||
constant_left,
|
constant_left,
|
||||||
|
|
@ -20,64 +17,20 @@ namespace psemek::geom
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct gradient
|
T easing(easing_type type, T t)
|
||||||
{
|
{
|
||||||
template <typename ... Args>
|
switch (type) {
|
||||||
gradient(Args const & ... args)
|
case easing_type::nearest: return (2 * t < 1) ? 0 : 1;
|
||||||
{
|
case easing_type::constant_left: return 0;
|
||||||
init(args...);
|
case easing_type::constant_right: return 1;
|
||||||
|
case easing_type::linear: return t;
|
||||||
|
case easing_type::quadratic_in: return t * t;
|
||||||
|
case easing_type::quadratic_out: return t * (2 - t);
|
||||||
|
case easing_type::cubic: return t * t * (3 - 2 * t);
|
||||||
|
default: assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
gradient(std::vector<geom::vector<T, 2>> points, std::vector<easing> segments)
|
return {};
|
||||||
{
|
}
|
||||||
assert(points.size() == segments.size() + 1);
|
|
||||||
points_ = std::move(points);
|
|
||||||
segments_ = std::move(segments);
|
|
||||||
}
|
|
||||||
|
|
||||||
T operator()(T const & t) const
|
|
||||||
{
|
|
||||||
auto it = std::upper_bound(points_.begin(), points_.end(), t, [](T const & t, auto const & p){ return t < p[0]; });
|
|
||||||
if (it == points_.begin())
|
|
||||||
return points_.front()[1];
|
|
||||||
if (it == points_.end())
|
|
||||||
return points_.back()[1];
|
|
||||||
|
|
||||||
std::size_t i = (it - points_.begin()) - 1;
|
|
||||||
|
|
||||||
T s = (t - points_[i][0]) * (points_[i + 1][1] - points_[i][1]);
|
|
||||||
|
|
||||||
switch (segments_[i]) {
|
|
||||||
case easing::nearest: s = (2 * s < 1) ? 0 : 1; break;
|
|
||||||
case easing::constant_left: s = 0; break;
|
|
||||||
case easing::constant_right: s = 1; break;
|
|
||||||
case easing::linear: break;
|
|
||||||
case easing::quadratic_in: s = s * s; break;
|
|
||||||
case easing::quadratic_out: s = s * (2 - s); break;
|
|
||||||
case easing::cubic: s = s * s * (3 - 2 * s); break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return points_[i][1] + s * (points_[i + 1][1] - points_[i][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<geom::vector<T, 2>> points_;
|
|
||||||
std::vector<easing> segments_;
|
|
||||||
|
|
||||||
void init(geom::vector<T, 2> const & p)
|
|
||||||
{
|
|
||||||
points_.push_back(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ... Args>
|
|
||||||
void init(geom::vector<T, 2> const & p, easing t, Args const & ... args)
|
|
||||||
{
|
|
||||||
points_.push_back(p);
|
|
||||||
segments_.push_back(t);
|
|
||||||
init(args...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
libs/geom/include/psemek/geom/gradient.hpp
Normal file
63
libs/geom/include/psemek/geom/gradient.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/geom/easing.hpp>
|
||||||
|
#include <psemek/geom/math.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace psemek::geom
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T, typename R = T>
|
||||||
|
struct gradient
|
||||||
|
{
|
||||||
|
using result_type = R;
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
gradient(Args const & ... args)
|
||||||
|
{
|
||||||
|
init(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
gradient(std::vector<std::pair<T, R>> points, std::vector<easing_type> segments)
|
||||||
|
{
|
||||||
|
assert(points.size() == segments.size() + 1);
|
||||||
|
points_ = std::move(points);
|
||||||
|
segments_ = std::move(segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
R operator()(T const & t) const
|
||||||
|
{
|
||||||
|
auto it = std::upper_bound(points_.begin(), points_.end(), t, [](T const & t, auto const & p){ return t < p.first; });
|
||||||
|
if (it == points_.begin())
|
||||||
|
return points_.front().second;
|
||||||
|
if (it == points_.end())
|
||||||
|
return points_.back().second;
|
||||||
|
|
||||||
|
std::size_t i = (it - points_.begin()) - 1;
|
||||||
|
|
||||||
|
T s = easing(segments_[i], (t - points_[i].first) / (points_[i + 1].first - points_[i].first));
|
||||||
|
|
||||||
|
return lerp(points_[i].second, points_[i + 1].second, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<T, R>> points_;
|
||||||
|
std::vector<easing_type> segments_;
|
||||||
|
|
||||||
|
void init(std::pair<T, R> const & p)
|
||||||
|
{
|
||||||
|
points_.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ... Args>
|
||||||
|
void init(std::pair<T, R> const & p, easing_type t, Args const & ... args)
|
||||||
|
{
|
||||||
|
points_.push_back(p);
|
||||||
|
segments_.push_back(t);
|
||||||
|
init(args...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue