<commit_before>#include "stdafx.h"

#include "Rasterizer.h"
#include "Primitive.h"
#include "Display.h"

#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"

#define WIDTH 1280
#define HEIGHT 720
#define DISPLAY_FULLSCREEN false

using namespace std;
using namespace glm;
using namespace softlit;

//#define SINGLE_FRAME_OUTPUT

struct UBO
{
	mat4 MV;
	mat4 MVP;
	mat3 NORMAL;
};

// VS
vec4 VS_Simple(const glm::vec3& pos, const UBO* const ubo, const Vertex_IN* const in, Vertex_OUT* out)
{
	out->PushVertexAttribute(in->attrib_vec3[0]); // Push normal

	return (ubo->MVP * vec4(pos, 1));
}

// FS
vec4 FS_Simple(const UBO* const ubo, const Vertex_OUT* const in)
{
	const vec3 outcol = in->attrib_vec3[0] * 0.5f + 0.5f;

	return vec4(outcol, 1);
}

void ImportOBJ(vector<Primitive*>& objects, const string&);

int main(int argc, char* argv[])
{
	float fov = 60.f;
	uint32_t width = WIDTH;
	uint32_t height = HEIGHT;

	vector<Primitive*> objects;

	//TODO: Handle multiple objects in a single .obj
	//ImportOBJ(objects, "../assets/bunny.obj");
	ImportOBJ(objects, "../assets/cube.obj");

	DBG_ASSERT(!objects.empty() && "Failed to import models!");

	RasterizerSetup rasterSetup;
	rasterSetup.vertexWinding = VertexWinding::COUNTER_CLOCKWISE;
	rasterSetup.viewport = { 0u, 0u, width, height };

	Rasterizer* rasterizer = new Rasterizer(rasterSetup);

	vec3 eye(3, 2, -5);
	vec3 lookat(0, 0, 0);
	vec3 up(0, 1, 0);

	mat4 view = lookAt(eye, lookat, up);
	mat4 proj = perspective(glm::radians(fov), (float)width / (float)height, 0.5f, 100.f);
	mat4 model;

	// Create primitive shading data
	const auto VS = reinterpret_cast<vertex_shader> (&VS_Simple);
	const auto FS = reinterpret_cast<fragment_shader> (&FS_Simple);

	UBO ubo;

	for (Primitive* prim : objects)
	{
		prim->setVS(VS);
		prim->setFS(FS);
		prim->UBO(&ubo);
	}

#ifdef SINGLE_FRAME_OUTPUT
	rasterizer->ClearBuffers();

	for (Primitive* prim : objects)
	{
		//model = rotate(model, 0.025f, vec3(0, 1, 0));
		mat4 mv = view * model;
		mat3 normal = { mv[0], mv[1], mv[2] };
		mat4 mvp = proj * mv;

		mat_ubo* ubo = static_cast<mat_ubo*> (prim->UBO());
		ubo->MVP = mvp;
		ubo->NORMAL = normal;

		rasterizer->Draw(prim);
	}

	const vector<vec4>& frameBuffer = rasterizer->getFrameBuffer();
	FILE *f = NULL;
	fopen_s(&f, "../render.ppm", "w");
	fprintf(f, "P3\n%d %d\n%d\n ", WIDTH, HEIGHT, 255);
	for (int32_t i = 0; i < WIDTH * HEIGHT; ++i)
	{
		uint r = (uint)(255 * frameBuffer[i].x);
		uint g = (uint)(255 * frameBuffer[i].y);
		uint b = (uint)(255 * frameBuffer[i].z);
		fprintf(f, "%d %d %d ", r, g, b);
	}
	fclose(f);

	printf("DONE\n");

#else
	// Init SDL
	Display display(width, height, DISPLAY_FULLSCREEN);

	SDL_Event event;
	bool running = true;
	bool paused = false;
	while (running)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
			case SDL_KEYDOWN:
				switch (event.key.keysym.scancode)
				{
				case SDL_SCANCODE_SPACE:
					paused = !paused;
					break;
				case SDL_SCANCODE_ESCAPE:
					running = false;
					break;
				default:
					break;
				}
				break;
			case SDL_KEYUP:
				break;
			case SDL_QUIT:
				running = false;
				break;
			default:
				break;
			}
		}

		const auto drawBegin = chrono::high_resolution_clock::now();
		if (!paused) // When unpaused, re-draw every frame
		{
			display.ClearRenderTarget(ivec3(0, 0, 0));

			// Pre-draw, invalidate frame and depth buffers
			rasterizer->ClearBuffers();

			for (size_t i = 0; i < objects.size(); i++)
			{
				Primitive* prim = objects[i];
				model = rotate(model, 0.025f, vec3(0, 1, 0));
				mat4 mv = view * model;
				mat3 normal = { mv[0], mv[1], mv[2] };
				mat4 mvp = proj * mv;<commit_msg>Use separate model xform for each object<commit_after>#include "stdafx.h"

#include "Rasterizer.h"
#include "Primitive.h"
#include "Display.h"

#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"

#define WIDTH 1280
#define HEIGHT 720
#define DISPLAY_FULLSCREEN false

using namespace std;
using namespace glm;
using namespace softlit;

//#define SINGLE_FRAME_OUTPUT

struct UBO
{
	mat4 MV;
	mat4 MVP;
	mat3 NORMAL;
};

// VS
vec4 VS_Simple(const glm::vec3& pos, const UBO* const ubo, const Vertex_IN* const in, Vertex_OUT* out)
{
	out->PushVertexAttribute(in->attrib_vec3[0]); // Push normal

	return (ubo->MVP * vec4(pos, 1));
}

// FS
vec4 FS_Simple(const UBO* const ubo, const Vertex_OUT* const in)
{
	const vec3 outcol = in->attrib_vec3[0] * 0.5f + 0.5f;

	return vec4(outcol, 1);
}

void ImportOBJ(vector<Primitive*>& objects, const string&);

int main(int argc, char* argv[])
{
	float fov = 60.f;
	uint32_t width = WIDTH;
	uint32_t height = HEIGHT;

	vector<Primitive*> objects;

	//TODO: Handle multiple objects in a single .obj
	//ImportOBJ(objects, "../assets/bunny.obj");
	ImportOBJ(objects, "../assets/cube.obj");

	DBG_ASSERT(!objects.empty() && "Failed to import models!");

	RasterizerSetup rasterSetup;
	rasterSetup.vertexWinding = VertexWinding::COUNTER_CLOCKWISE;
	rasterSetup.viewport = { 0u, 0u, width, height };

	Rasterizer* rasterizer = new Rasterizer(rasterSetup);

	vec3 eye(3, 2, -5);
	vec3 lookat(0, 0, 0);
	vec3 up(0, 1, 0);

	mat4 view = lookAt(eye, lookat, up);
	mat4 proj = perspective(glm::radians(fov), (float)width / (float)height, 0.5f, 100.f);
	
	vector<mat4> models(objects.size());

	// Create primitive shading data
	const auto VS = reinterpret_cast<vertex_shader> (&VS_Simple);
	const auto FS = reinterpret_cast<fragment_shader> (&FS_Simple);

	UBO ubo;

	for (Primitive* prim : objects)
	{
		prim->setVS(VS);
		prim->setFS(FS);
		prim->UBO(&ubo);
	}

#ifdef SINGLE_FRAME_OUTPUT
	rasterizer->ClearBuffers();

	for (Primitive* prim : objects)
	{
		//model = rotate(model, 0.025f, vec3(0, 1, 0));
		mat4 mv = view * model;
		mat3 normal = { mv[0], mv[1], mv[2] };
		mat4 mvp = proj * mv;

		mat_ubo* ubo = static_cast<mat_ubo*> (prim->UBO());
		ubo->MVP = mvp;
		ubo->NORMAL = normal;

		rasterizer->Draw(prim);
	}

	const vector<vec4>& frameBuffer = rasterizer->getFrameBuffer();
	FILE *f = NULL;
	fopen_s(&f, "../render.ppm", "w");
	fprintf(f, "P3\n%d %d\n%d\n ", WIDTH, HEIGHT, 255);
	for (int32_t i = 0; i < WIDTH * HEIGHT; ++i)
	{
		uint r = (uint)(255 * frameBuffer[i].x);
		uint g = (uint)(255 * frameBuffer[i].y);
		uint b = (uint)(255 * frameBuffer[i].z);
		fprintf(f, "%d %d %d ", r, g, b);
	}
	fclose(f);

	printf("DONE\n");

#else
	// Init SDL
	Display display(width, height, DISPLAY_FULLSCREEN);

	SDL_Event event;
	bool running = true;
	bool paused = false;
	while (running)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
			case SDL_KEYDOWN:
				switch (event.key.keysym.scancode)
				{
				case SDL_SCANCODE_SPACE:
					paused = !paused;
					break;
				case SDL_SCANCODE_ESCAPE:
					running = false;
					break;
				default:
					break;
				}
				break;
			case SDL_KEYUP:
				break;
			case SDL_QUIT:
				running = false;
				break;
			default:
				break;
			}
		}

		const auto drawBegin = chrono::high_resolution_clock::now();
		if (!paused) // When unpaused, re-draw every frame
		{
			display.ClearRenderTarget(ivec3(0, 0, 0));

			// Pre-draw, invalidate frame and depth buffers
			rasterizer->ClearBuffers();

			for (size_t i = 0; i < objects.size(); i++)
			{
				Primitive* prim = objects[i];
				models[i] = rotate(models[i], 0.025f, vec3(0, 1, 0));
				mat4 mv = view * models[i];
				mat3 normal = { mv[0], mv[1], mv[2] };
				mat4 mvp = proj * mv;
{'fraction_non_alphanumeric': 0.15478752017213557, 'fraction_numerical': 0.027972027972027972, 'mean_word_length': 3.7189086294416245, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2163521', 'n_tokens_mistral': 3368, 'n_tokens_neox': 2962, 'n_words': 723}