openMSX
gl_transform_Test.cc
Go to the documentation of this file.
1 #include "gl_transform.hh"
2 #include <cassert>
3 #include <iostream>
4 
5 using namespace gl;
6 
7 // Not used in test, but useful to debug.
8 template<int N, typename T> void print(const vecN<N, T>& x)
9 {
10  for (int i = 0; i < N; ++i) {
11  std::cout << x[i] << " ";
12  }
13  std::cout << std::endl;
14 }
15 template<int M, int N, typename T> void print(const matMxN<M, N, T>& A)
16 {
17  for (int j = 0; j < M; ++j) {
18  for (int i = 0; i < N; ++i) {
19  std::cout << A[i][j] << " ";
20  }
21  std::cout << std::endl;
22  }
23  std::cout << std::endl;
24 }
25 
26 // Test approximations.
27 bool approxEq(float x, float y)
28 {
29  return fabsf(x - y) < 1.0e-5f;
30 }
31 bool approxEq(const vec4& x, const vec4&y)
32 {
33  return length2(x - y) < 1.0e-4f;
34 }
35 bool approxEq(const mat4& x, const mat4&y)
36 {
37  return norm2_2(x - y) < 1.0e-3f;
38 }
39 
40 int main()
41 {
42  {
43  // scale
44  mat4 S1 = scale(vec3(1,2,3));
45  mat4 S2 = scale(S1, vec3(2,3,4)); // first this scale, then S1
46  assert(S1 == mat4(vec4(1,0,0,0),vec4(0,2,0,0),vec4(0,0,3,0),vec4(0,0,0,1)));
47  assert(S2 == mat4(vec4(2,0,0,0),vec4(0,6,0,0),vec4(0,0,12,0),vec4(0,0,0,1)));
48 
49  vec4 p(4,5,6,1); // point
50  vec4 d(4,5,6,0); // direction
51  assert(S1 * p == vec4(4,10,18,1));
52  assert(S1 * d == vec4(4,10,18,0));
53  assert(S2 * p == vec4(8,30,72,1));
54  assert(S2 * d == vec4(8,30,72,0));
55 
56  assert(S1 * S2 == S2 * S1); // scaling is commutative
57  assert(approxEq(inverse(S1), scale(vec3(1.0f/1.0f, 1.0f/2.0f, 1.0f/3.0f))));
58  }
59  {
60  // translate
61  mat4 T1 = translate( vec3( 1,2, 3));
62  mat4 T2 = translate(T1, vec3(-2,1,-1)); // first this, then T1
63  mat4 T3 = translate( vec3(-1,3, 2));
64 
65  assert(T1 == mat4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(1,2,3,1)));
66  assert(T2 == mat4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(-1,3,2,1)));
67  assert(T2 == T3);
68 
69  vec4 p(4,5,6,1); // point
70  vec4 d(4,5,6,0); // direction
71  assert((T1 * p) == (p + vec4(1,2,3,0)));
72  assert((T1 * d) == d);
73  assert((T2 * p) == (p + vec4(-1,3,2,0)));
74  assert((T2 * d) == d);
75 
76  assert(T1 * T2 == T2 * T1); // translation is commutative
77  assert(approxEq(inverse(T1), translate(vec3(-1,-2,-3))));
78  }
79  {
80  // scale + translate
81  vec3 s(2,1,1);
82  vec3 t(1,1,0);
83  mat4 S1 = scale(s);
84  mat4 T1 = translate(t);
85  mat4 ST1 = T1 * S1; // first scale, then translate
86  mat4 TS1 = S1 * T1; // first translate, then scale
87  mat4 ST2 = scale(T1, s); // first scale, then translate
88  mat4 TS2 = translate(S1, t); // first translate, then scale
89 
90  assert(ST1 == ST2);
91  assert(TS1 == TS2);
92  assert(ST1 != TS1); // not commutative
93 
94  vec4 p(4,5,6,1); // point
95  vec4 d(4,5,6,0); // direction
96  assert(ST1 * p == vec4( 9,6,6,1));
97  assert(ST1 * d == vec4( 8,5,6,0));
98  assert(TS1 * p == vec4(10,6,6,1));
99  assert(TS1 * d == vec4( 8,5,6,0));
100  }
101  {
102  // rotation
103  float deg0 = 0.0f;
104  float deg90 = M_PI / 2.0f;
105  float deg180 = M_PI;
106  float deg270 = -M_PI / 2.0f;
107 
108  // x
109  mat4 Rx0 = rotateX(deg0);
110  mat4 Rx90 = rotateX(deg90);
111  mat4 Rx180 = rotateX(deg180);
112  mat4 Rx270 = rotateX(deg270);
113  assert(approxEq(Rx0, mat4(vec4(1,0,0,0),vec4(0, 1, 0,0),vec4(0, 0, 1,0),vec4(0,0,0,1))));
114  assert(approxEq(Rx90, mat4(vec4(1,0,0,0),vec4(0, 0, 1,0),vec4(0,-1, 0,0),vec4(0,0,0,1))));
115  assert(approxEq(Rx180, mat4(vec4(1,0,0,0),vec4(0,-1, 0,0),vec4(0, 0,-1,0),vec4(0,0,0,1))));
116  assert(approxEq(Rx270, mat4(vec4(1,0,0,0),vec4(0, 0,-1,0),vec4(0, 1, 0,0),vec4(0,0,0,1))));
117 
118  assert(approxEq(rotateX(Rx90, deg90 ), Rx180));
119  assert(approxEq(rotateX(Rx90, deg180), Rx270));
120  assert(approxEq(rotateX(Rx90, deg270), Rx0 ));
121  assert(approxEq(rotateX(Rx180, deg270), Rx90 ));
122 
123  assert(approxEq(inverse(Rx90 ), Rx270));
124  assert(approxEq(inverse(Rx180), Rx180));
125  assert(approxEq(inverse(Rx90), transpose(Rx90)));
126 
127  // y
128  mat4 Ry0 = rotateY(deg0);
129  mat4 Ry90 = rotateY(deg90);
130  mat4 Ry180 = rotateY(deg180);
131  mat4 Ry270 = rotateY(deg270);
132  assert(approxEq(Ry0, mat4(vec4( 1,0, 0,0),vec4(0,1,0,0),vec4( 0,0, 1,0),vec4(0,0,0,1))));
133  assert(approxEq(Ry90, mat4(vec4( 0,0,-1,0),vec4(0,1,0,0),vec4( 1,0, 0,0),vec4(0,0,0,1))));
134  assert(approxEq(Ry180, mat4(vec4(-1,0, 0,0),vec4(0,1,0,0),vec4( 0,0,-1,0),vec4(0,0,0,1))));
135  assert(approxEq(Ry270, mat4(vec4( 0,0, 1,0),vec4(0,1,0,0),vec4(-1,0, 0,0),vec4(0,0,0,1))));
136 
137  assert(approxEq(rotateY(Ry180, deg90 ), Ry270));
138  assert(approxEq(rotateY(Ry180, deg180), Ry0 ));
139  assert(approxEq(rotateY(Ry180, deg270), Ry90 ));
140  assert(approxEq(rotateY(Ry270, deg270), Ry180));
141 
142  assert(approxEq(inverse(Ry90 ), Ry270));
143  assert(approxEq(inverse(Ry180), Ry180));
144  assert(approxEq(inverse(Ry90), transpose(Ry90)));
145 
146  // z
147  mat4 Rz0 = rotateZ(deg0);
148  mat4 Rz90 = rotateZ(deg90);
149  mat4 Rz180 = rotateZ(deg180);
150  mat4 Rz270 = rotateZ(deg270);
151  assert(approxEq(Rz0, mat4(vec4( 1, 0,0,0),vec4( 0, 1,0,0),vec4(0,0,1,0),vec4(0,0,0,1))));
152  assert(approxEq(Rz90, mat4(vec4( 0, 1,0,0),vec4(-1, 0,0,0),vec4(0,0,1,0),vec4(0,0,0,1))));
153  assert(approxEq(Rz180, mat4(vec4(-1, 0,0,0),vec4( 0,-1,0,0),vec4(0,0,1,0),vec4(0,0,0,1))));
154  assert(approxEq(Rz270, mat4(vec4( 0,-1,0,0),vec4( 1, 0,0,0),vec4(0,0,1,0),vec4(0,0,0,1))));
155 
156  assert(approxEq(rotateZ(Rz270, deg90 ), Rz0 ));
157  assert(approxEq(rotateZ(Rz270, deg180), Rz90 ));
158  assert(approxEq(rotateZ(Rz270, deg270), Rz180));
159  assert(approxEq(rotateZ(Rz90, deg270), Rz0 ));
160 
161  assert(approxEq(inverse(Rz90 ), Rz270));
162  assert(approxEq(inverse(Rz180), Rz180));
163  assert(approxEq(inverse(Rz90), transpose(Rz90)));
164 
165  // arbitrary axis
166  vec3 axis = normalize(vec3(1,2,3));
167  mat4 rot1 = rotate(1.23f, axis);
168  mat4 rot2 = rotate(Rx90, 1.23f, axis);
169  mat4 rot3 = Rx90 * rot1;
170  assert(approxEq(rot2, rot3));
171  vec4 p(-1,2,1,1);
172  vec4 q = rot1 * p;
173  assert(approxEq(q, vec4(-1.05647, 0.231566, 2.19778, 1)));
174  assert(approxEq(length(p), length(q)));
175  assert(approxEq(inverse(rot1), rotate(-1.23f, axis)));
176  assert(approxEq(inverse(rot1), transpose(rot1)));
177  }
178  {
179  // ortho
180  mat4 O = ortho(0, 640, 0, 480, -1, 1);
181  assert(approxEq(O, mat4(vec4(0.003125, 0, 0, 0),
182  vec4(0, 0.00416667, 0, 0),
183  vec4(0, 0, -1, 0),
184  vec4(-1, -1, 0, 1))));
185  }
186  {
187  // ortho
188  mat4 F = frustum(0, 640, 0, 480, -1, 1);
189  assert(approxEq(F, mat4(vec4(-0.003125, 0, 0, 0),
190  vec4(0, 0.00416667, 0, 0),
191  vec4(1, 1, 0, -1),
192  vec4(0, 0, 1, 0))));
193  }
194 }
195 
196 
197 // The following functions are not part of the actual test. They get compiled,
198 // but never executed. I used them to (manually) inspect the quality of the
199 // generated code.
200 
201 void test_scale(float x, float y, float z, mat4& A)
202 {
203  A = scale(vec3(x, y, z));
204 }
205 void test_scale(mat4& A, float x, float y, float z, mat4& B)
206 {
207  B = scale(A, vec3(x, y, z));
208 }
209 
210 void test_translate(float x, float y, float z, mat4& A)
211 {
212  A = translate(vec3(x, y, z));
213 }
214 void test_translate(mat4& A, float x, float y, float z, mat4& B)
215 {
216  B = translate(A, vec3(x, y, z));
217 }
218 
219 void test_rotate(float a, float x, float y, float z, mat4& A)
220 {
221  A = rotate(a, vec3(x, y, z));
222 }
223 
224 void test_ortho(float l, float r, float b, float t, float n, float f, mat4& A)
225 {
226  A = ortho(l, r, b, t, n, f);
227 }
228 
229 void test_frustum(float l, float r, float b, float t, float n, float f, mat4& A)
230 {
231  A = frustum(l, r, b, t, n, f);
232 }
bool approxEq(float x, float y)
mat4 frustum(float left, float right, float bottom, float top, float nearVal, float farVal)
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:333
mat4 rotateY(float angle)
T length2(const vecN< N, T > &x)
Definition: gl_vec.hh:326
void test_frustum(float l, float r, float b, float t, float n, float f, mat4 &A)
void test_rotate(float a, float x, float y, float z, mat4 &A)
matMxN< 4, 4, float > mat4
Definition: gl_mat.hh:159
#define M_PI
Definition: Math.hh:27
vecN< N, T > normalize(const vecN< N, T > &x)
Definition: gl_vec.hh:340
T norm2_2(const matMxN< M, N, T > &A)
Definition: gl_mat.hh:376
mat4 scale(const vec3 &xyz)
Definition: gl_transform.hh:19
#define O(a)
Definition: YM2151.cc:135
vecN< 4, float > vec4
Definition: gl_vec.hh:140
mat4 rotateZ(float angle)
matMxN< 2, 2, T > inverse(const matMxN< 2, 2, T > &A)
Definition: gl_mat.hh:293
void test_scale(float x, float y, float z, mat4 &A)
void test_translate(float x, float y, float z, mat4 &A)
vecN< 3, float > vec3
Definition: gl_vec.hh:139
matMxN< N, M, T > transpose(const matMxN< M, N, T > &A)
Definition: gl_mat.hh:246
mat4 translate(const vec3 &xyz)
Definition: gl_transform.hh:36
mat4 rotate(float angle, const vec3 &axis)
Definition: gl_transform.hh:56
int main()
mat4 ortho(float left, float right, float bottom, float top, float nearVal, float farVal)
void test_ortho(float l, float r, float b, float t, float n, float f, mat4 &A)
mat4 rotateX(float angle)
Definition: gl_transform.hh:91
Definition: gl_mat.hh:24
void print(const vecN< N, T > &x)