added Normal lines mode for perspective aligned lines

This commit is contained in:
2017-05-07 15:25:54 +01:00
parent de1ace0d63
commit b50011babf
9 changed files with 220 additions and 36 deletions

View File

@@ -8,6 +8,7 @@ std::vector<CanvasMode*> ui::Canvas::modes[] = {
{ new CanvasModePen, new CanvasModeBasicCamera },
{ new CanvasModeLine, new CanvasModeBasicCamera },
{ new CanvasModeCamera, new CanvasModeBasicCamera },
{ new CanvasModeNormal, new CanvasModeBasicCamera },
};
glm::vec3 ui::Canvas::m_plane_origin[6] = {
{ 0, 0,-1}, // front
@@ -127,32 +128,11 @@ 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 plane_tangent, 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);
point_unproject(s.pos, { 0, 0, m_box.zw }, m_mv, m_proj, ray_origin, ray_dir);
glm::vec3 hit;
glm::vec2 fb_pos;
if (intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
{
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
@@ -252,6 +232,74 @@ void ui::Canvas::stroke_draw()
m_commit_delayed = false;
}
}
bool ui::Canvas::point_trace(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
glm::vec3& hit_pos, glm::vec3& hit_normal, int& out_plane_id)
{
point_unproject(loc, { 0, 0, m_box.zw }, m_mv, m_proj, ray_origin, ray_dir);
glm::vec3 hit;
glm::vec2 fb_pos;
for (int i = 0; i < 6; i++)
{
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit))
{
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
if (glm::abs(plane_local.x) < 1.f && glm::abs(plane_local.y) < 1.f)
{
fb_pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
fb_pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
hit_pos = hit;
hit_normal = m_plane_normal[i];
out_plane_id = i;
return true;
}
else continue;
}
else continue;
}
return false;
}
bool ui::Canvas::point_trace_plane(glm::vec2 loc, glm::vec3& ray_origin, glm::vec3& ray_dir,
glm::vec3& hit_pos, glm::vec3& hit_normal, int plane_id)
{
point_unproject(loc, { 0, 0, m_box.zw }, m_mv, m_proj, ray_origin, ray_dir);
glm::vec3 hit;
glm::vec2 fb_pos;
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[plane_id],
m_plane_normal[plane_id], m_plane_tangent[plane_id], hit))
{
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[plane_id], m_plane_normal[plane_id], m_plane_tangent[plane_id]);
hit_pos = hit;
hit_normal = m_plane_normal[plane_id];
return true;
}
return false;
}
bool ui::Canvas::ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
glm::vec3 plane_normal, glm::vec3 plane_tangent, 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;
};
void ui::Canvas::point_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);
};
void ui::Canvas::stroke_commit()
{
if (!m_dirty || m_layers.empty())
@@ -723,6 +771,37 @@ ui::Image ui::Canvas::thumbnail_read(std::string data_path)
return std::move(thumb);
}
void ui::Canvas::draw_objects(std::function<void(const glm::mat4& camera, const glm::mat4& proj)> observer)
{
// save viewport and clear color states
GLint vp[4];
GLfloat cc[4];
glGetIntegerv(GL_VIEWPORT, vp);
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
GLboolean blend = glIsEnabled(GL_BLEND);
// prepare common states
glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND);
glm::mat4 proj = glm::perspective(glm::radians(90.f), 1.f, .1f, 100.f);
for (int i = 0; i < 6; i++)
{
glm::mat4 plane_camera = glm::lookAt(glm::vec3(0), m_plane_origin[i], m_plane_tangent[i]);
m_layers[m_current_layer_idx].m_rtt[i].bindFramebuffer();
observer(plane_camera, proj);
m_layers[m_current_layer_idx].m_rtt[i].unbindFramebuffer();
}
// restore viewport and clear color states
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glViewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
glActiveTexture(GL_TEXTURE0);
}
///////////////////////////////////////////////////////////////////////////////////////////
void ui::Layer::destroy()