diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c9f2df..224e402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,62 +1,68 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) project(atelier) find_package(ECM REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(KDECompilerSettings) include(KDEInstallDirs) include(KDECMakeSettings) include(ECMInstallIcons) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(QT_MIN_VERSION "5.9.0") set(KF5_DEP_VERSION "5.30.0") set(KDE_APPLICATIONS_VERSION_MAJOR "1") set(KDE_APPLICATIONS_VERSION_MINOR "0") set(KDE_APPLICATIONS_VERSION_MICRO "0") set(KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") endif() #Atelier Dependencies find_package(AtCore REQUIRED COMPONENTS AtCore ) find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS Solid I18n XmlGui ConfigWidgets TextEditor ) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Widgets SerialPort Charts + Quick + Qml + 3DCore + 3DExtras + 3DRender + 3DInput ) if(BUILD_TESTING) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) endif() # config.h configure_file (config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/src/config.h) include(ECMPoQmTools) include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(src) add_subdirectory(deploy) if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ecm_install_po_files_as_qm(po) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cedfa26..1780bab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,17 +1,17 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTORCC ON) set(atelier_SRCS main.cpp mainwindow.cpp ) add_subdirectory(dialogs) add_subdirectory(widgets) add_executable(atelier ${atelier_SRCS} icons.qrc) ecm_create_qm_loader(atelier_SRCS atelier) -target_link_libraries(atelier AtelierWidgets AtelierDialogs AtCore::AtCore KF5::Solid KF5::XmlGui KF5::ConfigWidgets) +target_link_libraries(atelier AtelierWidgets AtelierDialogs Atelier3D AtCore::AtCore KF5::Solid KF5::XmlGui KF5::ConfigWidgets) install(TARGETS atelier RUNTIME DESTINATION bin) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ca38a1f..24534ff 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,356 +1,357 @@ /* Atelier KDE Printer Host for 3D Printing Copyright (C) <2016> Author: Lays Rodrigues - laysrodrigues@gmail.com Chris Rizzitello - rizzitello@kde.org 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 . */ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent), ui(new Ui::MainWindow), profilesDialog(new ProfilesDialog(this)), connectSettingsDialog(new ConnectSettingsDialog(this)) { ui->setupUi(this); logWidget = new LogWidget; setupActions(); initConnectsToAtCore(); initWidgets(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initConnectsToAtCore() { // Start Connection to the 3DPrinter connect(connectSettingsDialog, &ConnectSettingsDialog::startConnection, [ = ](QString port, QMap data) { core.initSerial(port, data["bps"].toInt()); }); // Handle AtCore status change connect(&core, &AtCore::stateChanged, this, &MainWindow::handlePrinterStatusChanged); // If the number of extruders from the printer change, we need to update the radiobuttons on the widget connect(this, &MainWindow::extruderCountChanged, ui->bedExtWidget, &BedExtruderWidget::setExtruderCount); // Bed and Extruder temperatures management connect(ui->bedExtWidget, &BedExtruderWidget::bedTemperatureChanged, &core, &AtCore::setBedTemp); connect(ui->bedExtWidget, &BedExtruderWidget::extTemperatureChanged, &core, &AtCore::setExtruderTemp); // Connect AtCore temperatures changes on Atelier Plot connect(&core.temperature(), &Temperature::bedTemperatureChanged, [ = ](float temp) { checkTemperature(0x00, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTemp(temp); }); connect(&core.temperature(), &Temperature::bedTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x01, 0, temp); ui->plotWidget->appendPoint(i18n("Target Bed"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateBedTargetTemp(temp); }); connect(&core.temperature(), &Temperature::extruderTemperatureChanged, [ = ](float temp) { checkTemperature(0x02, 0, temp); ui->plotWidget->appendPoint(i18n("Actual Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTemp(temp); }); connect(&core.temperature(), &Temperature::extruderTargetTemperatureChanged, [ = ](float temp) { checkTemperature(0x03, 0, temp); ui->plotWidget->appendPoint(i18n("Target Ext.1"), temp); ui->plotWidget->update(); ui->bedExtWidget->updateExtTargetTemp(temp); }); connect(ui->pushGCodeWidget, &PushGCodeWidget::push, [ = ](QString command) { logWidget->addLog("Push " + command); core.pushCommand(command); }); // Fan, Flow and Speed management connect(ui->ratesControlWidget, &RatesControlWidget::fanSpeedChanged, &core, &AtCore::setFanSpeed); connect(ui->ratesControlWidget, &RatesControlWidget::flowRateChanged, &core, &AtCore::setFlowRate); connect(ui->ratesControlWidget, &RatesControlWidget::printSpeedChanged, &core, &AtCore::setPrinterSpeed); connect(ui->axisViewWidget, &AxisControl::clicked, this, &MainWindow::axisControlClicked); } void MainWindow::initWidgets() { // Disable Toolbox to prevent the user to mess up without a printer being connected ui->controlDockWidget->setDisabled(true); ui->axisDockWidget->setDisabled(true); // This dock is of Printing Progress. It only need to be show while printing ui->printProgressDockWidget->setVisible(false); ui->logDockWidget->setWidget(logWidget); ui->statusBar->addWidget(ui->statusBarWidget); // When a new profile is added on the Profile Dialog it needs to update the profiles on connection dialog connect(profilesDialog, &ProfilesDialog::updateProfiles, connectSettingsDialog, &ConnectSettingsDialog::updateProfiles); connectSettingsDialog->setFirmwareList(core.availableFirmwarePlugins()); profilesDialog->setBaudRates(core.serial()->validBaudRates()); ui->homeAllPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); ui->homeXPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); ui->homeYPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); ui->homeZPB->setIcon(style()->standardIcon(QStyle::SP_DirHomeIcon)); tabifyDockWidget(ui->axisDockWidget, ui->controlDockWidget); } void MainWindow::setupActions() { // Actions for the Toolbar QAction *action; action = actionCollection()->addAction(QStringLiteral("open_gcode")); action->setText(i18n("&Open GCode")); connect(action, &QAction::triggered, this, &MainWindow::openFile); _connect = actionCollection()->addAction(QStringLiteral("connect")); _connect->setText(i18n("&Connect")); _connect->setCheckable(true); connect(_connect, &QAction::toggled, [ = ](bool checked) { if (checked) { connectSettingsDialog->show(); } else { core.closeConnection(); _connect->setText(i18n("&Connect")); ui->bedExtWidget->stopHeating(); core.setState(AtCore::DISCONNECTED); } }); connect(connectSettingsDialog, &ConnectSettingsDialog::setConnectValue, _connect, &QAction::setChecked); connect(ui->homeAllPB, &QPushButton::clicked, [=]{ core.home(); }); connect(ui->homeXPB, &QPushButton::clicked, [=]{ core.home(AtCore::X); }); connect(ui->homeYPB, &QPushButton::clicked, [=]{ core.home(AtCore::Y); }); connect(ui->homeZPB, &QPushButton::clicked, [=]{ core.home(AtCore::Z); }); action = actionCollection()->addAction(QStringLiteral("profiles")); action->setText(i18n("&Profiles")); connect(action, &QAction::triggered, profilesDialog, &ProfilesDialog::show); action = actionCollection()->addAction(QStringLiteral("print")); action->setText(i18n("&Print")); connect(action, &QAction::triggered, this, &MainWindow::printFile); action = actionCollection()->addAction(QStringLiteral("pause")); action->setText(i18n("&Pause")); connect(action, &QAction::triggered, this, &MainWindow::pausePrint); action = actionCollection()->addAction(QStringLiteral("stop")); action->setText(i18n("&Stop")); connect(action, &QAction::triggered, this, &MainWindow::stopPrint); #ifdef Q_OS_LINUX //only set icons from theme on linux actionCollection()->action(QStringLiteral("profiles"))->setIcon(QIcon::fromTheme("emblem-favorite")); #endif //use style's standardIcon for the icons we can. actionCollection()->action(QStringLiteral("open_gcode"))->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); actionCollection()->action(QStringLiteral("print"))->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); actionCollection()->action(QStringLiteral("pause"))->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); actionCollection()->action(QStringLiteral("stop"))->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); // Actions for the Docks action = actionCollection()->addAction(QStringLiteral("gcode"), ui->gcodeDockWidget->toggleViewAction()); action->setText(i18n("&GCode")); action = KStandardAction::quit(qApp, SLOT(quit()), actionCollection()); // Plot action = actionCollection()->addAction(QStringLiteral("plot"), ui->plotDockWidget->toggleViewAction()); action->setText(i18n("Temperature Timeline")); action = actionCollection()->addAction(QStringLiteral("controller"), ui->controlDockWidget->toggleViewAction()); action->setText(i18n("Controller")); action = actionCollection()->addAction(QStringLiteral("axis"), ui->axisDockWidget->toggleViewAction()); action->setText(i18n("Axis")); action = actionCollection()->addAction(QStringLiteral("log"), ui->logDockWidget->toggleViewAction()); action->setText(i18n("Log")); setupGUI(Default, "atelierui.rc"); } void MainWindow::openFile() { QUrl fileNameFromDialog = QFileDialog::getOpenFileUrl(this, i18n("Open GCode"), QDir::homePath(), i18n("GCode (*.gco *.gcode)")); if (!fileNameFromDialog.isEmpty()) { fileName = fileNameFromDialog; ui->gcodeEditorWidget->loadFile(fileName); guiFactory()->addClient(ui->gcodeEditorWidget->gcodeView()); + ui->view3DWidget->drawModel(fileName.toString()); } } void MainWindow::printFile() { if (!fileName.isEmpty() && (core.state() == AtCore::IDLE)) { QString f = fileName.toLocalFile(); core.print(f); } } void MainWindow::pausePrint() { core.pause(QString()); } void MainWindow::stopPrint() { core.stop(); } void MainWindow::handlePrinterStatusChanged(AtCore::STATES newState) { QString stateString; switch (newState) { case AtCore::CONNECTING: { stateString = i18n("Connecting..."); connect(&core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); connect(core.serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); } break; case AtCore::IDLE: { stateString = i18n("Connected to ") + core.serial()->portName(); ui->controlDockWidget->setEnabled(true); ui->axisDockWidget->setEnabled(true); emit extruderCountChanged(core.extruderCount()); logWidget->addLog(i18n("Serial connected")); _connect->setText(i18n("&Disconnect")); } break; case AtCore::DISCONNECTED: { stateString = i18n("Not Connected"); ui->controlDockWidget->setEnabled(false); ui->axisDockWidget->setEnabled(false); disconnect(&core, &AtCore::receivedMessage, this, &MainWindow::checkReceivedCommand); disconnect(core.serial(), &SerialLayer::pushedCommand, this, &MainWindow::checkPushedCommands); logWidget->addLog(i18n("Serial disconnected")); } break; case AtCore::STARTPRINT: { stateString = i18n("Starting Print"); ui->printProgressDockWidget->setVisible(true); connect(&core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); } break; case AtCore::FINISHEDPRINT: { stateString = i18n("Finished Print"); ui->printProgressDockWidget->setVisible(false); disconnect(&core, &AtCore::printProgressChanged, ui->printProgressWidget, &PrintProgressWidget::updateProgressBar); } break; case AtCore::BUSY: { stateString = i18n("Printing"); } break; case AtCore::PAUSE: { stateString = i18n("Paused"); } break; case AtCore::STOP: { stateString = i18n("Stoping Print"); } break; case AtCore::ERRORSTATE: { stateString = i18n("Error"); } break; } ui->lblState->setText(stateString); } void MainWindow::checkTemperature(uint sensorType, uint number, uint temp) { QString msg; switch (sensorType) { case 0x00: // bed msg = QString::fromLatin1("Bed Temperature "); break; case 0x01: // bed target msg = QString::fromLatin1("Bed Target Temperature "); break; case 0x02: // extruder msg = QString::fromLatin1("Extruder Temperature "); break; case 0x03: // extruder target msg = QString::fromLatin1("Extruder Target Temperature "); break; case 0x04: // enclosure msg = QString::fromLatin1("Enclosure Temperature "); break; case 0x05: // enclosure target msg = QString::fromLatin1("Enclosure Target Temperature "); break; } msg.append(QString::fromLatin1("[%1] : %2")); msg = msg.arg(QString::number(number)) .arg(QString::number(temp)); logWidget->addRLog(msg); } void MainWindow::checkReceivedCommand(const QByteArray &message) { logWidget->addRLog(QString::fromUtf8(message)); } void MainWindow::checkPushedCommands(QByteArray bmsg) { QString msg = QString::fromUtf8(bmsg); QRegExp _newLine(QChar::fromLatin1('\n')); QRegExp _return(QChar::fromLatin1('\r')); msg.replace(_newLine, QStringLiteral("\\n")); msg.replace(_return, QStringLiteral("\\r")); logWidget->addSLog(msg); } void MainWindow::axisControlClicked(QChar axis, int value) { core.setRelativePosition(); core.pushCommand(GCode::toCommand(GCode::G1, QStringLiteral("%1%2").arg(axis, QString::number(value)))); core.setAbsolutePosition(); } diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 86b19d7..8f2255c 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1,298 +1,287 @@ MainWindow 0 0 490 446 Atelier - - - QFrame::Box - - - - - 6 - 6 - 47 - 18 - - - - 3DView - - - + 6 418 801 46 100 0 0 0 0 0 Printer State: Not Connected Qt::Horizontal QSizePolicy::Expanding 0 0 0 0 490 30 Fi&le Edit Edit &GCode 1 Cont&roller 2 0 Temperatures Advanced Te&mperatures Timeline 2 Pri&nt Progress 2 true &Log true 1 Qt::NoContextMenu false A&xis 2 All X Y Z GCodeEditorWidget QWidget
widgets/gcodeeditorwidget.h
1
PlotWidget QWidget
widgets/plotwidget.h
1
RatesControlWidget QWidget
widgets/ratescontrolwidget.h
1
PrintProgressWidget QWidget
widgets/printprogresswidget.h
1
AxisControl QGraphicsView
widgets/axiscontrol.h
BedExtruderWidget QWidget
widgets/bedextruderwidget.h
1
PushGCodeWidget QWidget
widgets/pushgcodewidget.h
1
+ + Viewer3D + QWidget +
widgets/3dview/viewer3d.h
+ 1 +
diff --git a/src/widgets/3dview/AnimatedEntity.qml b/src/widgets/3dview/AnimatedEntity.qml new file mode 100644 index 0000000..0cb7ad1 --- /dev/null +++ b/src/widgets/3dview/AnimatedEntity.qml @@ -0,0 +1,97 @@ +import QtQuick 2.7 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 +import Qt3D.Logic 2.0 +import GridMesh 1.0 +import LineMesh 1.0 + +Entity { + id: sceneRoot + + signal fpsChanged(var fps) + + function runLineMesh(path) { + lineMesh.readAndRun(path) + } + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.01 + farPlane : 1000.0 + position: Qt.vector3d( 10.0, -10.0, 35.0 ) + upVector: Qt.vector3d( 0.0, 0.85, 0.75 ) + viewCenter: Qt.vector3d( 10.0, 10.0, 0.0 ) + } + + FirstPersonCameraController { camera: camera } + + components: [ + RenderSettings { + activeFrameGraph: ClearBuffers { + buffers: ClearBuffers.ColorDepthBuffer + clearColor: "transparent" + + RenderSurfaceSelector { + id: surfaceSelector + ClearBuffers { + buffers : ClearBuffers.ColorDepthBuffer + NoDraw {} + } + + Viewport { + id: topLeftViewport + CameraSelector { + id: cameraSelectorTopLeftViewport + camera: camera + } + } + } + } + }, + InputSettings { } + ] + + FrameAction { + id: frameAction + + onTriggered: { + sceneRoot.fpsChanged(1/dt) + } + } + + GridMesh { + id: gridMesh + enabled: true + } + + LineMesh { + id: lineMesh + objectName: "lineMesh" + enabled: true + } + + PhongMaterial { + id: material + ambient: "darkBlue" + } + + PhongMaterial { + id: lineMaterial + ambient: "darkGreen" + } + + Entity { + id: gridEntity + components: [ gridMesh, material ] + } + + Entity { + id: lineEntity + components: [ lineMesh, lineMaterial ] + } +} diff --git a/src/widgets/3dview/CMakeLists.txt b/src/widgets/3dview/CMakeLists.txt new file mode 100644 index 0000000..98123e4 --- /dev/null +++ b/src/widgets/3dview/CMakeLists.txt @@ -0,0 +1,28 @@ +set(3d_SRCS + gcodeto4d.cpp + fileloader.cpp + linemesh.cpp + gridmesh.cpp + linemeshgeometry.cpp + viewer3d.cpp +) + +file(GLOB 3d_SRC_QML + AnimatedEntity.qml + viewer3d.qml + ) + +qt5_add_resources(3dfiles_RCS viewer3d.qrc) + +add_library(Atelier3D STATIC ${3d_SRCS} ${3dfiles_RCS} ${3d_SRC_QML}) + +target_link_libraries(Atelier3D + Qt5::Core + Qt5::Widgets + Qt5::Quick + Qt5::Qml + Qt5::3DCore + Qt5::3DExtras + Qt5::3DRender + Qt5::3DInput + ) diff --git a/src/widgets/3dview/fileloader.cpp b/src/widgets/3dview/fileloader.cpp new file mode 100644 index 0000000..8b3ecb3 --- /dev/null +++ b/src/widgets/3dview/fileloader.cpp @@ -0,0 +1,131 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "fileloader.h" + +#include +#include +#include +#include +#include + +namespace +{ +const static QString _commentChar = QStringLiteral(";"); +const static QStringList _moveCommands = {QStringLiteral("G0"), QStringLiteral("G1")}; +const static QString _space = QStringLiteral(" "); + +const static QString _E = QStringLiteral("E"); +const static QString _X = QStringLiteral("X"); +const static QString _Y = QStringLiteral("Y"); +const static QString _Z = QStringLiteral("Z"); +}; + +FileLoader::FileLoader(QString &fileName, QObject *parent) + : QObject(parent) + , _file(fileName) +{ +} + +void FileLoader::run() +{ + QList pos; + qint64 totalSize = _file.bytesAvailable(); + qint64 stillSize = totalSize; + float lastPerc = 0.0; + + if (_file.open(QIODevice::ReadOnly)) { + QTextStream in(&_file); + while (!in.atEnd()) { + //Get each line + QString line = in.readLine(); + stillSize -= line.size() + 1; // +1 endl + const float perc = (totalSize - stillSize) * 100.0 / totalSize; + if (perc - lastPerc > 1) { + emit percentUpdate((int)perc); + lastPerc = perc; + } + line = line.simplified(); + //Is it a comment ? Drop it + if (line.isEmpty()) { + continue; + } + //Remove comment in the end of command + if (line.indexOf(_commentChar) != -1) { + line.resize(line.indexOf(_commentChar)); + //Remove trailing spaces + line = line.simplified(); + } + + //Split command and args + QStringList commAndArgs = line.split(_space); + + if (_moveCommands.contains(commAndArgs[0])) { + QVector4D actualPos; + //Compute args + commAndArgs.removeFirst(); + for (QString element : commAndArgs) { + if (element.contains(_X)) { + actualPos.setX(element.remove(0, 1).toFloat() / 10); + } + + if (element.contains(_Y)) { + actualPos.setY(element.remove(0, 1).toFloat() / 10); + } + + if (element.contains(_Z)) { + actualPos.setZ(element.remove(0, 1).toFloat() / 10); + } + + if (element.contains(_E)) { + actualPos.setW(element.remove(0, 1).toFloat() / 10); + } + } + + if (!pos.isEmpty()) { + if (!line.contains(_X)) { + actualPos.setX(pos.last().x()); + } + + if (!line.contains(_Y)) { + actualPos.setY(pos.last().y()); + } + + if (!line.contains(_Z)) { + actualPos.setZ(pos.last().z()); + } + + if (!line.contains(_E)) { + actualPos.setW(pos.last().w()); + } + } + + pos.append(actualPos); + } + } + emit percentUpdate(100); + emit posFinished(pos); + } +}; + +FileLoader::~FileLoader() +{ +}; \ No newline at end of file diff --git a/src/widgets/3dview/fileloader.h b/src/widgets/3dview/fileloader.h new file mode 100644 index 0000000..2a9fd29 --- /dev/null +++ b/src/widgets/3dview/fileloader.h @@ -0,0 +1,49 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include +#include +#include +#include + +class QString; +class QVector4D; + +class FileLoader : public QObject +{ + Q_OBJECT + +public: + FileLoader(QString &fileName, QObject *parent = nullptr); + ~FileLoader(); + +private: + QFile _file; + +signals: + void percentUpdate(QVariant var); + void posFinished(const QList &pos); + +public slots: + void run(); +}; diff --git a/src/widgets/3dview/gcodeto4d.cpp b/src/widgets/3dview/gcodeto4d.cpp new file mode 100644 index 0000000..e8027cb --- /dev/null +++ b/src/widgets/3dview/gcodeto4d.cpp @@ -0,0 +1,52 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "gcodeto4d.h" +#include "fileloader.h" + +#include +#include +#include +#include +#include + +GcodeTo4D::GcodeTo4D(QObject *parent) : + QObject(parent) +{ +} + +void GcodeTo4D::read(const QString &url) +{ + _thread = new QThread; + QString path = QUrl(url).path(); + auto fileLoader = new FileLoader(path); + fileLoader->moveToThread(_thread); + connect(fileLoader, &FileLoader::percentUpdate, this, &GcodeTo4D::percentUpdate); + connect(fileLoader, &FileLoader::posFinished, this, &GcodeTo4D::posFinished); + connect(fileLoader, &FileLoader::posFinished, _thread, &QThread::quit); + connect(_thread, &QThread::started, fileLoader, &FileLoader::run); + connect(_thread, &QThread::finished, fileLoader, &FileLoader::deleteLater); + _thread->start(); +} + +GcodeTo4D::~GcodeTo4D() +{ +} \ No newline at end of file diff --git a/src/widgets/3dview/gcodeto4d.h b/src/widgets/3dview/gcodeto4d.h new file mode 100644 index 0000000..6e21f76 --- /dev/null +++ b/src/widgets/3dview/gcodeto4d.h @@ -0,0 +1,44 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include + +class GcodeTo4D : public QObject +{ + Q_OBJECT + +public: + explicit GcodeTo4D(QObject *parent = 0); + ~GcodeTo4D(); + +public: + void read(const QString &url); + +signals: + void percentUpdate(const QVariant &percent); + void posFinished(const QList &pos); + +private: + QThread *_thread; + bool _wait; +}; diff --git a/src/widgets/3dview/gridmesh.cpp b/src/widgets/3dview/gridmesh.cpp new file mode 100644 index 0000000..206312e --- /dev/null +++ b/src/widgets/3dview/gridmesh.cpp @@ -0,0 +1,57 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "linemeshgeometry.h" +#include "gridmesh.h" + +#include +#include +#include +#include + +GridMesh::GridMesh(Qt3DCore::QNode *parent) + : Qt3DRender::QGeometryRenderer(parent) +{ + setInstanceCount(1); + setIndexOffset(0); + setFirstInstance(0); + setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); + + QVector2D s(20, 20); + QList vertices; + for (uint i = 0; i <= s.x(); i++) { + for (uint j = 0; j <= s.y(); j++) { + vertices.append(QVector4D(i, 0, 0, 0)); + vertices.append(QVector4D(i, j, 0, 0)); + + vertices.append(QVector4D(0, j, 0, 0)); + vertices.append(QVector4D(i, j, 0, 0)); + } + } + + auto geometry = new LineMeshGeometry(vertices, this); + setVertexCount(geometry->vertexCount()); + setGeometry(geometry); +} + +GridMesh::~GridMesh() +{ +} diff --git a/src/widgets/3dview/gridmesh.h b/src/widgets/3dview/gridmesh.h new file mode 100644 index 0000000..043b255 --- /dev/null +++ b/src/widgets/3dview/gridmesh.h @@ -0,0 +1,34 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include +#include +#include + +class GridMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT +public: + explicit GridMesh(Qt3DCore::QNode *parent = nullptr); + ~GridMesh(); +}; diff --git a/src/widgets/3dview/linemesh.cpp b/src/widgets/3dview/linemesh.cpp new file mode 100644 index 0000000..a55aece --- /dev/null +++ b/src/widgets/3dview/linemesh.cpp @@ -0,0 +1,64 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "gcodeto4d.h" +#include "linemesh.h" +#include "linemeshgeometry.h" + +#include +#include +#include + +LineMesh::LineMesh(Qt3DCore::QNode *parent) + : Qt3DRender::QGeometryRenderer(parent) + , _lineMeshGeo(nullptr) +{ + setInstanceCount(1); + setIndexOffset(0); + setFirstInstance(0); + setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + + qRegisterMetaType >("QList"); + connect(&_gcode, &GcodeTo4D::posFinished, this, &LineMesh::posUpdate); +} + +void LineMesh::readAndRun(const QString &path) +{ + _gcode.read(path); +} + +void LineMesh::read(const QString &path) +{ + emit run(path); +} + +void LineMesh::posUpdate(const QList &pos) +{ + _vertices = pos; + _lineMeshGeo = new LineMeshGeometry(_vertices, this); + setVertexCount(_lineMeshGeo->vertexCount()); + setGeometry(_lineMeshGeo); + emit finished(); +} + +LineMesh::~LineMesh() +{ +} diff --git a/src/widgets/3dview/linemesh.h b/src/widgets/3dview/linemesh.h new file mode 100644 index 0000000..b6eec27 --- /dev/null +++ b/src/widgets/3dview/linemesh.h @@ -0,0 +1,53 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include +#include +#include +#include + +#include "gcodeto4d.h" + +class LineMeshGeometry; +class QString; +class QVector4D; + +class LineMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT +public: + explicit LineMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~LineMesh(); + Q_INVOKABLE void readAndRun(const QString &path); + void read(const QString &path); + void posUpdate(const QList &pos); + +signals: + void finished(); + void run(const QString &path); + +private: + QList _vertices; + LineMeshGeometry *_lineMeshGeo; + GcodeTo4D _gcode; +}; diff --git a/src/widgets/3dview/linemeshgeometry.cpp b/src/widgets/3dview/linemeshgeometry.cpp new file mode 100644 index 0000000..51929ef --- /dev/null +++ b/src/widgets/3dview/linemeshgeometry.cpp @@ -0,0 +1,62 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "linemeshgeometry.h" + +#include +#include +#include + +LineMeshGeometry::LineMeshGeometry(const QList &vertices, Qt3DCore::QNode *parent) : + Qt3DRender::QGeometry(parent) + , _positionAttribute(new Qt3DRender::QAttribute(this)) + , _vertexBuffer(new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, this)) +{ + QByteArray vertexBufferData; + vertexBufferData.resize(vertices.size() * 3 * sizeof(float)); + float *rawVertexArray = reinterpret_cast(vertexBufferData.data()); + int idx = 0; + for (const auto &v : vertices) { + rawVertexArray[idx++] = v.x(); + rawVertexArray[idx++] = v.y(); + rawVertexArray[idx++] = v.z(); + _vertices.append(v.toVector3D()); + } + + _vertexBuffer->setData(vertexBufferData); + + _positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); + _positionAttribute->setBuffer(_vertexBuffer); + _positionAttribute->setDataType(Qt3DRender::QAttribute::Float); + _positionAttribute->setDataSize(3); + _positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); + + addAttribute(_positionAttribute); +} + +int LineMeshGeometry::vertexCount() +{ + return _vertices.size(); +} + +LineMeshGeometry::~LineMeshGeometry() +{ +} diff --git a/src/widgets/3dview/linemeshgeometry.h b/src/widgets/3dview/linemeshgeometry.h new file mode 100644 index 0000000..2012343 --- /dev/null +++ b/src/widgets/3dview/linemeshgeometry.h @@ -0,0 +1,41 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include +#include +#include + +class LineMeshGeometry : public Qt3DRender::QGeometry +{ + Q_OBJECT +public: + LineMeshGeometry(const QList &vertices, Qt3DCore::QNode *parent = Q_NULLPTR); + ~LineMeshGeometry(); + + int vertexCount(); + +private: + Qt3DRender::QAttribute *_positionAttribute; + Qt3DRender::QBuffer *_vertexBuffer; + QVector _vertices; +}; diff --git a/src/widgets/3dview/viewer3d.cpp b/src/widgets/3dview/viewer3d.cpp new file mode 100644 index 0000000..deb4a22 --- /dev/null +++ b/src/widgets/3dview/viewer3d.cpp @@ -0,0 +1,69 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#include "linemesh.h" +#include "gridmesh.h" +#include "viewer3d.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +Viewer3D::Viewer3D(QWidget *parent) + : QWidget(parent) + , _lineMesh(new LineMesh) +{ + Q_INIT_RESOURCE(viewer3d); + + QDirIterator it(QStringLiteral(":"), QDirIterator::Subdirectories); + while (it.hasNext()) { + qDebug() << it.next(); + } + + qmlRegisterType("GridMesh", 1, 0, "GridMesh"); + qmlRegisterType("LineMesh", 1, 0, "LineMesh"); + + _view = new QQuickView(&_engine, nullptr); + _view->setResizeMode(QQuickView::SizeRootObjectToView); + _view->setSource(QUrl(QStringLiteral("qrc:/viewer3d.qml"))); + QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout->addWidget(QWidget::createWindowContainer(_view)); + this->setLayout(mainLayout); +} + +void Viewer3D::drawModel(QString file) +{ + + QObject *object = _view->rootObject(); + QObject *fileName = object->findChild(QStringLiteral("fileName")); + fileName->setProperty("text", QVariant(file)); +} + +Viewer3D::~Viewer3D() +{ +} diff --git a/src/widgets/3dview/viewer3d.h b/src/widgets/3dview/viewer3d.h new file mode 100644 index 0000000..558c199 --- /dev/null +++ b/src/widgets/3dview/viewer3d.h @@ -0,0 +1,44 @@ +/* Atelier KDE Printer Host for 3D Printing + Copyright (C) <2017> + Author: Patrick José Pereira - patrickelectric@gmail.com + + 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 any later version accepted by the membership of + KDE e.V. (or its successor approved by the membership of KDE + e.V.), which shall act as a proxy defined in Section 14 of + version 3 of the license. + + 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 . +*/ + +#pragma once + +#include +#include +#include + +class LineMesh; +class QString; + +class Viewer3D : public QWidget +{ + Q_OBJECT + +public: + explicit Viewer3D(QWidget *parent = nullptr); + ~Viewer3D() override; + + void drawModel(QString file); +private: + QQuickView *_view; + LineMesh *_lineMesh; + QQmlApplicationEngine _engine; +}; diff --git a/src/widgets/3dview/viewer3d.qml b/src/widgets/3dview/viewer3d.qml new file mode 100644 index 0000000..1d42a2c --- /dev/null +++ b/src/widgets/3dview/viewer3d.qml @@ -0,0 +1,36 @@ +import QtQuick 2.0 +import QtQuick.Scene3D 2.0 +import LineMesh 1.0 + +Item { + id: item + width: 1000 + height: 1000 + Rectangle { + id: scene + anchors.fill: parent + Scene3D { + id: scene3d + anchors.fill: parent + focus: true + aspects: ["input", "logic"] + cameraAspectRatioMode: Scene3D.AutomaticAspectRatio + AnimatedEntity { + id: entity + onFpsChanged: { + // print(fps) + } + } + + } + } + + Text { + objectName: "fileName" + id: fileName + text: "" + onTextChanged: { + entity.runLineMesh(text) + } + } +} diff --git a/src/widgets/3dview/viewer3d.qrc b/src/widgets/3dview/viewer3d.qrc new file mode 100644 index 0000000..5e3ed7c --- /dev/null +++ b/src/widgets/3dview/viewer3d.qrc @@ -0,0 +1,6 @@ + + + AnimatedEntity.qml + viewer3d.qml + + diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 7e89c63..47b713b 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -1,14 +1,23 @@ set(widgets_SRCS gcodeeditorwidget.cpp axiscontrol.cpp bedextruderwidget.cpp plotwidget.cpp pushgcodewidget.cpp ratescontrolwidget.cpp printprogresswidget.cpp logwidget.cpp ) add_library(AtelierWidgets STATIC ${widgets_SRCS}) -target_link_libraries(AtelierWidgets Qt5::Core Qt5::Widgets Qt5::SerialPort KF5::Solid KF5::I18n KF5::TextEditor Qt5::Charts) +target_link_libraries(AtelierWidgets + Qt5::Core + Qt5::Widgets + Qt5::SerialPort + KF5::Solid + KF5::I18n + KF5::TextEditor + Qt5::Charts) + +add_subdirectory(3dview)