1 /**
2 * Mandelbulber v2, a 3D fractal generator ,=#MKNmMMKmmßMNWy,
3 * ,B" ]L,,p%%%,,,§;, "K
4 * Copyright (C) 2016-20 Mandelbulber Team §R-==%w["'~5]m%=L.=~5N
5 * ,=mm=§M ]=4 yJKA"/-Nsaj "Bw,==,,
6 * This file is part of Mandelbulber. §R.r= jw",M Km .mM FW ",§=ß., ,TN
7 * ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
8 * Mandelbulber is free software: §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
9 * you can redistribute it and/or §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
10 * modify it under the terms of the "§M=M =D=4"N #"%==A%p M§ M6 R' #"=~.4M
11 * GNU General Public License as §W =, ][T"]C § § '§ e===~ U !§[Z ]N
12 * published by the 4M",,Jm=,"=e~ § § j]]""N BmM"py=ßM
13 * Free Software Foundation, ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
14 * either version 3 of the License, TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
15 * or (at your option) TW=,-#"%=;[ =Q:["V"" ],,M.m == ]N
16 * any later version. J§"mr"] ,=,," =="""J]= M"M"]==ß"
17 * §= "=C=4 §"eM "=B:m|4"]#F,§~
18 * Mandelbulber is distributed in "9w=,,]w em%wJ '"~" ,=,,ß"
19 * the hope that it will be useful, . "K= ,=RMMMßM"""
20 * but WITHOUT ANY WARRANTY; .'''
21 * without even the implied warranty
22 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 *
24 * See the GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
27 *
28 * ###########################################################################
29 *
30 * Authors: Krzysztof Marczak (buddhi1980@gmail.com)
31 *
32 * Widget which contains UI for rendering engine
33 */
34
35 #include "dock_rendering_engine.h"
36
37 #include "ui_dock_rendering_engine.h"
38
39 #include "dock_fractal.h"
40 #include "dock_image_adjustments.h"
41 #include "dock_navigation.h"
42
43 #include "src/automated_widgets.hpp"
44 #include "src/initparameters.hpp"
45 #include "src/interface.hpp"
46 #include "src/netrender.hpp"
47 #include "src/projection_3d.hpp"
48 #include "src/render_window.hpp"
49 #include "src/synchronize_interface.hpp"
50
cDockRenderingEngine(QWidget * parent)51 cDockRenderingEngine::cDockRenderingEngine(QWidget *parent)
52 : QWidget(parent), ui(new Ui::cDockRenderingEngine)
53 {
54 ui->setupUi(this);
55 automatedWidgets = new cAutomatedWidgets(this);
56 automatedWidgets->ConnectSignalsForSlidersInWindow(this);
57 ConnectSignals();
58
59 ui->groupBox_netrender_client_config->setVisible(false);
60 }
61
~cDockRenderingEngine()62 cDockRenderingEngine::~cDockRenderingEngine()
63 {
64 delete ui;
65 }
66
ConnectSignals() const67 void cDockRenderingEngine::ConnectSignals() const
68 {
69 connect(ui->checkBox_use_default_bailout, SIGNAL(stateChanged(int)), this,
70 SLOT(slotChangedCheckBoxUseDefaultBailout(int)));
71 connect(ui->pushButton_optimization_LQ, SIGNAL(clicked()), this,
72 SLOT(slotPressedButtonOptimizeForLQ()));
73 connect(ui->pushButton_optimization_MQ, SIGNAL(clicked()), this,
74 SLOT(slotPressedButtonOptimizeForMQ()));
75 connect(ui->pushButton_optimization_HQ, SIGNAL(clicked()), this,
76 SLOT(slotPressedButtonOptimizeForHQ()));
77 connect(ui->logedit_detail_level, SIGNAL(returnPressed()), this, SLOT(slotDetailLevelChanged()));
78 connect(ui->comboBox_delta_DE_method, SIGNAL(currentIndexChanged(int)), this,
79 SLOT(slotChangedComboDistanceEstimationMethod(int)));
80
81 // Limits
82 connect(ui->bu_bounding_box_to_limit, SIGNAL(clicked()), this,
83 SLOT(slotPressedButtonSetBoundingBoxAsLimits()));
84 connect(ui->bu_bounding_box_size_x_up, SIGNAL(clicked()), this,
85 SLOT(slotPressedButtonBoundingBoxSizeXUp()));
86 connect(ui->bu_bounding_box_size_x_down, SIGNAL(clicked()), this,
87 SLOT(slotPressedButtonBoundingBoxSizeXDown()));
88 connect(ui->bu_bounding_box_size_y_up, SIGNAL(clicked()), this,
89 SLOT(slotPressedButtonBoundingBoxSizeYUp()));
90 connect(ui->bu_bounding_box_size_y_down, SIGNAL(clicked()), this,
91 SLOT(slotPressedButtonBoundingBoxSizeYDown()));
92 connect(ui->bu_bounding_box_size_z_up, SIGNAL(clicked()), this,
93 SLOT(slotPressedButtonBoundingBoxSizeZUp()));
94 connect(ui->bu_bounding_box_size_z_down, SIGNAL(clicked()), this,
95 SLOT(slotPressedButtonBoundingBoxSizeZDown()));
96 connect(ui->bu_bounding_box_move_x_neg, SIGNAL(clicked()), this,
97 SLOT(slotPressedButtonBoundingBoxMoveXNeg()));
98 connect(ui->bu_bounding_box_move_x_pos, SIGNAL(clicked()), this,
99 SLOT(slotPressedButtonBoundingBoxMoveXPos()));
100 connect(ui->bu_bounding_box_move_y_neg, SIGNAL(clicked()), this,
101 SLOT(slotPressedButtonBoundingBoxMoveYNeg()));
102 connect(ui->bu_bounding_box_move_y_pos, SIGNAL(clicked()), this,
103 SLOT(slotPressedButtonBoundingBoxMoveYPos()));
104 connect(ui->bu_bounding_box_move_z_neg, SIGNAL(clicked()), this,
105 SLOT(slotPressedButtonBoundingBoxMoveZNeg()));
106 connect(ui->bu_bounding_box_move_z_pos, SIGNAL(clicked()), this,
107 SLOT(slotPressedButtonBoundingBoxMoveZPos()));
108
109 // NetRender
110 connect(ui->bu_netrender_connect, SIGNAL(clicked()), this, SLOT(slotNetRenderClientConnect()));
111 connect(
112 ui->bu_netrender_disconnect, SIGNAL(clicked()), this, SLOT(slotNetRenderClientDisconnect()));
113 connect(ui->bu_netrender_start_server, SIGNAL(clicked()), this, SLOT(slotNetRenderServerStart()));
114 connect(ui->bu_netrender_stop_server, SIGNAL(clicked()), this, SLOT(slotNetRenderServerStop()));
115 connect(ui->comboBox_netrender_mode, SIGNAL(currentIndexChanged(int)), this,
116 SLOT(slotNetRenderClientServerChange(int)));
117 connect(
118 ui->group_netrender, SIGNAL(toggled(bool)), this, SLOT(slotCheckBoxDisableNetRender(bool)));
119 connect(ui->bu_netrender_connect, SIGNAL(clicked()), this, SLOT(slotNetRenderClientConnect()));
120 connect(gNetRender, &cNetRender::NewStatusClient, this,
121 &cDockRenderingEngine::slotNetRenderStatusClientUpdate);
122 connect(gNetRender, &cNetRender::NewStatusServer, this,
123 &cDockRenderingEngine::slotNetRenderStatusServerUpdate);
124 connect(gNetRender, &cNetRender::ClientsChanged, this,
125 &cDockRenderingEngine::slotNetRenderClientListUpdate);
126 connect(gNetRender, &cNetRender::ClientsChangedRow, this,
127 &cDockRenderingEngine::slotNetRenderClientListUpdateRow);
128 connect(gNetRender, &cNetRender::ClientsChangedCell, this,
129 &cDockRenderingEngine::slotNetRenderClientListUpdateCell);
130
131 connect(ui->checkBox_connect_detail_level_2, SIGNAL(stateChanged(int)), this,
132 SIGNAL(stateChangedConnectDetailLevel(int)));
133
134 connect(ui->pushButton_calculate_dist_thresh, SIGNAL(clicked()), this,
135 SLOT(slotCalculateDistanceThreshold()));
136 }
137
slotNetRenderServerStart() const138 void cDockRenderingEngine::slotNetRenderServerStart() const
139 {
140 SynchronizeInterfaceWindow(ui->group_netrender, gPar, qInterface::read);
141 qint32 port = gPar->Get<int>("netrender_server_local_port");
142 gNetRender->SetServer(port);
143 }
144
slotNetRenderServerStop()145 void cDockRenderingEngine::slotNetRenderServerStop()
146 {
147 gNetRender->DeleteServer();
148 }
149
slotNetRenderClientConnect() const150 void cDockRenderingEngine::slotNetRenderClientConnect() const
151 {
152 SynchronizeInterfaceWindow(ui->group_netrender, gPar, qInterface::read);
153 QString address = gPar->Get<QString>("netrender_client_remote_address");
154 qint32 port = gPar->Get<int>("netrender_client_remote_port");
155 gNetRender->SetClient(address, port);
156 }
157
slotNetRenderClientDisconnect()158 void cDockRenderingEngine::slotNetRenderClientDisconnect()
159 {
160 gNetRender->DeleteClient();
161 }
162
slotNetRenderClientServerChange(int index) const163 void cDockRenderingEngine::slotNetRenderClientServerChange(int index) const
164 {
165 ui->groupBox_netrender_client_config->setVisible(index == cNetRender::netRenderDeviceType_CLIENT);
166 ui->groupBox_netrender_server_config->setVisible(index == cNetRender::netRenderDeviceType_SERVER);
167 }
168
slotNetRenderClientListUpdate() const169 void cDockRenderingEngine::slotNetRenderClientListUpdate() const
170 {
171 QTableWidget *table = ui->tableWidget_netrender_connected_clients;
172
173 // reset table
174 if (gNetRender->GetClientCount() == 0)
175 {
176 table->clear();
177 return;
178 }
179
180 // init table
181 if (table->columnCount() == 0)
182 {
183 QStringList header;
184 header << tr("Name") << tr("Host") << tr("CPUs") << tr("Status") << tr("Items done")
185 << tr("Actions");
186 table->setColumnCount(header.size());
187 table->setHorizontalHeaderLabels(header);
188 }
189
190 QHeaderView *headers = table->horizontalHeader();
191 headers->setSectionResizeMode(QHeaderView::ResizeToContents);
192
193 // change table
194 if (table->rowCount() != gNetRender->GetClientCount())
195 {
196 table->setRowCount(gNetRender->GetClientCount());
197 }
198
199 // update table
200 for (int i = 0; i < table->rowCount(); i++)
201 {
202 slotNetRenderClientListUpdateRow(i);
203 }
204 }
205
slotNetRenderClientListUpdateRow(int i) const206 void cDockRenderingEngine::slotNetRenderClientListUpdateRow(int i) const
207 {
208 // update row i
209 QTableWidget *table = ui->tableWidget_netrender_connected_clients;
210 for (int j = 0; j < table->columnCount(); j++)
211 {
212 slotNetRenderClientListUpdateCell(i, j);
213 }
214 }
215
slotNetRenderClientListUpdateCell(int i,int j) const216 void cDockRenderingEngine::slotNetRenderClientListUpdateCell(int i, int j) const
217 {
218 // update element in row i, column j
219 QTableWidget *table = ui->tableWidget_netrender_connected_clients;
220
221 QTableWidgetItem *cell = table->item(i, j);
222 if (!cell)
223 {
224 cell = new QTableWidgetItem;
225 table->setItem(i, j, cell);
226 }
227
228 switch (j)
229 {
230 case 0: cell->setText(gNetRender->GetClient(i).name); break;
231 case 1: cell->setText(gNetRender->GetClient(i).socket->peerAddress().toString()); break;
232 case 2: cell->setText(QString::number(gNetRender->GetClient(i).clientWorkerCount)); break;
233 case 3:
234 {
235 QString text = cNetRender::GetStatusText(gNetRender->GetClient(i).status);
236 QString color = cNetRender::GetStatusColor(gNetRender->GetClient(i).status);
237
238 cell->setText(text);
239 cell->setForeground(QBrush(QColor(color)));
240 cell->setBackground(QBrush(Qt::white));
241 break;
242 }
243 case 4: cell->setText(QString::number(gNetRender->GetClient(i).itemsRendered)); break;
244 case 5:
245 {
246 QFrame *frame = new QFrame;
247 QGridLayout *gridLayout = new QGridLayout;
248 QToolButton *actionKickAndKill = new QToolButton;
249 actionKickAndKill->setIcon(actionKickAndKill->style()->standardIcon(QStyle::SP_TrashIcon));
250 actionKickAndKill->setFixedSize(24, 24);
251 actionKickAndKill->setObjectName(QString::number(i));
252 gridLayout->setContentsMargins(2, 2, 2, 2);
253 QObject::connect(
254 actionKickAndKill, SIGNAL(clicked()), this, SLOT(slotNetRenderKickAndKill()));
255 gridLayout->addWidget(actionKickAndKill, 0, 0);
256 gridLayout->setSpacing(0);
257 frame->setLayout(gridLayout);
258 table->setCellWidget(i, j, frame);
259 break;
260 }
261 default: break;
262 }
263 }
264
slotNetRenderStatusServerUpdate() const265 void cDockRenderingEngine::slotNetRenderStatusServerUpdate() const
266 {
267 QString text = cNetRender::GetStatusText(gNetRender->GetStatus());
268 QString color = cNetRender::GetStatusColor(gNetRender->GetStatus());
269 ui->label_netrender_server_status->setText(text);
270 ui->label_netrender_server_status->setStyleSheet(
271 "QLabel { color: " + color + "; font-weight: bold; border: 2px solid darkgray; border-radius: 3px;"
272 "background: white; text-align: center; qproperty-alignment: AlignCenter;}");
273
274 ui->bu_netrender_start_server->setEnabled(!gNetRender->IsServer());
275 ui->bu_netrender_stop_server->setEnabled(gNetRender->IsServer());
276 }
277
slotNetRenderStatusClientUpdate() const278 void cDockRenderingEngine::slotNetRenderStatusClientUpdate() const
279 {
280 QString text = cNetRender::GetStatusText(gNetRender->GetStatus());
281 QString color = cNetRender::GetStatusColor(gNetRender->GetStatus());
282 ui->label_netrender_client_connected_server->setText(gNetRender->GetServerName());
283 ui->label_netrender_client_status->setText(text);
284 ui->label_netrender_client_status->setStyleSheet(
285 "QLabel { color: " + color + "; font-weight: bold; border: 2px solid darkgray; border-radius: 3px;"
286 "background: white; text-align: center; qproperty-alignment: AlignCenter;}");
287
288 ui->bu_netrender_connect->setEnabled(!gNetRender->IsClient());
289 ui->bu_netrender_disconnect->setEnabled(gNetRender->IsClient());
290 gMainInterface->mainWindow->GetWidgetDockNavigation()->setEnabled(!gNetRender->IsClient());
291 }
292
slotCheckBoxDisableNetRender(bool on)293 void cDockRenderingEngine::slotCheckBoxDisableNetRender(bool on)
294 {
295 if (!on)
296 {
297 gNetRender->DeleteClient();
298 gNetRender->DeleteServer();
299 }
300 }
301
slotNetRenderKickAndKill()302 void cDockRenderingEngine::slotNetRenderKickAndKill()
303 {
304 QString buttonName = sender()->objectName();
305 gNetRender->KickAndKillClient(buttonName.toInt());
306 }
307
SynchronizeInterfaceDistanceEstimation(std::shared_ptr<cParameterContainer> par) const308 void cDockRenderingEngine::SynchronizeInterfaceDistanceEstimation(
309 std::shared_ptr<cParameterContainer> par) const
310 {
311 SynchronizeInterfaceWindow(ui->groupBox_detailLevel, par, qInterface::write);
312 }
313
ComboDeltaDEFunctionSetEnabled(bool enabled) const314 void cDockRenderingEngine::ComboDeltaDEFunctionSetEnabled(bool enabled) const
315 {
316 ui->comboBox_delta_DE_function->setEnabled(enabled);
317 }
318
ComboDeltaDEMethodCurrentIndex() const319 int cDockRenderingEngine::ComboDeltaDEMethodCurrentIndex() const
320 {
321 return ui->comboBox_delta_DE_method->currentIndex();
322 }
323
slotChangedComboDistanceEstimationMethod(int index) const324 void cDockRenderingEngine::slotChangedComboDistanceEstimationMethod(int index) const
325 {
326 Q_UNUSED(index);
327 // ui->comboBox_delta_DE_function->setEnabled(
328 // gMainInterface->mainWindow->GetWidgetDockFractal()->AreHybridFractalsEnabled()
329 // || index == int(fractal::forceDeltaDEMethod));
330 }
331
CheckboxConnectDetailLevelSetCheckState(Qt::CheckState state) const332 void cDockRenderingEngine::CheckboxConnectDetailLevelSetCheckState(Qt::CheckState state) const
333 {
334 ui->checkBox_connect_detail_level_2->setCheckState(state);
335 }
336
UpdateLabelWrongDEPercentage(const QString & text) const337 void cDockRenderingEngine::UpdateLabelWrongDEPercentage(const QString &text) const
338 {
339 ui->label_wrong_DE_percentage->setText(text);
340 }
341
UpdateLabelUsedDistanceEstimation(const QString & text) const342 void cDockRenderingEngine::UpdateLabelUsedDistanceEstimation(const QString &text) const
343 {
344 ui->label_used_distance_estimation->setText(text);
345 }
346
slotChangedCheckBoxUseDefaultBailout(int state) const347 void cDockRenderingEngine::slotChangedCheckBoxUseDefaultBailout(int state) const
348 {
349 ui->logedit_bailout->setEnabled(!state);
350 }
351
slotDetailLevelChanged()352 void cDockRenderingEngine::slotDetailLevelChanged()
353 {
354 if (gMainInterface->mainWindow->GetWidgetDockImageAdjustments()->IsConnectDetailLevelEnabled())
355 {
356 gMainInterface->SynchronizeInterface(gPar, gParFractal, qInterface::read);
357 gMainInterface->lockedDetailLevel = gPar->Get<double>("detail_level");
358 gMainInterface->lockedImageResolution =
359 CVector2<int>(gPar->Get<int>("image_width"), gPar->Get<int>("image_height"));
360 }
361 }
362
slotPressedButtonOptimizeForLQ()363 void cDockRenderingEngine::slotPressedButtonOptimizeForLQ()
364 {
365 gMainInterface->OptimizeStepFactor(1.0);
366 }
367
slotPressedButtonOptimizeForMQ()368 void cDockRenderingEngine::slotPressedButtonOptimizeForMQ()
369 {
370 gMainInterface->OptimizeStepFactor(0.1);
371 }
slotPressedButtonOptimizeForHQ()372 void cDockRenderingEngine::slotPressedButtonOptimizeForHQ()
373 {
374 gMainInterface->OptimizeStepFactor(0.01);
375 }
slotPressedButtonSetBoundingBoxAsLimits()376 void cDockRenderingEngine::slotPressedButtonSetBoundingBoxAsLimits()
377 {
378 gMainInterface->SetBoundingBoxAsLimitsTotal();
379 }
slotPressedButtonBoundingBoxSizeXUp()380 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeXUp()
381 {
382 gMainInterface->BoundingBoxMove('x', 0.05, 0.05);
383 }
slotPressedButtonBoundingBoxSizeXDown()384 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeXDown()
385 {
386 gMainInterface->BoundingBoxMove('x', -0.05, -0.05);
387 }
slotPressedButtonBoundingBoxSizeYUp()388 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeYUp()
389 {
390 gMainInterface->BoundingBoxMove('y', 0.05, 0.05);
391 }
slotPressedButtonBoundingBoxSizeYDown()392 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeYDown()
393 {
394 gMainInterface->BoundingBoxMove('y', -0.05, -0.05);
395 }
slotPressedButtonBoundingBoxSizeZUp()396 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeZUp()
397 {
398 gMainInterface->BoundingBoxMove('z', 0.05, 0.05);
399 }
slotPressedButtonBoundingBoxSizeZDown()400 void cDockRenderingEngine::slotPressedButtonBoundingBoxSizeZDown()
401 {
402 gMainInterface->BoundingBoxMove('z', -0.05, -0.05);
403 }
slotPressedButtonBoundingBoxMoveXNeg()404 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveXNeg()
405 {
406 gMainInterface->BoundingBoxMove('x', -0.05, 0.05);
407 }
slotPressedButtonBoundingBoxMoveXPos()408 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveXPos()
409 {
410 gMainInterface->BoundingBoxMove('x', 0.05, -0.05);
411 }
slotPressedButtonBoundingBoxMoveYNeg()412 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveYNeg()
413 {
414 gMainInterface->BoundingBoxMove('y', -0.05, 0.05);
415 }
slotPressedButtonBoundingBoxMoveYPos()416 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveYPos()
417 {
418 gMainInterface->BoundingBoxMove('y', 0.05, -0.05);
419 }
slotPressedButtonBoundingBoxMoveZNeg()420 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveZNeg()
421 {
422 gMainInterface->BoundingBoxMove('z', -0.05, 0.05);
423 }
slotPressedButtonBoundingBoxMoveZPos()424 void cDockRenderingEngine::slotPressedButtonBoundingBoxMoveZPos()
425 {
426 gMainInterface->BoundingBoxMove('z', 0.05, -0.05);
427 }
428
slotCalculateDistanceThreshold()429 void cDockRenderingEngine::slotCalculateDistanceThreshold()
430 {
431 gMainInterface->SynchronizeInterface(gPar, gParFractal, qInterface::read);
432 double distance = gMainInterface->GetDistanceForPoint(gPar->Get<CVector3>("camera"));
433 double detailLevel = gPar->Get<double>("detail_level");
434 double imageWidth = gPar->Get<int>("image_width");
435 params::enumPerspectiveType perspectiveType =
436 params::enumPerspectiveType(gPar->Get<int>("perspective_type"));
437 double fov = CalcFOV(gPar->Get<int>("fov"), perspectiveType);
438 double distThresh = fov / detailLevel / imageWidth * distance * 10.0;
439 gPar->Set("DE_thresh", distThresh);
440 gMainInterface->SynchronizeInterface(gPar, gParFractal, qInterface::write);
441 }
442