diff --git a/Rasteriser.cpp b/Rasteriser.cpp index 5e4bd32..b4ceeea 100644 --- a/Rasteriser.cpp +++ b/Rasteriser.cpp @@ -52,10 +52,10 @@ bool Rasteriser::Initialise() } } - //_lights.push_back(new AmbientLight(50, 50, 50)); - _lights.push_back(new AmbientLight(255, 255, 255)); - //_lights.push_back(new DirectionalLight(Vector3D(-1, 0, 0), 150, 150, 150)); - _lights.push_back(new PointLight(Vertex(0, 0, -10), 0, 1, 0.01f, 150, 0, 0)); + _lights.push_back(new AmbientLight(50, 50, 50)); + //_lights.push_back(new AmbientLight(255, 255, 255)); + _lights.push_back(new DirectionalLight(Vector3D(-1, 0, -1), 150, 150, 150)); + //_lights.push_back(new PointLight(Vertex(0, 0, -10), 0, 1, 0.01f, 150, 0, 0)); _cameras.push_back(Camera(0.0f, 0.0f, 0.0f, Vertex(0.0f, 0.0f, -50.0f))); _screenMinimized = false; @@ -132,7 +132,7 @@ float Rasteriser::Interpolate(int y, int x0, int x1, int y0, int y1) float Rasteriser::Lerp(float a, float b, float t) { - return a + (b - a) * t; + return (1 - t) * a + t * b; } float Rasteriser::Lerp(int a, int b, float t) @@ -140,8 +140,12 @@ 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; @@ -153,7 +157,7 @@ void Rasteriser::Update(const Bitmap& bitmap) if (!_screenMinimized) { - int currentRot = (_rotation % 360); + int currentRot = 0;// 45; // (_rotation % 360); Vertex startPos = Vertex(0, 0, 20); int currentZOff = 0; int currentModelIndex = 0; @@ -569,7 +573,7 @@ void Rasteriser::FillPolygonGouraud(HDC hDc, vector& verts) float cBlue = Lerp(verts[0].GetB(), verts[2].GetB(), vDiff); temp.SetColor(BoundsCheck(0, 255, (int)cRed), BoundsCheck(0, 255, (int)cGreen), BoundsCheck(0, 255, (int)cBlue)); - if (verts[1].GetX() <= temp.GetX()) + if (verts[1].GetX() < temp.GetX()) { FillGouraudSideTriangle(hDc, verts[0], verts[1], temp); FillGouraudSideTriangle(hDc, verts[2], verts[1], temp); @@ -628,15 +632,26 @@ void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex if (tempA.GetX() < tempB.GetX()) { - leftEndPoint = tempA.GetX() - 1.0f; + leftEndPoint = tempA.GetX(); rightEndPoint = tempB.GetX() + 1.0f; } else { - leftEndPoint = tempB.GetX() - 1.0f; + leftEndPoint = tempB.GetX(); rightEndPoint = tempA.GetX() + 1.0f; } + //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 + // a value higher then 255 to be used. 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); @@ -647,7 +662,7 @@ void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex int xLength = (int)ceil(rightEndPoint) - (int)ceil(leftEndPoint); int ci = 0; - for (int xi = (int)ceil(leftEndPoint); xi <= (int)ceil(rightEndPoint); xi++) + for (int xi = (int)leftEndPoint; xi <= (int)rightEndPoint; xi++) { float ti = (float)ci / (float)xLength; float redTmp = Lerp(iRedA, iRedB, ti); @@ -690,22 +705,22 @@ void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex { if (changed2) { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); + tempB.SetX((float)tempB.GetX() + (float)signx2); } else { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); + tempB.SetY((float)tempB.GetY() + (float)signy2); } e2 = e2 - 2 * dx2; } if (changed2) { - tempB.SetY((float)tempB.GetYInt() + (float)signy2); + tempB.SetY((float)tempB.GetY() + (float)signy2); } else { - tempB.SetX((float)tempB.GetXInt() + (float)signx2); + tempB.SetX((float)tempB.GetX() + (float)signx2); } e2 = e2 + 2 * dy2; } @@ -727,10 +742,18 @@ void Rasteriser::FillPolygonTextured(HDC hDc, Model& model, vector& vert { 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 tempU = model.GetUVCoord(verts[0].GetUVIndex()).GetU() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (model.GetUVCoord(verts[2].GetUVIndex()).GetU() - model.GetUVCoord(verts[0].GetUVIndex()).GetU()); - float tempV = model.GetUVCoord(verts[0].GetUVIndex()).GetV() + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (model.GetUVCoord(verts[2].GetUVIndex()).GetV() - model.GetUVCoord(verts[0].GetUVIndex()).GetV()); + 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()); @@ -738,19 +761,20 @@ void Rasteriser::FillPolygonTextured(HDC hDc, Model& model, vector& vert 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()) + if (drawn < toDraw + 100) { - temp.SetUVIndex(verts[2].GetUVIndex()); - FillTexturedSideTriangle(hDc, model, verts[0], verts[1], temp, model.GetUVCoord(verts[0].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex()), tempCoords); - temp.SetUVIndex(verts[0].GetUVIndex()); - FillTexturedSideTriangle(hDc, model, verts[2], verts[1], temp, model.GetUVCoord(verts[2].GetUVIndex()), model.GetUVCoord(verts[1].GetUVIndex()), tempCoords); - } - else - { - temp.SetUVIndex(verts[2].GetUVIndex()); - FillTexturedSideTriangle(hDc, model, verts[0], temp, verts[1], model.GetUVCoord(verts[0].GetUVIndex()), tempCoords, model.GetUVCoord(verts[1].GetUVIndex())); - temp.SetUVIndex(verts[0].GetUVIndex()); - FillTexturedSideTriangle(hDc, model, verts[2], temp, verts[1], model.GetUVCoord(verts[2].GetUVIndex()), tempCoords, model.GetUVCoord(verts[1].GetUVIndex())); + 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++; + } } } } @@ -798,10 +822,6 @@ void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v dx1 = dy1; dy1 = tempDx; - int tempDu = du1; - du1 = dv1; - dv1 = tempDu; - changed1 = true; } @@ -811,10 +831,6 @@ void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v dx2 = dy2; dy2 = tempDx; - int tempDu = du2; - du2 = dv2; - dv2 = tempDu; - changed2 = true; } @@ -825,27 +841,42 @@ void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v { float leftEndPoint; float rightEndPoint; - float leftUV; - float rightUV; + float leftU; + float rightU; + float leftV; + float rightV; if (tempA.GetX() < tempB.GetX()) { leftEndPoint = tempA.GetX() - 1.0f; rightEndPoint = tempB.GetX() + 1.0f; - leftUV = tempUVA.GetU(); - rightUV = tempUVB.GetU(); + leftU = tempUVA.GetU(); + rightU = tempUVB.GetU(); + leftV = tempUVA.GetV(); + rightV = tempUVB.GetV(); } else { leftEndPoint = tempB.GetX() - 1.0f; rightEndPoint = tempA.GetX() + 1.0f; - leftUV = tempUVB.GetU(); - rightUV = tempUVA.GetU(); + 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); - float UCoordA = Interpolate(uv1.GetV() + i, uv1.GetU(), uv2.GetU(), uv1.GetV(), uv2.GetV()); - float UCoordB = Interpolate(uv1.GetV() + i, uv1.GetU(), uv3.GetU(), uv1.GetV(), uv3.GetV()); + //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); @@ -857,19 +888,23 @@ void Rasteriser::FillTexturedSideTriangle(HDC hDc, Model& model, const Vertex& v int xLength = (int)ceil(rightEndPoint) - (int)ceil(leftEndPoint); int ci = 0; - for (int xi = (int)ceil(leftEndPoint); xi <= (int)ceil(rightEndPoint); xi++) - { - float ti = (float)ci / (float)xLength; - float UCoordTmp = Lerp(leftUV, rightUV, ti); - float redTmp = Lerp(iRedA, iRedB, ti) / 100; - float greenTmp = Lerp(iGreenA, iGreenB, ti) / 100; - float blueTmp = Lerp(iBlueA, iBlueB, ti) / 100; + 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)tempUVA.GetV()); - COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)(GetRValue(textureColor) * redTmp)), BoundsCheck(0, 255, (int)(GetGValue(textureColor) * greenTmp)), BoundsCheck(0, 255, (int)(GetBValue(textureColor) * blueTmp))); + 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++; + SetPixel(hDc, xi, tempA.GetYInt(), currentColor); + ci++; + } } diff --git a/Vertex.cpp b/Vertex.cpp index 2c6fd37..23fc46a 100644 --- a/Vertex.cpp +++ b/Vertex.cpp @@ -11,6 +11,11 @@ Vertex::Vertex() _r = 0; _g = 0; _b = 0; + _uvIndex = -1; + _zOriginal = 0; + _uOverZ = 0; + _vOverZ = 0; + _zRecip = 0; } Vertex::Vertex(const float x, const float y, const float z) @@ -24,6 +29,11 @@ Vertex::Vertex(const float x, const float y, const float z) _r = 0; _g = 0; _b = 0; + _uvIndex = -1; + _zOriginal = 0; + _uOverZ = 0; + _vOverZ = 0; + _zRecip = 0; } Vertex::Vertex(const float x, const float y, const float z, const float w) @@ -37,6 +47,11 @@ Vertex::Vertex(const float x, const float y, const float z, const float w) _r = 0; _g = 0; _b = 0; + _uvIndex = -1; + _zOriginal = 0; + _uOverZ = 0; + _vOverZ = 0; + _zRecip = 0; } Vertex::Vertex(const Vertex & other) @@ -187,6 +202,44 @@ void Vertex::SetUVIndex(const int index) _uvIndex = index; } +float Vertex::GetZOriginal() const +{ + return _zOriginal; +} + +float Vertex::GetUOverZ() const +{ + return _uOverZ; +} + +void Vertex::SetUOverZ(const float value) +{ + _uOverZ = value / _zOriginal; +} + +float Vertex::GetVOverZ() const +{ + return _vOverZ; +} + +void Vertex::SetVOverZ(const float value) +{ + _vOverZ = value / _zOriginal; +} + +float Vertex::GetZRecip() const +{ + return _zRecip; +} + +void Vertex::UVCorrect(float u, float v) +{ + _zOriginal = _w; + _zRecip = 1 / _zOriginal; + SetUOverZ(u); + SetVOverZ(v); +} + int Vertex::GetXInt(bool forceRoundUp) const { if (forceRoundUp) @@ -236,7 +289,7 @@ int Vertex::GetWInt(bool forceRoundUp) const } void Vertex::Dehomogenize() -{ +{ _x = _x / _w; _y = _y / _w; _z = _z / _w; @@ -293,4 +346,9 @@ void Vertex::Copy(const Vertex& other) _b = other.GetB(); _uvIndex = other.GetUVIndex(); + + _zOriginal = other.GetZOriginal(); + _uOverZ = other.GetUOverZ(); + _vOverZ = other.GetVOverZ(); + _zRecip = other.GetZRecip(); } diff --git a/Vertex.h b/Vertex.h index 026ba5e..1ca154a 100644 --- a/Vertex.h +++ b/Vertex.h @@ -44,6 +44,14 @@ public: int GetUVIndex() const; void SetUVIndex(const int index); + float GetZOriginal() const; + float GetUOverZ() const; + void SetUOverZ(const float value); + float GetVOverZ() const; + void SetVOverZ(const float value); + float GetZRecip() const; + void UVCorrect(float u, float v); + // 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 // use the floor function instead to round the number down @@ -79,6 +87,10 @@ private: int _uvIndex; + float _uOverZ; + float _vOverZ; + float _zRecip; + void Copy(const Vertex& other); }; diff --git a/model_data/uvcheck.pcx b/model_data/uvcheck.pcx new file mode 100644 index 0000000..77ec8ac Binary files /dev/null and b/model_data/uvcheck.pcx differ