void renderTriangles(const SPVertex * _pVertices, const GLubyte * _pElements, u32 _numElements)
{
	//Current depth buffer can be null if we are loading from a save state
	if(depthBufferList().getCurrent() == nullptr)
		return;

	vertexclip vclip[16];
	vertexi vdraw[12];
	const SPVertex * vsrc[4];
	SPVertex vdata[6];
	for (u32 i = 0; i < _numElements; i += 3) {
		u32 orbits = 0;
		if (_pElements != nullptr) {
			for (u32 j = 0; j < 3; ++j) {
				vsrc[j] = &_pVertices[_pElements[i + j]];
				orbits |= vsrc[j]->clip;
			}
		} else {
			for (u32 j = 0; j < 3; ++j) {
				vsrc[j] = &_pVertices[i + j];
				orbits |= vsrc[j]->clip;
			}
		}
		vsrc[3] = vsrc[0];

		int numVertex = clipW(vsrc, vdata);

		if (!calcScreenCoordinates(vdata, vclip, numVertex))
			continue;

		const int dzdx = ((orbits & CLIP_W) == 0) ? calcDzDx(vclip) : calcDzDx2(vsrc);
		if (dzdx == 0)
			continue;

		if (orbits == 0) {
			assert(numVertex == 3);
			if ((gSP.geometryMode & G_CULL_BACK) != 0) {
				for (int k = 0; k < 3; ++k) {
					vdraw[k].x = floatToFixed16(vclip[k].x);
					vdraw[k].y = floatToFixed16(vclip[k].y);
					vdraw[k].z = floatToFixed16(vclip[k].z);
				}
			} else {
				for (int k = 0; k < 3; ++k) {
					const u32 idx = 3 - k - 1;
					vdraw[k].x = floatToFixed16(vclip[idx].x);
					vdraw[k].y = floatToFixed16(vclip[idx].y);
					vdraw[k].z = floatToFixed16(vclip[idx].z);
				}
			}
		} else {
			vertexclip ** vtx;
			numVertex = ClipPolygon(&vtx, vclip, numVertex);
			if (numVertex < 3)
				continue;

			if ((gSP.geometryMode & G_CULL_BACK) != 0) {
				for (int k = 0; k < numVertex; ++k) {
					vdraw[k].x = floatToFixed16(vtx[k]->x);
					vdraw[k].y = floatToFixed16(vtx[k]->y);
					vdraw[k].z = floatToFixed16(vtx[k]->z);
				}
			} else {
				for (int k = 0; k < numVertex; ++k) {
					const u32 idx = numVertex - k - 1;
					vdraw[k].x = floatToFixed16(vtx[idx]->x);
					vdraw[k].y = floatToFixed16(vtx[idx]->y);
					vdraw[k].z = floatToFixed16(vtx[idx]->z);
				}
			}
		}

		Rasterize(vdraw, numVertex, dzdx);
	}
}
Example #2
0
void scanConverter(GzRender *render, GzCoord *vertexList)
{
	GzCoord top, mid, btm;
	GzCoord vtx1, vtx2, vtx3;

	/* Find a bounding box of the tri, and sort 3 verts */
	/* Find max and min x values */
	float minx, miny, maxx, maxy;
	if (vertexList[0][0] >= vertexList[1][0])
	{
		maxx = vertexList[0][0];
		minx = vertexList[1][0];
	}
	else
	{
		maxx = vertexList[1][0];
		minx = vertexList[0][0];
	}
	if (vertexList[2][0] > maxx) maxx = vertexList[2][0];
	if (vertexList[2][0] < minx) minx = vertexList[2][0];

	/* Find max and min y values*/
	if (vertexList[0][1] >= vertexList[1][1])
	{
		top[0] = vertexList[0][0]; top[1] = vertexList[0][1]; top[2] = vertexList[0][2];
		btm[0] = vertexList[1][0]; btm[1] = vertexList[1][1]; btm[2] = vertexList[1][2];
	}
	else
	{
		top[0] = vertexList[1][0]; top[1] = vertexList[1][1]; top[2] = vertexList[1][2];
		btm[0] = vertexList[0][0]; btm[1] = vertexList[0][1]; btm[2] = vertexList[0][2];
	}
	if (vertexList[2][1] > top[1])
	{
		mid[0] = top[0]; mid[1] = top[1]; mid[2] = top[2];
		top[0] = vertexList[2][0]; top[1] = vertexList[2][1]; top[2] = vertexList[2][2];
	}
	else if (vertexList[2][1] < btm[1])
	{
		mid[0] = btm[0]; mid[1] = btm[1]; mid[2] = btm[2];
		btm[0] = vertexList[2][0]; btm[1] = vertexList[2][1]; btm[2] = vertexList[2][2];
	}
	else
	{
		mid[0] = vertexList[2][0]; mid[1] = vertexList[2][1]; mid[2] = vertexList[2][2];
	}

	maxx = ceil(maxx);
	maxy = ceil(top[1]);
	minx = floor(minx);
	miny = floor(btm[1]);

	if (top[1] == mid[1]) // Top edge exits
	{
		if (top[0] < mid[0])
		{
			vtx1[0] = top[0]; vtx1[1] = top[1]; vtx1[2] = top[2];
			vtx2[0] = mid[0]; vtx2[1] = mid[1]; vtx2[2] = mid[2];
		}
		else
		{
			vtx2[0] = top[0]; vtx2[1] = top[1]; vtx2[2] = top[2];
			vtx1[0] = mid[0]; vtx1[1] = mid[1]; vtx1[2] = mid[2];
		}
		vtx3[0] = top[0]; vtx1[1] = top[1]; vtx1[2] = top[2];
	}
	else if (btm[1] == mid[1]) // Bottom edge exits
	{
		if (btm[0] < mid[0])
		{
			vtx3[0] = btm[0]; vtx3[1] = btm[1]; vtx3[2] = btm[2];
			vtx2[0] = mid[0]; vtx2[1] = mid[1]; vtx2[2] = mid[2];
		}
		else
		{
			vtx2[0] = btm[0]; vtx2[1] = btm[1]; vtx2[2] = btm[2];
			vtx3[0] = mid[0]; vtx3[1] = mid[1]; vtx3[2] = mid[2];
		}
		vtx1[0] = top[0]; vtx1[1] = top[1]; vtx1[2] = top[2];
	}
	else
	{
		float deltax = top[0] - btm[0];
		float deltay = top[1] - btm[1];
		float slope = deltax / deltay;
		float x = mid[1] * slope - top[1] * slope + top[0];
		vtx1[0] = top[0]; vtx1[1] = top[1]; vtx1[2] = top[2];
		if (x < mid[0])
		{
			vtx2[0] = mid[0]; vtx2[1] = mid[1]; vtx2[2] = mid[2];
			vtx3[0] = btm[0]; vtx3[1] = btm[1]; vtx3[2] = btm[2];
		}
		else
		{
			vtx2[0] = btm[0]; vtx2[1] = btm[1]; vtx2[2] = btm[2];
			vtx3[0] = mid[0]; vtx3[1] = mid[1]; vtx3[2] = mid[2];
		}
	}

	for (int i = (int)minx; i < (int)maxx; i++)
	{
		for (int j = (int)miny; j < (int)maxy; j++)
		{
			GzCoord point;
			point[0] = i;
			point[1] = j;
			point[2] = 0;
			if (LEE(vtx1, vtx2, point) >= 0 && LEE(vtx2, vtx3, point) >= 0 && LEE(vtx3, vtx1, point) >= 0)
			{
				/* Interpolate Z */
				float vector1[3], vector2[3];
				float *result = (float*)malloc(sizeof(float)* 3);
				vector1[0] = vtx1[0] - vtx2[0]; vector1[1] = vtx1[1] - vtx2[1]; vector1[2] = vtx1[2] - vtx2[2];
				vector2[0] = vtx3[0] - vtx2[0]; vector2[1] = vtx3[1] - vtx2[1]; vector2[2] = vtx3[2] - vtx2[2];
				result = crossProduct(vector1, vector2);
				if (result[0] * vtx2[0] + result[1] * vtx2[1] + result[2] * vtx2[2] == result[0] * vtx3[0] + result[1] * vtx3[1] + result[2] * vtx3[2])
					int a = 3;
				point[2] = (result[0] * vtx1[0] + result[1] * vtx1[1] + result[2] * vtx1[2] - result[0] * i - result[1] * j) / result[2];
				
				///* Do the transformation */
				//transform(render, point);
				
				Rasterize(render->display, point[0], point[1],
					ctoi(render->flatcolor[0]),
					ctoi(render->flatcolor[1]),
					ctoi(render->flatcolor[2]),
					1, point[2]);
			}
		}
	}
}