C++ - OpenGL - Using the OR and LEFT SHIFT operators to retrieve the display mode with strings

The following tutorial will show you how to exploit data taken from a binary variable.

In order to explain it, we are going to use the GLUT OpenGL library.

The display mode uses indeed this kind of mechanism with the OR operator, symbolized with the famous pipe: "|".

And we'll use the LEFT SHIFT operator "<<" to check data.

Let's dive into these binary operators.

First of all

In the GLUT library there are defines in the freeglut_std.h file such as GLUT_RBG, GLUT_INDEX, GLUT_DOUBLE, GLUT_DEPTH, etc.

What's interesting with these defines is that it's possible to combine them to create a unique data exploited later by the glutInitDisplayMode() function with only one argument.

How is it possible?

With the OR operator mechanism.

Indeed, it's possible to have something like that when defining your mode variable:

unsigned int mode = GLUT_DOUBLE | GLUT_STENCIL;

In this example, we can see that we are using two defines: GLUT_DOUBLE and GLUT_STENCIL.

And what is fun is that they combine into an only one variable because we use the OR operator "|".

In the code below, we will create a function to create an array with these defines then another one to check and retrieve the defines specified in the mode variable.

In the initModeMap() function we'll use the LEFT SHIFT binary operator "<<" to shift the value to 1 bit each time to check every bit of the data.

And retrieve the corresponding values.

Code

main.cpp

#include <iostream>

#include <GL\glew.h>        // the opengl library wrapped by extended features
#include <GL\freeglut.h>

#include "Badprog.hh"

using namespace std;

/**
* Main, what else?
*/
int main(int argc, char** argv) {
    Badprog bp;
    int x = 500;
    int y = 500;
    int width = 250;
    int height = 250;
    unsigned int mode = GLUT_DOUBLE | GLUT_STENCIL;

    bp.init(argc, argv);
    bp.setWindowPosition(x, y);
    bp.setWindowSize(width, height);
    bp.setDisplayMode(mode);
    bp.setWindowName(BADPROG_TITLE);
    bp.createWindow();
    
    cout << "Display mode: \t\t" << bp.getDisplayMode() << endl;
    cout << "Window name: \t\t" << bp.getWindowName() << endl;
    cout << "Window position X: \t" << bp.getWindowPositionX() << endl;
    cout << "Window position Y: \t" << bp.getWindowPositionY() << endl;
    cout << "Window size WIDTH: \t" << bp.getWindowSizeW() << endl;
    cout << "Window size HEIGHT: \t" << bp.getWindowSizeH() << endl;
    bp.consoleModeDisplay();
    bp.loop();

    return 0;
}

Badprog.hh

#pragma once

#include <vector>
#include <string>
#include <map>

#define BADPROG_TITLE "BadproG - Hello world :D"
#define BADPROG_CHANGE_ME "Change me please :D"

using namespace std;

class Badprog
{
public:

    // constructor
    Badprog();

    // init
    void init(int ac, char *av[]);
    void initWindow(int x, int y, int width, int height);
    
    // display mode
    void setDisplayMode(unsigned int mode);
    unsigned int getDisplayMode();
    void initModeMap();
    vector<string> findMode(unsigned int mode);
    void consoleModeDisplay();
    const map<unsigned int, string> getModeMap();

    // window name
    void setWindowName(const char *name);
    const char *getWindowName();
    
    // creation
    void createWindow();

    // position
    void setWindowPositionX(int x);
    void setWindowPositionY(int y);
    void setWindowPosition(int x, int y);
    int getWindowPositionX();
    int getWindowPositionY();

    // size
    void setWindowSizeW(int w);
    void setWindowSizeH(int h);
    void setWindowSize(int w, int h);
    int getWindowSizeW();
    int getWindowSizeH();

    // loop
    void loop();

    // destructor
    virtual ~Badprog();

private:
    unsigned int _mode;
    map<unsigned int, string>_modeMap;
    const char *_name;
    int _x;
    int _y;
    int _w;    // width
    int _h;    // height
};

Badprog.cpp

#include "Badprog.hh"

#include <GL\freeglut.h>    // library cross-platform toolkit windows and managing input operations

#include <iostream>

#define ZERO        0x0000
#define ONE            0x0001
#define TWO            0x0002
#define MODE_MAX    0x0200

/**
* Basic constructor.
*/
Badprog::Badprog() {
}


/**
* Initializing the FreeGLUT library with classic parameters.
*/
void Badprog::init(int ac, char *av[]) {
    // A. init
    glutInit(&ac, av);                                // 1. inits glut with arguments from the shell
}

/**
* Initializing the window.
*/
void Badprog::initWindow(int x, int y, int width, int height) {
    glutInitWindowPosition(x, y);                // 6. distance from the top-left screen
    glutInitWindowSize(width, height);                    // 3. window size
}

/**
* Initializing the window.
*/
void Badprog::setWindowPosition(int x, int y) {
    this->_x = x;
    this->_y = y;
    glutInitWindowPosition(x, y);
}

/**
* Setting window position X axis
*/
void Badprog::setWindowPositionX(int x) {
    this->_x = x;
    glutInitWindowPosition(x, this->_y);
}

/**
* Setting window position Y axis
*/
void Badprog::setWindowPositionY(int y) {
    this->_y = y;
    glutInitWindowPosition(this->_x, y);
}


/**
* Initializing the window.
*/
int Badprog::getWindowPositionX() {
    return this->_x;
}

/**
* Initializing the window.
*/
int Badprog::getWindowPositionY() {
    return this->_y;
}

/**
* Initializing the window.
*/
void Badprog::setWindowSize(int w, int h) {
    this->_w = w;
    this->_h = h;
    glutInitWindowSize(w, h);
}

/**
* Setting window position X axis
*/
void Badprog::setWindowSizeW(int w) {
    this->_w = w;
    glutInitWindowPosition(w, this->_h);
}

/**
* Setting window position Y axis
*/
void Badprog::setWindowSizeH(int h) {
    this->_h = h;
    glutInitWindowPosition(this->_w, h);
}


/**
* Get windows size WIDTH.
*/
int Badprog::getWindowSizeW() {
    return this->_w;
}

/**
* Get windows size HEIGHT.
*/
int Badprog::getWindowSizeH() {
    return this->_h;
}

/**
* Creating the main window.
*/
void Badprog::setWindowName(const char *name) {
    this->_name = name;
}

/**
* Creating the main window.
*/
const char *Badprog::getWindowName() {
    return this->_name;
}


/**
* Creating the main window.
*/
void Badprog::createWindow() {
    if (this->_name == "") {
        this->_name = BADPROG_CHANGE_ME;
    }
    glutCreateWindow(this->_name);
}


/*********************************************
***** MODE ********************************
**********************************************/

/**
* Initializing the display mode.
*/
void Badprog::setDisplayMode(unsigned int mode) {
    if (mode == NULL) {
        mode = ZERO;
    }
    this->_mode = mode;
    this->initModeMap();
    glutInitDisplayMode(mode);
}

/**
* Gets the display mode.
*/
unsigned int Badprog::getDisplayMode() {
    return this->_mode;
}


/**
* Initializing mode map.
*/
void Badprog::initModeMap() {
    vector <string> allMode = {
        "rgba",
        "index",
        "double",
        "accum",
        "alpha",
        "depth",
        "stencil",
        "multisample",
        "stereo",
        "luminance"
    };
    uint8_t i = ZERO;
    uint16_t j = ONE;

    this->_modeMap[ZERO] = allMode[i];
    while (i < allMode.size() && j <= MODE_MAX) {
        i++;
        this->_modeMap[j] = allMode[i];
        j <<= ONE;
        if (j == 0x0040) { // 64
            j <<= ONE;
        }
    }
}

/**
* It retrieves the display mode values as a vector in order to display
* corresponding strings.
*/
vector<string> Badprog::findMode(unsigned int mode) {
    vector<string> value;
    uint16_t checker = ZERO;

    map<unsigned int, string>::iterator it;
    it = this->_modeMap.begin();    // initialises the iterator
    it++;                            // increments to get the _modeMap[1] value
    while (it != this->_modeMap.end()) {
        checker = (mode)& (it->first);  // masks to test the value for each bit
        if (checker) {                 // masks is positive
            value.push_back(this->_modeMap[it->first]);
        }
        it++;
    }
    return value;
}

/**
* Display message on the console.
*/
void Badprog::consoleModeDisplay() {
    vector<string> modeMap;
    vector<string>::iterator it;
    unsigned short int j;

    if (this->_modeMap.empty()) {
        cout << "Error - The mode seems empty." << endl;
        return;
    }
    j = 0;
    modeMap = this->findMode(this->getDisplayMode());
    cout << "Display mode is made of: \t";

    if (modeMap.size() == 1 && this->_mode == ZERO) {
        cout <<  this->_modeMap[0] << " | " << " single";
    }
    else {
        for (it = modeMap.begin(); it != modeMap.end(); it++) {
            if ((modeMap.size() - 1) == j) { // checks we have the last mode
                cout << *it;
            }
            else {                            // if it's not the last mode, add "|"
                cout << *it << " | ";
            }
            j++;
        }
    }
    
    cout << endl;
}

/**
* Infinite loop
*/
void Badprog::loop() {
    while (1337);
}

/**
* Gets the current mode as a map.
*/
const map<unsigned int, string> Badprog::getModeMap() {
    return this->_modeMap;
}

/**
* Destructor.
*/
Badprog::~Badprog() {
}

Conclusion

The binary operators are widely used in electronics.

So it's always interesting to try to understand it with another context.

And in this case, the OpenGL context.

Good job, if you got it.

If not, don't hesitate to ask questions. cool

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.