enable rtt dtor, default values for <text> node, dual-brush wip, more brush options
This commit is contained in:
@@ -132,21 +132,28 @@ StrokeSample Stroke::randomize_sample(const glm::vec3& pos, float pressure, floa
|
||||
auto rnd_neg = [&] { return float((double)prng() / (double)prng.max() * 2.0 - 1.0); }; // normalized [-1, +1]
|
||||
auto rnd_rad = [&] { return float((double)prng() / (double)prng.max() * M_PI * 2.0); }; // normalized [0, 2pi]
|
||||
auto rnd_vec = [&] { float rad = rnd_rad(); return glm::vec3(cosf(rad), sinf(rad), 0); }; // normalized direction vector
|
||||
auto rnd_bneg = [&] { return prng() % 2 == 0 ? -1.f : 1.f; }; // -1 or 1
|
||||
|
||||
float size_dyn = m_brush->m_tip_size_pressure ? pressure : 1.f;
|
||||
float flow_dyn = m_brush->m_tip_flow_pressure ? pressure : 1.f;
|
||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||
|
||||
float randflipx = m_brush->m_tip_randflipx ? rnd_bneg() : 1.f;
|
||||
float randflipy = m_brush->m_tip_randflipy ? rnd_bneg() : 1.f;
|
||||
|
||||
StrokeSample s;
|
||||
s.scale.x = randflipx * (m_brush->m_tip_flipx ? -1.f : 1.f) *
|
||||
(m_brush->m_tip_aspect <= 0.5 ? m_brush->m_tip_aspect * 2.f : 1.f);
|
||||
s.scale.y = randflipy * (m_brush->m_tip_flipy ? -1.f : 1.f) *
|
||||
(m_brush->m_tip_aspect > 0.5 ? 1.f - (m_brush->m_tip_aspect - .5f) * 2.f : 1.f);
|
||||
s.origin = pos;
|
||||
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_neg() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
||||
s.size = 800.f * size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
||||
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * s.size);
|
||||
s.flow = m_brush->m_tip_flow * (1.f - rnd_nor() * m_brush->m_jitter_flow) * flow_dyn;
|
||||
auto hsv = convert_rgb2hsv(m_brush->m_tip_color);
|
||||
hsv.x = glm::clamp(glm::mix(hsv.x, (pressure - 0.5f) * 2.0f, m_brush->m_tip_hue * (float)m_brush->m_tip_hue_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_hue, 0.f, 1.f);
|
||||
hsv.y = glm::clamp(glm::mix(hsv.y, (1.f - pressure - 0.5f) * 2.0f, m_brush->m_tip_sat * (float)m_brush->m_tip_sat_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_sat, 0.f, 1.f);
|
||||
hsv.z = glm::clamp(glm::mix(hsv.z, (pressure - 0.5f) * 2.0f, m_brush->m_tip_val * (float)m_brush->m_tip_val_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_val, 0.f, 1.f);
|
||||
hsv.x = glm::clamp(glm::mix(hsv.x, (pressure - 0.5f) * 2.0f, m_brush->m_tip_hue) + (rnd_nor() - 0.5f) * m_brush->m_jitter_hue, 0.f, 1.f);
|
||||
hsv.y = glm::clamp(glm::mix(hsv.y, (1.f - pressure - 0.5f) * 2.0f, m_brush->m_tip_sat) + (rnd_nor() - 0.5f) * m_brush->m_jitter_sat, 0.f, 1.f);
|
||||
hsv.z = glm::clamp(glm::mix(hsv.z, (pressure - 0.5f) * 2.0f, m_brush->m_tip_val) + (rnd_nor() - 0.5f) * m_brush->m_jitter_val, 0.f, 1.f);
|
||||
m_hsv_jitter.add(hsv);
|
||||
s.col = convert_hsv2rgb(m_hsv_jitter.average());
|
||||
return s;
|
||||
@@ -159,13 +166,13 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
||||
samples.reserve(nsamples); // preallocate the estimate number of samples
|
||||
while (m_keypoints.back().dist > (m_dist + m_step))
|
||||
{
|
||||
bool is_first = m_last_kp == 0;
|
||||
m_dist += m_step;
|
||||
m_dir_dist += m_step;
|
||||
int old_kp = m_last_kp;
|
||||
while (m_dist > m_keypoints[m_last_kp + 1].dist)
|
||||
m_last_kp++;
|
||||
const auto& A = m_keypoints[m_last_kp];
|
||||
const auto& B = m_keypoints[m_last_kp + 1]; // NOTE: this should be true when while is true
|
||||
const auto& A = m_keypoints[old_kp];
|
||||
const auto& B = m_keypoints[m_last_kp == old_kp ? m_last_kp + 1 : m_last_kp]; // NOTE: this should be true when while is true
|
||||
float t = (m_dist - A.dist) / (B.dist - A.dist); // NOTE: must be A != B
|
||||
auto pos = glm::lerp(A.pos, B.pos, t);
|
||||
float pressure = glm::lerp(A.pressure, B.pressure, t);
|
||||
@@ -175,16 +182,20 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
||||
{
|
||||
if (m_brush->m_tip_angle_follow)
|
||||
{
|
||||
if (m_dir_dist > m_dir_step)
|
||||
if (m_dir_dist > m_dir_step && m_last_kp != m_dir_kp)
|
||||
{
|
||||
glm::vec2 v = glm::normalize(m_keypoints[m_last_kp].pos - m_keypoints[m_dir_kp].pos);
|
||||
m_dir_angle = -glm::orientedAngle(v, m_dir_ref);
|
||||
if (glm::abs(m_dir_angle) > glm::pi<float>() / 2.f || !m_dir_valid)
|
||||
if (m_brush->m_tip_angle_delay > 0 && (glm::abs(m_dir_angle) > glm::pi<float>() / 2.f || !m_dir_valid))
|
||||
{
|
||||
m_direction.clear();
|
||||
auto old_dir = m_dir_ref;
|
||||
m_dir_ref = v;
|
||||
m_dir_ref_angle = -glm::orientedAngle(m_dir_ref, { 1, 0 });
|
||||
m_dir_angle = 0;
|
||||
//m_direction.clear();
|
||||
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;
|
||||
}
|
||||
m_dir_kp = m_last_kp;
|
||||
m_dir_dist = 0;
|
||||
@@ -245,7 +256,7 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
if (m_brush->m_tip_size_pressure)
|
||||
{
|
||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||
m_step = glm::max(m_brush->m_tip_spacing * size * pressure * 800.f, 1.f);
|
||||
m_step = glm::max(m_brush->m_tip_spacing * size * pressure * 800.f, 0.1f);
|
||||
}
|
||||
|
||||
float dist = m_keypoints.empty() ? m_step :
|
||||
@@ -276,6 +287,7 @@ void Stroke::start(const std::shared_ptr<Brush>& brush)
|
||||
m_brush = brush;
|
||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||
m_step = glm::max(m_brush->m_tip_spacing * size * 800.f, 1.f);
|
||||
m_direction.resize(std::max<int>(1, m_brush->m_tip_angle_delay * 200.f / m_step));
|
||||
prng.seed(0);
|
||||
}
|
||||
|
||||
@@ -291,6 +303,18 @@ bool Brush::load_texture(const std::string& path, const std::string& thumb)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Brush::load_dual(const std::string& path, const std::string& thumb)
|
||||
{
|
||||
m_dual_texture = std::make_shared<Texture2D>();
|
||||
if (!m_dual_texture->load(path))
|
||||
return false;
|
||||
m_dual_texture->create_mipmaps();
|
||||
m_dual_texture->auto_destroy = true;
|
||||
m_dual_path = path;
|
||||
m_dual_thumb_path = thumb;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Brush::load_stencil(const std::string& path)
|
||||
{
|
||||
m_stencil_texture = std::make_shared<Texture2D>();
|
||||
@@ -316,6 +340,19 @@ bool Brush::load()
|
||||
m_tip_texture->create_mipmaps();
|
||||
m_tip_texture->auto_destroy = true;
|
||||
}
|
||||
if (!m_dual_path.empty())
|
||||
{
|
||||
m_dual_texture = std::make_shared<Texture2D>();
|
||||
if (!m_dual_texture->load(m_dual_path))
|
||||
{
|
||||
LOG("failed to load %s", m_dual_path.c_str());
|
||||
m_tip_texture = nullptr;
|
||||
m_dual_texture = nullptr;
|
||||
return false;
|
||||
}
|
||||
m_dual_texture->create_mipmaps();
|
||||
m_dual_texture->auto_destroy = true;
|
||||
}
|
||||
if (!m_stencil_path.empty())
|
||||
{
|
||||
m_stencil_texture = std::make_shared<Texture2D>();
|
||||
@@ -323,6 +360,7 @@ bool Brush::load()
|
||||
{
|
||||
LOG("failed to load %s", m_stencil_path.c_str());
|
||||
m_tip_texture = nullptr;
|
||||
m_dual_texture = nullptr;
|
||||
m_stencil_texture = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user