diff --git a/BaseFramework.sln b/BaseFramework.sln
new file mode 100644
index 0000000..755975a
--- /dev/null
+++ b/BaseFramework.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29326.143
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseFramework", "BaseFramework.vcxproj", "{E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Debug|x64.ActiveCfg = Debug|x64
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Debug|x64.Build.0 = Debug|x64
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Debug|x86.ActiveCfg = Debug|Win32
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Debug|x86.Build.0 = Debug|Win32
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Release|x64.ActiveCfg = Release|x64
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Release|x64.Build.0 = Release|x64
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Release|x86.ActiveCfg = Release|Win32
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4CC4CC5A-427D-44AF-A956-84094536848C}
+ EndGlobalSection
+EndGlobal
diff --git a/BaseFramework.vcxproj b/BaseFramework.vcxproj
new file mode 100644
index 0000000..64ce85e
--- /dev/null
+++ b/BaseFramework.vcxproj
@@ -0,0 +1,173 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ {E78A1901-BE1C-4A6F-9C82-3BFC672AFE28}
+ Win32Proj
+ BaseFramework
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+ Level3
+ Disabled
+ true
+ WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+ Disabled
+ true
+ _DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ true
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BaseFramework.vcxproj.filters b/BaseFramework.vcxproj.filters
new file mode 100644
index 0000000..9484823
--- /dev/null
+++ b/BaseFramework.vcxproj.filters
@@ -0,0 +1,70 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/Bitmap.cpp b/Bitmap.cpp
new file mode 100644
index 0000000..3d1383f
--- /dev/null
+++ b/Bitmap.cpp
@@ -0,0 +1,111 @@
+#include "Bitmap.h"
+
+Bitmap::Bitmap()
+{
+}
+
+Bitmap::~Bitmap()
+{
+ // Ensure we clean up any existing bitmap
+ DeleteBitmap();
+}
+
+// Create a new bitmap of the specified width and height, deleting any existing bitmap
+//
+// Returns value of false if bitmap cannot be created.
+
+bool Bitmap::Create(HWND hWnd, unsigned int width, unsigned int height)
+{
+ bool status = false;
+ HDC hDc;
+
+ // Delete any existing bitmap
+ DeleteBitmap();
+
+ // Create a device context compatible with the window device context
+ hDc = ::GetDC(hWnd);
+ _width = width;
+ _height = height;
+ _hMemDC = CreateCompatibleDC(hDc);
+ if (_hMemDC != 0)
+ {
+ // Create a bitmap compatible with the window
+ _hBitmap = CreateCompatibleBitmap(hDc, _width, _height);
+ if (_hBitmap != 0)
+ {
+ // Select the bitmap into the new device context, saving any old bitmap handle
+ _hOldBitmap = static_cast(SelectObject(_hMemDC, _hBitmap));
+ status = true;
+ }
+ }
+ // Release the device context for the window
+ ReleaseDC(hWnd, hDc);
+ return status;
+}
+
+// Return device context of bitmap
+
+HDC Bitmap::GetDC() const
+{
+ return _hMemDC;
+}
+
+// Return width of bitmap
+
+unsigned int Bitmap::GetWidth() const
+{
+ return _width;
+}
+
+// Return height of bitmap
+
+unsigned int Bitmap::GetHeight() const
+{
+ return _height;
+}
+
+// Delete any existing bitmap
+
+void Bitmap::DeleteBitmap()
+{
+ // Select any default bitmap that existed for the device context
+ if (_hOldBitmap != 0 && _hMemDC != 0)
+ {
+ SelectObject(_hMemDC, _hOldBitmap);
+ _hOldBitmap = 0;
+ }
+ // Delete any existing bitmap
+ if (_hBitmap != 0)
+ {
+ DeleteObject(_hBitmap);
+ _hBitmap = 0;
+ }
+ // Delete any existing bitmap device context
+ if (_hMemDC != 0)
+ {
+ DeleteDC(_hMemDC);
+ _hMemDC = 0;
+ }
+}
+
+// Clear bitmap using the specified brush
+
+void Bitmap::Clear(HBRUSH hBrush) const
+{
+ RECT rect;
+
+ rect.left = 0;
+ rect.right = _width;
+ rect.top = 0;
+ rect.bottom = _height;
+ FillRect(_hMemDC, &rect, hBrush);
+}
+
+// Clear bitmap using the specified colour
+
+void Bitmap::Clear(COLORREF colour) const
+{
+ HBRUSH brush = CreateSolidBrush(colour);
+ Clear(brush);
+ DeleteObject(brush);
+}
diff --git a/Bitmap.h b/Bitmap.h
new file mode 100644
index 0000000..d663647
--- /dev/null
+++ b/Bitmap.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "windows.h"
+
+class Bitmap
+{
+public:
+ Bitmap();
+ ~Bitmap();
+
+ bool Create(HWND hWnd, unsigned int width, unsigned int height);
+ HDC GetDC() const;
+ unsigned int GetWidth() const;
+ unsigned int GetHeight() const;
+ void Clear(HBRUSH hBrush) const;
+ void Clear(COLORREF colour) const;
+
+private:
+ HBITMAP _hBitmap{ 0 };
+ HBITMAP _hOldBitmap{ 0 };
+ HDC _hMemDC{ 0 };
+ unsigned int _width{ 0 };
+ unsigned int _height{ 0 };
+
+ void DeleteBitmap();
+};
+
diff --git a/Framework.cpp b/Framework.cpp
new file mode 100644
index 0000000..c5c6d21
--- /dev/null
+++ b/Framework.cpp
@@ -0,0 +1,275 @@
+#include "Framework.h"
+
+const unsigned int DEFAULT_FRAMERATE = 30;
+
+// Reference to ourselves - primarily used to access the message handler correctly
+// This is initialised in the constructor
+
+Framework * _thisFramework = NULL;
+
+// Flag set once the framework has been successfully initialised
+
+bool isInitialised = false;
+
+// Forward declaration of our window procedure
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
+ _In_opt_ HINSTANCE hPrevInstance,
+ _In_ LPWSTR lpCmdLine,
+ _In_ int nCmdShow)
+{
+ UNREFERENCED_PARAMETER(hPrevInstance);
+ UNREFERENCED_PARAMETER(lpCmdLine);
+
+ // We can only run if an instance of a class that inherits from Framework
+ // has been created
+ if (_thisFramework)
+ {
+ return _thisFramework->Run(hInstance, nCmdShow);
+ }
+ return -1;
+}
+
+Framework::Framework() : Framework(800, 600)
+{
+}
+
+Framework::Framework(unsigned int width, unsigned int height)
+ : _hInstance(0), _hWnd(0), _width(width), _height(height)
+{
+ _thisFramework = this;
+}
+
+Framework::~Framework()
+{
+}
+
+int Framework::Run(HINSTANCE hInstance, int nCmdShow)
+{
+ int returnValue;
+
+ _hInstance = hInstance;
+ if (!InitialiseMainWindow(nCmdShow))
+ {
+ return -1;
+ }
+ if (!Initialise())
+ {
+ return -1;
+ }
+ isInitialised = true;
+ returnValue = MainLoop();
+ Shutdown();
+ return returnValue;
+}
+
+// Main program loop.
+
+int Framework::MainLoop()
+{
+ MSG msg;
+ HACCEL hAccelTable = LoadAccelerators(_hInstance, MAKEINTRESOURCE(IDC_RASTERISER));
+ LARGE_INTEGER counterFrequency;
+ LARGE_INTEGER nextTime;
+ LARGE_INTEGER currentTime;
+ LARGE_INTEGER lastTime;
+ bool updateFlag = true;
+
+ // Initialise timer
+ QueryPerformanceFrequency(&counterFrequency);
+ DWORD msPerFrame = static_cast(counterFrequency.QuadPart / DEFAULT_FRAMERATE);
+ double timeFactor = 1.0 / counterFrequency.QuadPart;
+ QueryPerformanceCounter(&nextTime);
+ lastTime = nextTime;
+
+ // Main message loop:
+ msg.message = WM_NULL;
+ while (msg.message != WM_QUIT)
+ {
+ if (updateFlag)
+ {
+ QueryPerformanceCounter(¤tTime);
+ _timeSpan = (currentTime.QuadPart - lastTime.QuadPart) * timeFactor;
+ lastTime = currentTime;
+ Update(_bitmap);
+ updateFlag = false;
+ }
+ QueryPerformanceCounter(¤tTime);
+ // Is it time to render the frame?
+ if (currentTime.QuadPart > nextTime.QuadPart)
+ {
+ Render(_bitmap);
+ // Make sure that the window gets repainted
+ InvalidateRect(_hWnd, NULL, FALSE);
+ // Set time for next frame
+ nextTime.QuadPart += msPerFrame;
+ // If we get more than a frame ahead, allow one to be dropped
+ // Otherwise, we will never catch up if we let the error accumulate
+ // and message handling will suffer
+ if (nextTime.QuadPart < currentTime.QuadPart)
+ {
+ nextTime.QuadPart = currentTime.QuadPart + msPerFrame;
+ }
+ updateFlag = true;
+ }
+ // Each time we go through this loop, we look to see if there is a Windows message
+ // that needs to be processed
+ if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ return static_cast(msg.wParam);
+}
+
+// Initialise the application. Called after the window and bitmap has been
+// created, but before the main loop starts
+//
+// Return false if the application cannot be initialised.
+
+bool Framework::Initialise()
+{
+ return true;
+}
+
+// Perform any updates to the structures that will be used
+// to render the window (i.e. transformation matrices, etc).
+//
+// This should be overridden
+
+void Framework::Update(const Bitmap &bitmap)
+{
+ // Default update method does nothing
+}
+
+// Render the window. This should be overridden
+
+void Framework::Render(const Bitmap &bitmap)
+{
+ // Default render method just sets the background to the default window colour
+ bitmap.Clear(reinterpret_cast(COLOR_WINDOW + 1));
+}
+
+// Perform any application shutdown that is needed
+
+void Framework::Shutdown()
+{
+}
+
+// Register the window class, create the window and
+// create the bitmap that we will use for rendering
+
+bool Framework::InitialiseMainWindow(int nCmdShow)
+{
+ #define MAX_LOADSTRING 100
+
+ WCHAR windowTitle[MAX_LOADSTRING];
+ WCHAR windowClass[MAX_LOADSTRING];
+
+ LoadStringW(_hInstance, IDS_APP_TITLE, windowTitle, MAX_LOADSTRING);
+ LoadStringW(_hInstance, IDC_RASTERISER, windowClass, MAX_LOADSTRING);
+
+ WNDCLASSEXW wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = _hInstance;
+ wcex.hIcon = LoadIcon(_hInstance, MAKEINTRESOURCE(IDI_RASTERISER));
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wcex.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1);
+ wcex.lpszMenuName = nullptr;
+ wcex.lpszClassName = windowClass;
+ wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
+ if (!RegisterClassExW(&wcex))
+ {
+ return false;
+ }
+
+ // Now work out how large the window needs to be for our required client window size
+ RECT windowRect = { 0, 0, static_cast(_width), static_cast(_height) };
+ AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);
+ _width = windowRect.right - windowRect.left;
+ _height = windowRect.bottom - windowRect.top;
+
+ _hWnd = CreateWindowW(windowClass,
+ windowTitle,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, _width, _height,
+ nullptr, nullptr, _hInstance, nullptr);
+ if (!_hWnd)
+ {
+ return false;
+ }
+ ShowWindow(_hWnd, nCmdShow);
+ UpdateWindow(_hWnd);
+
+ // Create a bitmap of the same size as the client area of the window. This is what we
+ // will be drawing on
+ RECT clientArea;
+ GetClientRect(_hWnd, &clientArea);
+ _bitmap.Create(_hWnd, clientArea.right - clientArea.left, clientArea.bottom - clientArea.top);
+ return true;
+}
+
+// The WndProc for the current window. This cannot be a method, but we can
+// redirect all messages to a method.
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (_thisFramework != NULL)
+ {
+ // If framework is started, then we can call our own message proc
+ return _thisFramework->MsgProc(hWnd, message, wParam, lParam);
+ }
+ else
+ {
+ // otherwise, we just pass control to the default message proc
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+}
+
+// Our main WndProc
+
+LRESULT Framework::MsgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_PAINT:
+ {
+ // Copy the contents of the bitmap to the window
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ BitBlt(hdc, 0, 0, _bitmap.GetWidth(), _bitmap.GetHeight(), _bitmap.GetDC(), 0, 0, SRCCOPY);
+ EndPaint(hWnd, &ps);
+ }
+ break;
+
+ case WM_SIZE:
+ // Delete any existing bitmap and create a new one of the required size.
+ _bitmap.Create(hWnd, LOWORD(lParam), HIWORD(lParam));
+ // Now render to the resized bitmap (but only if we are fully initialised)
+ if (isInitialised)
+ {
+ Update(_bitmap);
+ Render(_bitmap);
+ InvalidateRect(hWnd, NULL, FALSE);
+ }
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
diff --git a/Framework.h b/Framework.h
new file mode 100644
index 0000000..87c975b
--- /dev/null
+++ b/Framework.h
@@ -0,0 +1,37 @@
+#pragma once
+#include
+#include "Resource.h"
+#include "Bitmap.h"
+
+using namespace std;
+
+class Framework
+{
+public:
+ Framework();
+ Framework(unsigned int width, unsigned int height);
+ virtual ~Framework();
+
+ int Run(HINSTANCE hInstance, int nCmdShow);
+
+ LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ virtual bool Initialise();
+ virtual void Update(const Bitmap &bitmap);
+ virtual void Render(const Bitmap &bitmap);
+ virtual void Shutdown();
+
+private:
+ HINSTANCE _hInstance;
+ HWND _hWnd;
+ Bitmap _bitmap;
+ unsigned int _width;
+ unsigned int _height;
+
+ // Used in timing loop
+ double _timeSpan{ 0 };
+
+ bool InitialiseMainWindow(int nCmdShow);
+ int MainLoop();
+};
+
diff --git a/Matrix.cpp b/Matrix.cpp
new file mode 100644
index 0000000..e5a23ed
--- /dev/null
+++ b/Matrix.cpp
@@ -0,0 +1,137 @@
+#include "Matrix.h"
+
+Matrix::Matrix() : _matrix{ 0 }
+{
+}
+
+Matrix::Matrix(std::initializer_list inputList) : _matrix{ 0 }
+{
+ if (inputList.size() != ROWS * COLS)
+ {
+ throw "You did not provide enough points to create the matrix";
+ }
+
+ auto listContainer = inputList.begin();
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ _matrix[i][j] = *listContainer++;
+ }
+ }
+}
+
+Matrix::Matrix(const float arrayIn[ROWS][COLS])
+{
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ _matrix[i][j] = arrayIn[i][j];
+ }
+ }
+}
+
+Matrix::Matrix(const Matrix& other)
+{
+ Copy(other);
+}
+
+Matrix::~Matrix()
+{
+
+}
+
+float Matrix::GetM(const int row, const int column) const
+{
+ return GetMatrixCell(row, column);
+}
+
+float Matrix::GetMatrixCell(const int row, const int column) const
+{
+ return _matrix[row][column];
+}
+
+void Matrix::SetM(const int row, const int column, const float value)
+{
+ SetMatrixCell(row, column, value);
+}
+
+void Matrix::SetMatrixCell(const int row, const int column, const float value)
+{
+ _matrix[row][column] = value;
+}
+
+void Matrix::FromArray(const float arrayIn[ROWS][COLS])
+{
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ _matrix[i][j] = arrayIn[i][j];
+ }
+ }
+}
+
+Matrix& Matrix::operator= (const Matrix& rhs)
+{
+ if (this != &rhs)
+ {
+ Copy(rhs);
+ }
+ return *this;
+}
+
+bool Matrix::operator== (const Matrix& other) const
+{
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ if (_matrix[i][j] != other.GetMatrixCell(i, j))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+const Matrix Matrix::operator*(const Matrix& other) const
+{
+ Matrix result;
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ float resultValue = 0;
+ for (int k = 0; k < ROWS; k++)
+ {
+ resultValue += _matrix[i][k] * other.GetMatrixCell(k, j);
+ }
+ result.SetMatrixCell(i, j, resultValue);
+ }
+ }
+ return result;
+}
+
+const Vertex Matrix::operator*(const Vertex& other) const
+{
+ Vertex newVertex(other);
+
+ newVertex.SetX(_matrix[0][0] * other.GetX() + _matrix[0][1] * other.GetY() + _matrix[0][2] * other.GetW());
+ newVertex.SetY(_matrix[1][0] * other.GetX() + _matrix[1][1] * other.GetY() + _matrix[1][2] * other.GetW());
+ newVertex.SetW(_matrix[2][0] * other.GetX() + _matrix[2][1] * other.GetY() + _matrix[2][2] * other.GetW());
+ return newVertex;
+}
+
+void Matrix::Copy(const Matrix& other)
+{
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ _matrix[i][j] = other.GetMatrixCell(i, j);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Matrix.h b/Matrix.h
new file mode 100644
index 0000000..334d3e7
--- /dev/null
+++ b/Matrix.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "Vertex.h"
+#include
+
+// Size of the matrix
+const int COLS = 3;
+const int ROWS = 3;
+
+class Matrix
+{
+public:
+ Matrix();
+ Matrix(std::initializer_list inputList);
+ // Take in an array of floats matching the cols and rows
+ Matrix(const float arrayIn[ROWS][COLS]);
+ Matrix(const Matrix& other);
+
+ ~Matrix();
+
+ float GetM(const int row, const int column) const;
+ float GetMatrixCell(const int row, const int column) const;
+
+ void SetM(const int row, const int column, const float value);
+ void SetMatrixCell(const int row, const int column, const float value);
+ void FromArray(const float arrayIn[ROWS][COLS]);
+
+ Matrix& operator= (const Matrix& rhs);
+
+ bool operator==(const Matrix& other) const;
+ const Matrix operator*(const Matrix& other) const;
+ const Vertex operator*(const Vertex& other) const;
+
+private:
+ float _matrix[ROWS][COLS];
+ void Copy(const Matrix& other);
+};
+
diff --git a/Rasteriser.cpp b/Rasteriser.cpp
new file mode 100644
index 0000000..a63fb12
--- /dev/null
+++ b/Rasteriser.cpp
@@ -0,0 +1,97 @@
+#include "Rasteriser.h"
+#include
+
+using namespace std;
+
+Rasteriser app;
+
+bool Rasteriser::Initialise()
+{
+ //_vertexArray.push_back(Vertex(175, 175, 1));
+ //_vertexArray.push_back(Vertex(225, 175, 1));
+ //_vertexArray.push_back(Vertex(225, 225, 1));
+ //_vertexArray.push_back(Vertex(175, 225, 1));
+
+ _vertexArray.push_back(Vertex(150, 200, 1));
+ _vertexArray.push_back(Vertex(187.5f, 187.5f, 1));
+ _vertexArray.push_back(Vertex(200, 150, 1));
+ _vertexArray.push_back(Vertex(212.5f, 187.5f, 1));
+ _vertexArray.push_back(Vertex(250, 200, 1));
+ _vertexArray.push_back(Vertex(212.5f, 212.5f, 1));
+ _vertexArray.push_back(Vertex(200, 250, 1));
+ _vertexArray.push_back(Vertex(187.5, 212.5f, 1));
+
+ return true;
+}
+
+void Rasteriser::Update(const Bitmap& bitmap)
+{
+ for (int i = 0; i < _vertexArray.size(); i++) {
+ _vertexArray[i] = Translate(_vertexArray[i], 2, 0);
+ _vertexArray[i] = Rotate(_vertexArray[i], 1);
+ _vertexArray[i] = Scale(_vertexArray[i], 1.001f, 1.001f);
+ }
+
+}
+
+void Rasteriser::Render(const Bitmap& bitmap)
+{
+ bitmap.Clear(RGB(255, 255, 255));
+ SelectObject(bitmap.GetDC(), GetStockObject(DC_BRUSH));
+ //DrawSquare(bitmap.GetDC(), _vertexArray);
+ DrawShape(bitmap.GetDC(), _vertexArray);
+}
+
+Vertex Rasteriser::Translate(const Vertex vertexIn, const float moveXBy, const float moveYBy)
+{
+ Matrix translationMatrix = Matrix({ 1, 0, moveXBy, 0, 1, moveYBy, 0, 0, 1 });
+ return translationMatrix * vertexIn;
+}
+
+Vertex Rasteriser::Scale(const Vertex vertexIn, const float scaleXBy, const float scaleYBy)
+{
+ Matrix scaleFactorMatrix = Matrix({ scaleXBy, 0, 0, 0, scaleYBy, 0, 0, 0, 1 });
+ return scaleFactorMatrix * vertexIn;
+}
+
+Vertex Rasteriser::Rotate(const Vertex vertexIn, const float rotationDegrees)
+{
+ float rotationRadian = DegreesToRadians(rotationDegrees);
+ Matrix rotationFactorMatrix = Matrix({ cos(rotationRadian), -sin(rotationRadian), 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 1});
+ return rotationFactorMatrix * vertexIn;
+}
+
+float Rasteriser::DegreesToRadians(const float degrees)
+{
+ return (degrees * _PI) / 180;
+}
+
+void Rasteriser::DrawSquare(HDC hDc, const vector verticies)
+{
+ POINT pointArray[4];
+ for (int i = 0; i < 4; i++)
+ {
+ pointArray[i].x = (long) verticies[i].GetX();
+ pointArray[i].y = (long) verticies[i].GetY();
+ }
+
+ SetDCBrushColor(hDc, RGB(255, 0, 255));
+ SetDCPenColor(hDc, RGB(0, 0, 255));
+ Polygon(hDc, pointArray, 4);
+}
+
+void Rasteriser::DrawShape(HDC hDc, const vector verticies)
+{
+ vector pointArray;
+ for (int i = 0; i < verticies.size(); i++)
+ {
+ POINT newPoint;
+ newPoint.x = (long)verticies[i].GetX();
+ newPoint.y = (long)verticies[i].GetY();
+ pointArray.push_back(newPoint);
+ }
+
+ SetDCBrushColor(hDc, RGB(rand() % 256, rand() % 256, rand() % 256));
+ SetDCPenColor(hDc, RGB(rand() % 256, rand() % 256, rand() % 256));
+ Polygon(hDc, pointArray.data(), (int) verticies.size());
+}
\ No newline at end of file
diff --git a/Rasteriser.h b/Rasteriser.h
new file mode 100644
index 0000000..9ec46d6
--- /dev/null
+++ b/Rasteriser.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "Framework.h"
+#include "Vertex.h"
+#include "Matrix.h"
+#include
+
+class Rasteriser : public Framework
+{
+public:
+ bool Initialise();
+ void Update(const Bitmap& bitmap);
+ void Render(const Bitmap& bitmap);
+
+ void DrawSquare(HDC hDc, const vector verticies);
+ void DrawShape(HDC hDc, const vector verticies);
+
+ Vertex Translate(const Vertex vertexIn, const float moveXBy, const float moveYBy);
+ Vertex Scale(const Vertex vertexIn, const float scaleXBy, const float scaleYBy);
+ Vertex Rotate(const Vertex vertexIn, const float rotationDegrees);
+
+ float DegreesToRadians(const float degrees);
+
+private:
+ vector _vertexArray;
+ const float _PI = (float) acos(-1);
+};
+
diff --git a/Rasteriser.ico b/Rasteriser.ico
new file mode 100644
index 0000000..b3ec03b
Binary files /dev/null and b/Rasteriser.ico differ
diff --git a/Rasteriser.rc b/Rasteriser.rc
new file mode 100644
index 0000000..2356eff
Binary files /dev/null and b/Rasteriser.rc differ
diff --git a/Resource.h b/Resource.h
new file mode 100644
index 0000000..c6d266c
--- /dev/null
+++ b/Resource.h
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WindowsApp.rc
+//
+
+#define IDS_APP_TITLE 103
+
+#define IDR_MAINFRAME 128
+#define IDI_RASTERISER 107
+#define IDI_SMALL 108
+#define IDC_RASTERISER 109
+#define IDC_MYICON 2
+#ifndef IDC_STATIC
+#define IDC_STATIC -1
+#endif
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NO_MFC 130
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/Vertex.cpp b/Vertex.cpp
new file mode 100644
index 0000000..e889f49
--- /dev/null
+++ b/Vertex.cpp
@@ -0,0 +1,84 @@
+#include "Vertex.h"
+
+Vertex::Vertex()
+{
+ _x = 0.0f;
+ _y = 0.0f;
+ _w = 0.0f;
+}
+
+Vertex::Vertex(float x, float y, float w)
+{
+ _x = x;
+ _y = y;
+ _w = w;
+}
+
+Vertex::Vertex(const Vertex & other)
+{
+ _x = other.GetX();
+ _y = other.GetY();
+ _w = other.GetW();
+}
+
+float Vertex::GetX() const
+{
+ return _x;
+}
+
+void Vertex::SetX(const float x)
+{
+ _x = x;
+}
+
+float Vertex::GetY() const
+{
+ return _y;
+}
+
+void Vertex::SetY(const float y)
+{
+ _y = y;
+}
+
+float Vertex::GetW() const
+{
+ return _w;
+}
+
+void Vertex::SetW(const float w)
+{
+ _w = w;
+}
+
+Vertex& Vertex::operator=(const Vertex& rhs)
+{
+ // Only do the assignment if we are not assigning
+ // to ourselves
+ if (this != &rhs)
+ {
+ _x = rhs.GetX();
+ _y = rhs.GetY();
+ _w = rhs.GetW();
+ }
+ return *this;
+}
+
+// The const at the end of the declaraion for '==" indicates that this operation does not change
+// any of the member variables in this class.
+
+bool Vertex::operator==(const Vertex& rhs) const
+{
+ return (_x == rhs.GetX() && _y == rhs.GetY() && _w == rhs.GetW());
+}
+
+// You can see three different uses of 'const' here:
+//
+// The first const indicates that the method changes the return value, but it is not moved in memory
+// The second const indicates that the parameter is passed by reference, but it is not modified
+// The third const indicates that the operator does not change any of the memory variables in the class.
+
+const Vertex Vertex::operator+(const Vertex& rhs) const
+{
+ return Vertex(_x + rhs.GetX(), _y + rhs.GetY(), _w + rhs.GetW());
+}
diff --git a/Vertex.h b/Vertex.h
new file mode 100644
index 0000000..e206585
--- /dev/null
+++ b/Vertex.h
@@ -0,0 +1,29 @@
+#pragma once
+class Vertex
+{
+public:
+ Vertex();
+ Vertex(float x, float y, float w);
+ Vertex(const Vertex& other);
+
+ // Accessors
+ float GetX() const;
+ void SetX(const float x);
+ float GetY() const;
+ void SetY(const float y);
+ float GetW() const;
+ void SetW(const float w);
+
+ // Assignment operator
+ Vertex& operator= (const Vertex& rhs);
+
+ bool operator== (const Vertex& rhs) const;
+
+ const Vertex operator+ (const Vertex& rhs) const;
+
+private:
+ float _x;
+ float _y;
+ float _w;
+};
+
diff --git a/small.ico b/small.ico
new file mode 100644
index 0000000..b3ec03b
Binary files /dev/null and b/small.ico differ
diff --git a/targetver.h b/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include