#include <pangolin/geometry/geometry.h>
#include <pangolin/geometry/glgeometry.h>
#include <pangolin/pangolin.h>

#include <Eigen/Core>

class SurfaceRendererState {
   public:
    std::vector<Eigen::Vector3f> views;
    std::vector<Eigen::Vector4f> face_normal_test;
    std::vector<bool> invisible_face_test;
    std::vector<bool> observed_backface_test;
    std::vector<int> face_observation_count;
    std::vector<Eigen::Vector4f> observed_normals;
    std::vector<Eigen::Vector4f> observed_points;
    std::vector<int> observed_points_view_index;
    SurfaceRendererState(int total_num_faces, int num_viewpoints,
                         float view_distance);
};

class SurfaceRenderer {
   private:
    int _width;
    int _height;
    pangolin::OpenGlRenderState _camera;
    pangolin::GlGeometry _geometry;

   public:
    SurfaceRenderer(pangolin::Geometry& geometry, int width, int height,
                    float camera_distance);
    void render(SurfaceRendererState& state, pangolin::GlSlProgram& program,
                pangolin::GlTexture& texture_normals,
                pangolin::GlTexture& texture_vertices,
                pangolin::GlFramebuffer& frame_buffer);
    void render_from_view(int view_index, Eigen::Vector3f& view,
                          pangolin::GlSlProgram& program,
                          pangolin::GlTexture& texture_normals,
                          pangolin::GlTexture& texture_vertices,
                          pangolin::GlFramebuffer& frame_buffer,
                          pangolin::TypedImage& image_normals,
                          pangolin::TypedImage& image_vertices,
                          std::vector<Eigen::Vector4f>& observed_normals,
                          std::vector<Eigen::Vector4f>& observed_points,
                          std::vector<int>& observed_points_view_index,
                          std::vector<Eigen::Vector4f>& face_normal_test,
                          std::vector<bool>& invisible_face_test,
                          std::vector<bool>& observed_backface_test,
                          std::vector<int>& face_observation_count);
};