complete stroke direction fix
This commit is contained in:
@@ -55,30 +55,27 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
||||
{
|
||||
std::vector<StrokeSample> samples;
|
||||
auto dirs = m_interp_dir.compute();
|
||||
m_dirs_cache.insert(m_dirs_cache.end(), dirs.begin(), dirs.end());
|
||||
auto points = m_interp_main.compute();
|
||||
//if (!dirs.empty() && !points.empty())
|
||||
{
|
||||
LOG("dirs %f - points %f", m_interp_dir.dist, m_interp_main.dist);
|
||||
}
|
||||
int dir_i = 0;
|
||||
for (const auto& kp : points)
|
||||
{
|
||||
for (; m_dir_i < m_dirs_cache.size() && (kp.dist >= m_dirs_cache[m_dir_i].dist || !m_dir_valid); m_dir_i++)
|
||||
for (; need_dir() && dir_i < dirs.size() && (kp.dist >= dirs[dir_i].dist || !m_dir_valid); dir_i++)
|
||||
{
|
||||
m_dir_angle = -glm::orientedAngle(-m_dirs_cache[m_dir_i].dir, m_dir_ref);
|
||||
m_dir_angle = -glm::orientedAngle(-dirs[dir_i].dir, m_dir_ref);
|
||||
if (m_dir_angle > glm::radians(120.f) || !m_dir_valid)
|
||||
{
|
||||
auto old_dir = m_dir_ref;
|
||||
m_dir_ref = -m_dirs_cache[m_dir_i].dir;
|
||||
m_dir_ref = -dirs[dir_i].dir;
|
||||
m_dir_ref_angle = -glm::orientedAngle(m_dir_ref, { 1, 0 });
|
||||
m_dir_angle = -glm::orientedAngle(-m_dirs_cache[m_dir_i].dir, m_dir_ref);
|
||||
m_dir_angle = -glm::orientedAngle(-dirs[dir_i].dir, m_dir_ref);
|
||||
auto angle_diff = -glm::orientedAngle(m_dir_ref, old_dir);
|
||||
for (int i = 0; i < m_direction.m_count; i++)
|
||||
m_direction.m_vec[i] -= angle_diff;
|
||||
}
|
||||
if (glm::abs(m_direction.average() - m_dir_angle) > glm::radians(120.f))
|
||||
m_direction.clear();
|
||||
|
||||
if (!m_dir_valid)
|
||||
m_dir_init = m_dir_angle + m_dir_ref_angle;
|
||||
m_dir_valid = true;
|
||||
}
|
||||
auto s = randomize_sample(kp.pos, kp.pressure, m_dir_angle);
|
||||
@@ -89,6 +86,10 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
||||
m_direction.add(m_dir_angle);
|
||||
s.angle += m_direction.average() + m_dir_ref_angle;
|
||||
}
|
||||
else if (m_brush->m_tip_angle_init)
|
||||
{
|
||||
s.angle += m_dir_init;
|
||||
}
|
||||
m_prev_sample = s;
|
||||
samples.push_back(s);
|
||||
}
|
||||
@@ -204,9 +205,14 @@ std::vector<StrokeSample> Stroke::compute_samples_old()
|
||||
}
|
||||
bool Stroke::has_sample()
|
||||
{
|
||||
//return m_keypoints.size() < 2 ? false : // no keypoints
|
||||
// (m_keypoints.back().dist > (m_dist + m_step)); // check if next kp is closer than spacing
|
||||
return m_interp_main.ready() && m_interp_dir.ready_first;
|
||||
return m_interp_main.ready() && (m_interp_dir.ready_first || !need_dir());
|
||||
}
|
||||
|
||||
bool Stroke::need_dir() const noexcept
|
||||
{
|
||||
return m_brush->m_tip_angle_follow ||
|
||||
m_brush->m_tip_angle_init ||
|
||||
m_brush->m_jitter_angle > 0;
|
||||
}
|
||||
|
||||
void Stroke::reset(bool clear_keypoints /*= false*/)
|
||||
@@ -217,8 +223,6 @@ void Stroke::reset(bool clear_keypoints /*= false*/)
|
||||
m_dir_dist = 0;
|
||||
m_last_kp = 0;
|
||||
m_dist = 0.f;
|
||||
m_dir_i = 0;
|
||||
m_dirs_cache.clear();
|
||||
if (clear_keypoints)
|
||||
m_keypoints.clear();
|
||||
m_interp_main.reset(clear_keypoints);
|
||||
@@ -246,8 +250,6 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
m_step = glm::max(0.5f, m_brush->m_tip_spacing * size * App::I->zoom * pressure);
|
||||
}
|
||||
|
||||
float dist = m_keypoints.empty() ? m_step :
|
||||
m_keypoints.back().dist + glm::distance(m_keypoints.back().pos, pos);
|
||||
if (m_keypoints.empty())
|
||||
m_prev_sample = randomize_sample(pos, pressure, 0);
|
||||
else if (m_keypoints.back().pos == pos)
|
||||
@@ -255,7 +257,7 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
Keypoint kp;
|
||||
kp.pos = pos;
|
||||
kp.pressure = pressure;
|
||||
kp.dist = dist;
|
||||
kp.dist = 0;
|
||||
m_keypoints.push_back(kp);
|
||||
|
||||
m_interp_main.add(kp);
|
||||
@@ -263,8 +265,6 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
}
|
||||
void Stroke::start(const std::shared_ptr<Brush>& brush)
|
||||
{
|
||||
m_dir_i = 0;
|
||||
m_dirs_cache.clear();
|
||||
m_hold_points.clear();
|
||||
m_curve = 0.f;
|
||||
m_direction.clear();
|
||||
@@ -295,8 +295,8 @@ void Stroke::start(const std::shared_ptr<Brush>& brush)
|
||||
m_direction.resize(std::max<int>(1, m_brush->m_tip_angle_smooth * 200.f / m_step));
|
||||
prng.seed(0);
|
||||
|
||||
m_interp_main = SamplesInterpolator(m_step);
|
||||
m_interp_dir = SamplesInterpolator(std::max(4.f, m_step));
|
||||
m_interp_main = SamplesInterpolator(m_step, false);
|
||||
m_interp_dir = SamplesInterpolator(std::max(4.f, m_step), need_dir());
|
||||
}
|
||||
|
||||
bool Brush::load_tip(const std::string& path, const std::string& thumb)
|
||||
@@ -658,12 +658,14 @@ void Brush::write(BinaryStreamWriter& w) const
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Stroke::SamplesInterpolator::SamplesInterpolator(float sp) noexcept
|
||||
Stroke::SamplesInterpolator::SamplesInterpolator(float sp, bool compute_dir) noexcept
|
||||
{
|
||||
spacing = sp;
|
||||
dist = 0;
|
||||
first = true;
|
||||
ready_first = false;
|
||||
calc_dir = compute_dir;
|
||||
initial_kp_done = false;
|
||||
}
|
||||
|
||||
Stroke::SamplesInterpolator::SamplesInterpolator() noexcept
|
||||
@@ -672,6 +674,8 @@ Stroke::SamplesInterpolator::SamplesInterpolator() noexcept
|
||||
dist = 0;
|
||||
first = true;
|
||||
ready_first = false;
|
||||
calc_dir = false;
|
||||
initial_kp_done = false;
|
||||
}
|
||||
|
||||
void Stroke::SamplesInterpolator::add(const Keypoint& p) noexcept
|
||||
@@ -688,8 +692,8 @@ void Stroke::SamplesInterpolator::add(const Keypoint& p) noexcept
|
||||
|
||||
bool Stroke::SamplesInterpolator::ready() const noexcept
|
||||
{
|
||||
return keypoints.size() > 1 &&
|
||||
glm::distance(last.pos, keypoints.back().pos) > spacing;
|
||||
return keypoints.size() > 0 &&
|
||||
(glm::distance(last.pos, keypoints.back().pos) > spacing || !calc_dir);
|
||||
}
|
||||
|
||||
void Stroke::SamplesInterpolator::reset(bool clear_keypoints) noexcept
|
||||
@@ -697,6 +701,7 @@ void Stroke::SamplesInterpolator::reset(bool clear_keypoints) noexcept
|
||||
dist = 0;
|
||||
if (clear_keypoints || keypoints.empty())
|
||||
{
|
||||
initial_kp_done = false;
|
||||
ready_first = false;
|
||||
first = true;
|
||||
keypoints.clear();
|
||||
@@ -710,6 +715,11 @@ void Stroke::SamplesInterpolator::reset(bool clear_keypoints) noexcept
|
||||
std::vector<Stroke::Keypoint> Stroke::SamplesInterpolator::compute() noexcept
|
||||
{
|
||||
std::vector<Stroke::Keypoint> ret;
|
||||
if (!calc_dir && last.dist == 0 && !initial_kp_done)
|
||||
{
|
||||
initial_kp_done = true;
|
||||
ret.push_back(last);
|
||||
}
|
||||
for (const auto& kp : keypoints)
|
||||
{
|
||||
float d = glm::distance(last.pos, kp.pos);
|
||||
@@ -729,7 +739,15 @@ std::vector<Stroke::Keypoint> Stroke::SamplesInterpolator::compute() noexcept
|
||||
ret.push_back(p);
|
||||
}
|
||||
if (!ret.empty())
|
||||
{
|
||||
if (last.dist == 0 && calc_dir && !initial_kp_done)
|
||||
{
|
||||
last.dir = ret.front().dir;
|
||||
ret.insert(ret.begin(), last);
|
||||
initial_kp_done = true;
|
||||
}
|
||||
last = ret.back();
|
||||
}
|
||||
}
|
||||
if (!ret.empty())
|
||||
keypoints.clear();
|
||||
|
||||
@@ -157,12 +157,14 @@ public:
|
||||
{
|
||||
Keypoint last;
|
||||
std::vector<Keypoint> keypoints;
|
||||
bool initial_kp_done;
|
||||
bool ready_first;
|
||||
bool first;
|
||||
float spacing;
|
||||
float dist;
|
||||
bool calc_dir;
|
||||
SamplesInterpolator() noexcept;
|
||||
SamplesInterpolator(float sp) noexcept;
|
||||
SamplesInterpolator(float sp, bool compute_dir) noexcept;
|
||||
void add(const Keypoint& p) noexcept;
|
||||
bool ready() const noexcept;
|
||||
void reset(bool clear_keypoints) noexcept;
|
||||
@@ -171,8 +173,6 @@ public:
|
||||
int m_layer = 0;
|
||||
int m_dir_kp = 0;
|
||||
bool m_dir_valid = false;
|
||||
std::vector<Keypoint> m_dirs_cache;
|
||||
int m_dir_i = 0;
|
||||
glm::vec2 m_dir_ref = { 1, 0 };
|
||||
float m_dir_ref_angle = 0;
|
||||
float m_dir_dist = 0;
|
||||
@@ -200,6 +200,7 @@ public:
|
||||
void add_point(glm::vec3 pos, float pressure);
|
||||
void reset(bool clear_keypoints = false);
|
||||
bool has_sample();
|
||||
bool need_dir() const noexcept;
|
||||
std::vector<StrokeSample> compute_samples();
|
||||
std::vector<StrokeSample> compute_samples_old();
|
||||
StrokeSample randomize_sample(const glm::vec3& pos, float pressure, float curve_angle);
|
||||
|
||||
Reference in New Issue
Block a user