#ifndef TEST_HALF_EDGE_STRUCTURE_H #define TEST_HALF_EDGE_STRUCTURE_H // Libraries #include "reactphysics3d.h" #include "Test.h" #include /// Reactphysics3D namespace namespace reactphysics3d { // Class TestHalfEdgeStructure /** * Unit test for the HalfEdgeStructure class. */ class TestHalfEdgeStructure : public Test { private : // ---------- Atributes ---------- // /// Memory allocator DefaultAllocator mAllocator; public : // ---------- Methods ---------- // /// Constructor TestHalfEdgeStructure(const std::string& name) : Test(name) { } /// Destructor virtual ~TestHalfEdgeStructure() { } /// Run the tests void run() { testCube(); testTetrahedron(); } void testCube() { // Create the half-edge structure for a cube rp3d::HalfEdgeStructure cubeStructure(mAllocator, 6, 8, 24); rp3d::Vector3 vertices[8] = { rp3d::Vector3(-0.5, -0.5, 0.5), rp3d::Vector3(0.5, -0.5, 0.5), rp3d::Vector3(0.5, 0.5, 0.5), rp3d::Vector3(-0.5, 0.5, 0.5), rp3d::Vector3(-0.5, -0.5, -0.5), rp3d::Vector3(0.5, -0.5, -0.5), rp3d::Vector3(0.5, 0.5, -0.5), rp3d::Vector3(-0.5, 0.5, -0.5) }; // Vertices cubeStructure.addVertex(0); cubeStructure.addVertex(1); cubeStructure.addVertex(2); cubeStructure.addVertex(3); cubeStructure.addVertex(4); cubeStructure.addVertex(5); cubeStructure.addVertex(6); cubeStructure.addVertex(7); // Faces List face0(mAllocator, 4); face0.add(0); face0.add(1); face0.add(2); face0.add(3); List face1(mAllocator, 4); face1.add(1); face1.add(5); face1.add(6); face1.add(2); List face2(mAllocator, 4); face2.add(5); face2.add(4); face2.add(7); face2.add(6); List face3(mAllocator, 4); face3.add(4); face3.add(0); face3.add(3); face3.add(7); List face4(mAllocator, 4); face4.add(0); face4.add(4); face4.add(5); face4.add(1); List face5(mAllocator, 4); face5.add(2); face5.add(6); face5.add(7); face5.add(3); cubeStructure.addFace(face0); cubeStructure.addFace(face1); cubeStructure.addFace(face2); cubeStructure.addFace(face3); cubeStructure.addFace(face4); cubeStructure.addFace(face5); cubeStructure.init(); // --- Test that the half-edge structure of the cube is valid --- // rp3d_test(cubeStructure.getNbFaces() == 6); rp3d_test(cubeStructure.getNbVertices() == 8); rp3d_test(cubeStructure.getNbHalfEdges() == 24); // Test vertices rp3d_test(vertices[cubeStructure.getVertex(0).vertexPointIndex].x == -0.5); rp3d_test(vertices[cubeStructure.getVertex(0).vertexPointIndex].y == -0.5); rp3d_test(vertices[cubeStructure.getVertex(0).vertexPointIndex].z == 0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(0).edgeIndex).vertexIndex == 0); rp3d_test(vertices[cubeStructure.getVertex(1).vertexPointIndex].x == 0.5); rp3d_test(vertices[cubeStructure.getVertex(1).vertexPointIndex].y == -0.5); rp3d_test(vertices[cubeStructure.getVertex(1).vertexPointIndex].z == 0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(1).edgeIndex).vertexIndex == 1); rp3d_test(vertices[cubeStructure.getVertex(2).vertexPointIndex].x == 0.5); rp3d_test(vertices[cubeStructure.getVertex(2).vertexPointIndex].y == 0.5); rp3d_test(vertices[cubeStructure.getVertex(2).vertexPointIndex].z == 0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(2).edgeIndex).vertexIndex == 2); rp3d_test(vertices[cubeStructure.getVertex(3).vertexPointIndex].x == -0.5); rp3d_test(vertices[cubeStructure.getVertex(3).vertexPointIndex].y == 0.5); rp3d_test(vertices[cubeStructure.getVertex(3).vertexPointIndex].z == 0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(3).edgeIndex).vertexIndex == 3); rp3d_test(vertices[cubeStructure.getVertex(4).vertexPointIndex].x == -0.5); rp3d_test(vertices[cubeStructure.getVertex(4).vertexPointIndex].y == -0.5); rp3d_test(vertices[cubeStructure.getVertex(4).vertexPointIndex].z == -0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(4).edgeIndex).vertexIndex == 4); rp3d_test(vertices[cubeStructure.getVertex(5).vertexPointIndex].x == 0.5); rp3d_test(vertices[cubeStructure.getVertex(5).vertexPointIndex].y == -0.5); rp3d_test(vertices[cubeStructure.getVertex(5).vertexPointIndex].z == -0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(5).edgeIndex).vertexIndex == 5); rp3d_test(vertices[cubeStructure.getVertex(6).vertexPointIndex].x == 0.5); rp3d_test(vertices[cubeStructure.getVertex(6).vertexPointIndex].y == 0.5); rp3d_test(vertices[cubeStructure.getVertex(6).vertexPointIndex].z == -0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(6).edgeIndex).vertexIndex == 6); rp3d_test(vertices[cubeStructure.getVertex(7).vertexPointIndex].x == -0.5); rp3d_test(vertices[cubeStructure.getVertex(7).vertexPointIndex].y == 0.5); rp3d_test(vertices[cubeStructure.getVertex(7).vertexPointIndex].z == -0.5); rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getVertex(7).edgeIndex).vertexIndex == 7); // Test faces for (uint f=0; f<6; f++) { rp3d_test(cubeStructure.getHalfEdge(cubeStructure.getFace(f).edgeIndex).faceIndex == f); } // Test edges for (uint f=0; f<6; f++) { uint edgeIndex = cubeStructure.getFace(f).edgeIndex; const uint firstEdgeIndex = edgeIndex; // For each half-edge of the face for (uint e=0; e<4; e++) { rp3d::HalfEdgeStructure::Edge edge = cubeStructure.getHalfEdge(edgeIndex); rp3d_test(cubeStructure.getHalfEdge(edge.twinEdgeIndex).twinEdgeIndex == edgeIndex); rp3d_test(edge.faceIndex == f); // Go to the next edge edgeIndex = edge.nextEdgeIndex; } rp3d_test(firstEdgeIndex == edgeIndex); } } void testTetrahedron() { // Create the half-edge structure for a tetrahedron std::vector> faces; rp3d::HalfEdgeStructure tetrahedron(mAllocator, 4, 4, 12); // Vertices rp3d::Vector3 vertices[4] = { rp3d::Vector3(1, -1, -1), rp3d::Vector3(-1, -1, -1), rp3d::Vector3(0, -1, 1), rp3d::Vector3(0, 1, 0) }; tetrahedron.addVertex(0); tetrahedron.addVertex(1); tetrahedron.addVertex(2); tetrahedron.addVertex(3); // Faces List face0(mAllocator, 3); face0.add(0); face0.add(1); face0.add(2); List face1(mAllocator, 3); face1.add(0); face1.add(3); face1.add(1); List face2(mAllocator, 3); face2.add(1); face2.add(3); face2.add(2); List face3(mAllocator, 3); face3.add(0); face3.add(2); face3.add(3); tetrahedron.addFace(face0); tetrahedron.addFace(face1); tetrahedron.addFace(face2); tetrahedron.addFace(face3); tetrahedron.init(); // --- Test that the half-edge structure of the tetrahedron is valid --- // rp3d_test(tetrahedron.getNbFaces() == 4); rp3d_test(tetrahedron.getNbVertices() == 4); rp3d_test(tetrahedron.getNbHalfEdges() == 12); // Test vertices rp3d_test(vertices[tetrahedron.getVertex(0).vertexPointIndex].x == 1); rp3d_test(vertices[tetrahedron.getVertex(0).vertexPointIndex].y == -1); rp3d_test(vertices[tetrahedron.getVertex(0).vertexPointIndex].z == -1); rp3d_test(tetrahedron.getHalfEdge(tetrahedron.getVertex(0).edgeIndex).vertexIndex == 0); rp3d_test(vertices[tetrahedron.getVertex(1).vertexPointIndex].x == -1); rp3d_test(vertices[tetrahedron.getVertex(1).vertexPointIndex].y == -1); rp3d_test(vertices[tetrahedron.getVertex(1).vertexPointIndex].z == -1); rp3d_test(tetrahedron.getHalfEdge(tetrahedron.getVertex(1).edgeIndex).vertexIndex == 1); rp3d_test(vertices[tetrahedron.getVertex(2).vertexPointIndex].x == 0); rp3d_test(vertices[tetrahedron.getVertex(2).vertexPointIndex].y == -1); rp3d_test(vertices[tetrahedron.getVertex(2).vertexPointIndex].z == 1); rp3d_test(tetrahedron.getHalfEdge(tetrahedron.getVertex(2).edgeIndex).vertexIndex == 2); rp3d_test(vertices[tetrahedron.getVertex(3).vertexPointIndex].x == 0); rp3d_test(vertices[tetrahedron.getVertex(3).vertexPointIndex].y == 1); rp3d_test(vertices[tetrahedron.getVertex(3).vertexPointIndex].z == 0); rp3d_test(tetrahedron.getHalfEdge(tetrahedron.getVertex(3).edgeIndex).vertexIndex == 3); // Test faces for (uint f=0; f<4; f++) { rp3d_test(tetrahedron.getHalfEdge(tetrahedron.getFace(f).edgeIndex).faceIndex == f); } // Test edges for (uint f=0; f<4; f++) { uint edgeIndex = tetrahedron.getFace(f).edgeIndex; const uint firstEdgeIndex = edgeIndex; // For each half-edge of the face for (uint e=0; e<3; e++) { rp3d::HalfEdgeStructure::Edge edge = tetrahedron.getHalfEdge(edgeIndex); rp3d_test(tetrahedron.getHalfEdge(edge.twinEdgeIndex).twinEdgeIndex == edgeIndex); rp3d_test(edge.faceIndex == f); // Go to the next edge edgeIndex = edge.nextEdgeIndex; } rp3d_test(firstEdgeIndex == edgeIndex); } } }; } #endif