src/gl/partrenderer.cpp

changeset 61
4585d8d7a7ec
parent 60
0f221121849b
child 66
77c819262b7a
equal deleted inserted replaced
60:0f221121849b 61:4585d8d7a7ec
32 QWidget* parent) : 32 QWidget* parent) :
33 QOpenGLWidget{parent}, 33 QOpenGLWidget{parent},
34 model{model}, 34 model{model},
35 documents{documents}, 35 documents{documents},
36 colorTable{colorTable}, 36 colorTable{colorTable},
37 compiler{new gl::Compiler{this->colorTable, this}}, 37 compiler{new gl::Compiler{this->colorTable, this}}
38 gridProgram{this}
39 { 38 {
40 this->setMouseTracking(true); 39 this->setMouseTracking(true);
41 } 40 }
42 41
43 PartRenderer::~PartRenderer() 42 PartRenderer::~PartRenderer()
44 { 43 {
45 } 44 }
46 45
47 static QVector3D vec3FromQColor(const QColor& color) 46 static QVector3D vec3FromQColor(const QColor& color)
48 { 47 {
49 return {(float)color.redF(), (float)color.greenF(), (float)color.blueF()}; 48 return {
49 toFloat(color.redF()),
50 toFloat(color.greenF()),
51 toFloat(color.blueF()),
52 };
50 } 53 }
51 54
52 void PartRenderer::initializeGL() 55 void PartRenderer::initializeGL()
53 { 56 {
54 this->initializeOpenGLFunctions(); 57 this->initializeOpenGLFunctions();
55 if (glGetError() != GL_NO_ERROR) 58 if (glGetError() != GL_NO_ERROR)
56 { 59 {
57 abort(); 60 abort();
58 } 61 }
59 this->gridProgram.emplace(this);
60 this->gridProgram->initialize();
61 this->compiler->initialize(); 62 this->compiler->initialize();
62 this->compiler->build(this->model, this->documents, this->renderPreferences); 63 this->compiler->build(this->model, this->documents, this->renderPreferences);
63 this->initialized = true; 64 this->initialized = true;
64 this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0}); 65 this->modelQuaternion = glm::angleAxis(glm::radians(30.0f), glm::vec3{-1, 0, 0});
65 this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0}); 66 this->modelQuaternion *= glm::angleAxis(glm::radians(225.0f), glm::vec3{-0, 1, 0});
77 glm::radians(45.0f), 78 glm::radians(45.0f),
78 static_cast<float>(width) / static_cast<float>(height), 79 static_cast<float>(width) / static_cast<float>(height),
79 0.1f, 80 0.1f,
80 10000.f); 81 10000.f);
81 this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix); 82 this->compiler->setUniformMatrix("projectionMatrix", this->projectionMatrix);
82 this->gridProgram->setProjectionMatrix(this->projectionMatrix); 83 emit projectionMatrixChanged();
83 } 84 }
84 85
85 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass) 86 static GLenum getGlTypeForArrayClass(const gl::ArrayClass vboClass)
86 { 87 {
87 switch (vboClass) 88 switch (vboClass)
171 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 172 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
172 this->setFragmentStyle(gl::FragmentStyle::Normal); 173 this->setFragmentStyle(gl::FragmentStyle::Normal);
173 this->renderAllArrays(); 174 this->renderAllArrays();
174 break; 175 break;
175 } 176 }
176 glEnable(GL_BLEND);
177 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
178 this->gridProgram->draw();
179 glDisable(GL_BLEND);
180 glDisable(GL_POLYGON_OFFSET_FILL); 177 glDisable(GL_POLYGON_OFFSET_FILL);
181 } 178 }
182 179
183 void PartRenderer::renderAllArrays() 180 void PartRenderer::renderAllArrays()
184 { 181 {
193 { 190 {
194 // I'm not quite sure why using the exponent function on the zoom factor causes linear zoom behavior 191 // I'm not quite sure why using the exponent function on the zoom factor causes linear zoom behavior
195 const double z = 2 * std::exp(this->zoom) * (1 + this->compiler->modelDistance()); 192 const double z = 2 * std::exp(this->zoom) * (1 + this->compiler->modelDistance());
196 this->viewMatrix = glm::lookAt(glm::vec3{0, 0, z}, {0, 0, 0}, {0, -1, 0}); 193 this->viewMatrix = glm::lookAt(glm::vec3{0, 0, z}, {0, 0, 0}, {0, -1, 0});
197 this->compiler->setUniformMatrix("viewMatrix", this->viewMatrix); 194 this->compiler->setUniformMatrix("viewMatrix", this->viewMatrix);
198 this->gridProgram->setViewMatrix(this->viewMatrix); 195 emit this->viewMatrixChanged();
199 } 196 }
200 197
201 void PartRenderer::updateModelMatrix() 198 void PartRenderer::updateModelMatrix()
202 { 199 {
203 const glm::mat4 modelMatrix = glm::mat4_cast(this->modelQuaternion); 200 this->modelMatrix = glm::mat4_cast(this->modelQuaternion);
204 this->compiler->setUniformMatrix("modelMatrix", modelMatrix); 201 this->compiler->setUniformMatrix("modelMatrix", modelMatrix);
205 this->gridProgram->setModelMatrix(modelMatrix); 202 emit this->modelMatrixChanged();
206 this->update(); 203 this->update();
207 } 204 }
208 205
209 void PartRenderer::setupBackgroundColor() 206 void PartRenderer::setupBackgroundColor()
210 { 207 {
211 if (this->gridProgram.has_value())
212 {
213 const bool isDark = luma(this->renderPreferences.backgroundColor) < 0.25;
214 this->gridProgram->setGridColor(isDark ? Qt::white : Qt::black);
215 }
216 } 208 }
217 209
218 void PartRenderer::renderVao(const gl::ArrayClass arrayClass) 210 void PartRenderer::renderVao(const gl::ArrayClass arrayClass)
219 { 211 {
220 this->compiler->bindVertexArray(arrayClass); 212 this->compiler->bindVertexArray(arrayClass);
253 } 245 }
254 246
255 void PartRenderer::mouseMoveEvent(QMouseEvent* event) 247 void PartRenderer::mouseMoveEvent(QMouseEvent* event)
256 { 248 {
257 const bool left = event->buttons() & Qt::LeftButton; 249 const bool left = event->buttons() & Qt::LeftButton;
258 const QPointF move = pointToPointF(event->pos()) - this->lastMousePosition; 250 const QPoint move = event->pos() - this->lastMousePosition;
259 if (left and not move.isNull()) 251 if (left and not move.isNull())
260 { 252 {
261 // q_x is the rotation of the brick along the vertical y-axis, because turning the 253 // q_x is the rotation of the brick along the vertical y-axis, because turning the
262 // vertical axis causes horizontal (=x) rotation. Likewise q_y is the rotation of the 254 // vertical axis causes horizontal (=x) rotation. Likewise q_y is the rotation of the
263 // brick along the horizontal x-axis, which causes vertical rotation. 255 // brick along the horizontal x-axis, which causes vertical rotation.
267 const glm::quat q_x = glm::angleAxis(scalar * move_x, glm::vec3{0, -1, 0}); 259 const glm::quat q_x = glm::angleAxis(scalar * move_x, glm::vec3{0, -1, 0});
268 const glm::quat q_y = glm::angleAxis(scalar * move_y, glm::vec3{-1, 0, 0}); 260 const glm::quat q_y = glm::angleAxis(scalar * move_y, glm::vec3{-1, 0, 0});
269 this->modelQuaternion = q_x * q_y * this->modelQuaternion; 261 this->modelQuaternion = q_x * q_y * this->modelQuaternion;
270 this->updateModelMatrix(); 262 this->updateModelMatrix();
271 } 263 }
272 this->lastMousePosition = pointToPointF(event->pos()); 264 this->lastMousePosition = event->pos();
273 } 265 }
274 266
275 void PartRenderer::wheelEvent(QWheelEvent* event) 267 void PartRenderer::wheelEvent(QWheelEvent* event)
276 { 268 {
277 static constexpr double WHEEL_STEP = 1 / 1000.0; 269 static constexpr double WHEEL_STEP = 1 / 1000.0;
278 const double move = (-event->angleDelta().y()) * WHEEL_STEP; 270 const double move = (-event->angleDelta().y()) * WHEEL_STEP;
279 this->zoom = std::clamp(this->zoom + move, MIN_ZOOM, MAX_ZOOM); 271 this->zoom = std::clamp(this->zoom + move, MIN_ZOOM, MAX_ZOOM);
280 this->updateViewMatrix(); 272 this->updateViewMatrix();
281 this->update(); 273 this->update();
282 }
283
284 glm::vec3 PartRenderer::viewport(const glm::vec3& point)
285 {
286 return viewport(point, this->width(), this->height());
287 } 274 }
288 275
289 /** 276 /**
290 * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the 277 * @brief Converts the specified on the screen into the 3D world. The point is unprojected twice into 3D and the
291 * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind 278 * intersection of the resulting line with the specified plane is returned. If the intersection point lies behind
294 * @param plane Plane to raycast against 281 * @param plane Plane to raycast against
295 * @return world co-ordinates, or no value if the point is behind the camera. 282 * @return world co-ordinates, or no value if the point is behind the camera.
296 */ 283 */
297 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane) 284 std::optional<glm::vec3> PartRenderer::screenToModelCoordinates(const QPoint& point, const geom::Plane& plane)
298 { 285 {
299 auto p1 = this->unproject({point.x(), point.y(), 0}); 286 const glm::vec3 p1 = this->unproject({point.x(), point.y(), 0});
300 auto p2 = this->unproject({point.x(), point.y(), 1}); 287 const glm::vec3 p2 = this->unproject({point.x(), point.y(), 1});
301 geom::Line line = geom::lineFromPoints(p1, p2); 288 const geom::Line line = geom::lineFromPoints(p1, p2);
302 std::optional<glm::vec3> result; 289 std::optional<glm::vec3> result;
303 result = geom::linePlaneIntersection(line, plane, 0.01f); 290 result = geom::linePlaneIntersection(line, plane, 0.01f);
304 // If the point lies behind the camera, do not return a result. 291 // If the point lies behind the camera, do not return a result.
305 if (result.has_value() and glm::dot(line.direction, *result - p1) < 0) 292 if (result.has_value() and glm::dot(line.direction, *result - p1) < 0)
306 { 293 {
374 if (mainColorChanged or backgroundColorChanged) 361 if (mainColorChanged or backgroundColorChanged)
375 { 362 {
376 this->compiler->build(this->model, this->documents, this->renderPreferences); 363 this->compiler->build(this->model, this->documents, this->renderPreferences);
377 this->setupBackgroundColor(); 364 this->setupBackgroundColor();
378 } 365 }
379 this->update(); 366 emit this->renderPreferencesChanged();
380 } 367 this->update();
381 368 }
382 glm::vec3 PartRenderer::viewport(const glm::vec3& point, float width, float height)
383 {
384 return {
385 width * 0.5 * (point.x + 1),
386 height * 0.5 * (-point.y + 1),
387 0
388 };
389 }

mercurial