Abstract Classes and Polymorphism Revisited

I’m on a fundamentals trip at the moment, so I’m going back over things I mostly understand to ensure I really understand the principles involved and not just in a vague hand-waving kind of way. Today’s fundamental revisited is abstract (pure virtual) classes and polymorphism in C++ – it’s commented to the hilt to make clear not only what’s going on but WHY it’s going on. You wouldn’t generally comment your code this heavily, but as a reminder/guide I’m fine with it:

#include <iostream>
 
using namespace std;
 
/*** ----- Shape base class - (Abstract)----- ***/
 
class Shape
{
public:
        // Only a single method needs to be a pure virtual function (which we use the '= 0'
        // phrasing to denote) to make the class an Abstract class. But we'll assign them all
        // to be pure virtual functions with no implementation.
        //
        // Note: Any class which inherits from an abstract class must implement ALL methods
        // of that abstract class!
        virtual string type()      = 0;
        virtual float  area()      = 0;
        virtual float  perimeter() = 0;
 
        // Because Shape is an abstract class we should provide it with a virtual destructor
        // If we didn't declare this as virtual then it wouldn't get called when the destructor
        // of an object of a derived class is called.
        virtual ~Shape()
        {
            cout << "Virtual Shape destructor called!" << endl;
        }
};
 
 
/*** ----- Circle derived class ----- ***/
 
class Circle : public Shape
{
public:
        // Constructor declaration
        Circle(float rad);
 
        // Derived destructor
        ~Circle()
        {
            // Nothing to do here as radius property is not allocated on the heap using the 'new' keyword.
            // If it was, however, then this would be where we'd have to free that memory.
            cout << "Derived Circle destructor called!" << endl;
 
            // Note: After this, as a Circle is a type of Shape, the Shape virtual destructor will be called.
        }
 
        // Polyomrphic public methods
        string type();
        float  area();
        float  perimeter();
 
protected:
        float radius;
};
 
Circle::Circle(float rad) : radius(rad)
{
    /***
     * Member property set in initialisation list for efficiency.
     * If we set the property in the constructor then we perform TWO operations:
     *
     *     - We construct the member property with a default value,
     *     - We then overwrite that default value with our constructor parameter.
     *
     * If we use the parameter list to initialise the value, we only perform ONE operation,
     * which is to initialise the property with the parameter we passed in. This can have
     * significant performance implications when working with large arrays of objects.
     ***/
}
 
string Circle::type()     { return "Circle";                }
float Circle::area()      { return 3.14f * radius * radius; }
float Circle::perimeter() { return 2.0f * 3.14f * radius;   }
 
 
/*** ----- Rectangle derived classs ----- ***/
 
class Rectangle : public Shape
{
public:
        // Consturctor declaration
        Rectangle(float theWidth, float theHeight);
 
        // Derived destructor
        ~Rectangle()
        {
            // Nothing to do here as width and length properties are not allocated on the heap using the 'new' keyword.
            // If they were was, however, then this would be where we'd have to free that memory.
            cout << "Derived Rectangle destructor called!" << endl;
 
            // Note: After this, as a Rectangle is a type of Shape, the Shape virtual destructor will be called.
        }
 
        // Polymorphic public methods
        string type();
        float  area();
        float  perimeter();
 
protected:
        float width;
        float length;
};
 
Rectangle::Rectangle(float theWidth, float theLength) : width(theWidth), length(theLength)
{
    // Constructor uses initialisation list rather than initialising members in constuctor.
    // See Circle constructor for reasons why.
}
 
string Rectangle::type()     { return "Rectangle";             }
float Rectangle::area()      { return width * length;          }
float Rectangle::perimeter() { return 2.0f * (width + length); }
 
 
int main()
{
    // Create an array of 10 pointers to Shape objects
    // Note: The shape objects are not instantiated to any specific class as yet!
    // In fact, as Shape is now an abstract class we CANNOT instantiate an object of type Shape!
    // That is, the following would cause a compile-time error: Shape myShape;
    Shape *shapes[10];
 
    // Create 5 Circles
    shapes[0] = new Circle(1.0f);
    shapes[1] = new Circle(2.0f);
    shapes[2] = new Circle(3.0f);
    shapes[3] = new Circle(4.0f);
    shapes[4] = new Circle(5.0f);
 
    // Create 5 Rectangles
    shapes[5] = new Rectangle(1.0f,  2.0f);
    shapes[6] = new Rectangle(2.0f,  4.0f);
    shapes[7] = new Rectangle(4.0f,  8.0f);
    shapes[8] = new Rectangle(8.0f,  16.0f);
    shapes[9] = new Rectangle(16.0f, 32.0f);
 
    // Print the shape object details for each object
    for (int loop = 0; loop < 10; loop++)
    {
        string type      = shapes[loop]->type();
        float  area      = shapes[loop]->area();
        float  perimeter = shapes[loop]->perimeter();
 
        cout << "Shape[" << loop << "]'s type = " << type << ", area = " << area << ", perimeter = " << perimeter << endl;
    }
 
    // GOTCHA: We should NOT try to free the allocated pointer to the shapes array using:
    //      delete[] shapes;
    //
    // The reason being that the array of pointers to shapes was declared like this: Shape *shapes[10];
    // This means that the array of pointers to shapes is on the STACK and not the HEAP!
    // The objects themselves are on the heap, but the pointers to objects are on the stack and
    // as such don't need to (and shouldn't) be freed!
    //
    // Instead, we should free the memory used by each shape like this:
    // Note: As we have an array of pointers to Shapes, and Shape has a virtual destructor,
    // the derived class destructor will be called and then the base class destructor will be called.
    for (int loop = 0; loop < 10; loop++)
    {
        delete shapes[loop];
    }
 
    return 0;
}

What would happen if we did NOT declare Shape as an abstract class? Well, we’d have to provide implementations for the type(), area() and perimeter() methods for Shape – but that’s about it. The polymorphism part would still work, that is, we could still create an array of pointers to a Shape, and then instantiate each shape as a Circle or a Rectangle as we see fit – and the correct functions would execute for each derived class.

However, it makes good sense to declare Shape as an abstract class so that we can’t instantiate it (even if we wanted to), in the same way that we’d make a Car class abstract. You can’t go out and buy a Car – it’s generic. You can buy a Ford Escort, or a Hyundai i30 or even a Ferrari F40, but you can’t buy a car in the same way that you can’t (technically) eat food or drink beer.

Doesn’t stop me trying though. Cheers! =D

How To: Read and Write ASCII and Binary Files in C++

I’m working on my C++ fundamentals at the moment, so I took a little time to cover reading and writing objects to/from files in ASCII and binary formats. I’ve worked with Java’s serializable mechanism before and liked it, so I was interested to see how C++ handled serialisation. In its usual C++ way; it does so at a lower level than you might expect.

Reading Strings From Binary Files

One of the interesting things I found was that if you write a string to a binary file, you can’t get it back because there’s no way to find its length. As you might imagine, the solution to this is to add a null-terminator (i.e. ‘\0’) at the end of your string, so you can pull it back in char-by-char and stop when you hit the terminator. This isn’t going to be very fast as we’re reading in such tiny (1 Byte) chunks – but depending on your scenario it may be perfectly acceptable:

// Method to read a string from a binary file by reading a char at a time until we hit the null-terminator
static string readBinaryString()
{
	string tempString = "";
	char tempChar;
 
	do {
		// Read a single char worth of data from the file (i.e. 1 byte)
		infileBinary.read( (char*)&tempChar, 1 );
 
		// If the character we read isn't a null-terminator, add it onto the end of the string
		if (tempChar != '\0')
		{
			tempString += tempChar;
		}
 
	} while (tempChar != '\0'); // Keep trucking until we hit the null-character that signifies the end of the string
 
	// Return the string we've just built
	return tempString;
}

There’s other ways of reading strings back from binary files, like writing the size of the string first, and then the string itself. When reading, you’d then read the size first (for example, as a 4 Byte unsigned int), and then read however many Bytes of data as specified by the size you just read. Or, alternatively, you can simply not use strings – instead, have a fixed size char array so, for example, name is always 30 characters. You might not use all 30, but even if you waste like 20 chars or so on average – so what? It’s only 20 Bytes. Then, you can just go: read 30 bytes of data and store it in my name char array, no null-terminator required.

Why Use Binary?

BenderBinary

Another interesting thing is why you’d bother storing things in binary in the first place – once your data’s in binary it’s not human-readable anymore, you need a hex editor if you really want to to modify it, and just… why? The answer lies in size and efficiency.

If we want to store an integer value, then typically an int is 4 Bytes. So lets say we had an unsigned int and we wanted to store the maximum value we can fit in that 4 bytes, in that case we’d be be storing the value 4,294,967,295 (just under 4.3 billion). Now, if we wanted to store that as a char array to keep things human readable, how many chars would we need? Counting them up gives us 10 chars worth of data (we won’t count the commas – I just put those in for formatting, and we’ll leave off any kind of terminator for now).

So, at 1 Byte of data per char, that’s 10 Bytes. What about if we wanted to store it in binary format? Well, we already said that one unsigned byte takes 4 Bytes – so there’s our answer – which means we’ve saved 6 Bytes of bloat on this one value alone. When you start working with 3D models, which might have thousands or even millions or vertices, each of which is typically 3 floats (x/y/z location) and maybe another 3 floats on top of that per vertex (x/y/z surface normal), and we may also have colour values (r/g/b/a) and maybe texture coordinates (s/t/[also p if 3D textures]) — we’re looking at a huge amount of data in a single model (and this doesn’t even account for multiple animation frames of a model!).

When our files get this big we’re never going to manually go into the data and twiddle it, so we gain nothing by keeping it human-readable. In fact, we lose time in loading/processing/writing the data as it will be significantly larger in ASCII than pure binary. So even though it’s a little bit more work to set up the read/write in binary, we gain a lot down the line by doing so.

Those of you who’re sharp as a tack will have noticed that I picked a large unsigned integer value (10 chars) to store in our example, and you may well be wondering what if we stored a small value, like something between 0 and 9 instead? Well, in that specific case we’d actually save 3 Bytes by storing it as a char (1 Byte each) rather than an unsigned int (4 Bytes each). But… if you were dealing with such a small range, you can only get a range of between 0 and 9 as a char (1 Byte) while you can store a value in the range -128 to +127 when treating the same Byte as a signed numerical type (or 0 to 255 unsigned) for the exact same storage. In effect, you’re never going to gain anything by using chars over numeric types!

If you really wanted to maximise your storage you can go further by using a tightly packed bit field (cppreference.com, wikipedia) instead of a ‘wasteful’ numeric type with all its fancy-pants byte alignment =P (Although bit-scrimper beware: unpacking non-boundary aligned data can come with performance penalties!).

Anyways, that’s the theory. You can find some heavily commented source code for reading/writing objects (which include a string property) to files in ASCII and binary formats below. In this simple example we write and then read two objects to a file in ASCII mode, and then do the exact same thing in binary mode, which results in file sizes of: 156 Bytes (ASCII) Vs. 33 Bytes (Binary).

Cheers!

Continue reading How To: Read and Write ASCII and Binary Files in C++

A Simple C++ OpenGL Shader Loader

Update: There’s a re-worked and improved version of this shader loading code here: https://r3dux.org/2015/01/a-simple-c-opengl-shader-loader-improved/ – you should probably use that instead of this.


I’ve been doing a bunch of OpenGL programming recently and wanted to create my own shader classes to make setting up shaders as easy as possible – so I did ;-) To create vertex and fragment shaders and tie them into a shader program you can just import the Shader.hpp and ShaderProgram.hpp classes and use code like the following:

// Set up vertex shader
Shader vertexShader(GL_VERTEX_SHADER);
vertexShader.loadFromFile("MyVertexShader.vert");
vertexShader.compile();
 
// Set up fragment shader
Shader fragmentShader(GL_FRAGMENT_SHADER);
fragmentShader.loadFromFile("MyFragmentShader.frag");
fragmentShader.compile();
 
// Set up shader program
shaderProgram = new ShaderProgram();
shaderProgram->attachShader(vertexShader);
shaderProgram->attachShader(fragmentShader);
shaderProgram->linkProgram();

There’s also a loadFromString(some-string-containing-GLSL-source-code) method, if that’s your preference.

The ShaderProgram class uses a string/int map as a key/value pair, so to add attributes or uniforms you just specify their name and they’ll have a location assigned to them:

// Add the shader attributes
shaderProgram->addAttribute("vVertex");
// ...
 
// Add the shader uniforms
shaderProgram->addUniform("pMatrix");
// ...

The ShaderProgram class then uses two methods called attribute and uniform to return the bound locations (you could argue that I should have called these methods getAttribute and getUniform – but I felt that just attribute and uniform were cleaner in use. Feel free to mod if you feel strongly about it). When binding vertex attribute pointers you can use code like this:

// Set up a vertex buffer object to hold the vertex position data
GLuint vertexBufferId;
glGenBuffers(1, &vertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
glBufferData(GL_ARRAY_BUFFER, model.getVertexDataSizeBytes(), model.getVertexData(), GL_STATIC_DRAW);
 
// Set up the vertex attribute pointer for the vVertex attribute
glVertexAttribPointer(
    shaderProgram->attribute("vVertex"),  // Attribute location
    VERTEX_COMPONENTS,                    // Number of elements per vertex, here (x,y,z), so 3
    GL_FLOAT,                             // Data type of each element
    GL_FALSE,                             // Normalised?
    0,                                    // Stride
    0                                     // Offset
);

Finally, when drawing your geometry you can get just enable the shader program, provide the location and data for bound uniforms, and then disable it like this (I’m using the GL Mathematics library for matrices – you can use anything you fancy):

shaderProgram->use();
 
    // Provide uniform data
    glUniformMatrix4fv( shaderProgram->uniform("mMatrix"), 1, GL_FALSE, glm::value_ptr(mMatrix) );
    // ...
 
    // Draw stuff
 
shaderProgram->disable();

That’s pretty much it – nice and simple. I haven’t done anything with geometry shaders yet so I’ve no idea if there’s anything else you’ll need, but if so it likely won’t be too tricky a job to implement it yourself. Anyways, you can look at the source code for the classes themselves below, and I’ll put the two classes in a zip file here: ShaderHelperClasses.zip.

As a final note, you can’t create anything shader-y without having a valid OpenGL rendering context (i.e. a window to draw stuff to) or the code will segfault – that’s just how it works. The easiest way around this if you want to keep a global ShaderProgram object around is to create it as a pointer (i.e. ShaderProgram *shaderProgram;) and then initialise it later on when you’ve got the window open with shaderProgram = new ShaderProgram(); like I’ve done above.

Cheers! =D

Source code after the jump…

How To: Transfer elements between vectors in C++

Sometimes I end up needing to do this, so I re-implement the functionality… And it segfaults or behaves strangely. This time I’ll write it down somewhere I know where I can find it!

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. int main()
  8. {
  9. 	// Create an empty vector of type string for our shopping list
  10. 	vector<string> shoppingList;
  11.  
  12. 	// Add a few items to it
  13. 	shoppingList.push_back("Milk");
  14. 	shoppingList.push_back("Bread");
  15. 	shoppingList.push_back("Eggs");
  16.  
  17. 	// Create an empty vector of type string for our purchases
  18. 	vector<string> purchases;
  19.  
  20. 	// Create a string to hold the user's answer
  21. 	string answer;
  22.  
  23. 	// Transfer items bought from the shopping list to the purchases list (includes removal from the shoppingList vector)
  24. 	vector<string>::iterator i = shoppingList.begin();
  25. 	while (i != shoppingList.end() )
  26. 	{
  27. 		cout << "Item: " << *i << endl;
  28. 		cout << "Purchase item? (y/n)" << endl;
  29.  
  30. 		cin >> answer;
  31.  
  32. 		// If we said yes...
  33. 		if (answer == "y")
  34. 		{
  35. 			// ...add the item to the purchases vector and...
  36. 			purchases.push_back(*i);
  37.  
  38. 			// ...remove the item from the shoppingList vector. Erase returns an
  39. 			// iterator which points at the next element in the vector, so we need to
  40. 			// skip incrementing the iterator in this case or we might go out of bounds!
  41. 			i = shoppingList.erase(i);
  42. 		}
  43. 		else // Otherwise just move on to the next item!
  44. 		{
  45. 			i++;
  46. 		}
  47. 	}
  48.  
  49. 	cout << endl;
  50.  
  51. 	// Display both lists
  52. 	cout << "----- Shopping List ----" << endl;
  53. 	for (i = shoppingList.begin(); i != shoppingList.end(); i++)
  54. 	{
  55. 		cout << *i << endl;
  56. 	}
  57.  
  58. 	cout << endl;
  59.  
  60. 	cout << "----- Purchases ----" << endl;
  61. 	for (i = purchases.begin(); i != purchases.end(); i++)
  62. 	{
  63. 		cout << *i << endl;
  64. 	}
  65.  
  66. 	cout << endl;
  67.  
  68. 	return 0;
  69. }

TLTB ;-)

How-To: Create A Simple OpenGL 2D Particle Fountain in C++

I was recently asked about some particle systems I’d put together, so in response, this isn’t really a “look what I’ve coded” post – instead, it’s more of a “this is an easy way to set up a particle system framework” post.

To demonstrate the setup of a particle system using OpenGL, I’ve put together some simple starter code which displays a 2D particle fountain. I was going to just dump this code as a zipped project into a reply, but then (as my wife pointed out) it would be pretty much buried in the comments, so if other people starting OpenGL coding wanted to learn the basics of particle systems my code wouldn’t be as visible. As such, I’ve made this into a separate post – and all our example code does is this:

It’s a dirt-simple effect, but what it does isn’t so important right now – it’s deliberately simple. How it does what it does is what we’ll talk about.

Looking at particle systems from a high level – you generally have to choose between two different approaches to the system as a whole:

  1. You have a fixed number of particles (i.e. you have a fixed size array of however many particles) and you reset each particle to “recycle” it, or
  2. You have a dynamic number of particles (i.e. you have a dynamically resizable array) and you destroy each particle and create a new one as required.

I’ve gone with the latter approach for this code using a vector of particles (nothing to do with Vec2/Vec3 math – just the name of resizable array kinda construct). Admittedly, there’s more overhead in the creation and destruction of particles, but on the upside you don’t get that initial rush of particles you get when using fixed size arrays and as soon as you start the program BLAM! All your particles going at once.

To demonstrate what I mean, in the video below I’ve modified the code to instantiate ALL particles up to the particle limit at once, and then as soon as a particle goes off the bottom of the screen it gets destroyed and a new particle is created. The effect of which is that you get a single big burst of particles, and then as they all get destroyed and recreated at different times they turn into a smooth flow within a couple of seconds:

If you’re using a fixed size particle array, you’ll need to implement some mechanism to delay the instantiation or “launch” of the particles – for example, you might give each particle a random framesUntilLaunch value and decrease it by 1 each frame until it gets to 0 and you can let the particle do its thing. I wrote such a delay system for some fireworks code I did a while back if you’d like to see a concrete example.

Anyways, back at this code, our main is using three main classes to encapsulate data and provide methods to manipulate it:

  • Colour4f.hpp – A class to store a colour as red/green/blue/alpha floating point values and manipulate ’em (including interpolation of colours),
  • Vec2.hpp – A templatised class to store two values as a vector (Not a resizable array this time! An actually “euclidian vector” – i.e. two values which represent a direction and magnitude). It also includes lots of overloaded operators so you can add two vectors together (“up” + “right” gives you “up-right” etc.), multiply a vector by a scalar (i.e. moving “up-right” multiplied by 10 means you’re now moving up-right ten times as fast). By templatised, I mean that you can create a Vec2 of ints, or floats, or doubles, or shorts, or whatever numeric type makes sense for your application – take a look at the source below if you want examples, and finally
  • Particle2D.hpp – A particle class which uses the above Colour4f and Vec2 classes to provide powerful movement and colour modification options in a small & easy to use package.

You can download the complete source code as a Code::Blocks project here, if you’d like: PointSprite_Particle_Fountain_2D.zip.

Note: As my OS of choice is GNU/Linux (LMDE, to be specific), the source files provided will have Linux line-endings – so you’ll need to open them with a good text editor like Notepad++ if you’re in in Windows, otherwise each file will look like a single massive block of noise!

Or, if you’d prefer to just browse the source code so you can copy and paste sections, you’ll find it all laid out below.

I love particle systems – you can do some visually stunning things with really simple code, or you can do amazing things if you take it further. Either way, I hope you have a lot of fun with them (there’s lots more particle stuff on this site if you’re looking for inspiration – try Actionscript tag for a start!) – and if you make anything cool or pretty using and you think I’ve helped – please do show me or let me know – I’ve love to see or hear about what you’ve done! =D

Also – if you make this – show me how, okay?

Cheers!

Continue reading How-To: Create A Simple OpenGL 2D Particle Fountain in C++