diff --git a/BaseFramework.vcxproj b/BaseFramework.vcxproj index a7510ed..0c59717 100644 --- a/BaseFramework.vcxproj +++ b/BaseFramework.vcxproj @@ -29,26 +29,26 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode diff --git a/Model.cpp b/Model.cpp index 5c0a4b5..16ed899 100644 --- a/Model.cpp +++ b/Model.cpp @@ -334,11 +334,9 @@ void Model::CalculateVertexNormals() } for (Vertex& currentVertex : _transformedVertices) - { - - currentVertex.SetNormal(currentVertex.GetNormal() / currentVertex.GetContributeCount()); - currentVertex.NormalizeNormal(); - + { + currentVertex.SetNormal(currentVertex.GetNormal() / currentVertex.GetContributeCount()); + currentVertex.NormalizeNormal(); } } @@ -360,4 +358,17 @@ void Model::Sort() } sort(_polygons.begin(), _polygons.end(), DepthCompare); +} + +void Model::CalculateUVPerspective() +{ + for (Polygon3D& currentPolygon : _polygons) + { + + for (int cpi = 0; cpi < currentPolygon.GetPolygonVertexCount(); cpi++) + { + _transformedVertices[currentPolygon.GetIndex(cpi)].UVCorrect(_uvCoords[currentPolygon.GetUVIndex(cpi)].GetU(), _uvCoords[currentPolygon.GetUVIndex(cpi)].GetV()); + } + + } } \ No newline at end of file diff --git a/Model.h b/Model.h index a959115..efc7d97 100644 --- a/Model.h +++ b/Model.h @@ -78,6 +78,8 @@ public: void CalculateVertexNormals(); void Sort(void); + void CalculateUVPerspective(void); + private: vector _polygons; vector _vertices; diff --git a/Rasteriser.cpp b/Rasteriser.cpp index b4ceeea..2208877 100644 --- a/Rasteriser.cpp +++ b/Rasteriser.cpp @@ -8,12 +8,12 @@ Rasteriser::~Rasteriser() _sceneModels.~vector(); } -void Rasteriser::DrawString(HDC hDc, int x, int y, LPCTSTR text, COLORREF textColor, COLORREF backgroundColor) +void Rasteriser::DrawString(HDC hDc, int x, int y, LPCTSTR text, int fontSize, COLORREF textColor, COLORREF backgroundColor) { HFONT hFont, hOldFont; // Retrieve a handle to the variable stock font. - hFont = hFont = CreateFont(48, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, + hFont = hFont = CreateFont(fontSize, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, TEXT("Myfont")); // Select the variable stock font into the specified device context. @@ -60,6 +60,16 @@ bool Rasteriser::Initialise() _screenMinimized = false; + //Set the current Time for the automation + time(&_startTime); + time(&_currentTime); + _currentState = 0; + _maxStates = 5; + for (int i = 0; i < (sizeof _counters / sizeof _counters[0]); i++) + { + _counters[i] = 0; + } + return true; } @@ -140,12 +150,8 @@ float Rasteriser::Lerp(int a, int b, float t) return Lerp((float)a, (float)b, t); } -int toDraw = 1; -int drawn = 0; - void Rasteriser::Update(const Bitmap& bitmap) -{ - drawn = 0; +{ if (bitmap.GetWidth() == 0 || bitmap.GetHeight() == 0) { _screenMinimized = true; @@ -155,19 +161,58 @@ void Rasteriser::Update(const Bitmap& bitmap) _screenMinimized = false; } - if (!_screenMinimized) + int duration = 0; + switch (_currentState) { - int currentRot = 0;// 45; // (_rotation % 360); - Vertex startPos = Vertex(0, 0, 20); - int currentZOff = 0; - int currentModelIndex = 0; + case -1: + duration = -1; + case 0: + duration = 10; + break; + case 1: + duration = 10; + break; + case 2: + duration = 10; + break; + case 3: + duration = 10; + break; + case 4: + duration = 10; + break; + } + if (!_screenMinimized) + { for (Model& currentModel : _sceneModels) { if (currentModel.GetActive()) { - currentModel.EnqueueTransform(GetTranslateMatrix(startPos)); - currentModel.EnqueueTransform(GetRotationMatrix(Axis::Y, (float)currentRot)); + switch (_currentState) + { + case -1: + + break; + case 0: + currentModel.SetDrawMethod(DrawMethod::Wireframe); + break; + case 1: + currentModel.SetDrawMethod(DrawMethod::Flat); + break; + case 2: + currentModel.SetDrawMethod(DrawMethod::FlatRaster); + break; + case 3: + currentModel.SetDrawMethod(DrawMethod::Smooth); + break; + case 4: + currentModel.SetDrawMethod(DrawMethod::Textured); + break; + } + + //currentModel.EnqueueTransform(GetTranslateMatrix(startPos)); + //currentModel.EnqueueTransform(GetRotationMatrix(Axis::Y, (float)currentRot)); /*startPos.SetX(startPos.GetX() + 100); if ((currentModelIndex % 2) == 1) { @@ -178,7 +223,7 @@ void Rasteriser::Update(const Bitmap& bitmap) currentZOff = 100; } startPos.SetZ((float)currentZOff);*/ - currentModelIndex++; + } } @@ -186,19 +231,26 @@ void Rasteriser::Update(const Bitmap& bitmap) _currentPerspectiveMatrix = GetPerspectiveProjectionMatrix(1, _currentAspectRatio); _currentViewMatrix = GetViewMatrix(1, bitmap.GetWidth(), bitmap.GetHeight()); - if (_rotation == 360) + } + + if (((int)_currentTime > (int)_startTime + duration) && (duration != -1)) + { + if (_currentState == _maxStates) { - _rotation = 0; + _currentState = 0; } else { - _rotation += 1; - } - } + _currentState++; + } + time(&_startTime); + } + time(&_currentTime); } void Rasteriser::Render(const Bitmap& bitmap) { + bool titleDrawn = false; if (!_screenMinimized) { ClearViewport(bitmap); @@ -224,12 +276,22 @@ void Rasteriser::Render(const Bitmap& bitmap) switch (currentModel.GetDrawMethod()) { case (DrawMethod::Wireframe): + if (!titleDrawn) + { + DrawString(bitmap.GetDC(), 10, 10, _T("Wireframe")); + titleDrawn = true; + } currentModel.ApplyTransformToTransformedVertices(_currentPerspectiveMatrix); currentModel.DehomogenizeAllVertices(); currentModel.ApplyTransformToTransformedVertices(_currentViewMatrix); DrawWireFrame(bitmap.GetDC(), currentModel); break; case (DrawMethod::Flat): + if (!titleDrawn) + { + DrawString(bitmap.GetDC(), 10, 10, TEXT("Flat Polygon")); + titleDrawn = true; + } currentModel.CalculateVertexNormals(); CalculateLighting(currentModel, false); @@ -239,6 +301,11 @@ void Rasteriser::Render(const Bitmap& bitmap) DrawSolidFlat(bitmap.GetDC(), currentModel); break; case (DrawMethod::FlatRaster): + if (!titleDrawn) + { + DrawString(bitmap.GetDC(), 10, 10, _T("Flat Raster")); + titleDrawn = true; + } currentModel.CalculateVertexNormals(); CalculateLighting(currentModel, false); @@ -248,6 +315,11 @@ void Rasteriser::Render(const Bitmap& bitmap) DrawRasterisedSolidFlat(bitmap.GetDC(), currentModel); break; case (DrawMethod::Smooth): + if (!titleDrawn) + { + DrawString(bitmap.GetDC(), 10, 10, _T("Gouraud Shading")); + titleDrawn = true; + } currentModel.CalculateVertexNormals(); CalculateLighting(currentModel, true); @@ -257,6 +329,11 @@ void Rasteriser::Render(const Bitmap& bitmap) DrawGouraud(bitmap.GetDC(), currentModel); break; case (DrawMethod::Textured): + if (!titleDrawn) + { + DrawString(bitmap.GetDC(), 10, 10, _T("Textured")); + titleDrawn = true; + } currentModel.CalculateVertexNormals(); CalculateLighting(currentModel, true); @@ -269,8 +346,6 @@ void Rasteriser::Render(const Bitmap& bitmap) currentModel.ClearPendingTransforms(); } } - - DrawString(bitmap.GetDC(), 10, 10, _T("Hello World")); } } @@ -393,6 +468,8 @@ void Rasteriser::DrawGouraud(HDC hDc, Model& model) void Rasteriser::DrawSolidTextured(HDC hDc, Model& model) { + model.CalculateUVPerspective(); + int modelPolygonCount = (int)model.GetPolygonCount(); for (int i = 0; i < modelPolygonCount; i++) { @@ -439,112 +516,110 @@ void Rasteriser::FillPolygonFlat(HDC hDc, vector& verts, COLORREF colorI void Rasteriser::FillFlatSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3, COLORREF colorIn) { + // Check if any of the vertices match and dont draw the triangle if they do, this should stop the infinite loop that can happen with small vertex float numbers + if ((v1.GetXInt() == v2.GetXInt() && v1.GetYInt() == v2.GetYInt()) || (v1.GetXInt() == v3.GetXInt() && v1.GetYInt() == v3.GetYInt()) || (v2.GetXInt() == v3.GetXInt() && v3.GetYInt() == v2.GetYInt())) + { + return; + } + Vertex tempA = Vertex(v1); Vertex tempB = Vertex(v1); bool changed1 = false; bool changed2 = false; - int dx1 = (int)ceil(abs(v2.GetX() - v1.GetX())); - int dy1 = (int)ceil(abs(v2.GetY() - v1.GetY())); + int dx1 = (int)abs(v2.GetXInt() - v1.GetXInt()); + int dy1 = (int)abs(v2.GetYInt() - v1.GetYInt()); + int dx2 = (int)abs(v3.GetXInt() - v1.GetXInt()); + int dy2 = (int)abs(v3.GetYInt() - v1.GetYInt()); - int dx2 = (int)ceil(abs(v3.GetX() - v1.GetX())); - int dy2 = (int)ceil(abs(v3.GetY() - v1.GetY())); - - int signx1 = (int)ceil(sgn(v2.GetX() - v1.GetX())); - int signx2 = (int)ceil(sgn(v3.GetX() - v1.GetX())); - - int signy1 = (int)ceil(sgn(v2.GetY() - v1.GetY())); - int signy2 = (int)ceil(sgn(v3.GetY() - v1.GetY())); + int signx1 = (int)sgn(v2.GetXInt() - v1.GetXInt()); + int signx2 = (int)sgn(v3.GetXInt() - v1.GetXInt()); + int signy1 = (int)sgn(v2.GetYInt() - v1.GetYInt()); + int signy2 = (int)sgn(v3.GetYInt() - v1.GetYInt()); if (dy1 > dx1) { - int tempInt = dx1; - dx1 = dy1; - dy1 = tempInt; + swap(dx1, dy1); changed1 = true; } if (dy2 > dx2) { - int tempInt = dx2; - dx2 = dy2; - dy2 = tempInt; + swap(dx2, dy2); changed2 = true; } int e1 = 2 * dy1 - dx1; - int e2 = 2 * dy2 - dx2; + int e2 = 2 * dy2 - dx2; for (int i = 0; i <= dx1; i++) { - float leftEndPoint; - float rightEndPoint; - - if (tempA.GetX() < tempB.GetX()) + int leftEndPoint; + int rightEndPoint; + + if (tempA.GetXInt() < tempB.GetXInt()) { - leftEndPoint = tempA.GetX() - 1.0f; - rightEndPoint = tempB.GetX() + 1.0f; + leftEndPoint = tempA.GetXInt(); + rightEndPoint = tempB.GetXInt(); } else { - leftEndPoint = tempB.GetX() - 1.0f; - rightEndPoint = tempA.GetX() + 1.0f; + leftEndPoint = tempB.GetXInt(); + rightEndPoint = tempA.GetXInt(); } - for (int xi = (int)ceil(leftEndPoint); xi <= (int)ceil(rightEndPoint); xi++) + for (int xi = leftEndPoint; xi < rightEndPoint; xi++) { SetPixel(hDc, xi, tempA.GetYInt(), colorIn); } - - while (e1 >= 0) { if (changed1) { - tempA.SetX((float)tempA.GetX() + (float)signx1); + tempA.SetX((float)(tempA.GetXInt() + signx1)); } else { - tempA.SetY((float)tempA.GetY() + (float)signy1); + tempA.SetY((float)(tempA.GetYInt() + signy1)); } e1 = e1 - 2 * dx1; } if (changed1) { - tempA.SetY((float)tempA.GetY() + (float)signy1); + tempA.SetY((float)(tempA.GetYInt() + signy1)); } else { - tempA.SetX((float)tempA.GetX() + (float)signx1); + tempA.SetX((float)(tempA.GetXInt() + signx1)); } e1 = e1 + 2 * dy1; - while (tempB.GetYInt() != tempA.GetYInt()) + while (tempB.GetYInt(true) != tempA.GetYInt(true)) { while (e2 >= 0) { if (changed2) { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); + tempB.SetX((float)(tempB.GetXInt() + signx2)); } else { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); + tempB.SetY((float)(tempB.GetYInt() + signy2)); } e2 = e2 - 2 * dx2; } if (changed2) { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); + tempB.SetY((float)(tempB.GetYInt() + signy2)); } else { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); + tempB.SetX((float)(tempB.GetXInt() + signx2)); } e2 = e2 + 2 * dy2; } @@ -588,66 +663,62 @@ void Rasteriser::FillPolygonGouraud(HDC hDc, vector& verts) void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3) { + // Check if any of the vertices match and dont draw the triangle if they do, this should stop the infinite loop that can happen with small vertex float numbers + if ((v1.GetXInt() == v2.GetXInt() && v1.GetYInt() == v2.GetYInt()) || (v1.GetXInt() == v3.GetXInt() && v1.GetYInt() == v3.GetYInt()) || (v2.GetXInt() == v3.GetXInt() && v3.GetYInt() == v2.GetYInt())) + { + return; + } + Vertex tempA = Vertex(v1); Vertex tempB = Vertex(v1); bool changed1 = false; bool changed2 = false; - int dx1 = (int)ceil(abs(v2.GetX() - v1.GetX())); - int dy1 = (int)ceil(abs(v2.GetY() - v1.GetY())); + int dx1 = (int)abs(v2.GetXInt() - v1.GetXInt()); + int dy1 = (int)abs(v2.GetYInt() - v1.GetYInt()); + int dx2 = (int)abs(v3.GetXInt() - v1.GetXInt()); + int dy2 = (int)abs(v3.GetYInt() - v1.GetYInt()); - int dx2 = (int)ceil(abs(v3.GetX() - v1.GetX())); - int dy2 = (int)ceil(abs(v3.GetY() - v1.GetY())); - - int signx1 = (int)ceil(sgn(v2.GetX() - v1.GetX())); - int signx2 = (int)ceil(sgn(v3.GetX() - v1.GetX())); - - int signy1 = (int)ceil(sgn(v2.GetY() - v1.GetY())); - int signy2 = (int)ceil(sgn(v3.GetY() - v1.GetY())); + int signx1 = (int)sgn(v2.GetXInt() - v1.GetXInt()); + int signx2 = (int)sgn(v3.GetXInt() - v1.GetXInt()); + int signy1 = (int)sgn(v2.GetYInt() - v1.GetYInt()); + int signy2 = (int)sgn(v3.GetYInt() - v1.GetYInt()); if (dy1 > dx1) { - int tempDx = dx1; - dx1 = dy1; - dy1 = tempDx; + swap(dx1, dy1); changed1 = true; } if (dy2 > dx2) { - int tempDx = dx2; - dx2 = dy2; - dy2 = tempDx; + swap(dx2, dy2); changed2 = true; } - int e1 = 2 * (int)dy1 - (int)dx1; - int e2 = 2 * (int)dy2 - (int)dx2; + int e1 = 2 * dy1 - dx1; + int e2 = 2 * dy2 - dx2; - for (int i = 0; i <= (int)dx1; i++) + for (int i = 0; i <= dx1; i++) { - float leftEndPoint; - float rightEndPoint; + int leftEndPoint; + int rightEndPoint; + int sideFix; - if (tempA.GetX() < tempB.GetX()) + if (tempA.GetXInt() < tempB.GetXInt()) { - leftEndPoint = tempA.GetX(); - rightEndPoint = tempB.GetX() + 1.0f; + leftEndPoint = tempA.GetXInt(); + rightEndPoint = tempB.GetXInt(); + sideFix = 0; } else { - leftEndPoint = tempB.GetX(); - rightEndPoint = tempA.GetX() + 1.0f; + leftEndPoint = tempB.GetXInt(); + rightEndPoint = tempA.GetXInt(); + sideFix = 1; } - //float iRedA = Interpolate(tempA.GetY(), (float)v1.GetR(), (float)v2.GetR(), v1.GetY(), v2.GetY()); - //float iRedB = Interpolate(tempA.GetY(), (float)v1.GetR(), (float)v3.GetR(), v1.GetY(), v3.GetY()); - //float iGreenA = Interpolate(tempA.GetY(), (float)v1.GetG(), (float)v2.GetG(), v1.GetY(), v2.GetY()); - //float iGreenB = Interpolate(tempA.GetY(), (float)v1.GetG(), (float)v3.GetG(), v1.GetY(), v3.GetY()); - //float iBlueA = Interpolate(tempA.GetY(), (float)v1.GetB(), (float)v2.GetB(), v1.GetY(), v2.GetY()); - //float iBlueB = Interpolate(tempA.GetY(), (float)v1.GetB(), (float)v3.GetB(), v1.GetY(), v3.GetY()); - // Interpolate the Edge Colors of the 3 Vertex, Lerping seems to give better results given the // non precise nature of converting the floats into ints since it works on the start and end, and // interpolates fixed between those values (regular interpolation would sometimes overflow and cause @@ -659,279 +730,49 @@ void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex float iBlueA = Lerp(v1.GetB(), v2.GetB(), (float)i / (float)dx1); float iBlueB = Lerp(v1.GetB(), v3.GetB(), (float)i / (float)dx1); - int xLength = (int)ceil(rightEndPoint) - (int)ceil(leftEndPoint); - int ci = 0; + int xLength = rightEndPoint - leftEndPoint; + int ci = xLength * sideFix; + + for (int xi = leftEndPoint; xi < rightEndPoint; xi++) + { + float ti = ((float)ci / (float)xLength); - for (int xi = (int)leftEndPoint; xi <= (int)rightEndPoint; xi++) - { - float ti = (float)ci / (float)xLength; float redTmp = Lerp(iRedA, iRedB, ti); float greenTmp = Lerp(iGreenA, iGreenB, ti); float blueTmp = Lerp(iBlueA, iBlueB, ti); COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)redTmp), BoundsCheck(0, 255, (int)greenTmp), BoundsCheck(0, 255, (int)blueTmp)); SetPixel(hDc, xi, tempA.GetYInt(), currentColor); - ci++; - } - - - while (e1 >= 0) - { - if (changed1) + if (sideFix == 1) { - tempA.SetX((float)tempA.GetX() + (float)signx1); + ci--; } else { - tempA.SetY((float)tempA.GetY() + (float)signy1); - } - e1 = e1 - 2 * dx1; - } - - if (changed1) - { - tempA.SetY((float)tempA.GetY() + (float)signy1); - } - else - { - tempA.SetX((float)tempA.GetX() + (float)signx1); - } - - e1 = e1 + 2 * dy1; - - while (tempB.GetYInt() != tempA.GetYInt()) - { - while (e2 >= 0) - { - if (changed2) - { - tempB.SetX((float)tempB.GetX() + (float)signx2); - } - else - { - tempB.SetY((float)tempB.GetY() + (float)signy2); - } - e2 = e2 - 2 * dx2; - } - - if (changed2) - { - tempB.SetY((float)tempB.GetY() + (float)signy2); - } - else - { - tempB.SetX((float)tempB.GetX() + (float)signx2); - } - e2 = e2 + 2 * dy2; - } - } -} - -void Rasteriser::FillPolygonTextured(HDC hDc, Model& model, vector& verts) -{ - sort(verts.begin(), verts.end(), VerticiesYCompareAsc); - if (verts[1].GetY() == verts[2].GetY()) - { - FillTexturedSideTriangle(hDc, model, verts[0], verts[1], verts[2], model.GetUVCoord(verts[0].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex()), model.GetUVCoord(verts[2].GetUVIndex())); - } - else if (verts[0].GetY() == verts[1].GetY()) - { - FillTexturedSideTriangle(hDc, model, verts[2], verts[0], verts[1], model.GetUVCoord(verts[2].GetUVIndex()), model.GetUVCoord(verts[0].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex())); - } - else - { - Vertex temp = Vertex(verts[0].GetX() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetX() - verts[0].GetX()), verts[1].GetY(), verts[1].GetZ()); - temp.SetNormal(verts[1].GetNormal()); - - //model.GetUVCoord(verts[1].GetUVIndex()).GetU() + ((model.GetUVCoord(verts[1].GetUVIndex()).GetV() - model.GetUVCoord(verts[0].GetUVIndex()).GetV()) / (model.GetUVCoord(verts[2].GetUVIndex()).GetV() - model.GetUVCoord(verts[0].GetUVIndex()).GetV())) * (model.GetUVCoord(verts[2].GetUVIndex()).GetU() - model.GetUVCoord(verts[0].GetUVIndex()).GetU()); - - float uc0 = model.GetUVCoord(verts[0].GetUVIndex()).GetU(); - float vc0 = model.GetUVCoord(verts[0].GetUVIndex()).GetV(); - float uc1 = model.GetUVCoord(verts[1].GetUVIndex()).GetU(); - float vc1 = model.GetUVCoord(verts[1].GetUVIndex()).GetV(); - float uc2 = model.GetUVCoord(verts[2].GetUVIndex()).GetU(); - float vc2 = model.GetUVCoord(verts[2].GetUVIndex()).GetV(); - - float tempU = uc0 + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (uc2 - uc0); - float tempV = vc0 + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (vc2 - vc0); - UVCoord tempCoords = UVCoord(tempU, tempV); - - float cRed = verts[0].GetR() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetR() - verts[0].GetR()); - float cGreen = verts[0].GetG() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetG() - verts[0].GetG()); - float cBlue = verts[0].GetB() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetB() - verts[0].GetB()); - temp.SetColor(BoundsCheck(0, 255, (int)cRed), BoundsCheck(0, 255, (int)cGreen), BoundsCheck(0, 255, (int)cBlue)); - - if (drawn < toDraw + 100) - { - if (verts[1].GetX() < temp.GetX()) - { - FillTexturedSideTriangle(hDc, model, verts[0], verts[1], temp, model.GetUVCoord(verts[0].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex()), tempCoords); - FillTexturedSideTriangle(hDc, model, verts[2], verts[1], temp, model.GetUVCoord(verts[2].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex()), tempCoords); - drawn++; - } - else - { - FillTexturedSideTriangle(hDc, model, verts[0], temp, verts[1], model.GetUVCoord(verts[0].GetUVIndex()), tempCoords, model.GetUVCoord(verts[1].GetUVIndex())); - FillTexturedSideTriangle(hDc, model, verts[2], temp, verts[1], model.GetUVCoord(verts[2].GetUVIndex()), tempCoords, model.GetUVCoord(verts[1].GetUVIndex())); - drawn++; - } - } - } -} - -void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3, const UVCoord& uv1, const UVCoord& uv2, const UVCoord& uv3) -{ - Vertex tempA = Vertex(v1); - Vertex tempB = Vertex(v1); - UVCoord tempUVA = UVCoord(uv1); - UVCoord tempUVB = UVCoord(uv1); - - bool changed1 = false; - bool changed2 = false; - - float uc0 = uv1.GetU(); - float vc0 = uv1.GetV(); - float uc1 = uv2.GetU(); - float vc1 = uv2.GetV(); - float uc2 = uv3.GetU(); - float vc2 = uv3.GetV(); - - int dx1 = (int)ceil(abs(v2.GetX() - v1.GetX())); - int dy1 = (int)ceil(abs(v2.GetY() - v1.GetY())); - int du1 = (int)ceil(abs(uc1 - uc0)); - int dv1 = (int)ceil(abs(vc1 - vc0)); - - int dx2 = (int)ceil(abs(v3.GetX() - v1.GetX())); - int dy2 = (int)ceil(abs(v3.GetY() - v1.GetY())); - int du2 = (int)ceil(abs(uc2 - uc0)); - int dv2 = (int)ceil(abs(vc2 - vc0)); - - int signx1 = (int)ceil(sgn(v2.GetX() - v1.GetX())); - int signx2 = (int)ceil(sgn(v3.GetX() - v1.GetX())); - int signu1 = (int)ceil(sgn(uc1 - uc0)); - int signu2 = (int)ceil(sgn(uc2 - uc0)); - - int signy1 = (int)ceil(sgn(v2.GetY() - v1.GetY())); - int signy2 = (int)ceil(sgn(v3.GetY() - v1.GetY())); - int signv1 = (int)ceil(sgn(vc1 - vc0)); - int signv2 = (int)ceil(sgn(vc2 - vc0)); - - if (dy1 > dx1) - { - int tempDx = dx1; - dx1 = dy1; - dy1 = tempDx; - - changed1 = true; - } - - if (dy2 > dx2) - { - int tempDx = dx2; - dx2 = dy2; - dy2 = tempDx; - - changed2 = true; - } - - int e1 = 2 * (int)dy1 - (int)dx1; - int e2 = 2 * (int)dy2 - (int)dx2; - - for (int i = 0; i <= (int)dx1; i++) - { - float leftEndPoint; - float rightEndPoint; - float leftU; - float rightU; - float leftV; - float rightV; - - if (tempA.GetX() < tempB.GetX()) - { - leftEndPoint = tempA.GetX() - 1.0f; - rightEndPoint = tempB.GetX() + 1.0f; - leftU = tempUVA.GetU(); - rightU = tempUVB.GetU(); - leftV = tempUVA.GetV(); - rightV = tempUVB.GetV(); - } - else - { - leftEndPoint = tempB.GetX() - 1.0f; - rightEndPoint = tempA.GetX() + 1.0f; - leftU = tempUVB.GetU(); - rightU = tempUVA.GetU(); - leftV = tempUVB.GetV(); - rightV = tempUVA.GetV(); - } - - float uy1 = Lerp(uv1.GetV(), uv2.GetV(), (float)i / (float)dx1); - float uy2 = Lerp(uv1.GetV(), uv3.GetV(), (float)i / (float)dx1); - - //x0 + (y - y0) * ((x1 - x0) / (y1 - y0)) - //a + (b - a) * t - float UCoordA = Interpolate(tempA.GetY(), uv1.GetU(), uv2.GetU(), v1.GetY(), v2.GetY()); - float UCoordB = Interpolate(tempA.GetY(), uv1.GetU(), uv3.GetU(), v1.GetY(), v3.GetY()); - float VCoordA = Interpolate(tempA.GetY(), uv1.GetV(), uv2.GetV(), v1.GetY(), v2.GetY()); - float VCoordB = Interpolate(tempA.GetY(), uv1.GetV(), uv3.GetV(), v1.GetY(), v3.GetY()); - - float UCoord = (rightU - leftU) / (rightEndPoint - leftEndPoint); - float VCoord = (rightV - leftV) / (rightEndPoint - leftEndPoint); - - float iRedA = Lerp(v1.GetR(), v2.GetR(), (float)i / (float)dx1); - float iRedB = Lerp(v1.GetR(), v3.GetR(), (float)i / (float)dx1); - float iGreenA = Lerp(v1.GetG(), v2.GetG(), (float)i / (float)dx1); - float iGreenB = Lerp(v1.GetG(), v3.GetG(), (float)i / (float)dx1); - float iBlueA = Lerp(v1.GetB(), v2.GetB(), (float)i / (float)dx1); - float iBlueB = Lerp(v1.GetB(), v3.GetB(), (float)i / (float)dx1); - - int xLength = (int)ceil(rightEndPoint) - (int)ceil(leftEndPoint); - int ci = 0; - - if (i < 10000) - { - for (int xi = (int)ceil(leftEndPoint); xi <= (int)ceil(rightEndPoint); xi++) - { - float ti = (float)ci / (float)xLength; - float UCoordTmp = Lerp(UCoordA, UCoordB, ti); - float VCoordTmp = Lerp(VCoordA, VCoordB, ti); - float redTmp = Lerp(iRedA, iRedB, ti) / 100; - float greenTmp = Lerp(iGreenA, iGreenB, ti) / 100; - float blueTmp = Lerp(iBlueA, iBlueB, ti) / 100; - - COLORREF textureColor = model.GetTexture().GetTextureValue((int)UCoordTmp, (int)VCoordTmp); - COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)(GetRValue(textureColor) * redTmp)), BoundsCheck(0, 255, (int)(GetGValue(textureColor) * greenTmp)), BoundsCheck(0, 255, (int)(GetBValue(textureColor) * blueTmp))); - - SetPixel(hDc, xi, tempA.GetYInt(), currentColor); ci++; } } - while (e1 >= 0) { if (changed1) { - tempA.SetX((float)tempA.GetXInt() + (float)signx1); - tempUVA.SetU((float)tempUVA.GetU() + (float)signu1); + tempA.SetX((float)(tempA.GetXInt() + signx1)); } else { - tempA.SetY((float)tempA.GetYInt() + (float)signy1); - tempUVA.SetV((float)tempUVA.GetV() + (float)signv1); + tempA.SetY((float)(tempA.GetYInt() + signy1)); } e1 = e1 - 2 * dx1; } if (changed1) { - tempA.SetY((float)tempA.GetYInt() + (float)signy1); - tempUVA.SetV((float)tempUVA.GetV() + (float)signv1); + tempA.SetY((float)(tempA.GetYInt() + signy1)); } else { - tempA.SetX((float)tempA.GetXInt() + (float)signx1); - tempUVA.SetU((float)tempUVA.GetU() + (float)signu1); + tempA.SetX((float)(tempA.GetXInt() + signx1)); } e1 = e1 + 2 * dy1; @@ -942,28 +783,491 @@ void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v { if (changed2) { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); - tempUVB.SetU((float)tempUVB.GetU() + (float)signu2); + tempB.SetX((float)(tempB.GetXInt() + signx2)); } else { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); - tempUVB.SetV((float)tempUVB.GetV() + (float)signv2); + tempB.SetY((float)(tempB.GetYInt() + signy2)); } e2 = e2 - 2 * dx2; } if (changed2) { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); - tempUVB.SetV((float)tempUVB.GetV() + (float)signv2); + tempB.SetY((float)(tempB.GetYInt() + signy2)); } else { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); - tempUVB.SetU((float)tempUVB.GetU() + (float)signu2); + tempB.SetX((float)(tempB.GetXInt() + signx2)); } e2 = e2 + 2 * dy2; } } -} \ No newline at end of file +} + +void Rasteriser::FillPolygonTextured(HDC hDc, Model& model, vector& verts) +{ + sort(verts.begin(), verts.end(), VerticiesYCompareAsc); + + if (verts[1].GetY() == verts[2].GetY()) + { + FillTexturedSideTriangle(hDc, model, verts[0], verts[1], verts[2]); + } + else if (verts[0].GetY() == verts[1].GetY()) + { + FillTexturedSideTriangle(hDc, model, verts[2], verts[0], verts[1]); + } + else + { + Vertex temp = verts[1]; + temp.SetX(verts[0].GetX() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetX() - verts[0].GetX())); + + float tempZr = verts[0].GetZRecip() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetZRecip() - verts[0].GetZRecip()); + temp.SetZRecip(tempZr); + + float tempU = verts[0].GetUOverZ() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetUOverZ() - verts[0].GetUOverZ()); + float tempV = verts[0].GetVOverZ() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetVOverZ() - verts[0].GetVOverZ()); + temp.SetUOverZ(tempU); + temp.SetVOverZ(tempV); + + // Get the RGB value at the new vertex point + float cRed = verts[0].GetR() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetR() - verts[0].GetR()); + float cGreen = verts[0].GetG() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetG() - verts[0].GetG()); + float cBlue = verts[0].GetB() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetB() - verts[0].GetB()); + temp.SetColor(BoundsCheck(0, 255, (int)cRed), BoundsCheck(0, 255, (int)cGreen), BoundsCheck(0, 255, (int)cBlue)); + + if (verts[1].GetX() < temp.GetX()) + { + FillTexturedSideTriangle(hDc, model, verts[0], verts[1], temp); + FillTexturedSideTriangle(hDc, model, verts[2], verts[1], temp); + } + else + { + FillTexturedSideTriangle(hDc, model, verts[0], temp, verts[1]); + FillTexturedSideTriangle(hDc, model, verts[2], temp, verts[1]); + } + } +} + +void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + // Check if any of the vertices match and dont draw the triangle if they do, this should stop the infinite loop that can happen with small vertex float numbers + if ((v1.GetXInt() == v2.GetXInt() && v1.GetYInt() == v2.GetYInt()) || (v1.GetXInt() == v3.GetXInt() && v1.GetYInt() == v3.GetYInt()) || (v2.GetXInt() == v3.GetXInt() && v3.GetYInt() == v2.GetYInt())) + { + return; + } + + Vertex tempA = Vertex(v1); + Vertex tempB = Vertex(v1); + + bool changed1 = false; + bool changed2 = false; + + int dx1 = (int)abs(v2.GetXInt() - v1.GetXInt()); + int dy1 = (int)abs(v2.GetYInt() - v1.GetYInt()); + int dx2 = (int)abs(v3.GetXInt() - v1.GetXInt()); + int dy2 = (int)abs(v3.GetYInt() - v1.GetYInt()); + + int signx1 = (int)sgn(v2.GetXInt() - v1.GetXInt()); + int signx2 = (int)sgn(v3.GetXInt() - v1.GetXInt()); + int signy1 = (int)sgn(v2.GetYInt() - v1.GetYInt()); + int signy2 = (int)sgn(v3.GetYInt() - v1.GetYInt()); + + if (dy1 > dx1) + { + swap(dx1, dy1); + changed1 = true; + } + + if (dy2 > dx2) + { + swap(dx2, dy2); + changed2 = true; + } + + int e1 = 2 * dy1 - dx1; + int e2 = 2 * dy2 - dx2; + + for (int i = 0; i <= dx1; i++) + { + int leftEndPoint; + int rightEndPoint; + int sideFix; + + if (tempA.GetXInt() < tempB.GetXInt()) + { + leftEndPoint = tempA.GetXInt(); + rightEndPoint = tempB.GetXInt(); + sideFix = 0; + } + else + { + leftEndPoint = tempB.GetXInt(); + rightEndPoint = tempA.GetXInt(); + sideFix = 1; + } + + float currentPoint = (float)i / (float)dx1; + float UCoordA = Interpolate(tempA.GetY(), v1.GetUOverZ(), v2.GetUOverZ(), v1.GetY(), v2.GetY()); + float UCoordB = Interpolate(tempA.GetY(), v1.GetUOverZ(), v3.GetUOverZ(), v1.GetY(), v3.GetY()); + float VCoordA = Interpolate(tempA.GetY(), v1.GetVOverZ(), v2.GetVOverZ(), v1.GetY(), v2.GetY()); + float VCoordB = Interpolate(tempA.GetY(), v1.GetVOverZ(), v3.GetVOverZ(), v1.GetY(), v3.GetY()); + float ZRecipA = Interpolate(tempA.GetY(), v1.GetZRecip(), v2.GetZRecip(), v1.GetY(), v2.GetY()); + float ZRecipB = Interpolate(tempA.GetY(), v1.GetZRecip(), v3.GetZRecip(), v1.GetY(), v3.GetY()); + + float iRedA = Lerp(v1.GetR(), v2.GetR(), currentPoint); + float iRedB = Lerp(v1.GetR(), v3.GetR(), currentPoint); + float iGreenA = Lerp(v1.GetG(), v2.GetG(), currentPoint); + float iGreenB = Lerp(v1.GetG(), v3.GetG(), currentPoint); + float iBlueA = Lerp(v1.GetB(), v2.GetB(), currentPoint); + float iBlueB = Lerp(v1.GetB(), v3.GetB(), currentPoint); + + int xLength = rightEndPoint - leftEndPoint; + int ci = xLength * sideFix; + + for (int xi = leftEndPoint; xi < rightEndPoint; xi++) + { + float ti = ((float)ci / (float)xLength); + + float UCoordTmp = Lerp(UCoordA, UCoordB, ti); + float VCoordTmp = Lerp(VCoordA, VCoordB, ti); + float ZRecipTmp = Lerp(ZRecipA, ZRecipB, ti); + float redTmp = Lerp(iRedA, iRedB, ti) / 100; + float greenTmp = Lerp(iGreenA, iGreenB, ti) / 100; + float blueTmp = Lerp(iBlueA, iBlueB, ti) / 100; + + float uFinal = UCoordTmp / ZRecipTmp; + float vFinal = VCoordTmp / ZRecipTmp; + + COLORREF textureColor = model.GetTexture().GetTextureValue((int)uFinal, (int)vFinal); + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)(GetRValue(textureColor) * redTmp)), BoundsCheck(0, 255, (int)(GetGValue(textureColor) * greenTmp)), BoundsCheck(0, 255, (int)(GetBValue(textureColor) * blueTmp))); + + SetPixel(hDc, xi, tempA.GetYInt(), currentColor); + if (sideFix == 1) + { + ci--; + } + else + { + ci++; + } + } + + while (e1 >= 0) + { + if (changed1) + { + tempA.SetX((float)(tempA.GetXInt() + signx1)); + } + else + { + tempA.SetY((float)(tempA.GetYInt() + signy1)); + } + e1 = e1 - 2 * dx1; + } + + if (changed1) + { + tempA.SetY((float)(tempA.GetYInt() + signy1)); + } + else + { + tempA.SetX((float)(tempA.GetXInt() + signx1)); + } + + e1 = e1 + 2 * dy1; + + while (tempB.GetYInt(true) != tempA.GetYInt(true)) + { + while (e2 >= 0) + { + if (changed2) + { + tempB.SetX((float)(tempB.GetXInt() + signx2)); + } + else + { + tempB.SetY((float)(tempB.GetYInt() + signy2)); + } + e2 = e2 - 2 * dx2; + } + + if (changed2) + { + tempB.SetY((float)(tempB.GetYInt() + signy2)); + } + else + { + tempB.SetX((float)(tempB.GetXInt() + signx2)); + } + e2 = e2 + 2 * dy2; + } + + } +} + +void Rasteriser::FillPolygonTexturedA(HDC hDc, Model& model, vector& verts) +{ + sort(verts.begin(), verts.end(), VerticiesYCompareAsc); + + if (verts[1].GetY() == verts[2].GetY()) + { + FillTexturedBottomFlatTriangle(hDc, model, verts[0], verts[1], verts[2]); + } + else if (verts[0].GetY() == verts[1].GetY()) + { + FillTexturedTopFlatTriangle(hDc, model, verts[0], verts[1], verts[2]); + } + else + { + Vertex temp = verts[1]; + temp.SetX(verts[0].GetX() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetX() - verts[0].GetX())); + + float tempZr = verts[1].GetZOriginal() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetZOriginal() - verts[0].GetZOriginal()); + temp.SetZOriginal(tempZr); + + float uc1 = model.GetUVCoord(verts[0].GetUVIndex()).GetU(); + float vc1 = model.GetUVCoord(verts[0].GetUVIndex()).GetV(); + float uc2 = model.GetUVCoord(verts[1].GetUVIndex()).GetU(); + float vc2 = model.GetUVCoord(verts[1].GetUVIndex()).GetV(); + float uc3 = model.GetUVCoord(verts[2].GetUVIndex()).GetU(); + float vc3 = model.GetUVCoord(verts[2].GetUVIndex()).GetV(); + + float tempU = Interpolate(verts[1].GetY(), uc1, uc3, verts[0].GetY(), verts[2].GetY()); // uc1 + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (uc3 - uc1); + float tempV = Interpolate(verts[1].GetY(), vc1, vc3, verts[0].GetY(), verts[2].GetY()); // vc2 + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (vc3 - vc2); + temp.UVCorrect(tempU, tempV); + //temp.SetUOverZ(tempU); + //temp.SetVOverZ(tempV); + + //x0 + (y - y0) * ((x1 - x0) / (y1 - y0)); + + float cRed = verts[0].GetR() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetR() - verts[0].GetR()); + float cGreen = verts[0].GetG() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetG() - verts[0].GetG()); + float cBlue = verts[0].GetB() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (verts[2].GetB() - verts[0].GetB()); + temp.SetColor(BoundsCheck(0, 255, (int)cRed), BoundsCheck(0, 255, (int)cGreen), BoundsCheck(0, 255, (int)cBlue)); + + FillTexturedBottomFlatTriangle(hDc, model, verts[0], verts[1], temp); + FillTexturedTopFlatTriangle(hDc, model, verts[1], temp, verts[2]); + + } +} + +void Rasteriser::FillTexturedBottomFlatTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + float slope1 = (v2.GetX() - v1.GetX()) / (v2.GetY() - v1.GetY()); + float slope2 = (v3.GetX() - v1.GetX()) / (v3.GetY() - v1.GetY()); + + float x1 = v1.GetX() - 1.0f; + float x2 = v1.GetX() + 1.0f; + + float v2v1Diff = (v2.GetY() - v1.GetY()); + float colorSlopeBlue1 = (v2.GetB() - v1.GetB()) / v2v1Diff; + float colorSlopeRed1 = (v2.GetR() - v1.GetR()) / v2v1Diff; + float colorSlopeGreen1 = (v2.GetG() - v1.GetG()) / v2v1Diff; + float uSlope1 = (v2.GetUOverZ() - v1.GetUOverZ()) / v2v1Diff; + float vSlope1 = (v2.GetVOverZ() - v1.GetVOverZ()) / v2v1Diff; + float zrSlope1 = (v2.GetZRecip() - v1.GetZRecip()) / v2v1Diff; + + float v3v1Diff = (v3.GetY() - v1.GetY()); + float colorSlopeBlue2 = (v3.GetB() - v1.GetB()) / v3v1Diff; + float colorSlopeRed2 = (v3.GetR() - v1.GetR()) / v3v1Diff; + float colorSlopeGreen2 = (v3.GetG() - v1.GetG()) / v3v1Diff; + float uSlope2 = (v3.GetUOverZ() - v1.GetUOverZ()) / v3v1Diff; + float vSlope2 = (v3.GetVOverZ() - v1.GetVOverZ()) / v3v1Diff; + float zrSlope2 = (v3.GetZRecip() - v1.GetZRecip()) / v3v1Diff; + + float cBlue1 = (float)v1.GetB(); + float cRed1 = (float)v1.GetR(); + float cGreen1 = (float)v1.GetG(); + float uc1 = v1.GetUOverZ(); + float vc1 = v1.GetVOverZ(); + float zr1 = v1.GetZRecip(); + float cBlue2 = (float)v1.GetB(); + float cRed2 = (float)v1.GetR(); + float cGreen2 = (float)v1.GetG(); + float uc2 = v1.GetUOverZ(); + float vc2 = v1.GetVOverZ(); + float zr2 = v1.GetZRecip(); + + if (slope2 < slope1) + { + float slopeTmp = slope1; + slope1 = slope2; + slope2 = slopeTmp; + + slopeTmp = colorSlopeRed1; + colorSlopeRed1 = colorSlopeRed2; + colorSlopeRed2 = slopeTmp; + + slopeTmp = colorSlopeGreen1; + colorSlopeGreen1 = colorSlopeGreen2; + colorSlopeGreen2 = slopeTmp; + + slopeTmp = colorSlopeBlue1; + colorSlopeBlue1 = colorSlopeBlue2; + colorSlopeBlue2 = slopeTmp; + + slopeTmp = uSlope1; + uSlope1 = uSlope2; + uSlope2 = slopeTmp; + + slopeTmp = vSlope1; + vSlope1 = vSlope2; + vSlope2 = slopeTmp; + + slopeTmp = zrSlope1; + zrSlope1 = zrSlope2; + zrSlope2 = slopeTmp; + } + + for (float scanlineY = v1.GetY(); scanlineY < v2.GetY() + 0.5f; scanlineY++) + { + for (int xPos = (int)ceil(x1); xPos < (int)x2; xPos++) + { + float t = (xPos - x1) / (x2 - x1); + + float redTmp = Lerp(cRed1, cRed2, t) / 100; + float greenTmp = Lerp(cGreen1, cGreen2, t) / 100; + float blueTmp = Lerp(cBlue1, cBlue2, t) / 100; + + float UCoordTmp = Lerp(uc1, uc2, t); + float VCoordTmp = Lerp(vc1, vc2, t); + float ZRecipTmp = Lerp(zr1, zr2, t); + + float uFinal = UCoordTmp / ZRecipTmp; + float vFinal = VCoordTmp / ZRecipTmp; + + COLORREF textureColor = model.GetTexture().GetTextureValue((int)uFinal, (int)vFinal); + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)(GetRValue(textureColor) * redTmp)), BoundsCheck(0, 255, (int)(GetGValue(textureColor) * greenTmp)), BoundsCheck(0, 255, (int)(GetBValue(textureColor) * blueTmp))); + + SetPixel(hDc, xPos, (int)scanlineY, currentColor); + } + + x1 += slope1; + x2 += slope2; + + cRed1 += colorSlopeRed1; + cGreen1 += colorSlopeGreen1; + cBlue1 += colorSlopeBlue1; + uc1 += uSlope1; + vc1 += vSlope1; + zr1 += zrSlope1; + + cRed2 += colorSlopeRed2; + cGreen2 += colorSlopeGreen2; + cBlue2 += colorSlopeBlue2; + uc2 += uSlope2; + vc2 += vSlope2; + zr2 += zrSlope2; + } +} + +void Rasteriser::FillTexturedTopFlatTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + float slope1 = (v3.GetX() - v1.GetX()) / (v3.GetY() - v1.GetY()); + float slope2 = (v3.GetX() - v2.GetX()) / (v3.GetY() - v2.GetY()); + + float x1 = v3.GetX() - 1.0f; + float x2 = v3.GetX() + 1.0f; + + float v3v1Diff = (v3.GetY() - v1.GetY()); + float colorSlopeBlue1 = (v3.GetB() - v1.GetB()) / v3v1Diff; + float colorSlopeRed1 = (v3.GetR() - v1.GetR()) / v3v1Diff; + float colorSlopeGreen1 = (v3.GetG() - v1.GetG()) / v3v1Diff; + float uSlope1 = (v3.GetUOverZ() - v1.GetUOverZ()) / v3v1Diff; + float vSlope1 = (v3.GetVOverZ() - v1.GetVOverZ()) / v3v1Diff; + float zrSlope1 = (v3.GetZRecip() - v1.GetZRecip()) / v3v1Diff; + + float v3v2Diff = (v3.GetY() - v2.GetY()); + float colorSlopeBlue2 = (v3.GetB() - v2.GetB()) / v3v2Diff; + float colorSlopeRed2 = (v3.GetR() - v2.GetR()) / v3v2Diff; + float colorSlopeGreen2 = (v3.GetG() - v2.GetG()) / v3v2Diff; + float uSlope2 = (v3.GetUOverZ() - v2.GetUOverZ()) / v3v2Diff; + float vSlope2 = (v3.GetVOverZ() - v2.GetVOverZ()) / v3v2Diff; + float zrSlope2 = (v3.GetZRecip() - v2.GetZRecip()) / v3v2Diff; + + float cBlue1 = (float)v3.GetB(); + float cRed1 = (float)v3.GetR(); + float cGreen1 = (float)v3.GetG(); + float uc1 = v3.GetUOverZ(); + float vc1 = v3.GetVOverZ(); + float zr1 = v3.GetZRecip(); + float cBlue2 = (float)v3.GetB(); + float cRed2 = (float)v3.GetR(); + float cGreen2 = (float)v3.GetG(); + float uc2 = v3.GetUOverZ(); + float vc2 = v3.GetVOverZ(); + float zr2 = v3.GetZRecip(); + + if (slope1 < slope2) + { + float slopeTmp = slope1; + slope1 = slope2; + slope2 = slopeTmp; + + slopeTmp = colorSlopeRed1; + colorSlopeRed1 = colorSlopeRed2; + colorSlopeRed2 = slopeTmp; + + slopeTmp = colorSlopeGreen1; + colorSlopeGreen1 = colorSlopeGreen2; + colorSlopeGreen2 = slopeTmp; + + slopeTmp = colorSlopeBlue1; + colorSlopeBlue1 = colorSlopeBlue2; + colorSlopeBlue2 = slopeTmp; + + slopeTmp = uSlope1; + uSlope1 = uSlope2; + uSlope2 = slopeTmp; + + slopeTmp = vSlope1; + vSlope1 = vSlope2; + vSlope2 = slopeTmp; + + slopeTmp = zrSlope1; + zrSlope1 = zrSlope2; + zrSlope2 = slopeTmp; + } + + for (float scanlineY = v3.GetY(); scanlineY > v1.GetY(); scanlineY--) + { + for (int xPos = (int)ceil(x1); xPos < (int)x2; xPos++) + { + float t = (xPos - x1) / (x2 - x1); + + float redTmp = Lerp(cRed1, cRed2, t) / 100; + float greenTmp = Lerp(cGreen1, cGreen2, t) / 100; + float blueTmp = Lerp(cBlue1, cBlue2, t) / 100; + + float UCoordTmp = Lerp(uc1, uc2, t); + float VCoordTmp = Lerp(vc1, vc2, t); + float ZRecipTmp = Lerp(zr1, zr2, t); + + float uFinal = UCoordTmp / ZRecipTmp; + float vFinal = VCoordTmp / ZRecipTmp; + + COLORREF textureColor = model.GetTexture().GetTextureValue((int)uFinal, (int)vFinal); + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)(GetRValue(textureColor) * redTmp)), BoundsCheck(0, 255, (int)(GetGValue(textureColor) * greenTmp)), BoundsCheck(0, 255, (int)(GetBValue(textureColor) * blueTmp))); + + SetPixel(hDc, xPos, (int)scanlineY, currentColor); + } + + x1 -= slope1; + x2 -= slope2; + + cRed1 -= colorSlopeRed1; + cGreen1 -= colorSlopeGreen1; + cBlue1 -= colorSlopeBlue1; + uc1 -= uSlope1; + vc1 -= vSlope1; + zr1 -= zrSlope1; + + cRed2 -= colorSlopeRed2; + cGreen2 -= colorSlopeGreen2; + cBlue2 -= colorSlopeBlue2; + uc2 -= uSlope2; + vc2 -= vSlope2; + zr2 -= zrSlope2; + } +} diff --git a/Rasteriser.h b/Rasteriser.h index c948ce2..162b21b 100644 --- a/Rasteriser.h +++ b/Rasteriser.h @@ -2,6 +2,7 @@ #include #include #include +#include #include "Framework.h" #include "Vector3D.h" #include "Vertex.h" @@ -25,7 +26,7 @@ public: void Update(const Bitmap& bitmap); void Render(const Bitmap& bitmap); void ClearViewport(const Bitmap& bitmap); - void DrawString(HDC hDc, int x, int y, LPCTSTR text, COLORREF textColor = 0x00FFFFFF, COLORREF backgroundColor = 0x00000000); + void DrawString(HDC hDc, int x, int y, LPCTSTR text, int fontSize = 48, COLORREF textColor = 0x00FFFFFF, COLORREF backgroundColor = 0x00000000); ~Rasteriser(); @@ -58,23 +59,40 @@ public: void FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3); void FillPolygonTextured(HDC hDc, Model& model, vector& verticies); - void FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3, const UVCoord& uv1, const UVCoord& uv2, const UVCoord& uv3); + void FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3); + + void FillPolygonTexturedA(HDC hDc, Model& model, vector& verticies); + void FillTexturedBottomFlatTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3); + void FillTexturedTopFlatTriangle(HDC hDc, Model& model, const Vertex& v1, const Vertex& v2, const Vertex& v3); private: + // Vector arrays to hold the scene models, the lights and the cameras. vector _sceneModels; vector _lights; vector _cameras; + // Index of the currently viewing camera. int _currentCamera = 0; + // Matrices and Aspect ration for the viewing and perspective transformations. Matrix _currentPerspectiveMatrix; Matrix _currentViewMatrix; float _currentAspectRatio = 0.0f; - int _rotation = 0; - - int _currentDrawMode = 0; + // bool to check if the screen is minimized to stop processing bool _screenMinimized = false; string _modelDataLocation = ".//model_data/"; + + // timer variables to hold the start time of the showcase, and the current time for + // calculation of where in the showcase we are. + time_t _startTime; + time_t _currentTime; + + // an int to store the current state of the showcase. + int _currentState; + int _maxStates; + + // An array to store counters for use in. + int _counters[10]; }; diff --git a/Vertex.cpp b/Vertex.cpp index 23fc46a..f306dc0 100644 --- a/Vertex.cpp +++ b/Vertex.cpp @@ -207,14 +207,19 @@ float Vertex::GetZOriginal() const return _zOriginal; } -float Vertex::GetUOverZ() const +void Vertex::SetZOriginal(const float value) { - return _uOverZ; + _zOriginal = value; +} + +float Vertex::GetUOverZ() const +{ + return _uOverZ; } void Vertex::SetUOverZ(const float value) { - _uOverZ = value / _zOriginal; + _uOverZ = value; } float Vertex::GetVOverZ() const @@ -224,20 +229,27 @@ float Vertex::GetVOverZ() const void Vertex::SetVOverZ(const float value) { - _vOverZ = value / _zOriginal; + _vOverZ = value; } float Vertex::GetZRecip() const { - return _zRecip; + return _zRecip; } -void Vertex::UVCorrect(float u, float v) +void Vertex::SetZRecip(const float value) { - _zOriginal = _w; - _zRecip = 1 / _zOriginal; - SetUOverZ(u); - SetVOverZ(v); + _zRecip = value; +} + +void Vertex::UVCorrect(float u, float v, bool calcZRecip) +{ + SetUOverZ(u / _zOriginal); + SetVOverZ(v / _zOriginal); + if (calcZRecip) + { + SetZRecip(1 / _zOriginal); + } } int Vertex::GetXInt(bool forceRoundUp) const @@ -289,7 +301,8 @@ int Vertex::GetWInt(bool forceRoundUp) const } void Vertex::Dehomogenize() -{ +{ + _zOriginal = _w; _x = _x / _w; _y = _y / _w; _z = _z / _w; diff --git a/Vertex.h b/Vertex.h index 1ca154a..e38537b 100644 --- a/Vertex.h +++ b/Vertex.h @@ -45,12 +45,14 @@ public: void SetUVIndex(const int index); float GetZOriginal() const; + void SetZOriginal(const float value); float GetUOverZ() const; void SetUOverZ(const float value); - float GetVOverZ() const; + float GetVOverZ() const; void SetVOverZ(const float value); float GetZRecip() const; - void UVCorrect(float u, float v); + void SetZRecip(const float value); + void UVCorrect(float u, float v, bool calcZRecip = true); // Accessors for returning the private x, y, z and w values as integeres instead of floats // the ceil function to round the number up by defaults but using providing a false param will @@ -76,6 +78,7 @@ private: float _z; float _w; + float _zOriginalSet = 0; float _zOriginal; int _contributeCount;