crt/camera.cpp
#include "camera.hpp"
#define DOV 10000.0
Camera::Camera(const vertex_t& origin, const vertex_t& direction, unsigned w, unsigned h)
: ray(origin, direction), depth(direction.len()), raster_w((w*2+1)/2), raster_h((h*2+1)/2) {
update_raster();
}
void Camera::update_raster() {
raster_center = ray.origin + ray.direction;
static const vertex_t y_axis(0, 1, 0);
//if (y_axis.dot(ray.direction) >= 0.0) { // orthogonal or acute angle
raster_x = y_axis.crossed(ray.direction);
if (raster_x.nulls() == 3) { // direction was along the y axis
raster_x.x = 1;
}
raster_y = ray.direction.crossed(raster_x);
raster_x.norm();
raster_y.norm();
}
void Camera::get_move(const vertex_t& moveo, ray_t& rv) const {
rv.origin = ray.origin;
rv.direction = (raster_x * moveo.x) + (raster_y * moveo.y) + (ray.direction.normed() * moveo.z);
}
void Camera::move(const vertex_t& moveo, const vertex_t& movel) {
ray.origin += (raster_x * moveo.x) + (raster_y * moveo.y) + (ray.direction.normed() * moveo.z);
ray.direction += (raster_x * movel.x) + (raster_y * movel.y);
ray.direction.norm();
ray.direction *= depth;
update_raster();
}
void Camera::get_ray(unsigned x, unsigned y, ray_t& r, vertex_t& nrm) const {
assert(x < raster_w);
assert(y < raster_h);
#if 1
// from origin through raster
r.origin = ray.origin;
nrm = raster_center + (raster_x * ((int)x-((int)raster_w/2))) + (raster_y * ((int)y-((int)raster_h/2))) - ray.origin;
#else
// start at raster, s.t. we wont see anything between origin and raster and for better box checks
r.origin = raster_center + (raster_x * ((int)x-((int)raster_w/2))) + (raster_y * ((int)y-((int)raster_h/2)));
nrm = r.origin - ray.origin;
#endif
// parallel projection: { raster_center + (raster_x * ((int)x-((int)raster_w/2))) + (raster_y * ((int)y-((int)raster_h/2))), ray.direction }
nrm.norm(); // will be cached
r.direction = nrm * DOV;
}