针孔相机,带旋转,移动等功能。
类声明:
#pragma once #ifndef __PINHOLE_HEADER__ #define __PINHOLE_HEADER__ #include "camera.h" class Pinhole :public Camera { public: Pinhole(); ~Pinhole(); Pinhole(const Pinhole& ph); void set_view_distance(const ldouble a); void set_zoom(const ldouble factor); void set_angle(const ldouble deg); Vector3 ray_direction(const Point3& p) const; virtual Camera* clone() const; virtual void render_scene(World& w); Pinhole& operator=(const Pinhole& ph); private: ldouble d, zoom; }; #endif
类实现:
#include "pch.h" #include "pinhole.h" #include "../utilities/world.h" #include "../utilities/viewplane.h" #include "../samplers/sampler.h" #include "../tracers/tracer.h" Pinhole::Pinhole() :Camera(), d(1), zoom(1) {} Pinhole::Pinhole(const Pinhole& ph) : Camera(ph), d(ph.d), zoom(ph.zoom) {} Pinhole::~Pinhole() {} void Pinhole::set_view_distance(const ldouble a) { d = a; } void Pinhole::set_zoom(const ldouble factor) { zoom = factor; } void Pinhole::set_angle(const ldouble deg) { ldouble rad = radian(deg); up = Point3(std::cos(rad) * up.x - std::sin(rad) * up.y, std::sin(rad) * up.x + std::cos(rad) * up.y, up.z);//绕z轴旋转 } Vector3 Pinhole::ray_direction(const Point3& p) const{ Vector3 dir = p.x * u + p.y * v - w / d;//书中这里是错误的 dir.normalize(); return dir; } Camera* Pinhole::clone() const { return new Pinhole(*this); } void Pinhole::render_scene(World& w) { ViewPlane vp(w.vp); Ray ray; integer depth = 0; Point3 sp, pp; w.open_window(vp.hres, vp.vres); vp.s = 1 / (zoom * vp.s); ray.o = eye; for (integer r = vp.vres - 1; r >= 0; r--)//render from left-corner to right-corner for (integer c = 0; c < vp.hres; c++) { RGBColor color; for (integer p = 0; p < vp.nsamples; p++) { sp = vp.sampler->sample_unit_square(); pp.x = (c - 0.5 * vp.hres + sp.x) * vp.s; pp.y = (r - 0.5 * vp.vres + sp.y) * vp.s; ray.d = ray_direction(pp); color += w.tracer_ptr->trace_ray(ray); } color /= vp.nsamples; color *= exposure_time; w.display_pixel(r, c, color); } } Pinhole& Pinhole::operator=(const Pinhole& ph) { if (this == &ph) return *this; Camera::operator= (ph); d = ph.d; zoom = ph.zoom; return *this; }
需要修改的World类:
class World { public: World(); World(const World& wr); ~World(); void build(); void render(); ... void open_window(const integer hres, const integer vres); void display_pixel(const integer row, const integer column, const RGBColor& color); void set_camera(Camera* const cam_ptr);//新加 ViewPlane vp; Tracer* tracer_ptr; private: std::stringstream ss; std::vector<Geometrics*> objects; RGBColor backgrd_color; Camera* camera_ptr;//新加 };
实现代码修改:
void World::build() { vp.set_hres(200); vp.set_vres(100); vp.set_sampler(new Hammersley()); vp.sampler->map_to_sphere(); tracer_ptr = new MultiSphere(this); Geometrics* obj = new Sphere(0, 0.5); obj->set_color(RGBColor(1, 0, 0)); add_object(obj); obj = new Sphere(Point3(0, -100.5, 0), 100); obj->set_color(RGBColor(0, 0, 1)); add_object(obj); Pinhole* pinhole = new Pinhole(); pinhole->set_eye(Point3(0, 0, 1)); pinhole->set_lookat(Point3(0)); pinhole->set_view_distance(1.5);//视距测试 pinhole->set_angle(-45);//旋转测试 //pinhole->set_zoom(2.0);//缩放测试 pinhole->compute_uvw(); set_camera(pinhole); } void World::render() { camera_ptr->render_scene(*this); }
测试效果图(左旋转45度图):