
#include <cstdio>
#include <cmath>
#include <cfloat>

#include "vec.h"
#include "mat.h"
#include "mesh.h"
#include "wavefront.h"
#include "image.h"
#include "image_io.h"
#include "orbiter.h"

#include "bvh.h"


int main( int argc, char **argv )
{
    const char *file= "geometry.obj";
    if(argc > 1) file= argv[1];
    
    Mesh mesh= read_mesh(file);
    if(mesh == Mesh::error())
        return 1;
    
    Orbiter camera= read_orbiter("orbiter.txt");
    
    BVH bvh= make_bvh(mesh.positions);

    release_mesh(mesh);
    
    // go
    Image image(1024, 640);
    
    Point d0;
    Vector dx, dy;
    Point o= orbiter_position(camera);
    orbiter_image_frame(camera, image.width(), image.height(), 1, 45, d0, dx, dy);
    
#pragma omp parallel for schedule(dynamic, 16)
    for(int y= 0; y < image.height(); y++)
    for(int x= 0; x < image.width(); x++)
    {
        Point e= d0 + (float) x * dx + (float) y * dy;
        Ray ray= make_ray(o, e);
        
        Hit hit;
        if(intersect(bvh, ray, FLT_MAX, hit))
        {
            Color color= make_white();
            color= make_color( std::abs(ray.direction.x), std::abs(ray.direction.y), std::abs(ray.direction.z) );
            float cos_theta= std::abs(dot(hit.n, normalize(make_vector(hit.p, o))) );
            
            Hit mhit;
            Ray mray= reflect(ray, hit.p, hit.n);
            //~ Ray tray;
            //~ if(refract(ray, hit.p, hit.n, 1.5f, tray))
                
            //~ if(intersect(bvh, tray, FLT_MAX, mhit))
            //~ if(intersect(bvh, mray, FLT_MAX, mhit))
                //~ color= make_color( std::abs(mray.direction.x), std::abs(mray.direction.y), std::abs(mray.direction.z) );
                //~ color= make_color( std::abs(mhit.n.x), std::abs(mhit.n.y), std::abs(mhit.n.z) ) * fresnel(mray, hit.p, hit.n, 1.5f);
            
            image(x, y)= Color(color * cos_theta, 1);
        }
    }
    
    printf("triangles %lu %f/ray, boxes %lu %f/ray\n", tri_n, (float) tri_n / (float) image.size(), box_n, (float) box_n / (float) image.size());
    
    write_image(image, "render.png");
    return 0;
}
