/** * @file main.cpp * @brief Phase 2 verification program */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace are; // Test result tracking struct TestResult { std::string name; bool passed; std::string message; }; std::vector test_results; void report_test(const std::string& name, bool passed, const std::string& message = "") { test_results.push_back({name, passed, message}); if (passed) { ARE_LOG_INFO("✓ " + name); } else { ARE_LOG_ERROR("✗ " + name + ": " + message); } } // Test 1: Vertex operations void test_vertex() { Vertex v1(Vec3(1, 2, 3)); Vertex v2(Vec3(4, 5, 6), Vec3(0, 1, 0)); Vertex v3 = Vertex::lerp(v1, v2, 0.5f); bool passed = glm::length(v3.position_ - Vec3(2.5f, 3.5f, 4.5f)) < are_epsilon; report_test("Vertex interpolation", passed); } // Test 2: AABB operations void test_aabb() { AABB aabb1(Vec3(-1, -1, -1), Vec3(1, 1, 1)); AABB aabb2(Vec3(0, 0, 0), Vec3(2, 2, 2)); bool test1 = aabb1.is_valid(); bool test2 = aabb1.contains(Vec3(0, 0, 0)); bool test3 = aabb1.intersects(aabb2); bool test4 = aabb1.longest_axis() == 0; // All axes equal AABB merged = AABB::merge(aabb1, aabb2); bool test5 = merged.contains(Vec3(-1, -1, -1)) && merged.contains(Vec3(2, 2, 2)); report_test("AABB validity", test1); report_test("AABB contains point", test2); report_test("AABB intersection", test3); report_test("AABB merge", test5); } // Test 3: Triangle operations void test_triangle() { Vertex v0(Vec3(0, 0, 0), Vec3(0, 0, 1)); Vertex v1(Vec3(1, 0, 0), Vec3(0, 0, 1)); Vertex v2(Vec3(0, 1, 0), Vec3(0, 0, 1)); Triangle tri(v0, v1, v2); Vec3 centroid = tri.centroid(); bool test1 = glm::length(centroid - Vec3(1.0f/3.0f, 1.0f/3.0f, 0.0f)) < are_epsilon; Vec3 normal = tri.normal(); bool test2 = glm::length(normal - Vec3(0, 0, 1)) < are_epsilon; Real area = tri.area(); bool test3 = std::abs(area - 0.5f) < are_epsilon; AABB aabb = tri.compute_aabb(); bool test4 = aabb.contains(Vec3(0, 0, 0)) && aabb.contains(Vec3(1, 0, 0)); report_test("Triangle centroid", test1); report_test("Triangle normal", test2); report_test("Triangle area", test3); report_test("Triangle AABB", test4); } // Test 4: Ray-Triangle intersection void test_ray_triangle_intersection() { Vertex v0(Vec3(0, 0, 0), Vec3(0, 0, 1)); Vertex v1(Vec3(1, 0, 0), Vec3(0, 0, 1)); Vertex v2(Vec3(0, 1, 0), Vec3(0, 0, 1)); Triangle tri(v0, v1, v2); // Ray hitting the triangle Ray ray1(Vec3(0.25f, 0.25f, -1.0f), Vec3(0, 0, 1)); HitRecord hit1; bool test1 = tri.intersect(ray1, hit1); // Ray missing the triangle Ray ray2(Vec3(2, 2, -1), Vec3(0, 0, 1)); HitRecord hit2; bool test2 = !tri.intersect(ray2, hit2); report_test("Ray-Triangle hit", test1); report_test("Ray-Triangle miss", test2); } // Test 5: Transform operations void test_transform() { Transform t1 = Transform::translate(Vec3(1, 2, 3)); Transform t2 = Transform::rotate(Vec3(0, are_pi / 2, 0)); Transform t3 = Transform::scale(Vec3(2, 2, 2)); Vec3 point = Vec3(1, 0, 0); Vec3 transformed = t1.transform_point(point); bool test1 = glm::length(transformed - Vec3(2, 2, 3)) < are_epsilon; Vec3 scaled = t3.transform_point(point); bool test2 = glm::length(scaled - Vec3(2, 0, 0)) < are_epsilon; report_test("Transform translation", test1); report_test("Transform scale", test2); } // Test 6: Camera operations void test_camera() { Camera camera(Vec3(0, 0, 5), Vec3(0, 0, 0)); camera.set_perspective(45.0f, 16.0f / 9.0f, 0.1f, 100.0f); Vec3 forward = camera.get_forward(); bool test1 = glm::length(forward - Vec3(0, 0, -1)) < are_epsilon; Vec3 origin, direction; camera.generate_ray(0.5f, 0.5f, origin, direction); bool test2 = glm::length(origin - Vec3(0, 0, 5)) < are_epsilon; bool test3 = glm::length(direction - Vec3(0, 0, -1)) < 0.1f; // Approximate report_test("Camera forward vector", test1); report_test("Camera ray generation origin", test2); report_test("Camera ray generation direction", test3); } // Test 7: Mesh operations void test_mesh() { std::vector vertices = { Vertex(Vec3(0, 0, 0), Vec3(0, 0, 1)), Vertex(Vec3(1, 0, 0), Vec3(0, 0, 1)), Vertex(Vec3(0, 1, 0), Vec3(0, 0, 1)) }; std::vector indices = {0, 1, 2}; Mesh mesh(vertices, indices); bool test1 = mesh.get_vertex_count() == 3; bool test2 = mesh.get_triangle_count() == 1; bool test3 = mesh.get_aabb().is_valid(); Vertex v0, v1, v2; bool test4 = mesh.get_triangle(0, v0, v1, v2); report_test("Mesh vertex count", test1); report_test("Mesh triangle count", test2); report_test("Mesh AABB", test3); report_test("Mesh get triangle", test4); } // Test 8: Material operations void test_material() { Material mat; mat.set_albedo(Vec3(0.8f, 0.2f, 0.1f)); mat.set_metallic(0.5f); mat.set_roughness(0.3f); mat.set_emissive(Vec3(1.0f, 0.5f, 0.0f)); bool test1 = glm::length(mat.get_albedo() - Vec3(0.8f, 0.2f, 0.1f)) < are_epsilon; bool test2 = std::abs(mat.get_metallic() - 0.5f) < are_epsilon; bool test3 = mat.is_emissive(); mat.set_albedo_map("textures/albedo.png"); bool test4 = mat.has_albedo_map(); report_test("Material albedo", test1); report_test("Material metallic", test2); report_test("Material emissive", test3); report_test("Material texture map", test4); } // Test 9: Light operations void test_lights() { // Directional light DirectionalLight dir_light(Vec3(0, -1, 0), Vec3(1, 1, 1), 1.0f); bool test1 = dir_light.affects_point(Vec3(100, 100, 100)); // Point light PointLight point_light(Vec3(0, 0, 0), Vec3(1, 1, 1), 1.0f, 10.0f); bool test2 = point_light.affects_point(Vec3(5, 0, 0)); bool test3 = !point_light.affects_point(Vec3(20, 0, 0)); // Spot light SpotLight spot_light(Vec3(0, 0, 0), Vec3(0, 0, -1), 30.0f, 45.0f); bool test4 = spot_light.affects_point(Vec3(0, 0, -5)); report_test("Directional light affects all points", test1); report_test("Point light range (inside)", test2); report_test("Point light range (outside)", test3); report_test("Spot light cone", test4); } // Test 10: SceneManager operations void test_scene_manager() { SceneManager scene; // Add mesh std::vector vertices = { Vertex(Vec3(0, 0, 0)), Vertex(Vec3(1, 0, 0)), Vertex(Vec3(0, 1, 0)) }; std::vector indices = {0, 1, 2}; Mesh mesh(vertices, indices); MeshHandle mesh_handle = scene.add_mesh(mesh); bool test1 = mesh_handle != are_invalid_handle; bool test2 = scene.get_mesh_count() == 1; // Add material Material mat; MaterialHandle mat_handle = scene.add_material(mat); bool test3 = mat_handle != are_invalid_handle; bool test4 = scene.get_material_count() == 1; // Add light auto light = std::make_shared(); LightHandle light_handle = scene.add_light(light); bool test5 = light_handle != are_invalid_handle; bool test6 = scene.get_light_count() == 1; // Test dirty flag bool test7 = scene.is_dirty(); scene.clear_dirty(); bool test8 = !scene.is_dirty(); // Remove mesh scene.remove_mesh(mesh_handle); bool test9 = scene.get_mesh_count() == 0; report_test("SceneManager add mesh", test1); report_test("SceneManager mesh count", test2); report_test("SceneManager add material", test3); report_test("SceneManager material count", test4); report_test("SceneManager add light", test5); report_test("SceneManager light count", test6); report_test("SceneManager dirty flag (set)", test7); report_test("SceneManager dirty flag (clear)", test8); report_test("SceneManager remove mesh", test9); } int main() { // Initialize logger Logger::init(LogLevel::ARE_LOG_INFO); ARE_LOG_INFO("========================================"); ARE_LOG_INFO("Phase 2 Verification Program"); ARE_LOG_INFO("========================================"); // Run all tests test_vertex(); test_aabb(); test_triangle(); test_ray_triangle_intersection(); test_transform(); test_camera(); test_mesh(); test_material(); test_lights(); test_scene_manager(); // Print summary ARE_LOG_INFO("========================================"); ARE_LOG_INFO("Test Summary"); ARE_LOG_INFO("========================================"); int passed = 0; int failed = 0; for (const auto& result : test_results) { if (result.passed) { ++passed; } else { ++failed; } } ARE_LOG_INFO("Total tests: " + std::to_string(test_results.size())); ARE_LOG_INFO("Passed: " + std::to_string(passed)); ARE_LOG_INFO("Failed: " + std::to_string(failed)); if (failed == 0) { ARE_LOG_INFO("========================================"); ARE_LOG_INFO("✓ All Phase 2 tests passed!"); ARE_LOG_INFO("========================================"); } else { ARE_LOG_ERROR("========================================"); ARE_LOG_ERROR("✗ Some tests failed. Please review."); ARE_LOG_ERROR("========================================"); } Logger::shutdown(); return failed == 0 ? 0 : 1; }