Skip to content

Commit

Permalink
Add random sampler interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
tatsy committed Aug 18, 2015
1 parent ae95dab commit 0c9974d
Show file tree
Hide file tree
Showing 22 changed files with 312 additions and 99 deletions.
4 changes: 3 additions & 1 deletion src/random/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/random.cc
${CMAKE_CURRENT_LIST_DIR}/halton.cc
${CMAKE_CURRENT_LIST_DIR}/random_sampler.cc
PARENT_SCOPE)

set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/random_base.h
${CMAKE_CURRENT_LIST_DIR}/random.h
${CMAKE_CURRENT_LIST_DIR}/halton.h
${CMAKE_CURRENT_LIST_DIR}/random_base.h
${CMAKE_CURRENT_LIST_DIR}/random_sampler.h
PARENT_SCOPE)
17 changes: 12 additions & 5 deletions src/random/halton.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <cstdlib>
#include <algorithm>

#include "random_sampler.h"

namespace spica {

namespace {
Expand Down Expand Up @@ -68,7 +70,7 @@ namespace spica {
}
}

Halton::Halton(int dim, bool isPermute, int seed)
Halton::Halton(int dim, bool isPermute, unsigned int seed)
: dims(dim)
, bases(NULL)
, permute(NULL)
Expand Down Expand Up @@ -103,18 +105,23 @@ namespace spica {
delete[] permute;
}

void Halton::requestSamples(RandomSeq& rseq, const int numRequested) {
void Halton::request(Stack<double>* rstk, const int numRequested) {
Assertion(numRequested <= dims, "Requested samples are too many !!");

rseq.resize(numRequested);
rstk->clear();

int* p = permute;
for (int i = 0; i < numRequested; i++) {
rseq.set(i, radicalInverse(numUsedSamples, bases[i], p));
rstk->push(radicalInverse(numUsedSamples, bases[i], p));
p += bases[i];
}
numUsedSamples++;
rseq.reset();
}

RandomSampler Halton::factory(int dim, bool isPermute, unsigned int seed) {
RandomSampler rand;
rand._rng.reset(new Halton(dim, isPermute, seed));
return std::move(rand);
}

double Halton::radicalInverse(int n, int base, const int* p) const {
Expand Down
6 changes: 4 additions & 2 deletions src/random/halton.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ namespace spica {
// @param[in] dim: dimension of halton sequence
// @param[in] isPermute: whether or not use permuted Halton
// @param[in] seed: if permuted Halton is used, it is a seed for random for the permutation
explicit Halton(int dim = 200, bool isPermute = true, int seed = -1);
explicit Halton(int dim = 200, bool isPermute = true, unsigned int seed = 0);
~Halton();

// Request specified amount of random numbers
void requestSamples(RandomSeq& rseq, const int numRequested);
void request(Stack<double>* rstk, const int numRequested) override;

static RandomSampler factory(int dim = 200, bool isPermute = true, unsigned int seed = 0);

private:
double radicalInverse(int n, int base, const int* p) const;
Expand Down
20 changes: 13 additions & 7 deletions src/random/random.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,19 @@ Thanks!

#include "../utils/common.h"

#include "random_sampler.h"

namespace spica {

/* Period parameters */
const unsigned int Random::MATRIX_A = 0x9908b0dfU; /* constant vector a */
const unsigned int Random::UPPER_MASK = 0x80000000U; /* most significant w-r bits */
const unsigned int Random::LOWER_MASK = 0x7fffffffU; /* least significant r bits */

Random::Random(int seed)
Random::Random(unsigned int seed)
: mti(N + 1)
{
unsigned int ulseed = seed >= 0 ? seed : (unsigned int)time(NULL);
init_genrand(ulseed);
init_genrand(seed);
}

int Random::nextInt() {
Expand All @@ -85,12 +86,11 @@ namespace spica {
return genrand_real2();
}

void Random::requestSamples(RandomSeq& rseq, const int numRequested) {
rseq.resize(numRequested);
void Random::request(Stack<double>* rands, const int numRequested) {
rands->clear();
for (int i = 0; i < numRequested; i++) {
rseq.set(i, nextReal());
rands->push(nextReal());
}
rseq.reset();
}

/* initializes mt[N] with a seed */
Expand Down Expand Up @@ -173,6 +173,12 @@ namespace spica {
return y;
}

RandomSampler Random::factory(unsigned int seed) {
RandomSampler rand;
rand._rng.reset(new Random(seed));
return std::move(rand);
}

/* generates a random number on [0,0x7fffffff]-interval */
int Random::genrand_int31(void) {
return static_cast<int>(genrand_int32() >> 1);
Expand Down
9 changes: 7 additions & 2 deletions src/random/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

namespace spica {

class RandomSampler;

// --------------------------------------------------
// Random number generator with Mersenne twister
// --------------------------------------------------
Expand All @@ -31,7 +33,7 @@ namespace spica {
int mti;

public:
explicit Random(int seed = -1);
explicit Random(unsigned int seed = 0);

// Generate a random integer from [0, n-1]
int nextInt();
Expand All @@ -41,7 +43,10 @@ namespace spica {
double nextReal();

// Request specified amount of random numbers
void requestSamples(RandomSeq& rseq, const int numRequested);
void request(Stack<double>* rands, const int numRequested) override;

// Factory method for RandomSampler
static RandomSampler factory(unsigned int seed = 0);

private:
void init_genrand(unsigned int s);
Expand Down
59 changes: 6 additions & 53 deletions src/random/random_base.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#ifdef _MSC_VER
#pragma once
#endif

#ifndef _SPICA_RANDOM_BASE_H_
#define _SPICA_RANDOM_BASE_H_

Expand All @@ -10,61 +14,10 @@
#include <vector>

#include "../utils/uncopyable.h"
#include "../utils/stack.h"

namespace spica {

// --------------------------------------------------
// Random number sequence genrated by generator classes
// --------------------------------------------------
class RandomSeq : private Uncopyable {
private:
int _pos;
int _size;
double* _values;

public:
RandomSeq()
: _pos(0)
, _size(0)
, _values(NULL)
{
}

~RandomSeq()
{
delete[] _values;
}

void resize(const int size) {
if (_size != size) {
delete[] _values;
this->_size = size;
_values = new double[_size];
}
}

void set(int i, double val) {
Assertion(0 <= i && i < _size, "Sample index out of bounds!!");
_values[i] = val;
}

void reset() {
_pos = 0;
}

double next() {
Assertion(_pos < _size, "No more samples are stored...");
return _values[_pos++];
}

void next(const int n, std::vector<double>* v) {
v->resize(n);
for (int i = 0; i < n; i++) {
(*v)[i] = next();
}
}
};

// --------------------------------------------------
// Interface class for random number generator
// --------------------------------------------------
Expand All @@ -73,7 +26,7 @@ namespace spica {
virtual ~RandomBase() {}

// Request specified amount of random numbers
virtual void requestSamples(RandomSeq& randSeq, const int numRequested) = 0;
virtual void request(Stack<double>* randSeq, const int numRequested) = 0;
};
};

Expand Down
31 changes: 31 additions & 0 deletions src/random/random_sampler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#define SPICA_RANDOM_SAMPLER_EXPORT
#include "random_sampler.h"

namespace spica {

RandomSampler::RandomSampler()
: _rng()
{
}

RandomSampler::~RandomSampler()
{
}

void RandomSampler::request(Stack<double>* rands, int n) {
if (_rng) {
_rng->request(rands, n);
}
}

RandomSampler::RandomSampler(RandomSampler&& rs)
: _rng(std::move(rs._rng))
{
}

RandomSampler& RandomSampler::operator=(RandomSampler&& rs) {
this->_rng = std::move(rs._rng);
return *this;
}

} // namespace spica
48 changes: 48 additions & 0 deletions src/random/random_sampler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifdef _MSC_VER
#pragma once
#endif

#ifndef _SPICA_RANDOM_SAMPLER_H_
#define _SPICA_RANDOM_SAMPLER_H_

#if defined(_WIN32) || defined(__WIN32__)
#ifdef SPICA_RANDOM_SAMPLER_EXPORT
#define SPICA_RANDOM_SAMPLER_DLL __declspec(dllexport)
#else
#define SPICA_RANDOM_SAMPLER_DLL __declspec(dllimport)
#endif
#else
#define SPICA_RANDOM_SAMPLER_DLL
#endif

#include <memory>

#include "random_base.h"
#include "../utils/stack.h"

namespace spica {

class RandomSampler {
private:
std::unique_ptr<RandomBase> _rng;

public:
RandomSampler();
~RandomSampler();

void request(Stack<double>* rands, int n);

RandomSampler(RandomSampler&& rs);
RandomSampler& operator=(RandomSampler&& rs);

private:
RandomSampler(const RandomSampler&) = delete;
RandomSampler& operator=(const RandomSampler&) = delete;

friend class Random;
friend class Halton;
};

} // namespace spica

#endif // _SPICA_RANDOM_SAMPLER_H_
10 changes: 5 additions & 5 deletions src/renderer/camera.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ namespace spica {

}

CameraSample Camera::sample(const double imageX, const double imageY, RandomSeq& rseq) const {
const double uOnPixel = rseq.next();
const double vOnPixel = rseq.next();
CameraSample Camera::sample(const double imageX, const double imageY, Stack<double>& rstk) const {
const double uOnPixel = rstk.pop();
const double vOnPixel = rstk.pop();

CameraSample sample;
sample.camera = this;
Expand All @@ -211,8 +211,8 @@ namespace spica {
const double vOnObjplane = -ratio * vOnSensor;
sample.posObjectPlane = objplane_.center + (uOnObjplane * objplane_.width) * objplane_.unitU + (vOnObjplane * objplane_.height) * objplane_.unitV;

const double r0 = sqrt(rseq.next());
const double r1 = rseq.next() * (2.0 * PI);
const double r0 = sqrt(rstk.pop());
const double r1 = rstk.pop() * (2.0 * PI);
const double uOnLens = r0 * cos(r1);
const double vOnLens = r0 * sin(r1);
sample.posLens = lens_.center + (uOnLens * lens_.radius) * lens_.unitU + (vOnLens * lens_.radius) * lens_.unitV;
Expand Down
5 changes: 4 additions & 1 deletion src/renderer/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
#endif

#include "../geometry/plane.h"

#include "../utils/image.h"
#include "../utils/stack.h"

#include "../random/random.h"
#include "../random/halton.h"

Expand Down Expand Up @@ -127,7 +130,7 @@ namespace spica {
void samplePoints(const int imageX, const int imageY, Random& rng, Vector3D& positionOnSensor, Vector3D& positionOnObjplane, Vector3D& positionOnLens, double& PImage, double& PLens) const;

CameraSample sample(const double imageX, const double imageY, double randnum[4]) const;
CameraSample sample(const double imageX, const double imageY, RandomSeq& rseq) const;
CameraSample sample(const double imageX, const double imageY, Stack<double>& rseq) const;

inline unsigned int imageW() const { return width_; }
inline unsigned int imageH() const { return height_; }
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/photon_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace spica {

Photon& operator=(const Photon& photon);

static Photon sample(const Scene& scene, RandomSeq& rseq, const int numPhotons);
static Photon sample(const Scene& scene, Stack<double>& rstk, const int numPhotons);

inline Color flux() const { return _flux; }
inline Vector3D direction() const { return _direction; }
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/photon_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ namespace spica {
private:
void buildPM(const Scene& scene, const Camera& camera, const int numPhotons, const RandomType randType);

Color executePathTracing(const Scene& scene, const Camera& camera, RandomSeq& rseq, const double pixelX, const double pixelY, const int numTargetPhotons, const double targetRadius) const;
Color radiance(const Scene& scene, const Ray& ray, RandomSeq& rseq, const int numTargetPhotons, const double targetRadius, const int depth, const int depthLimit = 32, const int maxDepth = 6) const;
Color executePathTracing(const Scene& scene, const Camera& camera, Stack<double>& rseq, const double pixelX, const double pixelY, const int numTargetPhotons, const double targetRadius) const;
Color radiance(const Scene& scene, const Ray& ray, Stack<double>& rseq, const int numTargetPhotons, const double targetRadius, const int depth, const int depthLimit = 32, const int maxDepth = 6) const;
};

}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/progressive_photonmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ namespace spica {
// 2nd pass: Trace photons from lights
void tracePhotons(const Scene& scene, RandomBase* rand, const int numPhotons);

void executePathTracing(const Scene& scene, const Camera& camera, RandomSeq& rseq, HPoint* hp, const int bounceLimit = 64);
void executePathTracing(const Scene& scene, const Camera& camera, Stack<double>& rseq, HPoint* hp, const int bounceLimit = 64);

void constructHashGrid(std::vector<HPoint>& hpoints, const int imageW, const int imageH);
};
Expand Down
Loading

0 comments on commit 0c9974d

Please sign in to comment.