diff --git a/core/test/processing/core/PShapeOBJTest.java b/core/test/processing/core/PShapeOBJTest.java new file mode 100644 index 000000000..c69843a27 --- /dev/null +++ b/core/test/processing/core/PShapeOBJTest.java @@ -0,0 +1,236 @@ +package processing.core; + +import org.junit.Before; +import org.junit.Test; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import static org.junit.Assert.*; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class PShapeOBJTest { + private PApplet parent; + private ArrayList faces; + private ArrayList materials; + private ArrayList coords; + private ArrayList normals; + private ArrayList texcoords; + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Before + public void setUp() { + parent = new PApplet(); + faces = new ArrayList<>(); + materials = new ArrayList<>(); + coords = new ArrayList<>(); + normals = new ArrayList<>(); + texcoords = new ArrayList<>(); + } + + // Ensure a basic object is parsed correctly - if this fails, something is wrong + @Test + public void testBasicOBJParsing() { + + // Define the data to be parsed + String objData = + "v 0.0 0.0 0.0\n" + + "v 1.0 0.0 0.0\n" + + "v 0.0 1.0 0.0\n" + + "f 1 2 3\n"; + + // Create a buffered reader, and parse the data + BufferedReader reader = new BufferedReader(new StringReader(objData)); + PShapeOBJ.parseOBJ(parent, "", reader, faces, materials, coords, normals, texcoords); + + // Ensure the data was parsed correctly - can be expanded on as needed + assertEquals(3, coords.size()); + assertEquals(1, faces.size()); + assertEquals(3, faces.get(0).vertIdx.size()); + } + + // Ensure a basic material is parsed correctly + @Test + public void testMaterialParsing() throws Exception { + + // Define the data to be parsed + String mtlData = + "newmtl Material1\n" + + "Ka 0.2 0.2 0.2\n" + + "Kd 0.8 0.8 0.8\n" + + "Ks 1.0 1.0 1.0\n" + + "Ns 50.0\n" + + "d 1.0\n"; + + // Create a temporary file with this data + File mtlFile = tempFolder.newFile("test.mtl"); + try (FileWriter writer = new FileWriter(mtlFile)) { + writer.write(mtlData); + } + + // Create a buffered reader with the data, and initialize the materials hash + BufferedReader reader = new BufferedReader(new StringReader(mtlData)); + Map materialsHash = new HashMap<>(); + + // Parse the data + PShapeOBJ.parseMTL(parent, mtlFile.getAbsolutePath(), "", reader, materials, materialsHash); + + // Ensure the data was parsed correctly - can be expanded on as needed + assertEquals(1, materials.size()); + PShapeOBJ.OBJMaterial material = materials.get(0); + assertEquals("Material1", material.name); + assertEquals(0.2f, material.ka.x, 0.001f); + assertEquals(0.8f, material.kd.y, 0.001f); + assertEquals(1.0f, material.ks.z, 0.001f); + assertEquals(50.0f, material.ns, 0.001f); + assertEquals(1.0f, material.d, 0.001f); + } + + // Ensure verticies and normals are parsed correctly for a basic object + @Test + public void testVertexNormalParsing() { + + // Define the data to be parsed + String objData = + "v 0.0 0.0 0.0\n" + + "v 1.0 0.0 0.0\n" + + "v 0.0 1.0 0.0\n" + + "vn 0.0 0.0 1.0\n" + + "vn 0.0 1.0 0.0\n" + + "vn 1.0 0.0 0.0\n" + + "f 1//1 2//2 3//3\n"; + + // Create a buffered reader, and parse the data + BufferedReader reader = new BufferedReader(new StringReader(objData)); + PShapeOBJ.parseOBJ(parent, "", reader, faces, materials, coords, normals, texcoords); + + // Ensure the data was parsed correctly - can be expanded on as needed + assertEquals(3, normals.size()); + assertEquals(3, faces.get(0).normIdx.size()); + } + + // Ensure parsing properly handles texture coordinates as well + @Test + public void testTextureCoordinateParsing() { + + // Define the data to be parsed + String objData = + "v 0.0 0.0 0.0\n" + + "v 1.0 0.0 0.0\n" + + "v 0.0 1.0 0.0\n" + + "vt 0.0 0.0\n" + + "vt 1.0 0.0\n" + + "vt 0.0 1.0\n" + + "f 1/1 2/2 3/3\n"; + // Create a buffered reader with the data, and parse the data + BufferedReader reader = new BufferedReader(new StringReader(objData)); + PShapeOBJ.parseOBJ(parent, "", reader, faces, materials, coords, normals, texcoords); + + // Ensure the data was parsed correctly - can be expanded on as needed + assertEquals(3, texcoords.size()); + assertEquals(3, faces.get(0).texIdx.size()); + } + + // Ensure conversion from PVector to 32-bit color int works correctly + @Test + public void testRGBAValueConversion() { + + // Define the PVector color + PVector color = new PVector(1.0f, 0.5f, 0.0f); + + // Convert to 32-bit color int + int rgba = PShapeOBJ.rgbaValue(color); + + // Ensure the conversion was correct - note alpha is always 0xFF here + assertEquals(0xFF, (rgba >> 24) & 0xFF); // A + assertEquals(0xFF, (rgba >> 16) & 0xFF); // R + assertEquals(0x7F, (rgba >> 8) & 0xFF); // G + assertEquals(0x00, rgba & 0xFF); // B + } + + // Ensure conversion from PVector to 32-bit color int (with alpha) works correctly + @Test + public void testRGBAValueConversionWithAlpha() { + + // Define the PVector color, and alpha + PVector color = new PVector(1.0f, 0.5f, 0.0f); + float alpha = 0.5f; + + //Convert to 32-bit color int + int rgba = PShapeOBJ.rgbaValue(color, alpha); + + // Ensure the conversion was correct + assertEquals(0x7F, (rgba >> 24) & 0xFF); // A + assertEquals(0xFF, (rgba >> 16) & 0xFF); // R + assertEquals(0x7F, (rgba >> 8) & 0xFF); // G + assertEquals(0x00, rgba & 0xFF); // B + } + + // Ensure a newly-created OBJFace is initialized correctly + @Test + public void testOBJFaceCreation() { + + // Create the empty OBJFace + PShapeOBJ.OBJFace face = new PShapeOBJ.OBJFace(); + + // Verify attributes are initialized correctly - can be expanded on as needed + assertTrue(face.vertIdx.isEmpty()); + assertTrue(face.texIdx.isEmpty()); + assertTrue(face.normIdx.isEmpty()); + assertEquals(-1, face.matIdx); + assertEquals("", face.name); + } + + // Ensure a newly-created OBJFace is initialized correctly + @Test + public void testOBJMaterialCreation() { + + // Create the empty OBJMaterial + PShapeOBJ.OBJMaterial material = new PShapeOBJ.OBJMaterial("TestMaterial"); + + // Verify attributes are initialized correctly - can be expanded on as needed + assertEquals("TestMaterial", material.name); + assertEquals(0.5f, material.ka.x, 0.001f); + assertEquals(0.5f, material.kd.y, 0.001f); + assertEquals(0.5f, material.ks.z, 0.001f); + assertEquals(1.0f, material.d, 0.001f); + assertEquals(0.0f, material.ns, 0.001f); + assertNull(material.kdMap); + } + + // After previous tests, ensure a more complex shape, with verticies, materials, and normals is parsed correctly + @Test + public void testComplexFaceParsing() { + + // Define the data to be parsed + String objData = + "v 0.0 0.0 0.0\n" + + "v 1.0 0.0 0.0\n" + + "v 0.0 1.0 0.0\n" + + "v 1.0 1.0 0.0\n" + + "vt 0.0 0.0\n" + + "vt 1.0 0.0\n" + + "vt 0.0 1.0\n" + + "vt 1.0 1.0\n" + + "vn 0.0 0.0 1.0\n" + + "f 1/1/1 2/2/1 3/3/1 4/4/1\n"; + + // Create a buffered reader with the data, and parse the data + BufferedReader reader = new BufferedReader(new StringReader(objData)); + PShapeOBJ.parseOBJ(parent, "", reader, faces, materials, coords, normals, texcoords); + + // Ensure the data was parsed correctly - can be expanded on as needed + assertEquals(1, faces.size()); + PShapeOBJ.OBJFace face = faces.get(0); + assertEquals(4, face.vertIdx.size()); + assertEquals(4, face.texIdx.size()); + assertEquals(4, face.normIdx.size()); + } +} \ No newline at end of file