#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
}