<commit_before>#include <polar/core/polar.h>
#include <polar/asset/shaderprogram.h>
#include <polar/system/renderer/gl32.h>
#include <polar/system/event.h>
#include <polar/system/asset.h>
#include <polar/system/integrator.h>
#include <polar/component/position.h>
#include <polar/component/orientation.h>
#include <polar/component/scale.h>
#include <polar/component/color.h>
#include <polar/component/text.h>
#include <polar/component/playercamera.h>
#include <polar/component/screenposition.h>

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
#endif

namespace polar { namespace system { namespace renderer {
	bool gl32::supported() {
		gl32 renderer(nullptr, {});
		try {
			renderer.initGL();
			GLint major, minor;
			if(!GL(glGetIntegerv(GL_MAJOR_VERSION, &major))) { debugmanager()->fatal("failed to get OpenGL major version"); }
			if(!GL(glGetIntegerv(GL_MINOR_VERSION, &minor))) { debugmanager()->fatal("failed to get OpenGL minor version"); }
			/* if OpenGL version is 3.2 or greater */
			if(!(major > 3 || (major == 3 && minor >= 2))) {
				std::stringstream msg;
				msg << "actual OpenGL version is " << major << '.' << minor;
				debugmanager()->fatal(msg.str());
			}
			return true;
		} catch(std::exception &) {
			return false;
		}
	}

	void gl32::initGL() {
		if(!SDL(SDL_Init(SDL_INIT_EVERYTHING))) { debugmanager()->fatal("failed to init SDL"); }
		if(!SDL(TTF_Init())) { debugmanager()->fatal("failed to init TTF"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3))) { debugmanager()->fatal("failed to set major version attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2))) { debugmanager()->fatal("failed to set minor version attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE))) { debugmanager()->fatal("failed to set profile mask attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1))) { debugmanager()->fatal("failed to set double buffer attribute"); }
		if(!SDL(window = SDL_CreateWindow("Polar Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height,
			SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)))) {
			debugmanager()->fatal("failed to create window");
		}
		if(!SDL(context = SDL_GL_CreateContext(window))) { debugmanager()->fatal("failed to create OpenGL context"); }
		if(!SDL(SDL_GL_SetSwapInterval(1))) { debugmanager()->critical("failed to set swap interval"); }

		if(!SDL(SDL_SetRelativeMouseMode(capture ? SDL_TRUE : SDL_FALSE))) { debugmanager()->fatal("failed to set relative mouse mode"); }

		/* set up controller joysticks */
		SDL_GameController *controller = nullptr;
		for(int i = 0; i < SDL_NumJoysticks(); ++i) {
			bool isGameCon;
			SDL(isGameCon = SDL_IsGameController(i));
			if(isGameCon) {
				debugmanager()->verbose("SDL detected controller #", i);
				SDL(controller = SDL_GameControllerOpen(i));
			}
		}
		SDL(SDL_GameControllerEventState(SDL_ENABLE));

		glewExperimental = GL_TRUE;
		GLenum err = glewInit();

		if(err != GLEW_OK) { debugmanager()->fatal("GLEW: glewInit failed"); }

		/* GLEW cals glGetString(EXTENSIONS) which
		 * causes GL_INVALID_ENUM on GL 3.2+ core contexts
		 */
		glGetError();

		GL(glDisable(GL_DEPTH_TEST));
		GL(glDisable(GL_BLEND));
		GL(glEnable(GL_CULL_FACE));
		GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
		GL(glCullFace(GL_BACK));
	}

	void gl32::init() {
		initGL();

		setclearcolor(Point4(0.0f));

		GL(glGenVertexArrays(1, &viewportVAO));
		GL(glBindVertexArray(viewportVAO));

		GLuint vbo;
		GL(glGenBuffers(1, &vbo));

		std::vector<glm::vec2> points = {
			Point2(-1, -1),
			Point2( 1, -1),
			Point2(-1,  1),
			Point2( 1,  1)
		};

		GL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
		GL(glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 4, points.data(), GL_STATIC_DRAW));
		GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL));

		GL(glEnableVertexAttribArray(0));

		debugmanager()->trace("MakePipeline from Init");
		makepipeline(pipelineNames);
		debugmanager()->trace("MakePipeline done");

		auto assetM = engine->getsystem<asset>().lock();
		spriteProgram = makeprogram(assetM->get<polar::asset::shaderprogram>("sprite"));

		inited = true;
	}

	void gl32::update(DeltaTicks &dt) {
		// upload changed uniforms
		for(size_t i = 0; i < nodes.size(); ++i) {
			bool usingProgram = false;
			auto &node = nodes[nodes.size() - 1 - i];
			for(auto &name : changedUniformsU32) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsU32[name]);
				}
			}
			for(auto &name : changedUniformsFloat) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsFloat[name]);
				}
			}
			for(auto &name : changedUniformsPoint3) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsPoint3[name]);
				}
			}
		}
		changedUniformsU32.clear();
		changedUniformsFloat.clear();
		changedUniformsPoint3.clear();

		fpsDtor = engine->addobject(&fpsID);

		if(dt.Seconds() > 0) {
			fps = glm::mix(fps, 1 / dt.Seconds(), Decimal(0.1));
		}

		if(showFPS) {
			std::ostringstream oss;
			oss << (int)fps << " fps";

			auto assetM = engine->getsystem<asset>().lock();
			auto font = assetM->get<polar::asset::font>("nasalization-rg");

			engine->addcomponent<component::text>(fpsID, font, oss.str());
			engine->addcomponent<component::screenposition>(fpsID, Point2(5, 5), support::ui::origin::topleft);
			engine->addcomponent<component::color>(fpsID, Point4(1, 1, 1, 0.8));
			engine->addcomponent<component::scale>(fpsID, Point3(0.125));
		}

		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			handleSDL(event);
		}
		SDL_ClearError();

		auto integrator_s = engine->getsystem<integrator>().lock();
		float alpha = integrator_s->alphaMicroseconds / 1000000.0f;

		Mat4 cameraView;
		auto pairRight = engine->objects.right.equal_range(&typeid(component::playercamera));
		for(auto itRight = pairRight.first; itRight != pairRight.second; ++itRight) {
			auto camera = static_cast<component::playercamera *>(itRight->info.get());

			component::position *pos = nullptr;
			component::orientation *orient = nullptr;

			auto pairLeft = engine->objects.left.equal_range(itRight->get_left());
			for(auto itLeft = pairLeft.first; itLeft != pairLeft.second; ++itLeft) {
				auto type = itLeft->get_right();
				if(type == &typeid(component::position)) {
					pos = static_cast<component::position *>(itLeft->info.get());
				} else if(type == &typeid(component::orientation)) {
					orient = static_cast<component::orientation *>(itLeft->info.get());
				}
			}

			cameraView = glm::translate(cameraView, -camera->distance.temporal(alpha).to<Point3>());
			cameraView *= glm::toMat4(camera->orientation);
			if(orient != nullptr) { cameraView *= glm::toMat4(orient->orient); }
			cameraView = glm::translate(cameraView, -camera->position.temporal(alpha).to<Point3>());
			if(pos != nullptr) { cameraView = glm::translate(cameraView, -pos->pos.temporal(alpha).to<Point3>()); }
		}

		std::unordered_map<std::string, GLuint> globals;
		for(unsigned int i = 0; i < nodes.size(); ++i) {
			auto &node = nodes[i];

			GL(glBindFramebuffer(GL_FRAMEBUFFER, node.fbo));
			GL(glUseProgram(node.program));
			GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

			uploaduniform(node.program, "u_view", cameraView);
			uploaduniform(node.program, "u_invViewProj", glm::inverse(CalculateProjection() * cameraView));

			switch(i) {
			case 0: {
				auto pairRight = engine->objects.right.equal_range(&typeid(component::model));
				for(auto itRight = pairRight.first; itRight != pairRight.second; ++itRight) {
					auto model = static_cast<component::model *>(itRight->info.get());
					component::position *pos = nullptr;
					component::orientation *orient = nullptr;

					auto pairLeft = engine->objects.left.equal_range(itRight->get_left());
					for(auto itLeft = pairLeft.first; itLeft != pairLeft.second; ++itLeft) {
						auto type = itLeft->get_right();
						if(type == &typeid(component::position)) {
							pos = static_cast<component::position *>(itLeft->info.get());
						} else if(type == &typeid(component::orientation)) {
							orient = static_cast<component::orientation *>(itLeft->info.get());
						}
					}

					auto property = model->get<model_p>().lock();
					if(property) {
						Mat4 modelMatrix;

						if(pos != nullptr) { modelMatrix = glm::translate(modelMatrix, pos->pos.temporal(alpha).to<Point3>()); }
						if(orient != nullptr) { modelMatrix *= glm::toMat4(glm::inverse(orient->orient)); }

						GLenum drawMode = GL_TRIANGLES;
						switch(model->type) {
						case GeometryType::Lines:
							drawMode = GL_LINES;
							break;
						case GeometryType::Triangles:
							drawMode = GL_TRIANGLES;
							break;<commit_msg>Take scale components into account for models<commit_after>#include <polar/core/polar.h>
#include <polar/asset/shaderprogram.h>
#include <polar/system/renderer/gl32.h>
#include <polar/system/event.h>
#include <polar/system/asset.h>
#include <polar/system/integrator.h>
#include <polar/component/position.h>
#include <polar/component/orientation.h>
#include <polar/component/scale.h>
#include <polar/component/color.h>
#include <polar/component/text.h>
#include <polar/component/playercamera.h>
#include <polar/component/screenposition.h>

#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
#endif

namespace polar { namespace system { namespace renderer {
	bool gl32::supported() {
		gl32 renderer(nullptr, {});
		try {
			renderer.initGL();
			GLint major, minor;
			if(!GL(glGetIntegerv(GL_MAJOR_VERSION, &major))) { debugmanager()->fatal("failed to get OpenGL major version"); }
			if(!GL(glGetIntegerv(GL_MINOR_VERSION, &minor))) { debugmanager()->fatal("failed to get OpenGL minor version"); }
			/* if OpenGL version is 3.2 or greater */
			if(!(major > 3 || (major == 3 && minor >= 2))) {
				std::stringstream msg;
				msg << "actual OpenGL version is " << major << '.' << minor;
				debugmanager()->fatal(msg.str());
			}
			return true;
		} catch(std::exception &) {
			return false;
		}
	}

	void gl32::initGL() {
		if(!SDL(SDL_Init(SDL_INIT_EVERYTHING))) { debugmanager()->fatal("failed to init SDL"); }
		if(!SDL(TTF_Init())) { debugmanager()->fatal("failed to init TTF"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3))) { debugmanager()->fatal("failed to set major version attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2))) { debugmanager()->fatal("failed to set minor version attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE))) { debugmanager()->fatal("failed to set profile mask attribute"); }
		if(!SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1))) { debugmanager()->fatal("failed to set double buffer attribute"); }
		if(!SDL(window = SDL_CreateWindow("Polar Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height,
			SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)))) {
			debugmanager()->fatal("failed to create window");
		}
		if(!SDL(context = SDL_GL_CreateContext(window))) { debugmanager()->fatal("failed to create OpenGL context"); }
		if(!SDL(SDL_GL_SetSwapInterval(1))) { debugmanager()->critical("failed to set swap interval"); }

		if(!SDL(SDL_SetRelativeMouseMode(capture ? SDL_TRUE : SDL_FALSE))) { debugmanager()->fatal("failed to set relative mouse mode"); }

		/* set up controller joysticks */
		SDL_GameController *controller = nullptr;
		for(int i = 0; i < SDL_NumJoysticks(); ++i) {
			bool isGameCon;
			SDL(isGameCon = SDL_IsGameController(i));
			if(isGameCon) {
				debugmanager()->verbose("SDL detected controller #", i);
				SDL(controller = SDL_GameControllerOpen(i));
			}
		}
		SDL(SDL_GameControllerEventState(SDL_ENABLE));

		glewExperimental = GL_TRUE;
		GLenum err = glewInit();

		if(err != GLEW_OK) { debugmanager()->fatal("GLEW: glewInit failed"); }

		/* GLEW cals glGetString(EXTENSIONS) which
		 * causes GL_INVALID_ENUM on GL 3.2+ core contexts
		 */
		glGetError();

		GL(glDisable(GL_DEPTH_TEST));
		GL(glDisable(GL_BLEND));
		GL(glEnable(GL_CULL_FACE));
		GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
		GL(glCullFace(GL_BACK));
	}

	void gl32::init() {
		initGL();

		setclearcolor(Point4(0.0f));

		GL(glGenVertexArrays(1, &viewportVAO));
		GL(glBindVertexArray(viewportVAO));

		GLuint vbo;
		GL(glGenBuffers(1, &vbo));

		std::vector<glm::vec2> points = {
			Point2(-1, -1),
			Point2( 1, -1),
			Point2(-1,  1),
			Point2( 1,  1)
		};

		GL(glBindBuffer(GL_ARRAY_BUFFER, vbo));
		GL(glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 4, points.data(), GL_STATIC_DRAW));
		GL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL));

		GL(glEnableVertexAttribArray(0));

		debugmanager()->trace("MakePipeline from Init");
		makepipeline(pipelineNames);
		debugmanager()->trace("MakePipeline done");

		auto assetM = engine->getsystem<asset>().lock();
		spriteProgram = makeprogram(assetM->get<polar::asset::shaderprogram>("sprite"));

		inited = true;
	}

	void gl32::update(DeltaTicks &dt) {
		// upload changed uniforms
		for(size_t i = 0; i < nodes.size(); ++i) {
			bool usingProgram = false;
			auto &node = nodes[nodes.size() - 1 - i];
			for(auto &name : changedUniformsU32) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsU32[name]);
				}
			}
			for(auto &name : changedUniformsFloat) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsFloat[name]);
				}
			}
			for(auto &name : changedUniformsPoint3) {
				if(node.uniforms.find(name) != node.uniforms.cend()) {
					if(!usingProgram) {
						GL(glUseProgram(node.program));
						usingProgram = true;
					}
					uploaduniform(node.program, name, uniformsPoint3[name]);
				}
			}
		}
		changedUniformsU32.clear();
		changedUniformsFloat.clear();
		changedUniformsPoint3.clear();

		fpsDtor = engine->addobject(&fpsID);

		if(dt.Seconds() > 0) {
			fps = glm::mix(fps, 1 / dt.Seconds(), Decimal(0.1));
		}

		if(showFPS) {
			std::ostringstream oss;
			oss << (int)fps << " fps";

			auto assetM = engine->getsystem<asset>().lock();
			auto font = assetM->get<polar::asset::font>("nasalization-rg");

			engine->addcomponent<component::text>(fpsID, font, oss.str());
			engine->addcomponent<component::screenposition>(fpsID, Point2(5, 5), support::ui::origin::topleft);
			engine->addcomponent<component::color>(fpsID, Point4(1, 1, 1, 0.8));
			engine->addcomponent<component::scale>(fpsID, Point3(0.125));
		}

		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			handleSDL(event);
		}
		SDL_ClearError();

		auto integrator_s = engine->getsystem<integrator>().lock();
		float alpha = integrator_s->alphaMicroseconds / 1000000.0f;

		Mat4 cameraView;
		auto pairRight = engine->objects.right.equal_range(&typeid(component::playercamera));
		for(auto itRight = pairRight.first; itRight != pairRight.second; ++itRight) {
			auto camera = static_cast<component::playercamera *>(itRight->info.get());

			component::position *pos = nullptr;
			component::orientation *orient = nullptr;
			component::scale *sc = nullptr;

			auto pairLeft = engine->objects.left.equal_range(itRight->get_left());
			for(auto itLeft = pairLeft.first; itLeft != pairLeft.second; ++itLeft) {
				auto type = itLeft->get_right();
				if(type == &typeid(component::position)) {
					pos = static_cast<component::position *>(itLeft->info.get());
				} else if(type == &typeid(component::orientation)) {
					orient = static_cast<component::orientation *>(itLeft->info.get());
				}
			}

			cameraView = glm::translate(cameraView, -camera->distance.temporal(alpha).to<Point3>());
			cameraView *= glm::toMat4(camera->orientation);
			if(orient != nullptr) { cameraView *= glm::toMat4(orient->orient); }
			cameraView = glm::translate(cameraView, -camera->position.temporal(alpha).to<Point3>());
			if(pos != nullptr) { cameraView = glm::translate(cameraView, -pos->pos.temporal(alpha).to<Point3>()); }
		}

		std::unordered_map<std::string, GLuint> globals;
		for(unsigned int i = 0; i < nodes.size(); ++i) {
			auto &node = nodes[i];

			GL(glBindFramebuffer(GL_FRAMEBUFFER, node.fbo));
			GL(glUseProgram(node.program));
			GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

			uploaduniform(node.program, "u_view", cameraView);
			uploaduniform(node.program, "u_invViewProj", glm::inverse(CalculateProjection() * cameraView));

			switch(i) {
			case 0: {
				auto pairRight = engine->objects.right.equal_range(&typeid(component::model));
				for(auto itRight = pairRight.first; itRight != pairRight.second; ++itRight) {
					auto model = static_cast<component::model *>(itRight->info.get());
					component::position *pos = nullptr;
					component::orientation *orient = nullptr;
					component::scale *sc = nullptr;

					auto pairLeft = engine->objects.left.equal_range(itRight->get_left());
					for(auto itLeft = pairLeft.first; itLeft != pairLeft.second; ++itLeft) {
						auto type = itLeft->get_right();
						if(type == &typeid(component::position)) {
							pos = static_cast<component::position *>(itLeft->info.get());
						} else if(type == &typeid(component::orientation)) {
							orient = static_cast<component::orientation *>(itLeft->info.get());
						} else if(type == &typeid(component::scale)) {
							sc = static_cast<component::scale *>(itLeft->info.get());
						}
					}

					auto property = model->get<model_p>().lock();
					if(property) {
						Mat4 modelMatrix;

						if(pos != nullptr)    { modelMatrix = glm::translate(modelMatrix, pos->pos.temporal(alpha).to<Point3>()); }
						if(orient != nullptr) { modelMatrix *= glm::toMat4(glm::inverse(orient->orient)); }
						if(sc != nullptr)     { modelMatrix = glm::scale(modelMatrix, sc->sc.temporal(alpha).to<Point3>()); }

						GLenum drawMode = GL_TRIANGLES;
						switch(model->type) {
						case GeometryType::Lines:
							drawMode = GL_LINES;
							break;
						case GeometryType::Triangles:
							drawMode = GL_TRIANGLES;
							break;
{'fraction_non_alphanumeric': 0.16403214646867847, 'fraction_numerical': 0.010804193943264677, 'mean_word_length': 4.66134377824646, 'pattern_counts': {'":': 0, '<': 105, '<?xml version=': 0, '>': 185, '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': '4804560', 'n_tokens_mistral': 7561, 'n_tokens_neox': 6307, 'n_words': 1110}