11#include < algorithm>
2+ #include < array>
23#include < vector>
34
45#include " main.h"
@@ -190,6 +191,64 @@ namespace
190191 return msh;
191192 }
192193
194+ Holder<Mesh> makeLargeGrid ()
195+ {
196+ std::vector<Vec3> p;
197+ p.reserve (1000 );
198+ for (uint32 y = 0 ; y < 101 ; y++)
199+ for (uint32 x = 0 ; x < 101 ; x++)
200+ p.push_back (Vec3 (Real (x) - 50 , Real (y) - 50 , 0 ));
201+ std::vector<uint32> is;
202+ is.reserve (1000 );
203+ for (uint32 y = 0 ; y < 100 ; y++)
204+ {
205+ for (uint32 x = 0 ; x < 100 ; x++)
206+ {
207+ const uint32 a = y * 101 + x;
208+ static constexpr uint32 o[6 ] = { 0 , 1 , 101 , 1 , 102 , 101 };
209+ for (uint32 b : o)
210+ is.push_back (a + b);
211+ }
212+ }
213+ Holder<Mesh> msh = newMesh ();
214+ msh->positions (p);
215+ msh->indices (is);
216+ return msh;
217+ }
218+
219+ Holder<Mesh> makeCube ()
220+ {
221+ static constexpr Vec3 verts[] = {
222+ Vec3 (-1 , -1 , -1 ), // 0
223+ Vec3 (1 , -1 , -1 ), // 1
224+ Vec3 (1 , 1 , -1 ), // 2
225+ Vec3 (-1 , 1 , -1 ), // 3
226+ Vec3 (-1 , -1 , 1 ), // 4
227+ Vec3 (1 , -1 , 1 ), // 5
228+ Vec3 (1 , 1 , 1 ), // 6
229+ Vec3 (-1 , 1 , 1 ) // 7
230+ };
231+
232+ static constexpr uint32 faces[] = { // Back face
233+ 0 , 1 , 2 , 2 , 3 , 0 ,
234+ // Front face
235+ 4 , 5 , 6 , 6 , 7 , 4 ,
236+ // Left face
237+ 0 , 3 , 7 , 7 , 4 , 0 ,
238+ // Right face
239+ 1 , 5 , 6 , 6 , 2 , 1 ,
240+ // Bottom face
241+ 0 , 1 , 5 , 5 , 4 , 0 ,
242+ // Top face
243+ 3 , 2 , 6 , 6 , 7 , 3
244+ };
245+
246+ Holder<Mesh> msh = newMesh ();
247+ msh->positions (verts);
248+ msh->indices (faces);
249+ return msh;
250+ }
251+
193252 void testMeshBasics ()
194253 {
195254 const Holder<const Mesh> msh = makeSphere ();
@@ -995,6 +1054,76 @@ namespace
9951054 CAGE_TEST (msh->indicesCount () == cnt);
9961055 meshSimplify (+msh, {}); // make sure that the resulting mesh has usable topology
9971056 }
1057+
1058+ void testMeshClipping ()
1059+ {
1060+ CAGE_TESTCASE (" mesh clipping" );
1061+
1062+ for (Real offset : { Real (-2 ), Real (-1.5 ), Real (0 ), Real (0.5 ), Real (1.33 ) })
1063+ {
1064+ Holder<Mesh> grid = makeGrid ();
1065+ meshApplyTransform (+grid, Transform (Vec3 (), Quat (), 0.5 ));
1066+ Holder<Mesh> box = makeCube ();
1067+ meshApplyTransform (+box, Transform (Vec3 (offset, 0 , 0 ), Quat (), 1 ));
1068+ Aabb aabb = box->boundingBox ();
1069+ meshClip (+grid, aabb);
1070+
1071+ { // merge the box with the grid for better visual check
1072+ const auto inds = box->indices ();
1073+ const auto poss = box->positions ();
1074+ const uint32 tris = numeric_cast<uint32>(inds.size () / 3 );
1075+ for (uint32 tri = 0 ; tri < tris; tri++)
1076+ {
1077+ const uint32 *ids = inds.data () + tri * 3 ;
1078+ const Vec3 &a = poss[ids[0 ]];
1079+ const Vec3 &b = poss[ids[1 ]];
1080+ const Vec3 &c = poss[ids[2 ]];
1081+ const Triangle t = Triangle (a, b, c);
1082+ grid->addTriangle (t);
1083+ }
1084+ }
1085+ grid->exportFile (Stringizer () + " meshes/algorithms/testClipping/" + offset + " .obj" );
1086+ }
1087+ }
1088+
1089+ Real meshSurfaceArea (const Mesh *mesh)
1090+ {
1091+ const auto inds = mesh->indices ();
1092+ const auto poss = mesh->positions ();
1093+ const uint32 cnt = numeric_cast<uint32>(inds.size () / 3 );
1094+ Real result = 0 ;
1095+ for (uint32 ti = 0 ; ti < cnt; ti++)
1096+ {
1097+ const Triangle t = Triangle (poss[inds[ti * 3 + 0 ]], poss[inds[ti * 3 + 1 ]], poss[inds[ti * 3 + 2 ]]);
1098+ result += t.area ();
1099+ }
1100+ return result;
1101+ }
1102+
1103+ void testMeshChunking ()
1104+ {
1105+ CAGE_TESTCASE (" mesh chunking" );
1106+
1107+ Holder<Mesh> grid = makeLargeGrid ();
1108+ const Aabb initialBox = grid->boundingBox ();
1109+ approxEqual (initialBox, Aabb (Vec3 (-50 , -50 , 0 ), Vec3 (50 , 50 , 0 )));
1110+ const Real initialArea = meshSurfaceArea (+grid);
1111+ CAGE_TEST (abs (initialArea - 10'000 ) < 1 );
1112+ MeshChunkingConfig cfg;
1113+ cfg.maxSurfaceArea = 10'000 / randomRange (10 , 30 );
1114+ auto r = meshChunking (+grid, cfg);
1115+ Real sum = 0 ;
1116+ Aabb box;
1117+ uint32 i = 0 ;
1118+ for (const auto &it : r)
1119+ {
1120+ sum += meshSurfaceArea (+it);
1121+ box += it->boundingBox ();
1122+ it->exportFile (Stringizer () + " meshes/algorithms/testChunking/" + (i++) + " .obj" );
1123+ }
1124+ CAGE_TEST (abs (sum - initialArea) < 1 );
1125+ approxEqual (box, initialBox);
1126+ }
9981127}
9991128
10001129void testMesh ()
@@ -1007,4 +1136,6 @@ void testMesh()
10071136 testMeshRetexture ();
10081137 testMeshLines ();
10091138 testMeshConsistentWinding ();
1139+ testMeshClipping ();
1140+ testMeshChunking ();
10101141}
0 commit comments