此是所有采样的基类,这样定义的好处是,我们可以分别测试每一个采样算法。
类定义:
#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;
}