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