src/gl/partrenderer.h

Thu, 15 Jun 2023 16:18:03 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Thu, 15 Jun 2023 16:18:03 +0300
changeset 383
530d23cd4e97
parent 382
94d5587bb0c4
permissions
-rw-r--r--

Refactor, make selecting elements from the model select the corresponding line from the editor as well

#pragma once
#include "src/basics.h"
#include "src/documentmanager.h"
#include "src/types/boundingbox.h"
#include "src/gl/common.h"
#include "src/gl/compiler.h"
#include <QOpenGLWidget>

class PartRenderer final : public QOpenGLWidget
{
	Q_OBJECT
	QTextDocument* const model;
	DocumentManager* const documents;
	const ColorTable& colorTable;
	BoundingBox boundingBox;
	gl::ModelShaders shaders;
	ModelId highlighted = {0};
	glm::mat4 projectionMatrix;
	glm::mat4 viewMatrix;
	glm::mat4 modelMatrix;
	glm::vec4 viewportVector;
	glm::quat modelQuaternion;
	glm::vec3 modelViewOrigin = {0, 0, 0};
	QPoint lastMousePosition;
	int totalMouseMove = 0;
	double zoom = 1.0;
	bool initialized = false;
	bool needBuild = true;
	std::vector<RenderLayer*> activeRenderLayers;
	std::vector<RenderLayer*> inactiveRenderLayers;
	std::chrono::time_point<std::chrono::steady_clock> lastClickTime;
	bool frozen = false;
public:
	static const gl::RenderPreferences default_render_preferences;
	static const gl::build_preferences default_build_preferences;
	const gl::RenderPreferences* render_preferences = &PartRenderer::default_render_preferences;
	const gl::build_preferences* build_preferences = &PartRenderer::default_build_preferences;
	PartRenderer(
		QTextDocument* model,
		DocumentManager* documents,
		const ColorTable& colorTable,
		QWidget* parent = nullptr);
	~PartRenderer() override;
	ModelId getHighlightedObject() const;
	void addRenderLayer(RenderLayer* layer);
	void setLayerEnabled(RenderLayer* layer, bool enabled);
	std::optional<glm::vec3> screenToModelCoordinates(const QPointF& point, const Plane& plane) const;
	QPointF modelToScreenCoordinates(const glm::vec3& point) const;
	bool isDark() const;
	std::int32_t pick(QPoint where);
	void setSelection(const QSet<std::int32_t>& selectedIds);
	glm::vec3 cameraVector(const QPointF& point) const;
	Line<3> cameraLine(const QPointF& point) const;
	Q_SLOT void setModelViewOrigin(const glm::vec3& newViewOrigin);
	Q_SLOT void build();
Q_SIGNALS:
	void projectionMatrixChanged(const glm::mat4& newMatrix);
	void modelMatrixChanged(const glm::mat4& newMatrix);
	void viewMatrixChanged(const glm::mat4& newMatrix);
	void message(const Message& message);
private:
	void initializeGL() override;
	void resizeGL(int width, int height) override;
	void paintGL() override;
	void mouseMoveEvent(QMouseEvent* event) override;
	void mousePressEvent(QMouseEvent* event) override;
	void mouseReleaseEvent(QMouseEvent* event) override;
	void keyReleaseEvent(QKeyEvent* event) override;
	void wheelEvent(QWheelEvent* event) override;
	glm::vec3 unproject(const glm::vec3& win) const;
	void setFragmentStyle(gl::FragmentStyle fragStyle);
	void renderScene(const gl::RenderPreferences* preferences);
	void updateViewMatrix();
	void updateModelMatrix();
	void renderVao(const gl::ArrayClass arrayClass, const GLenum glType);
	template<gl::ArrayClass arrayClass>
	void renderVao();
	void checkForGLErrors();
};

inline constexpr opt<GLenum> getGlTypeForArrayClass(const gl::ArrayClass vboClass)
{
	switch (vboClass)
	{
	case gl::ArrayClass::Lines:
	case gl::ArrayClass::ConditionalLines:
		return GL_LINES;
	case gl::ArrayClass::Triangles:
		return GL_TRIANGLES;
	case gl::ArrayClass::Quads:
		return GL_QUADS;
	}
	return {};
}

template<gl::ArrayClass arrayClass>
void PartRenderer::renderVao()
{
	constexpr opt<GLenum> glType = getGlTypeForArrayClass(arrayClass);
	static_assert(glType.has_value());
	this->renderVao(arrayClass, *glType);
}

inline QVector<QPointF> convertWorldPointsToScreenPoints(
	const std::vector<glm::vec3> &worldPoints,
	const PartRenderer* renderer)
{
	QVector<QPointF> points2d;
	points2d.reserve(static_cast<int>(worldPoints.size()));
	for (const glm::vec3& point : worldPoints)
	{
		points2d.push_back(renderer->modelToScreenCoordinates(point));
	}
	return points2d;
}

inline winding_e worldPolygonWinding(
	const std::vector<glm::vec3> &points,
	const PartRenderer* renderer)
{
	return calculate_polygon_winding(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
}

inline void drawWorldPoint(
	QPainter* painter,
	const glm::vec3& worldPoint,
	const PartRenderer* renderer)
{
	const QPointF center = renderer->modelToScreenCoordinates(worldPoint);
	painter->drawEllipse(inscribe(CircleF{center, 5}));
}

inline void drawWorldPolyline(
	QPainter *painter,
	const std::vector<glm::vec3> &points,
	const PartRenderer* renderer)
{
	painter->drawPolyline(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
}

inline void drawWorldPolygon(
	QPainter* painter,
	const std::vector<glm::vec3> &points,
	const PartRenderer* renderer)
{
	painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
}

mercurial