quetzalfir quetzalfir - 1 month ago 13
C++ Question

C++ design for init static members, any time required

I'm developing a little game engine for Android with Android NDK and opengl es 2.0, recently the project is getting big, and I need to refactor some code, and I couldn't find a proper design pattern for the next problem.

On android when the app reach the OnPause() state the opengl context is destroyed, but the state of the variables and objects in java and c++ are maintained. so each time the player pauses and resumes the app I have to reinitializate the opengl part, buffers, shaders, vertex, etc.

I have classes like "Square" that makes "square objects", and each one has its own attributes, and each "square object" can be drawn, so the squares can access to static (opengl) members of the class, that are used to be properly rendered. So this static members must be initialized before objects can be drawn, I do it when the opengl context is created or recreated.

moreover each class has its own opengl attributes, so each class is initialized individually with its own parameters, so I want a design in what each class can set some initial parameters, pass or catch those parameters to initialize the static members of the class (I forgot to say that these parameters are private). But as I said before, these parameters need to be reinitialized each time the app is resumed.

currently I initialize these members individually like

Square::init(/*hardcoded parameters*/);
Circle::init(/*hardcoded parameters*/);
Triangle::init(/*hardcoded parameters*/);
Polygon::init(/*hardcoded parameters*/);
Shape::init(/*hardcoded parameters*/);
.
.
.
.
// Many other inits.....
.


and I want to write something like

// here all the classes with opengl part are initialized
// all init methods of each class are called here, with their respective parameters
Opengl_Initializer::init(); // <--- magic way, no other init calls


So I want to set some (static/harcoded) variables to the class and then when the opengl context be created, the class be initialized in a "magic" way, and not having the need to code the call to an init method for each class.

I've tried to use inheritance, but the issue is that I need to initialize the class not the object, also tried to implement a static object and initialize this object in the cpp file, and store a pointer to the object in a vector when this is created in his contructor, in a vector that is in the object's own class, but this design has gave me many problems.

Does anyone know some design that can help me?

EDIT: the stucture of my classes

the
init()
function is really big because
shader
and
frag
parameters are paths file and I perform some task on them, pass the result of that perform to opengl and returns me a
ID
that is the program static variable, all clases with opengl part implement this same process, the parameter
camera
is just to attach it into a camera

class Square {
// static variable all classes have
static GLuint program;

// other glparameters not in common, initialized in the same static init() method
static GLint uniform1;
static GLint uniform2;

public;
// the static init function has the same header on all the classes
static init(const char* shader, const char* frag, const char *camera);
}


and maybe some structure I'd want is

class Square {
static GLuint program;
static const char *vertex = "hardcode";
static const char *frag = "hardcode";
static const char *cam = "harcode";

static init();

/// or somethig like
static Initializer init(
"harcode shader", "hardcode frag", "hardcode camera",
[&] (void) ->void {
//this is the init function
}
);

public:

}

Answer

I suggest a versioning system, so that initialization can be automatically performed at time-of-use, but in a way that skips it very cheaply when the initialization has already been done. Something like

int global_gl_generation = 0; // increment each time you recreate the context

inline bool check_gl_generation(int& local_generation)
{
    if (local_generation == global_gl_generation)
        return false;

    local_generation = global_gl_generation;
    return true;
}

and then in each class,

class Square
{
    // static variable all classes have
    static int generation_inited;

    static GLuint program;
    static GLint uniform1;
    static GLint uniform2;

    static init(const char* shader, const char* frag, const char *camera);

public;
    void draw() override
    {
         if (check_gl_generation(generation_inited)) init(...);

         // use program, uniform1, uniform2
    }
};