Fermat
Generic Programming
Most of CUGAR's functions and data structures are C++ templates providing the flexibility and compile-time code generation needed to accomodate the exponential amount of type combinations possible in typical applications.
Just as an example, consider the following code, building a K-d tree over a set of points:
The following code snippet shows how to use this builder:
thrust::device_vector<Vector3f> points;
... // code to fill the input vector of points
thrust::device_vector<Kd_node> kd_nodes;
thrust::device_vector<uint2> kd_leaves;
thrust::device_vector<uint32> kd_index;
cugar::cuda::Kd_builder<uint64> builder( kd_index );
cugar::cuda::Kd_context kd_tree( &kd_nodes, &kd_leaves, NULL );
builder.build(
kd_tree, // output tree
kd_index, // output index
Bbox3f( Vector3f(0.0f), Vector3f(1.0f) ), // suppose all bboxes are in [0,1]^3
points.begin(), // begin iterator
points.end(), // end iterator
4 ); // target 4 objects per leaf
In the above code, the builder stores the nodes of the resulting K-d tree into a flat array of Kd_node's. But what if we wanted to store them using a different layout? It turns out the builder itself doesn't know anything about the actual output it produces, but rather, it delegates everything to an OutputTree template class which must possess the following interface:
struct OutputTree
{
void reserve_nodes(const uint32 n); // reserve space for n nodes
void reserve_leaves(const uint32 n); // reserve space for n leaves
Context get_context(); // get a context to write nodes/leaves
struct Context
{
void write_node(
const uint32 node, // node to write
const uint32 offset, // child offset
const uint32 skip_node, // skip node
const uint32 begin, // node range begin
const uint32 end, // node range end
const uint32 split_index, // split index
const uint32 split_dim, // splitting dimension
const uint32 split_plane); // splitting plane
void write_node(
const uint32 node, // node to write
const uint32 offset, // child offset
const uint32 skip_node, // skip node
const uint32 begin, // node range begin
const uint32 end); // node range end
void write_leaf(
const uint32 index, // leaf to write
const uint32 begin, // leaf range begin
const uint32 end); // leaf range end
};
};
allowing its behaviour to be completely customized. In this case, we just relied on the default implementation provided by cugar::cuda::Kd_context.

Next: Host & Device Top: mainpage