aboutsummaryrefslogblamecommitdiff
path: root/main.cpp
blob: a5e5df97f5f85dadf85fde0968eea9e8ce218d9b (plain) (tree)



























































































































































                                                                                                                                       
                                                                                      




                                                                                       
#include<fstream>
#include<cmath>

class Vertice
{
public:
	float x, y, z;
	unsigned char red, green, blue;
	Vertice(float x, float y, float z, int red, int green, int blue)
	{
		this->x = x;
		this->y = y;
		this->z = z;

		this->red = (unsigned char)red;
		this->green = (unsigned char)green;
		this->blue = (unsigned char)blue;
	}
	void fitToImage(int imageWidth, int imageHeight)
	{
		x = (x * (imageWidth / 2)) + (imageWidth / 2);
		y = (-y * (imageHeight / 2)) + (imageHeight / 2);
	}
};

class Image
{
public:
	int imageWidth, imageHeight;
	unsigned char* pixels;
	Image(int imageWidth, int imageHeight)
	{
		this->imageWidth = imageWidth;
		this->imageHeight = imageHeight;
		pixels = new unsigned char[imageWidth * imageHeight * 3];
	}
	~Image()
	{
		delete[] pixels;
	}
	void setPixel(int x, int y, int red, int green, int blue)
	{
		int help_var = ((y * imageWidth) + x) * 3;
		pixels[help_var + 0] = (unsigned char)red;
		pixels[help_var + 1] = (unsigned char)green;
		pixels[help_var + 2] = (unsigned char)blue;
	}
	void fillPixels(int red, int green, int blue)
	{
		int help_var = imageWidth * imageHeight * 3;
		for (int i = 0; i < help_var; i += 3) {
			pixels[i + 0] = (unsigned char)red;
			pixels[i + 1] = (unsigned char)green;
			pixels[i + 2] = (unsigned char)blue;
		}
	}
	//-------------------SCANLINE TRIANGLE RASTERISATION---------------------------
	void fillFlatTopTriangle(Vertice* v1, Vertice* v2, Vertice* v3)
	{
		float invslope1 = (float)(v3->x - v1->x) / (float)(v3->y - v1->y);
		float invslope2 = (float)(v3->x - v2->x) / (float)(v3->y - v2->y);

		float curx1 = v3->x;
		float curx2 = v3->x;
		int cury1 = (int)ceil(v1->y - 0.5f);
		int cury2 = (int)ceil(v3->y - 0.5f);

		for (int i = cury2; i >= cury1; i--)
		{
			if(curx1 < curx2)
				for (int j = (int)ceil(curx1 - 0.5f); j <= (int)ceil(curx2 - 0.5f); j++)
					setPixel(j, i, 255, 0, 0);
			else
				for (int j = (int)ceil(curx2 - 0.5f); j <= (int)ceil(curx1 - 0.5f); j++)
					setPixel(j, i, 255, 0, 0);

			curx1 -= invslope1;
			curx2 -= invslope2;
		}
	}
	void fillFlatBottomTriangle(Vertice* v1, Vertice* v2, Vertice* v3)
	{
		float invslope1 = (float)(v2->x - v1->x) / (float)(v2->y - v1->y);
		float invslope2 = (float)(v3->x - v1->x) / (float)(v3->y - v1->y);

		float curx1 = v1->x;
		float curx2 = v1->x;
		int cury1 = (int)ceil(v1->y - 0.5f);
		int cury2 = (int)ceil(v2->y - 0.5f);
		for (int i = cury1; i <= cury2; i++)
		{
			if(curx1 < curx2)
				for (int j = (int)ceil(curx1 - 0.5f); j <= (int)ceil(curx2 - 0.5f); j++)
					setPixel(j, i, 255, 0, 0);
			else
				for (int j = (int)ceil(curx2 - 0.5f); j <= (int)ceil(curx1 - 0.5f); j++)
					setPixel(j, i, 255, 0, 0);

			curx1 += invslope1;
			curx2 += invslope2;
		}
	}
	void fillTriangle(Vertice* v1, Vertice* v2, Vertice* v3)
	{
		if (v1->y > v2->y)
			std::swap(v1, v2);
		if (v1->y > v3->y)
			std::swap(v1, v3);
		if (v2->y > v3->y)
			std::swap(v2, v3);

		if (v2->y == v3->y){
			if(v2->x < v3->x)
				std::swap(v2, v3);
			fillFlatBottomTriangle(v1, v2, v3);
		}
		else if (v1->y == v2->y){
			if(v1->x < v2->x)
				std::swap(v1, v2);
			fillFlatTopTriangle(v1, v2, v3);
		}
		else
		{
			Vertice v4(
				(v1->x + (((float)(v2->y - v1->y) / (float)(v3->y - v1->y)) * (v3->x - v1->x))), v2->y, 0.0f, 0, 0, 0);
			if(v1->x < v4.x){
				fillFlatBottomTriangle(v1, v2, &v4);
				fillFlatTopTriangle(v2, &v4, v3);
			}
			else{
				fillFlatBottomTriangle(v1, &v4, v2);
				fillFlatTopTriangle(&v4, v2, v3);
			}
		}

	}
	//-----------------------------------------------------------------------------
};

int main()
{
	Image image(800, 600);
	image.fillPixels(255, 255, 255);

	Vertice a(0.2f, 0.5f, 0.0f, 255, 0, 0);
	Vertice b(-0.5f, 0.0f, 0.0f, 0, 255, 0);
	Vertice c(0.5f, -0.5f, 0.0f, 0, 0, 255);

	a.fitToImage(image.imageWidth, image.imageHeight);
	b.fitToImage(image.imageWidth, image.imageHeight);
	c.fitToImage(image.imageWidth, image.imageHeight);
	
	image.fillTriangle(&a, &b, &c);

	std::ofstream imageFile;
	imageFile.open("./image.ppm");
	imageFile << "P6 " << image.imageWidth << " " << image.imageHeight << " 255 ";
	imageFile.write((char*)image.pixels, image.imageWidth * image.imageHeight * 3);
	imageFile.close();

	return 0;
}