Tue, 28 Sep 2021 23:07:23 +0300
Use QSaveFile to save the file more safely
/* * 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 <QWidget> #include <QColor> #include <QOpenGLBuffer> #include <QOpenGLFunctions> #include <QOpenGLShader> #include <QOpenGLShaderProgram> #include <QOpenGLVertexArrayObject> #include <glm/gtc/type_ptr.hpp> #include "basics.h" #include "colors.h" namespace gl { struct Polygon; class ShaderProgram; void buildShaders( QOpenGLShaderProgram* shaderProgram, const char* vertexShaderSource, const char* fragmentShaderSource); void checkForGLErrors(QWidget* parent); inline glm::vec3 colorToVector3(const QColor& color) { return {toFloat(color.redF()), toFloat(color.greenF()), toFloat(color.blueF())}; } inline glm::vec4 colorToVector4(const QColor& color) { return {gl::colorToVector3(color), toFloat(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); } }; struct gl::Polygon { enum Type : qint8 { EdgeLine, Triangle, Quadrilateral, ConditionalEdge } type; glm::vec3 vertices[4]; ldraw::Color color; ldraw::id_t id; /** * @return amount of vertices used for geometry */ inline unsigned int numPolygonVertices() const { if (type == Type::ConditionalEdge) return 2; else return numVertices(); } /** * @return amount of vertices */ inline unsigned int numVertices() const { switch (type) { case Type::EdgeLine: return 2; case Type::Triangle: return 3; case Type::ConditionalEdge: case Type::Quadrilateral: return 4; } return 0; } }; Q_DECLARE_METATYPE(gl::Polygon) namespace gl { constexpr Polygon::Type POLYGON_TYPES[] = { Polygon::Type::EdgeLine, Polygon::Type::Triangle, Polygon::Type::Quadrilateral, Polygon::Type::ConditionalEdge }; constexpr int NUM_POLYGON_TYPES = countof(POLYGON_TYPES); inline Polygon edgeLine(const glm::vec3& v_1, const glm::vec3& v_2, ldraw::Color color, ldraw::id_t id) { return {Polygon::EdgeLine, {v_1, v_2}, color, id}; } inline Polygon triangle( const glm::vec3& v_1, const glm::vec3& v_2, const glm::vec3& v_3, ldraw::Color color, ldraw::id_t id) { return {Polygon::Triangle, {v_1, v_2, v_3}, color, id}; } inline Polygon quadrilateral( const glm::vec3& v_1, const glm::vec3& v_2, const glm::vec3& v_3, const glm::vec3& v_4, ldraw::Color color, ldraw::id_t id) { return {Polygon::Quadrilateral, {v_1, v_2, v_3, v_4}, color, id}; } inline Polygon conditionalEdge( const glm::vec3& v_1, const glm::vec3& v_2, const glm::vec3& control_1, const glm::vec3& control_2, ldraw::Color color, ldraw::id_t id) { return {Polygon::ConditionalEdge, {v_1, v_2, control_1, control_2}, color, id}; } // Vbo names enum class ArrayClass : std::uint8_t { Lines, Triangles, Quads, ConditionalLines }; constexpr ArrayClass ARRAY_CLASSES[] = { ArrayClass::Lines, ArrayClass::Triangles, ArrayClass::Quads, ArrayClass::ConditionalLines, }; constexpr int NUM_ARRAY_CLASSES = countof(ARRAY_CLASSES); // Different ways to render the scene enum class RenderStyle { // Normal rendering style Normal, // Render all polygons as lines Wireframe, // 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; }; }