Tag: Class

2017-02 Update

I didn’t know about boxing and unboxing of primitives to objects (or much about references as it happens) when I wrote this back in 2013. Primitives like int/bool/float/char/double etc. DO get copied via the default copy constructor because they have default working copy/assignment functions. However if the Example class held an instance of, say, a DeepCopyWang object (it was the first thing I could think of) – it wouldn’t copy cleanly with the default assignment or copy constructors – any new object would just hold a reference to the original DeepCopyWang object and its properties. That is, the new object trying to be a copy of the first would be a shallow copy (i.e. it may contain references to properties of the first object) and not a deep copy (i.e. completely separate objects and all properties there-in which can be individually manipulated). So take the below with a suitably sized pinch of salt.

Still on my fundamentals trip, I’m hitting up the ‘this’ pointer. Every class that you create has a ‘this’ pointer invisibly assigned to it by the compiler. Let’s look at a simple class to see what’s going on:

You can substitute either of these classes into a project, compile it (in Release mode if you have both in there and just comment each out in turn!), and you’ll end up with byte-wise identical executables down to the very last bit. Not only are they functionally equivalent, they’re absolutely equivalent – as the compiler sees them, it’s the exact same code. Don’t take my word for it – try it out, if you’d like!

The ‘this’ pointer’s already being used, but what exactly is it doing? Well, let’s drill down into the nuts and bolts of it and take a look…

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:

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:

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):

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.

This is the third post of three, where we finally get to create a Camera class which encapsulates all the important properties of a camera suitable for FPS controls. I could, and indeed did, have this written to just use three floats for the camera position, three for the rotation, three for the movement speed etc – but it makes more sense to use a vector class to encapsulate those values into a single item and provide methods for easy manipulation, so that’s what I’ve done.

The end result of this is that although the Camera class now depends on the Vec3 class, the Camera class itself is now more concise and easier to use. If you don’t like the coupling you can easily break it and return to individual values, but I think I prefer it this way. Oh, and this class is designed to work with GLFW, although it could be very easily modified to remove that requirement and be used with SDL or something instead. In fact, we only ever use the glfwSetMousePos(x, y) method to reset the mouse position to the centre of the screen each frame!

Anyways, let’s look at the header first to see the properties and methods of the class:

Finally! Done! You can see a video of the first version of the FPS controls here – this code works identically, it’s just that the Camera is now in its own class, we’re using our own little Vec3 class to keep group and manipulate some values, and the whole thing works in a framerate independent manner thanks to the FpsManager class. Phew!

I’m working my way through C++ FAQs book by Cline and Lomow, and it’s excellent. There’s lots of issues going on with inheritance, arrays and casting that could be a real pain to deal with towards the end of system development, but that you can nip in the bud and make life easier for yourself. For example, just knowing that an array of objects of a Derived class is NOT a kind-of array of objects of the Base class can prevent you a lot of headaches…

// Book: C++ FAQs by Cline & Lomow// FAQ 136 & 137 - Is array-of Derived a kind-of array-of Base?// Answer: NO!#include <iostream>usingnamespace std;class Base
{protected:int i;public:
Base(): i(42*42){}virtual ~Base(){}virtualvoid service(){cout<<"Base::service() called.\n"<< flush;}};class Derived :public Base
{protected:// Add some extra things so that an object of type Derived is a different// size to an object of type Baseint j;float k;unsignedlong l;public:
Derived(): Base(), j(42*42*42){}virtualvoid service(){cout<<"Derived::service() called.\n"<< flush;}};// Userland functionvoid useSubscript(Base *b){cout<<"b[0].service(): "<< flush; b[0].service();cout<<"b[1].service(): "<< flush; b[1].service();// BOOM! Segfault!// This fails because the size of Base and the size of Derived are different:// "The fundamental problem is that a pointer to the first of an array-of-things// has exactly the same type as a pointer to a single thing. This was inherited// from C."//// In essence, as we're passing in Base pointers, in this case Base moves from// element to element in 16 byte intervals, but we actually provided an array// of Derived objects, which have a size of 32 bytes each, so b[1] starts// at b[0]+16, which is really only half-way through our first Derived element d[0]!//// The way to do this properly is to use a templatised container class instead.// If you tried to pass Array<Derived> as Array<Base> this would be caught at compile time.}int main(){
Derived d[10];cout<<"Base has a size of : "<<sizeof(Base)<<" bytes."<< endl;// 16 bytescout<<"Derived has a size of: "<<sizeof(Derived)<<" bytes."<< endl << endl;// 32 bytes
useSubscript(d);return0;}