I know this is definitely the question people would ask and in fact what you have mention is more straightforward and you clearly saw that I was not satisfied with the current implementation, but the problem was a bit complicated, so let me show you the “simplest” example from that original C++ code:
#include <sb7.h>
class simpleclear_app : public sb7::application
{
void init()
{
static const char title[] = "OpenGL SuperBible - Simple Clear";
sb7::application::init();
memcpy(info.title, title, sizeof(title));
}
virtual void render(double currentTime)
{
static const GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, red);
}
};
DECLARE_MAIN(simpleclear_app)
The example of the book is really like what you have mentioned, which is a complete black box and I had no idea how sb7.h and DECLARE_MAIN() works in the first place, not to mention some other “in-house” libraries hide under the sb7.h that have already been replaced with some zig dependencies, and it has no documentation (as far as I have read the book) about that part in the book and it kept on telling me just call and override the function in sb7.h. I have read an earlier edition of the book in a school library (no longer have the access) where it didn’t have such encrapsulation and I do think that is clearer than the latest edition; however, 7th edition is the only version I have, and it is also the only version that is available on the book store, so I have to stick with what I have.
As a result, instead of writing the code in a more optimal and more idiomatic way, I have to write code aligning to the book so that not only I can understand what sb7.h is really doing, but it also offer a smoother transition for migrating the code from C++ to zig without rewrite all the configuration from sketch for every projects, so I did the function pointers.
I want to write what you have mentioned which I did in my first triangle as well, but your example will end up putting all the code inside the original run()
function back to the main, flooding with full of all the original configurations for glfw instead of showing the gl part that actually draws the shapes. Perhaps I will find a way to expose the main event loop only, but try to have a clearer separation between gl and glfw in the later version. For the “virtual” functions, I will find a better way because their callback have a strict input parameter typed with C convention, and I prefer to list the input and output type of the callback instead of repetitively correcting and guessing the callback function based on the compiler.
Some of the practice is not necessary and I definitely need some time to get rid of the OOP part of the original C++ implementation, but now I know how it works and I have a working zig solution, so It will be easier for me to improve or rewrite the code from a bad implementation.