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;

}
Example #2
0
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());
}