@@ -58,6 +58,7 @@ class TestUtilities : public TestBase {
5858 void testEulerConversion ();
5959 void testBase64 ();
6060 void testSanitizeDirName ();
61+ void testIsBlockInSight ();
6162};
6263
6364static TestUtilities g_test_instance;
@@ -90,6 +91,7 @@ void TestUtilities::runTests(IGameDef *gamedef)
9091 TEST (testEulerConversion);
9192 TEST (testBase64);
9293 TEST (testSanitizeDirName);
94+ TEST (testIsBlockInSight);
9395}
9496
9597// //////////////////////////////////////////////////////////////////////////////
@@ -636,3 +638,69 @@ void TestUtilities::testSanitizeDirName()
636638 UASSERT (sanitizeDirName (" cOnIn$" , " ~" ) == " ~cOnIn$" );
637639 UASSERT (sanitizeDirName (" cOnIn$ " , " ~" ) == " _cOnIn$_" );
638640}
641+
642+ template <typename F, typename C>
643+ C apply_all (const C &co, F functor)
644+ {
645+ C ret;
646+ for (auto it = co.begin (); it != co.end (); it++)
647+ ret.push_back (functor (*it));
648+ return ret;
649+ }
650+
651+ #define cast_v3 (T, other ) T((other).X, (other).Y, (other).Z)
652+
653+ void TestUtilities::testIsBlockInSight ()
654+ {
655+ const std::vector<v3s16> testdata1 = {
656+ {0 , 1 * (int )BS, 0 }, // camera_pos
657+ {1 , 0 , 0 }, // camera_dir
658+
659+ { 2 , 0 , 0 },
660+ {-2 , 0 , 0 },
661+ {0 , 0 , 3 },
662+ {0 , 0 , -3 },
663+ {0 , 0 , 0 },
664+ {6 , 0 , 0 }
665+ };
666+ auto test1 = [] (const std::vector<v3s16> &data) {
667+ float range = BS * MAP_BLOCKSIZE * 4 ;
668+ float fov = 72 * core::DEGTORAD;
669+ v3f cam_pos = cast_v3 (v3f, data[0 ]), cam_dir = cast_v3 (v3f, data[1 ]);
670+ UASSERT ( isBlockInSight (data[2 ], cam_pos, cam_dir, fov, range));
671+ UASSERT (!isBlockInSight (data[3 ], cam_pos, cam_dir, fov, range));
672+ UASSERT (!isBlockInSight (data[4 ], cam_pos, cam_dir, fov, range));
673+ UASSERT (!isBlockInSight (data[5 ], cam_pos, cam_dir, fov, range));
674+
675+ // camera block must be visible
676+ UASSERT (isBlockInSight (data[6 ], cam_pos, cam_dir, fov, range));
677+
678+ // out of range is never visible
679+ UASSERT (!isBlockInSight (data[7 ], cam_pos, cam_dir, fov, range));
680+ };
681+ // XZ rotations
682+ for (int j = 0 ; j < 4 ; j++) {
683+ auto tmpdata = apply_all (testdata1, [&] (v3s16 v) -> v3s16 {
684+ v.rotateXZBy (j*90 );
685+ return v;
686+ });
687+ test1 (tmpdata);
688+ }
689+ // just two for XY
690+ for (int j = 0 ; j < 2 ; j++) {
691+ auto tmpdata = apply_all (testdata1, [&] (v3s16 v) -> v3s16 {
692+ v.rotateXYBy (90 +j*180 );
693+ return v;
694+ });
695+ test1 (tmpdata);
696+ }
697+
698+ {
699+ float range = BS * MAP_BLOCKSIZE * 2 ;
700+ float fov = 72 * core::DEGTORAD;
701+ v3f cam_pos (-(MAP_BLOCKSIZE - 1 ) * BS, 0 , 0 ), cam_dir (1 , 0 , 0 );
702+ // we're looking at X+ but are so close to block (-1,0,0) that it
703+ // should still be considered visible
704+ UASSERT (isBlockInSight ({-1 , 0 , 0 }, cam_pos, cam_dir, fov, range));
705+ }
706+ }
0 commit comments