I’m working on a simple graphics engine and I have Drawable objects which are supposed to register themselves to Renderer (by inserting them in a set) upon creation (in constructor). They also need to be sorted for rendering (by transparency, depth mask, etc.), i.e. they need to be sorted by some boolean flags.
So here is my set.
std::set<Drawable *, DrawableComp> drawable_set;
Comparison functor:
struct DrawableComp : public std::binary_function<const Drawable *, const Drawable *, bool> {
bool operator() (const Drawable * lhs, const Drawable * rhs) const
{
return *lhs < *rhs;
}
};
And overloaded operator< of Drawable:
bool Drawable::operator<(const Drawable & rhs) const
{
if (writesDepth() != rhs.writesDepth())
return !writesDepth() < !rhs.writesDepth();
else
return getSortNumber() < rhs.getSortNumber();
}
Note, this is supposed to insert Drawables into set in order so that first go objects that write to depth buffer followed by those that don’t write to depth buffer. Sort number is unique for each object.
Problem is, that doesn’t work. I get Drawables that write to depth buffer at the end of set.
Also, writeDepth() is virtual bool function. Drawable is just an abstract interface. If I make writeDepth() pure virtual, I get runtime error “pure virtual method called”. It’s not quite clear to me why is that because I never put Drawable objects in set, rather its concrete implementations.
Ok, I’ve found problem. I was registering Drawables from Drawable constructor. I had this call in constructor (registerDrawable just inserts into set):
Problem is that this sends pointer to object of type Drawable rather of some derived type, so set “doesn’t know” what derived class is and it just calls base method writeDepth().
Simple solution is to just move this call to derived constructor. Although it inserts a little mess and redundancy into my design…