Demonstration Video
Background
This Project expands on the initial work done in the S2D
Framework Project by introducing us to what happens under the hood, as the S2D Framework is a 2D
OpenGL Framework.
Initially we were given the task of drawing a shape onto the screen manually, using screen-space
coordinates, by manually creating vertices and converting them into a polygon through OpenGL's
functions.
After this, I started to create Classes that can store Object data, such as Transform
, which
contains two Vector3
s, of which describe Position and Rotation.
Once this was completed I wrote a 2D N-gon generator and gave the data from this into Object Classes
- which formed the basis of future work with 3D models and loading in from .obj files.
Next for this was a Parent-Child relationship, which required researching how OpenGL handles its
matrices internally. The solution for this was Popping and Pushing matrices in order of how they
would be seen in something like Unity's Scene Viewer.
You Pop the Parent's matrix
, so the parent's transformations, then you Pop any
children's matrices and calculate the transformations and one the way back up you Push them back.
This is a recursive process and as such I wrote recursive function to handle this.
Texturing and Object Loading
The next few things I worked on were pretty simple:- Converting the Camera to use Perspective instead of Orthographic views.
- Use OpenGL Callbacks to get Keyboard data and write a Class to deal with the data separately.
- Convert the Scene Graph to use
LinkedList
s instead ofstd::vector
s - which improves memory efficiency as vectors may or may not free memory until it goes out of scope. - Allow the Screen to be resized without stretching the Viewport.
- Converting to all Objects to use
std::shared_ptr
s so that Heap data is managed for me through Smart Pointers.
The format of .obj files is readable in UTF-8 so understanding what each line of data does becomes somewhat simpler.
Each line of an .obj file starts with a 'token' that describes what the data on the line does. For example
v 0.4 0.1 1.0
describes a Vertex and its position relative to the centre of the
object in 3D coordinates.
Reading the data in was as simple as grabbing the 'token' and then an if statement to determine what the token does.
Texture files (.tga) on the other hand are not readable in UTF-8, however they are simply image files with a header with data.
The header is 18 bytes and describes the image file, such as its Width, Height and Bit-Depth - of which some of the data needs to be used by OpenGL to determine if:
- The image is uncompressed
- The image follows either RGB or RGBA formats
After texturing was complete, I started work on lighting and materials - even if in the OpenGL fixed pipeline it's simple.
Materials and Lighting
TheMaterial
contains 4 values, 3 float4
s for Ambient, Specular and Diffuse
and also a float
for Shininess.
Using these
Material
s in the rendering is made very simple by using
glMaterialfv()
and glMaterialf()
.
Lights are simple in fixed pipeline OpenGL too, they need the same 3
float4
s.
Then using glLightfv()
you light the scene that frame.
Text
Text functions similarly to a regularGameObject
, as such the Text
class
derives
from GameObject
.
All is needed for the functionality is a
std::string
, Transform
and Vector3
of colour.
Due to how the
SceneGraph
works, the Text
would be Sliced, if it was not a
pointer - this is because of how C++ handles memory.
If it was declared on the stack, the memory allocated would be exactly for the base type, and not the
derived class - thus losing data.