#include "test_scaffold.h" #include "gp/containers/array.hpp" #include "gp/utils/pair.hpp" #include "gp/math.hpp" #include "gp/math/rendering/renderer.hpp" #include "gp/math/rendering/bmp_viewport.hpp" #include #include #include #include #include #include #include typedef std::mt19937_64 cheap_rand; struct sin_test : public test_scaffold { sin_test() { name = __FILE__ ":1"; } virtual int run() { int res = 0; for(float i = 0; i < 100; i += 0.1) { float v = gp::math::sin(i); float ref = sin(i); res += 0.3 < gp::math::abs(ref - v)*100.0/(gp::math::abs(ref+0.00000001)); } for(float i = 0; i < 100; i += 0.1) { float v = gp::math::cos(i); float ref = cos(i); res += 0.3 < gp::math::abs(ref - v)*100.0/(gp::math::abs(ref+0.00000001)); } for(float i = 0; i < 100; i += 0.1) { float v = gp::math::cos(i)*gp::math::cos(i) + gp::math::sin(i)*gp::math::sin(i); res += 1 + gp_config::rendering::epsilon < v; res += 1 - gp_config::rendering::epsilon > v; } return res; } }; append_test dummy_mldffh6f(new sin_test{}); struct render_test : public test_scaffold { render_test() { name = __FILE__ ":2"; } virtual int run() { using namespace gp::math::rendering; int res = 0; gp::array allocation_buffer; renderer a{allocation_buffer.as_buffer()}; a._resolution = vec2{128,64}; a.passes = 5; a.projection_end = 3; a.sky_box = material_t([](vec3) -> color_t { color_t ret; ret.r() = 0.5; ret.g() = 0.5; ret.b() = 1; ret.a() = 1; return ret; }, a.get_allocator()); auto red = a.materials.push( material_t([&](vec3 p) -> color_t { color_t ret; ret.r() = 1; ret.g() = 0; ret.b() = 0; ret.a() = 1; return ret; }, a.get_allocator()) ); auto green = a.materials.push( material_t([&](vec3 p) -> color_t { color_t ret; ret.r() = 0; ret.g() = 1; ret.b() = 0; ret.a() = 1; return ret; }, a.get_allocator()) ); auto sphere = a.scene_elements.push( sdf_t([&](vec3 pos) -> render_point { auto l_sdf = gp::math::difference_sdf( gp::math::sphere_sdf({0.0,0.0,0.0}, 1.0), gp::math::sphere_sdf({-0.75,0.0,0.0}, 1.0) ); render_point ret; ret.distance = l_sdf(pos); ret.material = red; return ret; }, a.get_allocator()) ); auto sphere2 = a.scene_elements.push( sdf_t([&](vec3 pos) -> render_point { auto l_sdf_b = gp::math::sphere_sdf({-0.75,0.0,0.0}, 0.05); render_point ret; ret.distance = l_sdf_b(pos); ret.material = green; return ret; }, a.get_allocator()) ); a._camera.position = vec3{0, 0, -5}; a._camera.normal = vec3{0, 0, 1}; using pic_color = gp::math::vec4_g; using viewport = gp::bmp_viewport; viewport vp{ {128,64}, viewport::src_t{[&](gp::math::vec2_g p) -> pic_color { auto orig = a.render({(float)p.x,(float)p.y}); pic_color ret{}; ret.x = (uint8_t)(orig.x*255); ret.y = (uint8_t)(orig.y*255); ret.z = (uint8_t)(orig.z*255); ret.w = (uint8_t)(orig.w*255); return ret; }, a.get_allocator()} }; auto buff = std::make_unique>(); auto begin = std::chrono::steady_clock::now(); auto r_end = vp.write(buff->as_buffer()); auto end = std::chrono::steady_clock::now(); std::cout << "render time: " << std::chrono::duration_cast(end - begin).count() << std::endl; auto myfile = std::fstream("render.bmp", std::ios::out | std::ios::binary); myfile.write(buff->begin().data, r_end - buff->begin()); //gp_config::assertion(a.render(vec2{64,32}).x == color_t{1.0,0,0,1.0}.x, "red sphere not perceived"); //gp_config::assertion(a.render(vec2{0,0}).x == color_t{0.0,0,1.0,1.0}.x, "blue sky not perceived"); return res; } }; append_test dummy_pzj6f(new render_test{}); struct function_test : public test_scaffold { function_test() { name = __FILE__ ":3"; } virtual int run() { using namespace gp::math::rendering; int res = 0; gp::array allocation_buffer; gp::buddy<> allocator{allocation_buffer.begin().data, allocation_buffer.size()}; gp::function l_sdf_b{gp::math::sphere_sdf({0.0,0.0,0.0}, 1.0), allocator}; { gp::function sdf{l_sdf_b}; gp_config::assertion(l_sdf_b(vec3(0,0,0)) == -1 && sdf(vec3(0,0,0)) == -1, "Bad sdf"); } return res; } }; append_test dummy_ml8576f(new function_test{}); template struct math_funcs_test : public test_scaffold { uint32_t seed; T low; T high; math_funcs_test(T low = std::numeric_limits::min(), T high = std::numeric_limits::max()) { this->low = low; this->high = high; seed = std::random_device{}(); name = __FILE__ ":4_math_funcs"; name += std::to_string(seed); } virtual int run() { cheap_rand setter(seed); bool result = true; std::uniform_real_distribution dist{low, high}; for(int i = 0 ; i < 10000; i++) { // TODO: Verify things, like, for real gp::pair v{dist(setter), dist(setter)}; gp::pair floorsign{gp::math::floor(v.first), gp::math::sign(v.second)}, sincos{gp::math::sin(v.first), gp::math::cos(v.second)}, isqrt{gp::math::isqrt(v.first), gp::math::fast_isqrt(v.second)}; double tan_v = gp::math::tan(dist(setter)); double sign_v = gp::math::sign(0); result += floorsign.first > v.first; result += gp::math::abs(floorsign.second) == 1; //result = ascending.first == descending.second ? result : false; } return !result; } }; append_test dummy_5qsz5ert443(new math_funcs_test{}); append_test dummy_436z5ert443(new math_funcs_test{}); append_test dummy_mqlsdf123(new math_funcs_test{-10,10}); append_test dummy_mqlsdf456(new math_funcs_test{-10,10});