diff --git a/CMakeLists.txt b/CMakeLists.txt index 7612c35..80ff3cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ else() set(QGLEngine_MAJOR 1) set(QGLEngine_MINOR 2) - set(QGLEngine_REVISION 0) + set(QGLEngine_REVISION 1) set(QGLEngine_SUFFIX "rc") set(QGLEngine_COMPANY SHS) set(QGLEngine_DOMAIN org.SHS) diff --git a/src/core/core/glmesh.cpp b/src/core/core/glmesh.cpp index 585b7d7..64d591a 100644 --- a/src/core/core/glmesh.cpp +++ b/src/core/core/glmesh.cpp @@ -172,12 +172,24 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) { buffer_geom.load(f, data_.constData(), gsize); buffer_ind.bind(f); - if (geom_type == GL_TRIANGLES) { + switch (geom_type) { + case GL_TRIANGLES: buffer_ind.resize(f, tsize); buffer_ind.load(f, triangles_.constData(), tsize); - } else { + break; + case GL_LINES: buffer_ind.resize(f, lsize); buffer_ind.load(f, lines_.constData(), lsize); + break; + case GL_POINTS: { + QVector points; + points.resize(vertices_.size()); + for (int i = 0; i < vertices_.size(); ++i) + points[i] = i; + int psize = points.size() * sizeof(GLint); + buffer_ind.resize(f, psize); + buffer_ind.load(f, points.constData(), psize); + } break; } return !isEmpty(); @@ -192,10 +204,12 @@ void Mesh::draw(QOpenGLExtraFunctions * f, int count, int type) { VertexObject * vao = vaoByType(type); vao->bindBuffers(f, buffer_geom, buffer_ind); - if (geom_type == GL_TRIANGLES) - vao->draw(f, geom_type, triangles_.size() * 3, count); - else - vao->draw(f, geom_type, lines_.size() * 2, count); + switch (geom_type) { + case GL_TRIANGLES: vao->draw(f, geom_type, triangles_.size() * 3, count); break; + case GL_LINES: vao->draw(f, geom_type, lines_.size() * 2, count); break; + case GL_POINTS: vao->draw(f, geom_type, vertices_.size(), count); break; + default: break; + } } diff --git a/src/core/render/renderer.cpp b/src/core/render/renderer.cpp index c6fce3a..7bb0411 100644 --- a/src/core/render/renderer.cpp +++ b/src/core/render/renderer.cpp @@ -304,6 +304,24 @@ void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) { } +void Renderer::setConeShadowMatrix() { + auto cone_ll = cur_lights.value(Light::Cone); + for (int i = 0; i < cone_ll.size(); ++i) { + Light * l = cone_ll[i]; + QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm; + om.translate(-l->worldAim()); + vm.translate(0., 0., -l->distance()); + // vm.rotate(-roll_, 0., 0., 1.); + QMatrix4x4 pmat = l->worldTransform(); + pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; + vm *= pmat.inverted(); + auto vpm = pm * (vm * om); + l->view_proj_matrix = vpm; + l->shadow_matrix = mat_norm_to_tex_coord * vpm * mat_camera_fullview_inv; + } +} + + void Renderer::renderObjects(Scene & scene, RenderPass pass) { QOpenGLExtraFunctions * f = view; QMapIterator it(scene.geometries_used[pass]); @@ -403,20 +421,11 @@ void Renderer::renderConeShadows() { } depth_maps_cone.resize(f, view->shadow_map_size, cone_ll.size()); for (int i = 0; i < cone_ll.size(); ++i) { - Light * l = cone_ll[i]; - QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm; - om.translate(-l->worldAim()); - vm.translate(0., 0., -l->distance()); - // vm.rotate(-roll_, 0., 0., 1.); - QMatrix4x4 pmat = l->worldTransform(); - pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; - vm *= pmat.inverted(); - auto vpm = pm * (vm * om); + Light * l = cone_ll[i]; if (l->isCastShadows()) { - prog->setUniformValue("qgl_ViewProjMatrix", vpm); + prog->setUniformValue("qgl_ViewProjMatrix", l->view_proj_matrix); renderConeShadow(i, l); } - l->shadow_matrix = mat_norm_to_tex_coord * vpm * mat_camera_fullview_inv; } } } @@ -533,6 +542,9 @@ void Renderer::renderScene() { } phase.end(); + /// setup cone lights matrices + setConeShadowMatrix(); + if (view->shadows()) { /// cone shadows and shadow matrix phase.begin("shadows cone"); diff --git a/src/core/render/renderer.h b/src/core/render/renderer.h index cf1dbc8..6f36c42 100644 --- a/src/core/render/renderer.h +++ b/src/core/render/renderer.h @@ -116,6 +116,7 @@ public: protected: void fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass); + void setConeShadowMatrix(); void renderObjects(Scene & scene, RenderPass pass); void renderLight(int first_wr_buff, bool clear_only); void renderConeShadows(); diff --git a/src/core/scene/globject.h b/src/core/scene/globject.h index de1050b..9cd6ed6 100644 --- a/src/core/scene/globject.h +++ b/src/core/scene/globject.h @@ -319,7 +319,7 @@ public: float size; Type light_type; Framebuffer shadow_map; - QMatrix4x4 shadow_matrix; + QMatrix4x4 shadow_matrix, view_proj_matrix; Map light_map; }; diff --git a/src/core/view/qglview.cpp b/src/core/view/qglview.cpp index a7d82e2..a0a41cf 100644 --- a/src/core/view/qglview.cpp +++ b/src/core/view/qglview.cpp @@ -163,6 +163,8 @@ void QGLView::render() { if (!framebuffer_size.isEmpty()) render_size = framebuffer_size; resizeGL(render_size.width(), render_size.height()); emit glBeginPaint(); + glPointSize(lineWidth_); + glLineWidth(lineWidth_); QSizeF fbo_sz = renderer_.fbo_ds.size(); renderer_.rend_selection.size_coeff = {double(fbo_sz.width()) / pixelWidth(), double(fbo_sz.height()) / pixelHeight()}; renderer_.mouse_pos = mapFromGlobal(QCursor::pos()) * devicePixelRatio(); diff --git a/src/icons/dialog-information.png b/src/icons/dialog-information.png new file mode 100644 index 0000000..dfe70b9 Binary files /dev/null and b/src/icons/dialog-information.png differ diff --git a/src/widgets/materials_editor.cpp b/src/widgets/materials_editor.cpp index 28490c2..f3c81bf 100644 --- a/src/widgets/materials_editor.cpp +++ b/src/widgets/materials_editor.cpp @@ -118,6 +118,7 @@ void MaterialsEditor::materialsChanged() { return; } Material * cm = currentMaterial(); + ui->comboMaterial->blockSignals(true); ui->comboMaterial->clear(); if (!view) return; QVector mats = view->scene()->getMaterials(); @@ -128,6 +129,8 @@ void MaterialsEditor::materialsChanged() { ui->comboMaterial->setItemIcon(i, QIcon(QPixmap::fromImage(view->materialThumbnail(m)))); if (cm == m) ui->comboMaterial->setCurrentIndex(i); } + ui->comboMaterial->blockSignals(false); + if (currentMaterial() != cm) on_comboMaterial_currentIndexChanged(ui->comboMaterial->currentIndex()); } diff --git a/src/widgets/scene_tree.cpp b/src/widgets/scene_tree.cpp index 2c450e1..559ee88 100644 --- a/src/widgets/scene_tree.cpp +++ b/src/widgets/scene_tree.cpp @@ -19,11 +19,13 @@ #include "scene_tree.h" #include "glcamera.h" +#include "glmesh.h" #include "qglview.h" #include "ui_scene_tree.h" #include #include +#include #include #include #include @@ -110,9 +112,9 @@ QList SceneTree::actionsAdd() { QList SceneTree::actionsSelection() { QList ret; ret << ui->actionFocus << newSeparator() << ui->actionGroup << ui->actionClone << newSeparator() << ui->actionSelect_parent - << ui->actionSelect_by_mesh << ui->actionSelect_by_material << newSeparator() << ui->actionMove_to_parent - << ui->actionTransfer_transform_to_children << newSeparator() << ui->actionActive_camera << ui->actionDefault_camera - << newSeparator() << ui->actionRemove; + << ui->actionSelect_by_mesh << ui->actionSelect_by_material << newSeparator() << ui->actionMesh_info << newSeparator() + << ui->actionMove_to_parent << ui->actionTransfer_transform_to_children << newSeparator() << ui->actionActive_camera + << ui->actionDefault_camera << newSeparator() << ui->actionRemove; return ret; } @@ -310,6 +312,7 @@ void SceneTree::checkActions() { ui->actionSelect_parent->setEnabled(has_1); ui->actionSelect_by_mesh->setEnabled(has_mesh); ui->actionSelect_by_material->setEnabled(has_mesh); + ui->actionMesh_info->setEnabled(has_mesh); ui->actionActive_camera->setEnabled(has_cam); ui->actionDefault_camera->setEnabled(!is_def_cam); } @@ -507,6 +510,31 @@ void SceneTree::on_actionSelect_by_material_triggered() { } +void SceneTree::on_actionMesh_info_triggered() { + if (!view) return; + ObjectBaseList sol = view->scene()->selectedObjects(true); + for (auto o: sol) { + if (o->mesh()) { + auto m = o->mesh(); + int objects = 0; + ObjectBaseList aol = view->scene()->objects(true); + for (auto i: aol) + if (i->mesh() == m) ++objects; + + auto bb = o->mesh()->boundingBox(); + QString info; + QTextStream ts(&info); + ts << "Vertices: " << m->verticesCount() << "\n"; + ts << "Triangles: " << m->trianglesCount() << "\n"; + ts << "Bounding box: " << bb.length << "x" << bb.width << "x" << bb.height << "\n"; + ts << "Objects with this mesh: " << objects << "\n"; + QMessageBox::information(nullptr, tr("Mesh info"), info); + break; + } + } +} + + void SceneTree::removeObjects() { if (!view) return; QAD::CursorOverrider curov; diff --git a/src/widgets/scene_tree.h b/src/widgets/scene_tree.h index 8375d27..4ff7dff 100644 --- a/src/widgets/scene_tree.h +++ b/src/widgets/scene_tree.h @@ -88,6 +88,8 @@ private slots: void on_actionSelect_by_mesh_triggered(); void on_actionSelect_by_material_triggered(); + void on_actionMesh_info_triggered(); + void objectsTreeChanged(); void selectionChanged(); void materialsChanged(); diff --git a/src/widgets/scene_tree.ui b/src/widgets/scene_tree.ui index 238752a..4a5549b 100644 --- a/src/widgets/scene_tree.ui +++ b/src/widgets/scene_tree.ui @@ -130,7 +130,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -175,7 +175,7 @@ - + :/icons/type-geo.png:/icons/type-geo.png @@ -235,7 +235,7 @@ true - + :/icons/type-geo.png:/icons/type-geo.png @@ -247,7 +247,7 @@ true - + :/icons/type-light.png:/icons/type-light.png @@ -259,7 +259,7 @@ true - + :/icons/type-camera.png:/icons/type-camera.png @@ -273,7 +273,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -282,7 +282,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -298,6 +298,15 @@ Move to parent + + + + :/icons/dialog-information.png:/icons/dialog-information.png + + + Mesh info ... + + @@ -312,9 +321,9 @@ + - diff --git a/src/widgets/view_editor.cpp b/src/widgets/view_editor.cpp index 4714b4f..7ad305e 100644 --- a/src/widgets/view_editor.cpp +++ b/src/widgets/view_editor.cpp @@ -70,6 +70,7 @@ void ViewEditor::assignQGLView(QGLView * v) { ui->checkSoftShadows->setChecked(view->softShadows()); ui->spinSoftShadowSamples->setValue(view->softShadowsSamples()); ui->spinSoftShadowQuality->setValue(view->softShadowsQuality()); + ui->spinLineWidth->setValue(view->lineWidth()); auto setMapSize = [](QComboBox * combo, QSize sz) { for (int i = 0; i < combo->count(); ++i) { if (combo->itemData(i).toSize() == sz) { @@ -268,6 +269,12 @@ void ViewEditor::on_spinSoftShadowQuality_valueChanged(double arg1) { } +void ViewEditor::on_spinLineWidth_valueChanged(double v) { + if (!view || !active) return; + view->setLineWidth(v); +} + + void ViewEditor::on_checkVSync_clicked(bool val) { if (!view || !active) return; view->setVSync(val); diff --git a/src/widgets/view_editor.h b/src/widgets/view_editor.h index ffaa22f..2ad53c5 100644 --- a/src/widgets/view_editor.h +++ b/src/widgets/view_editor.h @@ -72,6 +72,7 @@ private slots: void on_checkSoftShadows_clicked(bool arg1); void on_spinSoftShadowSamples_valueChanged(double arg1); void on_spinSoftShadowQuality_valueChanged(double arg1); + void on_spinLineWidth_valueChanged(double v); }; #endif // VIEW_EDITOR_H diff --git a/src/widgets/view_editor.ui b/src/widgets/view_editor.ui index 2f39eb8..ab1029c 100644 --- a/src/widgets/view_editor.ui +++ b/src/widgets/view_editor.ui @@ -7,7 +7,7 @@ 0 0 479 - 897 + 976 @@ -37,7 +37,7 @@ 0 0 479 - 897 + 976 @@ -161,6 +161,30 @@ + + + + FXAA + + + + + + + VSync + + + true + + + + + + + Auto exposure + + + @@ -181,30 +205,6 @@ - - - - FXAA - - - - - - - Auto exposure - - - - - - - VSync - - - true - - - @@ -253,6 +253,50 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Line width: + + + + + + + 1 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + diff --git a/src/widgets/widgets.qrc b/src/widgets/widgets.qrc index 86c45f5..4fc665d 100644 --- a/src/widgets/widgets.qrc +++ b/src/widgets/widgets.qrc @@ -15,5 +15,6 @@ ../icons/group.png ../icons/legend.png ../icons/format-fill-color.png + ../icons/dialog-information.png