diff --git a/BaseFramework.vcxproj b/BaseFramework.vcxproj
index 64ce85e..5fe775d 100644
--- a/BaseFramework.vcxproj
+++ b/BaseFramework.vcxproj
@@ -148,6 +148,9 @@
+
+
+
@@ -155,6 +158,9 @@
+
+
+
diff --git a/BaseFramework.vcxproj.filters b/BaseFramework.vcxproj.filters
index 9484823..bf48fe3 100644
--- a/BaseFramework.vcxproj.filters
+++ b/BaseFramework.vcxproj.filters
@@ -30,6 +30,15 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -53,6 +62,15 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/MD2Loader.cpp b/MD2Loader.cpp
new file mode 100644
index 0000000..3aac28c
--- /dev/null
+++ b/MD2Loader.cpp
@@ -0,0 +1,136 @@
+#include "MD2Loader.h"
+
+// File reading
+#include
+#include
+
+using namespace std;
+
+// BYTE added in case Windows.h is not included.
+typedef unsigned char BYTE;
+
+// Magic number for MD2 files "IDP2" or 844121161
+const int MD2_IDENT = (('2'<<24) + ('P'<<16) + ('D'<<8) + 'I');
+
+// MS2 version
+const int MD2_VERSION = 8;
+
+struct Md2Header
+{
+ int indent; // The magic number used to identify the file.
+ int version; // The file version number (must be 8).
+ int skinWidth; // The width in pixels of our image.
+ int skinHeight; // The height in pixels of our image.
+ int frameSize; // The size in bytes the frames are.
+ int numSkins; // The number of skins associated with the model.
+ int numVertices; // The number of vertices.
+ int numTexCoords; // The number of texture coordinates.
+ int numTriangles; // The number of faces (polygons).
+ int numGlCommands; // The number of gl commands.
+ int numFrames; // The number of animated frames.
+ int offsetSkins; // The offset in the file for the skin data.
+ int offsetTexCoords; // The offset in the file for the texture data.
+ int offsetTriangles; // The offset in the file for the face data.
+ int offsetFrames; // The offset in the file for the frames data.
+ int offsetGlCommands; // The offset in the file for the gl commands data.
+ int offsetEnd; // The end of the file offset.
+};
+
+struct Md2Triangle
+{
+ short vertexIndex[3]; // Vertex indices of the triangle
+ short uvIndex[3]; // Texture coordinate indices
+};
+
+struct Md2Vertex
+{
+ BYTE v[3]; // Compressed vertex (x, y, z) coordinates
+ BYTE lightNormalIndex; // Index to a normal vector for the lighting
+};
+
+struct Md2Frame
+{
+ float scale[3]; // Scale values
+ float translate[3]; // Translation vector
+ char name[16]; // Frame name
+ Md2Vertex verts[1]; // First vertex of this frame
+};
+
+// ----------------------------------------------
+// LoadModel() - load model from file.
+// ----------------------------------------------
+
+bool MD2Loader::LoadModel(const char* md2Filename, Model& model, AddPolygon addPolygon, AddVertex addVertex)
+{
+ ifstream file;
+ Md2Header header;
+
+ // Try to open MD2 file
+ file.open(md2Filename, ios::in | ios::binary);
+ if (file.fail())
+ {
+ return false;
+ }
+ // Read file header
+ file.read(reinterpret_cast(&header), sizeof(Md2Header));
+
+ // Verify that this is a MD2 file (check for the magic number and version number)
+ if ((header.indent != MD2_IDENT) && (header.version != MD2_VERSION))
+ {
+ // This is not a MD2 model
+ file.close();
+ return false;
+ }
+
+ // Allocate the memory we need
+ Md2Triangle* triangles = new Md2Triangle[header.numTriangles];
+ // We are only interested in the first frame
+ BYTE* frameBuffer = new BYTE[header.frameSize];
+ Md2Frame* frame = reinterpret_cast(frameBuffer);
+
+ // Read polygon data...
+ file.seekg(header.offsetTriangles, ios::beg);
+ file.read(reinterpret_cast(triangles), sizeof(Md2Triangle) * header.numTriangles);
+
+ // Read frame data...
+ file.seekg(header.offsetFrames, ios::beg);
+ file.read(reinterpret_cast(frame), header.frameSize);
+
+ // Close the file
+ file.close();
+
+ //----------------------------------------------------------------------------------------------
+
+ // Polygon array initialization
+ for ( int i = 0; i < header.numTriangles; ++i )
+ {
+ // Call supplied member function to add a new polygon to the list
+ std::invoke(addPolygon, model, triangles[i].vertexIndex[0], triangles[i].vertexIndex[1], triangles[i].vertexIndex[2]);
+ }
+
+ // Vertex array initialization
+ for( int i = 0; i < header.numVertices; ++i )
+ {
+ // The following are the expressions needed to access each of the co-ordinates.
+ //
+ // X co-ordinate: frame->verts[i].v[0] * frame->scale[0] + frame->translate[0]
+ // Y co-ordinate: frame->verts[i].v[2] * frame->scale[2] + frame->translate[2]
+ // Z co-ordinate: frame->verts[i].v[1] * frame->scale[1] + frame->translate[1]
+ //
+ // NOTE: We have to swap Y and Z over because Z is up in MD2 and we have Y as up-axis
+ std::invoke(addVertex, model,
+ static_cast((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]),
+ static_cast((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]),
+ static_cast((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]));
+ }
+
+ // Free dynamically allocated memory
+ delete [] triangles; // NOTE: this is 'array' delete. Must be sure to use this
+ triangles = 0;
+
+ delete [] frameBuffer;
+ frameBuffer = 0;
+ frame = 0;
+
+ return true;
+}
diff --git a/MD2Loader.h b/MD2Loader.h
new file mode 100644
index 0000000..3d9ada9
--- /dev/null
+++ b/MD2Loader.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Model.h"
+
+// Declare typedefs used by the MD2Loader to call the methods to add a vertex and
+// add a polygon to the lists
+
+typedef void (Model::*AddVertex)(float x, float y, float z);
+typedef void (Model::*AddPolygon)(int i0, int i1, int i2);
+
+class MD2Loader
+{
+ public:
+ static bool LoadModel(const char* md2Filename, Model& model, AddPolygon addPolygon, AddVertex addVertex);
+};
diff --git a/Matrix.cpp b/Matrix.cpp
index e5a23ed..549fe5c 100644
--- a/Matrix.cpp
+++ b/Matrix.cpp
@@ -119,12 +119,31 @@ 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());
+ newVertex.SetX(_matrix[0][0] * other.GetX() + _matrix[0][1] * other.GetY() + _matrix[0][2] * other.GetZ() + _matrix[0][3] * other.GetW());
+ newVertex.SetY(_matrix[1][0] * other.GetX() + _matrix[1][1] * other.GetY() + _matrix[1][2] * other.GetZ() + _matrix[1][3] * other.GetW());
+ newVertex.SetZ(_matrix[2][0] * other.GetX() + _matrix[2][1] * other.GetY() + _matrix[2][2] * other.GetZ() + _matrix[2][3] * other.GetW());
+ newVertex.SetW(_matrix[3][0] * other.GetX() + _matrix[3][1] * other.GetY() + _matrix[3][2] * other.GetZ() + _matrix[3][3] * other.GetW());
return newVertex;
}
+Matrix Matrix::IdentityMatrix()
+{
+ for (int i = 0; i < ROWS; i++)
+ {
+ for (int j = 0; j < COLS; j++)
+ {
+ float currentValue = 0.0f;
+ if (j == i)
+ {
+ currentValue = 1.0f;
+ }
+ _matrix[i][j] = currentValue;
+ }
+ }
+
+ return _matrix;
+}
+
void Matrix::Copy(const Matrix& other)
{
for (int i = 0; i < ROWS; i++)
diff --git a/Matrix.h b/Matrix.h
index 334d3e7..31f03d5 100644
--- a/Matrix.h
+++ b/Matrix.h
@@ -4,8 +4,8 @@
#include
// Size of the matrix
-const int COLS = 3;
-const int ROWS = 3;
+const int COLS = 4;
+const int ROWS = 4;
class Matrix
{
@@ -25,6 +25,8 @@ public:
void SetMatrixCell(const int row, const int column, const float value);
void FromArray(const float arrayIn[ROWS][COLS]);
+ Matrix IdentityMatrix();
+
Matrix& operator= (const Matrix& rhs);
bool operator==(const Matrix& other) const;
diff --git a/Model.cpp b/Model.cpp
new file mode 100644
index 0000000..b6706aa
--- /dev/null
+++ b/Model.cpp
@@ -0,0 +1,39 @@
+#include "Model.h"
+
+Model::Model()
+{
+}
+
+Model::~Model()
+{
+}
+
+const vector& Model::GetPolygons()
+{
+ return _polygons;
+}
+
+const vector& Model::GetVertices()
+{
+ return _vertices;
+}
+
+size_t Model::GetPolygonCount()
+{
+ return _polygons.size();
+}
+
+size_t Model::GetVerticesCount()
+{
+ return _vertices.size();
+}
+
+void Model::AddVertex(float x, float y, float z)
+{
+ _vertices.push_back(Vertex(x, y, z));
+}
+
+void Model::AddPolygon(int index0, int index1, int index2)
+{
+ _polygons.push_back(Polygon3D(index0, index1, index2));
+}
\ No newline at end of file
diff --git a/Model.h b/Model.h
new file mode 100644
index 0000000..593164c
--- /dev/null
+++ b/Model.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "Polygon3D.h"
+#include "Vertex.h"
+#include
+
+using namespace std;
+
+class Model
+{
+public:
+ Model();
+
+ ~Model();
+
+ const vector& GetPolygons();
+ const vector& GetVertices();
+
+ size_t GetPolygonCount();
+ size_t GetVerticesCount();
+
+ void AddVertex(float x, float y, float z);
+ void AddPolygon(int index0, int index1, int index2);
+
+private:
+ vector _polygons;
+ vector _vertices;
+};
+
diff --git a/Polygon3D.cpp b/Polygon3D.cpp
new file mode 100644
index 0000000..63f3a8a
--- /dev/null
+++ b/Polygon3D.cpp
@@ -0,0 +1,43 @@
+#include "Polygon3D.h"
+
+Polygon3D::Polygon3D() : _indices{ 0 }
+{
+}
+
+Polygon3D::Polygon3D(int index0, int index1, int index2)
+{
+ _indices[0] = index0;
+ _indices[1] = index1;
+ _indices[2] = index2;
+}
+
+Polygon3D::Polygon3D(const Polygon3D& other)
+{
+ Copy(other);
+}
+
+Polygon3D::~Polygon3D()
+{
+}
+
+int Polygon3D::GetIndex(const int index) const
+{
+ return _indices[index];
+}
+
+Polygon3D& Polygon3D::operator= (const Polygon3D& rhs)
+{
+ if (this != &rhs)
+ {
+ Copy(rhs);
+ }
+ return *this;
+}
+
+void Polygon3D::Copy(const Polygon3D& other)
+{
+ for (int i = 0; i < sizeof(_indices)/sizeof(_indices[0]); i++)
+ {
+ _indices[i] = other.GetIndex(i);
+ }
+}
\ No newline at end of file
diff --git a/Polygon3D.h b/Polygon3D.h
new file mode 100644
index 0000000..b6cdaef
--- /dev/null
+++ b/Polygon3D.h
@@ -0,0 +1,20 @@
+#pragma once
+class Polygon3D
+{
+public:
+ Polygon3D();
+ Polygon3D(int index0, int index1, int index2);
+ Polygon3D(const Polygon3D& other);
+
+ ~Polygon3D();
+
+ int GetIndex(int index) const;
+
+ Polygon3D& operator= (const Polygon3D& rhs);
+
+private:
+ int _indices[3];
+
+ void Copy(const Polygon3D& other);
+};
+
diff --git a/Rasteriser.cpp b/Rasteriser.cpp
index a63fb12..d35fa65 100644
--- a/Rasteriser.cpp
+++ b/Rasteriser.cpp
@@ -7,58 +7,76 @@ 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));
+ //_initialVertexArray.push_back(Vertex(175, 175, 0, 1));
+ //_initialVertexArray.push_back(Vertex(225, 175, 0, 1));
+ //_initialVertexArray.push_back(Vertex(225, 225, 0, 1));
+ //_initialVertexArray.push_back(Vertex(175, 225, 0, 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));
+ _initialVertexArray.push_back(Vertex(150, 200, 1));
+ _initialVertexArray.push_back(Vertex(187.5f, 187.5f, 1));
+ _initialVertexArray.push_back(Vertex(200, 150, 1));
+ _initialVertexArray.push_back(Vertex(212.5f, 187.5f, 1));
+ _initialVertexArray.push_back(Vertex(250, 200, 1));
+ _initialVertexArray.push_back(Vertex(212.5f, 212.5f, 1));
+ _initialVertexArray.push_back(Vertex(200, 250, 1));
+ _initialVertexArray.push_back(Vertex(187.5, 212.5f, 1));
+ _currentVertexArray = _initialVertexArray;
+
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);
+{
+ int currentRot = (_rotation % 360);
+ for (int i = 0; i < _initialVertexArray.size(); i++) {
+ Matrix currentTransfomation = GetRotationMatrixFromPoint(Axis::Z, (float) currentRot, _initialVertexArray[0].GetX(), _initialVertexArray[0].GetY(), 0);
+ _currentVertexArray[i] = currentTransfomation * _initialVertexArray[i];
}
-
+ _rotation += 1;
}
void Rasteriser::Render(const Bitmap& bitmap)
{
- bitmap.Clear(RGB(255, 255, 255));
+ ClearViewport(bitmap);
SelectObject(bitmap.GetDC(), GetStockObject(DC_BRUSH));
- //DrawSquare(bitmap.GetDC(), _vertexArray);
- DrawShape(bitmap.GetDC(), _vertexArray);
+ //DrawSquare(bitmap.GetDC(), _initialVertexArray);
+ DrawShape(bitmap.GetDC(), _currentVertexArray);
}
-Vertex Rasteriser::Translate(const Vertex vertexIn, const float moveXBy, const float moveYBy)
+void Rasteriser::ClearViewport(const Bitmap& bitmap)
+{
+ bitmap.Clear(RGB(255, 255, 255));
+}
+
+Matrix Rasteriser::GetTranslateMatrix(const float x, const float y, const float z)
+{
+ return Matrix({ 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 });
+}
+
+Matrix Rasteriser::GetScaleMatrix(const float x, const float y, const float z)
{
- Matrix translationMatrix = Matrix({ 1, 0, moveXBy, 0, 1, moveYBy, 0, 0, 1 });
- return translationMatrix * vertexIn;
+ return Matrix({ x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 });
}
-Vertex Rasteriser::Scale(const Vertex vertexIn, const float scaleXBy, const float scaleYBy)
+Matrix Rasteriser::GetRotationMatrix(const Axis rotAxis, const float rotDegrees)
{
- Matrix scaleFactorMatrix = Matrix({ scaleXBy, 0, 0, 0, scaleYBy, 0, 0, 0, 1 });
- return scaleFactorMatrix * vertexIn;
+ float rotationRadian = DegreesToRadians(rotDegrees);
+ switch (rotAxis)
+ {
+ case (Axis::X):
+ return Matrix({ 1, 0, 0, 0, 0, cos(rotationRadian), -sin(rotationRadian), 0, 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1 });
+ case (Axis::Y):
+ return Matrix({ cos(rotationRadian), 0, sin(rotationRadian), 0, 0, 1, 0, 0, -sin(rotationRadian), 0, cos(rotationRadian), 0, 0, 0, 0, 1 });
+ default:
+ case (Axis::Z):
+ return Matrix({ cos(rotationRadian), -sin(rotationRadian), 0, 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 });
+ }
}
-Vertex Rasteriser::Rotate(const Vertex vertexIn, const float rotationDegrees)
+Matrix Rasteriser::GetRotationMatrixFromPoint(const Axis rotAxis, const float rotDegrees, const float x, const float y, const float z)
{
- float rotationRadian = DegreesToRadians(rotationDegrees);
- Matrix rotationFactorMatrix = Matrix({ cos(rotationRadian), -sin(rotationRadian), 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 1});
- return rotationFactorMatrix * vertexIn;
+ return GetTranslateMatrix(x, y, z) * GetRotationMatrix(rotAxis, rotDegrees) * GetTranslateMatrix(-x, -y, -z);
}
float Rasteriser::DegreesToRadians(const float degrees)
diff --git a/Rasteriser.h b/Rasteriser.h
index 9ec46d6..8c331b1 100644
--- a/Rasteriser.h
+++ b/Rasteriser.h
@@ -4,24 +4,30 @@
#include "Matrix.h"
#include
+enum class Axis { X, Y, Z };
+
class Rasteriser : public Framework
{
-public:
+public:
bool Initialise();
void Update(const Bitmap& bitmap);
void Render(const Bitmap& bitmap);
+ void ClearViewport(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);
-
+ Matrix GetTranslateMatrix(const float x, const float y, const float z);
+ Matrix GetScaleMatrix(const float x, const float y, const float z);
+ Matrix GetRotationMatrix(const Axis rotAxis, const float rotDegrees);
+ Matrix GetRotationMatrixFromPoint(const Axis rotAxis, const float rotDegrees, const float x, const float y, const float z);
+
float DegreesToRadians(const float degrees);
private:
- vector _vertexArray;
+ vector _initialVertexArray;
+ vector _currentVertexArray;
const float _PI = (float) acos(-1);
+ int _rotation;
};
diff --git a/Vertex.cpp b/Vertex.cpp
index e889f49..739f89c 100644
--- a/Vertex.cpp
+++ b/Vertex.cpp
@@ -4,21 +4,29 @@ Vertex::Vertex()
{
_x = 0.0f;
_y = 0.0f;
+ _z = 0.0f;
_w = 0.0f;
}
-Vertex::Vertex(float x, float y, float w)
+Vertex::Vertex(const float x, const float y, const float z)
{
_x = x;
_y = y;
+ _z = z;
+ _w = 1.0f;
+}
+
+Vertex::Vertex(const float x, const float y, const float z, const float w)
+{
+ _x = x;
+ _y = y;
+ _z = z;
_w = w;
}
Vertex::Vertex(const Vertex & other)
{
- _x = other.GetX();
- _y = other.GetY();
- _w = other.GetW();
+ Copy(other);
}
float Vertex::GetX() const
@@ -41,6 +49,16 @@ void Vertex::SetY(const float y)
_y = y;
}
+float Vertex::GetZ() const
+{
+ return _z;
+}
+
+void Vertex::SetZ(const float z)
+{
+ _z = z;
+}
+
float Vertex::GetW() const
{
return _w;
@@ -57,9 +75,7 @@ Vertex& Vertex::operator=(const Vertex& rhs)
// to ourselves
if (this != &rhs)
{
- _x = rhs.GetX();
- _y = rhs.GetY();
- _w = rhs.GetW();
+ Copy(rhs);
}
return *this;
}
@@ -69,7 +85,7 @@ Vertex& Vertex::operator=(const Vertex& rhs)
bool Vertex::operator==(const Vertex& rhs) const
{
- return (_x == rhs.GetX() && _y == rhs.GetY() && _w == rhs.GetW());
+ return (_x == rhs.GetX() && _y == rhs.GetY() && _z == rhs.GetZ() && _w == rhs.GetW());
}
// You can see three different uses of 'const' here:
@@ -80,5 +96,13 @@ bool Vertex::operator==(const Vertex& rhs) const
const Vertex Vertex::operator+(const Vertex& rhs) const
{
- return Vertex(_x + rhs.GetX(), _y + rhs.GetY(), _w + rhs.GetW());
+ return Vertex(_x + rhs.GetX(), _y + rhs.GetY(), _z + rhs.GetZ(), _w + rhs.GetW());
+}
+
+void Vertex::Copy(const Vertex& other)
+{
+ _x = other.GetX();
+ _y = other.GetY();
+ _z = other.GetZ();
+ _w = other.GetW();
}
diff --git a/Vertex.h b/Vertex.h
index e206585..0782a1e 100644
--- a/Vertex.h
+++ b/Vertex.h
@@ -3,7 +3,8 @@ class Vertex
{
public:
Vertex();
- Vertex(float x, float y, float w);
+ Vertex(const float x, const float y, const float z);
+ Vertex(const float x, const float y, const float z, const float w);
Vertex(const Vertex& other);
// Accessors
@@ -11,6 +12,8 @@ public:
void SetX(const float x);
float GetY() const;
void SetY(const float y);
+ float GetZ() const;
+ void SetZ(const float z);
float GetW() const;
void SetW(const float w);
@@ -24,6 +27,9 @@ public:
private:
float _x;
float _y;
+ float _z;
float _w;
+
+ void Copy(const Vertex& other);
};
diff --git a/cube.md2 b/cube.md2
new file mode 100644
index 0000000..ec7354c
Binary files /dev/null and b/cube.md2 differ