Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-06-22 06:19:11 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-06-22 06:21:30 +0300
commit2642ba13b4639fc524bc77e30c112942cd3f5355 (patch)
tree527842604fdd299328256700ae51b1f2f0c1496c /source/blender/gpu
parent1b2b9c6b1f203048d5abf88083823614b405a790 (diff)
GPU_matrix: Add GPU_matrix_unproject_precalc
Pre-calculates values needed for unprojecting to avoid a matrix invert and extracting projection matrix dimensions for every call to GPU_matrix_unproject. Use for gizmo selection drawing.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_matrix.h31
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c79
2 files changed, 71 insertions, 39 deletions
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index 6f7d25dafa7..61622c40ff0 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -96,21 +96,38 @@ void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far)
/* 3D Projection between Window and World Space */
+struct GPUMatrixUnproject_Precalc {
+ float model_inverted[4][4];
+ float view[4];
+ bool is_persp;
+ /** Result of 'projmat_dimensions'. */
+ struct {
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ } dims;
+};
+
+bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *unproj_precalc,
+ const float model[4][4],
+ 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 win[3]);
+ 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 world[3]);
-void GPU_matrix_unproject_model_inverted(const float win[3],
- const float model_inverted[4][4],
- const float proj[4][4],
- const int view[4],
- float world[3]);
+ float r_world[3]);
+
+void GPU_matrix_unproject_with_precalc(const struct GPUMatrixUnproject_Precalc *unproj_precalc,
+ const float win[3],
+ float r_world[3]);
/* 2D Projection Matrix */
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index cc89da19705..858afdc534e 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -481,58 +481,73 @@ void GPU_matrix_project(const float world[3],
* But that solution loses much precision.
* Therefore, get the same result without inverting the matrix.
*/
-static void gpu_mul_invert_projmat_m4_unmapped_v3(const float projmat[4][4], float co[3])
+static void gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc(
+ const struct GPUMatrixUnproject_Precalc *precalc, float co[3])
{
- float left, right, bottom, top, near, far;
- bool is_persp = projmat[3][3] == 0.0f;
+ /* 'precalc->dims' is the result of 'projmat_dimensions(proj, ...)'. */
+ co[0] = precalc->dims.xmin + co[0] * (precalc->dims.xmax - precalc->dims.xmin);
+ co[1] = precalc->dims.ymin + co[1] * (precalc->dims.ymax - precalc->dims.ymin);
- projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far);
-
- co[0] = left + co[0] * (right - left);
- co[1] = bottom + co[1] * (top - bottom);
-
- if (is_persp) {
- co[2] = far * near / (far + co[2] * (near - far));
+ if (precalc->is_persp) {
+ co[2] = precalc->dims.zmax * precalc->dims.zmin /
+ (precalc->dims.zmax + co[2] * (precalc->dims.zmin - precalc->dims.zmax));
co[0] *= co[2];
co[1] *= co[2];
}
else {
- co[2] = near + co[2] * (far - near);
+ co[2] = precalc->dims.zmin + co[2] * (precalc->dims.zmax - precalc->dims.zmin);
}
co[2] *= -1;
}
-void GPU_matrix_unproject_model_inverted(const float win[3],
- const float model_inverted[4][4],
- const float proj[4][4],
- const int view[4],
- float world[3])
-{
- float in[3];
-
- copy_v3_v3(in, win);
-
- /* Map x and y from window coordinates */
- in[0] = (in[0] - view[0]) / view[2];
- in[1] = (in[1] - view[1]) / view[3];
+bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *precalc,
+ const float model[4][4],
+ const float proj[4][4],
+ const int view[4])
+{
+ precalc->is_persp = proj[3][3] == 0.0f;
+ projmat_dimensions(proj,
+ &precalc->dims.xmin,
+ &precalc->dims.xmax,
+ &precalc->dims.ymin,
+ &precalc->dims.ymax,
+ &precalc->dims.zmin,
+ &precalc->dims.zmax);
+ for (int i = 0; i < 4; i++) {
+ precalc->view[i] = (float)view[i];
+ }
+ if (!invert_m4_m4(precalc->model_inverted, model)) {
+ unit_m4(precalc->model_inverted);
+ return false;
+ }
+ return true;
+}
- gpu_mul_invert_projmat_m4_unmapped_v3(proj, in);
- mul_v3_m4v3(world, model_inverted, in);
+void GPU_matrix_unproject_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],
+ (win[1] - precalc->view[1]) / precalc->view[3],
+ win[2],
+ };
+ gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc(precalc, in);
+ 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 world[3])
+ float r_world[3])
{
- float model_inverted[4][4];
-
- if (!invert_m4_m4(model_inverted, model)) {
- zero_v3(world);
+ struct GPUMatrixUnproject_Precalc precalc;
+ if (!GPU_matrix_unproject_precalc(&precalc, model, proj, view)) {
+ zero_v3(r_world);
return false;
}
- GPU_matrix_unproject_model_inverted(win, model_inverted, proj, view, world);
+ GPU_matrix_unproject_with_precalc(&precalc, win, r_world);
return true;
}