VHFMill/backplotwidget.cpp
2023-01-29 18:45:42 +01:00

338 lines
12 KiB
C++

#include "backplotwidget.h"
#include <QWidget>
#include <QCamera>
#include <QCameraLens>
#include <QMaterial>
#include <QGeometry>
#include <Qt3DExtras/QCylinderMesh>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DRender/qpointlight.h>
#include <QRenderSettings>
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<int> 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<double>(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<int> BackPlotWidget::getFields(QByteArray command)
{
command.remove(0, 2);
QList<QByteArray> fieldsText = command.split(',');
QList<int> 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<QByteArray> 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<int> 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<int> 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<float*>(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<unsigned int*>(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);
}