diff --git a/AmbientLight.cpp b/AmbientLight.cpp index c1dda3d..18474ba 100644 --- a/AmbientLight.cpp +++ b/AmbientLight.cpp @@ -5,7 +5,7 @@ AmbientLight::AmbientLight(const AmbientLight& other) : Light(other) Copy(other); } -COLORREF AmbientLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +COLORREF AmbientLight::CalculateLightShared(const Model& currentModel, COLORREF colorIn) { float workingRed = (float)GetRedLightIntensity(); float workingGreen = (float)GetGreenLightIntensity(); @@ -27,6 +27,16 @@ COLORREF AmbientLight::CalculateLight(const Model& currentModel, const Polygon3D return outputColor; } +COLORREF AmbientLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, colorIn); +} + +COLORREF AmbientLight::CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, colorIn); +} + AmbientLight& AmbientLight::operator= (const AmbientLight& rhs) { if (this != &rhs) diff --git a/AmbientLight.h b/AmbientLight.h index 91b45df..3dd8a41 100644 --- a/AmbientLight.h +++ b/AmbientLight.h @@ -9,7 +9,10 @@ public: AmbientLight(int red, int green, int blue) : Light(red, green, blue) {}; AmbientLight(const AmbientLight& other); + COLORREF CalculateLightShared(const Model& currentModel, COLORREF colorIn); + COLORREF CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn); + COLORREF CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn); AmbientLight& operator= (const AmbientLight& rhs); diff --git a/Camera.cpp b/Camera.cpp index dd5ccdf..20520de 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -1,19 +1,11 @@ #include "Camera.h" -Camera::Camera() -{ -} - Camera::Camera(float xRot, float yRot, float zRot, const Vertex& pos) { - _initialRotation[0] = xRot; - _currentRotation[0] = xRot; - _initialRotation[1] = yRot; - _currentRotation[1] = yRot; - _initialRotation[2] = zRot; - _currentRotation[2] = zRot; - _initialPosition = pos; - _currentPosition = pos; + _xRot = xRot; + _yRot = yRot; + _zRot = zRot; + _cameraPosition = pos; } Camera::Camera(const Camera& other) @@ -27,61 +19,56 @@ Camera::~Camera() Matrix Camera::UpdateCameraPosition(const Vertex& newPos) { - _currentPosition = newPos; + _cameraPosition = newPos; return GetCurrentCameraTransformMatrix(); } Matrix Camera::RotateCamera(float xRot, float yRot, float zRot) { - _currentRotation[0] = xRot; - _currentRotation[1] = yRot; - _currentRotation[2] = zRot; + _xRot = xRot; + _yRot = yRot; + _zRot = zRot; return GetCurrentCameraTransformMatrix(); } Matrix Camera::GetCurrentCameraTransformMatrix() { - return GetCameraRotationMatrix(Axis::X, _currentRotation[0]) * GetCameraRotationMatrix(Axis::Y, _currentRotation[1]) * GetCameraRotationMatrix(Axis::Z, _currentRotation[2]) * GetCameraTranslateMatrix(_currentPosition); + return GetCameraRotationMatrix(Axis::X, _xRot) * GetCameraRotationMatrix(Axis::Y, _yRot) * GetCameraRotationMatrix(Axis::Z, _zRot) * GetCameraTranslateMatrix(_cameraPosition); } -float Camera::GetCurrentRotationValue(const Axis axis) +void Camera::SetXRot(const float value) { - switch (axis) - { - case (Axis::X): - return _currentRotation[0]; - case (Axis::Y): - return _currentRotation[1]; - case (Axis::Z): - return _currentRotation[2]; - default: - throw "No valid axis?"; - } + _xRot = value; } -float Camera::GetInitialRotationValue(const Axis axis) +float Camera::GetXRot() const { - switch (axis) - { - case (Axis::X): - return _initialRotation[0]; - case (Axis::Y): - return _initialRotation[1]; - case (Axis::Z): - return _initialRotation[2]; - default: - throw "No valid axis?"; - } + return _xRot; } -Vertex Camera::GetCurrentPosition() +void Camera::SetYRot(const float value) { - return _currentPosition; + _yRot = value; } -Vertex Camera::GetInitialPosition() +float Camera::GetYRot() const { - return _initialPosition; + return _yRot; +} + +void Camera::SetZRot(const float value) +{ + _zRot = value; +} + +float Camera::GetZRot() const +{ + return _zRot; +} + +Vertex Camera::GetCameraPosition() const +{ + return _cameraPosition; } Camera& Camera::operator=(const Camera& rhs) @@ -95,12 +82,9 @@ Camera& Camera::operator=(const Camera& rhs) void Camera::Copy(const Camera& other) { - _initialRotation[0] = other._initialRotation[0]; - _currentRotation[0] = other._currentRotation[0]; - _initialRotation[1] = other._initialRotation[1]; - _currentRotation[1] = other._currentRotation[1]; - _initialRotation[2] = other._initialRotation[2]; - _currentRotation[2] = other._currentRotation[2]; - _initialPosition = other._initialPosition; - _currentPosition = other._currentPosition; + _xRot = other.GetXRot(); + _yRot = other.GetYRot(); + _zRot = other.GetZRot(); + + _cameraPosition = other.GetCameraPosition(); } \ No newline at end of file diff --git a/Camera.h b/Camera.h index a19322d..ad4c8cb 100644 --- a/Camera.h +++ b/Camera.h @@ -8,7 +8,7 @@ using namespace SharedTools; class Camera { public: - Camera(); + Camera() : _xRot(0), _yRot(0), _zRot(0) {}; Camera(float xRot, float yRot, float zRot, const Vertex& pos); Camera(const Camera& other); @@ -17,23 +17,23 @@ public: Matrix UpdateCameraPosition(const Vertex& newPos); Matrix RotateCamera(float xRot, float yRot, float zRot); - Matrix GetCurrentCameraTransformMatrix(); + void SetXRot(const float value); + float GetXRot() const; + void SetYRot(const float value); + float GetYRot() const; + void SetZRot(const float value); + float GetZRot() const; - float GetCurrentRotationValue(const Axis axis); - float GetInitialRotationValue(const Axis axis); - Vertex GetCurrentPosition(); - Vertex GetInitialPosition(); + Matrix GetCurrentCameraTransformMatrix(); + Vertex GetCameraPosition() const; Camera& operator= (const Camera& rhs); private: - float _initialRotation[3] = { 0 }; - Vertex _initialPosition; - - float _currentRotation[3] = { 0 }; - Vertex _currentPosition; - - Matrix _currentCameraTransform; + float _xRot; + float _yRot; + float _zRot; + Vertex _cameraPosition; void Copy(const Camera& other); }; diff --git a/DirectionalLight.cpp b/DirectionalLight.cpp index a7ad8d0..816eaef 100644 --- a/DirectionalLight.cpp +++ b/DirectionalLight.cpp @@ -34,17 +34,17 @@ Vector3D DirectionalLight::GetLightDirection() const return _lightDirection; } -COLORREF DirectionalLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +COLORREF DirectionalLight::CalculateLightShared(const Model& currentModel, const Vector3D& currentNormal, COLORREF colorIn) { - float workingRed = (float) GetRedLightIntensity(); - float workingGreen = (float) GetGreenLightIntensity(); - float workingBlue = (float) GetBlueLightIntensity(); + float workingRed = (float)GetRedLightIntensity(); + float workingGreen = (float)GetGreenLightIntensity(); + float workingBlue = (float)GetBlueLightIntensity(); workingRed *= currentModel.GetRedReflectionCoefficient(); workingGreen *= currentModel.GetGreenReflectionCoefficient(); workingBlue *= currentModel.GetBlueReflectionCoefficient(); - - float lightDotProd = Vector3D::DotProduct(_normalizedLightDirection, currentPolygon.GetNormal()); + + float lightDotProd = Vector3D::DotProduct(_normalizedLightDirection, currentNormal); workingRed *= lightDotProd; workingGreen *= lightDotProd; @@ -62,6 +62,16 @@ COLORREF DirectionalLight::CalculateLight(const Model& currentModel, const Polyg return outputColor; } +COLORREF DirectionalLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, currentPolygon.GetNormal(), colorIn); +} + +COLORREF DirectionalLight::CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, currentVertex.GetNormal(), colorIn); +} + DirectionalLight& DirectionalLight::operator= (const DirectionalLight& rhs) { if (this != &rhs) diff --git a/DirectionalLight.h b/DirectionalLight.h index dec5def..6c000f2 100644 --- a/DirectionalLight.h +++ b/DirectionalLight.h @@ -13,7 +13,10 @@ public: void SetLightDirection(Vector3D direction); Vector3D GetLightDirection() const; + COLORREF CalculateLightShared(const Model& currentModel, const Vector3D& currentNormal, COLORREF colorIn); + COLORREF CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn); + COLORREF CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn); DirectionalLight& operator= (const DirectionalLight& rhs); diff --git a/Light.h b/Light.h index 05e1b51..07b39e8 100644 --- a/Light.h +++ b/Light.h @@ -27,6 +27,7 @@ public: int GetBlueLightIntensity() const; virtual COLORREF CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) = 0; + virtual COLORREF CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn) = 0; Light& operator= (const Light& rhs); diff --git a/Model.cpp b/Model.cpp index 65d1e23..fdb026c 100644 --- a/Model.cpp +++ b/Model.cpp @@ -16,7 +16,7 @@ vector& Model::GetPolygons() return _polygons; } -const vector& Model::GetVertices() +vector& Model::GetVertices() { return _vertices; } @@ -77,6 +77,27 @@ const Vertex& Model::GetVertex(int index) const return _transformedVertices[index]; } +vector Model::GetPolygonVertexArray(int index) const +{ + vector polygonVerticies = {}; + + for (int i = 0; i < GetPolygon(index).GetPolygonVertexCount(); i++) + { + polygonVerticies.push_back(GetVertex(index, i)); + } + return polygonVerticies; +} + +void Model::SetPolygonColor(int index, COLORREF color) +{ + _polygons[index].SetColor(color); +} + +void Model::SetVertexColor(int polyIndex, int vertIndex, COLORREF color) +{ + _transformedVertices[GetPolygon(polyIndex).GetIndex(vertIndex)].SetColor(color); +} + void Model::SetReflectionCoefficient(float red, float green, float blue) { _kdRed = BoundsCheck(0.0f, 1.0f, red); @@ -171,7 +192,7 @@ void Model::ApplyTransformToTransformedVertices(const Matrix& transform) void Model::DehomogenizeAllVertices() { - for (Vertex ¤tVertex : _transformedVertices) + for (Vertex& currentVertex : _transformedVertices) { currentVertex.Dehomogenize(); } @@ -179,12 +200,14 @@ void Model::DehomogenizeAllVertices() void Model::CalculateBackfaces(Camera& currentCamera) { - for (Polygon3D ¤tPolygon : _polygons) + for (Polygon3D& currentPolygon : _polygons) { Vector3D vectorA = _transformedVertices[currentPolygon.GetIndex(1)] - _transformedVertices[currentPolygon.GetIndex(0)]; Vector3D vectorB = _transformedVertices[currentPolygon.GetIndex(2)] - _transformedVertices[currentPolygon.GetIndex(0)]; - currentPolygon.SetNormal(Vector3D::CrossProduct(vectorA, vectorB)); - Vector3D eyeVector = _transformedVertices[currentPolygon.GetIndex(0)] - currentCamera.GetCurrentPosition(); + currentPolygon.SetNormal(Vector3D::CrossProduct(vectorA, vectorB)); + currentPolygon.NormalizeNormal(); + Vector3D eyeVector = _transformedVertices[currentPolygon.GetIndex(0)] - currentCamera.GetCameraPosition(); + eyeVector.Normalize(); float dotProduct = Vector3D::DotProduct(currentPolygon.GetNormal(), eyeVector); if (dotProduct < 0) @@ -198,6 +221,31 @@ void Model::CalculateBackfaces(Camera& currentCamera) } } +void Model::CalculateVertexNormals() +{ + for (Vertex& currentVertex : _transformedVertices) + { + currentVertex.ResetNormal(true); + } + + for (int pi = 0; pi < GetPolygonCount(); pi++) + { + for (int i = 0; i < _polygons[pi].GetPolygonVertexCount(); i++) + { + _transformedVertices[_polygons[pi].GetIndex(i)].SetNormal(_transformedVertices[_polygons[pi].GetIndex(i)].GetNormal() + _polygons[pi].GetNormal()); + _transformedVertices[_polygons[pi].GetIndex(i)].IncrementContributeCount(); + } + } + + for (Vertex& currentVertex : _transformedVertices) + { + + currentVertex.SetNormal(currentVertex.GetNormal() / currentVertex.GetContributeCount()); + currentVertex.NormalizeNormal(); + + } +} + bool DepthCompare(Polygon3D& a, Polygon3D& b) { return a.GetDepth() > b.GetDepth(); @@ -205,7 +253,7 @@ bool DepthCompare(Polygon3D& a, Polygon3D& b) void Model::Sort() { - for (Polygon3D ¤tPolygon : _polygons) + for (Polygon3D& currentPolygon : _polygons) { float zTotal = 0.0f; for (int i = 0; i < currentPolygon.GetPolygonVertexCount(); i++) diff --git a/Model.h b/Model.h index a0ccca7..1742d03 100644 --- a/Model.h +++ b/Model.h @@ -16,7 +16,7 @@ public: ~Model(); vector& GetPolygons(void); - const vector& GetVertices(void); + vector& GetVertices(void); const vector& GetPendingTransforms(void); size_t GetPolygonCount(void); @@ -32,6 +32,10 @@ public: const Vertex& GetVertex(int polygonIndex, int vertexPolygonIndex) const; const Vertex& GetVertex(int index) const; + vector GetPolygonVertexArray(int index) const; + void SetPolygonColor(int index, COLORREF color); + void SetVertexColor(int polyIndex, int vertIndex, COLORREF color); + void SetReflectionCoefficient(float red, float green, float blue); void SetReflectionCoefficient(ColRef color, float value); void SetRedReflectionCoefficient(float value); @@ -48,6 +52,7 @@ public: void DehomogenizeAllVertices(void); void CalculateBackfaces(Camera& currentCamera); + void CalculateVertexNormals(); void Sort(void); private: diff --git a/PointLight.cpp b/PointLight.cpp index e479289..4e3ca73 100644 --- a/PointLight.cpp +++ b/PointLight.cpp @@ -75,25 +75,25 @@ Vertex PointLight::GetLightPosition() const return _lightPosition; } -COLORREF PointLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +COLORREF PointLight::CalculateLightShared(const Model& currentModel, const Vertex& currentVertex, const Vector3D& currentNormal, COLORREF colorIn) { float workingRed = (float)GetRedLightIntensity(); float workingGreen = (float)GetGreenLightIntensity(); float workingBlue = (float)GetBlueLightIntensity(); - float fudge = 50; + float fudge = 100; workingRed *= currentModel.GetRedReflectionCoefficient(); workingGreen *= currentModel.GetGreenReflectionCoefficient(); workingBlue *= currentModel.GetBlueReflectionCoefficient(); - Vector3D lightSource = currentModel.GetVertex(currentPolygon.GetIndex(0)) - _lightPosition; + Vector3D lightSource = currentVertex - _lightPosition; Vector3D lightSourceNormalized = lightSource; lightSourceNormalized.Normalize(); - float distance = Vector3D::DotProduct(lightSource, currentPolygon.GetNormal()); + float distance = Vector3D::Length(currentNormal, lightSource); - float lightDotProd = Vector3D::DotProduct(lightSourceNormalized, currentPolygon.GetNormal()); + float lightDotProd = Vector3D::DotProduct(lightSourceNormalized, currentNormal); float attenuation = 1 / (GetAttenuationA() + GetAttenuationB() * distance + GetAttenuationC() * (distance * distance)); workingRed *= lightDotProd; @@ -120,6 +120,16 @@ COLORREF PointLight::CalculateLight(const Model& currentModel, const Polygon3D& return outputColor; } +COLORREF PointLight::CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, currentModel.GetVertex(currentPolygon.GetIndex(0)), currentPolygon.GetNormal(), colorIn); +} + +COLORREF PointLight::CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn) +{ + return CalculateLightShared(currentModel, currentVertex, currentVertex.GetNormal(), colorIn); +} + PointLight& PointLight::operator= (const PointLight& rhs) { if (this != &rhs) diff --git a/PointLight.h b/PointLight.h index 69d1d76..af239d2 100644 --- a/PointLight.h +++ b/PointLight.h @@ -21,8 +21,10 @@ public: float GetAttenuationB(); float GetAttenuationC(); + COLORREF CalculateLightShared(const Model& currentModel, const Vertex& currentVertex, const Vector3D& currentNormal, COLORREF colorIn); COLORREF CalculateLight(const Model& currentModel, const Polygon3D& currentPolygon, COLORREF colorIn); + COLORREF CalculateLight(const Model& currentModel, const Vertex& currentVertex, COLORREF colorIn); PointLight& operator= (const PointLight& rhs); diff --git a/Polygon3D.cpp b/Polygon3D.cpp index 3995aeb..1b37b9f 100644 --- a/Polygon3D.cpp +++ b/Polygon3D.cpp @@ -4,6 +4,7 @@ Polygon3D::Polygon3D() : _indices{ 0 } { _depth = 0.0f; _color = RGB(0, 0, 0); + _culled = false; } Polygon3D::Polygon3D(int index0, int index1, int index2) @@ -13,6 +14,7 @@ Polygon3D::Polygon3D(int index0, int index1, int index2) _indices[2] = index2; _depth = 0.0f; _color = RGB(0, 0, 0); + _culled = false; } Polygon3D::Polygon3D(const Polygon3D& other) @@ -39,11 +41,16 @@ void Polygon3D::SetNormal(const Vector3D& normal) _normal = normal; } -Vector3D Polygon3D::GetNormal() const +const Vector3D& Polygon3D::GetNormal() const { return _normal; } +void Polygon3D::NormalizeNormal() +{ + _normal.Normalize(); +} + void Polygon3D::SetColor(int red, int green, int blue) { int redChecked = BoundsCheck(0, 255, red); @@ -96,10 +103,10 @@ void Polygon3D::Copy(const Polygon3D& other) { for (int i = 0; i < sizeof(_indices)/sizeof(_indices[0]); i++) { - _indices[i] = other.GetIndex(i); - _normal = other.GetNormal(); - _culled = other.GetCulled(); - _depth = other.GetDepth(); - _color = other.GetColor(); + _indices[i] = other.GetIndex(i); } + _normal = other.GetNormal(); + _culled = other.GetCulled(); + _depth = other.GetDepth(); + _color = other.GetColor(); } \ No newline at end of file diff --git a/Polygon3D.h b/Polygon3D.h index 8de3a5a..5307a87 100644 --- a/Polygon3D.h +++ b/Polygon3D.h @@ -19,7 +19,8 @@ public: int GetIndex(int index) const; void SetNormal(const Vector3D& normal); - Vector3D GetNormal() const; + const Vector3D& GetNormal() const; + void NormalizeNormal(); void SetColor(int red, int green, int blue); void SetColor(const COLORREF color); @@ -35,8 +36,8 @@ public: private: int _indices[3]; Vector3D _normal; - float _depth = 0.0f; - bool _culled = false; + float _depth; + bool _culled; COLORREF _color; void Copy(const Polygon3D& other); diff --git a/Rasteriser.cpp b/Rasteriser.cpp index ba9e4cd..39ba2d8 100644 --- a/Rasteriser.cpp +++ b/Rasteriser.cpp @@ -5,8 +5,6 @@ Rasteriser app; bool Rasteriser::Initialise() { Model modelA; - Model modelB; - Model modelC; if (MD2Loader::LoadModel(".\\marvin.MD2", modelA, &Model::AddPolygon, &Model::AddVertex)) { _sceneModels.push_back(modelA); @@ -15,29 +13,15 @@ bool Rasteriser::Initialise() { return false; } + - if (MD2Loader::LoadModel(".\\megaman.MD2", modelB, &Model::AddPolygon, &Model::AddVertex)) - { - _sceneModels.push_back(modelB); - } - else - { - return false; - } + _lights.push_back(new AmbientLight(150, 150, 150)); + //_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(-10, 0, 10), 0, 1, 0, 100, 0, 0)); + _cameras.push_back(Camera(0.0f, 0.0f, 0.0f, Vertex(0.0f, 0.0f, -50.0f))); - if (MD2Loader::LoadModel(".\\w_railgun.MD2", modelC, &Model::AddPolygon, &Model::AddVertex)) - { - _sceneModels.push_back(modelC); - } - else - { - return false; - } - - _lights.push_back(new AmbientLight(50, 50, 50)); - _lights.push_back(new DirectionalLight(Vector3D(1, 0, 1), 50, 0, 0)); - _lights.push_back(new PointLight(Vertex(0, 10, 0), 0, 1, 0, 100, 0, 0)); - _cameras.push_back(Camera(0.0f, 0.0f, 0.0f, Vertex(0.0f, 0.0f, -100.0f))); + _screenMinimized = false; return true; } @@ -60,79 +44,124 @@ Camera& Rasteriser::GetCurrentCamera() return GetCamera(_currentCamera); } +void Rasteriser::CalculateLighting(Model& currentModel, bool fullLightRender) +{ + { + for (int pi = 0; pi < currentModel.GetPolygonCount(); pi++) + { + if (!currentModel.GetPolygon(pi).GetCulled()) + { + if (fullLightRender) + { + for (int i = 0; i < currentModel.GetPolygon(pi).GetPolygonVertexCount(); i++) + { + COLORREF colorWorking = RGB(0, 0, 0); + for (Light* currentLight : _lights) + { + colorWorking = currentLight->CalculateLight(currentModel, currentModel.GetVertex(pi, i), colorWorking); + } + currentModel.SetVertexColor(pi, i, colorWorking); + } + } + else + { + COLORREF colorWorking = RGB(0, 0, 0); + for (Light* currentLight : _lights) + { + colorWorking = currentLight->CalculateLight(currentModel, currentModel.GetPolygon(pi), colorWorking); + } + currentModel.SetPolygonColor(pi, colorWorking); + } + } + } + } +} + void Rasteriser::Update(const Bitmap& bitmap) { - int currentRot = (_rotation % 360); - Vertex startPos = Vertex(-50, 0, 0); - int currentZOff = 0; - int currentModelIndex = 0; + if (bitmap.GetWidth() == 0 || bitmap.GetHeight() == 0) + { + _screenMinimized = true; + } + else + { + _screenMinimized = false; + } - for (Model ¤tModel : _sceneModels) - { - currentModel.EnqueueTransform(GetTranslateMatrix(startPos)); - currentModel.EnqueueTransform(GetRotationMatrix(Axis::Y, (float) currentRot)); - startPos.SetX(startPos.GetX() + 50); - if ((currentModelIndex % 2) == 1) + if (!_screenMinimized) + { + int currentRot = (_rotation % 360); + Vertex startPos = Vertex(0, 0, 20); + int currentZOff = 0; + int currentModelIndex = 0; + + for (Model& currentModel : _sceneModels) { - currentZOff = 0; + currentModel.EnqueueTransform(GetTranslateMatrix(startPos)); + currentModel.EnqueueTransform(GetRotationMatrix(Axis::Y, (float)currentRot)); + //startPos.SetX(startPos.GetX() + 100); + if ((currentModelIndex % 2) == 1) + { + currentZOff = 0; + } + else + { + currentZOff = 100; + } + //startPos.SetZ((float)currentZOff); + currentModelIndex++; + } + + _currentAspectRatio = (float)(bitmap.GetWidth() / (float)bitmap.GetHeight()); + _currentPerspectiveMatrix = GetPerspectiveProjectionMatrix(1, _currentAspectRatio); + _currentViewMatrix = GetViewMatrix(1, bitmap.GetWidth(), bitmap.GetHeight()); + + if (_rotation == 360) + { + _rotation = 0; } else { - currentZOff = 100; - } - startPos.SetZ((float)currentZOff); - currentModelIndex++; + _rotation += 1; + } } - - _currentAspectRatio = (float)(bitmap.GetWidth() / bitmap.GetHeight()); - _currentPerspectiveMatrix = GetPerspectiveProjectionMatrix(1, _currentAspectRatio); - _currentViewMatrix = GetViewMatrix(1, bitmap.GetWidth(), bitmap.GetHeight()); - - if (_rotation == 360) - { - _rotation = 0; - } - else - { - _rotation += 1; - } } void Rasteriser::Render(const Bitmap& bitmap) { - ClearViewport(bitmap); - SelectObject(bitmap.GetDC(), GetStockObject(DC_BRUSH)); - SelectObject(bitmap.GetDC(), GetStockObject(DC_PEN)); - - for (Model ¤tModel : _sceneModels) + if (!_screenMinimized) { - currentModel.SetReflectionCoefficient(0.5f, 0.5f, 0.5f); - Matrix workingMatrix = workingMatrix.IdentityMatrix(); - for (Matrix currentTransform : currentModel.GetPendingTransforms()) + ClearViewport(bitmap); + SelectObject(bitmap.GetDC(), GetStockObject(DC_BRUSH)); + SelectObject(bitmap.GetDC(), GetStockObject(DC_PEN)); + + for (Model& currentModel : _sceneModels) { - workingMatrix *= currentTransform; - } - currentModel.ApplyTransformToLocalVertices(workingMatrix); - currentModel.CalculateBackfaces(GetCurrentCamera()); - for (Polygon3D ¤tPolygon : currentModel.GetPolygons()) - { - if (!currentPolygon.GetCulled()) + currentModel.SetReflectionCoefficient(0.5f, 0.5f, 0.5f); + Matrix workingMatrix = workingMatrix.IdentityMatrix(); + for (Matrix currentTransform : currentModel.GetPendingTransforms()) { - COLORREF colorWorking = RGB(0, 0, 0); - for (Light* currentLight : _lights) - { - colorWorking = currentLight->CalculateLight(currentModel, currentPolygon, colorWorking); - } - currentPolygon.SetColor(colorWorking); + workingMatrix *= currentTransform; } + currentModel.ApplyTransformToLocalVertices(workingMatrix); + currentModel.ApplyTransformToTransformedVertices(GetCurrentCamera().GetCurrentCameraTransformMatrix()); + + currentModel.CalculateBackfaces(GetCurrentCamera()); + currentModel.Sort(); + + currentModel.CalculateVertexNormals(); + CalculateLighting(currentModel, true); + + currentModel.ApplyTransformToTransformedVertices(_currentPerspectiveMatrix); + currentModel.DehomogenizeAllVertices(); + currentModel.ApplyTransformToTransformedVertices(_currentViewMatrix); + + //DrawWireFrame(bitmap.GetDC(), currentModel); + //DrawSolidFlat(bitmap.GetDC(), currentModel); + //DrawRasterisedSolidFlat(bitmap.GetDC(), currentModel); + DrawGouraud(bitmap.GetDC(), currentModel); + currentModel.ClearPendingTransforms(); } - currentModel.ApplyTransformToTransformedVertices(GetCurrentCamera().GetCurrentCameraTransformMatrix()); - currentModel.Sort(); - currentModel.ApplyTransformToTransformedVertices(_currentPerspectiveMatrix); - currentModel.DehomogenizeAllVertices(); - currentModel.ApplyTransformToTransformedVertices(_currentViewMatrix); - DrawSolidFlat(bitmap.GetDC(), currentModel); - currentModel.ClearPendingTransforms(); } } @@ -221,4 +250,442 @@ void Rasteriser::DrawSolidFlat(HDC hDc, Model& model) Polygon(hDc, pointArray.data(), currentPolygonVertexCount); } } -} \ No newline at end of file +} + +void Rasteriser::DrawRasterisedSolidFlat(HDC hDc, Model& model) +{ + int modelPolygonCount = (int)model.GetPolygonCount(); + for (int i = 0; i < modelPolygonCount; i++) + { + + if (!model.GetPolygon(i).GetCulled()) + { + vector vertexArray = model.GetPolygonVertexArray(i); + FillPolygonFlat(hDc, vertexArray, model.GetPolygon(i).GetColor()); + } + } +} + +void Rasteriser::DrawGouraud(HDC hDc, Model& model) +{ + int modelPolygonCount = (int)model.GetPolygonCount(); + for (int i = 0; i < modelPolygonCount; i++) + { + + if (!model.GetPolygon(i).GetCulled()) + { + vector vertexArray = model.GetPolygonVertexArray(i); + FillPolygonGouraud(hDc, vertexArray); + } + } +} + +bool VerticiesYCompareAsc(Vertex& v1, Vertex& v2) +{ + return v1.GetY() < v2.GetY(); +} + +void Rasteriser::FillPolygonFlat(HDC hDc, vector& verts, COLORREF colorIn) +{ + sort(verts.begin(), verts.end(), VerticiesYCompareAsc); + if (verts[1].GetY() == verts[2].GetY()) + { + FillFlatSideTriangle(hDc, verts[0], verts[1], verts[2], colorIn); + } + else if (verts[0].GetY() == verts[1].GetY()) + { + FillFlatSideTriangle(hDc, verts[2], verts[0], verts[1], colorIn); + } + 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()); + if (verts[1].GetX() < temp.GetX()) + { + FillFlatSideTriangle(hDc, verts[0], verts[1], temp, colorIn); + FillFlatSideTriangle(hDc, verts[2], verts[1], temp, colorIn); + } + else + { + FillFlatSideTriangle(hDc, verts[0], temp, verts[1], colorIn); + FillFlatSideTriangle(hDc, verts[2], temp, verts[1], colorIn); + } + } +} + +void Rasteriser::FillFlatSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3, COLORREF colorIn) +{ + 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 dx2 = (int)ceil(abs(v3.GetX() - v1.GetX())); + int dy2 = (int)ceil(abs(v3.GetY() - v1.GetY())); + + int signx1 = (int)sgn(v2.GetX() - v1.GetX()); + int signx2 = (int)sgn(v3.GetX() - v1.GetX()); + + int signy1 = (int)sgn(v2.GetY() - v1.GetY()); + int signy2 = (int)sgn(v3.GetY() - v1.GetY()); + + if (dy1 > dx1) + { + int tempInt = dx1; + dx1 = dy1; + dy1 = tempInt; + changed1 = true; + } + + if (dy2 > dx2) + { + int tempInt = dx2; + dx2 = dy2; + dy2 = tempInt; + changed2 = true; + } + + int e1 = 2 * dy1 - dx1; + int e2 = 2 * dy2 - dx2; + + for (int i = 0; i <= dx1; i++) + { + int startPoint; + int endPoint; + + if (tempA.GetXInt() < tempB.GetXInt()) + { + startPoint = tempA.GetXInt(); + endPoint = tempB.GetXInt(); + } + else + { + startPoint = tempB.GetXInt(); + endPoint = tempA.GetXInt(); + } + + for (int xi = (int)ceil(startPoint); xi <= endPoint; xi++) + { + SetPixel(hDc, xi, tempA.GetYInt(), colorIn); + } + + + while (e1 >= 0) + { + if (changed1) + { + tempA.SetX(tempA.GetX() + signx1); + } + else + { + tempA.SetY(tempA.GetY() + signy1); + } + e1 = e1 - 2 * dx1; + } + + if (changed1) + { + tempA.SetY(tempA.GetY() + signy1); + } + else + { + tempA.SetX(tempA.GetX() + signx1); + } + + e1 = e1 + 2 * dy1; + + while (tempB.GetY() != tempA.GetY()) + { + while (e2 >= 0) + { + if (changed2) + { + tempB.SetX(tempB.GetX() + signx2); + } + else + { + tempB.SetY(tempB.GetY() + signy2); + } + e2 = e2 - 2 * dx2; + } + + if (changed2) + { + tempB.SetY(tempB.GetY() + signy2); + } + else + { + tempB.SetX(tempB.GetX() + signx2); + } + e2 = e2 + 2 * dy2; + } + } +} + +void Rasteriser::FillPolygonGouraud(HDC hDc, vector& verts) +{ + sort(verts.begin(), verts.end(), VerticiesYCompareAsc); + if (verts[1].GetY() == verts[2].GetY()) + { + FillGouraudBottomFlatTriangle(hDc, verts[0], verts[1], verts[2]); + } + else if (verts[0].GetY() == verts[1].GetY()) + { + FillGouraudTopFlatTriangle(hDc, verts[0], verts[1], verts[2]); + } + 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()); + + float cRed = GetRValue(verts[0].GetColor()) + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (GetRValue(verts[2].GetColor()) - GetRValue(verts[0].GetColor())); + float cGreen = GetGValue(verts[0].GetColor()) + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (GetGValue(verts[2].GetColor()) - GetGValue(verts[0].GetColor())); + float cBlue = GetBValue(verts[0].GetColor()) + ((verts[1].GetY() - verts[0].GetY()) / (verts[2].GetY() - verts[0].GetY())) * (GetBValue(verts[2].GetColor()) - GetBValue(verts[0].GetColor())); + temp.SetColor(RGB((int)cRed, (int)cGreen, (int)cBlue)); + + temp.SetColor(verts[1].GetColor()); + + FillGouraudBottomFlatTriangle(hDc, verts[0], verts[1], temp); + FillGouraudTopFlatTriangle(hDc, verts[1], temp, verts[2]); + } +} + +void Rasteriser::FillGouraudBottomFlatTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + float slope1 = (float)(v2.GetX() - v1.GetX()) / (float)(v2.GetY() - v1.GetY()); + float slope2 = (float)(v3.GetX() - v1.GetX()) / (float)(v3.GetY() - v1.GetY()); + + float x1 = (float)v1.GetX(); + float x2 = (float)v1.GetX() + 0.5f; + + if (slope2 < slope1) + { + float slopeTmp = slope1; + slope1 = slope2; + slope2 = slopeTmp; + } + + for (int scanlineY = (int)v1.GetY(); scanlineY <= (int)v2.GetY(); scanlineY++) + { + float iRedA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetR() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetR(); + float iRedB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetR() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetR(); + float iGreenA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetG() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetG(); + float iGreenB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetG() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetG(); + float iBlueA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetB() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetB(); + float iBlueB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetB() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetB(); + + for (int xi = (int)ceil(x1); xi < (int)x2; xi++) + { + float redTmp = (x2 - xi) / (x2 - x1) * iRedA + (xi - x1) / (x2 - x1) * iRedB; + float greenTmp = (x2 - xi) / (x2 - x1) * iGreenA + (xi - x1) / (x2 - x1) * iGreenB; + float blueTmp = (x2 - xi) / (x2 - x1) * iBlueA + (xi - x1) / (x2 - x1) * iBlueB; + + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)redTmp), BoundsCheck(0, 255, (int)greenTmp), BoundsCheck(0, 255, (int)blueTmp)); + SetPixel(hDc, xi, scanlineY, currentColor); + } + + x1 += slope1; + x2 += slope2; + } +} + +void Rasteriser::FillGouraudTopFlatTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + float slope1 = (float)(v3.GetX() - v1.GetX()) / (float)(v3.GetY() - v1.GetY()); + float slope2 = (float)(v3.GetX() - v2.GetX()) / (float)(v3.GetY() - v2.GetY()); + + float x1 = (float)v3.GetX(); + float x2 = (float)v3.GetX() + 0.5f; + + if (slope1 < slope2) + { + float slopeTmp = slope1; + slope1 = slope2; + slope2 = slopeTmp; + } + + for (int scanlineY = (int)v3.GetY(); scanlineY > (int)v1.GetY(); scanlineY--) + { + float iRedA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetR() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetR(); + float iRedB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetR() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetR(); + float iGreenA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetG() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetG(); + float iGreenB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetG() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetG(); + float iBlueA = (scanlineY - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetB() + (v1.GetY() - scanlineY) / (v1.GetY() - v2.GetY()) * v2.GetB(); + float iBlueB = (scanlineY - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetB() + (v1.GetY() - scanlineY) / (v1.GetY() - v3.GetY()) * v3.GetB(); + + for (int xi = (int)ceil(x1); xi < (int)x2; xi++) + { + float redTmp = (x2 - xi) / (x2 - x1) * iRedA - (xi - x1) / (x2 - x1) * iRedB; + float greenTmp = (x2 - xi) / (x2 - x1) * iGreenA - (xi - x1) / (x2 - x1) * iGreenB; + float blueTmp = (x2 - xi) / (x2 - x1) * iBlueA - (xi - x1) / (x2 - x1) * iBlueB; + + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)redTmp), BoundsCheck(0, 255, (int)greenTmp), BoundsCheck(0, 255, (int)blueTmp)); + SetPixel(hDc, xi, scanlineY, currentColor); + } + + x1 -= slope1; + x2 -= slope2; + } +} + +void Rasteriser::FillPolygonGouraudInt(HDC hDc, vector& verts) +{ + sort(verts.begin(), verts.end(), VerticiesYCompareAsc); + if (verts[1].GetY() == verts[2].GetY()) + { + FillGouraudSideTriangle(hDc, verts[0], verts[1], verts[2]); + } + else if (verts[0].GetY() == verts[1].GetY()) + { + FillGouraudSideTriangle(hDc, verts[2], verts[0], verts[1]); + } + 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()); + + 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()) + { + FillGouraudSideTriangle(hDc, verts[0], verts[1], temp); + FillGouraudSideTriangle(hDc, verts[2], verts[1], temp); + } + else + { + FillGouraudSideTriangle(hDc, verts[0], temp, verts[1]); + FillGouraudSideTriangle(hDc, verts[2], temp, verts[1]); + } + } +} + +void Rasteriser::FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3) +{ + 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 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())); + + 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; + + if (tempA.GetX() < tempB.GetX()) + { + leftEndPoint = tempA.GetX(); + rightEndPoint = tempB.GetX(); + } + else + { + leftEndPoint = tempB.GetX(); + rightEndPoint = tempA.GetX(); + } + + float iRedA = (tempA.GetY() - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetR() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v2.GetY()) * v2.GetR(); + float iRedB = (tempA.GetY() - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetR() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v3.GetY()) * v3.GetR(); + float iGreenA = (tempA.GetY() - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetG() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v2.GetY()) * v2.GetG(); + float iGreenB = (tempA.GetY() - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetG() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v3.GetY()) * v3.GetG(); + float iBlueA = (tempA.GetY() - v2.GetY()) / (v1.GetY() - v2.GetY()) * v1.GetB() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v2.GetY()) * v2.GetB(); + float iBlueB = (tempA.GetY() - v3.GetY()) / (v1.GetY() - v3.GetY()) * v1.GetB() + (v1.GetY() - tempA.GetY()) / (v1.GetY() - v3.GetY()) * v3.GetB(); + + for (int xi = (int)ceil(leftEndPoint); xi <= (int)rightEndPoint; xi++) + { + float redTmp = (rightEndPoint - xi) / (rightEndPoint - leftEndPoint) * iRedA + (xi - leftEndPoint) / (rightEndPoint - leftEndPoint) * iRedB; + float greenTmp = (rightEndPoint - xi) / (rightEndPoint - leftEndPoint) * iGreenA + (xi - leftEndPoint) / (rightEndPoint - leftEndPoint) * iGreenB; + float blueTmp = (rightEndPoint - xi) / (rightEndPoint - leftEndPoint) * iBlueA + (xi - leftEndPoint) / (rightEndPoint - leftEndPoint) * iBlueB; + + COLORREF currentColor = RGB(BoundsCheck(0, 255, (int)redTmp), BoundsCheck(0, 255, (int)greenTmp), BoundsCheck(0, 255, (int)blueTmp)); + SetPixel(hDc, xi, tempA.GetYInt(), currentColor); + } + + + while (e1 >= 0) + { + if (changed1) + { + tempA.SetX((float)tempA.GetXInt() + (float)signx1); + } + else + { + tempA.SetY((float)tempA.GetYInt() + (float)signy1); + } + e1 = e1 - 2 * dx1; + } + + if (changed1) + { + tempA.SetY((float)tempA.GetYInt() + (float)signy1); + } + else + { + tempA.SetX((float)tempA.GetXInt() + (float)signx1); + } + + e1 = e1 + 2 * dy1; + + while (tempB.GetY() < tempA.GetY() && tempB.GetY() > tempA.GetY()) + { + while (e2 >= 0) + { + if (changed2) + { + tempB.SetX((float)tempB.GetXInt() + (float)signx2); + } + else + { + tempB.SetY((float)tempB.GetYInt() + (float)signy2); + } + e2 = e2 - 2 * dx2; + } + + if (changed2) + { + tempB.SetY((float)tempB.GetYInt() + (float)signy2); + } + else + { + tempB.SetX((float)tempB.GetXInt() + (float)signx2); + } + e2 = e2 + 2 * dy2; + } + } +} diff --git a/Rasteriser.h b/Rasteriser.h index f7ae6a7..7ea264b 100644 --- a/Rasteriser.h +++ b/Rasteriser.h @@ -28,11 +28,25 @@ public: Camera& GetCamera(int index); Camera& GetCurrentCamera(); + void CalculateLighting(Model& currentModel, bool fullLightRender); + void DrawSquare(HDC hDc, const vector verticies); void DrawShape(HDC hDc, const vector verticies); void DrawWireFrame(HDC hDc, Model& model); void DrawSolidFlat(HDC hDc, Model& model); + void DrawRasterisedSolidFlat(HDC hDc, Model& model); + void DrawGouraud(HDC hDc, Model& model); + + void FillPolygonFlat(HDC hDc, vector& verticies, COLORREF colorIn); + void FillFlatSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3, COLORREF colorIn); + + void FillPolygonGouraud(HDC hDc, vector& verticies); + void FillGouraudTopFlatTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3); + void FillGouraudBottomFlatTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3); + + void FillPolygonGouraudInt(HDC hDc, vector& verticies); + void FillGouraudSideTriangle(HDC hDc, const Vertex& v1, const Vertex& v2, const Vertex& v3); private: vector _sceneModels; @@ -45,5 +59,7 @@ private: Matrix _currentViewMatrix; float _currentAspectRatio = 0.0f; int _rotation = 0; + + bool _screenMinimized = false; }; diff --git a/SharedTools.cpp b/SharedTools.cpp index f72c8d3..3eb1439 100644 --- a/SharedTools.cpp +++ b/SharedTools.cpp @@ -92,12 +92,12 @@ Matrix SharedTools::GetViewMatrix(float d, int width, int height) Matrix SharedTools::GetCameraTranslateMatrix(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 }); + return GetTranslateMatrix(-x, -y, -z); } Matrix SharedTools::GetCameraTranslateMatrix(const Vertex& position) { - return GetCameraTranslateMatrix(position.GetX(), position.GetY(), position.GetZ()); + return GetTranslateMatrix(-position.GetX(), -position.GetY(), -position.GetZ()); } @@ -115,4 +115,4 @@ Matrix SharedTools::GetCameraRotationMatrix(const Axis rotAxis, const float rotD default: throw "Invalid axis selected"; } -} \ No newline at end of file +} diff --git a/SharedTools.h b/SharedTools.h index 05b4731..d99ccd2 100644 --- a/SharedTools.h +++ b/SharedTools.h @@ -5,6 +5,10 @@ enum class Axis { X, Y, Z }; enum class ColRef { Red, Green, Blue }; +template int sgn(T val) { + return (T(0) < val) - (val < T(0)); +} + namespace SharedTools { const float PI = (float)acos(-1); diff --git a/Vector3D.cpp b/Vector3D.cpp index 385eff0..96dba3f 100644 --- a/Vector3D.cpp +++ b/Vector3D.cpp @@ -2,16 +2,16 @@ Vector3D::Vector3D() { - SetX(1); - SetY(1); - SetZ(1); + _x = 1; + _y = 1; + _z = 1; } Vector3D::Vector3D(float x, float y, float z) { - SetX(x); - SetY(y); - SetZ(z); + _x = x; + _y = y; + _z = z; } Vector3D::Vector3D(const Vector3D& other) @@ -54,7 +54,7 @@ void Vector3D::SetZ(const float z) _z = z; } -void Vector3D::Normalize() +const void Vector3D::Normalize() { float length = sqrt(_x * _x + _y * _y + _z * _z); @@ -68,12 +68,17 @@ void Vector3D::Normalize() float Vector3D::DotProduct(const Vector3D v1, const Vector3D v2) { - return ((v1.GetX() * v2.GetX()) + (v1.GetY() * v2.GetY()) + (v1.GetZ() * v2.GetZ())); + return v1.GetX() * v2.GetX() + v1.GetY() * v2.GetY() + v1.GetZ() * v2.GetZ(); +} + +float Vector3D::Length(const Vector3D v1, const Vector3D v2) +{ + return (float)sqrt(pow((v1.GetX() - v2.GetX()), 2) + pow((v1.GetY() - v2.GetY()), 2) + pow((v1.GetZ() - v2.GetZ()), 2)); } Vector3D Vector3D::CrossProduct(const Vector3D v1, const Vector3D v2) { - return Vector3D((v1.GetY() * v2.GetZ()) - (v1.GetZ() * v2.GetY()), (v1.GetZ() * v2.GetX()) - (v1.GetX() * v2.GetZ()), (v1.GetX() * v2.GetY()) - (v1.GetY() * v2.GetX())); + return Vector3D(v1.GetY() * v2.GetZ() - v1.GetZ() * v2.GetY(), v1.GetZ() * v2.GetX() - v1.GetX() * v2.GetZ(), v1.GetX() * v2.GetY() - v1.GetY() * v2.GetX()); } @@ -82,6 +87,16 @@ const Vector3D Vector3D::operator+ (const Vector3D& rhs) const return Vector3D(_x + rhs.GetX(), _y + rhs.GetY(), _z + rhs.GetZ()); } +const Vector3D Vector3D::operator/ (const float rhs) const +{ + return Vector3D(_x / rhs, _y / rhs, _z / rhs); +} + +const Vector3D Vector3D::operator/ (const int rhs) const +{ + return Vector3D(_x / rhs, _y / rhs, _z / rhs); +} + void Vector3D::Copy(const Vector3D& other) { _x = other.GetX(); diff --git a/Vector3D.h b/Vector3D.h index 4f39ec9..f4bc9c5 100644 --- a/Vector3D.h +++ b/Vector3D.h @@ -18,12 +18,15 @@ public: float GetZ() const; void SetZ(const float z); - void Normalize(); + const void Normalize(); static float DotProduct(const Vector3D v1, const Vector3D v2); + static float Length(const Vector3D v1, const Vector3D v2); static Vector3D CrossProduct(const Vector3D v1, const Vector3D v2); const Vector3D operator+ (const Vector3D& rhs) const; + const Vector3D operator/ (const int rhs) const; + const Vector3D operator/ (const float rhs) const; private: float _x; diff --git a/Vertex.cpp b/Vertex.cpp index caab4d8..f878424 100644 --- a/Vertex.cpp +++ b/Vertex.cpp @@ -6,6 +6,11 @@ Vertex::Vertex() _y = 0.0f; _z = 0.0f; _w = 0.0f; + _contributeCount = 0; + _normal = Vector3D(0, 0, 0); + _r = 0; + _g = 0; + _b = 0; } Vertex::Vertex(const float x, const float y, const float z) @@ -14,6 +19,11 @@ Vertex::Vertex(const float x, const float y, const float z) _y = y; _z = z; _w = 1.0f; + _contributeCount = 0; + _normal = Vector3D(0, 0, 0); + _r = 0; + _g = 0; + _b = 0; } Vertex::Vertex(const float x, const float y, const float z, const float w) @@ -22,6 +32,11 @@ Vertex::Vertex(const float x, const float y, const float z, const float w) _y = y; _z = z; _w = w; + _contributeCount = 0; + _normal = Vector3D(0, 0, 0); + _r = 0; + _g = 0; + _b = 0; } Vertex::Vertex(const Vertex & other) @@ -69,6 +84,132 @@ void Vertex::SetW(const float w) _w = w; } +const int Vertex::GetContributeCount() const +{ + return _contributeCount; +} + +void Vertex::IncrementContributeCount() +{ + _contributeCount++; +} + +void Vertex::ResetContributeCount() +{ + _contributeCount = 0; +} + +const Vector3D& Vertex::GetNormal() const +{ + return _normal; +} + +void Vertex::SetNormal(float x, float y, float z) +{ + _normal.SetX(x); + _normal.SetY(y); + _normal.SetZ(z); +} + +void Vertex::SetNormal(const Vector3D& normal) +{ + SetNormal(normal.GetX(), normal.GetY(), normal.GetZ()); +} + +void Vertex::NormalizeNormal() +{ + _normal.Normalize(); +} + +void Vertex::ResetNormal(bool resetCount) +{ + SetNormal(0, 0, 0); + if (resetCount) + { + ResetContributeCount(); + } +} + +const COLORREF Vertex::GetColor() const +{ + return RGB(_r, _g, _b); +} + +int Vertex::GetR() const +{ + return _r; +} + +int Vertex::GetG() const +{ + return _g; +} + +int Vertex::GetB() const +{ + return _b; +} + +void Vertex::SetColor(int r, int g, int b) +{ + _r = r; + _g = g; + _b = b; +} + +void Vertex::SetColor(const COLORREF colorIn) +{ + SetColor((int)GetRValue(colorIn), (int)GetGValue(colorIn), (int)GetBValue(colorIn)); +} + +int Vertex::GetXInt(bool forceRoundUp) const +{ + if (forceRoundUp) + { + return (int)ceil(GetX()); + } + else + { + return (int)floor(GetX()); + } +;} + +int Vertex::GetYInt(bool forceRoundUp) const +{ + if (forceRoundUp) + { + return (int)ceil(GetY()); + } + else + { + return (int)floor(GetY()); + } +} + +int Vertex::GetZInt(bool forceRoundUp) const +{ + if (forceRoundUp) + { + return (int)ceil(GetZ()); + } + else + { + return (int)floor(GetZ()); + } +} + +int Vertex::GetWInt(bool forceRoundUp) const +{ + if (forceRoundUp) + { + return (int)ceil(GetW()); + } + else + { + return (int)floor(GetW()); + } +} + void Vertex::Dehomogenize() { _x = _x / _w; @@ -90,7 +231,7 @@ Vertex& Vertex::operator=(const Vertex& rhs) const Vector3D Vertex::operator-(const Vertex& rhs) const { - return Vector3D(rhs.GetX() - GetX(), rhs.GetY() - GetY(), rhs.GetZ() - GetZ()); + return Vector3D(rhs.GetX() - _x, rhs.GetY() - _y, rhs.GetZ() - _z); } // The const at the end of the declaraion for '==" indicates that this operation does not change @@ -118,4 +259,9 @@ void Vertex::Copy(const Vertex& other) _y = other.GetY(); _z = other.GetZ(); _w = other.GetW(); + + _contributeCount = other.GetContributeCount(); + SetNormal(other.GetNormal()); + + SetColor(other.GetR(), other.GetG(), other.GetB()); } diff --git a/Vertex.h b/Vertex.h index 71cc658..86e3f13 100644 --- a/Vertex.h +++ b/Vertex.h @@ -1,5 +1,6 @@ #pragma once #include "Vector3D.h" +#include "windows.h" class Vertex { @@ -19,6 +20,31 @@ public: float GetW() const; void SetW(const float w); + const int GetContributeCount() const; + void IncrementContributeCount(); + void ResetContributeCount(); + + const Vector3D& GetNormal() const; + void SetNormal(float x, float y, float z); + void SetNormal(const Vector3D& normal); + void NormalizeNormal(); + void ResetNormal(bool resetCount = false); + + const COLORREF GetColor() const; + int GetR() const; + int GetG() const; + int GetB() const; + void SetColor(const int r, const int g, const int b); + void SetColor(const COLORREF colorIn); + + // Accessor Methods 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 + int GetXInt(bool forceRoundUp = false) const; + int GetYInt(bool forceRoundUp = false) const; + int GetZInt(bool forceRoundUp = false) const; + int GetWInt(bool forceRoundUp = false) const; + void Dehomogenize(); // Assignment operator @@ -35,6 +61,13 @@ private: float _z; float _w; + int _contributeCount; + Vector3D _normal; + + int _r; + int _g; + int _b; + void Copy(const Vertex& other); }; diff --git a/cow.md2 b/cow.md2 new file mode 100644 index 0000000..34b2c2b Binary files /dev/null and b/cow.md2 differ diff --git a/teapot.md2 b/teapot.md2 new file mode 100644 index 0000000..b6d1ae5 Binary files /dev/null and b/teapot.md2 differ