Files
panopainter/src/brush.h

167 lines
4.4 KiB
C++

#pragma once
#include "rtt.h"
#include "shader.h"
#include "texture.h"
class Brush
{
public:
//Brush() = default;
//Brush(const Brush& brush) = default;
std::string m_name;
std::shared_ptr<Texture2D> m_tip_texture;
std::string m_brush_path;
std::string m_brush_thumb_path;
std::shared_ptr<Texture2D> m_dual_texture;
std::string m_dual_path;
std::string m_dual_thumb_path;
std::shared_ptr<Texture2D> m_pattern_texture;
std::string m_pattern_path;
std::string m_texture_thumb_path;
glm::vec4 m_tip_color{0, 0, 0, 1};
float m_tip_size = .25f;
float m_tip_spacing = .25;
float m_tip_flow = 1;
float m_tip_opacity = 1;
float m_tip_angle = 0;
float m_tip_angle_delay = 0;
float m_tip_mix = 0;
float m_tip_wet = 0;
float m_tip_noise = 0;
float m_tip_hue = 0;
float m_tip_sat = 0;
float m_tip_val = 0;
bool m_tip_angle_follow = false;
bool m_tip_flow_pressure = false;
bool m_tip_size_pressure = false;
float m_jitter_scale = 0;
float m_jitter_angle = 0;
float m_jitter_spread = 0;
float m_jitter_flow = 0;
float m_jitter_hue = 0;
float m_jitter_sat = 0;
float m_jitter_val = 0;
int m_blend_mode = 0;
bool m_tip_invert = false;
bool m_tip_flipx = false;
bool m_tip_flipy = false;
bool m_pattern_enabled = false;
bool m_dual_enabled = false;
int m_dual_blend_mode = 1;
bool m_dual_randflip = false;
float m_dual_size = .25;
float m_dual_spacing = .25;
float m_dual_scatter = 0;
bool m_dual_scatter_axis = false;
bool m_dual_invert = false;
bool m_dual_flipx = false;
bool m_dual_flipy = false;
bool m_tip_randflipx = false;
bool m_tip_randflipy = false;
float m_tip_aspect = 0.5f;
float m_dual_flow = .75f;
float m_dual_opacity = 1.f;
float m_dual_rotate = .25f;
int m_pattern_blend_mode = 1;
bool m_pattern_eachsample = false;
bool m_pattern_invert = false;
bool m_pattern_flipx = false;
bool m_pattern_flipy = false;
float m_pattern_scale = .25f;
float m_pattern_brightness = 0.5f;
float m_pattern_contrast = 0.5f;
bool m_pattern_rand_offset = false;
float m_pattern_depth = 1.f;
bool load_tip(const std::string& path, const std::string& thumb);
bool load_dual(const std::string& path, const std::string& thumb);
bool load_pattern(const std::string& path, const std::string& thumb);
bool load();
};
struct StrokeSample
{
glm::vec3 col = { 0, 0, 0 };
glm::vec3 pos = { 0, 0, 0 };
glm::vec3 origin = { 0, 0, 0 };
glm::vec2 scale = { 1, 1 };
float size = 0;
float flow = 0;
float angle = 0;
bool valid() const
{
return !(
glm::isnan(angle) ||
glm::isinf(angle) ||
glm::any(glm::isnan(col)) ||
glm::any(glm::isnan(pos)) ||
glm::any(glm::isnan(origin))
);
}
};
class BrushMesh
{
public:
GLuint buffers[3]{ 0 };
GLuint vao{ 0 };
struct instance_t { glm::mat4 mvp; float flow; };
int loc_flow = 0;
int loc_mvp = 0;
bool create();
void draw(const std::vector<StrokeSample>& samples, const glm::mat4& proj);
};
class Stroke
{
public:
struct Keypoint
{
glm::vec3 pos = { 0, 0, 0 };
float pressure = 0;
float dist = 0;
};
struct Camera
{
glm::mat4 rot;
float fov = 0;
};
int m_layer = 0;
int m_dir_kp = 0;
bool m_dir_valid = false;
glm::vec2 m_dir_ref = { 1, 0 };
float m_dir_ref_angle = 0;
float m_dir_dist = 0;
float m_dir_step = 10;
float m_dir_angle = 0;
float m_curve = 0;
float m_dist = 0;
float m_step = 0;
float m_max_size = FLT_MAX;
bool m_filter_points = true;
Camera m_camera;
std::shared_ptr<Brush> m_brush;
cbuffer<float> m_direction{ 1 };
cbuffer<float> m_pressure_buff{ 10 };
cbuffer<glm::vec3> m_hsv_jitter{ 3 };
StrokeSample m_prev_sample;
std::vector<Keypoint> m_keypoints;
std::vector<std::pair<glm::vec3, float>> m_hold_points;
std::vector<StrokeSample> m_samples;
int m_last_kp;
std::minstd_rand prng;
void start(const std::shared_ptr<Brush>& brush);
void add_point(glm::vec3 pos, float pressure);
void reset(bool clear_keypoints = false);
bool has_sample();
std::vector<StrokeSample> compute_samples();
StrokeSample randomize_sample(const glm::vec3& pos, float pressure, float curve_angle);
};