Visual Computing Library  devel
Loading...
Searching...
No Matches
matrix.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2026 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_SPACE_CORE_CAMERA_MATRIX_H
24#define VCL_SPACE_CORE_CAMERA_MATRIX_H
25
26#include "../matrix.h"
27#include "../point.h"
28
29namespace vcl {
30
31enum Handedness { LEFT_HAND, RIGHT_HAND };
32
33namespace detail {
34
35// creates a look at matrix and stores it in the given array, that represents a
36// 4x4 column major matrix.
37template<Point3Concept PointType>
38void lookAtMatrix(
39 auto* res,
40 const PointType& eye,
41 const PointType& center,
42 const PointType& up,
43 Handedness handedness = RIGHT_HAND)
44{
45 if (center != eye) {
46 PointType zaxis = handedness == RIGHT_HAND ?
47 (eye - center).normalized() :
48 (center - eye).normalized();
49
50 PointType xaxis = up.cross(zaxis);
51
52 if (xaxis.dot(xaxis) == 0) {
53 xaxis = handedness == RIGHT_HAND ? PointType(1, 0, 0) :
54 PointType(-1, 0, 0);
55 }
56 else {
57 xaxis = xaxis.normalized();
58 }
59
60 PointType yaxis = zaxis.cross(xaxis);
61
62 res[0] = xaxis.x();
63 res[1] = yaxis.x();
64 res[2] = zaxis.x();
65 res[3] = 0.0f;
66
67 res[4] = xaxis.y();
68 res[5] = yaxis.y();
69 res[6] = zaxis.y();
70 res[7] = 0.0f;
71
72 res[8] = xaxis.z();
73 res[9] = yaxis.z();
74 res[10] = zaxis.z();
75 res[11] = 0.0f;
76
77 res[12] = -xaxis.dot(eye);
78 res[13] = -yaxis.dot(eye);
79 res[14] = -zaxis.dot(eye);
80 res[15] = 1.0f;
81 }
82}
83
84template<typename Scalar>
85void projectionMatrixXYWH(
86 auto* res,
87 Scalar x,
88 Scalar y,
89 Scalar width,
90 Scalar height,
91 Scalar nearPlane,
92 Scalar farPlane,
93 bool homogeneousNDC,
94 Handedness handedness = RIGHT_HAND)
95{
96 // note: don't use 'near' and 'far' variable names, as they are already
97 // defined in windows.h headers
98 Scalar diff = farPlane - nearPlane;
99 Scalar a = homogeneousNDC ? (farPlane + nearPlane) / diff : farPlane / diff;
100 Scalar b =
101 homogeneousNDC ? (2.0 * farPlane * nearPlane) / diff : nearPlane * a;
102
103 std::fill(res, res + 16, 0);
104
105 res[0] = width;
106 res[5] = height;
107 res[8] = handedness == RIGHT_HAND ? x : -x;
108 res[9] = handedness == RIGHT_HAND ? y : -y;
109 res[10] = handedness == RIGHT_HAND ? -a : a;
110 res[11] = handedness == RIGHT_HAND ? -1.0 : 1.0;
111 res[14] = -b;
112}
113
114template<typename Scalar>
115void projectionMatrix(
116 auto* res,
117 Scalar fov,
118 Scalar aspect,
119 Scalar nearPlane,
120 Scalar farPlane,
121 bool homogeneousNDC,
122 Handedness handedness = RIGHT_HAND)
123{
124 Scalar h = 1.0 / std::tan(vcl::toRad(fov) * 0.5);
125 Scalar w = h * 1.0 / aspect;
126 detail::projectionMatrixXYWH(
127 res,
128 (Scalar) 0,
129 (Scalar) 0,
130 w,
131 h,
132 nearPlane,
133 farPlane,
134 homogeneousNDC,
135 handedness);
136}
137
138template<typename Scalar>
139void orthoProjectionMatrix(
140 auto* res,
141 Scalar left,
142 Scalar right,
143 Scalar top,
144 Scalar bottom,
145 Scalar nearPlane,
146 Scalar farPlane,
147 bool homogeneousNDC,
148 Handedness handedness = RIGHT_HAND)
149{
150 // note: don't use 'near' and 'far' variable names, as they are already
151 // defined in windows.h headers
152 Scalar c = homogeneousNDC ? 2.0 / (farPlane - nearPlane) :
153 1.0 / (farPlane - nearPlane);
154 Scalar f = homogeneousNDC ?
155 (farPlane + nearPlane) / (nearPlane - farPlane) :
156 nearPlane / (nearPlane - farPlane);
157
158 std::fill(res, res + 16, 0);
159 res[0] = 2.0 / (right - left);
160 res[5] = 2.0 / (top - bottom);
161 res[10] = RIGHT_HAND ? -c : c;
162 res[12] = (right + left) / (left - right);
163 res[13] = (bottom + top) / (bottom - top);
164 res[14] = f;
165 res[15] = 1.0;
166}
167
168} // namespace detail
169
170} // namespace vcl
171
172#endif // VCL_SPACE_CORE_CAMERA_MATRIX_H
void lookAtMatrix(auto *res, const PointType &eye, const PointType &center, const PointType &up, Handedness handedness=RIGHT_HAND)
Creates a look at matrix.
Definition matrix_camera.h:47
Scalar toRad(const Scalar &deg)
Converts an angle in degrees to radians.
Definition math.h:81