implement simple brush projection on single cube face, add camera rotation instead of pan
This commit is contained in:
@@ -54,9 +54,15 @@ public:
|
||||
float pressure;
|
||||
float dist;
|
||||
};
|
||||
struct Camera
|
||||
{
|
||||
glm::vec2 rot;
|
||||
float fov;
|
||||
};
|
||||
int m_layer;
|
||||
float m_dist;
|
||||
float m_step;
|
||||
Camera m_camera;
|
||||
ui::Brush m_brush;
|
||||
std::vector<Keypoint> m_keypoints;
|
||||
std::vector<StrokeSample> m_samples;
|
||||
|
||||
@@ -72,8 +72,46 @@ void ui::Canvas::stroke_draw()
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||
for (const auto& s : samples)
|
||||
{
|
||||
auto unproject = [](glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj, glm::vec3& out_origin, glm::vec3& out_dir) {
|
||||
auto clip_space = glm::vec2(loc.x, vp.w - loc.y - 1.f) / vp.zw() * 2.f - 1.f;
|
||||
auto inv = glm::inverse(proj * camera);
|
||||
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
||||
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
||||
out_origin = (wp0 / wp0.w).xyz();
|
||||
out_dir = glm::normalize((wp1 / wp1.w).xyz() - out_origin);
|
||||
};
|
||||
auto intersect = [](glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin, glm::vec3 plane_normal, glm::vec3& out_hit) {
|
||||
float den = glm::dot(ray_dir, plane_normal);
|
||||
if (den == 0)
|
||||
return false; // no intersection
|
||||
float num = glm::dot(plane_origin - ray_origin, plane_normal);
|
||||
float t = num / den;
|
||||
if (t > 0)
|
||||
out_hit = ray_origin + ray_dir * t;
|
||||
else
|
||||
// negative intersection
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
glm::vec3 ray_origin, ray_dir;
|
||||
unproject(s.pos, { 0, 0, m_box.zw }, m_mv, m_proj, ray_origin, ray_dir);
|
||||
glm::vec3 plane_origin{ 0, 0, -1 }, plane_dir{ 0, 0, 1 };
|
||||
glm::vec3 hit;
|
||||
glm::vec2 fb_pos;
|
||||
if (intersect(ray_origin, ray_dir, plane_origin, plane_dir, hit))
|
||||
{
|
||||
glm::mat4 plane_camera = glm::lookAt(plane_origin, plane_dir, { 0, 1, 0 });
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
if (glm::abs(plane_local.x) < 0.5f && glm::abs(plane_local.y) < 0.5f)
|
||||
{
|
||||
fb_pos.x = -(plane_local.x - 0.5f) * m_width;
|
||||
fb_pos.y = (plane_local.y + 0.5f) * m_height;
|
||||
LOG("draw %f %f", fb_pos.x, fb_pos.y);
|
||||
}
|
||||
}
|
||||
|
||||
auto mvp = proj *
|
||||
glm::translate(glm::vec3(s.pos, 0)) *
|
||||
glm::translate(glm::vec3(fb_pos, 0)) *
|
||||
glm::scale(glm::vec3(s.size, s.size, 1)) *
|
||||
glm::eulerAngleZ(s.angle);
|
||||
|
||||
@@ -112,10 +150,10 @@ void ui::Canvas::stroke_draw()
|
||||
m_box.xy = glm::min(m_box.xy(), (glm::vec2)tex_pos);
|
||||
m_box.zw = glm::max(m_box.zw(), (glm::vec2)(tex_pos + tex_sz));
|
||||
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, mvp);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::mat4());
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, s.flow);
|
||||
//m_plane.update_vertices(P);
|
||||
m_plane.draw_fill();
|
||||
m_plane_brush.update_vertices(P);
|
||||
m_plane_brush.draw_fill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +244,7 @@ void ui::Canvas::stroke_update(glm::vec2 point, float pressure)
|
||||
void ui::Canvas::stroke_start(glm::vec2 point, float pressure, const ui::Brush& brush)
|
||||
{
|
||||
m_current_stroke = std::make_unique<Stroke>();
|
||||
m_current_stroke->m_camera = { m_cam_rot, m_cam_fov };
|
||||
m_current_stroke->start(brush);
|
||||
m_current_stroke->add_point(point, pressure);
|
||||
|
||||
@@ -260,6 +299,7 @@ bool ui::Canvas::create(int width, int height)
|
||||
m_sampler.create();
|
||||
m_sampler_bg.create();
|
||||
m_plane.create<1>(1, 1);
|
||||
m_plane_brush.create<1>(1, 1);
|
||||
m_mesh.create();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ NS_START
|
||||
class Canvas
|
||||
{
|
||||
Plane m_plane;
|
||||
Plane m_plane_brush;
|
||||
BrushMesh m_mesh;
|
||||
bool m_dirty = false;
|
||||
public:
|
||||
bool m_erase = false;
|
||||
glm::mat4 m_mvp;
|
||||
glm::mat4 m_mv;
|
||||
glm::mat4 m_proj;
|
||||
glm::vec4 m_box;
|
||||
int m_width;
|
||||
int m_height;
|
||||
@@ -30,6 +32,8 @@ public:
|
||||
Texture2D m_tex2;
|
||||
Sampler m_sampler;
|
||||
Sampler m_sampler_bg;
|
||||
glm::vec2 m_cam_rot;
|
||||
float m_cam_fov = 85;
|
||||
|
||||
bool create(int width, int height);
|
||||
void resize(int width, int height);
|
||||
|
||||
100
engine/layout.h
100
engine/layout.h
@@ -1859,8 +1859,10 @@ class NodeCanvas : public Node
|
||||
glm::vec2 m_dragR_start;
|
||||
glm::vec2 m_pan_start;
|
||||
glm::vec2 m_pan;
|
||||
glm::vec2 m_cur;
|
||||
float m_zoom_canvas = 1.f;
|
||||
float m_zoom_start;
|
||||
bool method = true;
|
||||
public:
|
||||
std::unique_ptr<ui::Canvas> m_canvas;
|
||||
ui::Brush m_brush;
|
||||
@@ -1891,15 +1893,24 @@ public:
|
||||
glViewport(c.x, c.y, c.z, c.w);
|
||||
|
||||
glm::vec2 sz = { m_canvas->m_width, m_canvas->m_height };
|
||||
m_canvas->m_mvp = glm::ortho(0.f, box.z, 0.f, box.w, -1.f, 1.f) *
|
||||
glm::translate(glm::vec3(m_pan + m_size * 0.5f * zoom, 0)) * // pan
|
||||
glm::scale(glm::vec3(zoom * m_zoom_canvas, zoom * m_zoom_canvas, 1)) *
|
||||
glm::translate(glm::vec3(-sz/2.f, 0));
|
||||
|
||||
auto plane_mvp = glm::ortho(0.f, box.z, 0.f, box.w, -1.f, 1.f) *
|
||||
glm::translate(glm::vec3(m_pan + m_size * 0.5f * zoom, 0)) * // pan
|
||||
m_canvas->m_cam_rot = m_pan * 0.001f;
|
||||
|
||||
//glm::mat4 proj = glm::ortho(0.f, box.z, 0.f, box.w, -1000.f, 1000.f);
|
||||
glm::mat4 proj = glm::perspective(glm::radians(m_canvas->m_cam_fov), box.z / box.w, 0.1f, 1000.f);
|
||||
glm::mat4 camera = glm::eulerAngleXY(m_canvas->m_cam_rot.y, m_canvas->m_cam_rot.x);
|
||||
glm::mat4 transform =
|
||||
glm::translate(glm::vec3(m_pan + m_size * 0.5f * zoom, -1)) * // pan
|
||||
glm::scale(glm::vec3(zoom * m_zoom_canvas, zoom * m_zoom_canvas, 1)) *
|
||||
glm::scale(glm::vec3(sz, 1));
|
||||
glm::eulerAngleY(glm::radians(0.f));
|
||||
|
||||
m_canvas->m_mv = camera;
|
||||
m_canvas->m_proj = proj;
|
||||
m_canvas->m_box = box;
|
||||
|
||||
// auto plane_mvp = proj * camera * transform *
|
||||
// glm::scale(glm::vec3(sz, 1));
|
||||
auto plane_mvp = proj * camera * glm::translate(glm::vec3(0, 0, -1));
|
||||
|
||||
m_sampler.bind(0);
|
||||
ui::ShaderManager::use(kShader::TextureAlpha);
|
||||
@@ -1927,6 +1938,62 @@ public:
|
||||
m_canvas->m_tmp.unbindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
ui::ShaderManager::use(kShader::Color);
|
||||
ui::ShaderManager::u_vec4(kShaderUniform::Col, { 1, 0, 0, 1 });
|
||||
// auto loc = m_cur;
|
||||
// auto clip_space = glm::vec2(loc.x, box.w - loc.y - 1.f) / box.zw() * 2.f - 1.f;
|
||||
// auto inv = glm::inverse(proj * camera);
|
||||
// auto wp = inv * glm::vec4(clip_space, 0.9, 1);
|
||||
// wp = wp / wp.w;
|
||||
|
||||
auto unproject = [](glm::vec2 loc, glm::vec4 vp, glm::mat4 camera, glm::mat4 proj, glm::vec3& out_origin, glm::vec3& out_dir) {
|
||||
auto clip_space = glm::vec2(loc.x, vp.w - loc.y - 1.f) / vp.zw() * 2.f - 1.f;
|
||||
auto inv = glm::inverse(proj * camera);
|
||||
auto wp0 = inv * glm::vec4(clip_space, 0, 1);
|
||||
auto wp1 = inv * glm::vec4(clip_space, .5, 1);
|
||||
out_origin = (wp0 / wp0.w).xyz();
|
||||
out_dir = glm::normalize((wp1 / wp1.w).xyz() - out_origin);
|
||||
};
|
||||
auto intersect = [](glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin, glm::vec3 plane_normal, glm::vec3& out_hit) {
|
||||
float den = glm::dot(ray_dir, plane_normal);
|
||||
if (den == 0)
|
||||
return false; // no intersection
|
||||
float num = glm::dot(plane_origin - ray_origin, plane_normal);
|
||||
float t = num / den;
|
||||
if (t > 0)
|
||||
out_hit = ray_origin + ray_dir * t;
|
||||
else
|
||||
// negative intersection
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
glm::vec3 ray_origin, ray_dir;
|
||||
unproject(m_cur, { 0, 0, box.zw }, camera, proj, ray_origin, ray_dir);
|
||||
glm::vec3 plane_origin{ 0, 0, -1 }, plane_dir{ 0, 0, 1 };
|
||||
glm::vec3 hit;
|
||||
if (intersect(ray_origin, ray_dir, plane_origin, plane_dir, hit))
|
||||
{
|
||||
glm::mat4 plane_camera = glm::lookAt(plane_origin, plane_dir, { 0, 1, 0 });
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
if (glm::abs(plane_local.x) < 0.5f && glm::abs(plane_local.y) < 0.5f)
|
||||
{
|
||||
LOG("hit %f %f %f", plane_local.x, plane_local.y, plane_local.z);
|
||||
}
|
||||
}
|
||||
float fovy = glm::radians(m_canvas->m_cam_fov);
|
||||
float fovx = fovy * box.z / box.w;
|
||||
glm::vec2 fov = { fovx, fovy };
|
||||
auto fov_t = glm::vec2(m_cur.x, box.w - m_cur.y - 1.f) / box.zw();
|
||||
glm::vec2 fov_rot = glm::lerp(-fov*.5f, fov*.5f, fov_t);
|
||||
glm::mat4 fov_rot_mat = glm::eulerAngleXY(-fov_rot.y, fov_rot.x) * camera;
|
||||
if (method)
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera * glm::translate(hit) * glm::scale(glm::vec3(.1)));
|
||||
else
|
||||
ui::ShaderManager::u_mat4(kShaderUniform::MVP, proj * camera * glm::translate(hit) * glm::scale(glm::vec3(.1)) * glm::transpose(fov_rot_mat));
|
||||
|
||||
//NodeBorder::m_plane.draw_fill();
|
||||
|
||||
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
m_sampler.unbind();
|
||||
@@ -1947,16 +2014,16 @@ public:
|
||||
MouseEvent* me = static_cast<MouseEvent*>(e);
|
||||
KeyEvent* ke = static_cast<KeyEvent*>(e);
|
||||
GestureEvent* ge = static_cast<GestureEvent*>(e);
|
||||
auto loc = me->m_pos - m_pos;
|
||||
auto loc = (me->m_pos - m_pos) * root()->m_zoom;
|
||||
auto clip_space = glm::vec2(loc.x, m_size.y - loc.y - 1.f) / m_size * 2.f - 1.f;
|
||||
auto fb_space = glm::inverse(m_canvas->m_mvp) * glm::vec4(clip_space, 0, 1);
|
||||
auto cur = fb_space.xy();
|
||||
//auto fb_space = glm::inverse(m_canvas->m_mvp) * glm::vec4(clip_space, 0, 1);
|
||||
auto cur = glm::vec2(loc.x, m_size.y - loc.y - 1.f);// fb_space.xy();
|
||||
|
||||
switch (e->m_type)
|
||||
{
|
||||
case kEventType::MouseDownL:
|
||||
{
|
||||
m_canvas->stroke_start(cur, 1.f, m_brush);
|
||||
m_canvas->stroke_start(loc, 1.f, m_brush);
|
||||
m_dragging = true;
|
||||
mouse_capture();
|
||||
break;
|
||||
@@ -1978,9 +2045,10 @@ public:
|
||||
break;
|
||||
case kEventType::MouseMove:
|
||||
if (m_dragging)
|
||||
m_canvas->stroke_update(cur, 1.f);
|
||||
m_canvas->stroke_update(loc, 1.f);
|
||||
if (m_draggingR)
|
||||
m_pan = m_pan_start + (me->m_pos - m_dragR_start) * glm::vec2(1, -1);
|
||||
m_pan = m_pan_start + (me->m_pos - m_dragR_start) * glm::vec2(-1, -1);
|
||||
m_cur = loc;
|
||||
break;
|
||||
case kEventType::MouseScroll:
|
||||
m_zoom_canvas += me->m_scroll_delta * 0.1f;
|
||||
@@ -1991,7 +2059,10 @@ public:
|
||||
break;
|
||||
case kEventType::KeyDown:
|
||||
if (ke->m_key == kKey::KeyE)
|
||||
{
|
||||
m_canvas->m_erase = true;
|
||||
method = !method;
|
||||
}
|
||||
if (ke->m_key == kKey::AndroidVolumeUp)
|
||||
m_zoom_canvas *= 0.9f;
|
||||
if (ke->m_key == kKey::AndroidVolumeDown)
|
||||
@@ -2006,7 +2077,8 @@ public:
|
||||
m_zoom_start = m_zoom_canvas;
|
||||
break;
|
||||
case kEventType::GestureMove:
|
||||
m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(1, -1);
|
||||
m_pan = m_pan_start + ge->m_pos_delta * glm::vec2(-1, -1);
|
||||
//m_canvas->m_cam_fov = m_zoom_start + ge->m_distance_delta * .001f;
|
||||
m_zoom_canvas = m_zoom_start + ge->m_distance_delta * .001f;
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user