Commit fcb8fc6a authored by Campbell Barton's avatar Campbell Barton

Use segment clipping

parent 4c4b40e5
......@@ -49,6 +49,11 @@ pub struct ViewMatrix {
/// GL_MODELVIEW matrix
pub view: [[f64; 4]; 4],
/// inverse of 'view'
///
/// notes:
/// * `view_inv[2]` is the view Z axis, (pointing towards the view).
/// * for perspective projections `view_inv[3]` is the view origin.
///
pub view_inv: [[f64; 4]; 4],
/// 'view' * 'window'
pub persp: [[f64; 4]; 4],
......
......@@ -3,6 +3,7 @@
use math_misc::{
mul_m4v3_as_v4,
mul_m4v3,
mul_project_m4_v3_zfac,
};
......@@ -31,6 +32,27 @@ pub mod ProjTestFlag {
}
// TODO, add a lot of checks - see: ed_view3d_project__internal
// When we have pre-calculated zfac, using 'mul_project_m4_v3_zfac'.
pub fn project_i32_zfac(
ar: &ARegion, rv3d: &RegionView3D, co: &[f64; 3], co_zfac: f64, flag: ProjTestFlagType,
) -> Option<[i32; 2]> {
let vec3 = mul_m4v3(&rv3d.matrix.persp, &co);
let scalar = if co_zfac != 0.0 { 1.0 / co_zfac } else { 0.0 };
let fx = (ar.window_size[0] as f64 / 2.0) * (1.0 + (vec3[0] * scalar));
if (flag & ProjTestFlag::CLIP_WIN) == 0 || fx > 0.0 && fx < ar.window_size[0] as f64 {
let fy = (ar.window_size[1] as f64 / 2.0) * (1.0 + (vec3[1] * scalar));
if (flag & ProjTestFlag::CLIP_WIN) == 0 || fy > 0.0 && fy < ar.window_size[1] as f64 {
return Some([
fx as i32,
fy as i32
]);
}
}
return None;
}
pub fn project_i32(
ar: &ARegion, rv3d: &RegionView3D, co: &[f64; 3], flag: ProjTestFlagType,
) -> Option<[i32; 2]> {
......
......@@ -3,6 +3,11 @@
use super::local_prelude::*;
use view3d;
use math_misc::{
mul_project_m4_v3_zfac,
interp_v3v3,
};
struct View3DWElemData {
image: PxBuf,
// just for convenience
......@@ -83,20 +88,91 @@ fn update(welem: &mut WElem, ctx: &mut AppContext) {
use bmesh::prelude::*;
let use_clip = data.rv3d.is_persp != 0;
{
let use_blend = (bm.select_mode & BM_VERT) != 0;
let color_select = prefs.view3d.edge_select_color;
let color_unselect = prefs.view3d.wire_color;
for e in bm.edges.iter() {
if !e.is_hide() {
if let Some(co_proj_a) = view3d::project::project_i32(
let mut co0_zfac = mul_project_m4_v3_zfac(&data.rv3d.matrix.persp, &e.verts[0].co);
let mut co1_zfac = mul_project_m4_v3_zfac(&data.rv3d.matrix.persp, &e.verts[1].co);
// use when clipped
let co0_data: [f64; 3];
let co1_data: [f64; 3];
let (co0_ref, co1_ref) = if !use_clip {
(&e.verts[0].co, &e.verts[1].co)
} else {
// clip the edge
let mut co0 = &e.verts[0].co;
let mut co1 = &e.verts[1].co;
// near clipping
let co0_clip_min = co0_zfac < data.v3d.near;
let co1_clip_min = co1_zfac < data.v3d.near;
if co0_clip_min && co1_clip_min {
continue;
}
// far clipping
let co0_clip_max = co0_zfac > data.v3d.far;
let co1_clip_max = co1_zfac > data.v3d.far;
if co0_clip_max && co1_clip_max {
continue;
}
if co0_clip_min || co0_clip_max ||
co1_clip_min || co1_clip_max
{
let mut co0_fac = 0.0;
let mut co1_fac = 0.0;
let mut co0_zfac_new = co0_zfac;
let mut co1_zfac_new = co1_zfac;
if co0_clip_min && !co1_clip_min {
co0_fac = (co0_zfac - data.v3d.near) / (co0_zfac - co1_zfac);
co0_zfac_new = data.v3d.near;
} else if !co0_clip_min && co1_clip_min {
co1_fac = (co1_zfac - data.v3d.near) / (co1_zfac - co0_zfac);
co1_zfac_new = data.v3d.near;
}
if co0_clip_max && !co1_clip_max {
co0_fac = (data.v3d.far - co0_zfac) / (co1_zfac - co0_zfac);
co0_zfac_new = data.v3d.far;
} else if !co0_clip_max && co1_clip_max {
co1_fac = (data.v3d.far - co1_zfac) / (co0_zfac - co1_zfac);
co1_zfac_new = data.v3d.far;
}
if co0_fac != 0.0 {
co0_data = interp_v3v3(&e.verts[0].co, &e.verts[1].co, co0_fac);
co0 = &co0_data;
co0_zfac = co0_zfac_new;
}
if co1_fac != 0.0 {
co1_data = interp_v3v3(&e.verts[1].co, &e.verts[0].co, co1_fac);
co1 = &co1_data;
co1_zfac = co1_zfac_new;
}
}
(co0, co1)
};
if let Some(co_proj_a) = view3d::project::project_i32_zfac(
&data.ar, &data.rv3d,
&e.verts[0].co, view3d::project::ProjTestFlag::NOP)
{
if let Some(co_proj_b) = view3d::project::project_i32(
co0_ref, co0_zfac, view3d::project::ProjTestFlag::NOP,
) {
if let Some(co_proj_b) = view3d::project::project_i32_zfac(
&data.ar, &data.rv3d,
&e.verts[1].co, view3d::project::ProjTestFlag::NOP)
{
&co1_ref, co1_zfac, view3d::project::ProjTestFlag::NOP,
) {
let is_select = e.is_select();
if is_select {
image.draw_line_width(
......
......@@ -322,6 +322,14 @@ pub fn mul_m4v4(mat: &[[f64; 4]; 4], v: &[f64; 4]) -> [f64; 4] {
]
}
pub fn mul_m4v3(mat: &[[f64; 4]; 4], v: &[f64; 3]) -> [f64; 3] {
[
v[0] * mat[0][0] + v[1] * mat[1][0] + v[2] * mat[2][0] + mat[3][0],
v[0] * mat[0][1] + v[1] * mat[1][1] + v[2] * mat[2][1] + mat[3][1],
v[0] * mat[0][2] + v[1] * mat[1][2] + v[2] * mat[2][2] + mat[3][2],
]
}
///
/// Convenience function to get the projected depth of a position.
/// This avoids creating a temporary 4D vector and multiplying it - only for the 4th component.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment