Unravel Engine C++ Reference
Loading...
Searching...
No Matches
camera.cpp
Go to the documentation of this file.
1#include "camera.h"
2#include "base/basetypes.hpp"
3
4#include <graphics/graphics.h>
5
6#include <algorithm>
7#include <limits>
8
9namespace unravel
10{
11auto camera::get_zoom_factor() const -> float
12{
13 if(viewport_size_.height == 0)
14 {
15 return 0.0f;
16 }
17
18 return ortho_size_ / (float(viewport_size_.height) / 2.0f);
19}
20
21auto camera::get_ppu() const -> float
22{
23 return float(viewport_size_.height) / (2.0f * ortho_size_);
24}
25
26void camera::set_viewport_size(const usize32_t& viewport_size)
27{
28 viewport_size_ = viewport_size;
29 set_aspect_ratio(float(viewport_size.width) / float(viewport_size.height));
30}
31
32void camera::set_viewport_pos(const ipoint32_t& viewportPos)
33{
34 viewport_pos_ = viewportPos;
35}
36
38{
39 return viewport_size_;
40}
41
43{
44 return viewport_pos_;
45}
46
48{
50
51 touch();
52}
53
58
59auto camera::get_fov() const -> float
60{
61 return fov_;
62}
63
64auto camera::get_near_clip() const -> float
65{
66 return near_clip_;
67}
68
69auto camera::get_far_clip() const -> float
70{
71 return far_clip_;
72}
73
74auto camera::get_ortho_size() const -> float
75{
76 return ortho_size_;
77}
78
79void camera::set_fov(float fFOVY)
80{
81 // Skip if no-op
82 if(math::equal(fFOVY, fov_, math::epsilon<float>()))
83 {
84 return;
85 }
86
87 // Update projection matrix and view frustum
88 fov_ = fFOVY;
89
90 touch();
91}
92
94{
95 // Bail if this is a no op.
96 if(mode == projection_mode_)
97 {
98 return;
99 }
100
101 // Alter the projection mode.
102 projection_mode_ = mode;
103
104 touch();
105}
106
107void camera::set_near_clip(float distance)
108{
109 // Skip if this is a no-op
110 if(math::equal(distance, near_clip_, math::epsilon<float>()))
111 {
112 return;
113 }
114
115 // Store value
116 near_clip_ = distance;
117
118 touch();
119
120 // Make sure near clip is less than the far clip
122 {
124 }
125}
126
127void camera::set_far_clip(float distance)
128{
129 // Skip if this is a no-op
130 if(math::equal(distance, far_clip_, math::epsilon<float>()))
131 {
132 return;
133 }
134
135 // Store value
136 far_clip_ = distance;
137
138 touch();
139
140 // Make sure near clip is less than the far clip
142 {
144 }
145}
146
148{
149 if(projection_mode_ == projection_mode::perspective)
150 {
151 float far_size = math::tan(math::radians<float>(fov_ * 0.5f)) * far_clip_;
152 return math::bbox(-far_size * aspect_ratio_,
153 -far_size,
154 near_clip_,
155 far_size * aspect_ratio_,
156 far_size,
157 far_clip_);
158 }
159
160 float spread = far_clip_ - near_clip_;
161 math::vec3 center = {0.0f, 0.0f, (far_clip_ + near_clip_) * 0.5f};
162 float orthographicSize = get_ortho_size();
163 math::vec3 size = {orthographicSize * 2.0f * aspect_ratio_, orthographicSize * 2.0f, spread};
164 return math::bbox(center - (size / 2.0f), center + (size / 2.0f));
165}
166
167void camera::set_aspect_ratio(float aspect, bool bLocked /* = false */)
168{
169 // Is this a no-op?
170 if(math::equal(aspect, aspect_ratio_, math::epsilon<float>()))
171 {
172 aspect_locked_ = bLocked;
173 return;
174
175 } // End if aspect is the same
176
177 // Update camera properties
178 aspect_ratio_ = aspect;
179 aspect_locked_ = bLocked;
180 aspect_dirty_ = true;
181 frustum_dirty_ = true;
182 projection_dirty_ = true;
183}
184
185auto camera::get_aspect_ratio() const -> float
186{
187 return aspect_ratio_;
188}
189
194
195auto camera::is_frustum_locked() const -> bool
196{
197 return frustum_locked_;
198}
199
200void camera::lock_frustum(bool locked)
201{
202 frustum_locked_ = locked;
203}
204
205auto camera::get_projection() const -> const math::transform&
206{
207 // Only update matrix if something has changed
209 {
211 {
212 // Generate the updated perspective projection matrix
213 float fov_radians = math::radians<float>(get_fov());
214 static const auto perspective_ =
215 gfx::is_homogeneous_depth() ? math::perspectiveNO<float> : math::perspectiveZO<float>;
216
217 math::mat4 projection = perspective_(fov_radians, aspect_ratio_, near_clip_, far_clip_);
218
219 projection[2][0] += aa_data_.z;
220 projection[2][1] += aa_data_.w;
221 projection_ = projection;
222 // Matrix has been updated
223 projection_dirty_ = false;
224 aspect_dirty_ = false;
225
226 } // End if projection matrix needs updating
227 else if(aspect_dirty_)
228 {
229 // Just alter the aspect ratio
230 math::mat4 projection = projection_;
231 projection[0][0] = projection[1][1] / aspect_ratio_;
232 projection_ = projection;
233 // Matrix has been updated
234 aspect_dirty_ = false;
235
236 } // End if only aspect ratio changed
237
238 } // End if perspective
240 {
242 {
243 // Generate the updated orthographic projection matrix
244 float zoom = get_zoom_factor();
245 const frect_t rect = {-float(viewport_size_.width) / 2.0f,
246 float(viewport_size_.height) / 2.0f,
247 float(viewport_size_.width) / 2.0f,
248 -float(viewport_size_.height) / 2.0f};
249 static const auto ortho_ =
250 gfx::is_homogeneous_depth() ? math::orthoNO<float> : math::orthoZO<float>;
251
252 math::mat4 projection = ortho_(rect.left * zoom,
253 rect.right * zoom,
254 rect.bottom * zoom,
255 rect.top * zoom,
257 get_far_clip());
258 projection[2][0] += aa_data_.z;
259 projection[2][1] += aa_data_.w;
260 projection_ = projection;
261 // Matrix has been updated
262 projection_dirty_ = false;
263 aspect_dirty_ = false;
264
265 } // End if projection matrix needs updating
266
267 } // End if orthographic
268
269 // Return the projection matrix.
270 return projection_;
271}
272
273auto camera::get_prev_projection() const -> const math::transform&
274{
275 return last_projection_;
276}
277
278auto camera::get_view() const -> const math::transform&
279{
280 return view_;
281}
282
283auto camera::get_prev_view() const -> const math::transform&
284{
285 return last_view_;
286}
287
288auto camera::get_view_relative() const -> const math::transform&
289{
290 return view_relative_;
291}
292
293auto camera::get_prev_view_relative() const -> const math::transform&
294{
295 return last_view_relative_;
296}
297
298auto camera::get_view_inverse() const -> const math::transform&
299{
300 return view_inverse_;
301}
302
303auto camera::get_view_inverse_relative() const -> const math::transform&
304{
306}
307
308auto camera::get_view_projection() const -> math::transform
309{
310 return get_projection() * get_view();
311}
312
313auto camera::get_prev_view_projection() const -> math::transform
314{
316}
317
319{
321}
322
324{
326}
327
332
333void camera::look_at(const math::vec3& vEye, const math::vec3& vAt)
334{
335 look_at(vEye, vAt, math::vec3(0.0f, 1.0f, 0.0f));
336}
337
338void camera::look_at(const math::vec3& vEye, const math::vec3& vAt, const math::vec3& vUp)
339{
340 // First update so the camera can cache the previous matrices
341 // record_current_matrices();
342
343 view_ = math::lookAt(vEye, vAt, vUp);
345
346
347 view_relative_ = math::lookAt(math::vec3(0.0f, 0.0f, 0.0f), vAt - vEye, vUp);
349
350 touch();
351}
352
353auto camera::get_position() const -> const math::vec3&
354{
356}
357
358auto camera::x_unit_axis() const -> math::vec3
359{
360 return view_inverse_.x_unit_axis();
361}
362auto camera::y_unit_axis() const -> math::vec3
363{
364 return view_inverse_.y_unit_axis();
365}
366
367auto camera::z_unit_axis() const -> math::vec3
368{
369 return view_inverse_.z_unit_axis();
370}
371
372auto camera::get_frustum() const -> const math::frustum&
373{
374 // Recalculate frustum if necessary
376 {
378 frustum_dirty_ = false;
379
380 // Also build the frustum / volume that represents the space between the
381 // camera position and its near plane. This frustum represents the
382 // 'volume' that can end up clipping geometry.
383
388 //-math::dot((math::vec3&)_clipping_volume.planes[math::volume_plane::near_plane],
389 // get_position()); // At camera
391 // The corner points also need adjusting in this case such that they sit
392 // precisely on the new planes.
405
406 } // End if recalc frustum
407
408 // Return the frustum
409 return frustum_;
410}
411
412auto camera::get_clipping_volume() const -> const math::frustum&
413{
414 // Recalculate frustum if necessary
416 {
417 get_frustum();
418 }
419
420 // Return the clipping volume
421 return clipping_volume_;
422}
423
425{
426 // Recompute the frustum as necessary.
427 const math::frustum& f = get_frustum();
428
429 // Request that frustum classifies
430 return f.classify_aabb(AABB);
431}
432
433auto camera::test_aabb(const math::bbox& AABB) const -> bool
434{
435 // Recompute the frustum as necessary.
436 const math::frustum& f = get_frustum();
437
438 // Request that frustum classifies
439 return f.test_aabb(AABB);
440}
441
443{
444 // Recompute the frustum as necessary.
445 const math::frustum& f = get_frustum();
446
447 // Request that frustum classifies
448 return f.classify_obb(AABB, t);
449}
450
451auto camera::test_obb(const math::bbox& AABB, const math::transform& t) const -> bool
452{
453 // Recompute the frustum as necessary.
454 const math::frustum& f = get_frustum();
455
456 // Request that frustum classifies
457 return f.test_obb(AABB, t);
458}
459
460auto camera::test_billboard(float size, const math::transform& t) const -> bool
461{
462 // Recompute the frustum as necessary.
463 const math::frustum& f = get_frustum();
464
465 auto center = t.get_position();
466 // 2) Build our test‐sphere
467 float radius = size * glm::root_two<float>();
468 math::bsphere sphere{center, radius};
469
470 return f.test_sphere(sphere);
471}
472
473auto camera::world_to_viewport(const math::vec3& pos) const -> math::vec3
474{
475 // Ensure we have an up-to-date projection and view matrix
476 auto view_proj = get_view_projection();
477
478 // Transform the point into clip space
479 math::vec4 clip = view_proj * math::vec4{pos.x, pos.y, pos.z, 1.0f};
480
481 // Project!
482 const float recip_w = 1.0f / clip.w;
483 clip.x *= recip_w;
484 clip.y *= recip_w;
485 clip.z *= recip_w;
486
487 // Transform to final screen space position
488 math::vec3 point;
489 point.x = ((clip.x * 0.5f) + 0.5f) * float(viewport_size_.width) + float(viewport_pos_.x);
490 point.y = ((clip.y * -0.5f) + 0.5f) * float(viewport_size_.height) + float(viewport_pos_.y);
491 point.z = clip.z;
492
493 // Point on screen!
494 return point;
495}
496
497auto camera::viewport_to_ray(const math::vec2& point, math::vec3& vec_ray_start, math::vec3& vec_ray_dir) const -> bool
498{
499 // Ensure we have an up-to-date projection and view matrix
500 math::transform mtx_proj = get_projection();
501 math::transform mtx_view = get_view();
502 math::transform mtx_inv_view = math::inverse(mtx_view);
503
504 // Transform pick position from viewport to normalized device coordinates (NDC)
505 float ndc_x = 2.0f * (point.x - viewport_pos_.x) / float(viewport_size_.width) - 1.0f;
506 float ndc_y = 2.0f * (point.y - viewport_pos_.y) / float(viewport_size_.height) - 1.0f;
507
508 // Ensure projection matrix values are valid
509 if (math::abs(mtx_proj[0][0]) < math::epsilon<float>() || math::abs(mtx_proj[1][1]) < math::epsilon<float>())
510 {
511 return false;
512 }
513
514 math::vec3 cursor(ndc_x / mtx_proj[0][0], -ndc_y / mtx_proj[1][1], 1.0f);
515
516 if (get_projection_mode() == projection_mode::orthographic)
517 {
518 vec_ray_start = mtx_inv_view.transform_coord(cursor);
519 vec_ray_dir = math::normalize(mtx_inv_view[2]); // Z-axis direction
520 }
521 else
522 {
523 vec_ray_start = mtx_inv_view.get_position();
524 vec_ray_dir = math::normalize(mtx_inv_view.transform_normal(cursor));
525 }
526
527 return true;
528}
529
530auto camera::viewport_to_world(const math::vec2& point, const math::plane& pl, math::vec3& world_pos, bool clip) const
531 -> bool
532{
533 if(clip && ((point.x < viewport_pos_.x) || (point.x > (viewport_pos_.x + viewport_size_.width)) ||
534 (point.y < viewport_pos_.y) || (point.y > (viewport_pos_.y + viewport_size_.height))))
535 {
536 return false;
537 }
538
539 math::vec3 pick_ray_dir;
540 math::vec3 pick_ray_origin;
541 // Convert the screen coordinates to a ray.
542 if(!viewport_to_ray(point, pick_ray_origin, pick_ray_dir))
543 {
544 return false;
545 }
546
547 // Get the length of the 'adjacent' side of the virtual triangle formed
548 // by the direction and normal.
549 float proj_ray_length = math::plane::dot_normal(pl, pick_ray_dir);
550 if(math::abs<float>(proj_ray_length) < math::epsilon<float>())
551 {
552 return false;
553 }
554
555 // Calculate distance to plane along its normal
556 float distance = math::plane::dot_normal(pl, pick_ray_origin) + pl.data.w;
557
558 // If both the "direction" and origin are on the same side of the plane
559 // then we can't possibly intersect (perspective rule only)
560 if(get_projection_mode() == projection_mode::perspective)
561 {
562 int nSign1 = (distance > 0) ? 1 : (distance < 0) ? -1 : 0;
563 int nSign2 = (proj_ray_length > 0) ? 1 : (proj_ray_length < 0) ? -1 : 0;
564 if(nSign1 == nSign2)
565 {
566 return false;
567 }
568
569 } // End if perspective
570
571 // Calculate the actual interval (Distance along the adjacent side / length of
572 // adjacent side).
573 distance /= -proj_ray_length;
574
575 // Store the results
576 world_pos = pick_ray_origin + (pick_ray_dir * distance);
577
578 // Success!
579 return true;
580}
581
582auto camera::project_to_quad(const math::vec2& viewport_point,
583 const math::transform& quad_transform,
584 uint32_t quad_width,
585 uint32_t quad_height,
586 math::vec2& pixel_out) const -> bool
587{
588 const math::vec3 quad_center = quad_transform.get_position();
589 const math::vec3 quad_normal = quad_transform.z_unit_axis();
590 const auto plane = math::plane::from_point_normal(quad_center, quad_normal);
591
592 math::vec3 world_pos;
593 if(!viewport_to_world(viewport_point, plane, world_pos, false))
594 {
595 pixel_out = math::vec2(-1.0f, -1.0f);
596 return false;
597 }
598
599 const math::vec3 local = quad_transform.inverse_transform_coord(world_pos);
600 if(local.x < -0.5f || local.x > 0.5f || local.y < -0.5f || local.y > 0.5f)
601 {
602 pixel_out = math::vec2(-1.0f, -1.0f);
603 return false;
604 }
605 pixel_out.x = (local.x + 0.5f) * static_cast<float>(quad_width);
606 pixel_out.y = (0.5f - local.y) * static_cast<float>(quad_height);
607 return true;
608}
609
611 const math::vec3& Origin,
612 math::vec3& world_pos,
613 math::vec3& major_axis) const -> bool
614{
615 return viewport_to_major_axis(point, Origin, z_unit_axis(), world_pos, major_axis);
616}
617
619 const math::vec3& Origin,
620 const math::vec3& Normal,
621 math::vec3& world_pos,
622 math::vec3& major_axis) const -> bool
623{
624 // First select the major axis plane based on the specified normal
625 major_axis = math::vec3(1, 0, 0); // YZ
626
627 // Get absolute normal vector
628 float x = math::abs<float>(Normal.x);
629 float y = math::abs<float>(Normal.y);
630 float z = math::abs<float>(Normal.z);
631
632 // If all the components are effectively equal, select one plane
633 if(math::abs<float>(x - y) < math::epsilon<float>() && math::abs<float>(x - z) < math::epsilon<float>())
634 {
635 major_axis = math::vec3(0, 0, 1); // XY
636
637 } // End if components equal
638 else
639 {
640 // Calculate which component of the normal is the major axis
641 float norm = x;
642 if(norm < y)
643 {
644 norm = y;
645 major_axis = math::vec3(0, 1, 0);
646 } // XZ
647 if(norm < z)
648 {
649 norm = z;
650 major_axis = math::vec3(0, 0, 1);
651 } // XY
652
653 } // End if perform compare
654
655 // Generate the intersection plane based on this information
656 // and pass through to the standard viewportToWorld method
657 math::plane p = math::plane::from_point_normal(Origin, major_axis);
658 return viewport_to_world(point, p, world_pos, false);
659}
660
661auto camera::viewport_to_camera(const math::vec3& point, math::vec3& camera_pos) const -> bool
662{
663 // Ensure that we have an up-to-date projection and view matrix
664 auto& mtx_proj = get_projection();
665
666 // Transform the pick position from screen space into camera space
667 camera_pos.x = (((2.0f * (point.x - viewport_pos_.x)) / float(viewport_size_.width)) - 1) / mtx_proj[0][0];
668 camera_pos.y = -(((2.0f * (point.y - viewport_pos_.y)) / float(viewport_size_.height)) - 1) / mtx_proj[1][1];
669 camera_pos.z = get_near_clip();
670
671 // Success!
672 return true;
673}
674
675auto camera::estimate_zoom_factor(const math::plane& pl) const -> float
676{
677 // Just return the actual zoom factor if this is orthographic
678 if(get_projection_mode() == projection_mode::orthographic)
679 {
680 return get_zoom_factor();
681 }
682
683 math::vec3 world;
684 // Otherwise, estimate is based on the distance from the grid plane.
685 viewport_to_world(math::vec2(float(viewport_size_.width) / 2.0f, float(viewport_size_.height) / 2.0f),
686 pl,
687 world,
688 false);
689
690 // Perform full position based estimation
691 return estimate_zoom_factor(world);
692}
693
694//-----------------------------------------------------------------------------
695// Name : estimateZoomFactor ()
702//-----------------------------------------------------------------------------
703auto camera::estimate_zoom_factor(const math::vec3& world_pos) const -> float
704{
705 return estimate_zoom_factor(world_pos, std::numeric_limits<float>::max());
706}
707
708auto camera::estimate_zoom_factor(const math::plane& pl, float max_val) const -> float
709{
710 // Just return the actual zoom factor if this is orthographic
711 if(get_projection_mode() == projection_mode::orthographic)
712 {
713 float factor = get_zoom_factor();
714 return math::min(max_val, factor);
715
716 } // End if orthographic
717 // Otherwise, estimate is based on the distance from the grid plane.
718 math::vec3 world;
719 viewport_to_world(math::vec2(float(viewport_size_.width) / 2.0f, float(viewport_size_.height) / 2.0f),
720 pl,
721 world,
722 false);
723
724 // Perform full position based estimation
725 return estimate_zoom_factor(world, max_val);
726}
727
728auto camera::estimate_zoom_factor(const math::vec3& world_pos, float max_val) const -> float
729{
730 // Just return the actual zoom factor if this is orthographic
731 if(get_projection_mode() == projection_mode::orthographic)
732 {
733 float factor = get_zoom_factor();
734 return math::min(max_val, factor);
735
736 } // End if orthographic
737
738 // New Zoom factor is based on the distance to this position
739 // along the camera's look vector.
740 math::vec3 view_pos = get_view().transform_coord(world_pos);
741 float distance = view_pos.z / (float(viewport_size_.height) * (45.0f / get_fov()));
742 return std::min<float>(max_val, distance);
743}
744
745auto camera::estimate_pick_tolerance(float wire_tolerance,
746 const math::vec3& pos,
747 const math::transform& object_transform) const -> math::vec3
748{
749 // Scale tolerance based on estimated world space zoom factor.
750 math::vec3 v = object_transform.transform_coord(pos);
751 wire_tolerance *= estimate_zoom_factor(v);
752
753 // Convert into object space tolerance.
754 math::vec3 object_wire_tolerance;
755 const math::vec3& vAxisScale = object_transform.get_scale();
756 return object_wire_tolerance / vAxisScale;
757}
758
766
767void camera::set_aa_data(const usize32_t& viewport_size,
768 std::uint32_t temporal_frame_index,
769 std::uint32_t temporal_aa_samples,
770 taa_jitter_mode jitter_mode,
771 float jitter_amplitude,
772 float jitter_temporal_phase_scale)
773{
776
777 if(temporal_aa_samples > 1)
778 {
779 float SampleX = 0.0f;
780 float SampleY = 0.0f;
781 switch(jitter_mode)
782 {
784 math::taa_subpixel_offset_halton(temporal_frame_index,
785 SampleX,
786 SampleY,
787 jitter_temporal_phase_scale);
788 break;
790 math::taa_subpixel_offset_r2(temporal_frame_index,
791 SampleX,
792 SampleY,
793 jitter_temporal_phase_scale);
794 break;
796 {
797 const float SamplesX[] = {-4.0f / 16.0f, 4.0f / 16.0f};
798 const float SamplesY[] = {4.0f / 16.0f, -4.0f / 16.0f};
799 const std::uint32_t idx = temporal_frame_index % 2u;
800 SampleX = SamplesX[idx];
801 SampleY = SamplesY[idx];
802 break;
803 }
805 {
806 // Equilateral triangle inscribed in a circle of radius 0.4 px,
807 // centered at the pixel center (vertices at 90°/210°/330°). Keeps
808 // all offsets inside the standard [-0.5, +0.5] px convention used
809 // by the progressive / Halton / R2 / msaa_4 modes; side length
810 // r·√3 ≈ 0.69 px gives a per-frame step comparable to msaa_2.
811 const float SamplesX[] = {0.0f, -0.34641016f, 0.34641016f};
812 const float SamplesY[] = {0.4f, -0.2f, -0.2f};
813 const std::uint32_t idx = temporal_frame_index % 3u;
814 SampleX = SamplesX[idx];
815 SampleY = SamplesY[idx];
816 break;
817 }
819 {
820 const float SamplesX[] = {-2.0f / 16.0f, 6.0f / 16.0f, 2.0f / 16.0f, -6.0f / 16.0f};
821 const float SamplesY[] = {-6.0f / 16.0f, -2.0f / 16.0f, 6.0f / 16.0f, 2.0f / 16.0f};
822 const std::uint32_t idx = temporal_frame_index % 4u;
823 SampleX = SamplesX[idx];
824 SampleY = SamplesY[idx];
825 break;
826 }
828 default:
829 math::taa_subpixel_offset_progressive(temporal_frame_index,
830 SampleX,
831 SampleY,
832 jitter_temporal_phase_scale);
833 break;
834 }
835
836 const float amp = std::clamp(jitter_amplitude, 0.0f, 1.5f);
837 SampleX *= amp;
838 SampleY *= amp;
839
840 aa_data_ = math::vec4(float(temporal_frame_index & 0xFFFFu),
841 float(temporal_aa_samples),
842 SampleX,
843 SampleY);
844
845 float width = static_cast<float>(viewport_size.width);
846 float height = static_cast<float>(viewport_size.height);
847 aa_data_.z *= (2.0f / width);
848 aa_data_.w *= (2.0f / height);
849 }
850 else
851 {
852 aa_data_ = math::vec4(0.0f, 0.0f, 0.0f, 0.0f);
853 }
854
855 projection_dirty_ = true;
856}
857
858auto camera::get_aa_data() const -> const math::vec4&
859{
860 return aa_data_;
861}
862
864{
865 // All modifications require projection matrix and
866 // frustum to be updated.
867 view_dirty_ = true;
868 projection_dirty_ = true;
869 frustum_dirty_ = true;
870}
871
872auto camera::get_face_camera(uint32_t face, const math::transform& transform) -> camera
873{
874 camera cam;
875 cam.set_fov(90.0f);
876 cam.set_aspect_ratio(1.0f, true);
877 cam.set_near_clip(0.01f);
878 cam.set_far_clip(256.0f);
879
880 // Configurable axis vectors used to construct view matrices. In the
881 // case of the omni light, we align all frustums to the world axes.
882 math::vec3 X(1, 0, 0);
883 math::vec3 Y(0, 1, 0);
884 math::vec3 Z(0, 0, 1);
885 math::vec3 Zero(0, 0, 0);
887 // Generate the correct view matrix for the frustum
888
889 switch(face)
890 {
891 case 0: // right
892 t.set_rotation(-Z, +Y, +X);
893 break;
894 case 1: // left
895 t.set_rotation(+Z, +Y, -X);
896 break;
897 case 2: // up
899 {
900 t.set_rotation(+X, -Z, +Y);
901 }
902 else
903 {
904 t.set_rotation(+X, +Z, -Y);
905 }
906 break;
907 case 3: // down
909 {
910 t.set_rotation(+X, +Z, -Y);
911 }
912 else
913 {
914 t.set_rotation(+X, -Z, +Y);
915 }
916 break;
917 case 4: // front
918 t.set_rotation(+X, +Y, +Z);
919 break;
920 case 5: // back
921 t.set_rotation(-X, +Y, -Z);
922 break;
923 }
924
925 t = transform * t;
926
927 // Set new transform
928 cam.look_at(t.get_position(), t.get_position() + t.z_unit_axis(), t.y_unit_axis());
930 return cam;
931}
932} // namespace unravel
uint32_t width
uint32_t height
Provides storage for common representation of spherical bounding volume, and wraps up common function...
Definition bsphere.h:18
Storage for frustum planes / values and wraps up common functionality.
Definition frustum.h:18
vec3 position
Definition frustum.h:242
void update(const transform &view, const transform &proj, bool _oglNDC)
Updates the frustum based on the specified view and projection matrices.
Definition frustum.cpp:66
std::array< plane, 6 > planes
< The 6 planes of the frustum.
Definition frustum.h:238
std::array< vec3, 8 > points
The originating position of the frustum.
Definition frustum.h:240
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
auto get_position() const noexcept -> const vec3_t &
Get the position component.
auto transform_normal(const vec2_t &v) const noexcept -> vec2_t
Transform a 2D normal.
auto x_unit_axis() const noexcept -> vec3_t
Get the unit X axis of the transform.
auto z_unit_axis() const noexcept -> vec3_t
Get the unit Z axis of the transform.
auto y_unit_axis() const noexcept -> vec3_t
Get the unit Y axis of the transform.
auto transform_coord(const vec2_t &v) const noexcept -> vec2_t
Transform a 2D coordinate.
Class representing a camera. Contains functionality for manipulating and updating a camera....
Definition camera.h:62
auto get_view_projection_relative() const -> math::transform
Definition camera.cpp:323
auto get_far_clip() const -> float
Retrieves the distance from the camera to the far clip plane.
Definition camera.cpp:69
float far_clip_
Far clip plane Distance.
Definition camera.h:572
auto get_fov() const -> float
Retrieves the current field of view angle in degrees.
Definition camera.cpp:59
auto classify_obb(const math::bbox &bounds, const math::transform &t) const -> math::volume_query
Determines if the specified OBB is within the frustum.
Definition camera.cpp:442
math::transform taa_prev_view_
Snapshot for temporal reprojection: view/projection before advancing jitter (see set_aa_data).
Definition camera.h:559
auto viewport_to_major_axis(const math::vec2 &point, const math::vec3 &axis_origin, math::vec3 &position_out, math::vec3 &major_axis_out) const -> bool
Converts a screen position into a world space intersection point on a major axis plane.
Definition camera.cpp:610
auto get_taa_prev_view_projection() const -> math::transform
View-projection used for the previous rendered frame (before the latest jitter sample).
Definition camera.cpp:318
auto viewport_to_world(const math::vec2 &point, const math::plane &plane, math::vec3 &position_out, bool clip) const -> bool
Converts a screen position into a world space position on the specified plane.
Definition camera.cpp:530
auto viewport_to_ray(const math::vec2 &point, math::vec3 &vec_ray_start, math::vec3 &vec_ray_dir) const -> bool
Converts the specified screen position into a ray origin and direction vector.
Definition camera.cpp:497
auto get_prev_view_projection() const -> math::transform
Retrieves the previous view matrix.
Definition camera.cpp:313
auto get_viewport_pos() const -> const ipoint32_t &
Retrieves the position of the viewport.
Definition camera.cpp:42
auto test_obb(const math::bbox &bounds, const math::transform &t) const -> bool
Tests if the specified OBB is within the frustum.
Definition camera.cpp:451
auto get_prev_view_relative() const -> const math::transform &
Definition camera.cpp:293
ipoint32_t viewport_pos_
Viewport position.
Definition camera.h:578
void set_fov(float degrees)
Sets the field of view angle of this camera (perspective only).
Definition camera.cpp:79
auto get_projection_mode() const -> projection_mode
Retrieves the current projection mode for this camera.
Definition camera.cpp:54
void look_at(const math::vec3 &eye, const math::vec3 &at)
Sets the camera to look at a specified target.
Definition camera.cpp:333
void set_orthographic_size(float size)
Sets the half of the vertical size of the viewing volume in world units.
Definition camera.cpp:47
bool aspect_locked_
Should the aspect ratio be automatically updated by the render driver?
Definition camera.h:590
math::transform view_relative_
Definition camera.h:546
math::frustum clipping_volume_
The near clipping volume (area of space between the camera position and the near plane).
Definition camera.h:564
auto get_ppu() const -> float
Retrieves the pixels per unit (PPU).
Definition camera.cpp:21
auto get_viewport_size() const -> const usize32_t &
Retrieves the size of the viewport.
Definition camera.cpp:37
auto x_unit_axis() const -> math::vec3
Retrieves the x-axis unit vector of the camera's local coordinate system.
Definition camera.cpp:358
projection_mode projection_mode_
The type of projection currently selected for this camera.
Definition camera.h:566
bool view_dirty_
View matrix dirty ?
Definition camera.h:582
auto get_projection() const -> const math::transform &
Retrieves the current projection matrix.
Definition camera.cpp:205
auto get_clipping_volume() const -> const math::frustum &
Retrieves the frustum representing the space between the camera position and its near plane.
Definition camera.cpp:412
auto get_zoom_factor() const -> float
Retrieves the zoom factor.
Definition camera.cpp:11
math::frustum frustum_
Details regarding the camera frustum.
Definition camera.h:562
float aspect_ratio_
The aspect ratio used to generate the correct horizontal degrees (perspective only)
Definition camera.h:576
auto get_local_bounding_box() -> math::bbox
Retrieves the bounding box of this object.
Definition camera.cpp:147
static auto get_face_camera(std::uint32_t face, const math::transform &transform) -> camera
Retrieves a camera for one of six cube faces.
Definition camera.cpp:872
void touch()
Marks the camera as modified.
Definition camera.cpp:863
float near_clip_
Near clip plane Distance.
Definition camera.h:570
bool projection_dirty_
Projection matrix dirty ?
Definition camera.h:584
auto get_view() const -> const math::transform &
Retrieves the current view matrix.
Definition camera.cpp:278
math::transform view_inverse_relative_
Definition camera.h:547
math::transform projection_
Cached projection matrix.
Definition camera.h:550
float ortho_size_
camera's half-size when in orthographic mode.
Definition camera.h:574
math::transform last_view_
Cached "previous" view matrix.
Definition camera.h:552
auto test_aabb(const math::bbox &bounds) const -> bool
Tests if the specified AABB is within the frustum.
Definition camera.cpp:433
auto test_billboard(float size, const math::transform &t) const -> bool
Definition camera.cpp:460
math::transform view_
Cached view matrix.
Definition camera.h:543
bool frustum_dirty_
Are the frustum planes dirty ?
Definition camera.h:588
void set_projection_mode(projection_mode mode)
Sets the current projection mode for this camera (i.e. orthographic or perspective).
Definition camera.cpp:93
auto estimate_zoom_factor(const math::plane &plane) const -> float
Estimates the zoom factor based on the specified plane.
Definition camera.cpp:675
math::vec4 aa_data_
Anti-aliasing data.
Definition camera.h:541
auto get_prev_view_projection_relative() const -> math::transform
Definition camera.cpp:328
auto is_aspect_locked() const -> bool
Determines if the aspect ratio is currently being updated by the render driver.
Definition camera.cpp:190
void set_far_clip(float distance)
Sets the far plane distance.
Definition camera.cpp:127
void set_aa_data(const usize32_t &viewport_size, std::uint32_t temporal_frame_index, std::uint32_t temporal_aa_samples, taa_jitter_mode jitter_mode=taa_jitter_mode::progressive_golden, float jitter_amplitude=1.0f, float jitter_temporal_phase_scale=1.0f)
Sets the current jitter value for temporal anti-aliasing.
Definition camera.cpp:767
auto estimate_pick_tolerance(float pixel_tolerance, const math::vec3 &reference_position, const math::transform &object_transform) const -> math::vec3
Estimates the pick tolerance based on the pixel tolerance and reference position.
Definition camera.cpp:745
bool frustum_locked_
Is the frustum locked?
Definition camera.h:592
auto y_unit_axis() const -> math::vec3
Retrieves the y-axis unit vector of the camera's local coordinate system.
Definition camera.cpp:362
auto get_view_relative() const -> const math::transform &
Definition camera.cpp:288
void set_viewport_size(const usize32_t &viewport_size)
Sets the size of the viewport.
Definition camera.cpp:26
auto is_frustum_locked() const -> bool
Checks if the frustum is currently locked.
Definition camera.cpp:195
auto z_unit_axis() const -> math::vec3
Retrieves the z-axis unit vector of the camera's local coordinate system.
Definition camera.cpp:367
math::transform last_view_relative_
Definition camera.h:553
auto viewport_to_camera(const math::vec3 &point, math::vec3 &position_out) const -> bool
Converts a screen position into a camera space position at the near plane.
Definition camera.cpp:661
void set_aspect_ratio(float aspect, bool locked=false)
Sets the aspect ratio to be used for generating the horizontal FOV angle (perspective only).
Definition camera.cpp:167
auto get_prev_view() const -> const math::transform &
Definition camera.cpp:283
void lock_frustum(bool locked)
Locks or unlocks the frustum.
Definition camera.cpp:200
float fov_
Vertical degrees angle (perspective only).
Definition camera.h:568
auto get_view_inverse() const -> const math::transform &
Definition camera.cpp:298
auto get_position() const -> const math::vec3 &
Retrieves the current position of the camera.
Definition camera.cpp:353
void set_viewport_pos(const ipoint32_t &viewport_pos)
Sets the position of the viewport.
Definition camera.cpp:32
auto world_to_viewport(const math::vec3 &pos) const -> math::vec3
Transforms a point from world space into screen space.
Definition camera.cpp:473
auto classify_aabb(const math::bbox &bounds) const -> math::volume_query
Determines if the specified AABB falls within the frustum.
Definition camera.cpp:424
auto get_aspect_ratio() const -> float
Retrieves the aspect ratio used to generate the horizontal FOV angle.
Definition camera.cpp:185
auto project_to_quad(const math::vec2 &viewport_point, const math::transform &quad_transform, uint32_t quad_width, uint32_t quad_height, math::vec2 &pixel_out) const -> bool
Raycasts from viewport point onto a quad plane and returns pixel coordinates.
Definition camera.cpp:582
auto get_ortho_size() const -> float
Retrieves the orthographic size.
Definition camera.cpp:74
bool aspect_dirty_
Has the aspect ratio changed?
Definition camera.h:586
usize32_t viewport_size_
Viewport size.
Definition camera.h:580
auto get_view_projection() const -> math::transform
Retrieves the current view-projection matrix.
Definition camera.cpp:308
auto get_prev_projection() const -> const math::transform &
Definition camera.cpp:273
void record_current_matrices()
Makes a copy of the current view and projection matrices before they are changed.
Definition camera.cpp:759
math::transform taa_prev_projection_
Definition camera.h:560
math::transform last_projection_
Cached "previous" projection matrix.
Definition camera.h:556
void set_near_clip(float distance)
Sets the near plane distance.
Definition camera.cpp:107
math::transform view_inverse_
Definition camera.h:544
auto get_view_inverse_relative() const -> const math::transform &
Definition camera.cpp:303
auto get_frustum() const -> const math::frustum &
Retrieves the current camera object frustum.
Definition camera.cpp:372
auto get_aa_data() const -> const math::vec4 &
Retrieves the anti-aliasing data.
Definition camera.cpp:858
auto get_near_clip() const -> float
Retrieves the distance from the camera to the near clip plane.
Definition camera.cpp:64
float y
float x
float z
auto is_homogeneous_depth() -> bool
auto is_origin_bottom_left() -> bool
Definition bbox.cpp:5
void taa_subpixel_offset_progressive(std::uint32_t frame, float &offset_x, float &offset_y, float temporal_phase_scale=1.0f)
2D subpixel jitter in [-0.5, 0.5] for temporal AA (Kronecker / golden-ratio sequence).
Definition math.h:285
auto inverse(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
void taa_subpixel_offset_halton(std::uint32_t frame, float &offset_x, float &offset_y, float temporal_phase_scale=1.0f)
Definition math.h:309
void taa_subpixel_offset_r2(std::uint32_t frame, float &offset_x, float &offset_y, float temporal_phase_scale=1.0f)
Definition math.h:324
volume_query
Definition math_types.h:13
projection_mode
Enum representing the projection mode of a camera.
Definition camera.h:16
taa_jitter_mode
Subpixel jitter sequence for temporal AA (see camera::set_aa_data).
Definition camera.h:25
@ r2_low_discrepancy
R2 / recurrence lattice pair; alternative progressive 2D coverage.
@ progressive_golden
Kronecker / golden-ratio; smooth incommensurable steps (default).
@ halton_2_3
Halton(base 2,3) in [-0.5,0.5]; strong low-discrepancy, larger frame-to-frame steps.
@ sphere
Sphere type reflection probe.
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
Storage for infinite plane.
Definition plane.h:21
static auto from_point_normal(const vec3 &point, const vec3 &normal) -> plane
Creates a plane from a point and a normal.
Definition plane.cpp:20
static auto dot_normal(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane normal and a vec3.
Definition plane.cpp:15
static auto dot_coord(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane and a vec3 (considering the plane's distance).
Definition plane.cpp:10
T width
Definition basetypes.hpp:55
T height
Definition basetypes.hpp:56
float size