#pragma once
#include <list>
#include "thread.hpp"
#include "vertex.hpp"
class Object;
class Texture;
class PointLight;
/**
* @brief Translate raster/pixel coordinates into rays from camera through viewport onto scene.
*
* Camera/viewport rays are precomputed and only need to be translated to the current camera position.
* The viewport determines the FOV. The z-distance camera and viewport determines the DOV.
*/
class ZViewport {
public:
/** @brief Convenience aggregate to pass along the relevant basic settings. */
struct viewport_spec_t {
vertex_t raster;
vertex_t viewport; // width, height, z dist
fcoord_t camera_z;
res_t resolution;
};
private:
const viewport_spec_t config;
Buffer2D<ray_t> ray_cache; ///< precomputed rays for (camera ->) viewport -> z-axis
vertex_t camera; // updated upon movement
ray_t precompute_ray(fcoord_t u, fcoord_t v) const;
public:
ZViewport(const ZViewport::viewport_spec_t&);
const ZViewport::viewport_spec_t& get_config() const;
void update(vertex_t camera);
const vertex_t& get_camera() const;
/** @brief Raster coordinates to scene tracing ray. */
ray_t get_projected_ray(dcoord_t x, dcoord_t y) const;
/** @brief Volume that could intersect any projected ray according to current camera and viewport. */
box_t get_viewbox(const area_t&) const;
};
/** @brief Per-pixel @ref Object intersection hit as @ref Tracer result. */
struct trace_px_t {
const Object* obj;
vertex_t hit;
vertex_t nrm;
const Texture* tex;
uv_t uv;
};
/**
* @brief Current position, radius, and (possibly reduced) volume of a @ref PointLight.
* @see LightStack
* @see box_t::cut_down()
*/
struct lightbox_t {
const PointLight* light;
disc_t rad;
box_t box;
};
/** @brief Part of the scene for local parallel processing using the @ref ThreadPool. */
struct sub_frame_t {
area_t viewport; // start/end box
std::list<const Object*> visible_scene;
std::list<const Object*> effective_scene;
std::list<lightbox_t> effective_lights; //< dynamic lights
};
/** @brief Main frame datastructure, passed along the tracer pipeline.*/
struct context_t {
Timer timer; ///< measure time it takes to pass the pipeline
ZViewport viewport; ///< camera, viewport, rays
std::array<sub_frame_t, 4> corners; ///< local information for each @ref ThreadPool thread
Buffer2D<trace_px_t> trace_info; ///< filled by @ref Tracer, consumed by @ref LightTracer and @ref Renderer
Buffer2D<vertex_t> light_info; ///< filled by @ref LightTracer, consumed by @ref Renderer
context_t(const ZViewport::viewport_spec_t&);
};
/** @brief Single @ref context_t factory for caching and ownership. */
class ContextFactory : public PtrCache<context_t> {
private:
const ZViewport::viewport_spec_t viewport;
protected:
std::unique_ptr<context_t> make() override;
public:
ContextFactory(const ZViewport::viewport_spec_t& viewport);
};