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