FreeCAD / src /Mod /CAM /PathSimulator /AppGL /DlgCAMSimulator.cpp
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2024 Shai Seger <shaise at gmail> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#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());
// copy triangle indices and calculate normals
for (auto face : facets) {
indices.push_back(face.I1 + nVerts);
indices.push_back(face.I2 + nVerts);
indices.push_back(face.I3 + nVerts);
// calculate normal
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]++;
}
// copy points and set normals
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; // for debug only. not used otherwise.
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); // Request OpenGL 4.1 - for MacOS
format.setProfile(QSurfaceFormat::CoreProfile); // Use the core profile = for MacOS
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;
//************************************************************************************************************
// stock
//************************************************************************************************************
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()
{}
} // namespace CAMSimulator