| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include "DlgCAMSimulator.h" |
| | #include "MillSimulation.h" |
| | #include "Gui/View3DInventorViewer.h" |
| | #include <Mod/Part/App/BRepMesh.h> |
| | #include <QDateTime> |
| | #include <QSurfaceFormat> |
| | #include <QPoint> |
| | #include <App/Document.h> |
| |
|
| | QOpenGLContext* gOpenGlContext; |
| |
|
| | using namespace MillSim; |
| |
|
| | namespace CAMSimulator |
| | { |
| |
|
| | static const float MouseScrollDelta = 120.0F; |
| |
|
| | DlgCAMSimulator::DlgCAMSimulator(QWindow* parent) |
| | : QWindow(parent) |
| | { |
| | setSurfaceType(QWindow::OpenGLSurface); |
| | mMillSimulator = new MillSimulation(); |
| | } |
| |
|
| | DlgCAMSimulator::~DlgCAMSimulator() |
| | { |
| | delete mMillSimulator; |
| | } |
| |
|
| | void DlgCAMSimulator::render(QPainter* painter) |
| | { |
| | Q_UNUSED(painter); |
| | } |
| |
|
| | void DlgCAMSimulator::render() |
| | { |
| | mMillSimulator->ProcessSim((unsigned int)(QDateTime::currentMSecsSinceEpoch())); |
| | } |
| |
|
| | void DlgCAMSimulator::renderLater() |
| | { |
| | requestUpdate(); |
| | } |
| |
|
| | bool DlgCAMSimulator::event(QEvent* event) |
| | { |
| | switch (event->type()) { |
| | case QEvent::UpdateRequest: |
| | renderNow(); |
| | return true; |
| | default: |
| | break; |
| | } |
| | return QWindow::event(event); |
| | } |
| |
|
| | void DlgCAMSimulator::exposeEvent(QExposeEvent* event) |
| | { |
| | Q_UNUSED(event); |
| |
|
| | if (isExposed()) { |
| | renderNow(); |
| | } |
| | } |
| |
|
| | void DlgCAMSimulator::mouseMoveEvent(QMouseEvent* ev) |
| | { |
| | int modifiers = (ev->modifiers() & Qt::ShiftModifier) != 0 ? MS_KBD_SHIFT : 0; |
| | modifiers |= (ev->modifiers() & Qt::ControlModifier) != 0 ? MS_KBD_CONTROL : 0; |
| | modifiers |= (ev->modifiers() & Qt::AltModifier) != 0 ? MS_KBD_ALT : 0; |
| |
|
| | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| | QPoint pnt = ev->pos(); |
| | #else |
| | QPoint pnt = ev->position().toPoint(); |
| | #endif |
| | mMillSimulator->MouseMove(pnt.x(), pnt.y(), modifiers); |
| | } |
| |
|
| | void DlgCAMSimulator::mousePressEvent(QMouseEvent* ev) |
| | { |
| | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| | QPoint pnt = ev->pos(); |
| | #else |
| | QPoint pnt = ev->position().toPoint(); |
| | #endif |
| | mMillSimulator->MousePress(ev->button(), true, pnt.x(), pnt.y()); |
| | } |
| |
|
| | void DlgCAMSimulator::mouseReleaseEvent(QMouseEvent* ev) |
| | { |
| | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
| | QPoint pnt = ev->pos(); |
| | #else |
| | QPoint pnt = ev->position().toPoint(); |
| | #endif |
| | mMillSimulator->MousePress(ev->button(), false, pnt.x(), pnt.y()); |
| | } |
| |
|
| | void DlgCAMSimulator::wheelEvent(QWheelEvent* ev) |
| | { |
| | mMillSimulator->MouseScroll((float)ev->angleDelta().y() / MouseScrollDelta); |
| | } |
| |
|
| | void DlgCAMSimulator::resetSimulation() |
| | {} |
| |
|
| | void DlgCAMSimulator::addGcodeCommand(const char* cmd) |
| | { |
| | mMillSimulator->AddGcodeLine(cmd); |
| | } |
| |
|
| | void DlgCAMSimulator::addTool( |
| | const std::vector<float>& toolProfilePoints, |
| | int toolNumber, |
| | float diameter, |
| | float resolution |
| | ) |
| | { |
| | Q_UNUSED(resolution) |
| | std::string toolCmd = "T" + std::to_string(toolNumber); |
| | mMillSimulator->AddGcodeLine(toolCmd.c_str()); |
| | if (!mMillSimulator->ToolExists(toolNumber)) { |
| | mMillSimulator->AddTool(toolProfilePoints, toolNumber, diameter); |
| | } |
| | } |
| |
|
| | void DlgCAMSimulator::hideEvent(QHideEvent* ev) |
| | { |
| | mMillSimulator->Clear(); |
| | doGlCleanup(); |
| | mAnimating = false; |
| | QWindow::hideEvent(ev); |
| | close(); |
| | mInstance = nullptr; |
| | } |
| |
|
| | void DlgCAMSimulator::resizeEvent(QResizeEvent* event) |
| | { |
| | if (!mContext) { |
| | return; |
| | } |
| | QSize newSize = event->size(); |
| | int newWidth = newSize.width(); |
| | int newHeight = newSize.height(); |
| | if (mMillSimulator != nullptr) { |
| | mMillSimulator->UpdateWindowScale(newWidth, newHeight); |
| | } |
| | const qreal retinaScale = devicePixelRatio(); |
| | glViewport(0, 0, (int)(newWidth * retinaScale), (int)(newHeight * retinaScale)); |
| | } |
| |
|
| | void DlgCAMSimulator::GetMeshData( |
| | const Part::TopoShape& tshape, |
| | float resolution, |
| | std::vector<Vertex>& verts, |
| | std::vector<GLushort>& indices |
| | ) |
| | { |
| | std::vector<int> normalCount; |
| | int nVerts = 0; |
| | for (auto& shape : tshape.getSubTopoShapes(TopAbs_FACE)) { |
| | std::vector<Base::Vector3d> points; |
| | std::vector<Data::ComplexGeoData::Facet> facets; |
| | shape.getFaces(points, facets, resolution); |
| |
|
| | std::vector<Base::Vector3d> normals(points.size()); |
| | std::vector<int> normalCount(points.size()); |
| |
|
| | |
| | for (auto face : facets) { |
| | indices.push_back(face.I1 + nVerts); |
| | indices.push_back(face.I2 + nVerts); |
| | indices.push_back(face.I3 + nVerts); |
| |
|
| | |
| | Base::Vector3d vAB = points[face.I2] - points[face.I1]; |
| | Base::Vector3d vAC = points[face.I3] - points[face.I1]; |
| | Base::Vector3d vNorm = vAB.Cross(vAC).Normalize(); |
| |
|
| | normals[face.I1] += vNorm; |
| | normals[face.I2] += vNorm; |
| | normals[face.I3] += vNorm; |
| |
|
| | normalCount[face.I1]++; |
| | normalCount[face.I2]++; |
| | normalCount[face.I3]++; |
| | } |
| |
|
| | |
| | for (unsigned int i = 0; i < points.size(); i++) { |
| | Base::Vector3d& point = points[i]; |
| | Base::Vector3d& normal = normals[i]; |
| | int count = normalCount[i]; |
| | normal /= count; |
| | verts.push_back(Vertex(point.x, point.y, point.z, normal.x, normal.y, normal.z)); |
| | } |
| |
|
| | nVerts = verts.size(); |
| | } |
| | } |
| |
|
| | void DlgCAMSimulator::startSimulation(const Part::TopoShape& stock, float quality) |
| | { |
| | mQuality = quality; |
| | mNeedsInitialize = true; |
| | show(); |
| | checkInitialization(); |
| | SetStockShape(stock, 1); |
| | setAnimating(true); |
| | } |
| |
|
| | void DlgCAMSimulator::initialize() |
| | { |
| | const qreal retinaScale = devicePixelRatio(); |
| | mMillSimulator->InitSimulation(mQuality, retinaScale); |
| |
|
| | glViewport(0, 0, (int)(width() * retinaScale), (int)(height() * retinaScale)); |
| | } |
| |
|
| | void DlgCAMSimulator::checkInitialization() |
| | { |
| | if (!mContext) { |
| | mLastContext = QOpenGLContext::currentContext(); |
| | mContext = new QOpenGLContext(this); |
| | mContext->setFormat(requestedFormat()); |
| | mContext->create(); |
| | QSurfaceFormat format; |
| | format.setSamples(16); |
| | format.setSwapInterval(2); |
| | mContext->setFormat(format); |
| | gOpenGlContext = mContext; |
| | mNeedsInitialize = true; |
| | } |
| |
|
| | mContext->makeCurrent(this); |
| |
|
| | if (mNeedsInitialize) { |
| | initializeOpenGLFunctions(); |
| | initialize(); |
| | mNeedsInitialize = false; |
| | } |
| | } |
| |
|
| | void DlgCAMSimulator::doGlCleanup() |
| | { |
| | if (mLastContext != nullptr) { |
| | mLastContext->makeCurrent(this); |
| | } |
| | if (mContext != nullptr) { |
| | mContext->deleteLater(); |
| | mContext = nullptr; |
| | } |
| | } |
| |
|
| | void DlgCAMSimulator::renderNow() |
| | { |
| | static unsigned int lastTime = 0; |
| | static int frameCount = 0; |
| | static int fps = 0; |
| | if (!isExposed()) { |
| | return; |
| | } |
| |
|
| | checkInitialization(); |
| |
|
| | frameCount++; |
| | unsigned int curtime = QDateTime::currentMSecsSinceEpoch(); |
| | unsigned int timediff = curtime - lastTime; |
| | if (timediff > 10000) { |
| | fps = frameCount * 1000 / timediff; |
| | lastTime = curtime; |
| | frameCount = 0; |
| | } |
| | render(); |
| | mContext->swapBuffers(this); |
| |
|
| | if (mAnimating) { |
| | renderLater(); |
| | } |
| | (void)fps; |
| | } |
| |
|
| | void DlgCAMSimulator::setAnimating(bool animating) |
| | { |
| | mAnimating = animating; |
| |
|
| | if (animating) { |
| | renderLater(); |
| | } |
| | } |
| |
|
| | DlgCAMSimulator* DlgCAMSimulator::GetInstance() |
| | { |
| | if (mInstance == nullptr) { |
| | QSurfaceFormat format; |
| | format.setVersion(4, 1); |
| | format.setProfile(QSurfaceFormat::CoreProfile); |
| | int samples = Gui::View3DInventorViewer::getNumSamples(); |
| | if (samples > 1) { |
| | format.setSamples(samples); |
| | } |
| | format.setSwapInterval(2); |
| | format.setDepthBufferSize(24); |
| | format.setStencilBufferSize(8); |
| | mInstance = new DlgCAMSimulator(); |
| | mInstance->setFormat(format); |
| | mInstance->resize(MillSim::gWindowSizeW, MillSim::gWindowSizeH); |
| | mInstance->setModality(Qt::ApplicationModal); |
| | mInstance->setMinimumWidth(700); |
| | mInstance->setMinimumHeight(400); |
| |
|
| | App::Document* doc = App::GetApplication().getActiveDocument(); |
| | mInstance->setTitle(tr("%1 - New CAM Simulator").arg(QString::fromUtf8(doc->getName()))); |
| | } |
| | return mInstance; |
| | } |
| |
|
| | void DlgCAMSimulator::SetStockShape(const Part::TopoShape& shape, float resolution) |
| | { |
| | std::vector<Vertex> verts; |
| | std::vector<GLushort> indices; |
| | GetMeshData(shape, resolution, verts, indices); |
| | mMillSimulator->SetArbitraryStock(verts, indices); |
| | } |
| |
|
| | void DlgCAMSimulator::SetBaseShape(const Part::TopoShape& tshape, float resolution) |
| | { |
| | std::vector<Vertex> verts; |
| | std::vector<GLushort> indices; |
| | GetMeshData(tshape, resolution, verts, indices); |
| | mMillSimulator->SetBaseObject(verts, indices); |
| | } |
| |
|
| | DlgCAMSimulator* DlgCAMSimulator::mInstance = nullptr; |
| |
|
| | |
| | |
| | |
| | SimStock::SimStock(float px, float py, float pz, float lx, float ly, float lz, float res) |
| | : mPx(px) |
| | , mPy(py) |
| | , mPz(pz + 0.005 * lz) |
| | , mLx(lx) |
| | , mLy(ly) |
| | , mLz(1.01 * lz) |
| | { |
| | (void)res; |
| | } |
| |
|
| | SimStock::~SimStock() |
| | {} |
| |
|
| | } |
| |
|