Blender V4.3
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_view3d_types.h"
14
15#include "BLI_sys_types.h" /* int64_t */
16
17#include "BLI_math_geom.h"
18#include "BLI_math_matrix.h"
19#include "BLI_math_rotation.h"
20#include "BLI_math_vector.h"
21
22#include "BKE_camera.h"
23#include "BKE_screen.hh"
24
25#include "GPU_matrix.hh"
26
27#include "ED_view3d.hh" /* own include */
28
29#define BL_ZERO_CLIP 0.001
30
31/* Non Clipping Projection Functions
32 * ********************************* */
33
35 const float co[3],
36 const blender::float4x4 &mat)
37{
38 float vec4[4];
39
40 copy_v3_v3(vec4, co);
41 vec4[3] = 1.0;
42 // r_co[0] = IS_CLIPPED; /* Always overwritten. */
43
44 mul_m4_v4(mat.ptr(), vec4);
45
46 blender::float2 r_co;
47 if (vec4[3] > FLT_EPSILON) {
48 r_co[0] = float(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
49 r_co[1] = float(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
50 }
51 else {
52 zero_v2(r_co);
53 }
54 return r_co;
55}
56
58 const float co[3],
59 float r_co[3],
60 const float mat[4][4])
61{
62 float vec4[4];
63
64 copy_v3_v3(vec4, co);
65 vec4[3] = 1.0;
66 // r_co[0] = IS_CLIPPED; /* Always overwritten. */
67
68 mul_m4_v4(mat, vec4);
69
70 if (vec4[3] > FLT_EPSILON) {
71 r_co[0] = float(region->winx / 2.0f) + (region->winx / 2.0f) * vec4[0] / vec4[3];
72 r_co[1] = float(region->winy / 2.0f) + (region->winy / 2.0f) * vec4[1] / vec4[3];
73 r_co[2] = vec4[2] / vec4[3];
74 }
75 else {
76 zero_v3(r_co);
77 }
78}
79
80/* Clipping Projection Functions
81 * ***************************** */
82
83eV3DProjStatus ED_view3d_project_base(const ARegion *region, Base *base, float r_co[2])
84{
86 region, base->object->object_to_world().location(), r_co, V3D_PROJ_TEST_CLIP_DEFAULT);
87
88 /* Prevent uninitialized values when projection fails,
89 * although the callers should check the return value. */
90 if (ret != V3D_PROJ_RET_OK) {
91 r_co[0] = -1.0;
92 r_co[1] = -1.0;
93 }
94
95 return ret;
96}
97
104 const float perspmat[4][4],
105 const bool is_local, /* normally hidden */
106 const float co[3],
107 float r_co[2],
108 const eV3DProjTest flag)
109{
110 float vec4[4];
111
112 /* check for bad flags */
114
116 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
117 if (rv3d->rflag & RV3D_CLIPPING) {
118 if (ED_view3d_clipping_test(rv3d, co, is_local)) {
120 }
121 }
122 }
123
124 copy_v3_v3(vec4, co);
125 vec4[3] = 1.0;
126 mul_m4_v4(perspmat, vec4);
127 const float w = fabsf(vec4[3]);
128
129 if ((flag & V3D_PROJ_TEST_CLIP_ZERO) && (w <= float(BL_ZERO_CLIP))) {
131 }
132
133 if ((flag & V3D_PROJ_TEST_CLIP_NEAR) && (vec4[2] <= -w)) {
135 }
136
137 if ((flag & V3D_PROJ_TEST_CLIP_FAR) && (vec4[2] >= w)) {
139 }
140
141 const float scalar = (w != 0.0f) ? (1.0f / w) : 0.0f;
142 const float fx = (float(region->winx) / 2.0f) * (1.0f + (vec4[0] * scalar));
143 const float fy = (float(region->winy) / 2.0f) * (1.0f + (vec4[1] * scalar));
144
146 (fx <= 0.0f || fy <= 0.0f || fx >= float(region->winx) || fy >= float(region->winy)))
147 {
149 }
150
151 r_co[0] = fx;
152 r_co[1] = fy;
153
154 return V3D_PROJ_RET_OK;
155}
156
158 float perspmat[4][4],
159 const bool is_local,
160 const float co[3],
161 short r_co[2],
162 const eV3DProjTest flag)
163{
164 float tvec[2];
165 eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
166 if (ret == V3D_PROJ_RET_OK) {
167 if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) && (tvec[1] > -32700.0f && tvec[1] < 32700.0f))
168 {
169 r_co[0] = short(floorf(tvec[0]));
170 r_co[1] = short(floorf(tvec[1]));
171 }
172 else {
174 }
175 }
176 return ret;
177}
178
180 float perspmat[4][4],
181 const bool is_local,
182 const float co[3],
183 int r_co[2],
184 const eV3DProjTest flag)
185{
186 float tvec[2];
187 eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
188 if (ret == V3D_PROJ_RET_OK) {
189 if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) &&
190 (tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f))
191 {
192 r_co[0] = int(floorf(tvec[0]));
193 r_co[1] = int(floorf(tvec[1]));
194 }
195 else {
197 }
198 }
199 return ret;
200}
201
203 float perspmat[4][4],
204 const bool is_local,
205 const float co[3],
206 float r_co[2],
207 const eV3DProjTest flag)
208{
209 float tvec[2];
210 eV3DProjStatus ret = ed_view3d_project__internal(region, perspmat, is_local, co, tvec, flag);
211 if (ret == V3D_PROJ_RET_OK) {
212 if (isfinite(tvec[0]) && isfinite(tvec[1])) {
213 copy_v2_v2(r_co, tvec);
214 }
215 else {
217 }
218 }
219 return ret;
220}
221
223 const float co[3],
224 short r_co[2],
225 const eV3DProjTest flag)
226{
227 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
228 return ED_view3d_project_short_ex(region, rv3d->persmat, false, co, r_co, flag);
229}
231 const float co[3],
232 short r_co[2],
233 const eV3DProjTest flag)
234{
235 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
237 return ED_view3d_project_short_ex(region, rv3d->persmatob, true, co, r_co, flag);
238}
239
241 const float co[3],
242 int r_co[2],
243 const eV3DProjTest flag)
244{
245 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
246 return ED_view3d_project_int_ex(region, rv3d->persmat, false, co, r_co, flag);
247}
249 const float co[3],
250 int r_co[2],
251 const eV3DProjTest flag)
252{
253 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
255 return ED_view3d_project_int_ex(region, rv3d->persmatob, true, co, r_co, flag);
256}
257
259 const float co[3],
260 float r_co[2],
261 const eV3DProjTest flag)
262{
263 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
264 return ED_view3d_project_float_ex(region, rv3d->persmat, false, co, r_co, flag);
265}
267 const float co[3],
268 float r_co[2],
269 const eV3DProjTest flag)
270{
271 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
273 return ED_view3d_project_float_ex(region, rv3d->persmatob, true, co, r_co, flag);
274}
275
276/* More Generic Window/Ray/Vector projection functions
277 * *************************************************** */
278
279float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
280{
281 return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
282}
283
284float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3])
285{
286 return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize;
287}
288
289float ED_view3d_calc_zfac_ex(const RegionView3D *rv3d, const float co[3], bool *r_flip)
290{
291 float zfac = mul_project_m4_v3_zfac(rv3d->persmat, co);
292
293 if (r_flip) {
294 *r_flip = (zfac < 0.0f);
295 }
296
297 /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
298 * (accounting for near zero values) */
299 if (zfac < 1.e-6f && zfac > -1.e-6f) {
300 zfac = 1.0f;
301 }
302
303 /* Negative zfac means x, y, z was behind the camera (in perspective).
304 * This gives flipped directions, so revert back to ok default case. */
305 if (zfac < 0.0f) {
306 zfac = -zfac;
307 }
308
309 return zfac;
310}
311
312float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
313{
314 return ED_view3d_calc_zfac_ex(rv3d, co, nullptr);
315}
316
317float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3])
318{
319 if (rv3d->is_persp) {
320 return ED_view3d_calc_zfac(rv3d, co);
321 }
322 return -dot_v3v3(rv3d->viewinv[2], co);
323}
324
325static void view3d_win_to_ray_segment(const Depsgraph *depsgraph,
326 const ARegion *region,
327 const View3D *v3d,
328 const float mval[2],
329 float r_ray_co[3],
330 float r_ray_dir[3],
331 float r_ray_start[3],
332 float r_ray_end[3])
333{
334 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
335 float _ray_co[3], _ray_dir[3], start_offset, end_offset;
336
337 if (!r_ray_co) {
338 r_ray_co = _ray_co;
339 }
340 if (!r_ray_dir) {
341 r_ray_dir = _ray_dir;
342 }
343
344 ED_view3d_win_to_origin(region, mval, r_ray_co);
345 ED_view3d_win_to_vector(region, mval, r_ray_dir);
346
347 if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
348 end_offset = v3d->clip_end / 2.0f;
349 start_offset = -end_offset;
350 }
351 else {
352 ED_view3d_clip_range_get(depsgraph, v3d, rv3d, false, &start_offset, &end_offset);
353 }
354
355 if (r_ray_start) {
356 madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset);
357 }
358 if (r_ray_end) {
359 madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset);
360 }
361}
362
363bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
364{
365 if ((rv3d->rflag & RV3D_CLIPPING) &&
366 (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, ray_start, ray_end) == false))
367 {
368 return false;
369 }
370 return true;
371}
372
374 const ARegion *region,
375 const View3D *v3d,
376 const float mval[2],
377 const bool do_clip_planes,
378 float r_ray_co[3],
379 float r_ray_normal[3],
380 float r_ray_start[3],
381 float r_ray_end[3])
382{
384 depsgraph, region, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, r_ray_end);
385
386 /* bounds clipping */
387 if (do_clip_planes) {
389 static_cast<const RegionView3D *>(region->regiondata), r_ray_start, r_ray_end);
390 }
391
392 return true;
393}
394
396 const ARegion *region,
397 const View3D *v3d,
398 const float mval[2],
399 float r_ray_start[3],
400 float r_ray_normal[3],
401 const bool do_clip_planes)
402{
403 float ray_end_dummy[3];
405 region,
406 v3d,
407 mval,
408 do_clip_planes,
409 nullptr,
410 r_ray_normal,
411 r_ray_start,
412 ray_end_dummy);
413}
414
415void ED_view3d_win_to_ray(const ARegion *region,
416 const float mval[2],
417 float r_ray_start[3],
418 float r_ray_normal[3])
419{
420 ED_view3d_win_to_origin(region, mval, r_ray_start);
421 ED_view3d_win_to_vector(region, mval, r_ray_normal);
422}
423
424void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float r_out[3])
425{
426 if (rv3d->is_persp) {
427 float p1[4], p2[4];
428
429 copy_v3_v3(p1, coord);
430 p1[3] = 1.0f;
431 copy_v3_v3(p2, p1);
432 p2[3] = 1.0f;
433 mul_m4_v4(rv3d->viewmat, p2);
434
435 mul_v3_fl(p2, 2.0f);
436
437 mul_m4_v4(rv3d->viewinv, p2);
438
439 sub_v3_v3v3(r_out, p1, p2);
440 }
441 else {
442 copy_v3_v3(r_out, rv3d->viewinv[2]);
443 }
444 normalize_v3(r_out);
445}
446
447/* very similar to ED_view3d_win_to_3d() but has no advantage, de-duplicating */
448#if 0
449bool view3d_get_view_aligned_coordinate(ARegion *region,
450 float fp[3],
451 const int mval[2],
452 const bool do_fallback)
453{
454 RegionView3D *rv3d = region->regiondata;
455 float dvec[3];
456 int mval_cpy[2];
458
459 ret = ED_view3d_project_int_global(region, fp, mval_cpy, V3D_PROJ_TEST_NOP);
460
461 if (ret == V3D_PROJ_RET_OK) {
462 const float mval_f[2] = {float(mval_cpy[0] - mval[0]), float(mval_cpy[1] - mval[1])};
463 const float zfac = ED_view3d_calc_zfac(rv3d, fp);
464 ED_view3d_win_to_delta(region, mval_f, zfac, dvec);
465 sub_v3_v3(fp, dvec);
466
467 return true;
468 }
469 else {
470 /* fallback to the view center */
471 if (do_fallback) {
472 negate_v3_v3(fp, rv3d->ofs);
473 return view3d_get_view_aligned_coordinate(region, fp, mval, false);
474 }
475 else {
476 return false;
477 }
478 }
479}
480#endif
481
483 const ARegion *region,
484 const float depth_pt[3],
485 const float mval[2],
486 float r_out[3])
487{
488 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
489
490 float ray_origin[3];
491 float ray_direction[3];
492 float lambda;
493
494 if (rv3d->is_persp) {
495 copy_v3_v3(ray_origin, rv3d->viewinv[3]);
496 ED_view3d_win_to_vector(region, mval, ray_direction);
497
498 /* NOTE: we could use #isect_line_plane_v3()
499 * however we want the intersection to be in front of the view no matter what,
500 * so apply the unsigned factor instead. */
501 isect_ray_plane_v3_factor(ray_origin, ray_direction, depth_pt, rv3d->viewinv[2], &lambda);
502
503 lambda = fabsf(lambda);
504 }
505 else {
506 float dx = (2.0f * mval[0] / float(region->winx)) - 1.0f;
507 float dy = (2.0f * mval[1] / float(region->winy)) - 1.0f;
508
509 if (rv3d->persp == RV3D_CAMOB) {
510 /* ortho camera needs offset applied */
511 const Camera *cam = static_cast<const Camera *>(v3d->camera->data);
512 const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, region->winx, region->winy);
513 const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
514 const float aspx = region->winx / float(region->winy);
515 const float aspy = region->winy / float(region->winx);
516 const float shiftx = cam->shiftx * 0.5f *
517 (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
518 const float shifty = cam->shifty * 0.5f *
519 (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f);
520
521 dx += (rv3d->camdx + shiftx) * zoomfac;
522 dy += (rv3d->camdy + shifty) * zoomfac;
523 }
524 ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0];
525 ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1];
526 ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2];
527
528 copy_v3_v3(ray_direction, rv3d->viewinv[2]);
529 lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
530 }
531
532 madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda);
533}
534
536 const ARegion *region,
537 const float depth_pt[3],
538 const float mval[2],
539 float r_out[3])
540{
541 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
542
543 float ray_origin[3];
544 float ray_direction[3];
545 float lambda;
546
547 if (rv3d->is_persp) {
548 copy_v3_v3(ray_origin, rv3d->viewinv[3]);
549 ED_view3d_win_to_vector(region, mval, ray_direction);
550
551 /* NOTE: we could use #isect_line_plane_v3()
552 * however we want the intersection to be in front of the view no matter what,
553 * so apply the unsigned factor instead. */
554 isect_ray_plane_v3_factor(ray_origin, ray_direction, depth_pt, rv3d->viewinv[2], &lambda);
555
556 lambda = fabsf(lambda);
557 }
558 else {
559 float dx = (2.0f * mval[0] / float(region->winx)) - 1.0f;
560 float dy = (2.0f * mval[1] / float(region->winy)) - 1.0f;
561
562 if (rv3d->persp == RV3D_CAMOB) {
563 /* ortho camera needs offset applied */
564 const Camera *cam = static_cast<const Camera *>(v3d->camera->data);
565 const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, region->winx, region->winy);
566 const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f;
567 const float aspx = region->winx / float(region->winy);
568 const float aspy = region->winy / float(region->winx);
569 const float shiftx = cam->shiftx * 0.5f *
570 (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy);
571 const float shifty = cam->shifty * 0.5f *
572 (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f);
573
574 dx += (rv3d->camdx + shiftx) * zoomfac;
575 dy += (rv3d->camdy + shifty) * zoomfac;
576 }
577 ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->persinv[3][0];
578 ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->persinv[3][1];
579 ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->persinv[3][2];
580
581 copy_v3_v3(ray_direction, rv3d->viewinv[2]);
582 lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction);
583 }
584
585 madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda);
586}
587
589 const ARegion *region,
590 const float depth_pt[3],
591 const int mval[2],
592 float r_out[3])
593{
594 const float mval_fl[2] = {float(mval[0]), float(mval[1])};
595 ED_view3d_win_to_3d(v3d, region, depth_pt, mval_fl, r_out);
596}
597
599 const float plane[4],
600 const float mval[2],
601 const bool do_clip,
602 float r_out[3])
603{
604 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
605 const bool ray_co_is_centered = rv3d->is_persp == false && rv3d->persp != RV3D_CAMOB;
606 const bool do_clip_ray_plane = do_clip && !ray_co_is_centered;
607 float ray_co[3], ray_no[3];
608 ED_view3d_win_to_origin(region, mval, ray_co);
609 ED_view3d_win_to_vector(region, mval, ray_no);
610 float lambda;
611 if (isect_ray_plane_v3(ray_co, ray_no, plane, &lambda, do_clip_ray_plane)) {
612 madd_v3_v3v3fl(r_out, ray_co, ray_no, lambda);
613
614 /* Handle clipping with an orthographic view differently,
615 * check if the resulting point is behind the view instead of clipping the ray. */
616 if (do_clip && (do_clip_ray_plane == false)) {
617 /* The offset is unit length where over 1.0 is beyond the views clip-plane (near and far)
618 * as non-camera orthographic views only use far distance in both directions.
619 * Multiply `r_out` by `persmat` (with translation), and get it's Z value. */
620 const float z_offset = fabsf(dot_m4_v3_row_z(rv3d->persmat, r_out) + rv3d->persmat[3][2]);
621 if (z_offset > 1.0f) {
622 return false;
623 }
624 }
625 return true;
626 }
627 return false;
628}
629
631 const float plane[4],
632 const int mval[2],
633 const bool do_clip,
634 float r_out[3])
635{
636 const float mval_fl[2] = {float(mval[0]), float(mval[1])};
637 return ED_view3d_win_to_3d_on_plane(region, plane, mval_fl, do_clip, r_out);
638}
639
641 const float plane[4],
642 const float mval[2],
643 const bool do_clip,
644 const float plane_fallback[4],
645 float r_out[3])
646{
647 float isect_co[3], isect_no[3];
648 if (!isect_plane_plane_v3(plane, plane_fallback, isect_co, isect_no)) {
649 return false;
650 }
651 normalize_v3(isect_no);
652
653 /* Construct matrix to transform `plane_fallback` onto `plane`. */
654 float mat4[4][4];
655 {
656 float mat3[3][3];
657 rotation_between_vecs_to_mat3(mat3, plane, plane_fallback);
658 copy_m4_m3(mat4, mat3);
659 transform_pivot_set_m4(mat4, isect_co);
660 }
661
662 float co[3];
663 if (!ED_view3d_win_to_3d_on_plane(region, plane_fallback, mval, do_clip, co)) {
664 return false;
665 }
666 mul_m4_v3(mat4, co);
667
668 /* While the point is already on the plane, there may be some small in-precision
669 * so ensure the point is exactly on the plane. */
670 closest_to_plane_v3(r_out, plane, co);
671
672 return true;
673}
674
676 const float xy_delta[2],
677 const float zfac,
678 float r_out[3])
679{
680 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
681 float dx, dy;
682
683 dx = 2.0f * xy_delta[0] * zfac / region->winx;
684 dy = 2.0f * xy_delta[1] * zfac / region->winy;
685
686 r_out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
687 r_out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
688 r_out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy);
689}
690
691void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3])
692{
693 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
694 if (rv3d->is_persp) {
695 copy_v3_v3(r_out, rv3d->viewinv[3]);
696 }
697 else {
698 r_out[0] = 2.0f * mval[0] / region->winx - 1.0f;
699 r_out[1] = 2.0f * mval[1] / region->winy - 1.0f;
700
701 if (rv3d->persp == RV3D_CAMOB) {
702 r_out[2] = -1.0f;
703 }
704 else {
705 r_out[2] = 0.0f;
706 }
707
708 mul_project_m4_v3(rv3d->persinv, r_out);
709 }
710}
711
712void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3])
713{
714 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
715
716 if (rv3d->is_persp) {
717 r_out[0] = 2.0f * (mval[0] / region->winx) - 1.0f;
718 r_out[1] = 2.0f * (mval[1] / region->winy) - 1.0f;
719 r_out[2] = -0.5f;
720 mul_project_m4_v3(rv3d->persinv, r_out);
721 sub_v3_v3(r_out, rv3d->viewinv[3]);
722 }
723 else {
724 negate_v3_v3(r_out, rv3d->viewinv[2]);
725 }
726 normalize_v3(r_out);
727}
728
730 const ARegion *region,
731 const View3D *v3d,
732 const float mval[2],
733 float r_ray_start[3],
734 float r_ray_end[3],
735 const bool do_clip_planes)
736{
738 depsgraph, region, v3d, mval, nullptr, nullptr, r_ray_start, r_ray_end);
739
740 /* bounds clipping */
741 if (do_clip_planes) {
742 return ED_view3d_clip_segment((RegionView3D *)region->regiondata, r_ray_start, r_ray_end);
743 }
744
745 return true;
746}
747
748/* -------------------------------------------------------------------- */
751
753{
754 float vmat[4][4];
755 blender::float4x4 r_pmat;
756
757 mul_m4_m4m4(vmat, rv3d->viewmat, ob->object_to_world().ptr());
758 mul_m4_m4m4(r_pmat.ptr(), rv3d->winmat, vmat);
759 return r_pmat;
760}
761
767
768void ED_view3d_project_v3(const ARegion *region, const float world[3], float r_region_co[3])
769{
770 /* Viewport is set up to make coordinates relative to the region, not window. */
771 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
772 const int viewport[4] = {0, 0, region->winx, region->winy};
773 GPU_matrix_project_3fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
774}
775
776void ED_view3d_project_v2(const ARegion *region, const float world[3], float r_region_co[2])
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_2fv(world, rv3d->viewmat, rv3d->winmat, viewport, r_region_co);
782}
783
785 const ARegion *region, float regionx, float regiony, float regionz, float world[3])
786{
787 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
788 const int viewport[4] = {0, 0, region->winx, region->winy};
789 const float region_co[3] = {regionx, regiony, regionz};
790
791 return GPU_matrix_unproject_3fv(region_co, rv3d->viewinv, rv3d->winmat, viewport, world);
792}
793
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:998
#define BLI_assert(a)
Definition BLI_assert.h:50
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:433
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])
void mul_m4_v4(const float mat[4][4], float r[4])
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:274
@ V3D_PROJ_TEST_CLIP_FAR
Definition ED_view3d.hh:279
@ V3D_PROJ_TEST_CLIP_NEAR
Definition ED_view3d.hh:278
@ V3D_PROJ_TEST_CLIP_ZERO
Definition ED_view3d.hh:280
@ V3D_PROJ_TEST_NOP
Definition ED_view3d.hh:275
@ V3D_PROJ_TEST_CLIP_WIN
Definition ED_view3d.hh:277
@ V3D_PROJ_TEST_CLIP_BB
Definition ED_view3d.hh:276
eV3DProjStatus
Definition ED_view3d.hh:251
@ V3D_PROJ_RET_CLIP_WIN
Definition ED_view3d.hh:267
@ V3D_PROJ_RET_CLIP_BB
Definition ED_view3d.hh:265
@ V3D_PROJ_RET_CLIP_FAR
Definition ED_view3d.hh:256
@ V3D_PROJ_RET_CLIP_ZERO
Definition ED_view3d.hh:263
@ V3D_PROJ_RET_CLIP_NEAR
Definition ED_view3d.hh:254
@ V3D_PROJ_RET_OVERFLOW
Definition ED_view3d.hh:269
@ V3D_PROJ_RET_OK
Definition ED_view3d.hh:252
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:305
#define V3D_PROJ_TEST_ALL
Definition ED_view3d.hh:307
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])
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between world
#define U
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define floorf(x)
#define fabsf(x)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
velocity_obj_prev_buf[] vec4
MatBase< float, 4, 4 > float4x4
MatView< float, 4, 4, 4, 4, 0, 0, alignof(float)> float4x4_view
VecBase< float, 2 > float2
return ret
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])
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])
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])
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:138