src/gl/common.h

Fri, 01 Jul 2022 16:46:43 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Fri, 01 Jul 2022 16:46:43 +0300
changeset 312
2637134bc37c
parent 291
42b4953dff85
child 376
3cef3b016330
permissions
-rw-r--r--

Fix right click to delete not really working properly
Instead of removing the point that had been added, it would remove
the point that is being drawn, which would cause it to overwrite the
previous point using the new point, causing a bit of a delay

/*
 *  LDForge: LDraw parts authoring CAD
 *  Copyright (C) 2013 - 2018 Teemu Piippo
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <GL/glew.h>
#include <QWidget>
#include <QColor>
#include <QOpenGLBuffer>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <glm/gtc/type_ptr.hpp>
#include "src/basics.h"
#include "src/colors.h"
#include "src/model.h"

class RenderLayer
{
protected:
	class PartRenderer* renderer;
public:
	virtual ~RenderLayer(){}
	virtual void initializeGL(){}
	virtual void paintGL(){}
	virtual void overpaint(QPainter*){}
	virtual void mvpMatrixChanged(const glm::mat4& mvpMatrix) = 0;
	virtual void mouseMoved(const QMouseEvent*){}
	virtual void mouseClick(const QMouseEvent*){}
	void setRendererPointer(class PartRenderer* newRenderer)
	{
		this->renderer = newRenderer;
	}
};

namespace gl
{
	class ShaderProgram;

	void buildShaders(
		QOpenGLShaderProgram* shaderProgram,
		const char* vertexShaderSource,
		const char* fragmentShaderSource);
	void checkForGLErrors(QWidget* parent);
	inline glm::vec3 colorToVector3(const QColor& color)
	{
		return {float_cast(color.redF()), float_cast(color.greenF()), float_cast(color.blueF())};
	}
	inline glm::vec4 colorToVector4(const QColor& color)
	{
		return {gl::colorToVector3(color), float_cast(color.alphaF())};
	}
}

class gl::ShaderProgram : public QOpenGLShaderProgram
{
public:
	using QOpenGLShaderProgram::QOpenGLShaderProgram;
	// for some reason I cannot overload setUniformValue properly with this template thing
	template<typename Float, glm::qualifier Prec>
	void setUniformMatrix(const char* uniformName, const glm::mat<4, 4, Float, Prec>& value)
	{
		const float (*array)[4][4] = reinterpret_cast<const float(*)[4][4]>(glm::value_ptr(value));
		this->setUniformValue(uniformName, *array);
	}
	template<typename Float, glm::qualifier Prec>
	void setUniformVector(const char* uniformName, const glm::vec<4, Float, Prec>& value)
	{
		this->setUniformValue(uniformName, value.x, value.y, value.z, value.w);
	}
};

namespace gl
{
	// Different ways to render the scene
	enum class RenderStyle
	{
		// Normal rendering style
		Normal,
		// Use green colour for front faces and red colour for back faces
		BfcRedGreen,
		// Use a different colour for each object
		RandomColors,
		// Render so that the colour of an object has an one to one correspondence with its id
		PickScene,
		// Render a scene where vertices can be picked
		VertexPickScene,
	};
	
	// Different ways to render fragments.
	// These are also defined in shaders
	enum class FragmentStyle
	{
		// Use normal colours
		Normal = 0,
		// Use a distinctive green colour for BFC red/green view
		BfcGreen = 1,
		// Use a distinctive red colour for BFC red/green view
		BfcRed = 2,
		// Use a colour based on the object to distinguish objects
		RandomColors = 3,
		// Use a colour that codes the object's id
		Id = 4,
		// Render everything black
		Black = 5,
	};

	// User options for rendering
	struct RenderPreferences
	{
		gl::RenderStyle style = gl::RenderStyle::Normal;
		QColor mainColor{255, 255, 64};
		QColor backgroundColor{48, 48, 48};
		QColor selectedColor{32, 32, 255};
		GLfloat lineThickness = 2.0f;
		bool lineAntiAliasing = true;
		bool drawAxes = true;
		bool wireframe = false;
	};
}

Q_DECLARE_METATYPE(gl::RenderStyle)

inline QDataStream &operator<<(QDataStream& stream, const gl::RenderStyle style)
{
	return stream << enum_value_cast(style);
}

inline QDataStream &operator>>(QDataStream& stream, gl::RenderStyle& style)
{
	return stream >> enum_value_cast(style);
}

constexpr glm::vec3 idToColor(std::int32_t id)
{
	const int r = (id & 0x0000ff) >> 0;
	const int g = (id & 0x00ff00) >> 8;
	const int b = (id & 0xff0000) >> 16;
	return {
		static_cast<float>(r) / 255.0f,
		static_cast<float>(g) / 255.0f,
		static_cast<float>(b) / 255.0f,
	};
}

#include <QPainter>
#include <QPainterPath>
inline void drawBorderedText(QPainter* painter, const QPointF& point, const QFont& font, const QString& text)
{
	QPainterPath path;
	path.addText(point, font, text);
	painter->save();
	painter->setBrush(Qt::white);
	painter->setPen({Qt::black, 0.1 * font.pointSizeF()});
	painter->drawPath(path);
	painter->restore();
}

mercurial