Merge pull request #22204 from jffmichi/camsim
CAM: integrate new simulator as MDI widget into main window
This commit is contained in:
@@ -38,12 +38,12 @@ TYPESYSTEM_SOURCE(CAMSimulator::CAMSim, Base::BaseClass);
|
||||
|
||||
void CAMSim::BeginSimulation(const Part::TopoShape& stock, float quality)
|
||||
{
|
||||
DlgCAMSimulator::GetInstance()->startSimulation(stock, quality);
|
||||
DlgCAMSimulator::instance()->startSimulation(stock, quality);
|
||||
}
|
||||
|
||||
void CAMSimulator::CAMSim::resetSimulation()
|
||||
{
|
||||
DlgCAMSimulator::GetInstance()->resetSimulation();
|
||||
DlgCAMSimulator::instance()->resetSimulation();
|
||||
}
|
||||
|
||||
void CAMSim::addTool(
|
||||
@@ -53,7 +53,7 @@ void CAMSim::addTool(
|
||||
float resolution
|
||||
)
|
||||
{
|
||||
DlgCAMSimulator::GetInstance()->addTool(toolProfilePoints, toolNumber, diameter, resolution);
|
||||
DlgCAMSimulator::instance()->addTool(toolProfilePoints, toolNumber, diameter, resolution);
|
||||
}
|
||||
|
||||
void CAMSimulator::CAMSim::SetBaseShape(const Part::TopoShape& baseShape, float resolution)
|
||||
@@ -62,11 +62,11 @@ void CAMSimulator::CAMSim::SetBaseShape(const Part::TopoShape& baseShape, float
|
||||
return;
|
||||
}
|
||||
|
||||
DlgCAMSimulator::GetInstance()->SetBaseShape(baseShape, resolution);
|
||||
DlgCAMSimulator::instance()->setBaseShape(baseShape, resolution);
|
||||
}
|
||||
|
||||
void CAMSim::AddCommand(Command* cmd)
|
||||
{
|
||||
std::string gline = cmd->toGCode();
|
||||
DlgCAMSimulator::GetInstance()->addGcodeCommand(gline.c_str());
|
||||
DlgCAMSimulator::instance()->addGcodeCommand(gline.c_str());
|
||||
}
|
||||
|
||||
@@ -69,9 +69,6 @@ public:
|
||||
);
|
||||
void SetBaseShape(const Part::TopoShape& baseShape, float resolution);
|
||||
void AddCommand(Command* cmd);
|
||||
|
||||
public:
|
||||
std::unique_ptr<SimStock> m_stock;
|
||||
};
|
||||
|
||||
} // namespace CAMSimulator
|
||||
|
||||
@@ -24,6 +24,8 @@ SET(CAMSimulator_SRCS_Module
|
||||
DlgCAMSimulator.cpp
|
||||
DlgCAMSimulator.h
|
||||
PreCompiled.h
|
||||
ViewCAMSimulator.cpp
|
||||
ViewCAMSimulator.h
|
||||
)
|
||||
|
||||
SET(CAMSimulator_SRCS_Core
|
||||
|
||||
@@ -24,15 +24,19 @@
|
||||
|
||||
|
||||
#include "DlgCAMSimulator.h"
|
||||
#include "ViewCAMSimulator.h"
|
||||
#include "MillSimulation.h"
|
||||
#include "Gui/View3DInventorViewer.h"
|
||||
#include <Mod/Part/App/BRepMesh.h>
|
||||
#include <QDateTime>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QPoint>
|
||||
#include <QTimerEvent>
|
||||
#include <App/Document.h>
|
||||
|
||||
QOpenGLContext* gOpenGlContext;
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/MDIView.h>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPointer>
|
||||
|
||||
using namespace MillSim;
|
||||
|
||||
@@ -41,99 +45,125 @@ namespace CAMSimulator
|
||||
|
||||
static const float MouseScrollDelta = 120.0F;
|
||||
|
||||
DlgCAMSimulator::DlgCAMSimulator(QWindow* parent)
|
||||
: QWindow(parent)
|
||||
static QPointer<ViewCAMSimulator> viewCAMSimulator;
|
||||
|
||||
DlgCAMSimulator::DlgCAMSimulator(ViewCAMSimulator& view, QWidget* parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, mView(view)
|
||||
{
|
||||
setSurfaceType(QWindow::OpenGLSurface);
|
||||
mMillSimulator = new MillSimulation();
|
||||
// Under certain conditions, e.g. when docking/undocking the cam simulator, we need to create a
|
||||
// new widget (due to some OpenGL bug). The new widget becomes THE cam simulator.
|
||||
|
||||
viewCAMSimulator = &view;
|
||||
|
||||
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);
|
||||
setFormat(format);
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
mMillSimulator.reset(new MillSimulation);
|
||||
|
||||
mAnimatingTimer.setInterval(0);
|
||||
connect(
|
||||
&mAnimatingTimer,
|
||||
&QTimer::timeout,
|
||||
this,
|
||||
static_cast<void (DlgCAMSimulator::*)()>(&DlgCAMSimulator::update)
|
||||
);
|
||||
}
|
||||
|
||||
DlgCAMSimulator::~DlgCAMSimulator()
|
||||
{
|
||||
delete mMillSimulator;
|
||||
makeCurrent();
|
||||
mMillSimulator = nullptr;
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::render(QPainter* painter)
|
||||
void DlgCAMSimulator::cloneFrom(const DlgCAMSimulator& from)
|
||||
{
|
||||
Q_UNUSED(painter);
|
||||
mNeedsInitialize = true;
|
||||
mNeedsClear = true;
|
||||
setAnimating(from.mAnimating);
|
||||
|
||||
mQuality = from.mQuality;
|
||||
|
||||
mGCode = from.mGCode;
|
||||
mTools = from.mTools;
|
||||
|
||||
mStock = from.mStock;
|
||||
mStock.needsUpdate = true;
|
||||
|
||||
mBase = from.mBase;
|
||||
mBase.needsUpdate = true;
|
||||
|
||||
const auto state = from.mMillSimulator->GetState();
|
||||
mState = std::make_unique<MillSim::MillSimulationState>(state);
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::render()
|
||||
DlgCAMSimulator* DlgCAMSimulator::instance()
|
||||
{
|
||||
mMillSimulator->ProcessSim((unsigned int)(QDateTime::currentMSecsSinceEpoch()));
|
||||
}
|
||||
if (!viewCAMSimulator) {
|
||||
auto view = new ViewCAMSimulator(nullptr, nullptr);
|
||||
viewCAMSimulator = view;
|
||||
|
||||
void DlgCAMSimulator::renderLater()
|
||||
{
|
||||
requestUpdate();
|
||||
}
|
||||
|
||||
bool DlgCAMSimulator::event(QEvent* event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::UpdateRequest:
|
||||
renderNow();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
Gui::getMainWindow()->addWindow(view);
|
||||
}
|
||||
return QWindow::event(event);
|
||||
|
||||
return &viewCAMSimulator->dlg();
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::exposeEvent(QExposeEvent* event)
|
||||
void DlgCAMSimulator::setAnimating(bool animating)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
if (animating == mAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isExposed()) {
|
||||
renderNow();
|
||||
mAnimating = animating;
|
||||
|
||||
if (animating) {
|
||||
mAnimatingTimer.start();
|
||||
}
|
||||
else {
|
||||
mAnimatingTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::mouseMoveEvent(QMouseEvent* ev)
|
||||
void DlgCAMSimulator::startSimulation(const Part::TopoShape& stock, float quality)
|
||||
{
|
||||
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;
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
mView.setWindowTitle(tr("%1 - New CAM Simulator").arg(QString::fromUtf8(doc->getName())));
|
||||
|
||||
#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);
|
||||
}
|
||||
mQuality = quality;
|
||||
mNeedsInitialize = true;
|
||||
|
||||
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());
|
||||
}
|
||||
setStockShape(stock, 1);
|
||||
setAnimating(true);
|
||||
|
||||
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);
|
||||
Gui::getMainWindow()->setActiveWindow(&mView);
|
||||
mView.show();
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::resetSimulation()
|
||||
{}
|
||||
{
|
||||
mNeedsClear = true;
|
||||
|
||||
mGCode.clear();
|
||||
mTools.clear();
|
||||
mStock = {};
|
||||
mBase = {};
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::addGcodeCommand(const char* cmd)
|
||||
{
|
||||
mMillSimulator->AddGcodeLine(cmd);
|
||||
mGCode.push_back(cmd);
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::addTool(
|
||||
@@ -144,45 +174,16 @@ void DlgCAMSimulator::addTool(
|
||||
)
|
||||
{
|
||||
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);
|
||||
}
|
||||
addGcodeCommand(toolCmd.c_str());
|
||||
mTools.emplace_back(toolProfilePoints, toolNumber, diameter);
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::hideEvent(QHideEvent* ev)
|
||||
static SimShape getMeshData(const Part::TopoShape& tshape, float resolution)
|
||||
{
|
||||
mMillSimulator->Clear();
|
||||
doGlCleanup();
|
||||
mAnimating = false;
|
||||
QWindow::hideEvent(ev);
|
||||
close();
|
||||
mInstance = nullptr;
|
||||
}
|
||||
SimShape ret;
|
||||
|
||||
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)) {
|
||||
@@ -195,9 +196,9 @@ void DlgCAMSimulator::GetMeshData(
|
||||
|
||||
// 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);
|
||||
ret.indices.push_back(face.I1 + nVerts);
|
||||
ret.indices.push_back(face.I2 + nVerts);
|
||||
ret.indices.push_back(face.I3 + nVerts);
|
||||
|
||||
// calculate normal
|
||||
Base::Vector3d vAB = points[face.I2] - points[face.I1];
|
||||
@@ -219,162 +220,158 @@ void DlgCAMSimulator::GetMeshData(
|
||||
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));
|
||||
ret.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;
|
||||
nVerts = ret.verts.size();
|
||||
}
|
||||
|
||||
mContext->makeCurrent(this);
|
||||
ret.needsUpdate = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::setStockShape(const Part::TopoShape& shape, float resolution)
|
||||
{
|
||||
mStock = getMeshData(shape, resolution);
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::setBaseShape(const Part::TopoShape& tshape, float resolution)
|
||||
{
|
||||
mBase = getMeshData(tshape, resolution);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const qreal ratio = devicePixelRatioF();
|
||||
mMillSimulator->MouseMove(pnt.x() * ratio, pnt.y() * ratio, modifiers);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const qreal ratio = devicePixelRatioF();
|
||||
mMillSimulator->MousePress(ev->button(), true, pnt.x() * ratio, pnt.y() * ratio);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
const qreal ratio = devicePixelRatioF();
|
||||
mMillSimulator->MousePress(ev->button(), false, pnt.x() * ratio, pnt.y() * ratio);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::wheelEvent(QWheelEvent* ev)
|
||||
{
|
||||
mMillSimulator->MouseScroll((float)ev->angleDelta().y() / MouseScrollDelta);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::updateResources()
|
||||
{
|
||||
// clear simulator
|
||||
|
||||
if (mNeedsClear) {
|
||||
mMillSimulator->Clear();
|
||||
mLastGCode = 0;
|
||||
mNeedsClear = false;
|
||||
}
|
||||
|
||||
// update gcode
|
||||
|
||||
for (int i = mLastGCode; i < (int)mGCode.size(); i++) {
|
||||
const std::string& cmd = mGCode[i];
|
||||
mMillSimulator->AddGcodeLine(cmd.c_str());
|
||||
}
|
||||
|
||||
mLastGCode = mGCode.size();
|
||||
|
||||
// update tools
|
||||
|
||||
for (const auto& tool : mTools) {
|
||||
if (!mMillSimulator->ToolExists(tool.id)) {
|
||||
mMillSimulator->AddTool(tool.profile, tool.id, tool.diameter);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize simulator
|
||||
|
||||
if (mNeedsInitialize) {
|
||||
initializeOpenGLFunctions();
|
||||
initialize();
|
||||
mMillSimulator->InitSimulation(mQuality);
|
||||
mNeedsInitialize = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::doGlCleanup()
|
||||
{
|
||||
if (mLastContext != nullptr) {
|
||||
mLastContext->makeCurrent(this);
|
||||
// update stock and base
|
||||
|
||||
if (mStock.needsUpdate) {
|
||||
mMillSimulator->SetArbitraryStock(mStock.verts, mStock.indices);
|
||||
mStock.needsUpdate = false;
|
||||
}
|
||||
if (mContext != nullptr) {
|
||||
mContext->deleteLater();
|
||||
mContext = nullptr;
|
||||
|
||||
if (mBase.needsUpdate) {
|
||||
mMillSimulator->SetBaseObject(mBase.verts, mBase.indices);
|
||||
mBase.needsUpdate = false;
|
||||
}
|
||||
|
||||
// update state
|
||||
|
||||
if (mState) {
|
||||
mMillSimulator->SetState(*mState);
|
||||
mState = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::renderNow()
|
||||
void DlgCAMSimulator::updateWindowScale()
|
||||
{
|
||||
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;
|
||||
const qreal ratio = devicePixelRatioF();
|
||||
mMillSimulator->UpdateWindowScale(width() * ratio, height() * ratio);
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::setAnimating(bool animating)
|
||||
void DlgCAMSimulator::initializeGL()
|
||||
{
|
||||
mAnimating = animating;
|
||||
|
||||
if (animating) {
|
||||
renderLater();
|
||||
}
|
||||
initializeOpenGLFunctions();
|
||||
}
|
||||
|
||||
DlgCAMSimulator* DlgCAMSimulator::GetInstance()
|
||||
void DlgCAMSimulator::paintGL()
|
||||
{
|
||||
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);
|
||||
updateResources();
|
||||
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
mInstance->setTitle(tr("%1 - New CAM Simulator").arg(QString::fromUtf8(doc->getName())));
|
||||
}
|
||||
return mInstance;
|
||||
// We need to call updateWindowScale on every render since the devicePixelRatio we get in
|
||||
// resizeGL might be wrong on the first resize.
|
||||
updateWindowScale();
|
||||
|
||||
mMillSimulator->ProcessSim((unsigned int)(QDateTime::currentMSecsSinceEpoch()));
|
||||
}
|
||||
|
||||
void DlgCAMSimulator::SetStockShape(const Part::TopoShape& shape, float resolution)
|
||||
void DlgCAMSimulator::resizeGL(int w, int h)
|
||||
{
|
||||
std::vector<Vertex> verts;
|
||||
std::vector<GLushort> indices;
|
||||
GetMeshData(shape, resolution, verts, indices);
|
||||
mMillSimulator->SetArbitraryStock(verts, indices);
|
||||
(void)w, (void)h;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -29,10 +29,14 @@
|
||||
# pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <QWindow>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QExposeEvent>
|
||||
#include <QResizeEvent>
|
||||
#include <QMouseEvent>
|
||||
@@ -42,44 +46,53 @@ namespace MillSim
|
||||
{
|
||||
// use short declaration as using 'include' causes a header loop
|
||||
class MillSimulation;
|
||||
class MillSimulationState;
|
||||
struct Vertex;
|
||||
} // namespace MillSim
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
class MDIView;
|
||||
}
|
||||
|
||||
namespace CAMSimulator
|
||||
{
|
||||
|
||||
struct SimStock
|
||||
class ViewCAMSimulator;
|
||||
|
||||
struct SimShape
|
||||
{
|
||||
public:
|
||||
SimStock(float px, float py, float pz, float lx, float ly, float lz, float res);
|
||||
~SimStock();
|
||||
|
||||
public:
|
||||
float mPx, mPy, mPz; // stock zero position
|
||||
float mLx, mLy, mLz; // stock dimensions
|
||||
std::vector<MillSim::Vertex> verts;
|
||||
std::vector<GLushort> indices;
|
||||
bool needsUpdate = false;
|
||||
};
|
||||
|
||||
class DlgCAMSimulator: public QWindow, public QOpenGLExtraFunctions
|
||||
struct SimTool
|
||||
{
|
||||
public:
|
||||
std::vector<float> profile;
|
||||
int id;
|
||||
float diameter;
|
||||
float resolution;
|
||||
};
|
||||
|
||||
class DlgCAMSimulator: public QOpenGLWidget, public QOpenGLExtraFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgCAMSimulator(QWindow* parent = nullptr);
|
||||
explicit DlgCAMSimulator(ViewCAMSimulator& view, QWidget* parent = nullptr);
|
||||
~DlgCAMSimulator() override;
|
||||
|
||||
virtual void render(QPainter* painter);
|
||||
virtual void render();
|
||||
virtual void initialize();
|
||||
void cloneFrom(const DlgCAMSimulator& from);
|
||||
|
||||
static DlgCAMSimulator* instance();
|
||||
|
||||
void setAnimating(bool animating);
|
||||
static DlgCAMSimulator* GetInstance();
|
||||
void SetStockShape(const Part::TopoShape& tshape, float resolution);
|
||||
void SetBaseShape(const Part::TopoShape& tshape, float resolution);
|
||||
|
||||
public: // slots:
|
||||
void renderLater();
|
||||
void renderNow();
|
||||
void startSimulation(const Part::TopoShape& stock, float quality);
|
||||
void resetSimulation();
|
||||
|
||||
void addGcodeCommand(const char* cmd);
|
||||
void addTool(
|
||||
const std::vector<float>& toolProfilePoints,
|
||||
@@ -88,37 +101,44 @@ public: // slots:
|
||||
float resolution
|
||||
);
|
||||
|
||||
void setStockShape(const Part::TopoShape& tshape, float resolution);
|
||||
void setBaseShape(const Part::TopoShape& tshape, float resolution);
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event) override;
|
||||
void checkInitialization();
|
||||
void doGlCleanup();
|
||||
void exposeEvent(QExposeEvent* event) override;
|
||||
void mouseMoveEvent(QMouseEvent* ev) override;
|
||||
void mousePressEvent(QMouseEvent* ev) override;
|
||||
void mouseReleaseEvent(QMouseEvent* ev) override;
|
||||
void wheelEvent(QWheelEvent* ev) override;
|
||||
void hideEvent(QHideEvent* ev) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
void GetMeshData(
|
||||
const Part::TopoShape& tshape,
|
||||
float resolution,
|
||||
std::vector<MillSim::Vertex>& verts,
|
||||
std::vector<GLushort>& indices
|
||||
);
|
||||
|
||||
void updateResources();
|
||||
void updateWindowScale();
|
||||
|
||||
void initializeGL() override;
|
||||
void paintGL() override;
|
||||
void resizeGL(int w, int h) override;
|
||||
|
||||
private:
|
||||
bool mAnimating = false;
|
||||
bool mNeedsInitialize = false;
|
||||
bool mNeedsClear = false;
|
||||
bool mAnimating = false;
|
||||
QTimer mAnimatingTimer;
|
||||
|
||||
QOpenGLContext* mContext = nullptr;
|
||||
QOpenGLContext* mLastContext = nullptr;
|
||||
MillSim::MillSimulation* mMillSimulator = nullptr;
|
||||
static DlgCAMSimulator* mInstance;
|
||||
std::unique_ptr<MillSim::MillSimulation> mMillSimulator;
|
||||
float mQuality = 10;
|
||||
};
|
||||
|
||||
std::vector<std::string> mGCode;
|
||||
std::size_t mLastGCode = 0;
|
||||
|
||||
std::vector<SimTool> mTools;
|
||||
|
||||
SimShape mStock;
|
||||
SimShape mBase;
|
||||
|
||||
ViewCAMSimulator& mView;
|
||||
|
||||
std::unique_ptr<MillSim::MillSimulationState> mState;
|
||||
};
|
||||
|
||||
} // namespace CAMSimulator
|
||||
|
||||
|
||||
#endif // PATHSIMULATOR_PathSim_H
|
||||
|
||||
@@ -27,12 +27,8 @@
|
||||
|
||||
namespace MillSim
|
||||
{
|
||||
int gWindowSizeW = 800;
|
||||
int gWindowSizeH = 600;
|
||||
|
||||
int gDebug = -1;
|
||||
|
||||
mat4x4 identityMat = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
|
||||
const mat4x4 identityMat = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}};
|
||||
|
||||
void GLClearError()
|
||||
{
|
||||
@@ -50,11 +46,4 @@ bool GLLogError()
|
||||
return isError;
|
||||
}
|
||||
|
||||
|
||||
typedef struct Vertex
|
||||
{
|
||||
vec3 pos;
|
||||
vec3 col;
|
||||
} Vertex;
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
#ifndef __glutils_h__
|
||||
#define __glutils_h__
|
||||
|
||||
#include "OpenGlWrapper.h"
|
||||
#include "linmath.h"
|
||||
|
||||
|
||||
constexpr auto EPSILON = 0.00001f;
|
||||
#define EQ_FLOAT(x, y) (fabs((x) - (y)) < EPSILON)
|
||||
|
||||
@@ -46,7 +46,6 @@ constexpr auto EPSILON = 0.00001f;
|
||||
__debugbreak(); \
|
||||
}
|
||||
|
||||
|
||||
#define GLDELETE(type, x) \
|
||||
{ \
|
||||
if (x != 0) \
|
||||
@@ -62,11 +61,12 @@ constexpr auto EPSILON = 0.00001f;
|
||||
|
||||
namespace MillSim
|
||||
{
|
||||
|
||||
extern const mat4x4 identityMat;
|
||||
|
||||
void GLClearError();
|
||||
bool GLLogError();
|
||||
extern mat4x4 identityMat;
|
||||
extern int gDebug;
|
||||
extern int gWindowSizeW;
|
||||
extern int gWindowSizeH;
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
#endif // !__glutils_h__
|
||||
|
||||
@@ -30,12 +30,11 @@
|
||||
#include <QPoint>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
using namespace MillSim;
|
||||
|
||||
// clang-format off
|
||||
// NOLINTBEGIN(*-magic-numbers)
|
||||
GuiItem guiItems[] = {
|
||||
static const std::vector<DefaultGuiItem> defaultGuiItems = {
|
||||
{.name=eGuiItemSlider, .vbo=0, .vao=0, .sx=28, .sy=-80, .actionKey=0, .hidden=false, .flags=0},
|
||||
{.name=eGuiItemThumb, .vbo=0, .vao=0, .sx=328, .sy=-94, .actionKey=1, .hidden=false, .flags=0},
|
||||
{.name=eGuiItemPause, .vbo=0, .vao=0, .sx=28, .sy=-50, .actionKey='P', .hidden=true, .flags=0},
|
||||
@@ -58,10 +57,9 @@ GuiItem guiItems[] = {
|
||||
// NOLINTEND(*-magic-numbers)
|
||||
// clang-format on
|
||||
|
||||
#define NUM_GUI_ITEMS (sizeof(guiItems) / sizeof(GuiItem))
|
||||
#define TEX_SIZE 256
|
||||
|
||||
std::vector<std::string> guiFileNames = {
|
||||
static const std::vector<std::string> guiFileNames = {
|
||||
"Slider.png",
|
||||
"Thumb.png",
|
||||
"Pause.png",
|
||||
@@ -82,17 +80,49 @@ std::vector<std::string> guiFileNames = {
|
||||
"Home.png"
|
||||
};
|
||||
|
||||
GuiItem::GuiItem(const DefaultGuiItem& item, GuiDisplay& d)
|
||||
: DefaultGuiItem(item)
|
||||
, display(d)
|
||||
{}
|
||||
|
||||
int GuiItem::posx()
|
||||
{
|
||||
return sx >= 0 ? sx : display.width() + sx;
|
||||
}
|
||||
|
||||
int GuiItem::posy()
|
||||
{
|
||||
return sy >= 0 ? sy : display.height() + sy;
|
||||
}
|
||||
|
||||
void GuiItem::setPosx(int x)
|
||||
{
|
||||
sx = sx >= 0 ? x : x - display.width();
|
||||
}
|
||||
|
||||
void GuiItem::setPosy(int y)
|
||||
{
|
||||
sy = sy >= 0 ? y : y - display.height();
|
||||
}
|
||||
|
||||
GuiDisplay::GuiDisplay()
|
||||
{
|
||||
for (auto& item : defaultGuiItems) {
|
||||
mItems.emplace_back(item, *this);
|
||||
}
|
||||
}
|
||||
|
||||
void GuiDisplay::UpdateProjection()
|
||||
{
|
||||
mat4x4 projmat;
|
||||
// mat4x4 viewmat;
|
||||
mat4x4_ortho(projmat, 0, gWindowSizeW, gWindowSizeH, 0, -1, 1);
|
||||
mat4x4_ortho(projmat, 0, mWidth, mHeight, 0, -1, 1);
|
||||
mShader.Activate();
|
||||
mShader.UpdateProjectionMat(projmat);
|
||||
mThumbMaxMotion = guiItems[eGuiItemAmbientOclusion].posx()
|
||||
+ guiItems[eGuiItemAmbientOclusion].texItem.w
|
||||
- guiItems[eGuiItemSlider].posx(); // - guiItems[eGuiItemThumb].texItem.w;
|
||||
HStretchGlItem(&(guiItems[eGuiItemSlider]), mThumbMaxMotion, 10.0f);
|
||||
mThumbMaxMotion = mItems[eGuiItemAmbientOclusion].posx()
|
||||
+ mItems[eGuiItemAmbientOclusion].texItem.w
|
||||
- mItems[eGuiItemSlider].posx(); // - guiItems[eGuiItemThumb].texItem.w;
|
||||
HStretchGlItem(&(mItems[eGuiItemSlider]), mThumbMaxMotion, 10.0f);
|
||||
}
|
||||
|
||||
bool GuiDisplay::GenerateGlItem(GuiItem* guiItem)
|
||||
@@ -127,7 +157,7 @@ bool GuiDisplay::GenerateGlItem(GuiItem* guiItem)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MillSim::GuiDisplay::HStretchGlItem(GuiItem* guiItem, float newWidth, float edgeWidth)
|
||||
bool GuiDisplay::HStretchGlItem(GuiItem* guiItem, float newWidth, float edgeWidth)
|
||||
{
|
||||
if (guiItem->vbo == 0) {
|
||||
return false;
|
||||
@@ -190,6 +220,7 @@ bool GuiDisplay::InitGui()
|
||||
if (guiInitiated) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// index buffer
|
||||
SetupTooltips();
|
||||
glGenBuffers(1, &mIbo);
|
||||
@@ -202,29 +233,32 @@ bool GuiDisplay::InitGui()
|
||||
return false;
|
||||
}
|
||||
mTexture.LoadImage(buffer, TEX_SIZE, TEX_SIZE);
|
||||
for (unsigned int i = 0; i < NUM_GUI_ITEMS; i++) {
|
||||
guiItems[i].texItem = *tLoader.GetTextureItem(i);
|
||||
GenerateGlItem(&(guiItems[i]));
|
||||
for (unsigned int i = 0; i < mItems.size(); i++) {
|
||||
auto& item = mItems[i];
|
||||
item.texItem = *tLoader.GetTextureItem(i);
|
||||
GenerateGlItem(&item);
|
||||
}
|
||||
|
||||
mThumbStartX = guiItems[eGuiItemSlider].posx() - guiItems[eGuiItemThumb].texItem.w / 2;
|
||||
mThumbMaxMotion = (float)guiItems[eGuiItemSlider].texItem.w;
|
||||
mThumbStartX = mItems[eGuiItemSlider].posx() - mItems[eGuiItemThumb].texItem.w / 2;
|
||||
mThumbMaxMotion = (float)mItems[eGuiItemSlider].texItem.w;
|
||||
|
||||
// init shader
|
||||
mShader.CompileShader("GuiDisplay", (char*)VertShader2DTex, (char*)FragShader2dTex);
|
||||
mShader.UpdateTextureSlot(0);
|
||||
|
||||
UpdatePlayState(false);
|
||||
UpdateSimSpeed(1);
|
||||
UpdateProjection();
|
||||
guiInitiated = true;
|
||||
|
||||
UpdateWindowScale(800, 600);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiDisplay::ResetGui()
|
||||
{
|
||||
mShader.Destroy();
|
||||
for (unsigned int i = 0; i < NUM_GUI_ITEMS; i++) {
|
||||
DestroyGlItem(&(guiItems[i]));
|
||||
for (auto& item : mItems) {
|
||||
DestroyGlItem(&item);
|
||||
}
|
||||
mTexture.DestroyTexture();
|
||||
GLDELETE_BUFFER(mIbo);
|
||||
@@ -233,13 +267,13 @@ void GuiDisplay::ResetGui()
|
||||
|
||||
void GuiDisplay::RenderItem(int itemId)
|
||||
{
|
||||
GuiItem* item = &(guiItems[itemId]);
|
||||
GuiItem* item = &(mItems[itemId]);
|
||||
if (item->hidden) {
|
||||
return;
|
||||
}
|
||||
mat4x4 model;
|
||||
mat4x4_translate(model, (float)item->posx(), (float)item->posy(), 0);
|
||||
mShader.UpdateModelMat(model, nullptr);
|
||||
mShader.UpdateModelMat(model, {});
|
||||
if (item == mPressedItem) {
|
||||
mShader.UpdateObjColor(mPressedColor);
|
||||
}
|
||||
@@ -262,33 +296,33 @@ void GuiDisplay::RenderItem(int itemId)
|
||||
glDrawElements(GL_TRIANGLES, nTriangles, GL_UNSIGNED_SHORT, nullptr);
|
||||
}
|
||||
|
||||
void MillSim::GuiDisplay::SetupTooltips()
|
||||
void GuiDisplay::SetupTooltips()
|
||||
{
|
||||
guiItems[eGuiItemPause].toolTip
|
||||
mItems[eGuiItemPause].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Pause simulation", nullptr);
|
||||
guiItems[eGuiItemPlay].toolTip
|
||||
mItems[eGuiItemPlay].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Play simulation", nullptr);
|
||||
guiItems[eGuiItemSingleStep].toolTip
|
||||
mItems[eGuiItemSingleStep].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Single step simulation", nullptr);
|
||||
guiItems[eGuiItemSlower].toolTip
|
||||
mItems[eGuiItemSlower].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Decrease simulation speed", nullptr);
|
||||
guiItems[eGuiItemFaster].toolTip
|
||||
mItems[eGuiItemFaster].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Increase simulation speed", nullptr);
|
||||
guiItems[eGuiItemPath].toolTip
|
||||
mItems[eGuiItemPath].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Show/Hide tool path", nullptr);
|
||||
guiItems[eGuiItemRotate].toolTip = QCoreApplication::translate(
|
||||
mItems[eGuiItemRotate].toolTip = QCoreApplication::translate(
|
||||
"CAM:Simulator:Tooltips",
|
||||
"Toggle turn table animation",
|
||||
nullptr
|
||||
);
|
||||
guiItems[eGuiItemAmbientOclusion].toolTip
|
||||
mItems[eGuiItemAmbientOclusion].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Toggle ambient occlusion", nullptr);
|
||||
guiItems[eGuiItemView].toolTip = QCoreApplication::translate(
|
||||
mItems[eGuiItemView].toolTip = QCoreApplication::translate(
|
||||
"CAM:Simulator:Tooltips",
|
||||
"Toggle view simulation/model",
|
||||
nullptr
|
||||
);
|
||||
guiItems[eGuiItemHome].toolTip
|
||||
mItems[eGuiItemHome].toolTip
|
||||
= QCoreApplication::translate("CAM:Simulator:Tooltips", "Reset camera", nullptr);
|
||||
}
|
||||
|
||||
@@ -296,24 +330,25 @@ void GuiDisplay::MouseCursorPos(int x, int y)
|
||||
{
|
||||
GuiItem* prevMouseOver = mMouseOverItem;
|
||||
mMouseOverItem = nullptr;
|
||||
for (unsigned int i = 0; i < NUM_GUI_ITEMS; i++) {
|
||||
GuiItem* g = &(guiItems[i]);
|
||||
if (g->actionKey == 0) {
|
||||
for (auto& item : mItems) {
|
||||
if (item.actionKey == 0) {
|
||||
continue;
|
||||
}
|
||||
bool mouseCursorContained = x > g->posx() && x < (g->posx() + g->texItem.w) && y > g->posy()
|
||||
&& y < (g->posy() + g->texItem.h);
|
||||
bool mouseCursorContained = x > item.posx() && x < (item.posx() + item.texItem.w)
|
||||
&& y > item.posy() && y < (item.posy() + item.texItem.h);
|
||||
|
||||
g->mouseOver = !g->hidden && mouseCursorContained;
|
||||
item.mouseOver = !item.hidden && mouseCursorContained;
|
||||
|
||||
if (g->mouseOver) {
|
||||
mMouseOverItem = g;
|
||||
if (item.mouseOver) {
|
||||
mMouseOverItem = &item;
|
||||
}
|
||||
}
|
||||
if (mMouseOverItem != prevMouseOver) {
|
||||
if (mMouseOverItem != nullptr && !mMouseOverItem->toolTip.isEmpty()) {
|
||||
QPoint pos(x, y);
|
||||
QPoint globPos = CAMSimulator::DlgCAMSimulator::GetInstance()->mapToGlobal(pos);
|
||||
const QWidget* w = CAMSimulator::DlgCAMSimulator::instance();
|
||||
const float ratio = w->devicePixelRatioF();
|
||||
const QPoint pos(x / ratio, y / ratio);
|
||||
const QPoint globPos = w->mapToGlobal(pos);
|
||||
QToolTip::showText(globPos, mMouseOverItem->toolTip);
|
||||
}
|
||||
else {
|
||||
@@ -322,7 +357,7 @@ void GuiDisplay::MouseCursorPos(int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
void MillSim::GuiDisplay::HandleActionItem(GuiItem* guiItem)
|
||||
void GuiDisplay::HandleActionItem(GuiItem* guiItem)
|
||||
{
|
||||
if (guiItem->actionKey >= ' ') {
|
||||
if (guiItem->flags & GUIITEM_CHECKABLE) {
|
||||
@@ -373,45 +408,66 @@ void GuiDisplay::MouseDrag(int /* buttons */, int dx, int /* dy */)
|
||||
}
|
||||
}
|
||||
|
||||
void GuiDisplay::SetMillSimulator(MillSimulation* millSim)
|
||||
{
|
||||
mMillSim = millSim;
|
||||
}
|
||||
|
||||
void GuiDisplay::UpdatePlayState(bool isRunning)
|
||||
{
|
||||
guiItems[eGuiItemPause].hidden = !isRunning;
|
||||
guiItems[eGuiItemPlay].hidden = isRunning;
|
||||
mItems[eGuiItemPause].hidden = !isRunning;
|
||||
mItems[eGuiItemPlay].hidden = isRunning;
|
||||
}
|
||||
|
||||
void MillSim::GuiDisplay::UpdateSimSpeed(int speed)
|
||||
void GuiDisplay::UpdateSimSpeed(int speed)
|
||||
{
|
||||
guiItems[eGuiItem1].hidden = speed != 1;
|
||||
guiItems[eGuiItem5].hidden = speed != 5;
|
||||
guiItems[eGuiItem10].hidden = speed != 10;
|
||||
guiItems[eGuiItem25].hidden = speed != 25;
|
||||
guiItems[eGuiItem50].hidden = speed != 50;
|
||||
mItems[eGuiItem1].hidden = speed != 1;
|
||||
mItems[eGuiItem5].hidden = speed != 5;
|
||||
mItems[eGuiItem10].hidden = speed != 10;
|
||||
mItems[eGuiItem25].hidden = speed != 25;
|
||||
mItems[eGuiItem50].hidden = speed != 50;
|
||||
}
|
||||
|
||||
void MillSim::GuiDisplay::HandleKeyPress(int key)
|
||||
void GuiDisplay::HandleKeyPress(int key)
|
||||
{
|
||||
for (unsigned int i = 0; i < NUM_GUI_ITEMS; i++) {
|
||||
GuiItem* g = &(guiItems[i]);
|
||||
if (g->actionKey == key) {
|
||||
HandleActionItem(g);
|
||||
for (auto& item : mItems) {
|
||||
if (item.actionKey == key) {
|
||||
HandleActionItem(&item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MillSim::GuiDisplay::IsChecked(eGuiItems item)
|
||||
bool GuiDisplay::IsChecked(eGuiItems item)
|
||||
{
|
||||
return (guiItems[item].flags & GUIITEM_CHECKED) != 0;
|
||||
return (mItems[item].flags & GUIITEM_CHECKED) != 0;
|
||||
}
|
||||
|
||||
void MillSim::GuiDisplay::UpdateWindowScale()
|
||||
void GuiDisplay::UpdateWindowScale(int width, int height)
|
||||
{
|
||||
if (!guiInitiated || (width == mWidth && height == mHeight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
UpdateProjection();
|
||||
}
|
||||
|
||||
int GuiDisplay::width() const
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
int GuiDisplay::height() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
void GuiDisplay::Render(float progress)
|
||||
{
|
||||
if (mPressedItem == nullptr || mPressedItem->name != eGuiItemThumb) {
|
||||
guiItems[eGuiItemThumb].setPosx((int)(mThumbMaxMotion * progress) + mThumbStartX);
|
||||
mItems[eGuiItemThumb].setPosx((int)(mThumbMaxMotion * progress) + mThumbStartX);
|
||||
}
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@@ -421,7 +477,7 @@ void GuiDisplay::Render(float progress)
|
||||
mShader.UpdateTextureSlot(0);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
for (int i = 0; i < (int)NUM_GUI_ITEMS; i++) {
|
||||
for (int i = 0; i < (int)mItems.size(); i++) {
|
||||
RenderItem(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ enum eGuiItems
|
||||
eGuiItemMax // this element must be the last item always
|
||||
};
|
||||
|
||||
struct GuiItem
|
||||
struct DefaultGuiItem
|
||||
{
|
||||
eGuiItems name;
|
||||
unsigned int vbo, vao;
|
||||
@@ -66,33 +66,32 @@ struct GuiItem
|
||||
int actionKey; // action key when item pressed
|
||||
bool hidden {}; // is item hidden
|
||||
unsigned int flags {};
|
||||
};
|
||||
|
||||
class GuiDisplay;
|
||||
|
||||
class GuiItem: public DefaultGuiItem
|
||||
{
|
||||
public:
|
||||
explicit GuiItem(const DefaultGuiItem& item, GuiDisplay& d);
|
||||
|
||||
int posx();
|
||||
int posy();
|
||||
void setPosx(int x);
|
||||
void setPosy(int y);
|
||||
|
||||
public:
|
||||
bool mouseOver {};
|
||||
TextureItem texItem {};
|
||||
QString toolTip {};
|
||||
|
||||
int posx()
|
||||
{
|
||||
return sx >= 0 ? sx : gWindowSizeW + sx;
|
||||
}
|
||||
int posy()
|
||||
{
|
||||
return sy >= 0 ? sy : gWindowSizeH + sy;
|
||||
}
|
||||
void setPosx(int x)
|
||||
{
|
||||
sx = sx >= 0 ? x : x - gWindowSizeW;
|
||||
}
|
||||
void setPosy(int y)
|
||||
{
|
||||
sy = sy >= 0 ? y : y - gWindowSizeH;
|
||||
}
|
||||
GuiDisplay& display;
|
||||
};
|
||||
|
||||
#define GUIITEM_CHECKABLE 0x01
|
||||
#define GUIITEM_CHECKED 0x02
|
||||
#define GUIITEM_STRETCHED 0x04
|
||||
|
||||
|
||||
struct Vertex2D
|
||||
{
|
||||
float x, y;
|
||||
@@ -102,7 +101,8 @@ struct Vertex2D
|
||||
class GuiDisplay
|
||||
{
|
||||
public:
|
||||
// GuiDisplay() {};
|
||||
GuiDisplay();
|
||||
|
||||
bool InitGui();
|
||||
void ResetGui();
|
||||
void Render(float progress);
|
||||
@@ -110,15 +110,15 @@ public:
|
||||
void HandleActionItem(GuiItem* guiItem);
|
||||
void MousePressed(int button, bool isPressed, bool isRunning);
|
||||
void MouseDrag(int buttons, int dx, int dy);
|
||||
void SetMillSimulator(MillSimulation* millSim)
|
||||
{
|
||||
mMillSim = millSim;
|
||||
}
|
||||
void SetMillSimulator(MillSimulation* millSim);
|
||||
void UpdatePlayState(bool isRunning);
|
||||
void UpdateSimSpeed(int speed);
|
||||
void HandleKeyPress(int key);
|
||||
bool IsChecked(eGuiItems item);
|
||||
void UpdateWindowScale();
|
||||
void UpdateWindowScale(int width, int height);
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
||||
public:
|
||||
bool guiInitiated = false;
|
||||
@@ -131,6 +131,11 @@ private:
|
||||
void RenderItem(int itemId);
|
||||
void SetupTooltips();
|
||||
|
||||
std::vector<GuiItem> mItems;
|
||||
|
||||
int mWidth = -1;
|
||||
int mHeight = -1;
|
||||
|
||||
vec3 mStdColor = {0.8f, 0.8f, 0.4f};
|
||||
vec3 mToggleColor = {0.9f, 0.6f, 0.2f};
|
||||
vec3 mHighlightColor = {1.0f, 1.0f, 0.9f};
|
||||
|
||||
@@ -55,8 +55,8 @@ struct MillMotion
|
||||
float x, y, z;
|
||||
float i, j, k;
|
||||
float r;
|
||||
char retract_mode;
|
||||
float retract_z;
|
||||
char retract_mode = 0;
|
||||
float retract_z = NAN;
|
||||
};
|
||||
|
||||
static inline void MotionPosToVec(vec3 vec, const MillMotion* motion)
|
||||
|
||||
@@ -89,11 +89,11 @@ void MillSimulation::SimNext()
|
||||
}
|
||||
}
|
||||
|
||||
void MillSimulation::InitSimulation(float quality, qreal devicePixelRatio)
|
||||
void MillSimulation::InitSimulation(float quality)
|
||||
{
|
||||
ClearMillPathSegments();
|
||||
millPathLine.Clear();
|
||||
simDisplay.applySSAO = guiDisplay.IsChecked(eGuiItemAmbientOclusion);
|
||||
mViewSSAO = guiDisplay.IsChecked(eGuiItemAmbientOclusion);
|
||||
|
||||
mDestMotion = mZeroPos;
|
||||
// gDestPos = curMillOperation->startPos;
|
||||
@@ -121,7 +121,7 @@ void MillSimulation::InitSimulation(float quality, qreal devicePixelRatio)
|
||||
}
|
||||
mNPathSteps = (int)MillPathSegments.size();
|
||||
millPathLine.GenerateModel();
|
||||
InitDisplay(quality, devicePixelRatio);
|
||||
InitDisplay(quality);
|
||||
}
|
||||
|
||||
EndMill* MillSimulation::GetTool(int toolId)
|
||||
@@ -163,6 +163,11 @@ void MillSimulation::AddTool(const std::vector<float>& toolProfile, int toolid,
|
||||
mToolTable.push_back(tool);
|
||||
}
|
||||
|
||||
bool MillSimulation::ToolExists(int toolid)
|
||||
{
|
||||
return GetTool(toolid) != nullptr;
|
||||
}
|
||||
|
||||
void MillSimulation::GlsimStart()
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
@@ -340,7 +345,7 @@ void MillSimulation::RenderTool()
|
||||
|
||||
void MillSimulation::RenderPath()
|
||||
{
|
||||
if (!guiDisplay.IsChecked(eGuiItemPath)) {
|
||||
if (!mViewPath) {
|
||||
return;
|
||||
}
|
||||
simDisplay.SetupLinePathPass(mPathStep, false);
|
||||
@@ -378,10 +383,10 @@ void MillSimulation::Render()
|
||||
RenderBaseShape();
|
||||
RenderPath();
|
||||
simDisplay.updateDisplay = false;
|
||||
simDisplay.RenderResult(true);
|
||||
simDisplay.RenderResult(true, mViewSSAO);
|
||||
}
|
||||
else {
|
||||
simDisplay.RenderResult(false);
|
||||
simDisplay.RenderResult(false, mViewSSAO);
|
||||
}
|
||||
|
||||
/* if (mDebug > 0) {
|
||||
@@ -446,7 +451,6 @@ void MillSimulation::HandleKeyPress(int key)
|
||||
}
|
||||
else if (key == 'K') {
|
||||
mDebug2++;
|
||||
gDebug = mNPathSteps - mDebug2;
|
||||
}
|
||||
else {
|
||||
guiDisplay.HandleKeyPress(key);
|
||||
@@ -502,11 +506,12 @@ void MillSimulation::HandleGuiAction(eGuiItems actionItem, bool checked)
|
||||
break;
|
||||
|
||||
case eGuiItemPath:
|
||||
mViewPath = checked;
|
||||
simDisplay.updateDisplay = true;
|
||||
break;
|
||||
|
||||
case eGuiItemAmbientOclusion:
|
||||
simDisplay.applySSAO = checked;
|
||||
mViewSSAO = checked;
|
||||
simDisplay.updateDisplay = true;
|
||||
break;
|
||||
|
||||
@@ -529,15 +534,19 @@ void MillSimulation::HandleGuiAction(eGuiItems actionItem, bool checked)
|
||||
}
|
||||
|
||||
|
||||
void MillSimulation::InitDisplay(float quality, qreal devicePixelRatio)
|
||||
void MillSimulation::InitDisplay(float quality)
|
||||
{
|
||||
// generate tools
|
||||
for (unsigned int i = 0; i < mToolTable.size(); i++) {
|
||||
mToolTable[i]->GenerateDisplayLists(quality);
|
||||
}
|
||||
|
||||
// Make sure the next call to UpdateWindowScale will not return early.
|
||||
mWidth = -1;
|
||||
mHeight = -1;
|
||||
|
||||
// init 3d display
|
||||
simDisplay.InitGL(devicePixelRatio);
|
||||
simDisplay.InitGL();
|
||||
|
||||
// init gui elements
|
||||
guiDisplay.InitGui();
|
||||
@@ -549,13 +558,16 @@ void MillSimulation::SetBoxStock(float x, float y, float z, float l, float w, fl
|
||||
simDisplay.ScaleViewToStock(&mStockObject);
|
||||
}
|
||||
|
||||
void MillSimulation::SetArbitraryStock(std::vector<Vertex>& verts, std::vector<GLushort>& indices)
|
||||
void MillSimulation::SetArbitraryStock(
|
||||
const std::vector<Vertex>& verts,
|
||||
const std::vector<GLushort>& indices
|
||||
)
|
||||
{
|
||||
mStockObject.GenerateSolid(verts, indices);
|
||||
simDisplay.ScaleViewToStock(&mStockObject);
|
||||
}
|
||||
|
||||
void MillSimulation::SetBaseObject(std::vector<Vertex>& verts, std::vector<GLushort>& indices)
|
||||
void MillSimulation::SetBaseObject(const std::vector<Vertex>& verts, const std::vector<GLushort>& indices)
|
||||
{
|
||||
mBaseShape.GenerateSolid(verts, indices);
|
||||
}
|
||||
@@ -639,13 +651,16 @@ void MillSimulation::Zoom(float factor)
|
||||
|
||||
void MillSimulation::UpdateWindowScale(int width, int height)
|
||||
{
|
||||
if (width == gWindowSizeW && height == gWindowSizeH) {
|
||||
if (width == mWidth && height == mHeight) {
|
||||
return;
|
||||
}
|
||||
gWindowSizeW = width;
|
||||
gWindowSizeH = height;
|
||||
simDisplay.UpdateWindowScale();
|
||||
guiDisplay.UpdateWindowScale();
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
simDisplay.UpdateWindowScale(width, height);
|
||||
guiDisplay.UpdateWindowScale(width, height);
|
||||
|
||||
simDisplay.updateDisplay = true;
|
||||
}
|
||||
|
||||
@@ -676,4 +691,26 @@ void MillSimulation::SetSimulationStage(float stage)
|
||||
CalcSegmentPositions();
|
||||
}
|
||||
|
||||
void MillSimulation::SetState(const MillSimulationState& state)
|
||||
{
|
||||
mSimPlaying = state.mSimPlaying;
|
||||
mSingleStep = state.mSingleStep;
|
||||
guiDisplay.UpdatePlayState(mSimPlaying);
|
||||
|
||||
const float stage = (float)state.mCurStep / state.mNTotalSteps;
|
||||
SetSimulationStage(stage);
|
||||
|
||||
mSimSpeed = state.mSimSpeed;
|
||||
guiDisplay.UpdateSimSpeed(mSimSpeed);
|
||||
|
||||
mViewItems = state.mViewItems;
|
||||
mViewPath = state.mViewPath;
|
||||
mViewSSAO = state.mViewSSAO;
|
||||
}
|
||||
|
||||
const MillSimulationState& MillSimulation::GetState() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
@@ -46,7 +46,23 @@
|
||||
namespace MillSim
|
||||
{
|
||||
|
||||
class MillSimulation
|
||||
struct MillSimulationState
|
||||
{
|
||||
int mCurStep = 0;
|
||||
int mNTotalSteps = 0;
|
||||
int mPathStep = -1;
|
||||
int mSubStep = 0;
|
||||
int mNPathSteps = 0;
|
||||
int mSimSpeed = 1;
|
||||
int mViewItems = VIEWITEM_SIMULATION;
|
||||
bool mViewPath = false;
|
||||
bool mViewSSAO = false;
|
||||
|
||||
bool mSimPlaying = false;
|
||||
bool mSingleStep = false;
|
||||
};
|
||||
|
||||
class MillSimulation: private MillSimulationState
|
||||
{
|
||||
public:
|
||||
MillSimulation();
|
||||
@@ -54,13 +70,10 @@ public:
|
||||
void ClearMillPathSegments();
|
||||
void Clear();
|
||||
void SimNext();
|
||||
void InitSimulation(float quality, qreal devicePixelRatio);
|
||||
void InitSimulation(float quality);
|
||||
void AddTool(EndMill* tool);
|
||||
void AddTool(const std::vector<float>& toolProfile, int toolid, float diameter);
|
||||
bool ToolExists(int toolid)
|
||||
{
|
||||
return GetTool(toolid) != nullptr;
|
||||
}
|
||||
bool ToolExists(int toolid);
|
||||
void RenderSimulation();
|
||||
void RenderTool();
|
||||
void RenderPath();
|
||||
@@ -72,9 +85,11 @@ public:
|
||||
bool LoadGCodeFile(const char* fileName);
|
||||
bool AddGcodeLine(const char* line);
|
||||
void SetSimulationStage(float stage);
|
||||
void SetState(const MillSimulationState& state);
|
||||
const MillSimulationState& GetState() const;
|
||||
void SetBoxStock(float x, float y, float z, float l, float w, float h);
|
||||
void SetArbitraryStock(std::vector<Vertex>& verts, std::vector<GLushort>& indices);
|
||||
void SetBaseObject(std::vector<Vertex>& verts, std::vector<GLushort>& indices);
|
||||
void SetArbitraryStock(const std::vector<Vertex>& verts, const std::vector<GLushort>& indices);
|
||||
void SetBaseObject(const std::vector<Vertex>& verts, const std::vector<GLushort>& indices);
|
||||
void MouseDrag(int buttons, int dx, int dy);
|
||||
void MouseMove(int px, int py, int modifiers);
|
||||
void MouseScroll(float dy);
|
||||
@@ -83,9 +98,8 @@ public:
|
||||
void Zoom(float factor);
|
||||
void UpdateWindowScale(int width, int height);
|
||||
|
||||
|
||||
protected:
|
||||
void InitDisplay(float quality, qreal devicePixelRatio);
|
||||
void InitDisplay(float quality);
|
||||
void GlsimStart();
|
||||
void GlsimToolStep1(void);
|
||||
void GlsimToolStep2(void);
|
||||
@@ -99,7 +113,6 @@ protected:
|
||||
EndMill* GetTool(int tool);
|
||||
void RemoveTool(int toolId);
|
||||
|
||||
|
||||
protected:
|
||||
std::vector<EndMill*> mToolTable;
|
||||
GCodeParser mCodeParser;
|
||||
@@ -115,6 +128,9 @@ protected:
|
||||
MillMotion mDestMotion = {.cmd=eNop, .tool=-1, .x=0, .y=0, .z=0, .i=0, .j=0, .k=0, .r=0, .retract_mode='\0', .retract_z=0.0};
|
||||
// clang-format on
|
||||
|
||||
int mWidth = -1;
|
||||
int mHeight = -1;
|
||||
|
||||
StockObject mStockObject;
|
||||
SolidObject mBaseShape;
|
||||
|
||||
@@ -124,24 +140,15 @@ protected:
|
||||
vec3 toolColor = {0.5f, 0.4f, 0.3f};
|
||||
vec3 baseShapeColor = {0.7f, 0.6f, 0.5f};
|
||||
|
||||
int mCurStep = 0;
|
||||
int mNTotalSteps = 0;
|
||||
int mPathStep = 0;
|
||||
int mSubStep = 0;
|
||||
int mNPathSteps = 0;
|
||||
int mDebug = 0;
|
||||
int mDebug1 = 0;
|
||||
int mDebug2 = 12;
|
||||
int mSimSpeed = 1;
|
||||
int mViewItems = VIEWITEM_SIMULATION;
|
||||
|
||||
int mLastMouseX = 0, mLastMouseY = 0;
|
||||
int mMouseButtonState = 0;
|
||||
int mLastModifiers = 0;
|
||||
|
||||
bool mIsInStock = false;
|
||||
bool mSimPlaying = false;
|
||||
bool mSingleStep = false;
|
||||
};
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
#define __openglwrapper_h__
|
||||
|
||||
#include "DlgCAMSimulator.h"
|
||||
extern QOpenGLContext* gOpenGlContext;
|
||||
#define gSimWindow CAMSimulator::DlgCAMSimulator::GetInstance()
|
||||
#define gSimWindow CAMSimulator::DlgCAMSimulator::instance()
|
||||
#define glClearColor gSimWindow->glClearColor
|
||||
#define glBlendFunc gSimWindow->glBlendFunc
|
||||
#define glClear gSimWindow->glClear
|
||||
|
||||
@@ -45,31 +45,31 @@ Shader::~Shader()
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void Shader::UpdateModelMat(mat4x4 tmat, mat4x4 nmat)
|
||||
void Shader::UpdateModelMat(const mat4x4& tmat, const mat4x4& nmat)
|
||||
{
|
||||
if (mModelPos >= 0) {
|
||||
glUniformMatrix4fv(mModelPos, 1, GL_FALSE, (GLfloat*)tmat);
|
||||
glUniformMatrix4fv(mModelPos, 1, GL_FALSE, (const GLfloat*)tmat);
|
||||
}
|
||||
if (mNormalRotPos >= 0) {
|
||||
glUniformMatrix4fv(mNormalRotPos, 1, GL_FALSE, (GLfloat*)nmat);
|
||||
glUniformMatrix4fv(mNormalRotPos, 1, GL_FALSE, (const GLfloat*)nmat);
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::UpdateProjectionMat(mat4x4 mat)
|
||||
void Shader::UpdateProjectionMat(const mat4x4& mat)
|
||||
{
|
||||
if (mProjectionPos >= 0) {
|
||||
glUniformMatrix4fv(mProjectionPos, 1, GL_FALSE, (GLfloat*)mat);
|
||||
glUniformMatrix4fv(mProjectionPos, 1, GL_FALSE, (const GLfloat*)mat);
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::UpdateViewMat(mat4x4 mat)
|
||||
void Shader::UpdateViewMat(const mat4x4& mat)
|
||||
{
|
||||
if (mViewPos >= 0) {
|
||||
glUniformMatrix4fv(mViewPos, 1, GL_FALSE, (GLfloat*)mat);
|
||||
glUniformMatrix4fv(mViewPos, 1, GL_FALSE, (const GLfloat*)mat);
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::UpdateEnvColor(vec3 lightPos, vec3 lightColor, vec3 ambient, float linearity)
|
||||
void Shader::UpdateEnvColor(const vec3& lightPos, const vec3& lightColor, const vec3& ambient, float linearity)
|
||||
{
|
||||
if (mLightPosPos >= 0) {
|
||||
glUniform3fv(mLightPosPos, 1, lightPos);
|
||||
@@ -95,14 +95,14 @@ void Shader::UpdateScreenDimension(int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::UpdateObjColor(vec3 objColor)
|
||||
void Shader::UpdateObjColor(const vec3& objColor)
|
||||
{
|
||||
if (mObjectColorPos >= 0) {
|
||||
glUniform3fv(mObjectColorPos, 1, objColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::UpdateObjColorAlpha(vec4 objColor)
|
||||
void Shader::UpdateObjColorAlpha(const vec4& objColor)
|
||||
{
|
||||
if (mObjectColorAlphaPos >= 0) {
|
||||
glUniform4fv(mObjectColorAlphaPos, 1, objColor);
|
||||
|
||||
@@ -39,13 +39,13 @@ public:
|
||||
|
||||
public:
|
||||
unsigned int shaderId = 0;
|
||||
void UpdateModelMat(mat4x4 transformMat, mat4x4 normalMat);
|
||||
void UpdateProjectionMat(mat4x4 mat);
|
||||
void UpdateViewMat(mat4x4 mat);
|
||||
void UpdateEnvColor(vec3 lightPos, vec3 lightColor, vec3 ambient, float linearity);
|
||||
void UpdateModelMat(const mat4x4& transformMat, const mat4x4& normalMat);
|
||||
void UpdateProjectionMat(const mat4x4& mat);
|
||||
void UpdateViewMat(const mat4x4& mat);
|
||||
void UpdateEnvColor(const vec3& lightPos, const vec3& lightColor, const vec3& ambient, float linearity);
|
||||
void UpdateScreenDimension(int width, int height);
|
||||
void UpdateObjColor(vec3 objColor);
|
||||
void UpdateObjColorAlpha(vec4 objColor);
|
||||
void UpdateObjColor(const vec3& objColor);
|
||||
void UpdateObjColorAlpha(const vec4& objColor);
|
||||
void UpdateNormalState(bool isInverted);
|
||||
void UpdateSsaoActive(bool isInverted);
|
||||
void UpdateTextureSlot(int slot);
|
||||
|
||||
@@ -131,7 +131,6 @@ void SimDisplay::UniformCircle(vec3& randVec)
|
||||
randVec[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
void SimDisplay::CreateDisplayFbos()
|
||||
{
|
||||
// setup frame buffer for simulation
|
||||
@@ -178,7 +177,6 @@ void SimDisplay::CreateDisplayFbos()
|
||||
|
||||
void SimDisplay::CreateSsaoFbos()
|
||||
{
|
||||
|
||||
mSsaoValid = true;
|
||||
|
||||
// setup framebuffer for SSAO processing
|
||||
@@ -240,7 +238,7 @@ SimDisplay::~SimDisplay()
|
||||
CleanGL();
|
||||
}
|
||||
|
||||
void SimDisplay::InitGL(qreal devicePixelRatio)
|
||||
void SimDisplay::InitGL()
|
||||
{
|
||||
if (displayInitiated) {
|
||||
return;
|
||||
@@ -249,16 +247,12 @@ void SimDisplay::InitGL(qreal devicePixelRatio)
|
||||
// setup light object
|
||||
mlightObject.GenerateBoxStock(-0.5f, -0.5f, -0.5f, 1, 1, 1);
|
||||
|
||||
mDevicePixelRatio = devicePixelRatio;
|
||||
mWidth = (int)(gWindowSizeW * mDevicePixelRatio);
|
||||
mHeight = (int)(gWindowSizeH * mDevicePixelRatio);
|
||||
InitShaders();
|
||||
CreateDisplayFbos();
|
||||
CreateSsaoFbos();
|
||||
CreateFboQuad();
|
||||
|
||||
UpdateProjection();
|
||||
displayInitiated = true;
|
||||
|
||||
UpdateWindowScale(800, 600);
|
||||
}
|
||||
|
||||
void SimDisplay::CleanFbos()
|
||||
@@ -299,7 +293,7 @@ void SimDisplay::CleanGL()
|
||||
displayInitiated = false;
|
||||
}
|
||||
|
||||
void SimDisplay::PrepareDisplay(vec3 objCenter)
|
||||
void SimDisplay::PrepareDisplay(const vec3& objCenter)
|
||||
{
|
||||
mat4x4_look_at(mMatLookAt, eye, target, upvec);
|
||||
mat4x4_translate_in_place(mMatLookAt, mEyeX * mEyeXZFactor, 0, mEyeZ * mEyeXZFactor);
|
||||
@@ -327,7 +321,7 @@ void SimDisplay::StartDepthPass()
|
||||
shaderFlat.UpdateViewMat(mMatLookAt);
|
||||
}
|
||||
|
||||
void SimDisplay::StartGeometryPass(vec3 objColor, bool invertNormals)
|
||||
void SimDisplay::StartGeometryPass(const vec3& objColor, bool invertNormals)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
|
||||
shaderGeom.Activate();
|
||||
@@ -340,7 +334,7 @@ void SimDisplay::StartGeometryPass(vec3 objColor, bool invertNormals)
|
||||
|
||||
// A 'closer' geometry pass is similar to std geometry pass, but render the objects
|
||||
// slightly closer to the camera. This mitigates overlapping faces artifacts.
|
||||
void SimDisplay::StartCloserGeometryPass(vec3 objColor)
|
||||
void SimDisplay::StartCloserGeometryPass(const vec3& objColor)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
|
||||
shaderGeomCloser.Activate();
|
||||
@@ -363,15 +357,18 @@ void SimDisplay::ScaleViewToStock(StockObject* obj)
|
||||
mMaxStockDim = fmaxf(obj->size[0], obj->size[1]);
|
||||
maxFar = mMaxStockDim * 16;
|
||||
UpdateProjection();
|
||||
|
||||
vec3_set(eye, 0, 0, 0);
|
||||
mEyeDistFactor = NAN;
|
||||
UpdateEyeFactor(0.1f);
|
||||
|
||||
vec3_set(lightPos, obj->position[0], obj->position[1], obj->position[2] + mMaxStockDim / 3);
|
||||
mlightObject.SetPosition(lightPos);
|
||||
}
|
||||
|
||||
void SimDisplay::RenderResult(bool recalculate)
|
||||
void SimDisplay::RenderResult(bool recalculate, bool ssao)
|
||||
{
|
||||
if (mSsaoValid && applySSAO) {
|
||||
if (mSsaoValid && ssao) {
|
||||
RenderResultSSAO(recalculate);
|
||||
}
|
||||
else {
|
||||
@@ -549,12 +546,20 @@ void SimDisplay::UpdateEyeFactor(float factor)
|
||||
eye[1] = -factor * maxFar;
|
||||
}
|
||||
|
||||
void SimDisplay::UpdateWindowScale()
|
||||
void SimDisplay::UpdateWindowScale(int width, int height)
|
||||
{
|
||||
mWidth = (int)(gWindowSizeW * mDevicePixelRatio);
|
||||
mHeight = (int)(gWindowSizeH * mDevicePixelRatio);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
|
||||
CleanFbos();
|
||||
if (!displayInitiated || (width == mWidth && height == mHeight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
if (mFbo != 0) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
|
||||
CleanFbos();
|
||||
}
|
||||
|
||||
CreateDisplayFbos();
|
||||
CreateSsaoFbos();
|
||||
UpdateProjection();
|
||||
@@ -564,7 +569,7 @@ void SimDisplay::UpdateProjection()
|
||||
{
|
||||
// Setup projection
|
||||
mat4x4 projmat;
|
||||
mat4x4_perspective(projmat, 0.7f, (float)gWindowSizeW / gWindowSizeH, 1.0f, maxFar);
|
||||
mat4x4_perspective(projmat, 0.7f, (float)mWidth / mHeight, 1.0f, maxFar);
|
||||
shader3D.Activate();
|
||||
shader3D.UpdateProjectionMat(projmat);
|
||||
shaderInv3D.Activate();
|
||||
@@ -584,5 +589,9 @@ void SimDisplay::UpdateProjection()
|
||||
shaderGeomCloser.UpdateProjectionMat(projmat);
|
||||
}
|
||||
|
||||
float SimDisplay::GetEyeFactor()
|
||||
{
|
||||
return mEyeDistFactor;
|
||||
}
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
@@ -47,17 +47,17 @@ class SimDisplay
|
||||
{
|
||||
public:
|
||||
~SimDisplay();
|
||||
void InitGL(qreal devicePixelRatio);
|
||||
void InitGL();
|
||||
void CleanGL();
|
||||
void CleanFbos();
|
||||
void PrepareDisplay(vec3 objCenter);
|
||||
void PrepareDisplay(const vec3& objCenter);
|
||||
void PrepareFrameBuffer();
|
||||
void StartDepthPass();
|
||||
void StartGeometryPass(vec3 objColor, bool invertNormals);
|
||||
void StartCloserGeometryPass(vec3 objColor);
|
||||
void StartGeometryPass(const vec3& objColor, bool invertNormals);
|
||||
void StartCloserGeometryPass(const vec3& objColor);
|
||||
void RenderLightObject();
|
||||
void ScaleViewToStock(StockObject* obj);
|
||||
void RenderResult(bool recalculate);
|
||||
void RenderResult(bool recalculate, bool ssao);
|
||||
void RenderResultStandard();
|
||||
void RenderResultSSAO(bool recalculate);
|
||||
void SetupLinePathPass(int curSegment, bool isHidden);
|
||||
@@ -66,16 +66,12 @@ public:
|
||||
void MoveEye(float x, float z);
|
||||
void MoveEyeCenter();
|
||||
void UpdateEyeFactor(float factor);
|
||||
void UpdateWindowScale();
|
||||
void UpdateWindowScale(int width, int height);
|
||||
|
||||
void UpdateProjection();
|
||||
float GetEyeFactor()
|
||||
{
|
||||
return mEyeDistFactor;
|
||||
}
|
||||
float GetEyeFactor();
|
||||
|
||||
public:
|
||||
bool applySSAO = false;
|
||||
bool updateDisplay = false;
|
||||
float maxFar = 100;
|
||||
bool displayInitiated = false;
|
||||
@@ -108,14 +104,12 @@ protected:
|
||||
mat4x4 mMatLookAt;
|
||||
StockObject mlightObject;
|
||||
|
||||
qreal mDevicePixelRatio;
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int mWidth = -1;
|
||||
int mHeight = -1;
|
||||
|
||||
std::mt19937 generator;
|
||||
std::uniform_real_distribution<float> distr01;
|
||||
|
||||
|
||||
float mEyeDistance = 30;
|
||||
float mEyeRoration = 0;
|
||||
float mEyeInclination = pi / 6; // 30 degree
|
||||
@@ -129,22 +123,23 @@ protected:
|
||||
float mEyeZ = 0.0f;
|
||||
|
||||
// base frame buffer
|
||||
unsigned int mFbo;
|
||||
unsigned int mFboColTexture;
|
||||
unsigned int mFboPosTexture;
|
||||
unsigned int mFboNormTexture;
|
||||
unsigned int mRboDepthStencil;
|
||||
unsigned int mFboQuadVAO, mFboQuadVBO;
|
||||
unsigned int mFbo = 0;
|
||||
unsigned int mFboColTexture = 0;
|
||||
unsigned int mFboPosTexture = 0;
|
||||
unsigned int mFboNormTexture = 0;
|
||||
unsigned int mRboDepthStencil = 0;
|
||||
unsigned int mFboQuadVAO = 0, mFboQuadVBO = 0;
|
||||
|
||||
// ssao frame buffers
|
||||
bool mSsaoValid = false;
|
||||
std::vector<Point3D> mSsaoKernel;
|
||||
unsigned int mSsaoFbo;
|
||||
unsigned int mSsaoBlurFbo;
|
||||
unsigned int mFboSsaoTexture;
|
||||
unsigned int mFboSsaoBlurTexture;
|
||||
unsigned int mFboRandTexture;
|
||||
unsigned int mSsaoFbo = 0;
|
||||
unsigned int mSsaoBlurFbo = 0;
|
||||
unsigned int mFboSsaoTexture = 0;
|
||||
unsigned int mFboSsaoBlurTexture = 0;
|
||||
unsigned int mFboRandTexture = 0;
|
||||
};
|
||||
|
||||
} // namespace MillSim
|
||||
|
||||
#endif // !__simdisplay_h__
|
||||
|
||||
@@ -327,7 +327,7 @@ void Shape::ExtrudeProfileLinear(
|
||||
SetModelData(vbuffer, ibuffer);
|
||||
}
|
||||
|
||||
void Shape::GenerateModel(float* vbuffer, GLushort* ibuffer, int numVerts, int nIndices)
|
||||
void Shape::GenerateModel(const float* vbuffer, const GLushort* ibuffer, int numVerts, int nIndices)
|
||||
{
|
||||
// GLuint vbo, ibo, vao;
|
||||
|
||||
@@ -354,9 +354,9 @@ void Shape::GenerateModel(float* vbuffer, GLushort* ibuffer, int numVerts, int n
|
||||
numIndices = nIndices;
|
||||
}
|
||||
|
||||
void MillSim::Shape::SetModelData(std::vector<Vertex>& vbuffer, std::vector<GLushort>& ibuffer)
|
||||
void Shape::SetModelData(const std::vector<Vertex>& vbuffer, const std::vector<GLushort>& ibuffer)
|
||||
{
|
||||
GenerateModel((float*)vbuffer.data(), ibuffer.data(), (int)vbuffer.size(), (int)ibuffer.size());
|
||||
GenerateModel((const float*)vbuffer.data(), ibuffer.data(), (int)vbuffer.size(), (int)ibuffer.size());
|
||||
}
|
||||
|
||||
void Shape::Render()
|
||||
@@ -366,7 +366,7 @@ void Shape::Render()
|
||||
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, nullptr);
|
||||
}
|
||||
|
||||
void Shape::Render(mat4x4 modelMat, mat4x4 normallMat) // normals are rotated only
|
||||
void Shape::Render(const mat4x4& modelMat, const mat4x4& normallMat) // normals are rotated only
|
||||
{
|
||||
CurrentShader->UpdateModelMat(modelMat, normallMat);
|
||||
Render();
|
||||
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
|
||||
public:
|
||||
void Render();
|
||||
void Render(mat4x4 modelMat, mat4x4 normallMat);
|
||||
void Render(const mat4x4& modelMat, const mat4x4& normallMat);
|
||||
void FreeResources();
|
||||
void SetModelData(std::vector<Vertex>& vbuffer, std::vector<GLushort>& ibuffer);
|
||||
void SetModelData(const std::vector<Vertex>& vbuffer, const std::vector<GLushort>& ibuffer);
|
||||
void RotateProfile(
|
||||
float* profPoints,
|
||||
int nPoints,
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
static int lastNumSlices;
|
||||
|
||||
protected:
|
||||
void GenerateModel(float* vbuffer, GLushort* ibuffer, int numVerts, int numIndices);
|
||||
void GenerateModel(const float* vbuffer, const GLushort* ibuffer, int numVerts, int numIndices);
|
||||
void CalculateExtrudeBufferSizes(
|
||||
int nProfilePoints,
|
||||
bool capStart,
|
||||
|
||||
@@ -55,14 +55,14 @@ void SolidObject::render()
|
||||
shape.Render(mModelMat, mModelMat); // model is not rotated hence both are identity matrix
|
||||
}
|
||||
|
||||
void SolidObject::GenerateSolid(std::vector<Vertex>& verts, std::vector<GLushort>& indices)
|
||||
void SolidObject::GenerateSolid(const std::vector<Vertex>& verts, const std::vector<GLushort>& indices)
|
||||
{
|
||||
shape.SetModelData(verts, indices);
|
||||
|
||||
// calculate object's bounding box:
|
||||
float x = 999999.0f, y = 999999.0f, z = 999999.0f;
|
||||
float l = -999999.0f, w = -999999.0f, h = -999999.0f;
|
||||
for (auto& vert : verts) {
|
||||
for (const auto& vert : verts) {
|
||||
x = std::fminf(x, vert.x);
|
||||
y = std::fminf(y, vert.y);
|
||||
z = std::fminf(z, vert.z);
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
/// Calls the display list.
|
||||
virtual void render();
|
||||
Shape shape;
|
||||
void GenerateSolid(std::vector<Vertex>& verts, std::vector<GLushort>& indices);
|
||||
void GenerateSolid(const std::vector<Vertex>& verts, const std::vector<GLushort>& indices);
|
||||
vec3 center = {};
|
||||
vec3 size = {};
|
||||
vec3 position = {};
|
||||
|
||||
53
src/Mod/CAM/PathSimulator/AppGL/ViewCAMSimulator.cpp
Normal file
53
src/Mod/CAM/PathSimulator/AppGL/ViewCAMSimulator.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 "ViewCAMSimulator.h"
|
||||
#include "DlgCAMSimulator.h"
|
||||
|
||||
namespace CAMSimulator
|
||||
{
|
||||
|
||||
ViewCAMSimulator::ViewCAMSimulator(Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags)
|
||||
: Gui::MDIView(pcDocument, parent, wflags)
|
||||
{
|
||||
mDlg = new DlgCAMSimulator(*this);
|
||||
setCentralWidget(mDlg);
|
||||
}
|
||||
|
||||
ViewCAMSimulator* ViewCAMSimulator::clone()
|
||||
{
|
||||
auto viewCam = new ViewCAMSimulator(_pcDocument, nullptr);
|
||||
|
||||
viewCam->cloneFrom(*this);
|
||||
viewCam->mDlg->cloneFrom(*mDlg);
|
||||
|
||||
return viewCam;
|
||||
}
|
||||
|
||||
DlgCAMSimulator& ViewCAMSimulator::dlg()
|
||||
{
|
||||
return *mDlg;
|
||||
}
|
||||
|
||||
} // namespace CAMSimulator
|
||||
53
src/Mod/CAM/PathSimulator/AppGL/ViewCAMSimulator.h
Normal file
53
src/Mod/CAM/PathSimulator/AppGL/ViewCAMSimulator.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef PATHSIMULATOR_VIEWCAMSIMULATOR_H
|
||||
#define PATHSIMULATOR_VIEWCAMSIMULATOR_H
|
||||
|
||||
#include <Gui/MDIView.h>
|
||||
|
||||
namespace CAMSimulator
|
||||
{
|
||||
class DlgCAMSimulator;
|
||||
|
||||
class ViewCAMSimulator: public Gui::MDIView
|
||||
{
|
||||
public:
|
||||
ViewCAMSimulator(
|
||||
Gui::Document* pcDocument,
|
||||
QWidget* parent,
|
||||
Qt::WindowFlags wflags = Qt::WindowFlags()
|
||||
);
|
||||
|
||||
ViewCAMSimulator* clone() override;
|
||||
|
||||
DlgCAMSimulator& dlg();
|
||||
|
||||
protected:
|
||||
DlgCAMSimulator* mDlg;
|
||||
};
|
||||
|
||||
} // namespace CAMSimulator
|
||||
|
||||
#endif /* PATHSIMULATOR_VIEWCAMSIMULATOR_H */
|
||||
Reference in New Issue
Block a user