diff --git a/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..48783891ba4230f25a6666bc8b4d1ecf9a12c1b5 --- /dev/null +++ b/MeshModel/src/test/java/cz/fidentis/analyst/mesh/io/MeshObjLoaderTest.java @@ -0,0 +1,200 @@ +package cz.fidentis.analyst.mesh.io; + +import com.mokiat.data.front.parser.IOBJParser; +import com.mokiat.data.front.parser.OBJDataReference; +import com.mokiat.data.front.parser.OBJFace; +import com.mokiat.data.front.parser.OBJMesh; +import com.mokiat.data.front.parser.OBJModel; +import com.mokiat.data.front.parser.OBJNormal; +import com.mokiat.data.front.parser.OBJObject; +import com.mokiat.data.front.parser.OBJParser; +import com.mokiat.data.front.parser.OBJTexCoord; +import com.mokiat.data.front.parser.OBJVertex; +import cz.fidentis.analyst.mesh.core.MeshFacet; +import cz.fidentis.analyst.mesh.core.MeshModel; +import cz.fidentis.analyst.mesh.core.MeshPoint; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.vecmath.Vector3d; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Tests for {@link cz.fidentis.analyst.mesh.io.MeshObjLoader} + * @author Marek Barinka; 456295 + */ +public class MeshObjLoaderTest { + + Path testFileDirectory = Paths.get("src", "test", "resources", "cz", "fidentis", "analyst", "mesh", "io"); + + @Test + void nullFileTest() throws IOException { + Exception ex = assertThrows(NullPointerException.class, () -> MeshObjLoader.read((File) null)); + } + + @Test + void nullStreamTest() throws IOException { + Exception ex = assertThrows(NullPointerException.class, () -> MeshObjLoader.read((InputStream) null)); + } + + @Test() + void emptyFileTest() throws IOException { + File empty = new File(testFileDirectory.toFile(), "Empty.obj"); + Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(empty)); + assertTrue(ex.getMessage().contains("File doesn't contain any model")); + } + + @Test + void moreObjectFileTest() { //TODO: Not testing in loader + File moreObjects = new File(testFileDirectory.toFile(), "MoreObjects.obj"); + Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(moreObjects)); + } + + @Test + void nonTriangularFaceAloneTest() { + File plane = new File(testFileDirectory.toFile(), "Plane.obj"); + Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(plane)); + assertTrue(ex.getMessage().contains("Mesh contains non-triangular face")); + } + + @Test + void nonTriangularFaceInTriangularModelTest() { + File icoSphereQuad = new File(testFileDirectory.toFile(), "IcoSphere-withQuad.obj"); + Exception ex = assertThrows(IOException.class, () -> MeshObjLoader.read(icoSphereQuad)); + assertTrue(ex.getMessage().contains("Mesh contains non-triangular face")); + } + + @Test + void validFileIcoSphereTest() throws IOException { + File icoSphere = new File(testFileDirectory.toFile(), "IcoSphere-Triangles.obj"); + MeshModel m = MeshObjLoader.read(icoSphere); + assertEquals(m.getFacets().get(0).getCornerTable().getSize(), 240); + assertEquals(m.getFacets().get(0).getNumberOfVertexes(), 240); + assertEquals(m.getFacets().size(), 1); + + OBJModel model; + final IOBJParser parser = new OBJParser(); + try (InputStream is = new FileInputStream(icoSphere)) { + model = parser.parse(is); + } + + OBJObject object = model.getObjects().get(0); + Set<MeshPoint> points = getPointsInObject(model, object); + + MeshFacet facet = m.getFacets().get(0); + for (int i = 0; i < facet.getNumberOfVertexes(); i++) { + MeshPoint p = facet.getVertex(i); + assertTrue(points.contains(p)); + } + } + + @Test + void validStreamTest() throws FileNotFoundException, IOException { + File icoSphere = new File(testFileDirectory.toFile(), "IcoSphere-Triangles.obj"); + MeshModel m; + try(InputStream is = new FileInputStream(icoSphere)) { + m = MeshObjLoader.read(is); + } + assertEquals(m.getFacets().get(0).getCornerTable().getSize(), 240); + assertEquals(m.getFacets().get(0).getNumberOfVertexes(), 240); + assertEquals(m.getFacets().size(), 1); + + OBJModel model; + final IOBJParser parser = new OBJParser(); + try (InputStream is = new FileInputStream(icoSphere)) { + model = parser.parse(is); + } + + OBJObject object = model.getObjects().get(0); + Set<MeshPoint> points = getPointsInObject(model, object); + + MeshFacet facet = m.getFacets().get(0); + for (int i = 0; i < facet.getNumberOfVertexes(); i++) { + MeshPoint p = facet.getVertex(i); + assertTrue(points.contains(p)); + } + } + + @Test + void validFileTetrahedronTest() throws IOException { + File tetrahedron = new File(testFileDirectory.toFile(), "tetrahedron.obj"); + MeshModel m = MeshObjLoader.read(tetrahedron); + assertEquals(m.getFacets().get(0).getCornerTable().getSize(), 12); + assertEquals(m.getFacets().get(0).getNumberOfVertexes(), 12); + assertEquals(m.getFacets().size(), 1); + + OBJModel model; + final IOBJParser parser = new OBJParser(); + try (InputStream is = new FileInputStream(tetrahedron)) { + model = parser.parse(is); + } + + OBJObject object = model.getObjects().get(0); + Set<MeshPoint> points = getPointsInObject(model, object); + + MeshFacet facet = m.getFacets().get(0); + for (int i = 0; i < facet.getNumberOfVertexes(); i++) { + MeshPoint p = facet.getVertex(i); + assertTrue(points.contains(p)); + } + } + + + @Test + void validFileIco20Test() throws IOException { + File ico20 = new File(testFileDirectory.toFile(), "IcoSphere-20.obj"); + MeshModel m = MeshObjLoader.read(ico20); + assertEquals(m.getFacets().get(0).getCornerTable().getSize(), 60); + assertEquals(m.getFacets().get(0).getNumberOfVertexes(), 60); + assertEquals(m.getFacets().size(), 1); + + OBJModel model; + final IOBJParser parser = new OBJParser(); + try (InputStream is = new FileInputStream(ico20)) { + model = parser.parse(is); + } + + OBJObject object = model.getObjects().get(0); + Set<MeshPoint> points = getPointsInObject(model, object); + + MeshFacet facet = m.getFacets().get(0); + for (int i = 0; i < facet.getNumberOfVertexes(); i++) { + MeshPoint p = facet.getVertex(i); + assertTrue(points.contains(p)); + } + } + + private Set<MeshPoint> getPointsInObject(OBJModel model, OBJObject object) { + Set<MeshPoint> points = new HashSet(); + for (OBJMesh mesh : object.getMeshes()) { + for (OBJFace face : mesh.getFaces()) { + for (OBJDataReference reference : face.getReferences()) { + final OBJVertex vertex = model.getVertex(reference); + Vector3d coords = new Vector3d(vertex.x, vertex.y, vertex.z); + Vector3d norm = null; + Vector3d texCoords = null; + if (reference.hasNormalIndex()) { + final OBJNormal normal = model.getNormal(reference); + norm = new Vector3d(normal.x, normal.y, normal.z); + } + if (reference.hasTexCoordIndex()) { + final OBJTexCoord texCoord = model.getTexCoord(reference); + texCoords = new Vector3d(texCoord.u, texCoord.v, texCoord.w); + } + points.add(new MeshPoint(coords, norm, texCoords)); + } + } + } + return points; + } +}