此是所有采样的基类,这样定义的好处是,我们可以分别测试每一个采样算法。
类定义:
#pragma once #ifndef __SAMPLER_HEADER__ #define __SAMPLER_HEADER__ #include "../utilities/geometry.h" class Sampler { public: Sampler(); virtual ~Sampler(); Sampler(const integer samps); Sampler(const integer samps, const integer sets); Sampler(const Sampler& s); virtual Sampler* clone() const = 0; virtual void generate_samples() = 0;//这个设置为纯虚函数,书中没有这样做,我们这样做是方便之后动态调整采样数量 virtual Point3 sample_unit_square(); void setup_shuffled_indices(); void set_num_sets(const integer sets); integer get_num_sets() const; void set_num_samples(const integer samps); integer get_num_samples() const; void clear(); Sampler& operator=(const Sampler& s); protected: integer nsamples; integer nsets; std::vector<Point3> samples;//这里采用Point3,兼容所有的采样算法 std::vector<integer> shuffled_indices; integer count; integer jump; }; #endif
类实现:
#include "pch.h" #include "sampler.h" Sampler::Sampler() :nsamples(16), nsets(36), count(0), jump(0) { setup_shuffled_indices(); } Sampler::~Sampler() {} Sampler::Sampler(const integer samps) : nsamples(samps), nsets(36), count(0), jump(0) { setup_shuffled_indices(); } Sampler::Sampler(const integer samps, const integer sets) : nsamples(samps), nsets(sets), count(0), jump(0) { setup_shuffled_indices(); } Sampler::Sampler(const Sampler& s) : nsamples(s.nsamples), nsets(s.nsets), count(s.count), jump(s.jump), samples(s.samples), shuffled_indices(s.shuffled_indices) {} Point3 Sampler::sample_unit_square() { if (count % nsamples == 0) jump = (random_integer() % nsets) * nsamples; return (samples[jump + shuffled_indices[jump + count++ % nsamples]]); } void Sampler::setup_shuffled_indices() { shuffled_indices.reserve(nsamples * nsets); std::vector<integer> indices; for (integer i = 0; i < nsamples; i++) indices.push_back(i); for (integer i = 0; i < nsets; i++) { random_shuffle(indices.begin(), indices.end()); shuffled_indices.insert(shuffled_indices.end(), indices.begin(), indices.end()); } } void Sampler::set_num_sets(const integer sets) { nsets = sets; } integer Sampler::get_num_sets() const { return nsets; } void Sampler::set_num_samples(const integer samps) { nsamples = samps; } integer Sampler::get_num_samples() const { return nsamples; } void Sampler::clear() { shuffled_indices.resize(0); samples.resize(0); count = jump = 0; } Sampler& Sampler::operator=(const Sampler& s) { if (this == &s) return *this; nsamples = s.nsamples; nsets = s.nsets; count = s.count; jump = s.jump; samples = s.samples; shuffled_indices = s.shuffled_indices; return *this; }