const Vertex Matrix3D::operator*(const Vertex &p) const { /* Multiplying a vertex by a matrix */ // Need to update this Vertex temp; temp.SetX((this->_m[0][0] * p.GetX()) + (this->_m[0][1] * p.GetY()) + (this->_m[0][2] * p.GetZ()) + (this->_m[0][3] * p.GetW())); temp.SetY((this->_m[1][0] * p.GetX()) + (this->_m[1][1] * p.GetY()) + (this->_m[1][2] * p.GetZ()) + (this->_m[1][3] * p.GetW())); temp.SetZ((this->_m[2][0] * p.GetX()) + (this->_m[2][1] * p.GetY()) + (this->_m[2][2] * p.GetZ()) + (this->_m[2][3] * p.GetW())); temp.SetW((this->_m[3][0] * p.GetX()) + (this->_m[3][1] * p.GetY()) + (this->_m[3][2] * p.GetZ()) + (this->_m[3][3] * p.GetW())); temp.GetColor().SetValue(p.GetColor().GetValue()); return temp; }
Edge::Edge(Gradients gradients,Vertex minYVertex,Vertex maxYVertex,int minYVertexIndex) { //To get the starting x we use the formula ((x2 - x1)/(y2 - y1)) + x1 m_yBegin = ceil(minYVertex.GetY()); m_yEnd = ceil(maxYVertex.GetY()); //The amount by which we step our x. m_reciprocalSlope = (maxYVertex.GetX() - minYVertex.GetX()) / (maxYVertex.GetY() - minYVertex.GetY()); // This variable is created because we need to take into account the truncated // values of each mathematical operation that converts float to an int. // If we don't this can come and haunt us later in the program at unexpected times. float yApproxFloatError = m_yBegin - minYVertex.GetY(); m_x = (m_reciprocalSlope * yApproxFloatError) + minYVertex.GetX(); float xApproxFloatError = m_x - minYVertex.GetX(); m_UOverZ = gradients.GetUOverZ(minYVertexIndex) + gradients.GetUOverZXGradient() * xApproxFloatError + gradients.GetUOverZYGradient() * yApproxFloatError; m_UOverZGradient = gradients.GetUOverZYGradient() + gradients.GetUOverZXGradient() * m_reciprocalSlope; m_VOverZ = gradients.GetVOverZ(minYVertexIndex) + gradients.GetVOverZXGradient() * xApproxFloatError + gradients.GetVOverZYGradient() * yApproxFloatError; m_VOverZGradient = gradients.GetVOverZYGradient() + gradients.GetVOverZXGradient() * m_reciprocalSlope; m_OneOverZ = gradients.GetOneOverZ(minYVertexIndex) + gradients.GetOneOverZXGradient() * xApproxFloatError + gradients.GetOneOverZYGradient() * yApproxFloatError; m_OneOverZGradient = gradients.GetOneOverZYGradient() + gradients.GetOneOverZXGradient() * m_reciprocalSlope; m_ZBuffer = gradients.GetZBuffer(minYVertexIndex) + gradients.GetZBufferXGradient() * xApproxFloatError + gradients.GetZBufferYGradient() * yApproxFloatError; m_ZBufferGradient = gradients.GetZBufferYGradient() + gradients.GetZBufferXGradient() * m_reciprocalSlope; }
// Interpolates between the given vertexs and sets the start and end values of each // scanline it encounters on the way. void Rasterizer::InterpolateScanline(ScanLine* scanlines, Vertex v1, Vertex v2) { // Swap the vertexs round if we need to, to make sure // the first vertex is the one at the top of the screen. if (v2.GetY() < v1.GetY()) { Vertex v3 = v2; v2 = v1; v1 = v3; } // Work out the difference between each vertex and the number of steps // we need to take to interpolate between each of the vertexs. float yDiff = (v2.GetY() - v1.GetY()); float xDiff = (v2.GetX() - v1.GetX()); float zDiff = (v2.GetPreTransformZ() - v1.GetPreTransformZ()); float numOfPoints = v2.GetY() - v1.GetY(); // Work out the difference in colour between each vertex. float redColorDiff = (float)(v2.GetColor().GetR() - v1.GetColor().GetR()); float greenColorDiff = (float)(v2.GetColor().GetG() - v1.GetColor().GetG()); float blueColorDiff = (float)(v2.GetColor().GetB() - v1.GetColor().GetB()); // WOrk out the difference between the normals. float xNormalDiff = (float)(v2.GetNormal().GetX() - v1.GetNormal().GetX()); float yNormalDiff = (float)(v2.GetNormal().GetY() - v1.GetNormal().GetY()); float zNormalDiff = (float)(v2.GetNormal().GetZ() - v1.GetNormal().GetZ()); // Work out the difference in uv coordinate between each vertex. UVCoordinate uvCoord1 = v1.GetUVCoordinate(); UVCoordinate uvCoord2 = v2.GetUVCoordinate(); uvCoord1.U = uvCoord1.U / v1.GetPreTransformZ(); uvCoord1.V = uvCoord1.V / v1.GetPreTransformZ(); uvCoord1.Z = 1.0f / v1.GetPreTransformZ(); uvCoord2.U = uvCoord2.U / v2.GetPreTransformZ(); uvCoord2.V = uvCoord2.V / v2.GetPreTransformZ(); uvCoord2.Z = 1.0f / v2.GetPreTransformZ(); float uCoordDiff = (uvCoord2.U - uvCoord1.U); float vCoordDiff = (uvCoord2.V - uvCoord1.V); float zCoordDiff = (uvCoord2.Z - uvCoord1.Z); // Go through each point in the interpolation and work out the // colour and uv values for pixel along the way. for (int i = 0; i < numOfPoints; i++) { unsigned int scanline = (int)(v1.GetY() + i); if (scanline < 0 || scanline >= _height) continue; // Get the x axis value in our interpolation. float x = v1.GetX() + i * (xDiff / yDiff); // Work out the colour value of the current pixel. float red = v1.GetColor().GetR() + ((redColorDiff / numOfPoints) * i); float green = v1.GetColor().GetG() + ((greenColorDiff / numOfPoints) * i); float blue = v1.GetColor().GetB() + ((blueColorDiff / numOfPoints) * i); // Work out the normal value of the current pixel. float normalX = v1.GetNormal().GetX() + ((xNormalDiff / numOfPoints) * i); float normalY = v1.GetNormal().GetY() + ((yNormalDiff / numOfPoints) * i); float normalZ = v1.GetNormal().GetZ() + ((zNormalDiff / numOfPoints) * i); // Work out the normal value of the current pixel. float pixelX = v1.GetX() + ((xDiff / numOfPoints) * i); float pixelY = v1.GetY() + ((yDiff / numOfPoints) * i); float pixelZ = v1.GetPreTransformZ() + ((zDiff / numOfPoints) * i); // Work out the UV value of the current pixel. float u = uvCoord1.U + ((uCoordDiff / numOfPoints) * i); float v = uvCoord1.V + ((vCoordDiff / numOfPoints) * i); float z = uvCoord1.Z + ((zCoordDiff / numOfPoints) * i); // If the x-value is below the scanline's start x-value, then // set the scanlines start value to the current values. if (x < scanlines[scanline].xStart) { scanlines[scanline].xStart = x; scanlines[scanline].redStart = red; scanlines[scanline].greenStart = green; scanlines[scanline].blueStart = blue; scanlines[scanline].uStart = u; scanlines[scanline].vStart = v; scanlines[scanline].zStart = z; scanlines[scanline].xNormalStart = normalX; scanlines[scanline].yNormalStart = normalY; scanlines[scanline].zNormalStart = normalZ; scanlines[scanline].pixelXStart = pixelX; scanlines[scanline].pixelYStart = pixelY; scanlines[scanline].pixelZStart = pixelZ; } // If the x-value is above the scanline's end x-value, then // set the scanlines end value to the current values. if (x > scanlines[scanline].xEnd) { scanlines[scanline].xEnd = x; scanlines[scanline].redEnd = red; scanlines[scanline].greenEnd = green; scanlines[scanline].blueEnd = blue; scanlines[scanline].uEnd = u; scanlines[scanline].vEnd = v; scanlines[scanline].zEnd = z; scanlines[scanline].xNormalEnd = normalX; scanlines[scanline].yNormalEnd = normalY; scanlines[scanline].zNormalEnd = normalZ; scanlines[scanline].pixelXEnd = pixelX; scanlines[scanline].pixelYEnd = pixelY; scanlines[scanline].pixelZEnd = pixelZ; } } }
// Gets the vector between 2 vertexs. Vector3D Vertex::GetVector(Vertex v1, Vertex v2) { return Vector3D(v2.GetX() - v1.GetX(), v2.GetY() - v1.GetY(), v2.GetZ() - v1.GetZ()); }