#include "Model.h" Model::Model() { _kdRed = 1.0f; _kdGreen = 1.0f; _kdBlue = 1.0f; _active = false; _drawMethod = DrawMethod::Wireframe; _modelMD2Filename = ""; _modelTextureFilename = ""; } Model::Model(string MD2Filename, string textureFilename) { _kdRed = 1.0f; _kdGreen = 1.0f; _kdBlue = 1.0f; _active = false; _drawMethod = DrawMethod::Wireframe; _modelMD2Filename = MD2Filename; _modelTextureFilename = textureFilename; } Model::~Model() { _vertices.~vector(); _transformedVertices.~vector(); _polygons.~vector(); _pendingTransforms.~vector(); _uvCoords.~vector(); } string Model::GetModelFilename() const { return _modelMD2Filename; } const char* Model::CGetModelFilename() const { return _modelMD2Filename.c_str(); } string Model::GetTextureFilename() const { return _modelTextureFilename; } const char* Model::CGetTextureFilename() const { return _modelTextureFilename.c_str(); } void Model::SetActive(bool value) { _active = value; } void Model::ToggleActive() { _active = !_active; } bool Model::GetActive() const { return _active; } void Model::SetDrawMethod(DrawMethod method) { _drawMethod = method; } DrawMethod Model::GetDrawMethod() const { return _drawMethod; } vector& Model::GetPolygons() { return _polygons; } vector& Model::GetVertices() { return _vertices; } vector& Model::GetUVCoords() { return _uvCoords; } const vector& Model::GetPendingTransforms() { return _pendingTransforms; } size_t Model::GetPolygonCount() { return _polygons.size(); } size_t Model::GetVerticesCount() { return _vertices.size(); } size_t Model::GetUVCoordCount() { return _uvCoords.size(); } size_t Model::GetPendingTransformCount() { return _pendingTransforms.size(); } void Model::AddVertex(float x, float y, float z) { _vertices.push_back(Vertex(x, y, z)); _transformedVertices.push_back(Vertex(x, y, z)); } void Model::AddPolygon(int index0, int index1, int index2, int uvIndex0, int uvIndex1, int uvIndex2) { _polygons.push_back(Polygon3D(index0, index1, index2, uvIndex0, uvIndex1, uvIndex2)); } void Model::AddTextureUV(float u, float v) { _uvCoords.push_back(UVCoord(u, v)); } void Model::EnqueueTransform(Matrix transform) { _pendingTransforms.push_back(transform); } void Model::ClearPendingTransforms() { _pendingTransforms.clear(); } Texture& Model::GetTexture() { return _texture; } const Polygon3D& Model::GetPolygon(int index) const { return _polygons[index]; } const Vertex& Model::GetVertex(int polygonIndex, int vertexPolygonIndex) const { return GetVertex(GetPolygon(polygonIndex).GetIndex(vertexPolygonIndex)); } const Vertex& Model::GetVertex(int index) const { return _transformedVertices[index]; } const UVCoord& Model::GetUVCoord(int index) const { return _uvCoords[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); _kdGreen = BoundsCheck(0.0f, 1.0f, green); _kdBlue = BoundsCheck(0.0f, 1.0f, blue); } void Model::SetReflectionCoefficient(ColRef color, float value) { float valueChecked = BoundsCheck(0.0f, 1.0f, value); switch (color) { default: case ColRef::Red: _kdRed = valueChecked; break; case ColRef::Green: _kdGreen = valueChecked; break; case ColRef::Blue: _kdBlue = valueChecked; break; } } void Model::SetRedReflectionCoefficient(float value) { SetReflectionCoefficient(ColRef::Red, value); } void Model::SetGreenReflectionCoefficient(float value) { SetReflectionCoefficient(ColRef::Green, value); } void Model::SetBlueReflectionCoefficient(float value) { SetReflectionCoefficient(ColRef::Blue, value); } float Model::GetReflectionCoefficient(ColRef color) const { float result; switch (color) { default: case ColRef::Red: result = _kdRed; break; case ColRef::Green: result = _kdGreen; break; case ColRef::Blue: result = _kdBlue; break; } return result; } float Model::GetRedReflectionCoefficient() const { return GetReflectionCoefficient(ColRef::Red); } float Model::GetGreenReflectionCoefficient() const { return GetReflectionCoefficient(ColRef::Green); } float Model::GetBlueReflectionCoefficient() const { return GetReflectionCoefficient(ColRef::Blue); } void Model::ApplyTransformToLocalVertices(const Matrix& transform) { for (int i = 0; i < GetVerticesCount(); i++) { _transformedVertices[i] = transform * _vertices[i]; } } void Model::ApplyTransformToTransformedVertices(const Matrix& transform) { for (int i = 0; i < GetVerticesCount(); i++) { _transformedVertices[i] = transform * _transformedVertices[i]; } } void Model::DehomogenizeAllVertices() { for (Vertex& currentVertex : _transformedVertices) { currentVertex.Dehomogenize(); } } void Model::CalculateBackfaces(Camera& currentCamera) { 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)); currentPolygon.NormalizeNormal(); Vector3D eyeVector = _transformedVertices[currentPolygon.GetIndex(0)] - currentCamera.GetCameraPosition(); eyeVector.Normalize(); float dotProduct = Vector3D::DotProduct(currentPolygon.GetNormal(), eyeVector); if (dotProduct < 0) { currentPolygon.SetCulled(true); } else { currentPolygon.SetCulled(false); } } } 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(); _transformedVertices[_polygons[pi].GetIndex(i)].SetUVIndex(_polygons[pi].GetUVIndex(i)); } } for (Vertex& currentVertex : _transformedVertices) { currentVertex.SetNormal(currentVertex.GetNormal() / currentVertex.GetContributeCount()); currentVertex.NormalizeNormal(); } } bool DepthCompare(Polygon3D& a, Polygon3D& b) { return a.GetDepth() > b.GetDepth(); } void Model::Sort() { for (Polygon3D& currentPolygon : _polygons) { float zTotal = 0.0f; for (int i = 0; i < currentPolygon.GetPolygonVertexCount(); i++) { zTotal += _transformedVertices[currentPolygon.GetIndex(i)].GetZ(); } currentPolygon.SetDepth(zTotal / currentPolygon.GetPolygonVertexCount()); } 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()); } } }