1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 /* Unit tests for functions in geometry.h */
21 
22 #include "math/func.h"
23 #include "math/geometry.h"
24 
25 #include <gtest/gtest.h>
26 
27 
28 const float TEST_TOLERANCE = 1e-5;
29 
30 
31 // Test for rewritten function RotateAngle()
TEST(GeometryTest,RotateAngleTest)32 TEST(GeometryTest, RotateAngleTest)
33 {
34     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE));
35 
36     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE));
37 
38     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE));
39 
40     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE));
41 
42     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE));
43 
44     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE));
45 
46     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE));
47 
48     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE));
49 
50     EXPECT_TRUE(Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE));
51 }
52 
53 // Tests for other altered, complex or uncertain functions
54 
55 /*
56 
57   TODO: write meaningful tests with proper test values
58 
59 int TestAngle()
60 {
61     const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805);
62     const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111);
63 
64     float mathResult = Math::Angle(u, v);
65     float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v));
66 
67     if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) )
68         return __LINE__;
69 
70     return 0;
71 }
72 
73 int TestRotateView()
74 {
75     const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284);
76     const float angleH = 44.5;
77     const float angleV = 12.3;
78     const float dist = 34.76;
79 
80     Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist);
81     Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist));
82 
83     if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
84         return __LINE__;
85 
86     return 0;
87 }
88 
89 int TestLookatPoint()
90 {
91     const Math::Vector eye(-2.451183170579471,  0.241270270546559, -0.490677411454893);
92     const float angleH = 48.4;
93     const float angleV = 32.4;
94     const float length = 74.44;
95 
96     Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length);
97     Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length));
98 
99     if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
100         return __LINE__;
101 
102     return 0;
103 }
104 
105 int TestProjection()
106 {
107     const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688);
108     const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799);
109     const Math::Vector p(2.289326061164255, -0.505511362271196,  0.660204551169491);
110 
111     Math::Vector mathResult = Math::Projection(a, b, p);
112     Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p)));
113 
114     if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
115         return __LINE__;
116 
117     return 0;
118 }
119 
120 int TestLoadViewMatrix()
121 {
122     const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744);
123     const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463);
124     const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582);
125 
126     Math::Matrix mathResult;
127     Math::LoadViewMatrix(mathResult, from, at, worldUp);
128 
129     Math::Matrix oldMathResult;
130     {
131         D3DMATRIX mat;
132         D3DVECTOR fromD3D = VEC_TO_D3DVEC(from);
133         D3DVECTOR atD3D = VEC_TO_D3DVEC(at);
134         D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp);
135         D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D);
136         oldMathResult = D3DMAT_TO_MAT(mat);
137     }
138 
139     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
140         return __LINE__;
141 
142     return 0;
143 }
144 
145 int TestLoadProjectionMatrix()
146 {
147     const float fov = 76.3f;
148     const float aspect = 0.891f;
149     const float nearPlane = 12.3f;
150     const float farPlane = 1238.9f;
151 
152     Math::Matrix mathResult;
153     Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane);
154 
155     Math::Matrix oldMathResult;
156     {
157         D3DMATRIX mat;
158         D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane);
159         oldMathResult = D3DMAT_TO_MAT(mat);
160     }
161 
162     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
163         return __LINE__;
164 
165     return 0;
166 }
167 
168 int TestLoadTranslationMatrix()
169 {
170     const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145);
171 
172     Math::Matrix mathResult;
173     Math::LoadTranslationMatrix(mathResult, translation);
174 
175     Math::Matrix oldMathResult;
176     {
177         D3DMATRIX mat;
178         D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z);
179         oldMathResult = D3DMAT_TO_MAT(mat);
180     }
181 
182     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
183         return __LINE__;
184 
185     return 0;
186 }
187 
188 int TestLoadScaleMatrix()
189 {
190     const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065);
191 
192     Math::Matrix mathResult;
193     Math::LoadScaleMatrix(mathResult, scale);
194 
195     Math::Matrix oldMathResult;
196     {
197         D3DMATRIX mat;
198         D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z);
199         oldMathResult = D3DMAT_TO_MAT(mat);
200     }
201 
202     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
203         return __LINE__;
204 
205     return 0;
206 }
207 
208 int TestLoadRotationXMatrix()
209 {
210     const float angle = 0.513790685774275;
211 
212     Math::Matrix mathResult;
213     Math::LoadRotationXMatrix(mathResult, angle);
214 
215     Math::Matrix oldMathResult;
216     {
217         D3DMATRIX mat;
218         D3DUtil_SetRotateXMatrix(mat, angle);
219         oldMathResult = D3DMAT_TO_MAT(mat);
220     }
221 
222     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
223         return __LINE__;
224 
225     return 0;
226 }
227 
228 int TestLoadRotationYMatrix()
229 {
230     const float angle = -0.569166650127303;
231 
232     Math::Matrix mathResult;
233     Math::LoadRotationYMatrix(mathResult, angle);
234 
235     Math::Matrix oldMathResult;
236     {
237         D3DMATRIX mat;
238         D3DUtil_SetRotateYMatrix(mat, angle);
239         oldMathResult = D3DMAT_TO_MAT(mat);
240     }
241 
242     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
243         return __LINE__;
244 
245     return 0;
246 }
247 
248 int TestLoadRotationZMatrix()
249 {
250     const float angle = 0.380448034347452;
251 
252     Math::Matrix mathResult;
253     Math::LoadRotationZMatrix(mathResult, angle);
254 
255     Math::Matrix oldMathResult;
256     {
257         D3DMATRIX mat;
258         D3DUtil_SetRotateZMatrix(mat, angle);
259         oldMathResult = D3DMAT_TO_MAT(mat);
260     }
261 
262     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
263         return __LINE__;
264 
265     return 0;
266 }
267 
268 int TestLoadRotationMatrix()
269 {
270     const float angle = -0.987747190637790;
271     const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884);
272 
273     Math::Matrix mathResult;
274     Math::LoadRotationMatrix(mathResult, dir, angle);
275 
276     Math::Matrix oldMathResult;
277     {
278         D3DMATRIX mat;
279         D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir);
280         D3DUtil_SetRotationMatrix(mat, dirD3D, angle);
281         oldMathResult = D3DMAT_TO_MAT(mat);
282     }
283 
284     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
285         return __LINE__;
286 
287     return 0;
288 }
289 
290 int TestLoadRotationXZYMatrix()
291 {
292     const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988);
293 
294     Math::Matrix mathResult;
295     Math::LoadRotationXZYMatrix(mathResult, angles);
296 
297     Math::Matrix oldMathResult;
298     {
299         D3DMATRIX mat;
300         MatRotateXZY(mat, VEC_TO_D3DVEC(angles));
301         oldMathResult = D3DMAT_TO_MAT(mat);
302     }
303 
304     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
305         return __LINE__;
306 
307     return 0;
308 }
309 
310 int TestLoadRotationZXYMatrix()
311 {
312     const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253);
313 
314     Math::Matrix mathResult;
315     Math::LoadRotationZXYMatrix(mathResult, angles);
316 
317     Math::Matrix oldMathResult;
318     {
319         D3DMATRIX mat;
320         MatRotateZXY(mat, VEC_TO_D3DVEC(angles));
321         oldMathResult = D3DMAT_TO_MAT(mat);
322     }
323 
324     if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
325         return __LINE__;
326 
327     return 0;
328 }
329 
330 int TestTransform()
331 {
332     Math::Matrix transformMatrix(
333         (float[4][4])
334         {
335             { -0.9282074720977896,  0.6794734970319730, -1.3234304946882685,  0.0925294727863890 },
336             { -0.0395527963683484,  0.2897634352353881,  1.9144398570315440, -1.4062267508968478 },
337             {  0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 },
338             {  0.0f, 0.0f, 0.0f, 1.0f }
339         }
340     );
341     Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574);
342 
343     Math::Vector mathResult = Math::Transform(transformMatrix, vector);
344     Math::Vector oldMathResult = Transform(transformMatrix, vector);
345 
346     if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
347         return __LINE__;
348 
349     return 0;
350 }
351 
352 */
353 
354