Blender  V3.3
view3d_project.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
8 #include "DNA_camera_types.h"
9 #include "DNA_object_types.h"
10 #include "DNA_scene_types.h"
11 #include "DNA_screen_types.h"
12 #include "DNA_view3d_types.h"
13 
14 #include "BLI_sys_types.h" /* int64_t */
15 
16 #include "BLI_math_vector.h"
17 
18 #include "BKE_camera.h"
19 #include "BKE_screen.h"
20 
21 #include "GPU_matrix.h"
22 
23 #include "ED_view3d.h" /* own include */
24 
25 #define BL_ZERO_CLIP 0.001
26 
27 /* Non Clipping Projection Functions
28  * ********************************* */
29 
31  const float co[3],
32  float r_co[2],
33  const float mat[4][4])
34 {
35  float vec4[4];
36 
37  copy_v3_v3(vec4, co);
38  vec4[3] = 1.0;
39  /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
40 
41  mul_m4_v4(mat, vec4);
42 
43  if (vec4[3] > FLT_EPSILON) {
44  r_co[0] = (float)(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
45  r_co[1] = (float)(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
46  }
47  else {
48  zero_v2(r_co);
49  }
50 }
51 
53  const float co[3],
54  float r_co[3],
55  const float mat[4][4])
56 {
57  float vec4[4];
58 
59  copy_v3_v3(vec4, co);
60  vec4[3] = 1.0;
61  /* r_co[0] = IS_CLIPPED; */ /* always overwritten */
62 
63  mul_m4_v4(mat, vec4);
64 
65  if (vec4[3] > FLT_EPSILON) {
66  r_co[0] = (float)(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
67  r_co[1] = (float)(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
68  r_co[2] = vec4[2] / vec4[3];
69  }
70  else {
71  zero_v3(r_co);
72  }
73 }
74 
75 /* Clipping Projection Functions
76  * ***************************** */
77 
78 eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, struct Base *base)
79 {
81  region, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
82 
83  if (ret != V3D_PROJ_RET_OK) {
84  base->sx = IS_CLIPPED;
85  base->sy = 0;
86  }
87 
88  return ret;
89 }
90 
91 /* perspmat is typically...
92  * - 'rv3d->perspmat', is_local == false
93  * - 'rv3d->persmatob', is_local == true
94  */
96  const float perspmat[4][4],
97  const bool is_local, /* normally hidden */
98  const float co[3],
99  float r_co[2],
100  const eV3DProjTest flag)
101 {
102  float vec4[4];
103 
104  /* check for bad flags */
105  BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag);
106 
107  if (flag & V3D_PROJ_TEST_CLIP_BB) {
108  RegionView3D *rv3d = region->regiondata;
109  if (rv3d->rflag & RV3D_CLIPPING) {
110  if (ED_view3d_clipping_test(rv3d, co, is_local)) {
111  return V3D_PROJ_RET_CLIP_BB;
112  }
113  }
114  }
115 
116  copy_v3_v3(vec4, co);
117  vec4[3] = 1.0;
118  mul_m4_v4(perspmat, vec4);
119  const float w = fabsf(vec4[3]);
120 
121  if ((flag & V3D_PROJ_TEST_CLIP_ZERO) && (w <= (float)BL_ZERO_CLIP)) {
122  return V3D_PROJ_RET_CLIP_ZERO;
123  }
124 
125  if ((flag & V3D_PROJ_TEST_CLIP_NEAR) && (vec4[2] <= -w)) {
126  return V3D_PROJ_RET_CLIP_NEAR;
127  }
128 
129  if ((flag & V3D_PROJ_TEST_CLIP_FAR) && (vec4[2] >= w)) {
130  return V3D_PROJ_RET_CLIP_FAR;
131  }
132 
133  const float scalar = (w != 0.0f) ? (1.0f / w) : 0.0f;
134  const float fx = ((float)region->winx / 2.0f) * (1.0f + (vec4[0] * scalar));
135  const float fy = ((float)region->winy / 2.0f) * (1.0f + (vec4[1] * scalar));
136 
137  if ((flag & V3D_PROJ_TEST_CLIP_WIN) &&
138  (fx <= 0.0f || fy <= 0.0f || fx >= (float)region->winx || fy >= (float)region->winy)) {
139  return V3D_PROJ_RET_CLIP_WIN;
140  }
141 
142  r_co[0] = fx;
143  r_co[1] = fy;
144 
145  return V3D_PROJ_RET_OK;
146 }
147 
149  float perspmat[4][4],
150  const bool is_local,
151  const float co[3],
152  short r_co[2],
153  const eV3DProjTest flag)
154 {
155  float tvec[2];
156  eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
157  if (ret == V3D_PROJ_RET_OK) {
158  if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) &&
159  (tvec[1] > -32700.0f && tvec[1] < 32700.0f)) {
160  r_co[0] = (short)floorf(tvec[0]);
161  r_co[1] = (short)floorf(tvec[1]);
162  }
163  else {
165  }
166  }
167  return ret;
168 }
169 
171  float perspmat[4][4],
172  const bool is_local,
173  const float co[3],
174  int r_co[2],
175  const eV3DProjTest flag)
176 {
177  float tvec[2];
178  eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
179  if (ret == V3D_PROJ_RET_OK) {
180  if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) &&
181  (tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f)) {
182  r_co[0] = (int)floorf(tvec[0]);
183  r_co[1] = (int)floorf(tvec[1]);
184  }
185  else {
187  }
188  }
189  return ret;
190 }
191 
193  float perspmat[4][4],
194  const bool is_local,
195  const float co[3],
196  float r_co[2],
197  const eV3DProjTest flag)
198 {
199  float tvec[2];
200  eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
201  if (ret == V3D_PROJ_RET_OK) {
202  if (isfinite(tvec[0]) && isfinite(tvec[1])) {
203  copy_v2_v2(r_co, tvec);
204  }
205  else {
207  }
208  }
209  return ret;
210 }
211 
213  const float co[3],
214  short r_co[2],
215  const eV3DProjTest flag)
216 {
217  RegionView3D *rv3d = region->regiondata;
218  return ED_view3d_project_short_ex(region, rv3d->persmat, false, co, r_co, flag);
219 }
221  const float co[3],
222  short r_co[2],
223  const eV3DProjTest flag)
224 {
225  RegionView3D *rv3d = region->regiondata;
227  return ED_view3d_project_short_ex(region, rv3d->persmatob, true, co, r_co, flag);
228 }
229 
231  const float co[3],
232  int r_co[2],
233  const eV3DProjTest flag)
234 {
235  RegionView3D *rv3d = region->regiondata;
236  return ED_view3d_project_int_ex(region, rv3d->persmat, false, co, r_co, flag);
237 }
239  const float co[3],
240  int r_co[2],
241  const eV3DProjTest flag)
242 {
243  RegionView3D *rv3d = region->regiondata;
245  return ED_view3d_project_int_ex(region, rv3d->persmatob, true, co, r_co, flag);
246 }
247 
249  const float co[3],
250  float r_co[2],
251  const eV3DProjTest flag)
252 {
253  RegionView3D *rv3d = region->regiondata;
254  return ED_view3d_project_float_ex(region, rv3d->persmat, false, co, r_co, flag);
255 }
257  const float co[3],
258  float r_co[2],
259  const eV3DProjTest flag)
260 {
261  RegionView3D *rv3d = region->regiondata;
263  return ED_view3d_project_float_ex(region, rv3d->persmatob, true, co, r_co, flag);
264 }
265 
266 /* More Generic Window/Ray/Vector projection functions
267  * *************************************************** */
268 
269 float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
270 {
271  return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
272 }
273 
274 float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3])
275 {
276  return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize;
277 }
278 
279 float ED_view3d_calc_zfac_ex(const RegionView3D *rv3d, const float co[3], bool *r_flip)
280 {
281  float zfac = mul_project_m4_v3_zfac(rv3d->persmat, co);
282 
283  if (r_flip) {
284  *r_flip = (zfac < 0.0f);
285  }
286 
287  /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
288  * (accounting for near zero values) */
289  if (zfac < 1.e-6f && zfac > -1.e-6f) {
290  zfac = 1.0f;
291  }
292 
293  /* Negative zfac means x, y, z was behind the camera (in perspective).
294  * This gives flipped directions, so revert back to ok default case. */
295  if (zfac < 0.0f) {
296  zfac = -zfac;
297  }
298 
299  return zfac;
300 }
301 
302 float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
303 {
304  return ED_view3d_calc_zfac_ex(rv3d, co, NULL);
305 }
306 
307 float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3])
308 {
309  if (rv3d->is_persp) {
310  return ED_view3d_calc_zfac(rv3d, co);
311  }
312  return -dot_v3v3(rv3d->viewinv[2], co);
313 }
314 
316  const ARegion *region,
317  const View3D *v3d,
318  const float mval[2],
319  float r_ray_co[3],
320  float r_ray_dir[3],
321  float r_ray_start[3],
322  float r_ray_end[3])
323 {
324  RegionView3D *rv3d = region->regiondata;
325  float _ray_co[3], _ray_dir[3], start_offset, end_offset;
326 
327  if (!r_ray_co) {
328  r_ray_co = _ray_co;
329  }
330  if (!r_ray_dir) {
331  r_ray_dir = _ray_dir;
332  }
333 
334  ED_view3d_win_to_origin(region, mval, r_ray_co);
335  ED_view3d_win_to_vector(region, mval, r_ray_dir);
336 
337  if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
338  end_offset = v3d->clip_end / 2.0f;
339  start_offset = -end_offset;
340  }
341  else {
342  ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false);
343  }
344 
345  if (r_ray_start) {
346  madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset);
347  }
348  if (r_ray_end) {
349  madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset);
350  }
351 }
352 
353 bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
354 {
355  if ((rv3d->rflag & RV3D_CLIPPING) &&
356  (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, ray_start, ray_end) == false)) {
357  return false;
358  }
359  return true;
360 }
361 
363  const ARegion *region,
364  const View3D *v3d,
365  const float mval[2],
366  float r_ray_co[3],
367  float r_ray_normal[3],
368  float r_ray_start[3],
369  bool do_clip_planes)
370 {
371  float ray_end[3];
372 
374  depsgraph, region, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
375 
376  /* bounds clipping */
377  if (do_clip_planes) {
378  return ED_view3d_clip_segment(region->regiondata, r_ray_start, ray_end);
379  }
380 
381  return true;
382 }
383 
385  const ARegion *region,
386  const View3D *v3d,
387  const float mval[2],
388  float r_ray_start[3],
389  float r_ray_normal[3],
390  const bool do_clip_planes)
391 {
393  depsgraph, region, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes);
394 }
395 
396 void ED_view3d_win_to_ray(const ARegion *region,
397  const float mval[2],
398  float r_ray_start[3],
399  float r_ray_normal[3])
400 {
401  ED_view3d_win_to_origin(region, mval, r_ray_start);
402  ED_view3d_win_to_vector(region, mval, r_ray_normal);
403 }
404 
405 void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3])
406 {
407  if (rv3d->is_persp) {
408  float p1[4], p2[4];
409 
410  copy_v3_v3(p1, coord);
411  p1[3] = 1.0f;
412  copy_v3_v3(p2, p1);
413  p2[3] = 1.0f;
414  mul_m4_v4(rv3d->viewmat, p2);
415 
416  mul_v3_fl(p2, 2.0f);
417 
418  mul_m4_v4(rv3d->viewinv, p2);
419 
420  sub_v3_v3v3(vec, p1, p2);
421  }
422  else {
423  copy_v3_v3(vec, rv3d->viewinv[2]);
424  }
425  normalize_v3(vec);
426 }
427 
428 /* very similar to ED_view3d_win_to_3d() but has no advantage, de-duplicating */
429 #if 0
430 bool view3d_get_view_aligned_coordinate(ARegion *region,
431  float fp[3],
432  const int mval[2],
433  const bool do_fallback)
434 {
435  RegionView3D *rv3d = region->regiondata;
436  float dvec[3];
437  int mval_cpy[2];
439 
440  ret = ED_view3d_project_int_global(region, fp, mval_cpy, V3D_PROJ_TEST_NOP);
441 
442  if (ret == V3D_PROJ_RET_OK) {
443  const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), (float)(mval_cpy[1] - mval[1])};
444  const float zfac = ED_view3d_calc_zfac(rv3d, fp);
445  ED_view3d_win_to_delta(region, mval_f, zfac, dvec);
446  sub_v3_v3(fp, dvec);
447 
448  return true;
449  }
450  else {
451  /* fallback to the view center */
452  if (do_fallback) {
453  negate_v3_v3(fp, rv3d->ofs);
454  return view3d_get_view_aligned_coordinate(region, fp, mval, false);
455  }
456  else {
457  return false;
458  }
459  }
460 }
461 #endif
462 
463 void ED_view3d_win_to_3d(const View3D *v3d,
464  const ARegion *region,
465  const float depth_pt[3],
466  const float mval[2],
467  float r_out[3])
468 {
469  RegionView3D *rv3d = region->regiondata;
470 
471  float ray_origin[3];
472  float ray_direction[3];
473  float lambda;
474 
475  if (rv3d->is_persp) {
476  float plane[4];
477 
478  copy_v3_v3(ray_origin, rv3d->viewinv[3]);
479  ED_view3d_win_to_vector(region, mval, ray_direction);
480 
481  /* NOTE: we could use #isect_line_plane_v3()
482  * however we want the intersection to be in front of the view no matter what,
483  * so apply the unsigned factor instead. */
484  plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]);
485 
486  isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false);
487  lambda = fabsf(lambda);
488  }
489  else {
490  float dx = (2.0f * mval[0] / (float)region->winx) - 1.0f;
491  float dy = (2.0f * mval[1] / (float)region->winy) - 1.0f;
492 
493  if (rv3d->persp == RV3D_CAMOB) {
494  /* ortho camera needs offset applied */
495  const Camera *cam = v3d->camera->data;
496  const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, region->winx, region->winy);
497  const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
498  const float aspx = region->winx / (float)region->winy;
499  const float aspy = region->winy / (float)region->winx;
500  const float shiftx = cam->shiftx * 0.5f *
501  (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
502  const float shifty = cam->shifty * 0.5f *
503  (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f);
504 
505  dx += (rv3d->camdx + shiftx) * zoomfac;
506  dy += (rv3d->camdy + shifty) * zoomfac;
507  }
508  ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
509  ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
510  ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];
511 
512  copy_v3_v3(ray_direction, rv3d->viewinv[2]);
513  lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
514  }
515 
516  madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda);
517 }
518 
520  const ARegion *region,
521  const float depth_pt[3],
522  const int mval[2],
523  float r_out[3])
524 {
525  const float mval_fl[2] = {mval[0], mval[1]};
526  ED_view3d_win_to_3d(v3d, region, depth_pt, mval_fl, r_out);
527 }
528 
530  const float plane[4],
531  const float mval[2],
532  const bool do_clip,
533  float r_out[3])
534 {
535  const RegionView3D *rv3d = region->regiondata;
536  const bool ray_co_is_centered = rv3d->is_persp == false && rv3d->persp != RV3D_CAMOB;
537  const bool do_clip_ray_plane = do_clip && !ray_co_is_centered;
538  float ray_co[3], ray_no[3];
539  ED_view3d_win_to_origin(region, mval, ray_co);
540  ED_view3d_win_to_vector(region, mval, ray_no);
541  float lambda;
542  if (isect_ray_plane_v3(ray_co, ray_no, plane, &lambda, do_clip_ray_plane)) {
543  madd_v3_v3v3fl(r_out, ray_co, ray_no, lambda);
544 
545  /* Handle clipping with an orthographic view differently,
546  * check if the resulting point is behind the view instead of clipping the ray. */
547  if (do_clip && (do_clip_ray_plane == false)) {
548  /* The offset is unit length where over 1.0 is beyond the views clip-plane (near and far)
549  * as non-camera orthographic views only use far distance in both directions.
550  * Multiply `r_out` by `persmat` (with translation), and get it's Z value. */
551  const float z_offset = fabsf(dot_m4_v3_row_z(rv3d->persmat, r_out) + rv3d->persmat[3][2]);
552  if (z_offset > 1.0f) {
553  return false;
554  }
555  }
556  return true;
557  }
558  return false;
559 }
560 
562  const float plane[4],
563  const int mval[2],
564  const bool do_clip,
565  float r_out[3])
566 {
567  const float mval_fl[2] = {mval[0], mval[1]};
568  return ED_view3d_win_to_3d_on_plane(region, plane, mval_fl, do_clip, r_out);
569 }
570 
572  const float plane[4],
573  const float mval[2],
574  const bool do_clip,
575  const float plane_fallback[4],
576  float r_out[3])
577 {
578  float isect_co[3], isect_no[3];
579  if (!isect_plane_plane_v3(plane, plane_fallback, isect_co, isect_no)) {
580  return false;
581  }
582  normalize_v3(isect_no);
583 
584  /* Construct matrix to transform `plane_fallback` onto `plane`. */
585  float mat4[4][4];
586  {
587  float mat3[3][3];
588  rotation_between_vecs_to_mat3(mat3, plane, plane_fallback);
589  copy_m4_m3(mat4, mat3);
590  transform_pivot_set_m4(mat4, isect_co);
591  }
592 
593  float co[3];
594  if (!ED_view3d_win_to_3d_on_plane(region, plane_fallback, mval, do_clip, co)) {
595  return false;
596  }
597  mul_m4_v3(mat4, co);
598 
599  /* While the point is already on the plane, there may be some small in-precision
600  * so ensure the point is exactly on the plane. */
601  closest_to_plane_v3(r_out, plane, co);
602 
603  return true;
604 }
605 
606 void ED_view3d_win_to_delta(const ARegion *region,
607  const float xy_delta[2],
608  const float zfac,
609  float r_out[3])
610 {
611  RegionView3D *rv3d = region->regiondata;
612  float dx, dy;
613 
614  dx = 2.0f * xy_delta[0] * zfac / region->winx;
615  dy = 2.0f * xy_delta[1] * zfac / region->winy;
616 
617  r_out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
618  r_out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
619  r_out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy);
620 }
621 
622 void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3])
623 {
624  RegionView3D *rv3d = region->regiondata;
625  if (rv3d->is_persp) {
626  copy_v3_v3(r_out, rv3d->viewinv[3]);
627  }
628  else {
629  r_out[0] = 2.0f * mval[0] / region->winx - 1.0f;
630  r_out[1] = 2.0f * mval[1] / region->winy - 1.0f;
631 
632  if (rv3d->persp == RV3D_CAMOB) {
633  r_out[2] = -1.0f;
634  }
635  else {
636  r_out[2] = 0.0f;
637  }
638 
639  mul_project_m4_v3(rv3d->persinv, r_out);
640  }
641 }
642 
643 void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3])
644 {
645  RegionView3D *rv3d = region->regiondata;
646 
647  if (rv3d->is_persp) {
648  r_out[0] = 2.0f * (mval[0] / region->winx) - 1.0f;
649  r_out[1] = 2.0f * (mval[1] / region->winy) - 1.0f;
650  r_out[2] = -0.5f;
651  mul_project_m4_v3(rv3d->persinv, r_out);
652  sub_v3_v3(r_out, rv3d->viewinv[3]);
653  }
654  else {
655  negate_v3_v3(r_out, rv3d->viewinv[2]);
656  }
657  normalize_v3(r_out);
658 }
659 
661  const ARegion *region,
662  const View3D *v3d,
663  const float mval[2],
664  float r_ray_start[3],
665  float r_ray_end[3],
666  const bool do_clip_planes)
667 {
668  view3d_win_to_ray_segment(depsgraph, region, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
669 
670  /* bounds clipping */
671  if (do_clip_planes) {
672  return ED_view3d_clip_segment((RegionView3D *)region->regiondata, r_ray_start, r_ray_end);
673  }
674 
675  return true;
676 }
677 
678 /* -------------------------------------------------------------------- */
682 void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, float r_pmat[4][4])
683 {
684  float vmat[4][4];
685 
686  mul_m4_m4m4(vmat, rv3d->viewmat, ob->obmat);
687  mul_m4_m4m4(r_pmat, rv3d->winmat, vmat);
688 }
689 
691  const float obmat[4][4],
692  float r_pmat[4][4])
693 {
694  float vmat[4][4];
695 
696  mul_m4_m4m4(vmat, rv3d->viewmat, obmat);
697  mul_m4_m4m4(r_pmat, rv3d->winmat, vmat);
698 }
699 
700 void ED_view3d_project_v3(const struct ARegion *region, const float world[3], float r_region_co[3])
701 {
702  /* Viewport is set up to make coordinates relative to the region, not window. */
703  RegionView3D *rv3d = region->regiondata;
704  const int viewport[4] = {0, 0, region->winx, region->winy};
705  GPU_matrix_project_3fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
706 }
707 
708 void ED_view3d_project_v2(const struct ARegion *region, const float world[3], float r_region_co[2])
709 {
710  /* Viewport is set up to make coordinates relative to the region, not window. */
711  RegionView3D *rv3d = region->regiondata;
712  const int viewport[4] = {0, 0, region->winx, region->winy};
713  GPU_matrix_project_2fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
714 }
715 
717  const struct ARegion *region, float regionx, float regiony, float regionz, float world[3])
718 {
719  RegionView3D *rv3d = region->regiondata;
720  const int viewport[4] = {0, 0, region->winx, region->winy};
721  const float region_co[3] = {regionx, regiony, regionz};
722 
723  return GPU_matrix_unproject_3fv(region_co, rv3d->viewinv, rv3d->winmat, viewport, world);
724 }
725 
typedef float(TangentPoint)[2]
Camera data-block and utility functions.
int BKE_camera_sensor_fit(int sensor_fit, float sizex, float sizey)
Definition: camera.c:246
float BKE_screen_view3d_zoom_to_fac(float camzoom)
Definition: screen.c:1027
#define BLI_assert(a)
Definition: BLI_assert.h:46
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], int plane_num, float r_p1[3], float r_p2[3])
Definition: math_geom.c:3464
bool isect_ray_plane_v3(const float ray_origin[3], const float ray_direction[3], const float plane[4], float *r_lambda, bool clip)
Definition: math_geom.c:1713
bool isect_plane_plane_v3(const float plane_a[4], const float plane_b[4], float r_isect_co[3], float r_isect_no[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_geom.c:2134
float ray_point_factor_v3(const float p[3], const float ray_origin[3], const float ray_direction[3])
Definition: math_geom.c:3232
void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:401
void mul_project_m4_v3(const float M[4][4], float vec[3])
Definition: math_matrix.c:820
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void mul_m4_v4(const float M[4][4], float r[4])
Definition: math_matrix.c:862
void copy_m4_m3(float m1[4][4], const float m2[3][3])
Definition: math_matrix.c:102
void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
Definition: math_matrix.c:2369
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ CAMERA_SENSOR_FIT_HOR
Object is a sort of wrapper for general info.
#define RV3D_CAMOB
#define RV3D_CLIPPING
bool ED_view3d_clip_range_get(const struct Depsgraph *depsgraph, const struct View3D *v3d, const struct RegionView3D *rv3d, float *r_clipsta, float *r_clipend, bool use_ortho_factor)
eV3DProjTest
Definition: ED_view3d.h:233
@ V3D_PROJ_TEST_CLIP_FAR
Definition: ED_view3d.h:238
@ V3D_PROJ_TEST_CLIP_NEAR
Definition: ED_view3d.h:237
@ V3D_PROJ_TEST_CLIP_ZERO
Definition: ED_view3d.h:239
@ V3D_PROJ_TEST_NOP
Definition: ED_view3d.h:234
@ V3D_PROJ_TEST_CLIP_WIN
Definition: ED_view3d.h:236
@ V3D_PROJ_TEST_CLIP_BB
Definition: ED_view3d.h:235
eV3DProjStatus
Definition: ED_view3d.h:216
@ V3D_PROJ_RET_CLIP_WIN
Definition: ED_view3d.h:227
@ V3D_PROJ_RET_CLIP_BB
Definition: ED_view3d.h:225
@ V3D_PROJ_RET_CLIP_FAR
Definition: ED_view3d.h:221
@ V3D_PROJ_RET_CLIP_ZERO
Definition: ED_view3d.h:223
@ V3D_PROJ_RET_CLIP_NEAR
Definition: ED_view3d.h:219
@ V3D_PROJ_RET_OVERFLOW
Definition: ED_view3d.h:229
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:217
bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], bool is_local)
#define IS_CLIPPED
Definition: ED_view3d.h:213
#define V3D_PROJ_TEST_CLIP_DEFAULT
Definition: ED_view3d.h:264
#define V3D_PROJ_TEST_ALL
Definition: ED_view3d.h:266
#define ED_view3d_check_mats_rv3d(rv3d)
Definition: ED_view3d.h:1031
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])
Definition: gpu_matrix.cc:481
bool GPU_matrix_unproject_3fv(const float win[3], const float model_inverted[4][4], const float proj[4][4], const int view[4], float r_world[3])
Definition: gpu_matrix.cc:500
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])
Definition: gpu_matrix.cc:461
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
World world
const Depsgraph * depsgraph
Frequency::PASS vec4
#define floorf(x)
Definition: metal/compat.h:224
#define fabsf(x)
Definition: metal/compat.h:219
bool isfinite(uchar)
Definition: scene/image.cpp:31
return ret
void * regiondata
short sy
struct Object * object
short sx
char sensor_fit
float shiftx
float shifty
float obmat[4][4]
void * data
float persmat[4][4]
float clip[6][4]
float persinv[4][4]
float viewmat[4][4]
float persmatob[4][4]
float viewinv[4][4]
float winmat[4][4]
float clip_end
struct Object * camera
bool ED_view3d_win_to_3d_on_plane(const ARegion *region, const float plane[4], const float mval[2], const bool do_clip, float r_out[3])
void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, float r_pmat[4][4])
void ED_view3d_project_float_v3_m4(const ARegion *region, const float co[3], float r_co[3], const float mat[4][4])
void ED_view3d_win_to_ray(const ARegion *region, const float mval[2], float r_ray_start[3], float r_ray_normal[3])
eV3DProjStatus ED_view3d_project_base(const struct ARegion *region, struct Base *base)
eV3DProjStatus ED_view3d_project_short_ex(const ARegion *region, float perspmat[4][4], const bool is_local, const float co[3], short r_co[2], const eV3DProjTest flag)
eV3DProjStatus ED_view3d_project_float_object(const ARegion *region, const float co[3], float r_co[2], const eV3DProjTest flag)
bool ED_view3d_win_to_3d_on_plane_with_fallback(const ARegion *region, const float plane[4], const float mval[2], const bool do_clip, const float plane_fallback[4], float r_out[3])
void ED_view3d_win_to_3d_int(const View3D *v3d, const ARegion *region, const float depth_pt[3], const int mval[2], float r_out[3])
float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3])
void ED_view3d_win_to_3d(const View3D *v3d, const ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], const bool do_clip_planes)
void ED_view3d_project_v3(const struct ARegion *region, const float world[3], float r_region_co[3])
void ED_view3d_win_to_delta(const ARegion *region, const float xy_delta[2], const float zfac, float r_out[3])
float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3])
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
static void view3d_win_to_ray_segment(const struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3])
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], const eV3DProjTest flag)
eV3DProjStatus ED_view3d_project_int_object(const ARegion *region, const float co[3], int r_co[2], const eV3DProjTest flag)
eV3DProjStatus ED_view3d_project_short_global(const ARegion *region, const float co[3], short r_co[2], const eV3DProjTest flag)
bool ED_view3d_unproject_v3(const struct ARegion *region, float regionx, float regiony, float regionz, float world[3])
eV3DProjStatus ED_view3d_project_int_ex(const ARegion *region, float perspmat[4][4], const bool is_local, const float co[3], int r_co[2], const eV3DProjTest flag)
bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_normal[3], const bool do_clip_planes)
void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3])
float ED_view3d_calc_zfac_ex(const RegionView3D *rv3d, const float co[3], bool *r_flip)
void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3])
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
void ED_view3d_project_v2(const struct ARegion *region, const float world[3], float r_region_co[2])
void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, const float obmat[4][4], float r_pmat[4][4])
#define BL_ZERO_CLIP
eV3DProjStatus ED_view3d_project_float_ex(const ARegion *region, float perspmat[4][4], const bool is_local, const float co[3], float r_co[2], const eV3DProjTest flag)
eV3DProjStatus ED_view3d_project_short_object(const ARegion *region, const float co[3], short r_co[2], const eV3DProjTest flag)
void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3])
void ED_view3d_project_float_v2_m4(const ARegion *region, const float co[3], float r_co[2], const float mat[4][4])
eV3DProjStatus ED_view3d_project_int_global(const ARegion *region, const float co[3], int r_co[2], const eV3DProjTest flag)
static eV3DProjStatus ed_view3d_project__internal(const ARegion *region, const float perspmat[4][4], const bool is_local, const float co[3], float r_co[2], const eV3DProjTest flag)
bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip_planes)
bool ED_view3d_win_to_3d_on_plane_int(const ARegion *region, const float plane[4], const int mval[2], const bool do_clip, float r_out[3])