diff --git a/include/mitsuba/bidir/mut_bidir.h b/include/mitsuba/bidir/mut_bidir.h
index 8f480ae6..8a89f0f0 100644
--- a/include/mitsuba/bidir/mut_bidir.h
+++ b/include/mitsuba/bidir/mut_bidir.h
@@ -64,7 +64,7 @@ public:
EMutationType getType() const;
Float suitability(const Path &path) const;
- bool sampleMutation(Path &source, Path &proposal, MutationRecord &muRec);
+ bool sampleMutation(Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec);
Float Q(const Path &source, const Path &proposal,
const MutationRecord &muRec) const;
void accept(const MutationRecord &muRec);
diff --git a/include/mitsuba/bidir/mut_caustic.h b/include/mitsuba/bidir/mut_caustic.h
index d501fe21..7e4899db 100644
--- a/include/mitsuba/bidir/mut_caustic.h
+++ b/include/mitsuba/bidir/mut_caustic.h
@@ -63,7 +63,7 @@ public:
EMutationType getType() const;
Float suitability(const Path &path) const;
bool sampleMutation(Path &source, Path &proposal,
- MutationRecord &muRec);
+ MutationRecord &muRec, const MutationRecord& sourceMuRec);
Float Q(const Path &source, const Path &proposal,
const MutationRecord &muRec) const;
void accept(const MutationRecord &muRec);
diff --git a/include/mitsuba/bidir/mut_lens.h b/include/mitsuba/bidir/mut_lens.h
index 0954bee0..35b66acf 100644
--- a/include/mitsuba/bidir/mut_lens.h
+++ b/include/mitsuba/bidir/mut_lens.h
@@ -63,7 +63,7 @@ public:
EMutationType getType() const;
Float suitability(const Path &path) const;
bool sampleMutation(Path &source, Path &proposal,
- MutationRecord &muRec);
+ MutationRecord &muRec, const MutationRecord& sourceMuRec);
Float Q(const Path &source, const Path &proposal,
const MutationRecord &muRec) const;
void accept(const MutationRecord &muRec);
diff --git a/include/mitsuba/bidir/mut_manifold.h b/include/mitsuba/bidir/mut_manifold.h
index 784b47c8..d99610fb 100644
--- a/include/mitsuba/bidir/mut_manifold.h
+++ b/include/mitsuba/bidir/mut_manifold.h
@@ -61,7 +61,7 @@ public:
EMutationType getType() const;
Float suitability(const Path &path) const;
bool sampleMutation(Path &source, Path &proposal,
- MutationRecord &muRec);
+ MutationRecord &muRec, const MutationRecord& sourceMuRec);
Float Q(const Path &source, const Path &proposal,
const MutationRecord &muRec) const;
void accept(const MutationRecord &muRec);
diff --git a/include/mitsuba/bidir/mut_mchain.h b/include/mitsuba/bidir/mut_mchain.h
index 5bbcb3fb..be100b38 100644
--- a/include/mitsuba/bidir/mut_mchain.h
+++ b/include/mitsuba/bidir/mut_mchain.h
@@ -63,7 +63,7 @@ public:
EMutationType getType() const;
Float suitability(const Path &path) const;
bool sampleMutation(Path &source, Path &proposal,
- MutationRecord &muRec);
+ MutationRecord &muRec, const MutationRecord& sourceMuRec);
Float Q(const Path &source, const Path &proposal,
const MutationRecord &muRec) const;
void accept(const MutationRecord &muRec);
diff --git a/include/mitsuba/bidir/mutator.h b/include/mitsuba/bidir/mutator.h
index 2e82054b..ec0cc3cc 100644
--- a/include/mitsuba/bidir/mutator.h
+++ b/include/mitsuba/bidir/mutator.h
@@ -64,13 +64,17 @@ public:
* \param muRec
* Data record that describes the sampled mutation strategy
*
+ * \param sourceMuRec
+ * Data record that describes the last successful mutation strategy
+ * (for the source path)
+ *
* \return \a true upon success. When the sampling step is
* unsuccessful (this could happen due to various
* reasons), the function returns false.
- */
+ */
virtual bool sampleMutation(Path &source, Path &proposal,
- MutationRecord &muRec) = 0;
+ MutationRecord &muRec, const MutationRecord& sourceMuRec) = 0;
/**
* \brief For a pair of paths, this function computes the inverse
diff --git a/src/integrators/erpt/erpt_proc.cpp b/src/integrators/erpt/erpt_proc.cpp
index 8237a84d..5ac664a2 100644
--- a/src/integrators/erpt/erpt_proc.cpp
+++ b/src/integrators/erpt/erpt_proc.cpp
@@ -174,7 +174,7 @@ public:
std::ostringstream oss;
Spectrum relWeight(0.0f);
Float accumulatedWeight = 0;
- MutationRecord muRec;
+ MutationRecord muRec, currentMuRec(Mutator::EMutationTypeCount, 0, 0, 0, Spectrum(0.f));
Path *current = new Path(),
*proposed = new Path();
size_t mutations = 0;
@@ -211,7 +211,7 @@ public:
mutator = m_mutators[mutatorIdx].get();
/* Sample a mutated path */
- success = mutator->sampleMutation(*current, *proposed, muRec);
+ success = mutator->sampleMutation(*current, *proposed, muRec, currentMuRec);
statsAccepted.incrementBase(1);
if (success) {
@@ -258,6 +258,7 @@ public:
std::swap(current, proposed);
relWeight = current->getRelativeWeight();
mutator->accept(muRec);
+ currentMuRec = muRec;
accumulatedWeight = a;
++statsAccepted;
++mutations;
diff --git a/src/integrators/mlt/mlt_proc.cpp b/src/integrators/mlt/mlt_proc.cpp
index 402120c4..4228c0ae 100644
--- a/src/integrators/mlt/mlt_proc.cpp
+++ b/src/integrators/mlt/mlt_proc.cpp
@@ -127,7 +127,7 @@ public:
BDAssert(!relWeight.isZero());
DiscreteDistribution suitabilities(m_mutators.size());
- MutationRecord muRec;
+ MutationRecord muRec, currentMuRec(Mutator::EMutationTypeCount,0,0,0,Spectrum(0.f));
ref timer = new Timer();
size_t consecRejections = 0;
@@ -171,7 +171,7 @@ public:
mutator = m_mutators[mutatorIdx].get();
/* Sample a mutated path */
- success = mutator->sampleMutation(*current, *proposed, muRec);
+ success = mutator->sampleMutation(*current, *proposed, muRec, currentMuRec);
#if defined(MTS_BD_DEBUG_HEAVY)
if (backup != *current)
@@ -263,11 +263,12 @@ public:
std::swap(current, proposed);
relWeight = current->getRelativeWeight();
mutator->accept(muRec);
+ currentMuRec = muRec;
accumulatedWeight = a;
consecRejections = 0;
++statsAccepted;
} else {
- /* The mutation was rejected */
+ /* The mutation was rejected */
proposed->release(muRec.l, muRec.l + muRec.ka + 1, *m_pool);
consecRejections++;
if (a > 0) {
diff --git a/src/libbidir/mut_bidir.cpp b/src/libbidir/mut_bidir.cpp
index 7cf67be0..dee4609e 100644
--- a/src/libbidir/mut_bidir.cpp
+++ b/src/libbidir/mut_bidir.cpp
@@ -44,7 +44,7 @@ Float BidirectionalMutator::suitability(const Path &path) const {
}
bool BidirectionalMutator::sampleMutation(
- Path &source, Path &proposal, MutationRecord &muRec) {
+ Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec) {
TwoTailedGeoDistr desiredLength(2), deletionLength(2);
int k = source.length();
diff --git a/src/libbidir/mut_caustic.cpp b/src/libbidir/mut_caustic.cpp
index bf351c23..203ebb4e 100644
--- a/src/libbidir/mut_caustic.cpp
+++ b/src/libbidir/mut_caustic.cpp
@@ -73,7 +73,7 @@ Float CausticPerturbation::suitability(const Path &path) const {
}
bool CausticPerturbation::sampleMutation(
- Path &source, Path &proposal, MutationRecord &muRec) {
+ Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec) {
int k = source.length(), m = k - 1, l = m - 1;
if (k < 4 || !source.vertex(l)->isConnectable())
diff --git a/src/libbidir/mut_lens.cpp b/src/libbidir/mut_lens.cpp
index e2f938e5..bc8aa971 100644
--- a/src/libbidir/mut_lens.cpp
+++ b/src/libbidir/mut_lens.cpp
@@ -70,7 +70,7 @@ Float LensPerturbation::suitability(const Path &path) const {
}
bool LensPerturbation::sampleMutation(
- Path &source, Path &proposal, MutationRecord &muRec) {
+ Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec) {
int k = source.length(), m = k-1, l = m-1;
while (!source.vertex(l)->isConnectable() && l >= 0)
--l;
diff --git a/src/libbidir/mut_manifold.cpp b/src/libbidir/mut_manifold.cpp
index 0ce9de7b..48af6dee 100644
--- a/src/libbidir/mut_manifold.cpp
+++ b/src/libbidir/mut_manifold.cpp
@@ -230,7 +230,7 @@ bool ManifoldPerturbation::sampleMutationRecord(
}
bool ManifoldPerturbation::sampleMutation(
- Path &source, Path &proposal, MutationRecord &muRec) {
+ Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec) {
int k = source.length();
int a, b, c, step, tries = 0;
diff --git a/src/libbidir/mut_mchain.cpp b/src/libbidir/mut_mchain.cpp
index bae1a6f1..1e608cfa 100644
--- a/src/libbidir/mut_mchain.cpp
+++ b/src/libbidir/mut_mchain.cpp
@@ -66,7 +66,7 @@ Float MultiChainPerturbation::suitability(const Path &path) const {
}
bool MultiChainPerturbation::sampleMutation(
- Path &source, Path &proposal, MutationRecord &muRec) {
+ Path &source, Path &proposal, MutationRecord &muRec, const MutationRecord& sourceMuRec) {
int k = source.length(), m = k - 1, l = m-1, nChains = 1;
while (l-1 >= 0 && (!source.vertex(l)->isConnectable()