#include "backplotwidget.h" #include #include #include #include #include #include #include #include #include BackPlotWidget::BackPlotWidget(QWidget *parent, double xLimit, double yLimit, double zLimit) : limits(xLimit, yLimit, zLimit), QWidget(parent) { containerWdiget = QWidget::createWindowContainer(&view); hLayout.addWidget(containerWdiget); containerWdiget->setParent(this); setLayout(&hLayout); view.defaultFrameGraph()->setClearColor("Black"); reset(); } void BackPlotWidget::reset() { view.setRootEntity(nullptr); if(rootEntity) delete rootEntity; rootEntity = new Qt3DCore::QEntity(); view.setRootEntity(rootEntity); view.renderSettings()->setRenderPolicy(Qt3DRender::QRenderSettings::OnDemand); camController = new OrbitCameraController(QVector2D(100, 100), rootEntity); camController->setLinearSpeed(200.0f); camController->setLookSpeed(360.0f); camController->setCamera(view.camera()); axisMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); rapidMaterial= new Qt3DExtras::QPhongMaterial(rootEntity); pathMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); axisMaterial->setAmbient(QColorConstants::Red); rapidMaterial->setAmbient(QColorConstants::Gray); pathMaterial->setAmbient(QColorConstants::White); view.camera()->setPosition(QVector3D(limits.x()/2, limits.y()/2, limits.z()*4)); view.camera()->setUpVector(QVector3D(0, 1, 0)); view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, 0)); Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity); Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity); light->setColor(QColorConstants::White); light->setIntensity(0.2); lightEntity->addComponent(light); Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity); lightTransform->setTranslation(QVector3D(0-limits.x()/2, 0-limits.y()/2, 1000.0f)); lightEntity->addComponent(lightTransform); Qt3DCore::QEntity* xAxisEntity = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity* yAxisEntity = new Qt3DCore::QEntity(rootEntity); Qt3DCore::QEntity* zAxisEntity = new Qt3DCore::QEntity(rootEntity); Qt3DExtras::QPhongMaterial* xAxisMaterial = new Qt3DExtras::QPhongMaterial(xAxisEntity); Qt3DExtras::QPhongMaterial* yAxisMaterial = new Qt3DExtras::QPhongMaterial(yAxisEntity); Qt3DExtras::QPhongMaterial* zAxisMaterial = new Qt3DExtras::QPhongMaterial(zAxisEntity); xAxisMaterial->setAmbient(QColorConstants::Green); yAxisMaterial->setAmbient(QColorConstants::Red); zAxisMaterial->setAmbient(QColor(18,128,255)); touchoffTransform = new Qt3DCore::QTransform(rootEntity); touchoffTransform->setTranslation(limits); xAxisEntity->addComponent(touchoffTransform); yAxisEntity->addComponent(touchoffTransform); zAxisEntity->addComponent(touchoffTransform); drawLine(QVector3D(0,0,0), QVector3D(-15,0,0), xAxisMaterial, xAxisEntity); drawLine(QVector3D(0,0,0), QVector3D(0,-15,0), yAxisMaterial, yAxisEntity); drawLine(QVector3D(0,0,0), QVector3D(0,0,15), zAxisMaterial, zAxisEntity); drawBox(QVector3D(0, 0, 0), limits, axisMaterial, new Qt3DCore::QEntity(rootEntity)); Qt3DCore::QEntity* planeEntity = new Qt3DCore::QEntity(rootEntity); Qt3DExtras::QPlaneMesh* plane = new Qt3DExtras::QPlaneMesh(planeEntity); Qt3DCore::QTransform *planeTransform = new Qt3DCore::QTransform(planeEntity); Qt3DExtras::QPhongMaterial* planeMaterial = new Qt3DExtras::QPhongMaterial(planeEntity); planeMaterial->setDiffuse(QColorConstants::DarkGray); planeTransform->setTranslation(QVector3D(limits.x()/2, limits.y()/2, -1)); planeTransform->setRotationX(90); plane->setHeight(limits.y()*2); plane->setWidth(limits.x()*2); planeEntity->addComponent(plane); planeEntity->addComponent(planeMaterial); planeEntity->addComponent(planeTransform); Qt3DCore::QEntity* planeRevEntity = new Qt3DCore::QEntity(rootEntity); Qt3DExtras::QPlaneMesh* planeRev = new Qt3DExtras::QPlaneMesh(planeRevEntity); Qt3DCore::QTransform *planeRevTransform = new Qt3DCore::QTransform(planeRevEntity); planeRevTransform->setTranslation(QVector3D(limits.x()/2, limits.y()/2, -1)); planeRevTransform->setRotationX(-90); planeRev->setHeight(limits.y()*2); planeRev->setWidth(limits.x()*2); planeRevEntity->addComponent(planeRev); planeRevEntity->addComponent(planeMaterial); planeRevEntity->addComponent(planeRevTransform); toolEntity = new Qt3DCore::QEntity(rootEntity); Qt3DExtras::QCylinderMesh* toolMesh = new Qt3DExtras::QCylinderMesh(toolEntity); Qt3DExtras::QPhongMaterial* toolMaterial = new Qt3DExtras::QPhongMaterial(toolEntity); toolTransform = new Qt3DCore::QTransform(toolEntity); toolTransform->setTranslation(limits + QVector3D(0,0,5)); toolTransform->setRotationX(90); toolMaterial->setDiffuse(QColorConstants::White); toolMaterial->setAmbient(QColor(64,64,64)); toolMesh->setRadius(1); toolMesh->setLength(10); toolEntity->addComponent(toolMesh); toolEntity->addComponent(toolMaterial); toolEntity->addComponent(toolTransform); } void BackPlotWidget::showView(ViewPos viewPos) { if(viewPos == VIEW_TOP) { view.camera()->setPosition(QVector3D(limits.x()/2, limits.y()/2, limits.z()*4)); view.camera()->setUpVector(QVector3D(0, 1, 0)); } else if(viewPos == VIEW_FRONT) { view.camera()->setPosition(QVector3D(limits.x()/2, 0-limits.y()*4, limits.z()/2)); view.camera()->setUpVector(QVector3D(0, 0, 1)); } else if(viewPos == VIEW_LEFT) { view.camera()->setPosition(QVector3D(0-limits.x()*4, limits.y()/2, limits.z()/2)); view.camera()->setUpVector(QVector3D(0, 0, 1)); } else if(viewPos == VIEW_RIGHT) { view.camera()->setPosition(QVector3D(limits.x()*4, limits.y()/2, limits.z()/2)); view.camera()->setUpVector(QVector3D(0, 0, 1)); } if(viewPos == VIEW_TOP) view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, 0)); else view.camera()->setViewCenter(QVector3D(limits.x()/2, limits.y()/2, limits.z()/2)); camController->setZoomFactor(1); } void BackPlotWidget::positionUpdate(std::vector position) { assert(position.size() >= 3); toolTransform->setTranslation(limits - QVector3D(position[0]/1000.0, position[1]/1000.0, (position[2]/1000.0)-5)); } void BackPlotWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); double aspectRatio = static_cast(geometry().width())/geometry().height(); double screenWidth; double screenHeight; if(aspectRatio > 1.0) { screenWidth = 500.0; screenHeight = screenWidth/aspectRatio; } else { screenHeight = 500; screenWidth = aspectRatio*screenHeight; } camController->setOrthoSize(QVector2D(screenWidth, screenHeight)); } void BackPlotWidget::drawBox(const QVector3D& a, const QVector3D& b, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent) { drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(b.x(), a.y(), a.z()), material, parent); drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(a.x(), b.y(), a.z()), material, parent); drawLine(QVector3D(a.x(), a.y(), a.z()), QVector3D(a.x(), a.y(), b.z()), material, parent); drawLine(QVector3D(b.x(), a.y(), a.z()), QVector3D(b.x(), b.y(), a.z()), material, parent); drawLine(QVector3D(b.x(), a.y(), a.z()), QVector3D(b.x(), a.y(), b.z()), material, parent); drawLine(QVector3D(a.x(), b.y(), a.z()), QVector3D(b.x(), b.y(), a.z()), material, parent); drawLine(QVector3D(a.x(), b.y(), a.z()), QVector3D(a.x(), b.y(), b.z()), material, parent); drawLine(QVector3D(a.x(), a.y(), b.z()), QVector3D(b.x(), a.y(), b.z()), material, parent); drawLine(QVector3D(a.x(), a.y(), b.z()), QVector3D(a.x(), b.y(), b.z()), material, parent); drawLine(QVector3D(b.x(), b.y(), a.z()), QVector3D(b.x(), b.y(), b.z()), material, parent); drawLine(QVector3D(a.x(), b.y(), b.z()), QVector3D(b.x(), b.y(), b.z()), material, parent); drawLine(QVector3D(b.x(), a.y(), b.z()), QVector3D(b.x(), b.y(), b.z()), material, parent); } QByteArray BackPlotWidget::removeComments(const QByteArray& program) { int commentCounter = 0; QByteArray out; for(char ch : program) { if(ch == '/') ++commentCounter; else if(ch == '\\' && commentCounter > 0) --commentCounter; else if(commentCounter == 0) out.push_back(ch); } return out; } QList BackPlotWidget::getFields(QByteArray command) { command.remove(0, 2); QList fieldsText = command.split(','); QList fields; for(const QByteArray& field : fieldsText) { if(field.size() == 0) fields.push_back(NO_FIELD); else fields.push_back(field.toInt()); } return fields; } void BackPlotWidget::programChanged(QByteArray program) { for(Qt3DCore::QEntity* entitiy : pathEntitys) delete entitiy; pathEntitys.clear(); program = removeComments(program); QList commands = program.split(';'); QVector3D lastPos = touchoffPosition; qDebug()<<__func__; for(QByteArray& command : commands) { command = command.trimmed().toUpper(); if(command.size() < 2) continue; if(command[0] == 'P' || command[0] == 'G') { QList fields = getFields(command); QVector3D pos; if(fields.size() <= 2 || fields[2] == NO_FIELD) pos.setZ(command[1] != 'R' ? lastPos.z()-touchoffPosition.z() : 0); else if(fields.size() > 2) pos.setZ(fields[2]/1000.0); if(fields.size() <= 1 || fields[1] == NO_FIELD) pos.setY(command[1] != 'R' ? lastPos.y()-touchoffPosition.y() : 0); else if(fields.size() > 1) pos.setY(fields[1]/1000.0); if(fields.size() <= 0 || fields[0] == NO_FIELD) pos.setX(command[1] != 'R' ? lastPos.x()-touchoffPosition.x() : 0); else if(fields.size() > 0) pos.setX(fields[0]/1000.0); if(command[1] == 'A') pos = pos+touchoffPosition; else if(command[1] == 'R') pos = pos+lastPos; pathEntitys.push_back(new Qt3DCore::QEntity(rootEntity)); drawLine(limits-lastPos, limits-pos, command[0] == 'G' ? rapidMaterial : pathMaterial, pathEntitys.back()); lastPos = pos; } } } void BackPlotWidget::touchoffUpdate(std::vector position) { assert(position.size() >= 3); touchoffPosition.setX(position[0]/1000.0); touchoffPosition.setY(position[1]/1000.0); touchoffPosition.setZ(position[2]/1000.0); touchoffTransform->setTranslation(limits-touchoffPosition); } void BackPlotWidget::drawLine(const QVector3D& start, const QVector3D& end, Qt3DRender::QMaterial* material, Qt3DCore::QEntity* parent) { Qt3DCore::QGeometry* geometry = new Qt3DCore::QGeometry(parent); // position vertices (start and end) QByteArray bufferBytes; bufferBytes.resize(3 * 2 * sizeof(float)); // start.x, start.y, start.end, end.x, end.y, end.z float* positions = reinterpret_cast(bufferBytes.data()); *positions++ = start.x(); *positions++ = start.y(); *positions++ = start.z(); *positions++ = end.x(); *positions++ = end.y(); *positions++ = end.z(); Qt3DCore::QBuffer* buf = new Qt3DCore::QBuffer(geometry); buf->setData(bufferBytes); auto *positionAttribute = new Qt3DCore::QAttribute(geometry); positionAttribute->setName(Qt3DCore::QAttribute::defaultPositionAttributeName()); positionAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float); positionAttribute->setVertexSize(3); positionAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute); positionAttribute->setBuffer(buf); positionAttribute->setByteStride(3 * sizeof(float)); positionAttribute->setCount(2); geometry->addAttribute(positionAttribute); // We add the vertices in the geometry // connectivity between vertices QByteArray indexBytes; indexBytes.resize(2 * sizeof(unsigned int)); // start to end unsigned int *indices = reinterpret_cast(indexBytes.data()); *indices++ = 0; *indices++ = 1; Qt3DCore::QBuffer* indexBuffer = new Qt3DCore::QBuffer(geometry); indexBuffer->setData(indexBytes); Qt3DCore::QAttribute *indexAttribute = new Qt3DCore::QAttribute(geometry); indexAttribute->setVertexBaseType(Qt3DCore::QAttribute::UnsignedInt); indexAttribute->setAttributeType(Qt3DCore::QAttribute::IndexAttribute); indexAttribute->setBuffer(indexBuffer); indexAttribute->setCount(2); geometry->addAttribute(indexAttribute); // We add the indices linking the points in the geometry // mesh auto *line = new Qt3DRender::QGeometryRenderer(parent); line->setGeometry(geometry); line->setPrimitiveType(Qt3DRender::QGeometryRenderer::Lines); // entity auto *lineEntity = new Qt3DCore::QEntity(parent); lineEntity->addComponent(line); lineEntity->addComponent(material); }