From a4da6ff79697c8a26e0c3afc356378757fcc2815 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 21 Jan 2009 13:57:54 +0100
Subject: [PATCH] adaptive sampling
---
src/ConsoleProgressIndicator.cpp | 10 ++++-
src/ConsoleProgressIndicator.h | 1 +
src/Entity.cpp | 77 +++++++++++++++++++++++++++++++++----
src/Entity.h | 3 +
src/EntitySet.cpp | 5 ++-
src/PatchCache.cpp | 21 ++++++++++
src/PatchCache.h | 1 +
src/ProgressObserverMultiStep.cpp | 4 ++
src/ProgressObserverMultiStep.h | 2 +
src/ProgressSubjectMultiStep.cpp | 8 ++++
src/ProgressSubjectMultiStep.h | 2 +
src/RadiosityRenderer.cpp | 8 ++++
src/RadiosityRenderer.h | 2 +
src/Scene.cpp | 21 ++++++----
src/Scene.h | 4 +-
src/rrv-compute.cpp | 37 +++++++++++++++++-
16 files changed, 186 insertions(+), 20 deletions(-)
diff --git a/src/ConsoleProgressIndicator.cpp b/src/ConsoleProgressIndicator.cpp
index e91165c..cf9cfcc 100644
--- a/src/ConsoleProgressIndicator.cpp
+++ b/src/ConsoleProgressIndicator.cpp
@@ -15,6 +15,10 @@ ConsoleProgressIndicator::~ConsoleProgressIndicator() {
renderer_->detach(this);
}
+void ConsoleProgressIndicator::updatePatchCount() {
+ renderer_->detach(this);
+ renderer_->attach(this, 100);
+}
void ConsoleProgressIndicator::updateStep() {
counter_ = 0;
std::cout
@@ -24,11 +28,13 @@ void ConsoleProgressIndicator::updateStep() {
<< " "
<< std::flush;
+#if 0
if (1== renderer_->currentStep()) {
renderer_->detach(this);
renderer_->attach(this, 10);
updatePerStepProgress();
}
+#endif
// FIXME: This should not be here
if (!renderer_->currentStep())
@@ -36,7 +42,7 @@ void ConsoleProgressIndicator::updateStep() {
}
void ConsoleProgressIndicator::updatePerStepProgress() {
- if (0==counter_%10 && !renderer_->currentStep()) {
+ if (0==counter_%10/* && !renderer_->currentStep()*/) {
if (counter_) {
std::cout
<< " cache raw size: "
@@ -57,8 +63,10 @@ void ConsoleProgressIndicator::updatePerStepProgress() {
else
std::cout << std::endl;
+#if 0
if (renderer_->currentStep() && counter_ >=10)
std::cout << std::endl;
+#endif
counter_++;
}
diff --git a/src/ConsoleProgressIndicator.h b/src/ConsoleProgressIndicator.h
index ad35249..241e1c2 100644
--- a/src/ConsoleProgressIndicator.h
+++ b/src/ConsoleProgressIndicator.h
@@ -23,6 +23,7 @@ class ConsoleProgressIndicator: public ProgressObserverMultiStep
~ConsoleProgressIndicator();
virtual void updateStep();
+ virtual void updatePatchCount();
virtual void updatePerStepProgress();
private:
diff --git a/src/Entity.cpp b/src/Entity.cpp
index 4710a14..6ab1983 100644
--- a/src/Entity.cpp
+++ b/src/Entity.cpp
@@ -16,6 +16,24 @@
using namespace std;
using namespace XML;
+namespace {
+ inline std::string vertexToString(const Vertex &v) {
+ std::ostringstream oss;
+ oss << v.x << "," << v.y << "," << v.z;
+ return oss.str();
+ }
+ inline float colorDist(Triangle *ta, Triangle *tb) {
+ Color ca = ta->radiosity;
+ Color cb = tb->radiosity;
+
+ float dr = ca.r - cb.r;
+ float dg = ca.g - cb.g;
+ float db = ca.b - cb.b;
+
+ return dr*dr + dg*dg + db*db;
+ }
+}
+
Entity::Entity():
patchSet_(0)
{
@@ -162,6 +180,57 @@ void Entity::divide (float size ) {
patchSet_ = pset;
}
+void Entity::divide () {
+ static const float MIN_PATCH_SIZE = 0.01; ///< TODO: read as parameter
+ static const float MAX_PATCH_DIST = 0.01; ///< TODO: read as parameter
+
+ TriangleSet &src = *patchSet_;
+
+ // Build map Vertex -> list of Triangles
+ typedef std::vector<Triangle *> TTrianglePtrList;
+ typedef std::map<std::string, TTrianglePtrList> TVertexMap;
+ TVertexMap vertexMap;
+ for(size_t i=0; i<src.count(); i++) {
+ Triangle &t = src[i];
+
+ for(int j=0; j<3; j++) {
+ TTrianglePtrList &cpList = vertexMap[vertexToString(t.vertex[j])];
+ cpList.push_back(&t);
+ }
+ }
+
+ TriangleSet *pset = new TriangleSet;
+
+ // main loop
+ for (size_t i=0; i<src.count(); i++) {
+ Triangle &t = src[i];
+ if (TriangleSet::size<1>(&t) < MIN_PATCH_SIZE) {
+ // patch too small
+ pset->add(&t);
+ continue;
+ }
+
+ // compute color distance
+ float maxDist = 0.0;
+ for(int j=0; j<3; j++) {
+ TTrianglePtrList &cpList = vertexMap[vertexToString(t.vertex[j])];
+ for(size_t k=0; k<cpList.size(); k++) {
+ float d = colorDist(&t, cpList[k]);
+ if (maxDist < d)
+ maxDist = d;
+ }
+ }
+
+ // divide if needed
+ if (maxDist < MAX_PATCH_DIST)
+ pset->add(&t);
+ else
+ pset->add(TriangleSet::divide(&t));
+ }
+
+ delete patchSet_;
+ patchSet_ = pset;
+}
/**
* @return PatchSequenceEnumerator*
@@ -316,14 +385,6 @@ void Entity::setColors( XMLNode* from, Color& em, Color& refl, Color& rad )
Entity::colorFromXMLNode( from, XMLNames::ATTRIBUTES[ Radiosity ] , rad );
}
-namespace {
- inline std::string vertexToString(const Vertex &v) {
- std::ostringstream oss;
- oss << v.x << "," << v.y << "," << v.z;
- return oss.str();
- }
-}
-
TriangleSetExt* Entity::computeVertexColors() {
// Create and fill TriangleSetExt
TriangleSetExt *tset = new TriangleSetExt;
diff --git a/src/Entity.h b/src/Entity.h
index ec123f8..832a146 100644
--- a/src/Entity.h
+++ b/src/Entity.h
@@ -67,6 +67,9 @@ public:
*/
void divide (float size);
+ /// adaptive division
+ void divide ();
+
/**
* @brief Create enumerator for entity's patches.
* @return Return instance of PatchSequenceEnumerator allocated on the heap.
diff --git a/src/EntitySet.cpp b/src/EntitySet.cpp
index c30acfa..b72dedf 100644
--- a/src/EntitySet.cpp
+++ b/src/EntitySet.cpp
@@ -17,7 +17,10 @@ void EntitySet::divide (float size ) {
TContainer::iterator i;
for(i= container_.begin(); i!= container_.end(); i++) {
Entity &e = *i;
- e.divide(size);
+ if (size == 0.0)
+ e.divide();
+ else
+ e.divide(size);
}
}
diff --git a/src/PatchCache.cpp b/src/PatchCache.cpp
index ce16e99..23b3253 100644
--- a/src/PatchCache.cpp
+++ b/src/PatchCache.cpp
@@ -23,6 +23,14 @@ PatchCache::PatchCache(
ffe_ = new FormFactorEngine(patchEnumerator);
}
+void PatchCache::setPatchEnumerator(PatchRandomAccessEnumerator *patchEnumerator) {
+ delete ffe_;
+ delete cache_;
+ patchCount_ = patchEnumerator->count();
+ cache_ = new TCache(patchCount_, 0);
+ ffe_ = new FormFactorEngine(patchEnumerator);
+}
+
PatchCache::~PatchCache() {
delete ffe_;
delete cacheQueue_;
@@ -42,6 +50,8 @@ long int PatchCache::cacheRawSize() const {
}
Color PatchCache::totalRadiosity(int destPatch) {
+#if 0
+ // master branche
PatchCacheLine *&cacheLine = cache_->operator[](destPatch);
if (0==cacheLine) {
// Cache-line was not in cache --> create and fill
@@ -52,10 +62,17 @@ Color PatchCache::totalRadiosity(int destPatch) {
cachedItems_ += cacheLine->itemCount();
cacheQueue_->push(&cacheLine);
}
+#else
+ // adaptive-division branche
+ PatchCacheLine *cacheLine = new PatchCacheLine(patchEnumerator_, ffTreshold_);
+ ffe_->fillCacheLine(destPatch, cacheLine);
+#endif
// Use cache-line to cumpute total radiosity
Color rad = cacheLine->totalRadiosity();
+#if 0
+ // master branche
if (this->cacheRawSize() >= maxCacheSize_) {
// maxCacheSize exceed --> free the largest cache-line
const TQueueItem &qi = cacheQueue_->top();
@@ -65,6 +82,10 @@ Color PatchCache::totalRadiosity(int destPatch) {
topCL = 0;
cacheQueue_->pop();
}
+#else
+ // adaptive-division branche
+ delete cacheLine;
+#endif
return rad;
}
diff --git a/src/PatchCache.h b/src/PatchCache.h
index 9a1e69e..4fc71ca 100644
--- a/src/PatchCache.h
+++ b/src/PatchCache.h
@@ -29,6 +29,7 @@ class PatchCache {
*/
PatchCache(PatchRandomAccessEnumerator *patchEnumerator, float ffTreshold, long maxCacheSize);
~PatchCache();
+ void setPatchEnumerator(PatchRandomAccessEnumerator *patchEnumerator);
/**
* This computation respectes form factor for each patch.
diff --git a/src/ProgressObserverMultiStep.cpp b/src/ProgressObserverMultiStep.cpp
index 469654e..5773718 100644
--- a/src/ProgressObserverMultiStep.cpp
+++ b/src/ProgressObserverMultiStep.cpp
@@ -19,6 +19,10 @@ void ProgressObserverMultiStep::updateStep() {
}
+void ProgressObserverMultiStep::updatePatchCount() {
+
+}
+
/**
*/
diff --git a/src/ProgressObserverMultiStep.h b/src/ProgressObserverMultiStep.h
index fb91a7e..480aa6e 100644
--- a/src/ProgressObserverMultiStep.h
+++ b/src/ProgressObserverMultiStep.h
@@ -22,6 +22,8 @@ class ProgressObserverMultiStep
*/
virtual void updateStep();
+ virtual void updatePatchCount();
+
/**
* @brief Notification about subject's progress.
diff --git a/src/ProgressSubjectMultiStep.cpp b/src/ProgressSubjectMultiStep.cpp
index 36d9c48..e4ee96b 100644
--- a/src/ProgressSubjectMultiStep.cpp
+++ b/src/ProgressSubjectMultiStep.cpp
@@ -46,6 +46,14 @@ void ProgressSubjectMultiStep::notifyStep() {
i->observer->updateStep();
}
+void ProgressSubjectMultiStep::notifyPatchCountChanged() {
+ // Must be copy of working list to avoid race condition!!
+ TList listCopy(observerList_);
+ TList::iterator i;
+ for(i= listCopy.begin(); i!= listCopy.end(); i++)
+ i->observer->updatePatchCount();
+}
+
void ProgressSubjectMultiStep::notifyPerStepProgress() {
// Must be copy of working list to avoid race condition!!
TList listCopy(observerList_);
diff --git a/src/ProgressSubjectMultiStep.h b/src/ProgressSubjectMultiStep.h
index 7a644b9..107554f 100644
--- a/src/ProgressSubjectMultiStep.h
+++ b/src/ProgressSubjectMultiStep.h
@@ -65,6 +65,8 @@ class ProgressSubjectMultiStep
* observer's request.
*/
void notifyPerStepProgress();
+
+ void notifyPatchCountChanged();
private:
struct TItem {
diff --git a/src/RadiosityRenderer.cpp b/src/RadiosityRenderer.cpp
index 7f4733c..f0ae653 100644
--- a/src/RadiosityRenderer.cpp
+++ b/src/RadiosityRenderer.cpp
@@ -29,6 +29,14 @@ RadiosityRenderer::RadiosityRenderer(
// #endif
}
+void RadiosityRenderer::setPatchEnumerator(PatchSequenceEnumerator *patchEnumerator) {
+ delete patchEnumerator_;
+ patchEnumerator_ = new PatchRandomAccessEnumerator(patchEnumerator);
+ patchCount_ = patchEnumerator_->count();
+ patchCache_->setPatchEnumerator(patchEnumerator_);
+ notifyPatchCountChanged();
+}
+
RadiosityRenderer::~RadiosityRenderer() {
delete patchCache_;
delete patchEnumerator_;
diff --git a/src/RadiosityRenderer.h b/src/RadiosityRenderer.h
index 79fe200..b5ae833 100644
--- a/src/RadiosityRenderer.h
+++ b/src/RadiosityRenderer.h
@@ -29,6 +29,8 @@ class RadiosityRenderer: public ProgressSubjectMultiStep {
*/
RadiosityRenderer(PatchSequenceEnumerator *patchEnumerator, int stepCount, float formFactorTreshold, long maxCacheSize);
~RadiosityRenderer();
+
+ void setPatchEnumerator(PatchSequenceEnumerator *patchEnumerator);
/**
* @brief Return total count of radiosity computation steps.
diff --git a/src/Scene.cpp b/src/Scene.cpp
index f3d0ee2..cd96683 100644
--- a/src/Scene.cpp
+++ b/src/Scene.cpp
@@ -3,10 +3,7 @@
#include "PatchSequenceEnumerator.h"
#include "RadiosityRenderer.h"
#include "TriangleSetExt.h"
-
-#ifndef NDEBUG
-# include "PatchRandomAccessEnumerator.h"
-#endif
+#include "PatchRandomAccessEnumerator.h"
using namespace XML;
@@ -89,18 +86,22 @@ void Scene::applyEmission() {
/**
*/
void Scene::divide (float size) {
-#ifndef NDEBUG
+#if 1//ndef NDEBUG
PatchRandomAccessEnumerator *iter=
PatchRandomAccessEnumerator::create(&entitySet_);
std::cout << "--- Count of patch: " << iter->count() << std::endl;
- std::cout << "--- Max. patch size: " << size << std::endl;
+ //std::cout << "--- Max. patch size: " << size << std::endl;
delete iter;
std::cout << ">>> Starting patch division ... " << std::flush;
#endif
- entitySet_.divide(size);
-#ifndef NDEBUG
+ entitySet_.divide(size);
+#if 1//ndef NDEBUG
std::cout << "ok" << std::endl;
+ iter= PatchRandomAccessEnumerator::create(&entitySet_);
+ std::cout << "--- Count of patch: " << iter->count() << std::endl;
+ std::cout << std::endl;
+ delete iter;
#endif
}
@@ -115,6 +116,10 @@ RadiosityRenderer* Scene::createRadiosityRenderer(int stepCount, float formFacto
return renderer;
}
+PatchSequenceEnumerator* Scene::createPatchSequenceEnumerator() {
+ return entitySet_.createPatchSequenceEnumerator();
+}
+
/**
* @param fileName
*/
diff --git a/src/Scene.h b/src/Scene.h
index 3b5e474..1b9ddc1 100644
--- a/src/Scene.h
+++ b/src/Scene.h
@@ -43,7 +43,7 @@ public:
* @brief Divide scene triangles to patches.
* @param size Maximum acceptable size of patch.
*/
- void divide (float size);
+ void divide (float size = 0.0);
/**
* @brief @return Return instance of RadiosityRenderer object allocated on the heap.
@@ -54,6 +54,8 @@ public:
*/
RadiosityRenderer* createRadiosityRenderer(int stepCount, float formFactorTreshold, long maxCacheSize);
+ PatchSequenceEnumerator* createPatchSequenceEnumerator();
+
/**
* @brief Save scene to XML file.
* @param fileName Name of file to save scene to.
diff --git a/src/rrv-compute.cpp b/src/rrv-compute.cpp
index deb13b3..cf11d56 100644
--- a/src/rrv-compute.cpp
+++ b/src/rrv-compute.cpp
@@ -27,13 +27,19 @@ class ContinousSaver: public ProgressObserverMultiStep {
{
renderer->attach(this, perStepFreq);
}
+ virtual void updatePatchCount() {
+ renderer_->detach(this);
+ renderer_->attach(this, perStepFreq_);
+ }
virtual void updateStep() {
perStepCounter_ = 0;
+#if 0
perStepFreq_ >>= 1;
if (perStepFreq_ < 1)
perStepFreq_ = 1;
renderer_->detach(this);
renderer_->attach(this, perStepFreq_);
+#endif
}
virtual void updatePerStepProgress() {
// if (1==perStepFreq_) {
@@ -53,6 +59,25 @@ class ContinousSaver: public ProgressObserverMultiStep {
}
};
+class AdaptiveDivider: public ProgressObserverMultiStep {
+ public:
+ AdaptiveDivider(Scene *scene, RadiosityRenderer *renderer):
+ scene_(scene),
+ renderer_(renderer)
+ {
+ renderer->attach(this, 1);
+ }
+ virtual void updateStep() {
+ if (!renderer_->currentStep())
+ return;
+ scene_->divide();
+ renderer_->setPatchEnumerator(scene_->createPatchSequenceEnumerator());
+ }
+ private:
+ Scene *scene_;
+ RadiosityRenderer *renderer_;
+};
+
int main(int argc, char *argv[]) {
ComputeArguments *args = new ComputeArguments();
args->parseArguments( argc, argv );
@@ -87,17 +112,27 @@ int main(int argc, char *argv[]) {
scene.createRadiosityRenderer(args->getSteps(), args->getTreshold(), args->getCache()*1048576);
//scene.createRadiosityRenderer(STEP_COUNT, FORM_FACTOR_TRESHOLD, MAX_CACHE_SIZE);
+#if 1
+ // adaptive-division branche
+ AdaptiveDivider *divider=
+ new AdaptiveDivider(&scene, renderer);
+#endif
+
ConsoleProgressIndicator *progressIndicator=
new ConsoleProgressIndicator(renderer);
ContinousSaver *saver=
new ContinousSaver(&scene, renderer, fileName, args->getSaves());
//new ContinousSaver(&scene, renderer, fileName, PER_STEP_SAVE_INITIAL);
-
+
renderer->compute();
delete saver;
delete progressIndicator;
+#if 1
+ // adaptive-division branche
+ delete divider;
+#endif
delete renderer;
//scene.save(fileName+"-final.xml");
--
1.6.1