1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the libgltf project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10 #include "APITest.h"
11 #include "OpenGLContext.h"
12 #include "PNGHelper.h"
13
14 #include <libgltf.h>
15 #include "TimeFunction.h"
16
17 #include <iostream>
18 #include <fstream>
19 #include <sstream>
20 #include <cmath>
21
22 namespace libgltf { namespace test
23 {
24
setUp()25 void APITest::setUp()
26 {
27 }
28
tearDown()29 void APITest::tearDown()
30 {
31 }
32
33 // I) Testing gltf_renderer_init() method
test_gltf_renderer_init()34 void APITest::test_gltf_renderer_init()
35 {
36 // 1) Test the usual case, valid *.json and empty vInputFiles
37 {
38 std::vector<glTFFile> vInputFiles;
39 glTFHandle* pHandle = gltf_renderer_init(DUCK_FILE_NAME, vInputFiles);
40 CPPUNIT_ASSERT(pHandle);
41 CPPUNIT_ASSERT_EQUAL(size_t(4), vInputFiles.size());
42
43 CPPUNIT_ASSERT_EQUAL(std::string("duckCM.png"), vInputFiles[0].filename);
44 CPPUNIT_ASSERT_EQUAL(GLTF_IMAGE, vInputFiles[0].type);
45
46 CPPUNIT_ASSERT_EQUAL(std::string("duck.bin"), vInputFiles[1].filename);
47 CPPUNIT_ASSERT_EQUAL(GLTF_BINARY, vInputFiles[1].type);
48
49 CPPUNIT_ASSERT_EQUAL(std::string("duck0FS.glsl"), vInputFiles[2].filename);
50 CPPUNIT_ASSERT_EQUAL(GLTF_GLSL, vInputFiles[2].type);
51
52 CPPUNIT_ASSERT_EQUAL(std::string("duck0VS.glsl"), vInputFiles[3].filename);
53 CPPUNIT_ASSERT_EQUAL(GLTF_GLSL, vInputFiles[3].type);
54
55 gltf_renderer_release(pHandle);
56 }
57
58 // 2) When *.json file name is empty
59 {
60 std::vector<glTFFile> vInputFiles;
61 glTFHandle* pHandle = gltf_renderer_init("", vInputFiles);
62 CPPUNIT_ASSERT(!pHandle);
63 }
64
65 // 3) When *.json file does not exist
66 {
67 std::vector<glTFFile> vInputFiles;
68 glTFHandle* pHandle = gltf_renderer_init("../duck_model/duck.json", vInputFiles);
69 CPPUNIT_ASSERT(!pHandle);
70 }
71
72 // 4) When *.json file is broken (invalid content)
73 {
74 std::vector<glTFFile> vInputFiles;
75 glTFHandle* pHandle = gltf_renderer_init("../data/duck_model/duck_broken.json", vInputFiles);
76 CPPUNIT_ASSERT(!pHandle);
77 }
78
79 // 5) When the output vector is not empty, check whether the method overwrites the vector
80 {
81 std::vector<glTFFile> vInputFiles;
82 vInputFiles.resize(10);
83 vInputFiles[0].filename = "dummy";
84 vInputFiles[0].size = 2000;
85 glTFHandle* pHandle = gltf_renderer_init(DUCK_FILE_NAME, vInputFiles);
86 CPPUNIT_ASSERT(pHandle);
87 CPPUNIT_ASSERT_EQUAL(size_t(4), vInputFiles.size());
88
89 CPPUNIT_ASSERT_EQUAL(std::string("duckCM.png"), vInputFiles[0].filename);
90 CPPUNIT_ASSERT_EQUAL(size_t(0), vInputFiles[0].size);
91
92 gltf_renderer_release(pHandle);
93 }
94
95 // 6) When *.json file contains not only file name of image/binary files but also a path
96 {
97 std::vector<glTFFile> vInputFiles;
98 glTFHandle* pHandle = gltf_renderer_init("../data/duck_model/duck_with_relative_path.json", vInputFiles);
99 CPPUNIT_ASSERT(pHandle);
100 CPPUNIT_ASSERT_EQUAL(size_t(4), vInputFiles.size());
101
102 CPPUNIT_ASSERT_EQUAL(std::string("textures/duckCM.png"), vInputFiles[0].filename);
103 CPPUNIT_ASSERT_EQUAL(GLTF_IMAGE, vInputFiles[0].type);
104
105 CPPUNIT_ASSERT_EQUAL(std::string("buffers/duck.bin"), vInputFiles[1].filename);
106 CPPUNIT_ASSERT_EQUAL(GLTF_BINARY, vInputFiles[1].type);
107
108 CPPUNIT_ASSERT_EQUAL(std::string("shaders/duck0FS.glsl"), vInputFiles[2].filename);
109 CPPUNIT_ASSERT_EQUAL(GLTF_GLSL, vInputFiles[2].type);
110
111 CPPUNIT_ASSERT_EQUAL(std::string("shaders/duck0VS.glsl"), vInputFiles[3].filename);
112 CPPUNIT_ASSERT_EQUAL(GLTF_GLSL, vInputFiles[3].type);
113
114 gltf_renderer_release(pHandle);
115 }
116 }
117
118 // II) Testing gltf_renderer_set_content() method
test_gltf_renderer_set_content()119 void APITest::test_gltf_renderer_set_content()
120 {
121 OpenGLContext aContext;
122 aContext.init();
123
124 // 1) Check when all files are available
125 {
126 std::vector<glTFFile> vInputFiles;
127 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
128
129 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
130 CPPUNIT_ASSERT_EQUAL(LIBGLTF_SUCCESS, nRet);
131 gltf_renderer_release(pHandle);
132 releaseInputFiles(vInputFiles);
133 }
134
135 // 2) Check when the texture file is missing entirely
136 {
137 std::vector<glTFFile> vInputFiles;
138 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
139
140 delete vInputFiles[0].buffer;
141 vInputFiles.erase(vInputFiles.begin());
142
143 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
144 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
145 gltf_renderer_release(pHandle);
146 releaseInputFiles(vInputFiles);
147 }
148
149 // 3) Check when the texture was not loaded actually
150 {
151 std::vector<glTFFile> vInputFiles;
152 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
153
154 delete vInputFiles[0].buffer;
155 vInputFiles[0].buffer = 0;
156 vInputFiles[0].imagewidth = 0;
157
158 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
159 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
160 gltf_renderer_release(pHandle);
161 releaseInputFiles(vInputFiles);
162 }
163
164 // 4) Check when the *.bin file is missing entirely
165 {
166 std::vector<glTFFile> vInputFiles;
167 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
168
169 delete vInputFiles[1].buffer;
170 vInputFiles.erase(++vInputFiles.begin());
171
172 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
173 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
174 gltf_renderer_release(pHandle);
175 releaseInputFiles(vInputFiles);
176 }
177
178 // 5) Check when the *.bin file was not loaded actually
179 {
180 std::vector<glTFFile> vInputFiles;
181 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
182
183 delete vInputFiles[1].buffer;
184 vInputFiles[1].buffer = 0;
185 vInputFiles[1].size = 0;
186
187 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
188 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
189 gltf_renderer_release(pHandle);
190 releaseInputFiles(vInputFiles);
191 }
192
193 // 6) Check when the *.bin file size is not equal with the size read from the *.json file
194 {
195 std::vector<glTFFile> vInputFiles;
196 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
197
198 vInputFiles[1].size = 10;
199
200 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
201 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
202 gltf_renderer_release(pHandle);
203 releaseInputFiles(vInputFiles);
204 }
205
206 // 7) Check when fragment shader is missing entirely
207 {
208 std::vector<glTFFile> vInputFiles;
209 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
210
211 delete vInputFiles[2].buffer;
212 vInputFiles.erase(++(++vInputFiles.begin()));
213
214 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
215 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
216 gltf_renderer_release(pHandle);
217 releaseInputFiles(vInputFiles);
218 }
219
220 // 8) Check when fragment shader file was not loaded actually
221 {
222 std::vector<glTFFile> vInputFiles;
223 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
224
225 delete vInputFiles[2].buffer;
226 vInputFiles[2].buffer = 0;
227 vInputFiles[2].size = 0;
228
229 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
230 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
231 gltf_renderer_release(pHandle);
232 releaseInputFiles(vInputFiles);
233 }
234
235 // 9) Check when fragment shader is invalid (GLSL error)
236 {
237 std::vector<glTFFile> vInputFiles;
238 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles,"../data/duck_model/duck_with_invalid_FS.json" );
239
240 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
241 CPPUNIT_ASSERT_EQUAL(LIBGLTF_SHADER_ERROR, nRet);
242 gltf_renderer_release(pHandle);
243 releaseInputFiles(vInputFiles);
244 }
245
246 // 10) Check when vertex shader is missing entirely
247 {
248 std::vector<glTFFile> vInputFiles;
249 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
250
251 delete vInputFiles[3].buffer;
252 vInputFiles.erase(++(++(++vInputFiles.begin())));
253
254 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
255 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
256 gltf_renderer_release(pHandle);
257 releaseInputFiles(vInputFiles);
258 }
259
260 // 11) Check when vertex shader file was not loaded actually
261 {
262 std::vector<glTFFile> vInputFiles;
263 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
264
265 delete vInputFiles[3].buffer;
266 vInputFiles[3].buffer = 0;
267 vInputFiles[3].size = 0;
268
269 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
270 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
271 gltf_renderer_release(pHandle);
272 releaseInputFiles(vInputFiles);
273 }
274
275 // 12) Check when vertex shader is invalid (GLSL error)
276 {
277 std::vector<glTFFile> vInputFiles;
278 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles,"../data/duck_model/duck_with_invalid_VS.json" );
279
280 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
281 CPPUNIT_ASSERT_EQUAL(LIBGLTF_SHADER_ERROR, nRet);
282 gltf_renderer_release(pHandle);
283 releaseInputFiles(vInputFiles);
284 }
285
286 // 13) Check when non of the files are available
287 {
288 std::vector<glTFFile> vInputFiles;
289 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
290
291 releaseInputFiles(vInputFiles);
292
293 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
294 CPPUNIT_ASSERT_EQUAL(LIBGLTF_FILE_NOT_LOAD, nRet);
295 gltf_renderer_release(pHandle);
296 }
297
298 // 14) Check when input files are given with relative path
299 {
300 std::vector<glTFFile> vInputFiles;
301 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles, "../data/duck_model/duck_with_relative_path.json");
302
303 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
304 CPPUNIT_ASSERT_EQUAL(LIBGLTF_SUCCESS, nRet);
305 gltf_renderer_release(pHandle);
306 }
307 }
308
309 // III) Testing gltf_get_camera_pos() method
test_gltf_get_camera_pos()310 void APITest::test_gltf_get_camera_pos()
311 {
312 // 1) When gltf_renderer_set_content() was not called yet (crash test)
313 {
314 std::vector<glTFFile> vInputFiles;
315 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
316
317 glm::vec3 vEye, vView, vUp;
318 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
319
320 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.x, 0.0001);
321 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.y, 0.0001);
322 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.z, 0.0001);
323
324 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.x, 0.0001);
325 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.y, 0.0001);
326 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.z, 0.0001);
327
328 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.x, 0.0001);
329 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.y, 0.0001);
330 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.z, 0.0001);
331
332 gltf_renderer_release(pHandle);
333 releaseInputFiles(vInputFiles);
334 }
335
336 // 2) When one of the parameters is null pointer (crash test)
337 {
338 std::vector<glTFFile> vInputFiles;
339 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
340
341 glm::vec3 vEye, vView, vUp;
342 gltf_get_camera_pos(pHandle, 0, &vView, &vUp);
343 gltf_get_camera_pos(pHandle, &vEye, 0, &vUp);
344 gltf_get_camera_pos(pHandle, &vEye, &vView, 0);
345
346 gltf_renderer_release(pHandle);
347 releaseInputFiles(vInputFiles);
348 }
349
350 // 3) Call with invalid handle
351 {
352 glm::vec3 vEye(1.0f), vView(1.0f), vUp(1.0f);
353 gltf_get_camera_pos(0, &vEye, &vView, &vUp);
354
355 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.x, 0.0001);
356 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.y, 0.0001);
357 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vEye.z, 0.0001);
358
359 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.x, 0.0001);
360 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.y, 0.0001);
361 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vView.z, 0.0001);
362
363 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.x, 0.0001);
364 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.y, 0.0001);
365 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vUp.z, 0.0001);
366 }
367
368 OpenGLContext aContext;
369 aContext.init();
370
371 // 4) When everything is ok
372 {
373 glTFHandle* pHandle = initSceneAndSetContent();
374
375 glm::vec3 vEye, vView, vUp;
376 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
377
378 CPPUNIT_ASSERT_DOUBLES_EQUAL(400.1130371, vEye.x, 0.0001);
379 CPPUNIT_ASSERT_DOUBLES_EQUAL(463.2640075, vEye.y, 0.0001);
380 CPPUNIT_ASSERT_DOUBLES_EQUAL(-431.0780029, vEye.z, 0.0001);
381
382 CPPUNIT_ASSERT_DOUBLES_EQUAL(399.5765686, vView.x, 0.0001);
383 CPPUNIT_ASSERT_DOUBLES_EQUAL(462.6428528, vView.y, 0.0001);
384 CPPUNIT_ASSERT_DOUBLES_EQUAL(-430.5067138, vView.z, 0.0001);
385
386 CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.4252052, vUp.x, 0.0001);
387 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.7836933, vUp.y, 0.0001);
388 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.4527971, vUp.z, 0.0001);
389 gltf_renderer_release(pHandle);
390 }
391
392 // 5) Test whether moving camera in walkthrough mode has any effect on camera position
393 {
394 glTFHandle* pHandle = initSceneAndSetContent();
395
396 // Get initial position
397 glm::vec3 vEye, vView, vUp;
398 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
399
400 // Move camera
401 gltf_renderer_move_camera(pHandle, 2.0, 3.0, 0.0, 0.0);
402
403 // Get changed position
404 glm::vec3 vEye2, vView2, vUp2;
405 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
406
407 // Affect on eye and view vector
408 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
409 std::abs(vEye.y - vEye2.y) > 0.01 ||
410 std::abs(vEye.z - vEye2.z) > 0.01);
411
412 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.01 ||
413 std::abs(vView.y - vView2.y) > 0.01 ||
414 std::abs(vView.z - vView2.z) > 0.01);
415
416 // No affect on up vector
417 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp2.x, 0.0001);
418 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp2.y, 0.0001);
419 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp2.z, 0.0001);
420
421 gltf_renderer_release(pHandle);
422 }
423
424 // 6) Test whether rotating camera in walkthrough mode has any effect on camera position
425 {
426 glTFHandle* pHandle = initSceneAndSetContent();
427
428 // a) horizontal rotation should affect view vector
429 // Get initial position
430 glm::vec3 vEye, vView, vUp;
431 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
432
433 // Rotate camera
434 gltf_renderer_rotate_camera(pHandle, 3.0, 0.0, 0.0);
435
436 // Get changed position
437 glm::vec3 vEye2, vView2, vUp2;
438 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
439
440 // Affect on view vector
441 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.001 ||
442 std::abs(vView.y - vView2.y) > 0.001 ||
443 std::abs(vView.z - vView2.z) > 0.001);
444
445 // No affect on eye and up vector
446 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.x, vEye2.x, 0.0001);
447 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.y, vEye2.y, 0.0001);
448 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.z, vEye2.z, 0.0001);
449
450 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp2.x, 0.0001);
451 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp2.y, 0.0001);
452 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp2.z, 0.0001);
453
454 // b) vertical rotation should affect both view and up vector
455 // Get initial position
456 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
457
458 // Rotate camera
459 gltf_renderer_rotate_camera(pHandle, 0.0, 3.0, 0.0);
460
461 // Get changed position
462 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
463
464 // Affect on view and up vector
465 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.001 ||
466 std::abs(vView.y - vView2.y) > 0.001 ||
467 std::abs(vView.z - vView2.z) > 0.001);
468
469 CPPUNIT_ASSERT(std::abs(vUp.x - vUp2.x) < 0.01 ||
470 std::abs(vUp.y - vUp2.y) < 0.01 ||
471 std::abs(vUp.z - vUp2.z) < 0.01);
472
473 // No affect on eye vector
474 // TODO: small changes in eye vector (be more precise)?
475 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.x, vEye2.x, 0.0001);
476 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.y, vEye2.y, 0.0001);
477 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.z, vEye2.z, 0.0001);
478
479 gltf_renderer_release(pHandle);
480 }
481
482 // 7) Test whether rotating camera in orbit mode has any effect on camera position
483 {
484 glTFHandle* pHandle = initSceneAndSetContent();
485
486 // a) horizontal rotation should affect eye vector
487 gltf_orbit_mode_start(pHandle);
488 glm::vec3 vEye, vView, vUp;
489 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
490
491 gltf_renderer_rotate_model(pHandle, 2.0, 0.0, 0.0);
492
493 glm::vec3 vEye2, vView2, vUp2;
494 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
495
496 // Affect on eye vector
497 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
498 std::abs(vEye.y - vEye2.y) > 0.01 ||
499 std::abs(vEye.z - vEye2.z) > 0.01);
500
501 // No affect on view and up vector
502 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vView2.x, 0.0001);
503 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vView2.y, 0.0001);
504 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vView2.z, 0.0001);
505
506 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp.x, 0.0001);
507 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp.y, 0.0001);
508 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp.z, 0.0001);
509
510 // b) vertical rotation should affect up and eye vectors
511 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
512 gltf_orbit_mode_start(pHandle);
513
514 gltf_renderer_rotate_model(pHandle, 0.0, 2.0, 0.0);
515
516 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
517
518 // Affect on eye and up vector
519 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
520 std::abs(vEye.y - vEye2.y) > 0.01 ||
521 std::abs(vEye.z - vEye2.z) > 0.01);
522
523 CPPUNIT_ASSERT(std::abs(vUp.x - vUp2.x) > 0.001 ||
524 std::abs(vUp.y - vUp2.y) > 0.001 ||
525 std::abs(vUp.z - vUp2.z) > 0.001);
526
527 // No affect on view vector
528 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vView2.x, 0.0001);
529 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vView2.y, 0.0001);
530 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vView2.z, 0.0001);
531
532 gltf_renderer_release(pHandle);
533 }
534
535 // 8) Test whether moving camera in orbit mode has any effect on camera position
536 {
537 glTFHandle* pHandle = initSceneAndSetContent();
538
539 gltf_orbit_mode_start(pHandle);
540 glm::vec3 vEye, vView, vUp;
541 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
542
543 gltf_renderer_move_camera(pHandle, 2.0, 3.0, 0.0, 0.0);
544
545 glm::vec3 vEye2, vView2, vUp2;
546 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
547
548 // Affect on eye vector
549 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
550 std::abs(vEye.y - vEye2.y) > 0.01 ||
551 std::abs(vEye.z - vEye2.z) > 0.01);
552
553 // No affect on view and up vector
554 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vView2.x, 0.0001);
555 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vView2.y, 0.0001);
556 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vView2.z, 0.0001);
557
558 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp.x, 0.0001);
559 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp.y, 0.0001);
560 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp.z, 0.0001);
561
562 gltf_renderer_release(pHandle);
563 }
564
565 // 9) Test whether camera position loaded from *.json file has any effect on the returned values
566 {
567 glTFHandle* pHandle = initSceneAndSetContent();
568
569 // Get camera position in walkthrough mode
570 glm::vec3 vEye, vView, vUp;
571 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
572 gltf_orbit_mode_start(pHandle);
573
574 // Compare it with the camera postion of the orbit mode (orbit mode ignores the default camera position)
575 // All the three vectors should change
576 glm::vec3 vEye2, vView2, vUp2;
577 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
578
579 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
580 std::abs(vEye.y - vEye2.y) > 0.01 ||
581 std::abs(vEye.z - vEye2.z) > 0.01);
582
583 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.01 ||
584 std::abs(vView.y - vView2.y) > 0.01 ||
585 std::abs(vView.z - vView2.z) > 0.01);
586
587 CPPUNIT_ASSERT(std::abs(vUp.x - vUp2.x) > 0.01 ||
588 std::abs(vUp.y - vUp2.y) > 0.01 ||
589 std::abs(vUp.z - vUp2.z) > 0.01);
590
591 gltf_renderer_release(pHandle);
592 }
593 }
594
595 // IV) Testing gltf_get_model_center_pos() method
test_gltf_get_model_center_pos()596 void APITest::test_gltf_get_model_center_pos()
597 {
598 // 1) When gltf_renderer_set_content() was not called yet (initial value: 0,0,0)
599 {
600 std::vector<glTFFile> vInputFiles;
601 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
602
603 glm::vec3* vCenterPos = gltf_get_model_center_pos(pHandle);
604
605 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vCenterPos->x, 0.0001);
606 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vCenterPos->y, 0.0001);
607 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, vCenterPos->z, 0.0001);
608
609 gltf_renderer_release(pHandle);
610 releaseInputFiles(vInputFiles);
611 }
612
613 // 2) Call with invalid handle
614 {
615 glm::vec3* vCenterPos = gltf_get_model_center_pos(0);
616
617 CPPUNIT_ASSERT_EQUAL((glm::vec3*)(0), vCenterPos);
618 }
619
620 OpenGLContext aContext;
621 aContext.init();
622
623 // 3) Default view in walkthrough mode
624 {
625 glTFHandle* pHandle = initSceneAndSetContent();
626
627 glm::vec3* vCenterPos = gltf_get_model_center_pos(pHandle);
628
629 CPPUNIT_ASSERT_DOUBLES_EQUAL(13.4406967, vCenterPos->x, 0.0001);
630 CPPUNIT_ASSERT_DOUBLES_EQUAL(86.9496841, vCenterPos->y, 0.0001);
631 CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.70149993, vCenterPos->z, 0.0001);
632
633 gltf_renderer_release(pHandle);
634 }
635
636 // 4) Test whether switching to orbit mode makes any difference
637 {
638 glTFHandle* pHandle = initSceneAndSetContent();
639
640 gltf_orbit_mode_start(pHandle);
641
642 glm::vec3* vCenterPos = gltf_get_model_center_pos(pHandle);
643
644 CPPUNIT_ASSERT_DOUBLES_EQUAL(13.4406967, vCenterPos->x, 0.0001);
645 CPPUNIT_ASSERT_DOUBLES_EQUAL(86.9496841, vCenterPos->y, 0.0001);
646 CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.70149993, vCenterPos->z, 0.0001);
647
648 gltf_renderer_release(pHandle);
649 }
650
651 // 5) Check whether camera look at the center position in orbit mode
652 {
653 glTFHandle* pHandle = initSceneAndSetContent();
654
655 gltf_orbit_mode_start(pHandle);
656
657 glm::vec3* vCenterPos = gltf_get_model_center_pos(pHandle);
658
659 glm::vec3 vEye, vView, vUp;
660 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
661
662 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vCenterPos->x, 0.0001);
663 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vCenterPos->y, 0.0001);
664 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vCenterPos->z, 0.0001);
665
666 gltf_renderer_release(pHandle);
667 }
668
669 // 6) Change the position via the pointer and check whether it has effect
670 // on the internal variables of the scene
671 {
672 glTFHandle* pHandle = initSceneAndSetContent();
673
674 gltf_orbit_mode_start(pHandle);
675
676 glm::vec3* vCenterPos = gltf_get_model_center_pos(pHandle);
677 vCenterPos->x = 6.0f;
678
679 glm::vec3* vCenterPos2 = gltf_get_model_center_pos(pHandle);
680 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->x, vCenterPos2->x, 0.0001);
681 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->y, vCenterPos2->y, 0.0001);
682 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->z, vCenterPos2->z, 0.0001);
683
684 glm::vec3 vEye, vView, vUp;
685 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
686
687 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->x, vView.x, 0.0001);
688 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->y, vView.y, 0.0001);
689 CPPUNIT_ASSERT_DOUBLES_EQUAL(vCenterPos->z, vView.z, 0.0001);
690
691 gltf_renderer_release(pHandle);
692 }
693 }
694
695 // VI) Testing gltf_get_model_size() method
test_gltf_get_model_size()696 void APITest::test_gltf_get_model_size()
697 {
698 // 1) When gltf_renderer_set_content() was not called yet (initial value: 0.0)
699 {
700 std::vector<glTFFile> vInputFiles;
701 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
702
703 double dSize = gltf_get_model_size(pHandle);
704
705 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, dSize, 0.0001);
706
707 gltf_renderer_release(pHandle);
708 releaseInputFiles(vInputFiles);
709 }
710
711 // 2) Call with invalid handle
712 {
713 double dSize = gltf_get_model_size(0);
714 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, dSize, 0.0001);
715 }
716
717 OpenGLContext aContext;
718 aContext.init();
719
720 // 3) When everything is ok
721 {
722 glTFHandle* pHandle = initSceneAndSetContent();
723
724 double dSize = gltf_get_model_size(0);
725
726 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, dSize, 0.0001);
727
728 gltf_renderer_release(pHandle);
729 }
730
731 // 4) Test whether view affect the size (view independent size)
732 {
733 glTFHandle* pHandle = initSceneAndSetContent();
734
735 double dSize = gltf_get_model_size(0);
736
737 gltf_orbit_mode_start(pHandle);
738
739 double dSize2 = gltf_get_model_size(0);
740
741 CPPUNIT_ASSERT_DOUBLES_EQUAL(dSize, dSize2, 0.0001);
742
743 gltf_renderer_release(pHandle);
744 }
745 }
746
747 // VI) Testing gltf_{enable\disable}_rotation() method
test_gltf_enable_disable_rotation()748 void APITest::test_gltf_enable_disable_rotation()
749 {
750 // 1) When gltf_renderer_set_content() was not called yet (crash test)
751 {
752 std::vector<glTFFile> vInputFiles;
753 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles);
754
755 gltf_enable_rotation(pHandle);
756 gltf_disable_rotation(pHandle);
757
758 gltf_renderer_release(pHandle);
759 releaseInputFiles(vInputFiles);
760 }
761
762 OpenGLContext aContext;
763 aContext.init();
764
765 // 2) By default camera rotation is enabled -> rotation works
766 {
767 glTFHandle* pHandle = initSceneAndSetContent();
768
769 // Get initial position
770 glm::vec3 vEye, vView, vUp;
771 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
772
773 // Rotate camera
774 gltf_renderer_rotate_camera(pHandle, 3.0, 0.0, 0.0);
775
776 // Get changed position
777 glm::vec3 vEye2, vView2, vUp2;
778 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
779
780 // Rotation has affect on view vector
781 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.001 ||
782 std::abs(vView.y - vView2.y) > 0.001 ||
783 std::abs(vView.z - vView2.z) > 0.001);
784
785 gltf_renderer_release(pHandle);
786 }
787
788 // 3) disable rotation in walkthrough mode -> no rotation
789 {
790 glTFHandle* pHandle = initSceneAndSetContent();
791
792 gltf_disable_rotation(pHandle);
793
794 // Get initial position
795 glm::vec3 vEye, vView, vUp;
796 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
797
798 // Rotate camera
799 gltf_renderer_rotate_camera(pHandle, 3.0, 0.0, 0.0);
800
801 // Get changed position
802 glm::vec3 vEye2, vView2, vUp2;
803 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
804
805 // Rotation was not applied on the camera position
806 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vView2.x, 0.0001);
807 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vView2.y, 0.0001);
808 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vView2.z, 0.0001);
809
810 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.x, vEye2.x, 0.0001);
811 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.y, vEye2.y, 0.0001);
812 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.z, vEye2.z, 0.0001);
813
814 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp2.x, 0.0001);
815 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp2.y, 0.0001);
816 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp2.z, 0.0001);
817
818 gltf_renderer_release(pHandle);
819 }
820
821 // 4) disable and reenable rotation in walkthrough mode -> rotation applied on the position
822 {
823 glTFHandle* pHandle = initSceneAndSetContent();
824
825 gltf_disable_rotation(pHandle);
826 gltf_enable_rotation(pHandle);
827
828 // Get initial position
829 glm::vec3 vEye, vView, vUp;
830 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
831
832 // Rotate camera
833 gltf_renderer_rotate_camera(pHandle, 3.0, 0.0, 0.0);
834
835 // Get changed position
836 glm::vec3 vEye2, vView2, vUp2;
837 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
838
839 // Rotation has affect on view vector
840 CPPUNIT_ASSERT(std::abs(vView.x - vView2.x) > 0.001 ||
841 std::abs(vView.y - vView2.y) > 0.001 ||
842 std::abs(vView.z - vView2.z) > 0.001);
843
844 gltf_renderer_release(pHandle);
845 }
846
847 // 5) disable rotation in orbit mode -> no rotation
848 {
849 glTFHandle* pHandle = initSceneAndSetContent();
850
851 gltf_disable_rotation(pHandle);
852
853 gltf_orbit_mode_start(pHandle);
854 glm::vec3 vEye, vView, vUp;
855 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
856
857 gltf_renderer_rotate_model(pHandle, 2.0, 0.0, 0.0);
858
859 glm::vec3 vEye2, vView2, vUp2;
860 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
861
862 // Rotation was not applied on the camera position
863 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.x, vEye2.x, 0.0001);
864 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.y, vEye2.y, 0.0001);
865 CPPUNIT_ASSERT_DOUBLES_EQUAL(vEye.z, vEye2.z, 0.0001);
866
867 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.x, vView2.x, 0.0001);
868 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.y, vView2.y, 0.0001);
869 CPPUNIT_ASSERT_DOUBLES_EQUAL(vView.z, vView2.z, 0.0001);
870
871 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.x, vUp.x, 0.0001);
872 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.y, vUp.y, 0.0001);
873 CPPUNIT_ASSERT_DOUBLES_EQUAL(vUp.z, vUp.z, 0.0001);
874
875 gltf_renderer_release(pHandle);
876 }
877
878 // 6) disable and reenable rotation in orbit mode -> rotation applied on the position
879 {
880 glTFHandle* pHandle = initSceneAndSetContent();
881
882 gltf_disable_rotation(pHandle);
883 gltf_enable_rotation(pHandle);
884
885 gltf_orbit_mode_start(pHandle);
886 glm::vec3 vEye, vView, vUp;
887 gltf_get_camera_pos(pHandle, &vEye, &vView, &vUp);
888
889 gltf_renderer_rotate_model(pHandle, 2.0, 0.0, 0.0);
890
891 glm::vec3 vEye2, vView2, vUp2;
892 gltf_get_camera_pos(pHandle, &vEye2, &vView2, &vUp2);
893
894 // Affect on eye vector
895 CPPUNIT_ASSERT(std::abs(vEye.x - vEye2.x) > 0.01 ||
896 std::abs(vEye.y - vEye2.y) > 0.01 ||
897 std::abs(vEye.z - vEye2.z) > 0.01);
898
899 gltf_renderer_release(pHandle);
900 }
901 }
902
parseJsonAndLoadInputFiles(std::vector<glTFFile> & vInputFiles,const std::string & sFilename)903 glTFHandle* APITest::parseJsonAndLoadInputFiles(std::vector<glTFFile>& vInputFiles, const std::string& sFilename)
904 {
905 glTFHandle* pHandle = gltf_renderer_init(sFilename.c_str(), vInputFiles);
906 CPPUNIT_ASSERT(pHandle);
907 CPPUNIT_ASSERT_EQUAL(size_t(4), vInputFiles.size());
908
909 readInputFiles(vInputFiles, sFilename);
910
911 return pHandle;
912 }
913
initSceneAndSetContent(const std::string & sFilename)914 glTFHandle* APITest::initSceneAndSetContent(const std::string& sFilename)
915 {
916 std::vector<glTFFile> vInputFiles;
917 glTFHandle* pHandle = parseJsonAndLoadInputFiles(vInputFiles, sFilename);
918
919 int nRet = gltf_renderer_set_content(pHandle, vInputFiles);
920 CPPUNIT_ASSERT_EQUAL(LIBGLTF_SUCCESS, nRet);
921 releaseInputFiles(vInputFiles);
922 return pHandle;
923 }
924
readInputFiles(std::vector<glTFFile> & vInputFiles,const std::string & sJsonName)925 void APITest::readInputFiles(std::vector<glTFFile>& vInputFiles, const std::string& sJsonName)
926 {
927 for( size_t i = 0; i < vInputFiles.size(); ++i )
928 {
929 glTFFile& rFile = vInputFiles[i];
930 const std::string sFileName(sJsonName.substr(0,sJsonName.find_last_of('/')+1) + rFile.filename);
931 if( rFile.type == GLTF_IMAGE )
932 {
933 bool bRet = pnghelper::ReadPNGFromFile(sFileName, &rFile.buffer, rFile.imagewidth, rFile.imageheight );
934 rFile.size = 4 * rFile.imagewidth * rFile.imageheight;
935 CPPUNIT_ASSERT_EQUAL(true, bRet);
936 }
937 else
938 {
939 std::ifstream ifs(sFileName.c_str());
940 CPPUNIT_ASSERT_EQUAL(true, ifs.is_open());
941
942 ifs.seekg (0, ifs.end);
943 rFile.size = ifs.tellg();
944 ifs.seekg (0, ifs.beg);
945 rFile.buffer = new char[rFile.size];
946 ifs.read (rFile.buffer,rFile.size);
947 ifs.close();
948 }
949 }
950 }
951
releaseInputFiles(std::vector<glTFFile> & vInputFiles)952 void APITest::releaseInputFiles(std::vector<glTFFile>& vInputFiles)
953 {
954 for( size_t i = 0; i < vInputFiles.size(); ++i )
955 {
956 glTFFile& rFile = vInputFiles[i];
957 delete rFile.buffer;
958 rFile.buffer = 0;
959 rFile.size = 0;
960 rFile.imagewidth = 0;
961 rFile.imageheight = 0;
962 }
963 vInputFiles.clear();
964 }
965
966 CPPUNIT_TEST_SUITE_REGISTRATION(APITest);
967
968 } // test
969 } // libgltf
970
971
972 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
973