andrewmac wrote: I've left culling alone for the time being because I want to do it well and try to avoid the pitfalls you describe. You sound experienced on the topic so any advice you can offer is much appreciated.
Essentially I've built the scene processing in a way that lends itself very well to various culling methods, but I haven't settled on one yet.
The only advice I can give here is to implement a common interface. You already have a method for marking dirty scene objects, but just make sure that it extends to the transform and bounds of an object.
There's no way you can implement a single partitioning scheme for an engine that is supposed to be general purpose. As an example, what works well for indoor scenes will be a memory hog for outdoor scenes and what works well for self contained scenes is terrible in all ways for any sort of streaming content. So it's important that you at least define a clear interface for how the partitioning scheme is supposed to work with the render system.
Then other people can write their own schemes, probably as plug-ins ( Ogre does much the same thing) and contribute to the project. If you really want too provide a set of pre-made culling systems, you could always implement a wrapper for the various Bullet scene types and use collision objects to represent the meshes and lights as well as the camera frustum. It might not be optimal, but it would be better than nothing and a good place to start without having to write a lot of code.