Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common/gsvector.cpp
4214 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "gsvector.h"
5
6
#include <cmath>
7
8
GSVector4i GSVector4i::rfit(const GSVector4i& fit_rect, const GSVector2i& image_size)
9
{
10
const GSVector2 ffit_size = GSVector2(fit_rect.rsize());
11
const GSVector2 fimage_size = GSVector2(image_size);
12
const float fit_ar = ffit_size.x / ffit_size.y;
13
const float image_ar = fimage_size.x / fimage_size.y;
14
15
GSVector4i ret;
16
if (fit_ar > image_ar)
17
{
18
// center horizontally
19
const float width = ffit_size.y * image_ar;
20
const float offset = (ffit_size.x - width) / 2.0f;
21
const float height = ffit_size.y;
22
ret = GSVector4i(GSVector4(offset, 0.0f, offset + width, height));
23
}
24
else
25
{
26
// center vertically
27
const float height = ffit_size.x / image_ar;
28
const float offset = (ffit_size.y - height) / 2.0f;
29
const float width = ffit_size.x;
30
ret = GSVector4i(GSVector4(0.0f, offset, width, offset + height));
31
}
32
33
return ret;
34
}
35
36
GSMatrix2x2::GSMatrix2x2(float e00, float e01, float e10, float e11)
37
{
38
E[0][0] = e00;
39
E[0][1] = e01;
40
E[1][0] = e10;
41
E[1][1] = e11;
42
}
43
44
GSMatrix2x2 GSMatrix2x2::operator*(const GSMatrix2x2& m) const
45
{
46
GSMatrix2x2 ret;
47
ret.E[0][0] = E[0][0] * m.E[0][0] + E[0][1] * m.E[1][0];
48
ret.E[0][1] = E[0][0] * m.E[0][1] + E[0][1] * m.E[1][1];
49
ret.E[1][0] = E[1][0] * m.E[0][0] + E[1][1] * m.E[1][0];
50
ret.E[1][1] = E[1][0] * m.E[0][1] + E[1][1] * m.E[1][1];
51
return ret;
52
}
53
54
GSVector2 GSMatrix2x2::operator*(const GSVector2& v) const
55
{
56
return GSVector2(row(0).dot(v), row(1).dot(v));
57
}
58
59
GSMatrix2x2 GSMatrix2x2::Identity()
60
{
61
GSMatrix2x2 ret;
62
ret.E[0][0] = 1.0f;
63
ret.E[0][1] = 0.0f;
64
ret.E[1][0] = 0.0f;
65
ret.E[1][1] = 1.0f;
66
return ret;
67
}
68
69
GSMatrix2x2 GSMatrix2x2::Rotation(float angle_in_radians)
70
{
71
const float sin_angle = std::sin(angle_in_radians);
72
const float cos_angle = std::cos(angle_in_radians);
73
74
GSMatrix2x2 ret;
75
ret.E[0][0] = cos_angle;
76
ret.E[0][1] = -sin_angle;
77
ret.E[1][0] = sin_angle;
78
ret.E[1][1] = cos_angle;
79
return ret;
80
}
81
82
GSVector2 GSMatrix2x2::row(size_t i) const
83
{
84
return GSVector2::load<true>(&E[i][0]);
85
}
86
87
GSVector2 GSMatrix2x2::col(size_t i) const
88
{
89
return GSVector2(E[0][i], E[1][i]);
90
}
91
92
void GSMatrix2x2::store(void* m)
93
{
94
std::memcpy(m, E, sizeof(E));
95
}
96
97
ALWAYS_INLINE static void MatrixMult4x4(GSMatrix4x4& res, const GSMatrix4x4& lhs, const GSMatrix4x4& rhs)
98
{
99
// This isn't speedy by any means, but it's not hot code either.
100
#define MultRC(rw, cl) \
101
lhs.E[rw][0] * rhs.E[0][cl] + lhs.E[rw][1] * rhs.E[1][cl] + lhs.E[rw][2] * rhs.E[2][cl] + lhs.E[rw][3] * rhs.E[3][cl]
102
103
res.E[0][0] = MultRC(0, 0);
104
res.E[0][1] = MultRC(0, 1);
105
res.E[0][2] = MultRC(0, 2);
106
res.E[0][3] = MultRC(0, 3);
107
res.E[1][0] = MultRC(1, 0);
108
res.E[1][1] = MultRC(1, 1);
109
res.E[1][2] = MultRC(1, 2);
110
res.E[1][3] = MultRC(1, 3);
111
res.E[2][0] = MultRC(2, 0);
112
res.E[2][1] = MultRC(2, 1);
113
res.E[2][2] = MultRC(2, 2);
114
res.E[2][3] = MultRC(2, 3);
115
res.E[3][0] = MultRC(3, 0);
116
res.E[3][1] = MultRC(3, 1);
117
res.E[3][2] = MultRC(3, 2);
118
res.E[3][3] = MultRC(3, 3);
119
120
#undef MultRC
121
}
122
123
GSMatrix4x4 GSMatrix4x4::operator*(const GSMatrix4x4& m) const
124
{
125
GSMatrix4x4 res;
126
MatrixMult4x4(res, *this, m);
127
return res;
128
}
129
130
GSMatrix4x4& GSMatrix4x4::operator*=(const GSMatrix4x4& m)
131
{
132
const GSMatrix4x4 copy(*this);
133
MatrixMult4x4(*this, copy, m);
134
return *this;
135
}
136
137
GSMatrix4x4 GSMatrix4x4::RotationX(float angle_in_radians)
138
{
139
const float sin_angle = std::sin(angle_in_radians);
140
const float cos_angle = std::cos(angle_in_radians);
141
142
return GSMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, cos_angle, -sin_angle, 0.0f, 0.0f, sin_angle, cos_angle, 0.0f, 0.0f,
143
0.0f, 0.0f, 1.0f);
144
}
145
146
GSMatrix4x4 GSMatrix4x4::RotationY(float angle_in_radians)
147
{
148
const float sin_angle = std::sin(angle_in_radians);
149
const float cos_angle = std::cos(angle_in_radians);
150
151
return GSMatrix4x4(cos_angle, 0.0f, sin_angle, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -sin_angle, 0.0f, cos_angle, 0.0f, 0.0f,
152
0.0f, 0.0f, 1.0f);
153
}
154
155
GSMatrix4x4 GSMatrix4x4::RotationZ(float angle_in_radians)
156
{
157
const float sin_angle = std::sin(angle_in_radians);
158
const float cos_angle = std::cos(angle_in_radians);
159
160
return GSMatrix4x4(cos_angle, -sin_angle, 0.0f, 0.0f, sin_angle, cos_angle, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
161
0.0f, 0.0f, 1.0f);
162
}
163
164
GSMatrix4x4 GSMatrix4x4::Translation(float x, float y, float z)
165
{
166
return GSMatrix4x4(1.0f, 0.0f, 0.0f, x, 0.0f, 1.0f, 0.0f, y, 0.0f, 0.0f, 1.0f, z, 0.0f, 0.0f, 0.0f, 1.0f);
167
}
168
169
GSMatrix4x4 GSMatrix4x4::OffCenterOrthographicProjection(float left, float top, float right, float bottom, float zNear,
170
float zFar)
171
{
172
return GSMatrix4x4(2.0f / (right - left), 0.0f, 0.0f, (left + right) / (left - right), 0.0f, 2.0f / (top - bottom),
173
0.0f, (top + bottom) / (bottom - top), 0.0f, 0.0f, 1.0f / (zNear - zFar), zNear / (zNear - zFar),
174
0.0f, 0.0f, 0.0f, 1.0f);
175
}
176
177
GSMatrix4x4 GSMatrix4x4::OffCenterOrthographicProjection(float width, float height, float zNear, float zFar)
178
{
179
return OffCenterOrthographicProjection(0.0f, 0.0f, width, height, zNear, zFar);
180
}
181
182
GSMatrix4x4 GSMatrix4x4::invert() const
183
{
184
GSMatrix4x4 ret;
185
186
float v0 = E[2][0] * E[3][1] - E[2][1] * E[3][0];
187
float v1 = E[2][0] * E[3][2] - E[2][2] * E[3][0];
188
float v2 = E[2][0] * E[3][3] - E[2][3] * E[3][0];
189
float v3 = E[2][1] * E[3][2] - E[2][2] * E[3][1];
190
float v4 = E[2][1] * E[3][3] - E[2][3] * E[3][1];
191
float v5 = E[2][2] * E[3][3] - E[2][3] * E[3][2];
192
193
const float t00 = +(v5 * E[1][1] - v4 * E[1][2] + v3 * E[1][3]);
194
const float t10 = -(v5 * E[1][0] - v2 * E[1][2] + v1 * E[1][3]);
195
const float t20 = +(v4 * E[1][0] - v2 * E[1][1] + v0 * E[1][3]);
196
const float t30 = -(v3 * E[1][0] - v1 * E[1][1] + v0 * E[1][2]);
197
198
const float inv_det = 1.0f / (t00 * E[0][0] + t10 * E[0][1] + t20 * E[0][2] + t30 * E[0][3]);
199
200
ret.E[0][0] = t00 * inv_det;
201
ret.E[1][0] = t10 * inv_det;
202
ret.E[2][0] = t20 * inv_det;
203
ret.E[3][0] = t30 * inv_det;
204
205
ret.E[0][1] = -(v5 * E[0][1] - v4 * E[0][2] + v3 * E[0][3]) * inv_det;
206
ret.E[1][1] = +(v5 * E[0][0] - v2 * E[0][2] + v1 * E[0][3]) * inv_det;
207
ret.E[2][1] = -(v4 * E[0][0] - v2 * E[0][1] + v0 * E[0][3]) * inv_det;
208
ret.E[3][1] = +(v3 * E[0][0] - v1 * E[0][1] + v0 * E[0][2]) * inv_det;
209
210
v0 = E[1][0] * E[3][1] - E[1][1] * E[3][0];
211
v1 = E[1][0] * E[3][2] - E[1][2] * E[3][0];
212
v2 = E[1][0] * E[3][3] - E[1][3] * E[3][0];
213
v3 = E[1][1] * E[3][2] - E[1][2] * E[3][1];
214
v4 = E[1][1] * E[3][3] - E[1][3] * E[3][1];
215
v5 = E[1][2] * E[3][3] - E[1][3] * E[3][2];
216
217
ret.E[0][2] = +(v5 * E[0][1] - v4 * E[0][2] + v3 * E[0][3]) * inv_det;
218
ret.E[1][2] = -(v5 * E[0][0] - v2 * E[0][2] + v1 * E[0][3]) * inv_det;
219
ret.E[2][2] = +(v4 * E[0][0] - v2 * E[0][1] + v0 * E[0][3]) * inv_det;
220
ret.E[3][2] = -(v3 * E[0][0] - v1 * E[0][1] + v0 * E[0][2]) * inv_det;
221
222
v0 = E[2][1] * E[1][0] - E[2][0] * E[1][1];
223
v1 = E[2][2] * E[1][0] - E[2][0] * E[1][2];
224
v2 = E[2][3] * E[1][0] - E[2][0] * E[1][3];
225
v3 = E[2][2] * E[1][1] - E[2][1] * E[1][2];
226
v4 = E[2][3] * E[1][1] - E[2][1] * E[1][3];
227
v5 = E[2][3] * E[1][2] - E[2][2] * E[1][3];
228
229
ret.E[0][3] = -(v5 * E[0][1] - v4 * E[0][2] + v3 * E[0][3]) * inv_det;
230
ret.E[1][3] = +(v5 * E[0][0] - v2 * E[0][2] + v1 * E[0][3]) * inv_det;
231
ret.E[2][3] = -(v4 * E[0][0] - v2 * E[0][1] + v0 * E[0][3]) * inv_det;
232
ret.E[3][3] = +(v3 * E[0][0] - v1 * E[0][1] + v0 * E[0][2]) * inv_det;
233
234
return ret;
235
}
236
237
void GSMatrix4x4::store(void* m)
238
{
239
std::memcpy(m, &E[0][0], sizeof(E));
240
}
241
242