memory optimization for octree pyrit
authorRadek Brich <radek.brich@devl.cz>
Sun, 30 Dec 2007 00:11:47 +0100
branchpyrit
changeset 43 0b8b968b42d1
parent 42 fbdeb3e04543
child 44 3763b26244f0
memory optimization for octree fixed some visual artifacts in textures C++ demo and set ambient occlussion for rendering (-r)
ccdemos/textures.cc
include/octree.h
src/octree.cc
--- a/ccdemos/textures.cc	Sat Dec 29 13:53:33 2007 +0100
+++ b/ccdemos/textures.cc	Sun Dec 30 00:11:47 2007 +0100
@@ -27,7 +27,7 @@
 void texture2D(Float u, Float v, Float &r, Float &g, Float &b)
 {
 	// checkers
-	r = fabs((int)(u*4.4)%2 + (int)(v*4.4)%2 - 1);
+	r = fabs((int)(u*4.2)%2 + (int)(v*4.2)%2 - 1);
 	g=r; b=r;
 }
 
@@ -60,12 +60,18 @@
 		{
 			if (fabs(point.x) > fabs(point.z))
 			{
-				u = point.y;
+				if (point.x < 0)
+					u = -point.y;
+				else
+					u = point.y;
 				v = point.z;
 			}
 			else
 			{
-				u = point.x;
+				if (point.z < 0)
+					u = -point.x;
+				else
+					u = point.x;
 				v = point.y;
 			}
 		}
@@ -73,12 +79,18 @@
 		{
 			if (fabs(point.y) > fabs(point.z))
 			{
-				u = point.x;
+				if (point.y < 0)
+					u = -point.x;
+				else
+					u = point.x;
 				v = point.z;
 			}
 			else
 			{
-				u = point.x;
+				if (point.z < 0)
+					u = -point.x;
+				else
+					u = point.x;
 				v = point.y;
 			}
 		}
@@ -266,6 +278,7 @@
 		Float *fdata = (Float *) malloc(w*h*3*sizeof(Float));
 		rt.setOversample(2);
 		rt.setSubsample(1);
+		rt.ambientocclusion(300, 5.0, 0.5);
 		rt.render(w, h, fdata);
 
 		struct image *img;
--- a/include/octree.h	Sat Dec 29 13:53:33 2007 +0100
+++ b/include/octree.h	Sun Dec 30 00:11:47 2007 +0100
@@ -12,22 +12,35 @@
 #include "vector.h"
 #include "scene.h"
 
+#include <assert.h>
+
 using namespace std;
 
 class OctreeNode
 {
-	OctreeNode *children; // pointer to first of eight children
+    union {
+		OctreeNode *children; // pointer to first of eight children
+		ShapeList *shapes;    // pointer to shape array, if this is leaf
+		off_t leaf;             // leaf indicator (bit 0)
+	};
 public:
-	ShapeList *shapes;    // pointer to shape array, if this is leaf
-
-	OctreeNode() : children(NULL) { shapes = new ShapeList(); };
+	OctreeNode()
+	{
+		shapes = new ShapeList();
+		assert(sizeof(off_t)==sizeof(void*) && !isLeaf());
+		setLeaf();
+	};
 	~OctreeNode();
 
-	bool isLeaf() { return shapes != NULL; };
+	bool isLeaf() { return leaf & 1; };
+	void setLeaf() { leaf = leaf | 1; };
 
-	OctreeNode *getChild(const int num) { return children+num; };
+	void makeChildren() { children = new OctreeNode[8]; assert(!isLeaf()); }; // this also cleans leaf bit
+	OctreeNode *getChild(const int num) { assert(!isLeaf()); return children + num; };
 
-	void addShape(Shape* aShape) { shapes->push_back(aShape); };
+	void addShape(Shape* aShape) { getShapes()->push_back(aShape); };
+	ShapeList *getShapes() { return (ShapeList*)((off_t)shapes & ~(off_t)1); };
+	void setShapes(ShapeList *const ashapes) { shapes = ashapes; assert(!isLeaf()); setLeaf(); };
 
 	void subdivide(BBox bbox, int maxdepth);
 };
--- a/src/octree.cc	Sat Dec 29 13:53:33 2007 +0100
+++ b/src/octree.cc	Sun Dec 30 00:11:47 2007 +0100
@@ -9,16 +9,21 @@
 
 OctreeNode::~OctreeNode()
 {
-	if (shapes != NULL)
+	if (isLeaf())
+	{
+		leaf = leaf^1; // zero leaf bit
 		delete shapes;
+	}
 	else
 		delete[] children;
 }
 
 void OctreeNode::subdivide(BBox bbox, int maxdepth)
 {
-	// make children
-	children = new OctreeNode[8];
+	ShapeList *l_shapes = getShapes();
+
+	// prepare children (this also sets this node as non-leaf)
+	makeChildren();
 
 	// evaluate centres for axes
 	const Float xsplit = (bbox.L.x + bbox.H.x)*0.5;
@@ -42,7 +47,7 @@
 	// distribute shapes to children
 	ShapeList::iterator sh;
 	unsigned int shapenum = 0;
-	for (sh = shapes->begin(); sh != shapes->end(); sh++)
+	for (sh = l_shapes->begin(); sh != l_shapes->end(); sh++)
 	{
 		for (int i = 0; i < 8; i++)
 			if ((*sh)->intersect_bbox(childbb[i]))
@@ -52,21 +57,21 @@
 			}
 	}
 
-	if ((shapes->size() <= 8 && shapenum > 2*shapes->size())
-	|| shapenum >= 6*shapes->size())
+	if ((l_shapes->size() <= 8 && shapenum > 2*l_shapes->size())
+	|| shapenum >= 6*l_shapes->size())
 	{
 		// bad subdivision, revert
 		delete[] children;
+		setShapes(l_shapes);
 		return;
 	}
 
 	// remove shapes and set this node to non-leaf
-	delete shapes;
-	shapes = NULL;
+	delete l_shapes;
 
 	// recursive subdivision
 	for (int i = 0; i < 8; i++)
-		if (maxdepth > 1 && getChild(i)->shapes->size() > 4)
+		if (maxdepth > 1 && getChild(i)->getShapes()->size() > 4)
 			children[i].subdivide(childbb[i], maxdepth-1);
 }
 
@@ -196,7 +201,7 @@
 					ShapeList::iterator shape;
 					//register Float mindist = max3(tx0,ty0,tz0);
 					register Float dist = min(nearest_distance, min3(tx1,ty1,tz1));
-					for (shape = node->shapes->begin(); shape != node->shapes->end(); shape++)
+					for (shape = node->getShapes()->begin(); shape != node->getShapes()->end(); shape++)
 						if (*shape != origin_shape && (*shape)->intersect(ray, dist))
 						{
 							nearest_shape = *shape;