GPU: add 2D projection function

When projecting into screen space Z value isn't always needed.
Add 2D projection functions, renaming them to avoid accidents
happening again.

- Add GPU_matrix_project_2fv
- Add ED_view3d_project_v2
- Rename ED_view3d_project to ED_view3d_project_v3
- Use the 2D versions of these functions when the Z value isn't used.
This commit is contained in:
Campbell Barton 2021-06-01 12:49:20 +10:00
parent c145cb7998
commit f71cf99616
15 changed files with 107 additions and 69 deletions

View File

@ -210,7 +210,7 @@ static bool stroke_elem_project(const struct CurveDrawData *cdd,
ED_view3d_depth_read_cached(depths, mval_i, 0, &depth_fl);
const double depth = (double)depth_fl;
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
if (ED_view3d_depth_unproject(region, mval_i, depth, r_location_world)) {
if (ED_view3d_depth_unproject_v3(region, mval_i, depth, r_location_world)) {
is_location_world_set = true;
if (r_normal_world) {
zero_v3(r_normal_world);

View File

@ -162,10 +162,10 @@ bool ED_view3d_depth_read_cached(const ViewDepths *vd,
bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
const int mval[2],
float r_normal[3]);
bool ED_view3d_depth_unproject(const struct ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3]);
bool ED_view3d_depth_unproject_v3(const struct ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3]);
void ED_view3d_depth_tag_update(struct RegionView3D *rv3d);
/* Projection */
@ -410,8 +410,13 @@ void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d,
const float obmat[4][4],
float r_pmat[4][4]);
void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3]);
bool ED_view3d_unproject(
void ED_view3d_project_v3(const struct ARegion *region,
const float world[3],
float r_region_co[3]);
void ED_view3d_project_v2(const struct ARegion *region,
const float world[3],
float r_region_co[2]);
bool ED_view3d_unproject_v3(
const struct ARegion *region, float regionx, float regiony, float regionz, float world[3]);
/* end */

View File

@ -578,8 +578,8 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd,
float r_origin_ofs[3])
{
/* unproject to find view ray */
ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin);
ED_view3d_unproject(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs);
ED_view3d_unproject_v3(kcd->vc.region, mval[0], mval[1], 0.0f, r_origin);
ED_view3d_unproject_v3(kcd->vc.region, mval[0], mval[1], ofs, r_origin_ofs);
/* transform into object space */
mul_m4_v3(kcd->ob_imat, r_origin);
@ -1745,7 +1745,7 @@ static bool point_is_visible(KnifeTool_OpData *kcd,
float view[3], p_ofs[3];
/* TODO: I think there's a simpler way to get the required raycast ray */
ED_view3d_unproject(kcd->vc.region, s[0], s[1], 0.0f, view);
ED_view3d_unproject_v3(kcd->vc.region, s[0], s[1], 0.0f, view);
mul_m4_v3(kcd->ob_imat, view);

View File

@ -525,7 +525,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
float d_a[3], d_b[3];
float d_a_proj[2], d_b_proj[2];
float preview_plane_proj[4][3];
float preview_plane_proj[4][2];
const float y_axis_proj[2] = {0.0f, 1.0f};
mid_v3_v3v3(text_pos, cd->preview_plane[0], cd->preview_plane[2]);
@ -534,7 +534,7 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev
for (int i = 0; i < 4; i++) {
float preview_plane_world_space[3];
mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]);
ED_view3d_project(region, preview_plane_world_space, preview_plane_proj[i]);
ED_view3d_project_v2(region, preview_plane_world_space, preview_plane_proj[i]);
}
/* Get the initial X and Y axis of the basis from the edges of the Bounding Box face. */

View File

@ -1654,7 +1654,7 @@ static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *x
if (center_tot) {
mul_v3_fl(center, 1.0f / center_tot);
float center_proj[3];
ED_view3d_project(xfd->vc.region, center, center_proj);
ED_view3d_project_v3(xfd->vc.region, center, center_proj);
xfd->prev.depth = center_proj[2];
xfd->prev.is_depth_valid = true;
}
@ -1890,7 +1890,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
xfd->prev.depth = depth_fl;
xfd->prev.is_depth_valid = true;
if (ED_view3d_depth_unproject(region, event->mval, depth, location_world)) {
if (ED_view3d_depth_unproject_v3(region, event->mval, depth, location_world)) {
if (is_translate) {
float normal[3];

View File

@ -609,7 +609,7 @@ static bool key_test_depth(const PEData *data, const float co[3], const int scre
}
float win[3];
ED_view3d_project(data->vc.region, co, win);
ED_view3d_project_v3(data->vc.region, co, win);
if (win[2] - 0.00001f > depth) {
return 0;

View File

@ -1039,7 +1039,7 @@ static void cursor_draw_point_screen_space(const uint gpuattr,
float translation_vertex_cursor[3], location[3];
copy_v3_v3(location, true_location);
mul_m4_v3(obmat, location);
ED_view3d_project(region, location, translation_vertex_cursor);
ED_view3d_project_v3(region, location, translation_vertex_cursor);
/* Do not draw points behind the view. Z [near, far] is mapped to [-1, 1]. */
if (translation_vertex_cursor[2] <= 1.0f) {
imm_draw_circle_fill_3d(

View File

@ -846,7 +846,7 @@ static int paint_space_stroke(bContext *C,
while (length > 0.0f) {
float spacing = paint_space_stroke_spacing_variable(
C, scene, stroke, pressure, dpressure, length);
float mouse[3];
float mouse[2];
if (length >= spacing) {
if (use_scene_spacing) {
@ -856,7 +856,7 @@ static int paint_space_stroke(bContext *C,
add_v3_v3v3(final_world_space_position,
stroke->last_world_space_position,
final_world_space_position);
ED_view3d_project(region, final_world_space_position, mouse);
ED_view3d_project_v2(region, final_world_space_position, mouse);
}
else {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
@ -1191,7 +1191,7 @@ static void paint_line_strokes_spacing(bContext *C,
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
float mouse[3], dmouse[2];
float mouse[2], dmouse[2];
float length;
float d_world_space_position[3] = {0.0f};
float world_space_position_old[3], world_space_position_new[3];
@ -1240,7 +1240,7 @@ static void paint_line_strokes_spacing(bContext *C,
mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing_final);
add_v3_v3v3(
final_world_space_position, world_space_position_old, final_world_space_position);
ED_view3d_project(region, final_world_space_position, mouse);
ED_view3d_project_v2(region, final_world_space_position, mouse);
}
else {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;

View File

@ -3666,8 +3666,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
if ((!ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) ||
(!ED_view3d_unproject(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
if ((!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) ||
(!ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
return OPERATOR_CANCELLED;
}
@ -3690,7 +3690,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
if (depth_close != FLT_MAX && ED_view3d_unproject(region, cent[0], cent[1], depth_close, p)) {
if (depth_close != FLT_MAX &&
ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) {
negate_v3_v3(new_ofs, p);
}
else {

View File

@ -154,10 +154,10 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
* Only pre-select a vertex when the cursor is really close to it. */
if (eve_test) {
BMVert *vert = (BMVert *)eve_test;
float vert_p_co[3], vert_co[3];
float vert_p_co[2], vert_co[3];
const float mval_f[2] = {UNPACK2(vc.mval)};
mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co);
ED_view3d_project(vc.region, vert_co, vert_p_co);
ED_view3d_project_v2(vc.region, vert_co, vert_p_co);
float len = len_v2v2(vert_p_co, mval_f);
if (len < 35) {
best.ele = (BMElem *)eve_test;

View File

@ -809,23 +809,30 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d,
/**
* Convert between region relative coordinates (x,y) and depth component z and
* a point in world space. */
void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3])
void ED_view3d_project_v3(const struct ARegion *region, const float world[3], float r_region_co[3])
{
/* Viewport is set up to make coordinates relative to the region, not window. */
RegionView3D *rv3d = region->regiondata;
const int viewport[4] = {0, 0, region->winx, region->winy};
GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
GPU_matrix_project_3fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
}
bool ED_view3d_unproject(
void ED_view3d_project_v2(const struct ARegion *region, const float world[3], float r_region_co[2])
{
/* Viewport is set up to make coordinates relative to the region, not window. */
RegionView3D *rv3d = region->regiondata;
const int viewport[4] = {0, 0, region->winx, region->winy};
GPU_matrix_project_2fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
}
bool ED_view3d_unproject_v3(
const struct ARegion *region, float regionx, float regiony, float regionz, float world[3])
{
RegionView3D *rv3d = region->regiondata;
const int viewport[4] = {0, 0, region->winx, region->winy};
const float region_co[3] = {regionx, regiony, regionz};
return GPU_matrix_unproject(region_co, rv3d->viewmat, rv3d->winmat, viewport, world);
return GPU_matrix_unproject_3fv(region_co, rv3d->viewmat, rv3d->winmat, viewport, world);
}
/** \} */

View File

@ -299,8 +299,8 @@ void ED_view3d_clipping_calc(
float xs = (ELEM(val, 0, 3)) ? rect->xmin : rect->xmax;
float ys = (ELEM(val, 0, 1)) ? rect->ymin : rect->ymax;
ED_view3d_unproject(region, xs, ys, 0.0, bb->vec[val]);
ED_view3d_unproject(region, xs, ys, 1.0, bb->vec[4 + val]);
ED_view3d_unproject_v3(region, xs, ys, 0.0, bb->vec[val]);
ED_view3d_unproject_v3(region, xs, ys, 1.0, bb->vec[4 + val]);
}
/* optionally transform to object space */
@ -1057,7 +1057,7 @@ bool ED_view3d_autodist(Depsgraph *depsgraph,
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
if (ED_view3d_unproject(region, centx, centy, depth_close, mouse_worldloc)) {
if (ED_view3d_unproject_v3(region, centx, centy, depth_close, mouse_worldloc)) {
return true;
}
}
@ -1091,7 +1091,7 @@ bool ED_view3d_autodist_simple(ARegion *region,
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
return ED_view3d_unproject(region, centx, centy, depth, mouse_worldloc);
return ED_view3d_unproject_v3(region, centx, centy, depth, mouse_worldloc);
}
bool ED_view3d_autodist_depth(ARegion *region, const int mval[2], int margin, float *depth)
@ -1716,7 +1716,7 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
ED_view3d_depth_read_cached(depths, mval_ofs, 0, &depth_fl);
const double depth = (double)depth_fl;
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
if (ED_view3d_depth_unproject(region, mval_ofs, depth, coords[i])) {
if (ED_view3d_depth_unproject_v3(region, mval_ofs, depth, coords[i])) {
depths_valid[i] = true;
}
}
@ -1751,14 +1751,14 @@ bool ED_view3d_depth_read_cached_normal(const ViewContext *vc,
return false;
}
bool ED_view3d_depth_unproject(const ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3])
bool ED_view3d_depth_unproject_v3(const ARegion *region,
const int mval[2],
const double depth,
float r_location_world[3])
{
float centx = (float)mval[0] + 0.5f;
float centy = (float)mval[1] + 0.5f;
return ED_view3d_unproject(region, centx, centy, depth, r_location_world);
return ED_view3d_unproject_v3(region, centx, centy, depth, r_location_world);
}
void ED_view3d_depth_tag_update(RegionView3D *rv3d)

View File

@ -118,21 +118,27 @@ bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *unproj_prec
const float proj[4][4],
const int view[4]);
void GPU_matrix_project(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_win[3]);
void GPU_matrix_project_3fv(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_win[3]);
bool GPU_matrix_unproject(const float win[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_world[3]);
void GPU_matrix_project_2fv(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_win[2]);
void GPU_matrix_unproject_with_precalc(const struct GPUMatrixUnproject_Precalc *unproj_precalc,
const float win[3],
float r_world[3]);
bool GPU_matrix_unproject_3fv(const float win[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_world[3]);
void GPU_matrix_unproject_3fv_with_precalc(const struct GPUMatrixUnproject_Precalc *unproj_precalc,
const float win[3],
float r_world[3]);
/* 2D Projection Matrix */

View File

@ -474,11 +474,11 @@ void GPU_matrix_look_at(float eyeX,
GPU_matrix_translate_3f(-eyeX, -eyeY, -eyeZ);
}
void GPU_matrix_project(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float win[3])
void GPU_matrix_project_3fv(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float win[3])
{
float v[4];
@ -494,6 +494,25 @@ void GPU_matrix_project(const float world[3],
win[2] = (v[2] + 1) * 0.5f;
}
void GPU_matrix_project_2fv(const float world[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float win[2])
{
float v[4];
mul_v4_m4v3(v, model, world);
mul_m4_v4(proj, v);
if (v[3] != 0.0f) {
mul_v2_fl(v, 1.0f / v[3]);
}
win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f;
win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
}
/**
* The same result could be obtained as follows:
*
@ -556,9 +575,9 @@ bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *precalc,
return true;
}
void GPU_matrix_unproject_with_precalc(const struct GPUMatrixUnproject_Precalc *precalc,
const float win[3],
float r_world[3])
void GPU_matrix_unproject_3fv_with_precalc(const struct GPUMatrixUnproject_Precalc *precalc,
const float win[3],
float r_world[3])
{
float in[3] = {
(win[0] - precalc->view[0]) / precalc->view[2],
@ -569,18 +588,18 @@ void GPU_matrix_unproject_with_precalc(const struct GPUMatrixUnproject_Precalc *
mul_v3_m4v3(r_world, precalc->model_inverted, in);
}
bool GPU_matrix_unproject(const float win[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_world[3])
bool GPU_matrix_unproject_3fv(const float win[3],
const float model[4][4],
const float proj[4][4],
const int view[4],
float r_world[3])
{
struct GPUMatrixUnproject_Precalc precalc;
if (!GPU_matrix_unproject_precalc(&precalc, model, proj, view)) {
zero_v3(r_world);
return false;
}
GPU_matrix_unproject_with_precalc(&precalc, win, r_world);
GPU_matrix_unproject_3fv_with_precalc(&precalc, win, r_world);
return true;
}

View File

@ -620,7 +620,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
struct GPUMatrixUnproject_Precalc unproj_precalc;
GPU_matrix_unproject_precalc(&unproj_precalc, rv3d->viewmat, rv3d->winmat, viewport);
GPU_matrix_unproject_with_precalc(&unproj_precalc, co_screen, co_3d_origin);
GPU_matrix_unproject_3fv_with_precalc(&unproj_precalc, co_screen, co_3d_origin);
uint *buf_iter = buffer;
int hit_found = -1;
@ -631,7 +631,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
float co_3d[3];
co_screen[2] = int_as_float(buf_iter[1]);
GPU_matrix_unproject_with_precalc(&unproj_precalc, co_screen, co_3d);
GPU_matrix_unproject_3fv_with_precalc(&unproj_precalc, co_screen, co_3d);
float select_bias = gz->select_bias;
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
select_bias *= gz->scale_final;