diff --git a/src/brush.cpp b/src/brush.cpp index f78e393..204ace1 100644 --- a/src/brush.cpp +++ b/src/brush.cpp @@ -55,30 +55,27 @@ std::vector Stroke::compute_samples() { std::vector 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 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 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) { - 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) m_direction.resize(std::max(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::SamplesInterpolator::compute() noexcept { std::vector 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::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(); diff --git a/src/brush.h b/src/brush.h index 6f09324..e08440c 100644 --- a/src/brush.h +++ b/src/brush.h @@ -157,12 +157,14 @@ public: { Keypoint last; std::vector 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 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 compute_samples(); std::vector compute_samples_old(); StrokeSample randomize_sample(const glm::vec3& pos, float pressure, float curve_angle);