Česky
Kamil Dudka

RRV - Radiosity Renderer and Visualizer (C++, OpenGL)

File detail

Name:Download0001-adaptive-sampling.patch [Download]
Location: rrv
Size:15.5 KB
Last modification:2009-10-21 22:58

Source code

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