src/layers/axeslayer.cpp

Tue, 11 Apr 2023 22:39:18 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Tue, 11 Apr 2023 22:39:18 +0300
changeset 376
3cef3b016330
parent 264
76a025db4948
child 377
e1c5e4310f8b
permissions
-rw-r--r--

Split GL preferences that affect GL build to a new build preferences structure, modifying that requires rebuild, modifying render preferences does not

/*
 *  LDForge: LDraw parts authoring CAD
 *  Copyright (C) 2020 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/>.
 */

#include <QPainter>
#include <QPainterPath>
#include "src/gl/partrenderer.h"
#include "src/layers/axeslayer.h"

static constexpr char vertexShaderSource[] = R"(
#version 330 core

layout (location = 0) in vec3 in_position;
layout (location = 1) in vec3 in_color;
uniform mat4 mvp;
smooth out vec3 ex_color;

void main()
{
	gl_Position = mvp * vec4(in_position, 1.0);
	ex_color = in_color;
}
)";

static constexpr char fragmentShaderSource[] = R"(
#version 330 core

out vec4 color;
smooth in vec3 ex_color;

void main(void)
{
	color = vec4(ex_color, 1);
}
)";

void AxesLayer::initializeGL()
{
	constexpr struct VertexType
	{
		glm::vec3 position;
		glm::vec3 color;
	} data[] = {
		{{10000, 0, 0}, {1, 0, 0}},
		{{0, 0, 0}, {1, 0, 0}},
		{{-10000, 0, 0}, {0.5, 0, 0}},
		{{0, 0, 0}, {0.5, 0, 0}},
		{{0, 10000, 0}, {0, 1, 0}},
		{{0, 0, 0}, {0, 1, 0}},
		{{0, -10000, 0}, {0, 0.5, 0}},
		{{0, 0, 0}, {0, 0.5, 0}},
		{{0, 0, 10000}, {0, 0, 1}},
		{{0, 0, 0}, {0, 0, 1}},
		{{0, 0, -10000}, {0, 0, 0.5}},
		{{0, 0, 0}, {0, 0, 0.5}},
	};
	constexpr int stride = sizeof(VertexType);
	this->shader.initialize(
		::vertexShaderSource,
		::fragmentShaderSource,
		QOpenGLBuffer::StaticDraw,
		{
			GLAttributeSpec{
				.type = GL_FLOAT,
				.offset = offsetof(VertexType, position),
				.tuplesize = 3,
				.stride = stride,
			},
			{
				.type = GL_FLOAT,
				.offset = offsetof(VertexType, color),
				.tuplesize = 3,
				.stride = stride,
			},
		});
	this->shader.bufferData(&data[0], countof(data), sizeof data[0]);
}

void AxesLayer::overpaint(QPainter* painter)
{
	painter->save();
	QFont font;
	font.setStyle(QFont::StyleItalic);
	font.setBold(true);
	painter->setFont(font);
	QFontMetrics fontMetrics{font};
	const auto renderText = [&](const QString& text, const PointOnRectagle& intersection)
	{
		QPointF position = toQPointF(intersection.position);
		const RectangleSide side = intersection.side;
		switch (side)
		{
		case RectangleSide::Top:
			position += QPointF{0, static_cast<qreal>(fontMetrics.ascent())};
			break;
		case RectangleSide::Left:
			break;
		case RectangleSide::Bottom:
			position += QPointF{0, static_cast<qreal>(-fontMetrics.descent())};
			break;
		case RectangleSide::Right:
			position += QPointF{static_cast<qreal>(-fontMetrics.horizontalAdvance(text)), 0};
			break;
		}
		drawBorderedText(painter, position, font, text);
	};
	const QRectF box {QPointF{0, 0}, sizeToSizeF(this->renderer->size())};
	const QPointF p1 = this->renderer->modelToScreenCoordinates(glm::vec3{0, 0, 0});
	static const struct
	{
		QString text;
		glm::vec3 direction;
	} directions[] =
	{
		{"+x", {1, 0, 0}},
		{"-x", {-1, 0, 0}},
		{"+y", {0, 1, 0}},
		{"-y", {0, -1, 0}},
		{"+z", {0, 0, 1}},
		{"-z", {0, 0, -1}},
	};
	for (const auto& axis : directions)
	{
		const QPointF x_p = this->renderer->modelToScreenCoordinates(axis.direction);
		const auto intersection = rayRectangleIntersection(
			rayFromPoints(toVec2(p1), toVec2(x_p)),
			box);
		if (intersection.has_value())
		{
			renderText(axis.text, *intersection);
		}
	}
	painter->restore();
}

void AxesLayer::paintGL()
{
	glLineWidth(5);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	this->shader.draw(GL_LINES);
	glDisable(GL_LINE_SMOOTH);
}

void AxesLayer::mvpMatrixChanged(const glm::mat4& mvpMatrix)
{
	this->shader.setMvpMatrix(mvpMatrix);
}

mercurial