

#include <queue>

 class BaseQueue {
public:
virtual void push( void *newItem ) = 0;
};

 class e_Object {
public:
// attributes:
float max_displace;
};

 class GeoPrim {
public:
virtual void bound() = 0;
virtual bool on_screen() = 0;
virtual bool projectable() = 0;
virtual void project() = 0;
virtual bool on_bucket() = 0;
virtual bool diceable() = 0;
virtual void dice() = 0;
virtual void split( BaseQueue *queue ) = 0;

public:
e_Object *obj;
Bound6f box;
};

 class RasterObject {
public:
bool is_grid();

public:
GeoPrim *object; // the geometric primitive
int flags; // the object flags
float zmin; // the minimum z coordinate of the object (used for occlusion culling)
};

 class ShadingGrid : public RasterObject {
public:
void shade();
void sample();

public:
float *vertices; // array of vertices
int *bounds; // the bound of the primitive (4 numbers per primitive)
float *sizes; // the size of the primitive (only makes sense for points)
float umin, umax, vmin, vmax; // the parametric range
int udiv, vdiv; // the number of division
int numVertices; // the number of vertices
int flags; // the primitive flags
};

 class GeoPrimQueue : public BaseQueue {
public:
// implemented for BaseQueue
void push( void *newItem )
 {
gp_queue.push( (GeoPrim *) newItem );
}

GeoPrim *get()
 {
GeoPrim *gprim = NULL;
if( !gp_queue.empty() )
 {
gprim = gp_queue.front();
gp_queue.pop();
}

return gprim;
}

private:
std::queue< GeoPrim * > gp_queue;
};

// priority queue

 class RasterObjectQueue : public BaseQueue {
public:
RasterObjectQueue( int ss = 100 )
 {
stepSize = ss;
maxItems = stepSize;
numItems = 1;
allItems = new RasterObject* [maxItems];
}

~RasterObjectQueue()
 {
delete [] allItems;
}

// implemented for BaseQueue
void push( void *newItem )
 {
insert( (RasterObject *) newItem );
}

void insert( RasterObject *cObject )
 {
int i,j;

// expand the buffer
 if (numItems >= maxItems) {
RasterObject **newItems;
maxItems += stepSize;
newItems = new RasterObject* [maxItems+1];
memcpy( newItems, allItems, numItems * sizeof(RasterObject*) );
delete [] allItems;
allItems = newItems;
stepSize *= 2;
}
// insert the item
i = numItems++;
j = i >> 1;
 while ((i > 1) && (cObject->zmin < allItems[j]->zmin)) {
allItems[i] = allItems[j];
i = j;
j = i >> 1;
}

allItems[i] = cObject;
}
RasterObject *get()
 {
int i = 1, j;
RasterObject *lItem,*cItem;
 if (numItems <= 1) {
cItem = NULL;
 } else {
cItem = allItems[1];
numItems--;
lItem = allItems[numItems];

 while (i <= numItems / 2) {
j = 2 * i;
if (j >= numItems) break;

if ((j < (numItems-1)) && (allItems[j]->zmin > allItems[j+1]->zmin))
j++;

if (allItems[j]->zmin > lItem->zmin)
break;

allItems[i] = allItems[j];
i = j;
}
allItems[i] = lItem;
}

return cItem;
}

RasterObject **allItems; // array of the heap
int numItems, maxItems, stepSize; // misc junk
};

 class Reyes {
public:
void render();
};

void Reyes::render()
  {
GeoPrimQueue gp_queue;

GeoPrim *gprim = NULL;

while( (gprim = gp_queue.get()) != NULL )
 {
// bound in camera space
// (including displacement and motion blur)
gprim->bound();

// frustum culling and backface culling
if( gprim->on_screen() )
 {
// the bound can be transformed into screen space
if( gprim->projectable() )
 {
// transform the bound into screen space
// (including depth of field)
// sort the gprim into buckets which its bound covers
gprim->project();
}
else
 {
// too large, divide and conquer
// add back to the queue
gprim->split( &gp_queue );
}
}

delete gprim;
}
}

void Bucket::render()
  {
RasterObjectQueue gp_queue;

RasterObject *gprim = NULL;

while( (gprim = gp_queue.get()) != NULL )
 {
// bound in camera space
// (including displacement and motion blur)
gprim->bound();

// frustum culling and backface culling
// occlusion culling
// transform the bound into screen space
// (including depth of field)
if( gprim->on_bucket() )
 {
// is a grid, draw it
if( gprim->is_grid() )
 {
ShadingGrid *grid = (ShadingGrid *) gprim;

// evaluate
// displacement shader
// surface shader
// light shader
// atmosphere shader
grid->shade();

// stitch cracks between micropolygon grids

// bust into individual micropolygons
// bound each micropolygon
// frustum culling and backface culling
// occlusion culling
// determine which pixels the micropolygons
// cover and stochastic sampling in pixels
grid->sample();
}
else
 {
// small enough to dice
if( gprim->diceable() )
 {
// dice into grids
gprim->dice();
}
else
 {
// too large, divide and conquer
// add back to the queue
gprim->split( &gp_queue );
}
}
}
}

// reconstruct the image portion of this bucket
}


|