memory optimization for octree
fixed some visual artifacts in textures C++ demo and set ambient occlussion for rendering (-r)
--- 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;