refactor stroke drawing
This commit is contained in:
403
src/canvas.cpp
403
src/canvas.cpp
@@ -272,77 +272,149 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
||||
|
||||
gl.restore();
|
||||
}
|
||||
void Canvas::stroke_draw()
|
||||
|
||||
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B)
|
||||
{
|
||||
if (!(m_current_stroke && m_current_stroke->has_sample()))
|
||||
// intersect P with the current face to clip diverging points from the plane
|
||||
auto unp_vp = zw(m_box);
|
||||
auto unp_inv = glm::inverse(m_proj * m_mv);
|
||||
std::array<std::vector<vertex_t>, 6> ret;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
//stroke_draw_mix({ 0,0 }, { m_mixer.getWidth(), m_mixer.getHeight() });
|
||||
return;
|
||||
auto P = poly_intersect(std::data(B), std::data(B) + 4, m_plane_shape[i]);
|
||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
|
||||
int intersections = 0;
|
||||
for (int j = 0; j < P.size(); j++)
|
||||
{
|
||||
glm::vec3 ray_origin, ray_dir;
|
||||
//if (s.pos.z == 0)
|
||||
{
|
||||
//point_unproject(P[j].pos, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
|
||||
|
||||
auto clip_space = glm::vec2(P[j].pos.x, unp_vp.y - P[j].pos.y - 1.f) / unp_vp * 2.f - 1.f;
|
||||
auto wp0 = unp_inv * glm::vec4(clip_space, 0, 1);
|
||||
auto wp1 = unp_inv * glm::vec4(clip_space, .5, 1);
|
||||
ray_origin = xyz(wp0 / wp0.w);
|
||||
ray_dir = glm::normalize(xyz(wp1 / wp1.w) - ray_origin);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// auto m = glm::inverse(glm::lookAt({ 0, 0, 0 }, s.pos, { 0, 1, 0 }));
|
||||
// glm::vec3 off_3d = m * glm::vec4(off[j], 0, 1);
|
||||
// ray_origin = glm::vec3(0);
|
||||
// ray_dir = s.pos + off_3d;
|
||||
//}
|
||||
|
||||
glm::vec3 hit;
|
||||
float hit_t;
|
||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
|
||||
{
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
|
||||
//P[j].uvs2 = xy(P[j].pos) / glm::vec2(App::I.width, App::I.height);
|
||||
P[j].pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
|
||||
P[j].pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
|
||||
|
||||
// Black magic - BEWARE!
|
||||
// interpolation perspective correction, use the current camera projection to correct the interpolation
|
||||
// because the new shape will have z fixed with an ortho projection when drawn to the face
|
||||
// we need to imitate the same perspective as the once in the camera
|
||||
// see: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
|
||||
auto hit_cam = m_mv * glm::vec4(hit, 1);
|
||||
P[j].pos.z = 0;
|
||||
P[j].pos.w = hit_cam.z;
|
||||
P[j].uvs *= hit_cam.z;
|
||||
P[j].uvs2 *= hit_cam.z;
|
||||
intersections++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (intersections >= 3)
|
||||
ret[i] = P;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
||||
{
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex[i].bind(); // bg, copy of framebuffer (copied before drawing)
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
glm::vec2 bb_min(m_width, m_height);
|
||||
glm::vec2 bb_max(0, 0);
|
||||
for (int j = 0; j < P.size(); j++)
|
||||
{
|
||||
bb_min = glm::max({ 0, 0 }, glm::min(bb_min, xy(P[j].pos)));
|
||||
bb_max = glm::min({ m_width, m_height }, glm::max(bb_max, xy(P[j].pos)));
|
||||
}
|
||||
auto bb_sz = bb_max - bb_min;
|
||||
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
|
||||
float zoom = m_node->root()->m_zoom;
|
||||
glm::vec2 pad(1);
|
||||
glm::ivec2 tex_pos = glm::clamp(glm::floor(bb_min) - pad, { 0, 0 }, { m_width, m_height });
|
||||
glm::ivec2 tex_sz = glm::clamp(glm::ceil(bb_sz) + pad * 2.f, { 0, 0 }, (glm::vec2)(glm::ivec2(m_width, m_height) - tex_pos));
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, tex_pos.x, tex_pos.y,
|
||||
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
}
|
||||
|
||||
m_dirty_box[i] = glm::vec4(glm::min(xy(m_dirty_box[i]), (glm::vec2)tex_pos),
|
||||
glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz)));
|
||||
|
||||
if (P.size() == 4)
|
||||
{
|
||||
static vertex_t rect[6];
|
||||
rect[0] = P[0];
|
||||
rect[1] = P[1];
|
||||
rect[2] = P[2];
|
||||
rect[3] = P[0];
|
||||
rect[4] = P[2];
|
||||
rect[5] = P[3];
|
||||
m_brush_shape.update_vertices(rect, 6);
|
||||
}
|
||||
else if (P.size() == 3)
|
||||
{
|
||||
m_brush_shape.update_vertices(P.data(), P.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
P = triangulate_simple(P);
|
||||
m_brush_shape.update_vertices(P.data(), P.size());
|
||||
}
|
||||
m_brush_shape.draw_fill();
|
||||
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex[i].unbind();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute()
|
||||
{
|
||||
std::vector<StrokeFrame> ret;
|
||||
const auto& m_brush = m_current_stroke->m_brush;
|
||||
auto samples = m_current_stroke->compute_samples();
|
||||
auto& tex = *m_brush->m_tip_texture;
|
||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||
|
||||
std::vector<vertex_t> B{
|
||||
std::array<vertex_t, 4> B = {
|
||||
vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} },
|
||||
vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} },
|
||||
vertex_t{ {0, 0, 1, 1}, {1, 1}, {1, 1} },
|
||||
vertex_t{ {0, 0, 1, 1}, {1, 0}, {1, 0} },
|
||||
};
|
||||
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
tex.bind();
|
||||
m_sampler_brush.bind(0);
|
||||
m_sampler_bg.bind(1);
|
||||
m_sampler_stencil.bind(2);
|
||||
m_sampler.bind(3);
|
||||
//m_sampler_linear.bind(5);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
if (m_brush->m_stencil_texture)
|
||||
m_brush->m_stencil_texture->bind();
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
m_mixer.bindTexture();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
ShaderManager::use(kShader::Stroke);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
|
||||
ShaderManager::u_int(kShaderUniform::TexStencil, 2); // stencil
|
||||
ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer
|
||||
//ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush->m_tip_stencil);
|
||||
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush->m_tip_mix);
|
||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush->m_tip_wet);
|
||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush->m_tip_noise);
|
||||
|
||||
auto unp_vp = zw(m_box);
|
||||
auto unp_inv = glm::inverse(m_proj * m_mv);
|
||||
|
||||
for (const auto& s : samples)
|
||||
{
|
||||
if (!s.valid())
|
||||
continue;
|
||||
|
||||
ret.emplace_back();
|
||||
auto& f = ret.back();
|
||||
|
||||
if (m_mixer_idle)
|
||||
{
|
||||
m_mixer_sample = s;
|
||||
@@ -377,154 +449,93 @@ void Canvas::stroke_draw()
|
||||
B[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1);
|
||||
B[j].uvs2 = p / mixer_sz;
|
||||
}
|
||||
|
||||
if (m_brush->m_tip_mix > 0.f)
|
||||
{
|
||||
stroke_draw_mix(mixer_bb_min, mixer_bb_max - mixer_bb_min);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
/*
|
||||
// check if plane is even visible
|
||||
glm::vec4 forward = m_mv * glm::vec4(0, 0, 1, 1);
|
||||
float dot = glm::dot(xyz(forward), m_plane_normal[i]);
|
||||
// TODO: use better threshold than 0.3
|
||||
// some trigonometric shit, tangent and stuff
|
||||
if (dot < -0.3f)
|
||||
continue;
|
||||
*/
|
||||
|
||||
int intersected = 0;
|
||||
|
||||
// intersect P with the current face to clip diverging points from the plane
|
||||
auto P = poly_intersect(B, m_plane_shape[i]);
|
||||
|
||||
glm::mat4 plane_camera = glm::lookAt(m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i]);
|
||||
for (int j = 0; j < P.size(); j++)
|
||||
{
|
||||
glm::vec3 ray_origin, ray_dir;
|
||||
if (s.pos.z == 0)
|
||||
{
|
||||
//point_unproject(P[j].pos, { 0, 0, zw(m_box) }, m_mv, m_proj, ray_origin, ray_dir);
|
||||
|
||||
auto clip_space = glm::vec2(P[j].pos.x, unp_vp.y - P[j].pos.y - 1.f) / unp_vp * 2.f - 1.f;
|
||||
auto wp0 = unp_inv * glm::vec4(clip_space, 0, 1);
|
||||
auto wp1 = unp_inv * glm::vec4(clip_space, .5, 1);
|
||||
ray_origin = xyz(wp0 / wp0.w);
|
||||
ray_dir = glm::normalize(xyz(wp1 / wp1.w) - ray_origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto m = glm::inverse(glm::lookAt({ 0, 0, 0 }, s.pos, { 0, 1, 0 }));
|
||||
glm::vec3 off_3d = m * glm::vec4(off[j], 0, 1);
|
||||
ray_origin = glm::vec3(0);
|
||||
ray_dir = s.pos + off_3d;
|
||||
}
|
||||
|
||||
glm::vec3 hit;
|
||||
float hit_t;
|
||||
if (ray_intersect(ray_origin, ray_dir, m_plane_origin[i], m_plane_normal[i], m_plane_tangent[i], hit, hit_t))
|
||||
{
|
||||
glm::vec4 plane_local = plane_camera * glm::vec4(hit, 1);
|
||||
|
||||
//P[j].uvs2 = xy(P[j].pos) / glm::vec2(App::I.width, App::I.height);
|
||||
P[j].pos.x = -(plane_local.x * 0.5f - 0.5f) * m_width;
|
||||
P[j].pos.y = (plane_local.y * 0.5f + 0.5f) * m_height;
|
||||
|
||||
// Black magic - BEWARE!
|
||||
// interpolation perspective correction, use the current camera projection to correct the interpolation
|
||||
// because the new shape will have z fixed with an ortho projection when drawn to the face
|
||||
// we need to imitate the same perspective as the once in the camera
|
||||
// see: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/perspective-correct-interpolation-vertex-attributes
|
||||
auto hit_cam = m_mv * glm::vec4(hit, 1);
|
||||
P[j].pos.z = 0;
|
||||
P[j].pos.w = hit_cam.z;
|
||||
P[j].uvs *= hit_cam.z;
|
||||
P[j].uvs2 *= hit_cam.z;
|
||||
|
||||
intersected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersected < 3)
|
||||
continue;
|
||||
|
||||
m_dirty_face[i] = true;
|
||||
|
||||
m_tmp[i].bindFramebuffer();
|
||||
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex[i].bind(); // bg, copy of framebuffer (copied before drawing)
|
||||
}
|
||||
|
||||
glm::vec2 bb_min(m_width, m_height);
|
||||
glm::vec2 bb_max(0, 0);
|
||||
for (int j = 0; j < P.size(); j++)
|
||||
{
|
||||
bb_min = glm::max({ 0, 0 }, glm::min(bb_min, xy(P[j].pos)));
|
||||
bb_max = glm::min({ m_width, m_height }, glm::max(bb_max, xy(P[j].pos)));
|
||||
}
|
||||
auto bb_sz = bb_max - bb_min;
|
||||
|
||||
glm::vec2 pad(1);
|
||||
glm::ivec2 tex_pos = glm::clamp(glm::floor(bb_min) - pad , { 0, 0 }, { m_width, m_height });
|
||||
glm::ivec2 tex_sz = glm::clamp(glm::ceil(bb_sz ) + pad*2.f, { 0, 0 }, (glm::vec2)(glm::ivec2(m_width, m_height) - tex_pos));
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, tex_pos.x, tex_pos.y,
|
||||
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||
}
|
||||
|
||||
m_dirty_box[i] = glm::vec4(glm::min(xy(m_dirty_box[i]), (glm::vec2)tex_pos),
|
||||
glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz)));
|
||||
|
||||
ShaderManager::use(kShader::Stroke);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(s.col, m_brush->m_tip_color.a));
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, s.flow);
|
||||
|
||||
if (P.size() == 4)
|
||||
{
|
||||
static vertex_t rect[6];
|
||||
rect[0] = P[0];
|
||||
rect[1] = P[1];
|
||||
rect[2] = P[2];
|
||||
rect[3] = P[0];
|
||||
rect[4] = P[2];
|
||||
rect[5] = P[3];
|
||||
m_brush_shape.update_vertices(rect, 6);
|
||||
}
|
||||
else if (P.size() == 3)
|
||||
{
|
||||
m_brush_shape.update_vertices(P.data(), P.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
P = triangulate_simple(P);
|
||||
m_brush_shape.update_vertices(P.data(), P.size());
|
||||
}
|
||||
m_brush_shape.draw_fill();
|
||||
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
m_tex[i].unbind();
|
||||
}
|
||||
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
}
|
||||
|
||||
f.m_mixer_rect = { mixer_bb_min, mixer_bb_max - mixer_bb_min };
|
||||
f.col = glm::vec4(s.col, m_brush->m_tip_color.a);
|
||||
f.pressure = s.flow;
|
||||
f.shapes = stroke_draw_project(B);
|
||||
|
||||
m_mixer_sample = s;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Canvas::stroke_draw()
|
||||
{
|
||||
if (!(m_current_stroke && m_current_stroke->has_sample()))
|
||||
{
|
||||
//stroke_draw_mix({ 0,0 }, { m_mixer.getWidth(), m_mixer.getHeight() });
|
||||
return;
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
|
||||
GLint vp[4];
|
||||
GLfloat cc[4];
|
||||
glGetIntegerv(GL_VIEWPORT, vp);
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||
|
||||
const auto& m_brush = m_current_stroke->m_brush;
|
||||
auto& tex = *m_brush->m_tip_texture;
|
||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||
|
||||
glViewport(0, 0, m_width, m_height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
tex.bind();
|
||||
m_sampler_brush.bind(0);
|
||||
m_sampler_bg.bind(1);
|
||||
m_sampler_stencil.bind(2);
|
||||
m_sampler.bind(3);
|
||||
//m_sampler_linear.bind(5);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
if (m_brush->m_stencil_texture)
|
||||
m_brush->m_stencil_texture->bind();
|
||||
else
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
m_mixer.bindTexture();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
ShaderManager::use(kShader::Stroke);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
|
||||
if (!ShaderManager::ext_framebuffer_fetch)
|
||||
ShaderManager::u_int(kShaderUniform::TexBG, 1); // bg
|
||||
ShaderManager::u_int(kShaderUniform::TexStencil, 2); // stencil
|
||||
ShaderManager::u_int(kShaderUniform::TexMix, 3); // mixer
|
||||
//ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush->m_tip_stencil);
|
||||
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush->m_tip_mix);
|
||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush->m_tip_wet);
|
||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush->m_tip_noise);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
||||
|
||||
auto frames = stroke_draw_compute();
|
||||
for (auto& f : frames)
|
||||
{
|
||||
if (m_brush->m_tip_mix > 0.f)
|
||||
{
|
||||
stroke_draw_mix(xy(f.m_mixer_rect), zw(f.m_mixer_rect));
|
||||
}
|
||||
|
||||
//ShaderManager::use(kShader::Stroke);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, f.col);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, f.pressure);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
auto& P = f.shapes[i];
|
||||
if (P.size() < 3)
|
||||
continue;
|
||||
m_dirty_face[i] = true;
|
||||
m_tmp[i].bindFramebuffer();
|
||||
stroke_draw_samples(i, P);
|
||||
m_tmp[i].unbindFramebuffer();
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
if (m_brush->m_stencil_texture)
|
||||
|
||||
11
src/canvas.h
11
src/canvas.h
@@ -126,6 +126,14 @@ struct PPIHeader
|
||||
|
||||
class Canvas
|
||||
{
|
||||
struct StrokeFrame
|
||||
{
|
||||
glm::vec4 col;
|
||||
float pressure;
|
||||
std::array<std::vector<vertex_t>, 6> shapes;
|
||||
glm::vec4 m_mixer_rect;
|
||||
};
|
||||
|
||||
public:
|
||||
Plane m_plane;
|
||||
Plane m_plane_brush;
|
||||
@@ -224,6 +232,9 @@ public:
|
||||
void stroke_start(glm::vec3 point, float pressure, const std::shared_ptr<Brush>& brush);
|
||||
void stroke_update(glm::vec3 point, float pressure);
|
||||
void stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz);
|
||||
std::array<std::vector<vertex_t>, 6> stroke_draw_project(std::array<vertex_t, 4>& B);
|
||||
void stroke_draw_samples(int i, std::vector<vertex_t>& P);
|
||||
std::vector<StrokeFrame> stroke_draw_compute();
|
||||
void stroke_draw();
|
||||
void stroke_end();
|
||||
void stroke_cancel();
|
||||
|
||||
@@ -99,11 +99,11 @@ bool point_side(glm::vec2 a, glm::vec2 b, glm::vec2 p)
|
||||
// a is a convex polygon
|
||||
// a and b are a list of non repeating points
|
||||
// returns the resulting intersection polygon points
|
||||
std::vector<vertex_t> poly_intersect(const std::vector<vertex_t>& poly, const std::vector<glm::vec2>& clip)
|
||||
std::vector<vertex_t> poly_intersect(const vertex_t* poly_begin, const vertex_t* poly_end, const std::vector<glm::vec2>& clip)
|
||||
{
|
||||
// implementing the Sutherland-Hodgman algorithm
|
||||
// see https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm
|
||||
std::vector<vertex_t> ret = poly;
|
||||
std::vector<vertex_t> ret(poly_begin, poly_end);
|
||||
for (int i = 0; i < clip.size(); i++)
|
||||
{
|
||||
std::vector<vertex_t> tmp;
|
||||
|
||||
@@ -53,7 +53,7 @@ bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_orig
|
||||
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
|
||||
const glm::vec2& p1a, const glm::vec2& p1b, glm::vec2& out_pt, glm::vec2& out_hit_uv);
|
||||
bool point_side(glm::vec2 a, glm::vec2 b, glm::vec2 p);
|
||||
std::vector<vertex_t> poly_intersect(const std::vector<vertex_t>& poly, const std::vector<glm::vec2>& clip);
|
||||
std::vector<vertex_t> poly_intersect(const vertex_t* poly_begin, const vertex_t* poly_end, const std::vector<glm::vec2>& clip);
|
||||
std::vector<glm::vec2> poly_intersect(const std::vector<glm::vec2>& poly, const std::vector<glm::vec2>& clip);
|
||||
std::vector<glm::vec3> poly_clip_near(const std::vector<glm::vec3>& poly, float near_plane_distance);
|
||||
glm::vec4 rand_color();
|
||||
|
||||
Reference in New Issue
Block a user