31 QWidget* parent) : |
31 QWidget* parent) : |
32 QOpenGLWidget{parent}, |
32 QOpenGLWidget{parent}, |
33 model{model}, |
33 model{model}, |
34 documents{documents}, |
34 documents{documents}, |
35 colorTable{colorTable}, |
35 colorTable{colorTable}, |
36 compiler{new gl::Compiler{this->colorTable, this}} |
36 compiler{new gl::Compiler{this->colorTable, this}}, |
|
37 gridProgram{this} |
37 { |
38 { |
38 this->setMouseTracking(true); |
39 this->setMouseTracking(true); |
39 } |
40 } |
40 |
41 |
41 PartRenderer::~PartRenderer() |
42 PartRenderer::~PartRenderer() |
42 { |
43 { |
|
44 } |
|
45 |
|
46 static QVector3D vec3FromQColor(const QColor& color) |
|
47 { |
|
48 return {(float)color.redF(), (float)color.greenF(), (float)color.blueF()}; |
43 } |
49 } |
44 |
50 |
45 void PartRenderer::initializeGL() |
51 void PartRenderer::initializeGL() |
46 { |
52 { |
47 this->initializeOpenGLFunctions(); |
53 this->initializeOpenGLFunctions(); |
48 if (glGetError() != GL_NO_ERROR) |
54 if (glGetError() != GL_NO_ERROR) |
49 { |
55 { |
50 abort(); |
56 abort(); |
51 } |
57 } |
|
58 this->gridProgram.emplace(this); |
|
59 this->gridProgram->initialize(); |
52 this->compiler->initialize(); |
60 this->compiler->initialize(); |
53 this->compiler->build(this->model, this->documents, this->renderPreferences); |
61 this->compiler->build(this->model, this->documents, this->renderPreferences); |
54 this->initialized = true; |
62 this->initialized = true; |
55 this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); |
63 this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); |
56 this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); |
64 this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); |
65 glm::radians(45.0f), |
73 glm::radians(45.0f), |
66 static_cast<float>(width) / static_cast<float>(height), |
74 static_cast<float>(width) / static_cast<float>(height), |
67 0.1f, |
75 0.1f, |
68 10000.f); |
76 10000.f); |
69 this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix); |
77 this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix); |
|
78 this->gridProgram->setProjectionMatrix(this->projectionMatrix); |
70 } |
79 } |
71 |
80 |
72 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass) |
81 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass) |
73 { |
82 { |
74 switch (vboClass) |
83 switch (vboClass) |
86 |
95 |
87 void PartRenderer::paintGL() |
96 void PartRenderer::paintGL() |
88 { |
97 { |
89 glEnable(GL_DEPTH_TEST); |
98 glEnable(GL_DEPTH_TEST); |
90 glShadeModel(GL_SMOOTH); |
99 glShadeModel(GL_SMOOTH); |
91 glEnable(GL_MULTISAMPLE); |
|
92 this->renderScene(); |
100 this->renderScene(); |
93 } |
101 } |
94 |
102 |
95 static QVector3D vec3FromQColor(const QColor& color) |
|
96 { |
|
97 return {(float)color.redF(), (float)color.greenF(), (float)color.blueF()}; |
|
98 } |
|
99 |
|
100 void PartRenderer::renderScene() |
103 void PartRenderer::renderScene() |
101 { |
104 { |
|
105 this->checkForGLErrors(); |
102 if (this->renderPreferences.lineAntiAliasing && this->renderPreferences.style != gl::RenderStyle::PickScene) |
106 if (this->renderPreferences.lineAntiAliasing && this->renderPreferences.style != gl::RenderStyle::PickScene) |
103 { |
107 { |
104 glEnable(GL_LINE_SMOOTH); |
108 glEnable(GL_LINE_SMOOTH); |
105 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
109 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); |
106 } |
110 } |
120 else |
124 else |
121 { |
125 { |
122 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
126 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
123 this->compiler->setUniform("useLighting", GL_FALSE); |
127 this->compiler->setUniform("useLighting", GL_FALSE); |
124 } |
128 } |
|
129 this->checkForGLErrors(); |
125 this->compiler->setUniform("selectedColor", vec3FromQColor(this->renderPreferences.selectedColor)); |
130 this->compiler->setUniform("selectedColor", vec3FromQColor(this->renderPreferences.selectedColor)); |
126 this->compiler->setUniform("highlighted", this->highlighted.value); |
131 this->compiler->setUniform("highlighted", this->highlighted.value); |
127 this->checkForGLErrors(); |
132 this->checkForGLErrors(); |
128 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
133 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
129 glEnable(GL_DEPTH_TEST); |
134 glEnable(GL_DEPTH_TEST); |
162 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
167 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
163 this->setFragmentStyle(gl::FragmentStyle::Normal); |
168 this->setFragmentStyle(gl::FragmentStyle::Normal); |
164 this->renderAllArrays(); |
169 this->renderAllArrays(); |
165 break; |
170 break; |
166 } |
171 } |
|
172 glEnable(GL_BLEND); |
|
173 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
174 this->gridProgram->draw(); |
|
175 glDisable(GL_BLEND); |
167 glDisable(GL_POLYGON_OFFSET_FILL); |
176 glDisable(GL_POLYGON_OFFSET_FILL); |
168 } |
177 } |
169 |
178 |
170 void PartRenderer::renderAllArrays() |
179 void PartRenderer::renderAllArrays() |
171 { |
180 { |
180 { |
189 { |
181 // I'm not quite sure why using the exponent function on the zoom factor causes linear zoom behavior |
190 // I'm not quite sure why using the exponent function on the zoom factor causes linear zoom behavior |
182 const double z = 2 * std::exp(this->zoom) * (1 + this->compiler->modelDistance()); |
191 const double z = 2 * std::exp(this->zoom) * (1 + this->compiler->modelDistance()); |
183 this->viewMatrix = glm::lookAt(glm::vec3{0, 0, z}, {0, 0, 0}, {0, -1, 0}); |
192 this->viewMatrix = glm::lookAt(glm::vec3{0, 0, z}, {0, 0, 0}, {0, -1, 0}); |
184 this->compiler->setUniformMatrix("viewMatrix", this->viewMatrix); |
193 this->compiler->setUniformMatrix("viewMatrix", this->viewMatrix); |
|
194 this->gridProgram->setViewMatrix(this->viewMatrix); |
185 } |
195 } |
186 |
196 |
187 void PartRenderer::renderVao(const gl::ArrayClass arrayClass) |
197 void PartRenderer::renderVao(const gl::ArrayClass arrayClass) |
188 { |
198 { |
189 this->compiler->bindVertexArray(arrayClass); |
199 this->compiler->bindVertexArray(arrayClass); |
194 this->compiler->releaseVertexArray(arrayClass); |
204 this->compiler->releaseVertexArray(arrayClass); |
195 this->checkForGLErrors(); |
205 this->checkForGLErrors(); |
196 } |
206 } |
197 |
207 |
198 void PartRenderer::checkForGLErrors() |
208 void PartRenderer::checkForGLErrors() |
|
209 { |
|
210 gl::checkForGLErrors(this); |
|
211 } |
|
212 |
|
213 void gl::checkForGLErrors(QWidget* parent) |
199 { |
214 { |
200 GLenum glError; |
215 GLenum glError; |
201 QStringList errors; |
216 QStringList errors; |
202 while ((glError = glGetError()) != GL_NO_ERROR) |
217 while ((glError = glGetError()) != GL_NO_ERROR) |
203 { |
218 { |
204 const QString glErrorString = QString::fromLatin1(reinterpret_cast<const char*>(::gluErrorString(glError))); |
219 const QString glErrorString = QString::fromLatin1(reinterpret_cast<const char*>(::gluErrorString(glError))); |
205 errors.append(glErrorString); |
220 errors.append(glErrorString); |
206 } |
221 } |
207 if (not errors.isEmpty()) |
222 if (not errors.isEmpty()) |
208 { |
223 { |
209 QMessageBox box{this}; |
224 QMessageBox box{parent}; |
210 box.setIcon(QMessageBox::Critical); |
225 box.setIcon(QMessageBox::Critical); |
211 box.setText(tr("Failed to render: %1").arg(errors.join("\n"))); |
226 box.setText(QObject::tr("OpenGL error: %1").arg(errors.join("\n"))); |
212 box.setWindowTitle(tr("Rendering error")); |
227 box.setWindowTitle(QObject::tr("OpenGL error")); |
213 box.setStandardButtons(QMessageBox::Close); |
228 box.setStandardButtons(QMessageBox::Close); |
214 box.button(QMessageBox::Close)->setText(tr("Damn it")); |
229 box.button(QMessageBox::Close)->setText(QObject::tr("Damn it")); |
215 box.exec(); |
230 box.exec(); |
216 } |
231 } |
217 } |
232 } |
218 |
233 |
219 void PartRenderer::mouseMoveEvent(QMouseEvent* event) |
234 void PartRenderer::mouseMoveEvent(QMouseEvent* event) |
229 const float move_x = static_cast<float>(move.x()); |
244 const float move_x = static_cast<float>(move.x()); |
230 const float move_y = static_cast<float>(move.y()); |
245 const float move_y = static_cast<float>(move.y()); |
231 const glm::quat q_x = glm::angleAxis(scalar * move_x, glm::vec3{0, -1, 0}); |
246 const glm::quat q_x = glm::angleAxis(scalar * move_x, glm::vec3{0, -1, 0}); |
232 const glm::quat q_y = glm::angleAxis(scalar * move_y, glm::vec3{-1, 0, 0}); |
247 const glm::quat q_y = glm::angleAxis(scalar * move_y, glm::vec3{-1, 0, 0}); |
233 this->modelQuaternion = q_x * q_y * this->modelQuaternion; |
248 this->modelQuaternion = q_x * q_y * this->modelQuaternion; |
234 this->compiler->setUniformMatrix("modelMatrix", glm::mat4_cast(this->modelQuaternion)); |
249 const glm::mat4 modelMatrix = glm::mat4_cast(this->modelQuaternion); |
|
250 this->compiler->setUniformMatrix("modelMatrix", modelMatrix); |
|
251 this->gridProgram->setModelMatrix(modelMatrix); |
235 this->update(); |
252 this->update(); |
236 } |
253 } |
237 this->lastMousePosition = pointToPointF(event->pos()); |
254 this->lastMousePosition = pointToPointF(event->pos()); |
238 } |
255 } |
239 |
256 |